diff --git a/dev/john/update-logging-example/container-platform-starter/common/images/icon-blue.png b/dev/john/update-logging-example/container-platform-starter/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/container-platform-starter/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/container-platform-starter/common/images/style/test-image.webp b/dev/john/update-logging-example/container-platform-starter/common/images/style/test-image.webp new file mode 100644 index 00000000..e566f7ac Binary files /dev/null and b/dev/john/update-logging-example/container-platform-starter/common/images/style/test-image.webp differ diff --git a/dev/john/update-logging-example/container-platform-starter/common/style/app.css b/dev/john/update-logging-example/container-platform-starter/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/container-platform-starter/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/container-platform-starter/common/style/style.html b/dev/john/update-logging-example/container-platform-starter/common/style/style.html new file mode 100644 index 00000000..900e9730 --- /dev/null +++ b/dev/john/update-logging-example/container-platform-starter/common/style/style.html @@ -0,0 +1,410 @@ + + + + + + + Style Examples + + + + + +
+
+

This is the main title in the header

+

The is the title tag in the header.

+
+
+ OpenFin +
+
+ +
+

Header 1

+

Header 2

+

Header 3

+

Header 4

+
Header 5
+

A paragraph of text.

+

A primary element.

+

An errored element.

+

A success element.

+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + + +
+
+ + + + +
+
+ Link + Link [Disabled] + Link Button + Link Button [Disabled] +
+
+ +
Blah blah
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Title 1Title 2Title 3Action
Data 1Data 2Data 3 + + + +
Data 4Data 5Data 6 + + + +
Data 7Data 8Data 9 + + + +
+
+
+ +
+
+
Tag
+
Title
+
Actions
+
+
+
Tag Data 1
+
Title Data 1
+
+
+
+
Tag Data 2
+
Title Data 2
+
+
+
+
+
+ + Test Image +
+
+ + Test Image +
+
+
+ + + + diff --git a/dev/john/update-logging-example/container-platform-starter/common/views/platform/of-info/index.html b/dev/john/update-logging-example/container-platform-starter/common/views/platform/of-info/index.html new file mode 100644 index 00000000..6af50bd1 --- /dev/null +++ b/dev/john/update-logging-example/container-platform-starter/common/views/platform/of-info/index.html @@ -0,0 +1,55 @@ + + + + + + OpenFin Information + + + + + + +
+
+

OpenFin Information

+

Information about the OpenFin environment

+
+
+ OpenFin +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + diff --git a/dev/john/update-logging-example/container-platform-starter/common/views/platform/of-info/of-info.js b/dev/john/update-logging-example/container-platform-starter/common/views/platform/of-info/of-info.js new file mode 100644 index 00000000..348a7df2 --- /dev/null +++ b/dev/john/update-logging-example/container-platform-starter/common/views/platform/of-info/of-info.js @@ -0,0 +1,60 @@ +/** + * Displays a view with information about the OpenFin runtime. + */ + +document.addEventListener('DOMContentLoaded', () => { + try { + init(); + } catch (error) { + console.error(error); + } +}); + +/** + * Initialize the DOM elements. + */ +async function init() { + let rvmInfo; + + try { + rvmInfo = await fin.System.getRvmInfo(); + } catch (err) { + console.error(err); + } + + const rvmVersionElement = document.querySelector('#rvmVersion'); + rvmVersionElement.textContent = `v${rvmInfo?.version ?? 'unknown'}`; + + const rvmPathElement = document.querySelector('#rvmPath'); + rvmPathElement.textContent = rvmInfo?.path ?? 'unknown'; + + const appLogDirectoryElement = document.querySelector('#appLogDirectory'); + appLogDirectoryElement.textContent = rvmInfo?.appLogDirectory ?? 'unknown'; + + let runtimeInfo; + try { + runtimeInfo = await fin.System.getRuntimeInfo(); + } catch (err) { + console.error(err); + } + + const runtimeVersionElement = document.querySelector('#runtimeVersion'); + runtimeVersionElement.textContent = `v${runtimeInfo?.version ?? 'unknown'}`; + + const chromeVersionElement = document.querySelector('#chromeVersion'); + chromeVersionElement.textContent = `v${runtimeInfo?.chromeVersion ?? 'unknown'}`; + + const electronVersionElement = document.querySelector('#electronVersion'); + electronVersionElement.textContent = runtimeInfo?.electronVersion ?? 'unknown'; + + let platform; + + try { + platform = fin.Platform.getCurrentSync(); + } catch (err) { + console.error(err); + } + + const platformIdentityElement = document.querySelector('#platformIdentity'); + platformIdentityElement.textContent = platform?.identity?.uuid ?? 'unknown'; +} diff --git a/dev/john/update-logging-example/container-platform-starter/favicon.ico b/dev/john/update-logging-example/container-platform-starter/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/container-platform-starter/favicon.ico differ diff --git a/dev/john/update-logging-example/container-platform-starter/html/provider.html b/dev/john/update-logging-example/container-platform-starter/html/provider.html new file mode 100644 index 00000000..ea0d630d --- /dev/null +++ b/dev/john/update-logging-example/container-platform-starter/html/provider.html @@ -0,0 +1,15 @@ + + + + + + Platform Provider + + + + + + +
Custom Provider...
+ + diff --git a/dev/john/update-logging-example/container-platform-starter/js/provider.bundle.js b/dev/john/update-logging-example/container-platform-starter/js/provider.bundle.js new file mode 100644 index 00000000..4a9f51e6 --- /dev/null +++ b/dev/john/update-logging-example/container-platform-starter/js/provider.bundle.js @@ -0,0 +1,11 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/*!********************************!*\ + !*** ./client/src/provider.ts ***! + \********************************/ + +fin.Platform.init({}).catch((error) => console.error(error)); + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIuYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vY29udGFpbmVyLXBsYXRmb3JtLXN0YXJ0ZXIvLi9jbGllbnQvc3JjL3Byb3ZpZGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImZpbi5QbGF0Zm9ybS5pbml0KHt9KS5jYXRjaCgoZXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoZXJyb3IpKTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/container-platform-starter/manifest.fin.json b/dev/john/update-logging-example/container-platform-starter/manifest.fin.json new file mode 100644 index 00000000..a5238741 --- /dev/null +++ b/dev/john/update-logging-example/container-platform-starter/manifest.fin.json @@ -0,0 +1,43 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "enableBeforeUnload": true, + "uuid": "container-platform-starter", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/container-platform-starter/favicon.ico", + "autoShow": false, + "providerUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/container-platform-starter/html/provider.html" + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "row", + "content": [ + { + "type": "stack", + "content": [ + { + "type": "component", + "title": "view1", + "componentName": "view", + "componentState": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/container-platform-starter/common/views/platform/of-info/index.html", + "name": "view1", + "componentName": "view" + } + } + ] + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/create-window/app.fin.json b/dev/john/update-logging-example/create-window/app.fin.json new file mode 100644 index 00000000..e1af65bf --- /dev/null +++ b/dev/john/update-logging-example/create-window/app.fin.json @@ -0,0 +1,28 @@ +{ + "devtools_port": 9090, + "startup_app": { + "name": "OpenMultipleWindows", + "description": "OpenMultipleWindows", + "url": "http://www.google.com", + "showTaskbarIcon": true, + "taskbarIcon": "http://cdn.openfin.co/hyperblotter/favicon.ico", + "icon": "http://cdn.openfin.co/hyperblotter/favicon.ico", + "uuid": "OpenMultipleWindows", + "autoShow": true, + "contextMenu": true, + "defaultHeight": 500, + "defaultwidth": 500, + "frame": true, + "defaultCentered": true, + "resizable": true + }, + "runtime": { + "arguments": "--enable-crash-reporting --no-sandbox", + "version": "38.126.83.79" + }, + "shortcut": { + "company": "OpenFin", + "description": "Openfin openfin application window Sample", + "name": "Openfin application window" + } +} diff --git a/dev/john/update-logging-example/create-window/common/images/icon-blue.png b/dev/john/update-logging-example/create-window/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/create-window/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/create-window/common/style/app.css b/dev/john/update-logging-example/create-window/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/create-window/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/create-window/favicon.ico b/dev/john/update-logging-example/create-window/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/create-window/favicon.ico differ diff --git a/dev/john/update-logging-example/create-window/html/app.html b/dev/john/update-logging-example/create-window/html/app.html new file mode 100644 index 00000000..af29044d --- /dev/null +++ b/dev/john/update-logging-example/create-window/html/app.html @@ -0,0 +1,36 @@ + + + + + + + Create Window + + + + + +
+
+

Create Window

+

Demonstrate how to open windows.

+
+
+ OpenFin +
+
+
+ + +
+ + +
+ + +
+ + +
+ + diff --git a/dev/john/update-logging-example/create-window/html/window.html b/dev/john/update-logging-example/create-window/html/window.html new file mode 100644 index 00000000..8f5ba2f1 --- /dev/null +++ b/dev/john/update-logging-example/create-window/html/window.html @@ -0,0 +1,37 @@ + + + + + + + Data Window + + + + +
+
+

Data Window

+

Receiving Data from custom options.

+
+
+ OpenFin +
+
+
+ + + +
+ + diff --git a/dev/john/update-logging-example/create-window/js/app.bundle.js b/dev/john/update-logging-example/create-window/js/app.bundle.js new file mode 100644 index 00000000..745220b6 --- /dev/null +++ b/dev/john/update-logging-example/create-window/js/app.bundle.js @@ -0,0 +1,115 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +document.addEventListener("DOMContentLoaded", async () => { + try { + await initDom(); + } + catch (error) { + console.error(error); + } +}); +/** + * Initialize the DOM components. + */ +async function initDom() { + const btnOpenDynamicWindow = document.querySelector("#btn-open-dynamic-window"); + if (btnOpenDynamicWindow) { + btnOpenDynamicWindow.addEventListener("click", async (e) => openDynamicApplicationWindow()); + } + const btnOpenManifestWindow = document.querySelector("#btn-open-manifest-window"); + if (btnOpenManifestWindow) { + btnOpenManifestWindow.addEventListener("click", async (e) => openManifestApplicationWindow()); + } + const btnOpenDataWindow = document.querySelector("#btn-open-data-window"); + if (btnOpenDataWindow) { + btnOpenDataWindow.addEventListener("click", async (e) => openDataWindow()); + } + const btnOpenDataPlatformWindow = document.querySelector("#btn-open-data-platform-window"); + if (btnOpenDataPlatformWindow) { + btnOpenDataPlatformWindow.addEventListener("click", openDataPlatformWindow); + } +} +/** + * Open a window using dynamic options. + * @returns The window. + */ +async function openDynamicApplicationWindow() { + const winOption = { + name: "child", + defaultWidth: 800, + defaultHeight: 800, + url: "https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.create.html", + frame: true, + autoShow: true + }; + return fin.Window.create(winOption); +} +/** + * Open a window using a manifest. + */ +async function openManifestApplicationWindow() { + try { + await fin.Application.startFromManifest("https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/create-window/app.fin.json"); + console.log("App is running"); + } + catch (err) { + console.error(err); + } +} +/** + * Open a window and pass it custom data. + * @returns The window. + */ +async function openDataWindow() { + const winOption = { + name: "child-data", + defaultWidth: 800, + defaultHeight: 800, + url: "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/create-window/html/window.html", + frame: true, + autoShow: true, + customData: { + dateNow: Date.now() + } + }; + return fin.Window.create(winOption); +} +/** + * Open a platform window using options. + */ +async function openDataPlatformWindow() { + const viewOption = { + name: "childview-data", + url: "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/create-window/html/window.html", + customData: { + dateNow: Date.now() + } + }; + await fin.Platform.getCurrentSync().createView(viewOption); +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUU7WUFDWCxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtTQUNuQjtLQUNELENBQUM7SUFDRixPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQ3JDLENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxzQkFBc0I7SUFDcEMsTUFBTSxVQUFVLEdBQXdDO1FBQ3ZELElBQUksRUFBRSxnQkFBZ0I7UUFDdEIsR0FBRyxFQUFFLHdDQUF3QztRQUM3QyxVQUFVLEVBQUU7WUFDWCxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtTQUNuQjtLQUNzQyxDQUFDO0lBQ3pDLE1BQU0sR0FBRyxDQUFDLFFBQVEsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7QUFDNUQsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL2FwcGxpY2F0aW9uLXdpbmRvdy1jcmVhdGlvbi93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi13aW5kb3ctY3JlYXRpb24vd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi13aW5kb3ctY3JlYXRpb24vLi9jbGllbnQvc3JjL2FwcC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBhc3luYyAoKSA9PiB7XG5cdHRyeSB7XG5cdFx0YXdhaXQgaW5pdERvbSgpO1xuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuXHR9XG59KTtcblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSBET00gY29tcG9uZW50cy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gaW5pdERvbSgpOiBQcm9taXNlPHZvaWQ+IHtcblx0Y29uc3QgYnRuT3BlbkR5bmFtaWNXaW5kb3cgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2J0bi1vcGVuLWR5bmFtaWMtd2luZG93XCIpO1xuXHRpZiAoYnRuT3BlbkR5bmFtaWNXaW5kb3cpIHtcblx0XHRidG5PcGVuRHluYW1pY1dpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKGU6IEV2ZW50KSA9PiBvcGVuRHluYW1pY0FwcGxpY2F0aW9uV2luZG93KCkpO1xuXHR9XG5cblx0Y29uc3QgYnRuT3Blbk1hbmlmZXN0V2luZG93ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNidG4tb3Blbi1tYW5pZmVzdC13aW5kb3dcIik7XG5cdGlmIChidG5PcGVuTWFuaWZlc3RXaW5kb3cpIHtcblx0XHRidG5PcGVuTWFuaWZlc3RXaW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGFzeW5jIChlOiBFdmVudCkgPT4gb3Blbk1hbmlmZXN0QXBwbGljYXRpb25XaW5kb3coKSk7XG5cdH1cblxuXHRjb25zdCBidG5PcGVuRGF0YVdpbmRvdyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjYnRuLW9wZW4tZGF0YS13aW5kb3dcIik7XG5cdGlmIChidG5PcGVuRGF0YVdpbmRvdykge1xuXHRcdGJ0bk9wZW5EYXRhV2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoZTogRXZlbnQpID0+IG9wZW5EYXRhV2luZG93KCkpO1xuXHR9XG5cblx0Y29uc3QgYnRuT3BlbkRhdGFQbGF0Zm9ybVdpbmRvdyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjYnRuLW9wZW4tZGF0YS1wbGF0Zm9ybS13aW5kb3dcIik7XG5cdGlmIChidG5PcGVuRGF0YVBsYXRmb3JtV2luZG93KSB7XG5cdFx0YnRuT3BlbkRhdGFQbGF0Zm9ybVdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgb3BlbkRhdGFQbGF0Zm9ybVdpbmRvdyk7XG5cdH1cbn1cblxuLyoqXG4gKiBPcGVuIGEgd2luZG93IHVzaW5nIGR5bmFtaWMgb3B0aW9ucy5cbiAqIEByZXR1cm5zIFRoZSB3aW5kb3cuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIG9wZW5EeW5hbWljQXBwbGljYXRpb25XaW5kb3coKTogUHJvbWlzZTxPcGVuRmluLldpbmRvdz4ge1xuXHRjb25zdCB3aW5PcHRpb24gPSB7XG5cdFx0bmFtZTogXCJjaGlsZFwiLFxuXHRcdGRlZmF1bHRXaWR0aDogODAwLFxuXHRcdGRlZmF1bHRIZWlnaHQ6IDgwMCxcblx0XHR1cmw6IFwiaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5jcmVhdGUuaHRtbFwiLFxuXHRcdGZyYW1lOiB0cnVlLFxuXHRcdGF1dG9TaG93OiB0cnVlXG5cdH07XG5cdHJldHVybiBmaW4uV2luZG93LmNyZWF0ZSh3aW5PcHRpb24pO1xufVxuXG4vKipcbiAqIE9wZW4gYSB3aW5kb3cgdXNpbmcgYSBtYW5pZmVzdC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gb3Blbk1hbmlmZXN0QXBwbGljYXRpb25XaW5kb3coKTogUHJvbWlzZTx2b2lkPiB7XG5cdHRyeSB7XG5cdFx0YXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0RnJvbU1hbmlmZXN0KFwiaHR0cDovL2xvY2FsaG9zdDo1MDUwL2FwcC5maW4uanNvblwiKTtcblx0XHRjb25zb2xlLmxvZyhcIkFwcCBpcyBydW5uaW5nXCIpO1xuXHR9IGNhdGNoIChlcnIpIHtcblx0XHRjb25zb2xlLmVycm9yKGVycik7XG5cdH1cbn1cblxuLyoqXG4gKiBPcGVuIGEgd2luZG93IGFuZCBwYXNzIGl0IGN1c3RvbSBkYXRhLlxuICogQHJldHVybnMgVGhlIHdpbmRvdy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gb3BlbkRhdGFXaW5kb3coKTogUHJvbWlzZTxPcGVuRmluLldpbmRvdz4ge1xuXHRjb25zdCB3aW5PcHRpb24gPSB7XG5cdFx0bmFtZTogXCJjaGlsZC1kYXRhXCIsXG5cdFx0ZGVmYXVsdFdpZHRoOiA4MDAsXG5cdFx0ZGVmYXVsdEhlaWdodDogODAwLFxuXHRcdHVybDogXCJodHRwOi8vbG9jYWxob3N0OjUwNTAvaHRtbC93aW5kb3cuaHRtbFwiLFxuXHRcdGZyYW1lOiB0cnVlLFxuXHRcdGF1dG9TaG93OiB0cnVlLFxuXHRcdGN1c3RvbURhdGE6IHtcblx0XHRcdGRhdGVOb3c6IERhdGUubm93KClcblx0XHR9XG5cdH07XG5cdHJldHVybiBmaW4uV2luZG93LmNyZWF0ZSh3aW5PcHRpb24pO1xufVxuXG4vKipcbiAqIE9wZW4gYSBwbGF0Zm9ybSB3aW5kb3cgdXNpbmcgb3B0aW9ucy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gb3BlbkRhdGFQbGF0Zm9ybVdpbmRvdygpOiBQcm9taXNlPHZvaWQ+IHtcblx0Y29uc3Qgdmlld09wdGlvbjogT3BlbkZpbi5QbGF0Zm9ybVZpZXdDcmVhdGlvbk9wdGlvbnMgPSB7XG5cdFx0bmFtZTogXCJjaGlsZHZpZXctZGF0YVwiLFxuXHRcdHVybDogXCJodHRwOi8vbG9jYWxob3N0OjUwNTAvaHRtbC93aW5kb3cuaHRtbFwiLFxuXHRcdGN1c3RvbURhdGE6IHtcblx0XHRcdGRhdGVOb3c6IERhdGUubm93KClcblx0XHR9XG5cdH0gYXMgT3BlbkZpbi5QbGF0Zm9ybVZpZXdDcmVhdGlvbk9wdGlvbnM7XG5cdGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpLmNyZWF0ZVZpZXcodmlld09wdGlvbik7XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/create-window/manifest.fin.json b/dev/john/update-logging-example/create-window/manifest.fin.json new file mode 100644 index 00000000..5e8c8d5e --- /dev/null +++ b/dev/john/update-logging-example/create-window/manifest.fin.json @@ -0,0 +1,35 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "how-to-open-windows", + "autoShow": true, + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/create-window/favicon.ico" + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "stack", + "id": "no-drop-target", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "processAffinity": "ps_1", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/create-window/html/app.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/integration-excel/common/images/icon-blue.png b/dev/john/update-logging-example/integration-excel/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/integration-excel/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/integration-excel/common/style/app.css b/dev/john/update-logging-example/integration-excel/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/integration-excel/favicon.ico b/dev/john/update-logging-example/integration-excel/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/integration-excel/favicon.ico differ diff --git a/dev/john/update-logging-example/integration-excel/js/excel.bundle.js b/dev/john/update-logging-example/integration-excel/js/excel.bundle.js new file mode 100644 index 00000000..94c9c0b6 --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/js/excel.bundle.js @@ -0,0 +1,3617 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "../../node_modules/@finos/fdc3/dist/fdc3.esm.js": +/*!*******************************************************!*\ + !*** ../../node_modules/@finos/fdc3/dist/fdc3.esm.js ***! + \*******************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ BridgingError: () => (/* binding */ BridgingError), +/* harmony export */ BridgingTypes: () => (/* binding */ BridgingTypes), +/* harmony export */ ChannelError: () => (/* binding */ ChannelError), +/* harmony export */ ContextTypes: () => (/* binding */ ContextTypes), +/* harmony export */ Convert: () => (/* binding */ Convert), +/* harmony export */ Intents: () => (/* binding */ Intents), +/* harmony export */ OpenError: () => (/* binding */ OpenError), +/* harmony export */ ResolveError: () => (/* binding */ ResolveError), +/* harmony export */ ResultError: () => (/* binding */ ResultError), +/* harmony export */ addContextListener: () => (/* binding */ addContextListener), +/* harmony export */ addIntentListener: () => (/* binding */ addIntentListener), +/* harmony export */ broadcast: () => (/* binding */ broadcast), +/* harmony export */ compareVersionNumbers: () => (/* binding */ compareVersionNumbers), +/* harmony export */ createPrivateChannel: () => (/* binding */ createPrivateChannel), +/* harmony export */ fdc3Ready: () => (/* binding */ fdc3Ready), +/* harmony export */ findInstances: () => (/* binding */ findInstances), +/* harmony export */ findIntent: () => (/* binding */ findIntent), +/* harmony export */ findIntentsByContext: () => (/* binding */ findIntentsByContext), +/* harmony export */ getAppMetadata: () => (/* binding */ getAppMetadata), +/* harmony export */ getCurrentChannel: () => (/* binding */ getCurrentChannel), +/* harmony export */ getInfo: () => (/* binding */ getInfo), +/* harmony export */ getOrCreateChannel: () => (/* binding */ getOrCreateChannel), +/* harmony export */ getSystemChannels: () => (/* binding */ getSystemChannels), +/* harmony export */ getUserChannels: () => (/* binding */ getUserChannels), +/* harmony export */ isStandardContextType: () => (/* binding */ isStandardContextType), +/* harmony export */ isStandardIntent: () => (/* binding */ isStandardIntent), +/* harmony export */ joinChannel: () => (/* binding */ joinChannel), +/* harmony export */ joinUserChannel: () => (/* binding */ joinUserChannel), +/* harmony export */ leaveCurrentChannel: () => (/* binding */ leaveCurrentChannel), +/* harmony export */ open: () => (/* binding */ open), +/* harmony export */ raiseIntent: () => (/* binding */ raiseIntent), +/* harmony export */ raiseIntentForContext: () => (/* binding */ raiseIntentForContext), +/* harmony export */ versionIsAtLeast: () => (/* binding */ versionIsAtLeast) +/* harmony export */ }); +// To parse this data: +// +// import { Convert, AgentErrorResponseMessage, AgentRequestMessage, AgentResponseMessage, BridgeErrorResponseMessage, BridgeRequestMessage, BridgeResponseMessage, BroadcastAgentRequest, BroadcastBridgeRequest, ConnectionStepMessage, ConnectionStep2Hello, ConnectionStep3Handshake, ConnectionStep4AuthenticationFailed, ConnectionStep6ConnectedAgentsUpdate, FindInstancesAgentErrorResponse, FindInstancesAgentRequest, FindInstancesAgentResponse, FindInstancesBridgeErrorResponse, FindInstancesBridgeRequest, FindInstancesBridgeResponse, FindIntentAgentErrorResponse, FindIntentAgentRequest, FindIntentAgentResponse, FindIntentBridgeErrorResponse, FindIntentBridgeRequest, FindIntentBridgeResponse, FindIntentsByContextAgentErrorResponse, FindIntentsByContextAgentRequest, FindIntentsByContextAgentResponse, FindIntentsByContextBridgeErrorResponse, FindIntentsByContextBridgeRequest, FindIntentsByContextBridgeResponse, GetAppMetadataAgentErrorResponse, GetAppMetadataAgentRequest, GetAppMetadataAgentResponse, GetAppMetadataBridgeErrorResponse, GetAppMetadataBridgeRequest, GetAppMetadataBridgeResponse, OpenAgentErrorResponse, OpenAgentRequest, OpenAgentResponse, OpenBridgeErrorResponse, OpenBridgeRequest, OpenBridgeResponse, PrivateChannelBroadcastAgentRequest, PrivateChannelBroadcastBridgeRequest, PrivateChannelEventListenerAddedAgentRequest, PrivateChannelEventListenerAddedBridgeRequest, PrivateChannelEventListenerRemovedAgentRequest, PrivateChannelEventListenerRemovedBridgeRequest, PrivateChannelOnAddContextListenerAgentRequest, PrivateChannelOnAddContextListenerBridgeRequest, PrivateChannelOnDisconnectAgentRequest, PrivateChannelOnDisconnectBridgeRequest, PrivateChannelOnUnsubscribeAgentRequest, PrivateChannelOnUnsubscribeBridgeRequest, RaiseIntentAgentErrorResponse, RaiseIntentAgentRequest, RaiseIntentAgentResponse, RaiseIntentBridgeErrorResponse, RaiseIntentBridgeRequest, RaiseIntentBridgeResponse, RaiseIntentResultAgentErrorResponse, RaiseIntentResultAgentResponse, RaiseIntentResultBridgeErrorResponse, RaiseIntentResultBridgeResponse, Context } from "./file"; +// +// const fDC3DesktopAgentAPISchema = Convert.toFDC3DesktopAgentAPISchema(json); +// const agentErrorResponseMessage = Convert.toAgentErrorResponseMessage(json); +// const agentRequestMessage = Convert.toAgentRequestMessage(json); +// const agentResponseMessage = Convert.toAgentResponseMessage(json); +// const bridgeErrorResponseMessage = Convert.toBridgeErrorResponseMessage(json); +// const bridgeRequestMessage = Convert.toBridgeRequestMessage(json); +// const bridgeResponseMessage = Convert.toBridgeResponseMessage(json); +// const broadcastAgentRequest = Convert.toBroadcastAgentRequest(json); +// const broadcastBridgeRequest = Convert.toBroadcastBridgeRequest(json); +// const bridgingCommons = Convert.toBridgingCommons(json); +// const connectionStepMessage = Convert.toConnectionStepMessage(json); +// const connectionStep2Hello = Convert.toConnectionStep2Hello(json); +// const connectionStep3Handshake = Convert.toConnectionStep3Handshake(json); +// const connectionStep4AuthenticationFailed = Convert.toConnectionStep4AuthenticationFailed(json); +// const connectionStep6ConnectedAgentsUpdate = Convert.toConnectionStep6ConnectedAgentsUpdate(json); +// const findInstancesAgentErrorResponse = Convert.toFindInstancesAgentErrorResponse(json); +// const findInstancesAgentRequest = Convert.toFindInstancesAgentRequest(json); +// const findInstancesAgentResponse = Convert.toFindInstancesAgentResponse(json); +// const findInstancesBridgeErrorResponse = Convert.toFindInstancesBridgeErrorResponse(json); +// const findInstancesBridgeRequest = Convert.toFindInstancesBridgeRequest(json); +// const findInstancesBridgeResponse = Convert.toFindInstancesBridgeResponse(json); +// const findIntentAgentErrorResponse = Convert.toFindIntentAgentErrorResponse(json); +// const findIntentAgentRequest = Convert.toFindIntentAgentRequest(json); +// const findIntentAgentResponse = Convert.toFindIntentAgentResponse(json); +// const findIntentBridgeErrorResponse = Convert.toFindIntentBridgeErrorResponse(json); +// const findIntentBridgeRequest = Convert.toFindIntentBridgeRequest(json); +// const findIntentBridgeResponse = Convert.toFindIntentBridgeResponse(json); +// const findIntentsByContextAgentErrorResponse = Convert.toFindIntentsByContextAgentErrorResponse(json); +// const findIntentsByContextAgentRequest = Convert.toFindIntentsByContextAgentRequest(json); +// const findIntentsByContextAgentResponse = Convert.toFindIntentsByContextAgentResponse(json); +// const findIntentsByContextBridgeErrorResponse = Convert.toFindIntentsByContextBridgeErrorResponse(json); +// const findIntentsByContextBridgeRequest = Convert.toFindIntentsByContextBridgeRequest(json); +// const findIntentsByContextBridgeResponse = Convert.toFindIntentsByContextBridgeResponse(json); +// const getAppMetadataAgentErrorResponse = Convert.toGetAppMetadataAgentErrorResponse(json); +// const getAppMetadataAgentRequest = Convert.toGetAppMetadataAgentRequest(json); +// const getAppMetadataAgentResponse = Convert.toGetAppMetadataAgentResponse(json); +// const getAppMetadataBridgeErrorResponse = Convert.toGetAppMetadataBridgeErrorResponse(json); +// const getAppMetadataBridgeRequest = Convert.toGetAppMetadataBridgeRequest(json); +// const getAppMetadataBridgeResponse = Convert.toGetAppMetadataBridgeResponse(json); +// const openAgentErrorResponse = Convert.toOpenAgentErrorResponse(json); +// const openAgentRequest = Convert.toOpenAgentRequest(json); +// const openAgentResponse = Convert.toOpenAgentResponse(json); +// const openBridgeErrorResponse = Convert.toOpenBridgeErrorResponse(json); +// const openBridgeRequest = Convert.toOpenBridgeRequest(json); +// const openBridgeResponse = Convert.toOpenBridgeResponse(json); +// const privateChannelBroadcastAgentRequest = Convert.toPrivateChannelBroadcastAgentRequest(json); +// const privateChannelBroadcastBridgeRequest = Convert.toPrivateChannelBroadcastBridgeRequest(json); +// const privateChannelEventListenerAddedAgentRequest = Convert.toPrivateChannelEventListenerAddedAgentRequest(json); +// const privateChannelEventListenerAddedBridgeRequest = Convert.toPrivateChannelEventListenerAddedBridgeRequest(json); +// const privateChannelEventListenerRemovedAgentRequest = Convert.toPrivateChannelEventListenerRemovedAgentRequest(json); +// const privateChannelEventListenerRemovedBridgeRequest = Convert.toPrivateChannelEventListenerRemovedBridgeRequest(json); +// const privateChannelOnAddContextListenerAgentRequest = Convert.toPrivateChannelOnAddContextListenerAgentRequest(json); +// const privateChannelOnAddContextListenerBridgeRequest = Convert.toPrivateChannelOnAddContextListenerBridgeRequest(json); +// const privateChannelOnDisconnectAgentRequest = Convert.toPrivateChannelOnDisconnectAgentRequest(json); +// const privateChannelOnDisconnectBridgeRequest = Convert.toPrivateChannelOnDisconnectBridgeRequest(json); +// const privateChannelOnUnsubscribeAgentRequest = Convert.toPrivateChannelOnUnsubscribeAgentRequest(json); +// const privateChannelOnUnsubscribeBridgeRequest = Convert.toPrivateChannelOnUnsubscribeBridgeRequest(json); +// const raiseIntentAgentErrorResponse = Convert.toRaiseIntentAgentErrorResponse(json); +// const raiseIntentAgentRequest = Convert.toRaiseIntentAgentRequest(json); +// const raiseIntentAgentResponse = Convert.toRaiseIntentAgentResponse(json); +// const raiseIntentBridgeErrorResponse = Convert.toRaiseIntentBridgeErrorResponse(json); +// const raiseIntentBridgeRequest = Convert.toRaiseIntentBridgeRequest(json); +// const raiseIntentBridgeResponse = Convert.toRaiseIntentBridgeResponse(json); +// const raiseIntentResultAgentErrorResponse = Convert.toRaiseIntentResultAgentErrorResponse(json); +// const raiseIntentResultAgentResponse = Convert.toRaiseIntentResultAgentResponse(json); +// const raiseIntentResultBridgeErrorResponse = Convert.toRaiseIntentResultBridgeErrorResponse(json); +// const raiseIntentResultBridgeResponse = Convert.toRaiseIntentResultBridgeResponse(json); +// const context = Convert.toContext(json); +// +// These functions will throw an error if the JSON doesn't +// match the expected interface, even if the JSON is valid. +// Converts JSON strings to/from your types +// and asserts the results of JSON.parse at runtime +var Convert$1 = /** @class */ (function () { + function Convert() { + } + Convert.toFDC3DesktopAgentAPISchema = function (json) { + return cast$1(JSON.parse(json), "any"); + }; + Convert.fDC3DesktopAgentAPISchemaToJson = function (value) { + return JSON.stringify(uncast$1(value, "any"), null, 2); + }; + Convert.toAgentErrorResponseMessage = function (json) { + return cast$1(JSON.parse(json), r$1("AgentErrorResponseMessage")); + }; + Convert.agentErrorResponseMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("AgentErrorResponseMessage")), null, 2); + }; + Convert.toAgentRequestMessage = function (json) { + return cast$1(JSON.parse(json), r$1("AgentRequestMessage")); + }; + Convert.agentRequestMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("AgentRequestMessage")), null, 2); + }; + Convert.toAgentResponseMessage = function (json) { + return cast$1(JSON.parse(json), r$1("AgentResponseMessage")); + }; + Convert.agentResponseMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("AgentResponseMessage")), null, 2); + }; + Convert.toBridgeErrorResponseMessage = function (json) { + return cast$1(JSON.parse(json), r$1("BridgeErrorResponseMessage")); + }; + Convert.bridgeErrorResponseMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("BridgeErrorResponseMessage")), null, 2); + }; + Convert.toBridgeRequestMessage = function (json) { + return cast$1(JSON.parse(json), r$1("BridgeRequestMessage")); + }; + Convert.bridgeRequestMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("BridgeRequestMessage")), null, 2); + }; + Convert.toBridgeResponseMessage = function (json) { + return cast$1(JSON.parse(json), r$1("BridgeResponseMessage")); + }; + Convert.bridgeResponseMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("BridgeResponseMessage")), null, 2); + }; + Convert.toBroadcastAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("BroadcastAgentRequest")); + }; + Convert.broadcastAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("BroadcastAgentRequest")), null, 2); + }; + Convert.toBroadcastBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("BroadcastBridgeRequest")); + }; + Convert.broadcastBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("BroadcastBridgeRequest")), null, 2); + }; + Convert.toBridgingCommons = function (json) { + return cast$1(JSON.parse(json), m$1("any")); + }; + Convert.bridgingCommonsToJson = function (value) { + return JSON.stringify(uncast$1(value, m$1("any")), null, 2); + }; + Convert.toConnectionStepMessage = function (json) { + return cast$1(JSON.parse(json), r$1("ConnectionStepMessage")); + }; + Convert.connectionStepMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("ConnectionStepMessage")), null, 2); + }; + Convert.toConnectionStep2Hello = function (json) { + return cast$1(JSON.parse(json), r$1("ConnectionStep2Hello")); + }; + Convert.connectionStep2HelloToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("ConnectionStep2Hello")), null, 2); + }; + Convert.toConnectionStep3Handshake = function (json) { + return cast$1(JSON.parse(json), r$1("ConnectionStep3Handshake")); + }; + Convert.connectionStep3HandshakeToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("ConnectionStep3Handshake")), null, 2); + }; + Convert.toConnectionStep4AuthenticationFailed = function (json) { + return cast$1(JSON.parse(json), r$1("ConnectionStep4AuthenticationFailed")); + }; + Convert.connectionStep4AuthenticationFailedToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("ConnectionStep4AuthenticationFailed")), null, 2); + }; + Convert.toConnectionStep6ConnectedAgentsUpdate = function (json) { + return cast$1(JSON.parse(json), r$1("ConnectionStep6ConnectedAgentsUpdate")); + }; + Convert.connectionStep6ConnectedAgentsUpdateToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("ConnectionStep6ConnectedAgentsUpdate")), null, 2); + }; + Convert.toFindInstancesAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesAgentErrorResponse")); + }; + Convert.findInstancesAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesAgentErrorResponse")), null, 2); + }; + Convert.toFindInstancesAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesAgentRequest")); + }; + Convert.findInstancesAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesAgentRequest")), null, 2); + }; + Convert.toFindInstancesAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesAgentResponse")); + }; + Convert.findInstancesAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesAgentResponse")), null, 2); + }; + Convert.toFindInstancesBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesBridgeErrorResponse")); + }; + Convert.findInstancesBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesBridgeErrorResponse")), null, 2); + }; + Convert.toFindInstancesBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesBridgeRequest")); + }; + Convert.findInstancesBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesBridgeRequest")), null, 2); + }; + Convert.toFindInstancesBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesBridgeResponse")); + }; + Convert.findInstancesBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesBridgeResponse")), null, 2); + }; + Convert.toFindIntentAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentAgentErrorResponse")); + }; + Convert.findIntentAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentAgentErrorResponse")), null, 2); + }; + Convert.toFindIntentAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentAgentRequest")); + }; + Convert.findIntentAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentAgentRequest")), null, 2); + }; + Convert.toFindIntentAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentAgentResponse")); + }; + Convert.findIntentAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentAgentResponse")), null, 2); + }; + Convert.toFindIntentBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentBridgeErrorResponse")); + }; + Convert.findIntentBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentBridgeErrorResponse")), null, 2); + }; + Convert.toFindIntentBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentBridgeRequest")); + }; + Convert.findIntentBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentBridgeRequest")), null, 2); + }; + Convert.toFindIntentBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentBridgeResponse")); + }; + Convert.findIntentBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentBridgeResponse")), null, 2); + }; + Convert.toFindIntentsByContextAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextAgentErrorResponse")); + }; + Convert.findIntentsByContextAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextAgentErrorResponse")), null, 2); + }; + Convert.toFindIntentsByContextAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextAgentRequest")); + }; + Convert.findIntentsByContextAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextAgentRequest")), null, 2); + }; + Convert.toFindIntentsByContextAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextAgentResponse")); + }; + Convert.findIntentsByContextAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextAgentResponse")), null, 2); + }; + Convert.toFindIntentsByContextBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextBridgeErrorResponse")); + }; + Convert.findIntentsByContextBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextBridgeErrorResponse")), null, 2); + }; + Convert.toFindIntentsByContextBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextBridgeRequest")); + }; + Convert.findIntentsByContextBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextBridgeRequest")), null, 2); + }; + Convert.toFindIntentsByContextBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextBridgeResponse")); + }; + Convert.findIntentsByContextBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextBridgeResponse")), null, 2); + }; + Convert.toGetAppMetadataAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataAgentErrorResponse")); + }; + Convert.getAppMetadataAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataAgentErrorResponse")), null, 2); + }; + Convert.toGetAppMetadataAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataAgentRequest")); + }; + Convert.getAppMetadataAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataAgentRequest")), null, 2); + }; + Convert.toGetAppMetadataAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataAgentResponse")); + }; + Convert.getAppMetadataAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataAgentResponse")), null, 2); + }; + Convert.toGetAppMetadataBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataBridgeErrorResponse")); + }; + Convert.getAppMetadataBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataBridgeErrorResponse")), null, 2); + }; + Convert.toGetAppMetadataBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataBridgeRequest")); + }; + Convert.getAppMetadataBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataBridgeRequest")), null, 2); + }; + Convert.toGetAppMetadataBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataBridgeResponse")); + }; + Convert.getAppMetadataBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataBridgeResponse")), null, 2); + }; + Convert.toOpenAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("OpenAgentErrorResponse")); + }; + Convert.openAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenAgentErrorResponse")), null, 2); + }; + Convert.toOpenAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("OpenAgentRequest")); + }; + Convert.openAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenAgentRequest")), null, 2); + }; + Convert.toOpenAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("OpenAgentResponse")); + }; + Convert.openAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenAgentResponse")), null, 2); + }; + Convert.toOpenBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("OpenBridgeErrorResponse")); + }; + Convert.openBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenBridgeErrorResponse")), null, 2); + }; + Convert.toOpenBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("OpenBridgeRequest")); + }; + Convert.openBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenBridgeRequest")), null, 2); + }; + Convert.toOpenBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("OpenBridgeResponse")); + }; + Convert.openBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenBridgeResponse")), null, 2); + }; + Convert.toPrivateChannelBroadcastAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelBroadcastAgentRequest")); + }; + Convert.privateChannelBroadcastAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelBroadcastAgentRequest")), null, 2); + }; + Convert.toPrivateChannelBroadcastBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelBroadcastBridgeRequest")); + }; + Convert.privateChannelBroadcastBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelBroadcastBridgeRequest")), null, 2); + }; + Convert.toPrivateChannelEventListenerAddedAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelEventListenerAddedAgentRequest")); + }; + Convert.privateChannelEventListenerAddedAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelEventListenerAddedAgentRequest")), null, 2); + }; + Convert.toPrivateChannelEventListenerAddedBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelEventListenerAddedBridgeRequest")); + }; + Convert.privateChannelEventListenerAddedBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelEventListenerAddedBridgeRequest")), null, 2); + }; + Convert.toPrivateChannelEventListenerRemovedAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelEventListenerRemovedAgentRequest")); + }; + Convert.privateChannelEventListenerRemovedAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelEventListenerRemovedAgentRequest")), null, 2); + }; + Convert.toPrivateChannelEventListenerRemovedBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelEventListenerRemovedBridgeRequest")); + }; + Convert.privateChannelEventListenerRemovedBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelEventListenerRemovedBridgeRequest")), null, 2); + }; + Convert.toPrivateChannelOnAddContextListenerAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnAddContextListenerAgentRequest")); + }; + Convert.privateChannelOnAddContextListenerAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnAddContextListenerAgentRequest")), null, 2); + }; + Convert.toPrivateChannelOnAddContextListenerBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnAddContextListenerBridgeRequest")); + }; + Convert.privateChannelOnAddContextListenerBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnAddContextListenerBridgeRequest")), null, 2); + }; + Convert.toPrivateChannelOnDisconnectAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnDisconnectAgentRequest")); + }; + Convert.privateChannelOnDisconnectAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnDisconnectAgentRequest")), null, 2); + }; + Convert.toPrivateChannelOnDisconnectBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnDisconnectBridgeRequest")); + }; + Convert.privateChannelOnDisconnectBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnDisconnectBridgeRequest")), null, 2); + }; + Convert.toPrivateChannelOnUnsubscribeAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnUnsubscribeAgentRequest")); + }; + Convert.privateChannelOnUnsubscribeAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnUnsubscribeAgentRequest")), null, 2); + }; + Convert.toPrivateChannelOnUnsubscribeBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnUnsubscribeBridgeRequest")); + }; + Convert.privateChannelOnUnsubscribeBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnUnsubscribeBridgeRequest")), null, 2); + }; + Convert.toRaiseIntentAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentAgentErrorResponse")); + }; + Convert.raiseIntentAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentAgentErrorResponse")), null, 2); + }; + Convert.toRaiseIntentAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentAgentRequest")); + }; + Convert.raiseIntentAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentAgentRequest")), null, 2); + }; + Convert.toRaiseIntentAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentAgentResponse")); + }; + Convert.raiseIntentAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentAgentResponse")), null, 2); + }; + Convert.toRaiseIntentBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentBridgeErrorResponse")); + }; + Convert.raiseIntentBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentBridgeErrorResponse")), null, 2); + }; + Convert.toRaiseIntentBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentBridgeRequest")); + }; + Convert.raiseIntentBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentBridgeRequest")), null, 2); + }; + Convert.toRaiseIntentBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentBridgeResponse")); + }; + Convert.raiseIntentBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentBridgeResponse")), null, 2); + }; + Convert.toRaiseIntentResultAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentResultAgentErrorResponse")); + }; + Convert.raiseIntentResultAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentResultAgentErrorResponse")), null, 2); + }; + Convert.toRaiseIntentResultAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentResultAgentResponse")); + }; + Convert.raiseIntentResultAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentResultAgentResponse")), null, 2); + }; + Convert.toRaiseIntentResultBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentResultBridgeErrorResponse")); + }; + Convert.raiseIntentResultBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentResultBridgeErrorResponse")), null, 2); + }; + Convert.toRaiseIntentResultBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentResultBridgeResponse")); + }; + Convert.raiseIntentResultBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentResultBridgeResponse")), null, 2); + }; + Convert.toContext = function (json) { + return cast$1(JSON.parse(json), r$1("Context")); + }; + Convert.contextToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("Context")), null, 2); + }; + return Convert; +}()); +function invalidValue$1(typ, val, key, parent) { + if (parent === void 0) { parent = ''; } + var prettyTyp = prettyTypeName$1(typ); + var parentText = parent ? " on ".concat(parent) : ''; + var keyText = key ? " for key \"".concat(key, "\"") : ''; + throw Error("Invalid value".concat(keyText).concat(parentText, ". Expected ").concat(prettyTyp, " but got ").concat(JSON.stringify(val))); +} +function prettyTypeName$1(typ) { + if (Array.isArray(typ)) { + if (typ.length === 2 && typ[0] === undefined) { + return "an optional ".concat(prettyTypeName$1(typ[1])); + } + else { + return "one of [".concat(typ.map(function (a) { return prettyTypeName$1(a); }).join(", "), "]"); + } + } + else if (typeof typ === "object" && typ.literal !== undefined) { + return typ.literal; + } + else { + return typeof typ; + } +} +function jsonToJSProps$1(typ) { + if (typ.jsonToJS === undefined) { + var map_1 = {}; + typ.props.forEach(function (p) { return map_1[p.json] = { key: p.js, typ: p.typ }; }); + typ.jsonToJS = map_1; + } + return typ.jsonToJS; +} +function jsToJSONProps$1(typ) { + if (typ.jsToJSON === undefined) { + var map_2 = {}; + typ.props.forEach(function (p) { return map_2[p.js] = { key: p.json, typ: p.typ }; }); + typ.jsToJSON = map_2; + } + return typ.jsToJSON; +} +function transform$1(val, typ, getProps, key, parent) { + if (key === void 0) { key = ''; } + if (parent === void 0) { parent = ''; } + function transformPrimitive(typ, val) { + if (typeof typ === typeof val) + return val; + return invalidValue$1(typ, val, key, parent); + } + function transformUnion(typs, val) { + // val must validate against one typ in typs + var l = typs.length; + for (var i = 0; i < l; i++) { + var typ_1 = typs[i]; + try { + return transform$1(val, typ_1, getProps); + } + catch (_) { } + } + return invalidValue$1(typs, val, key, parent); + } + function transformEnum(cases, val) { + if (cases.indexOf(val) !== -1) + return val; + return invalidValue$1(cases.map(function (a) { return l$1(a); }), val, key, parent); + } + function transformArray(typ, val) { + // val must be an array with no invalid elements + if (!Array.isArray(val)) + return invalidValue$1(l$1("array"), val, key, parent); + return val.map(function (el) { return transform$1(el, typ, getProps); }); + } + function transformDate(val) { + if (val === null) { + return null; + } + var d = new Date(val); + if (isNaN(d.valueOf())) { + return invalidValue$1(l$1("Date"), val, key, parent); + } + return d; + } + function transformObject(props, additional, val) { + if (val === null || typeof val !== "object" || Array.isArray(val)) { + return invalidValue$1(l$1(ref || "object"), val, key, parent); + } + var result = {}; + Object.getOwnPropertyNames(props).forEach(function (key) { + var prop = props[key]; + var v = Object.prototype.hasOwnProperty.call(val, key) ? val[key] : undefined; + result[prop.key] = transform$1(v, prop.typ, getProps, key, ref); + }); + Object.getOwnPropertyNames(val).forEach(function (key) { + if (!Object.prototype.hasOwnProperty.call(props, key)) { + result[key] = transform$1(val[key], additional, getProps, key, ref); + } + }); + return result; + } + if (typ === "any") + return val; + if (typ === null) { + if (val === null) + return val; + return invalidValue$1(typ, val, key, parent); + } + if (typ === false) + return invalidValue$1(typ, val, key, parent); + var ref = undefined; + while (typeof typ === "object" && typ.ref !== undefined) { + ref = typ.ref; + typ = typeMap$1[typ.ref]; + } + if (Array.isArray(typ)) + return transformEnum(typ, val); + if (typeof typ === "object") { + return typ.hasOwnProperty("unionMembers") ? transformUnion(typ.unionMembers, val) + : typ.hasOwnProperty("arrayItems") ? transformArray(typ.arrayItems, val) + : typ.hasOwnProperty("props") ? transformObject(getProps(typ), typ.additional, val) + : invalidValue$1(typ, val, key, parent); + } + // Numbers can be parsed by Date but shouldn't be. + if (typ === Date && typeof val !== "number") + return transformDate(val); + return transformPrimitive(typ, val); +} +function cast$1(val, typ) { + return transform$1(val, typ, jsonToJSProps$1); +} +function uncast$1(val, typ) { + return transform$1(val, typ, jsToJSONProps$1); +} +function l$1(typ) { + return { literal: typ }; +} +function a$1(typ) { + return { arrayItems: typ }; +} +function u$1() { + var typs = []; + for (var _i = 0; _i < arguments.length; _i++) { + typs[_i] = arguments[_i]; + } + return { unionMembers: typs }; +} +function o$1(props, additional) { + return { props: props, additional: additional }; +} +function m$1(additional) { + return { props: [], additional: additional }; +} +function r$1(name) { + return { ref: name }; +} +var typeMap$1 = { + "AgentErrorResponseMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("AgentResponseMetadata") }, + { json: "payload", js: "payload", typ: r$1("ErrorResponseMessagePayload") }, + { json: "type", js: "type", typ: r$1("ResponseMessageType") }, + ], false), + "AgentResponseMetadata": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ErrorResponseMessagePayload": o$1([ + { json: "error", js: "error", typ: r$1("ResponseErrorDetail") }, + ], "any"), + "AgentRequestMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("AgentRequestMetadata") }, + { json: "payload", js: "payload", typ: m$1("any") }, + { json: "type", js: "type", typ: r$1("RequestMessageType") }, + ], false), + "AgentRequestMetadata": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceIdentifier")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "BridgeParticipantIdentifier": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "appId", js: "appId", typ: u$1(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "SourceIdentifier": o$1([ + { json: "appId", js: "appId", typ: u$1(undefined, "") }, + { json: "desktopAgent", js: "desktopAgent", typ: u$1(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "AgentResponseMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("AgentResponseMetadata") }, + { json: "payload", js: "payload", typ: m$1("any") }, + { json: "type", js: "type", typ: r$1("ResponseMessageType") }, + ], false), + "BridgeErrorResponseMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("BridgeErrorResponseMessageMeta") }, + { json: "payload", js: "payload", typ: r$1("ResponseErrorMessagePayload") }, + { json: "type", js: "type", typ: "" }, + ], false), + "BridgeErrorResponseMessageMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "DesktopAgentIdentifier": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + ], "any"), + "ResponseErrorMessagePayload": o$1([ + { json: "error", js: "error", typ: u$1(undefined, r$1("ResponseErrorDetail")) }, + ], "any"), + "BridgeRequestMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("BridgeRequestMetadata") }, + { json: "payload", js: "payload", typ: m$1("any") }, + { json: "type", js: "type", typ: "" }, + ], false), + "BridgeRequestMetadata": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("BridgeParticipantIdentifier") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "BridgeResponseMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("BridgeResponseMessageMeta") }, + { json: "payload", js: "payload", typ: m$1("any") }, + { json: "type", js: "type", typ: "" }, + ], false), + "BridgeResponseMessageMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "BroadcastAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("BroadcastAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("BroadcastAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("BroadcastAgentRequestType") }, + ], false), + "BroadcastAgentRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("SourceObject") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "SourceObject": o$1([ + { json: "appId", js: "appId", typ: "" }, + { json: "desktopAgent", js: "desktopAgent", typ: u$1(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "BroadcastAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "ContextElement": o$1([ + { json: "id", js: "id", typ: u$1(undefined, m$1("any")) }, + { json: "name", js: "name", typ: u$1(undefined, "") }, + { json: "type", js: "type", typ: "" }, + ], "any"), + "BroadcastBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("BroadcastBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("BroadcastBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("BroadcastAgentRequestType") }, + ], false), + "BroadcastBridgeRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "MetaSource": o$1([ + { json: "appId", js: "appId", typ: "" }, + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "BroadcastBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "ConnectionStepMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("ConnectionStepMetadata") }, + { json: "payload", js: "payload", typ: m$1("any") }, + { json: "type", js: "type", typ: r$1("ConnectionStepMessageType") }, + ], false), + "ConnectionStepMetadata": o$1([ + { json: "requestUuid", js: "requestUuid", typ: u$1(undefined, "") }, + { json: "responseUuid", js: "responseUuid", typ: u$1(undefined, "") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ConnectionStep2Hello": o$1([ + { json: "meta", js: "meta", typ: r$1("ConnectionStep2HelloMeta") }, + { json: "payload", js: "payload", typ: r$1("ConnectionStep2HelloPayload") }, + { json: "type", js: "type", typ: r$1("ConnectionStep2HelloType") }, + ], false), + "ConnectionStep2HelloMeta": o$1([ + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ConnectionStep2HelloPayload": o$1([ + { json: "authRequired", js: "authRequired", typ: true }, + { json: "authToken", js: "authToken", typ: u$1(undefined, "") }, + { json: "desktopAgentBridgeVersion", js: "desktopAgentBridgeVersion", typ: "" }, + { json: "supportedFDC3Versions", js: "supportedFDC3Versions", typ: a$1("") }, + ], false), + "ConnectionStep3Handshake": o$1([ + { json: "meta", js: "meta", typ: r$1("ConnectionStep3HandshakeMeta") }, + { json: "payload", js: "payload", typ: r$1("ConnectionStep3HandshakePayload") }, + { json: "type", js: "type", typ: r$1("ConnectionStep3HandshakeType") }, + ], false), + "ConnectionStep3HandshakeMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ConnectionStep3HandshakePayload": o$1([ + { json: "authToken", js: "authToken", typ: u$1(undefined, "") }, + { json: "channelsState", js: "channelsState", typ: m$1(a$1(r$1("ContextElement"))) }, + { json: "implementationMetadata", js: "implementationMetadata", typ: r$1("ConnectingAgentImplementationMetadata") }, + { json: "requestedName", js: "requestedName", typ: "" }, + ], false), + "ConnectingAgentImplementationMetadata": o$1([ + { json: "fdc3Version", js: "fdc3Version", typ: "" }, + { json: "optionalFeatures", js: "optionalFeatures", typ: r$1("OptionalFeatures") }, + { json: "provider", js: "provider", typ: "" }, + { json: "providerVersion", js: "providerVersion", typ: u$1(undefined, "") }, + ], false), + "OptionalFeatures": o$1([ + { json: "DesktopAgentBridging", js: "DesktopAgentBridging", typ: true }, + { json: "OriginatingAppMetadata", js: "OriginatingAppMetadata", typ: true }, + { json: "UserChannelMembershipAPIs", js: "UserChannelMembershipAPIs", typ: true }, + ], false), + "ConnectionStep4AuthenticationFailed": o$1([ + { json: "meta", js: "meta", typ: r$1("ConnectionStep4AuthenticationFailedMeta") }, + { json: "payload", js: "payload", typ: r$1("ConnectionStep4AuthenticationFailedPayload") }, + { json: "type", js: "type", typ: r$1("ConnectionStep4AuthenticationFailedType") }, + ], false), + "ConnectionStep4AuthenticationFailedMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ConnectionStep4AuthenticationFailedPayload": o$1([ + { json: "message", js: "message", typ: u$1(undefined, "") }, + ], false), + "ConnectionStep6ConnectedAgentsUpdate": o$1([ + { json: "meta", js: "meta", typ: r$1("ConnectionStep6ConnectedAgentsUpdateMeta") }, + { json: "payload", js: "payload", typ: r$1("ConnectionStep6ConnectedAgentsUpdatePayload") }, + { json: "type", js: "type", typ: r$1("ConnectionStep6ConnectedAgentsUpdateType") }, + ], false), + "ConnectionStep6ConnectedAgentsUpdateMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ConnectionStep6ConnectedAgentsUpdatePayload": o$1([ + { json: "addAgent", js: "addAgent", typ: u$1(undefined, "") }, + { json: "allAgents", js: "allAgents", typ: a$1(r$1("DesktopAgentImplementationMetadata")) }, + { json: "channelsState", js: "channelsState", typ: u$1(undefined, m$1(a$1(r$1("ContextElement")))) }, + { json: "removeAgent", js: "removeAgent", typ: u$1(undefined, "") }, + ], false), + "DesktopAgentImplementationMetadata": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "fdc3Version", js: "fdc3Version", typ: "" }, + { json: "optionalFeatures", js: "optionalFeatures", typ: r$1("OptionalFeatures") }, + { json: "provider", js: "provider", typ: "" }, + { json: "providerVersion", js: "providerVersion", typ: u$1(undefined, "") }, + ], false), + "FindInstancesAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentErrorResponseType") }, + ], false), + "FindInstancesAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindInstancesAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindInstancesAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentRequestType") }, + ], false), + "FindInstancesAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceIdentifier")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "DestinationObject": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "appId", js: "appId", typ: u$1(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "FindInstancesAgentRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppIdentifier") }, + ], false), + "AppIdentifier": o$1([ + { json: "appId", js: "appId", typ: "" }, + { json: "desktopAgent", js: "desktopAgent", typ: u$1(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "FindInstancesAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentErrorResponseType") }, + ], false), + "FindInstancesAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindInstancesAgentResponsePayload": o$1([ + { json: "appIdentifiers", js: "appIdentifiers", typ: a$1(r$1("AppMetadata")) }, + ], false), + "AppMetadata": o$1([ + { json: "appId", js: "appId", typ: "" }, + { json: "description", js: "description", typ: u$1(undefined, "") }, + { json: "desktopAgent", js: "desktopAgent", typ: u$1(undefined, "") }, + { json: "icons", js: "icons", typ: u$1(undefined, a$1(r$1("Icon"))) }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + { json: "instanceMetadata", js: "instanceMetadata", typ: u$1(undefined, m$1("any")) }, + { json: "name", js: "name", typ: u$1(undefined, "") }, + { json: "resultType", js: "resultType", typ: u$1(undefined, u$1(null, "")) }, + { json: "screenshots", js: "screenshots", typ: u$1(undefined, a$1(r$1("Image"))) }, + { json: "title", js: "title", typ: u$1(undefined, "") }, + { json: "tooltip", js: "tooltip", typ: u$1(undefined, "") }, + { json: "version", js: "version", typ: u$1(undefined, "") }, + ], false), + "Icon": o$1([ + { json: "size", js: "size", typ: u$1(undefined, "") }, + { json: "src", js: "src", typ: "" }, + { json: "type", js: "type", typ: u$1(undefined, "") }, + ], false), + "Image": o$1([ + { json: "label", js: "label", typ: u$1(undefined, "") }, + { json: "size", js: "size", typ: u$1(undefined, "") }, + { json: "src", js: "src", typ: "" }, + { json: "type", js: "type", typ: u$1(undefined, "") }, + ], false), + "FindInstancesBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentErrorResponseType") }, + ], false), + "FindInstancesBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindInstancesBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindInstancesBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentRequestType") }, + ], false), + "FindInstancesBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSourceObject") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "MetaSourceObject": o$1([ + { json: "appId", js: "appId", typ: u$1(undefined, "") }, + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "FindInstancesBridgeRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppIdentifier") }, + ], false), + "FindInstancesBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentErrorResponseType") }, + ], false), + "FindInstancesBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindInstancesBridgeResponsePayload": o$1([ + { json: "appIdentifiers", js: "appIdentifiers", typ: a$1(r$1("AppMetadata")) }, + ], false), + "FindIntentAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentErrorResponseType") }, + ], false), + "FindIntentAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindIntentAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentRequestType") }, + ], false), + "FindIntentAgentRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceIdentifier")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + ], false), + "FindIntentAgentRequestPayload": o$1([ + { json: "context", js: "context", typ: u$1(undefined, r$1("ContextElement")) }, + { json: "intent", js: "intent", typ: "" }, + { json: "resultType", js: "resultType", typ: u$1(undefined, "") }, + ], false), + "FindIntentAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentErrorResponseType") }, + ], false), + "FindIntentAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentAgentResponsePayload": o$1([ + { json: "appIntent", js: "appIntent", typ: r$1("AppIntent") }, + ], false), + "AppIntent": o$1([ + { json: "apps", js: "apps", typ: a$1(r$1("AppMetadata")) }, + { json: "intent", js: "intent", typ: r$1("IntentMetadata") }, + ], false), + "IntentMetadata": o$1([ + { json: "displayName", js: "displayName", typ: "" }, + { json: "name", js: "name", typ: "" }, + ], false), + "FindIntentBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentErrorResponseType") }, + ], false), + "FindIntentBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindIntentBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentRequestType") }, + ], false), + "FindIntentBridgeRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("BridgeParticipantIdentifier") }, + { json: "timestamp", js: "timestamp", typ: Date }, + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + ], false), + "FindIntentBridgeRequestPayload": o$1([ + { json: "context", js: "context", typ: u$1(undefined, r$1("ContextElement")) }, + { json: "intent", js: "intent", typ: "" }, + { json: "resultType", js: "resultType", typ: u$1(undefined, "") }, + ], false), + "FindIntentBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentErrorResponseType") }, + ], false), + "FindIntentBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentBridgeResponsePayload": o$1([ + { json: "appIntent", js: "appIntent", typ: r$1("AppIntent") }, + ], false), + "FindIntentsByContextAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentErrorResponseType") }, + ], false), + "FindIntentsByContextAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentsByContextAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindIntentsByContextAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentRequestType") }, + ], false), + "FindIntentsByContextAgentRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + ], false), + "FindIntentsByContextAgentRequestPayload": o$1([ + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "FindIntentsByContextAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentErrorResponseType") }, + ], false), + "FindIntentsByContextAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentsByContextAgentResponsePayload": o$1([ + { json: "appIntents", js: "appIntents", typ: a$1(r$1("AppIntent")) }, + ], false), + "FindIntentsByContextBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentErrorResponseType") }, + ], false), + "FindIntentsByContextBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentsByContextBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindIntentsByContextBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentRequestType") }, + ], false), + "FindIntentsByContextBridgeRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + ], false), + "FindIntentsByContextBridgeRequestPayload": o$1([ + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "FindIntentsByContextBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentErrorResponseType") }, + ], false), + "FindIntentsByContextBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentsByContextBridgeResponsePayload": o$1([ + { json: "appIntents", js: "appIntents", typ: a$1(r$1("AppIntent")) }, + ], false), + "GetAppMetadataAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentErrorResponseType") }, + ], false), + "GetAppMetadataAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "GetAppMetadataAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentRequestType") }, + ], false), + "GetAppMetadataAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceIdentifier")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataAgentRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppDestinationIdentifier") }, + ], false), + "AppDestinationIdentifier": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "appId", js: "appId", typ: "" }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "GetAppMetadataAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentErrorResponseType") }, + ], false), + "GetAppMetadataAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataAgentResponsePayload": o$1([ + { json: "appMetadata", js: "appMetadata", typ: r$1("AppMetadata") }, + ], false), + "GetAppMetadataBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentErrorResponseType") }, + ], false), + "GetAppMetadataBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "GetAppMetadataBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentRequestType") }, + ], false), + "GetAppMetadataBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSourceObject") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataBridgeRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppDestinationIdentifier") }, + ], false), + "GetAppMetadataBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentErrorResponseType") }, + ], false), + "GetAppMetadataBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataBridgeResponsePayload": o$1([ + { json: "appMetadata", js: "appMetadata", typ: r$1("AppMetadata") }, + ], false), + "OpenAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentErrorResponseType") }, + ], false), + "OpenAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("OpenErrorMessage") }, + ], false), + "OpenAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentRequestType") }, + ], false), + "OpenAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("SourceObject") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenAgentRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppToOpen") }, + { json: "context", js: "context", typ: u$1(undefined, r$1("ContextElement")) }, + ], false), + "AppToOpen": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "appId", js: "appId", typ: "" }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "OpenAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentErrorResponseType") }, + ], false), + "OpenAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenAgentResponsePayload": o$1([ + { json: "appIdentifier", js: "appIdentifier", typ: r$1("AppIdentifier") }, + ], false), + "OpenBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentErrorResponseType") }, + ], false), + "OpenBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("OpenErrorMessage") }, + ], false), + "OpenBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentRequestType") }, + ], false), + "OpenBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenBridgeRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppToOpen") }, + { json: "context", js: "context", typ: u$1(undefined, r$1("ContextElement")) }, + ], false), + "OpenBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentErrorResponseType") }, + ], false), + "OpenBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenBridgeResponsePayload": o$1([ + { json: "appIdentifier", js: "appIdentifier", typ: r$1("AppIdentifier") }, + ], false), + "PrivateChannelBroadcastAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelBroadcastAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelBroadcastAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelBroadcastAgentRequestType") }, + ], false), + "PrivateChannelBroadcastAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "MetaDestination": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "appId", js: "appId", typ: "" }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "PrivateChannelBroadcastAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "PrivateChannelBroadcastBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelBroadcastBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelBroadcastBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelBroadcastAgentRequestType") }, + ], false), + "PrivateChannelBroadcastBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelBroadcastBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "PrivateChannelEventListenerAddedAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelEventListenerAddedAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelEventListenerAddedAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelEventListenerAddedAgentRequestType") }, + ], false), + "PrivateChannelEventListenerAddedAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelEventListenerAddedAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "listenerType", js: "listenerType", typ: r$1("PrivateChannelEventListenerTypes") }, + ], false), + "PrivateChannelEventListenerAddedBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelEventListenerAddedBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelEventListenerAddedBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelEventListenerAddedAgentRequestType") }, + ], false), + "PrivateChannelEventListenerAddedBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelEventListenerAddedBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "listenerType", js: "listenerType", typ: r$1("PrivateChannelEventListenerTypes") }, + ], false), + "PrivateChannelEventListenerRemovedAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelEventListenerRemovedAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelEventListenerRemovedAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelEventListenerRemovedAgentRequestType") }, + ], false), + "PrivateChannelEventListenerRemovedAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelEventListenerRemovedAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "listenerType", js: "listenerType", typ: r$1("PrivateChannelEventListenerTypes") }, + ], false), + "PrivateChannelEventListenerRemovedBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelEventListenerRemovedBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelEventListenerRemovedBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelEventListenerRemovedAgentRequestType") }, + ], false), + "PrivateChannelEventListenerRemovedBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelEventListenerRemovedBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "listenerType", js: "listenerType", typ: r$1("PrivateChannelEventListenerTypes") }, + ], false), + "PrivateChannelOnAddContextListenerAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelOnAddContextListenerAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnAddContextListenerAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnAddContextListenerAgentRequestType") }, + ], false), + "PrivateChannelOnAddContextListenerAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnAddContextListenerAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "contextType", js: "contextType", typ: u$1(null, "") }, + ], false), + "PrivateChannelOnAddContextListenerBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelOnAddContextListenerBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnAddContextListenerBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnAddContextListenerAgentRequestType") }, + ], false), + "PrivateChannelOnAddContextListenerBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnAddContextListenerBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "contextType", js: "contextType", typ: u$1(null, "") }, + ], false), + "PrivateChannelOnDisconnectAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelOnDisconnectAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnDisconnectAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnDisconnectAgentRequestType") }, + ], false), + "PrivateChannelOnDisconnectAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnDisconnectAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + ], false), + "PrivateChannelOnDisconnectBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelOnDisconnectBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnDisconnectBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnDisconnectAgentRequestType") }, + ], false), + "PrivateChannelOnDisconnectBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnDisconnectBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + ], false), + "PrivateChannelOnUnsubscribeAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelOnUnsubscribeAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnUnsubscribeAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnUnsubscribeAgentRequestType") }, + ], false), + "PrivateChannelOnUnsubscribeAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnUnsubscribeAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "contextType", js: "contextType", typ: u$1(null, "") }, + ], false), + "PrivateChannelOnUnsubscribeBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("ERequestMetadata") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnUnsubscribeBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnUnsubscribeAgentRequestType") }, + ], false), + "ERequestMetadata": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnUnsubscribeBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "contextType", js: "contextType", typ: u$1(null, "") }, + ], false), + "RaiseIntentAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentErrorResponseType") }, + ], false), + "RaiseIntentAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "RaiseIntentAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentRequestType") }, + ], false), + "RaiseIntentAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: r$1("MetaDestination") }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("SourceObject") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentAgentRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppDestinationIdentifier") }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + { json: "intent", js: "intent", typ: "" }, + ], false), + "RaiseIntentAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentErrorResponseType") }, + ], false), + "RaiseIntentAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentAgentResponsePayload": o$1([ + { json: "intentResolution", js: "intentResolution", typ: r$1("IntentResolution") }, + ], false), + "IntentResolution": o$1([ + { json: "intent", js: "intent", typ: "" }, + { json: "source", js: "source", typ: r$1("AppIdentifier") }, + { json: "version", js: "version", typ: u$1(undefined, "") }, + ], false), + "RaiseIntentBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentErrorResponseType") }, + ], false), + "RaiseIntentBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "RaiseIntentBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentRequestType") }, + ], false), + "RaiseIntentBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: r$1("MetaDestination") }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentBridgeRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppDestinationIdentifier") }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + { json: "intent", js: "intent", typ: "" }, + ], false), + "RaiseIntentBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentErrorResponseType") }, + ], false), + "RaiseIntentBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentBridgeResponsePayload": o$1([ + { json: "intentResolution", js: "intentResolution", typ: r$1("IntentResolution") }, + ], false), + "RaiseIntentResultAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentResultAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentResultAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentResultAgentErrorResponseType") }, + ], false), + "RaiseIntentResultAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentResultAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("RaiseIntentResultErrorMessage") }, + ], false), + "RaiseIntentResultAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentResultAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentResultAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentResultAgentErrorResponseType") }, + ], false), + "RaiseIntentResultAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentResultAgentResponsePayload": o$1([ + { json: "intentResult", js: "intentResult", typ: r$1("IntentResult") }, + ], false), + "IntentResult": o$1([ + { json: "context", js: "context", typ: u$1(undefined, r$1("ContextElement")) }, + { json: "channel", js: "channel", typ: u$1(undefined, r$1("Channel")) }, + ], false), + "Channel": o$1([ + { json: "displayMetadata", js: "displayMetadata", typ: u$1(undefined, r$1("DisplayMetadata")) }, + { json: "id", js: "id", typ: "" }, + { json: "type", js: "type", typ: r$1("Type") }, + ], false), + "DisplayMetadata": o$1([ + { json: "color", js: "color", typ: u$1(undefined, "") }, + { json: "glyph", js: "glyph", typ: u$1(undefined, "") }, + { json: "name", js: "name", typ: u$1(undefined, "") }, + ], false), + "RaiseIntentResultBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentResultBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentResultBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentResultAgentErrorResponseType") }, + ], false), + "RaiseIntentResultBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentResultBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("RaiseIntentResultErrorMessage") }, + ], false), + "RaiseIntentResultBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentResultBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentResultBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentResultAgentErrorResponseType") }, + ], false), + "RaiseIntentResultBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentResultBridgeResponsePayload": o$1([ + { json: "intentResult", js: "intentResult", typ: r$1("IntentResult") }, + ], false), + "Context": o$1([ + { json: "id", js: "id", typ: u$1(undefined, m$1("any")) }, + { json: "name", js: "name", typ: u$1(undefined, "") }, + { json: "type", js: "type", typ: "" }, + ], "any"), + "ResponseErrorDetail": [ + "AccessDenied", + "AgentDisconnected", + "AppNotFound", + "AppTimeout", + "CreationFailed", + "DesktopAgentNotFound", + "ErrorOnLaunch", + "IntentDeliveryFailed", + "IntentHandlerRejected", + "MalformedContext", + "MalformedMessage", + "NoAppsFound", + "NoChannelFound", + "NoResultReturned", + "NotConnectedToBridge", + "ResolverTimeout", + "ResolverUnavailable", + "ResponseToBridgeTimedOut", + "TargetAppUnavailable", + "TargetInstanceUnavailable", + "UserCancelledResolution", + ], + "ResponseMessageType": [ + "findInstancesResponse", + "findIntentResponse", + "findIntentsByContextResponse", + "getAppMetadataResponse", + "openResponse", + "raiseIntentResponse", + "raiseIntentResultResponse", + ], + "RequestMessageType": [ + "broadcastRequest", + "findInstancesRequest", + "findIntentRequest", + "findIntentsByContextRequest", + "getAppMetadataRequest", + "openRequest", + "PrivateChannel.broadcast", + "PrivateChannel.eventListenerAdded", + "PrivateChannel.eventListenerRemoved", + "PrivateChannel.onAddContextListener", + "PrivateChannel.onDisconnect", + "PrivateChannel.onUnsubscribe", + "raiseIntentRequest", + ], + "BroadcastAgentRequestType": [ + "broadcastRequest", + ], + "ConnectionStepMessageType": [ + "authenticationFailed", + "connectedAgentsUpdate", + "handshake", + "hello", + ], + "ConnectionStep2HelloType": [ + "hello", + ], + "ConnectionStep3HandshakeType": [ + "handshake", + ], + "ConnectionStep4AuthenticationFailedType": [ + "authenticationFailed", + ], + "ConnectionStep6ConnectedAgentsUpdateType": [ + "connectedAgentsUpdate", + ], + "ErrorMessage": [ + "AgentDisconnected", + "DesktopAgentNotFound", + "IntentDeliveryFailed", + "MalformedContext", + "MalformedMessage", + "NoAppsFound", + "NotConnectedToBridge", + "ResolverTimeout", + "ResolverUnavailable", + "ResponseToBridgeTimedOut", + "TargetAppUnavailable", + "TargetInstanceUnavailable", + "UserCancelledResolution", + ], + "FindInstancesAgentErrorResponseType": [ + "findInstancesResponse", + ], + "FindInstancesAgentRequestType": [ + "findInstancesRequest", + ], + "FindIntentAgentErrorResponseType": [ + "findIntentResponse", + ], + "FindIntentAgentRequestType": [ + "findIntentRequest", + ], + "FindIntentsByContextAgentErrorResponseType": [ + "findIntentsByContextResponse", + ], + "FindIntentsByContextAgentRequestType": [ + "findIntentsByContextRequest", + ], + "GetAppMetadataAgentErrorResponseType": [ + "getAppMetadataResponse", + ], + "GetAppMetadataAgentRequestType": [ + "getAppMetadataRequest", + ], + "OpenErrorMessage": [ + "AgentDisconnected", + "AppNotFound", + "AppTimeout", + "DesktopAgentNotFound", + "ErrorOnLaunch", + "MalformedContext", + "MalformedMessage", + "NotConnectedToBridge", + "ResolverUnavailable", + "ResponseToBridgeTimedOut", + ], + "OpenAgentErrorResponseType": [ + "openResponse", + ], + "OpenAgentRequestType": [ + "openRequest", + ], + "PrivateChannelBroadcastAgentRequestType": [ + "PrivateChannel.broadcast", + ], + "PrivateChannelEventListenerTypes": [ + "onAddContextListener", + "onDisconnect", + "onUnsubscribe", + ], + "PrivateChannelEventListenerAddedAgentRequestType": [ + "PrivateChannel.eventListenerAdded", + ], + "PrivateChannelEventListenerRemovedAgentRequestType": [ + "PrivateChannel.eventListenerRemoved", + ], + "PrivateChannelOnAddContextListenerAgentRequestType": [ + "PrivateChannel.onAddContextListener", + ], + "PrivateChannelOnDisconnectAgentRequestType": [ + "PrivateChannel.onDisconnect", + ], + "PrivateChannelOnUnsubscribeAgentRequestType": [ + "PrivateChannel.onUnsubscribe", + ], + "RaiseIntentAgentErrorResponseType": [ + "raiseIntentResponse", + ], + "RaiseIntentAgentRequestType": [ + "raiseIntentRequest", + ], + "RaiseIntentResultErrorMessage": [ + "AgentDisconnected", + "IntentHandlerRejected", + "MalformedMessage", + "NoResultReturned", + "NotConnectedToBridge", + "ResponseToBridgeTimedOut", + ], + "RaiseIntentResultAgentErrorResponseType": [ + "raiseIntentResultResponse", + ], + "Type": [ + "app", + "private", + "user", + ] +}; + +var BridgingTypes = { + __proto__: null, + Convert: Convert$1 +}; + +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright FINOS FDC3 contributors - see NOTICE file + */ +/** Constants representing the errors that can be encountered when calling the `open` method on the DesktopAgent object (`fdc3`). */ +var OpenError; +(function (OpenError) { + /** Returned if the specified application is not found.*/ + OpenError["AppNotFound"] = "AppNotFound"; + /** Returned if the specified application fails to launch correctly.*/ + OpenError["ErrorOnLaunch"] = "ErrorOnLaunch"; + /** Returned if the specified application launches but fails to add a context listener in order to receive the context passed to the `fdc3.open` call.*/ + OpenError["AppTimeout"] = "AppTimeout"; + /** Returned if the FDC3 desktop agent implementation is not currently able to handle the request.*/ + OpenError["ResolverUnavailable"] = "ResolverUnavailable"; + /** Returned if a call to the `open` function is made with an invalid context argument. Contexts should be Objects with at least a `type` field that has a `string` value.*/ + OpenError["MalformedContext"] = "MalformedContext"; + /** @experimental Returned if the specified Desktop Agent is not found, via a connected Desktop Agent Bridge.*/ + OpenError["DesktopAgentNotFound"] = "DesktopAgentNotFound"; +})(OpenError || (OpenError = {})); +/** Constants representing the errors that can be encountered when calling the `findIntent`, `findIntentsByContext`, `raiseIntent` or `raiseIntentForContext` methods on the DesktopAgent (`fdc3`). */ +var ResolveError; +(function (ResolveError) { + /** SHOULD be returned if no apps are available that can resolve the intent and context combination.*/ + ResolveError["NoAppsFound"] = "NoAppsFound"; + /** Returned if the FDC3 desktop agent implementation is not currently able to handle the request.*/ + ResolveError["ResolverUnavailable"] = "ResolverUnavailable"; + /** Returned if the user cancelled the resolution request, for example by closing or cancelling a resolver UI.*/ + ResolveError["UserCancelled"] = "UserCancelledResolution"; + /** SHOULD be returned if a timeout cancels an intent resolution that required user interaction. Please use `ResolverUnavailable` instead for situations where a resolver UI or similar fails.*/ + ResolveError["ResolverTimeout"] = "ResolverTimeout"; + /** Returned if a specified target application is not available or a new instance of it cannot be opened. */ + ResolveError["TargetAppUnavailable"] = "TargetAppUnavailable"; + /** Returned if a specified target application instance is not available, for example because it has been closed. */ + ResolveError["TargetInstanceUnavailable"] = "TargetInstanceUnavailable"; + /** Returned if the intent and context could not be delivered to the selected application or instance, for example because it has not added an intent handler within a timeout.*/ + ResolveError["IntentDeliveryFailed"] = "IntentDeliveryFailed"; + /** Returned if a call to one of the `raiseIntent` functions is made with an invalid context argument. Contexts should be Objects with at least a `type` field that has a `string` value.*/ + ResolveError["MalformedContext"] = "MalformedContext"; + /** @experimental Returned if the specified Desktop Agent is not found, via a connected Desktop Agent Bridge.*/ + ResolveError["DesktopAgentNotFound"] = "DesktopAgentNotFound"; +})(ResolveError || (ResolveError = {})); +var ResultError; +(function (ResultError) { + /** Returned if the intent handler exited without returning a valid result (a promise resolving to a Context, Channel object or void). */ + ResultError["NoResultReturned"] = "NoResultReturned"; + /** Returned if the Intent handler function processing the raised intent throws an error or rejects the Promise it returned. */ + ResultError["IntentHandlerRejected"] = "IntentHandlerRejected"; +})(ResultError || (ResultError = {})); +var ChannelError; +(function (ChannelError) { + /** Returned if the specified channel is not found when attempting to join a channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`).*/ + ChannelError["NoChannelFound"] = "NoChannelFound"; + /** SHOULD be returned when a request to join a user channel or to a retrieve a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods of the DesktopAgent (`fdc3`) object is denied. */ + ChannelError["AccessDenied"] = "AccessDenied"; + /** SHOULD be returned when a channel cannot be created or retrieved via the `getOrCreateChannel` method of the DesktopAgent (`fdc3`).*/ + ChannelError["CreationFailed"] = "CreationFailed"; + /** Returned if a call to the `broadcast` functions is made with an invalid context argument. Contexts should be Objects with at least a `type` field that has a `string` value.*/ + ChannelError["MalformedContext"] = "MalformedContext"; +})(ChannelError || (ChannelError = {})); +var BridgingError; +(function (BridgingError) { + /** @experimental Returned if a Desktop Agent did not return a response, via Desktop Agent Bridging, within the alloted timeout. */ + BridgingError["ResponseTimedOut"] = "ResponseToBridgeTimedOut"; + /** @experimental Returned if a Desktop Agent that has been targeted by a particular request has been disconnected from the Bridge before a response has been received from it. */ + BridgingError["AgentDisconnected"] = "AgentDisconnected"; + /** @experimental Returned for FDC3 API calls that are specified with arguments indicating that a remote Desktop agent should be targeted (e.g. raiseIntent with an app on a remote DesktopAgent targeted), when the local Desktop Agent is not connected to a bridge. */ + BridgingError["NotConnectedToBridge"] = "NotConnectedToBridge"; + /** @experimental Returned if a message to a Bridge deviates from the schema for that message sufficiently that it could not be processed. */ + BridgingError["MalformedMessage"] = "MalformedMessage"; +})(BridgingError || (BridgingError = {})); + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol */ + + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +} + +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +/** + * Ensures at compile time that the given string tuple is exhaustive on a given union type, i.e. contains ALL possible values of the given UNION_TYPE. + */ +var exhaustiveStringTuple = function () { return function () { + var tuple = []; + for (var _i = 0; _i < arguments.length; _i++) { + tuple[_i] = arguments[_i]; + } + return tuple; +}; }; + +var STANDARD_CONTEXT_TYPES = exhaustiveStringTuple()('fdc3.action', 'fdc3.chart', 'fdc3.chat.initSettings', 'fdc3.chat.message', 'fdc3.chat.room', 'fdc3.chat.searchCriteria', 'fdc3.contact', 'fdc3.contactList', 'fdc3.country', 'fdc3.currency', 'fdc3.email', 'fdc3.instrument', 'fdc3.instrumentList', 'fdc3.interaction', 'fdc3.message', 'fdc3.organization', 'fdc3.portfolio', 'fdc3.position', 'fdc3.nothing', 'fdc3.timeRange', 'fdc3.transactionResult', 'fdc3.valuation'); +// used internally to check if a given intent/context is a standard one +var StandardContextsSet = new Set(STANDARD_CONTEXT_TYPES); + +var STANDARD_INTENTS = exhaustiveStringTuple()('CreateInteraction', 'SendChatMessage', 'StartCall', 'StartChat', 'StartEmail', 'ViewAnalysis', 'ViewChat', 'ViewChart', 'ViewContact', 'ViewHoldings', 'ViewInstrument', 'ViewInteractions', 'ViewMessages', 'ViewNews', 'ViewOrders', 'ViewProfile', 'ViewQuote', 'ViewResearch'); +// used internally to check if a given intent/context is a standard one +var StandardIntentsSet = new Set(STANDARD_INTENTS); + +var DEFAULT_TIMEOUT = 5000; +var UnavailableError = new Error('FDC3 DesktopAgent not available at `window.fdc3`.'); +var TimeoutError = new Error('Timed out waiting for `fdc3Ready` event.'); +var UnexpectedError = new Error('`fdc3Ready` event fired, but `window.fdc3` not set to DesktopAgent.'); +function rejectIfNoGlobal(f) { + return window.fdc3 ? f() : Promise.reject(UnavailableError); +} +/** + * Utility function that returns a promise that will resolve immeadiately + * if the desktop agent API is found at `window.fdc3`. If the API is found, + * the promise will resolve when the `fdc3Ready` event is received or if it + * is found at the end of the specified timeout. If the API is not found, it + * will reject with an error. + * + * ```javascript + * await fdc3Ready(); + * const intentListener = await addIntentListener("ViewChart", intentHandlerFn); + * ``` + * + * @param waitForMs The number of milliseconds to wait for the FDC3 API to be + * ready. Defaults to 5 seconds. + */ +var fdc3Ready = function (waitForMs) { + if (waitForMs === void 0) { waitForMs = DEFAULT_TIMEOUT; } + return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, new Promise(function (resolve, reject) { + // if the global is already available resolve immediately + if (window.fdc3) { + resolve(); + } + else { + // if its not available setup a timeout to return a rejected promise + var timeout_1 = setTimeout(function () { return (window.fdc3 ? resolve() : reject(TimeoutError)); }, waitForMs); + // listen for the fdc3Ready event + window.addEventListener('fdc3Ready', function () { + clearTimeout(timeout_1); + window.fdc3 ? resolve() : reject(UnexpectedError); + }, { once: true }); + } + })]; + }); + }); +}; +function isString(app) { + return !!app && typeof app === 'string'; +} +function open(app, context) { + if (isString(app)) { + return rejectIfNoGlobal(function () { return window.fdc3.open(app, context); }); + } + else { + return rejectIfNoGlobal(function () { return window.fdc3.open(app, context); }); + } +} +function findIntent(intent, context, resultType) { + return rejectIfNoGlobal(function () { return window.fdc3.findIntent(intent, context, resultType); }); +} +function findIntentsByContext(context, resultType) { + return rejectIfNoGlobal(function () { return window.fdc3.findIntentsByContext(context, resultType); }); +} +function broadcast(context) { + return rejectIfNoGlobal(function () { return window.fdc3.broadcast(context); }); +} +function raiseIntent(intent, context, app) { + if (isString(app)) { + return rejectIfNoGlobal(function () { return window.fdc3.raiseIntent(intent, context, app); }); + } + else { + return rejectIfNoGlobal(function () { return window.fdc3.raiseIntent(intent, context, app); }); + } +} +function raiseIntentForContext(context, app) { + if (isString(app)) { + return rejectIfNoGlobal(function () { return window.fdc3.raiseIntentForContext(context, app); }); + } + else { + return rejectIfNoGlobal(function () { return window.fdc3.raiseIntentForContext(context, app); }); + } +} +function addIntentListener(intent, handler) { + return rejectIfNoGlobal(function () { return window.fdc3.addIntentListener(intent, handler); }); +} +function addContextListener(contextTypeOrHandler, handler) { + //Handle (deprecated) function signature that allowed contextType argument to be omitted + if (typeof contextTypeOrHandler !== 'function') { + return rejectIfNoGlobal(function () { return window.fdc3.addContextListener(contextTypeOrHandler, handler); }); + } + else { + return rejectIfNoGlobal(function () { return window.fdc3.addContextListener(null, contextTypeOrHandler); }); + } +} +function getUserChannels() { + return rejectIfNoGlobal(function () { + //fallback to getSystemChannels for FDC3 <2.0 implementations + if (window.fdc3.getUserChannels) { + return window.fdc3.getUserChannels(); + } + else { + return window.fdc3.getSystemChannels(); + } + }); +} +function getSystemChannels() { + //fallforward to getUserChannels for FDC3 2.0+ implementations + return getUserChannels(); +} +function joinUserChannel(channelId) { + return rejectIfNoGlobal(function () { + //fallback to joinChannel for FDC3 <2.0 implementations + if (window.fdc3.joinUserChannel) { + return window.fdc3.joinUserChannel(channelId); + } + else { + return window.fdc3.joinChannel(channelId); + } + }); +} +function joinChannel(channelId) { + //fallforward to joinUserChannel for FDC3 2.0+ implementations + return joinUserChannel(channelId); +} +function getOrCreateChannel(channelId) { + return rejectIfNoGlobal(function () { return window.fdc3.getOrCreateChannel(channelId); }); +} +function getCurrentChannel() { + return rejectIfNoGlobal(function () { return window.fdc3.getCurrentChannel(); }); +} +function leaveCurrentChannel() { + return rejectIfNoGlobal(function () { return window.fdc3.leaveCurrentChannel(); }); +} +function createPrivateChannel() { + return rejectIfNoGlobal(function () { return window.fdc3.createPrivateChannel(); }); +} +function getInfo() { + return rejectIfNoGlobal(function () { return window.fdc3.getInfo(); }); +} +function getAppMetadata(app) { + return rejectIfNoGlobal(function () { return window.fdc3.getAppMetadata(app); }); +} +function findInstances(app) { + return rejectIfNoGlobal(function () { return window.fdc3.findInstances(app); }); +} +/** + * Check if the given context is a standard context type. + * @param contextType + */ +function isStandardContextType(contextType) { + return StandardContextsSet.has(contextType); +} +/** + * Check if the given intent is a standard intent. + * @param intent + */ +function isStandardIntent(intent) { + return StandardIntentsSet.has(intent); +} +/** + * Compare numeric semver version number strings (in the form `1.2.3`). + * + * Returns `-1` if the first argument is a lower version number than the second, + * `1` if the first argument is greater than the second, 0 if the arguments are + * equal and `null` if an error occurred during the comparison. + * + * @param a + * @param b + */ +var compareVersionNumbers = function (a, b) { + try { + var aVerArr = a.split('.').map(Number); + var bVerArr = b.split('.').map(Number); + for (var index = 0; index < Math.max(aVerArr.length, bVerArr.length); index++) { + /* If one version number has more digits and the other does not, and they are otherwise equal, + assume the longer is greater. E.g. 1.1.1 > 1.1 */ + if (index === aVerArr.length || aVerArr[index] < bVerArr[index]) { + return -1; + } + else if (index === bVerArr.length || aVerArr[index] > bVerArr[index]) { + return 1; + } + } + return 0; + } + catch (e) { + console.error('Failed to compare version strings', e); + return null; + } +}; +/** + * Check if the FDC3 version in an ImplementationMetadata object is greater than + * or equal to the supplied numeric semver version number string (in the form `1.2.3`). + * + * Returns a boolean or null if an error occurred while comparing the version numbers. + * + * @param metadata + * @param version + */ +var versionIsAtLeast = function (metadata, version) { + var comparison = compareVersionNumbers(metadata.fdc3Version, version); + return comparison === null ? null : comparison >= 0 ? true : false; +}; + +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright FINOS FDC3 contributors - see NOTICE file + */ +/** + * @deprecated Use {@link StandardContextType} instead + */ +var ContextTypes; +(function (ContextTypes) { + ContextTypes["Chart"] = "fdc3.chart"; + ContextTypes["ChatInitSettings"] = "fdc3.chat.initSettings"; + ContextTypes["ChatRoom"] = "fdc3.chat.room"; + ContextTypes["Contact"] = "fdc3.contact"; + ContextTypes["ContactList"] = "fdc3.contactList"; + ContextTypes["Country"] = "fdc3.country"; + ContextTypes["Currency"] = "fdc3.currency"; + ContextTypes["Email"] = "fdc3.email"; + ContextTypes["Instrument"] = "fdc3.instrument"; + ContextTypes["InstrumentList"] = "fdc3.instrumentList"; + ContextTypes["Interaction"] = "fdc3.interaction"; + ContextTypes["Nothing"] = "fdc3.nothing"; + ContextTypes["Organization"] = "fdc3.organization"; + ContextTypes["Portfolio"] = "fdc3.portfolio"; + ContextTypes["Position"] = "fdc3.position"; + ContextTypes["ChatSearchCriteria"] = "fdc3.chat.searchCriteria"; + ContextTypes["TimeRange"] = "fdc3.timeRange"; + ContextTypes["TransactionResult"] = "fdc3.transactionResult"; + ContextTypes["Valuation"] = "fdc3.valuation"; +})(ContextTypes || (ContextTypes = {})); + +// To parse this data: +// +// import { Convert, Action, Chart, ChatInitSettings, ChatMessage, ChatRoom, ChatSearchCriteria, Contact, ContactList, Context, Country, Currency, Email, Instrument, InstrumentList, Interaction, Message, Nothing, Order, OrderList, Organization, Portfolio, Position, Product, TimeRange, Trade, TradeList, TransactionResult, Valuation } from "./file"; +// +// const action = Convert.toAction(json); +// const chart = Convert.toChart(json); +// const chatInitSettings = Convert.toChatInitSettings(json); +// const chatMessage = Convert.toChatMessage(json); +// const chatRoom = Convert.toChatRoom(json); +// const chatSearchCriteria = Convert.toChatSearchCriteria(json); +// const contact = Convert.toContact(json); +// const contactList = Convert.toContactList(json); +// const context = Convert.toContext(json); +// const country = Convert.toCountry(json); +// const currency = Convert.toCurrency(json); +// const email = Convert.toEmail(json); +// const instrument = Convert.toInstrument(json); +// const instrumentList = Convert.toInstrumentList(json); +// const interaction = Convert.toInteraction(json); +// const message = Convert.toMessage(json); +// const nothing = Convert.toNothing(json); +// const order = Convert.toOrder(json); +// const orderList = Convert.toOrderList(json); +// const organization = Convert.toOrganization(json); +// const portfolio = Convert.toPortfolio(json); +// const position = Convert.toPosition(json); +// const product = Convert.toProduct(json); +// const timeRange = Convert.toTimeRange(json); +// const trade = Convert.toTrade(json); +// const tradeList = Convert.toTradeList(json); +// const transactionResult = Convert.toTransactionResult(json); +// const valuation = Convert.toValuation(json); +// +// These functions will throw an error if the JSON doesn't +// match the expected interface, even if the JSON is valid. +/** + * Free text to be used for a keyword search + * + * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or + * `'Meeting'` although other string values are permitted. + */ +// Converts JSON strings to/from your types +// and asserts the results of JSON.parse at runtime +var Convert = /** @class */ (function () { + function Convert() { + } + Convert.toAction = function (json) { + return cast(JSON.parse(json), r("Action")); + }; + Convert.actionToJson = function (value) { + return JSON.stringify(uncast(value, r("Action")), null, 2); + }; + Convert.toChart = function (json) { + return cast(JSON.parse(json), r("Chart")); + }; + Convert.chartToJson = function (value) { + return JSON.stringify(uncast(value, r("Chart")), null, 2); + }; + Convert.toChatInitSettings = function (json) { + return cast(JSON.parse(json), r("ChatInitSettings")); + }; + Convert.chatInitSettingsToJson = function (value) { + return JSON.stringify(uncast(value, r("ChatInitSettings")), null, 2); + }; + Convert.toChatMessage = function (json) { + return cast(JSON.parse(json), r("ChatMessage")); + }; + Convert.chatMessageToJson = function (value) { + return JSON.stringify(uncast(value, r("ChatMessage")), null, 2); + }; + Convert.toChatRoom = function (json) { + return cast(JSON.parse(json), r("ChatRoom")); + }; + Convert.chatRoomToJson = function (value) { + return JSON.stringify(uncast(value, r("ChatRoom")), null, 2); + }; + Convert.toChatSearchCriteria = function (json) { + return cast(JSON.parse(json), r("ChatSearchCriteria")); + }; + Convert.chatSearchCriteriaToJson = function (value) { + return JSON.stringify(uncast(value, r("ChatSearchCriteria")), null, 2); + }; + Convert.toContact = function (json) { + return cast(JSON.parse(json), r("Contact")); + }; + Convert.contactToJson = function (value) { + return JSON.stringify(uncast(value, r("Contact")), null, 2); + }; + Convert.toContactList = function (json) { + return cast(JSON.parse(json), r("ContactList")); + }; + Convert.contactListToJson = function (value) { + return JSON.stringify(uncast(value, r("ContactList")), null, 2); + }; + Convert.toContext = function (json) { + return cast(JSON.parse(json), r("Context")); + }; + Convert.contextToJson = function (value) { + return JSON.stringify(uncast(value, r("Context")), null, 2); + }; + Convert.toCountry = function (json) { + return cast(JSON.parse(json), r("Country")); + }; + Convert.countryToJson = function (value) { + return JSON.stringify(uncast(value, r("Country")), null, 2); + }; + Convert.toCurrency = function (json) { + return cast(JSON.parse(json), r("Currency")); + }; + Convert.currencyToJson = function (value) { + return JSON.stringify(uncast(value, r("Currency")), null, 2); + }; + Convert.toEmail = function (json) { + return cast(JSON.parse(json), r("Email")); + }; + Convert.emailToJson = function (value) { + return JSON.stringify(uncast(value, r("Email")), null, 2); + }; + Convert.toInstrument = function (json) { + return cast(JSON.parse(json), r("Instrument")); + }; + Convert.instrumentToJson = function (value) { + return JSON.stringify(uncast(value, r("Instrument")), null, 2); + }; + Convert.toInstrumentList = function (json) { + return cast(JSON.parse(json), r("InstrumentList")); + }; + Convert.instrumentListToJson = function (value) { + return JSON.stringify(uncast(value, r("InstrumentList")), null, 2); + }; + Convert.toInteraction = function (json) { + return cast(JSON.parse(json), r("Interaction")); + }; + Convert.interactionToJson = function (value) { + return JSON.stringify(uncast(value, r("Interaction")), null, 2); + }; + Convert.toMessage = function (json) { + return cast(JSON.parse(json), r("Message")); + }; + Convert.messageToJson = function (value) { + return JSON.stringify(uncast(value, r("Message")), null, 2); + }; + Convert.toNothing = function (json) { + return cast(JSON.parse(json), r("Nothing")); + }; + Convert.nothingToJson = function (value) { + return JSON.stringify(uncast(value, r("Nothing")), null, 2); + }; + Convert.toOrder = function (json) { + return cast(JSON.parse(json), r("Order")); + }; + Convert.orderToJson = function (value) { + return JSON.stringify(uncast(value, r("Order")), null, 2); + }; + Convert.toOrderList = function (json) { + return cast(JSON.parse(json), r("OrderList")); + }; + Convert.orderListToJson = function (value) { + return JSON.stringify(uncast(value, r("OrderList")), null, 2); + }; + Convert.toOrganization = function (json) { + return cast(JSON.parse(json), r("Organization")); + }; + Convert.organizationToJson = function (value) { + return JSON.stringify(uncast(value, r("Organization")), null, 2); + }; + Convert.toPortfolio = function (json) { + return cast(JSON.parse(json), r("Portfolio")); + }; + Convert.portfolioToJson = function (value) { + return JSON.stringify(uncast(value, r("Portfolio")), null, 2); + }; + Convert.toPosition = function (json) { + return cast(JSON.parse(json), r("Position")); + }; + Convert.positionToJson = function (value) { + return JSON.stringify(uncast(value, r("Position")), null, 2); + }; + Convert.toProduct = function (json) { + return cast(JSON.parse(json), r("Product")); + }; + Convert.productToJson = function (value) { + return JSON.stringify(uncast(value, r("Product")), null, 2); + }; + Convert.toTimeRange = function (json) { + return cast(JSON.parse(json), r("TimeRange")); + }; + Convert.timeRangeToJson = function (value) { + return JSON.stringify(uncast(value, r("TimeRange")), null, 2); + }; + Convert.toTrade = function (json) { + return cast(JSON.parse(json), r("Trade")); + }; + Convert.tradeToJson = function (value) { + return JSON.stringify(uncast(value, r("Trade")), null, 2); + }; + Convert.toTradeList = function (json) { + return cast(JSON.parse(json), r("TradeList")); + }; + Convert.tradeListToJson = function (value) { + return JSON.stringify(uncast(value, r("TradeList")), null, 2); + }; + Convert.toTransactionResult = function (json) { + return cast(JSON.parse(json), r("TransactionResult")); + }; + Convert.transactionResultToJson = function (value) { + return JSON.stringify(uncast(value, r("TransactionResult")), null, 2); + }; + Convert.toValuation = function (json) { + return cast(JSON.parse(json), r("Valuation")); + }; + Convert.valuationToJson = function (value) { + return JSON.stringify(uncast(value, r("Valuation")), null, 2); + }; + return Convert; +}()); +function invalidValue(typ, val, key, parent) { + if (parent === void 0) { parent = ''; } + var prettyTyp = prettyTypeName(typ); + var parentText = parent ? " on ".concat(parent) : ''; + var keyText = key ? " for key \"".concat(key, "\"") : ''; + throw Error("Invalid value".concat(keyText).concat(parentText, ". Expected ").concat(prettyTyp, " but got ").concat(JSON.stringify(val))); +} +function prettyTypeName(typ) { + if (Array.isArray(typ)) { + if (typ.length === 2 && typ[0] === undefined) { + return "an optional ".concat(prettyTypeName(typ[1])); + } + else { + return "one of [".concat(typ.map(function (a) { return prettyTypeName(a); }).join(", "), "]"); + } + } + else if (typeof typ === "object" && typ.literal !== undefined) { + return typ.literal; + } + else { + return typeof typ; + } +} +function jsonToJSProps(typ) { + if (typ.jsonToJS === undefined) { + var map_1 = {}; + typ.props.forEach(function (p) { return map_1[p.json] = { key: p.js, typ: p.typ }; }); + typ.jsonToJS = map_1; + } + return typ.jsonToJS; +} +function jsToJSONProps(typ) { + if (typ.jsToJSON === undefined) { + var map_2 = {}; + typ.props.forEach(function (p) { return map_2[p.js] = { key: p.json, typ: p.typ }; }); + typ.jsToJSON = map_2; + } + return typ.jsToJSON; +} +function transform(val, typ, getProps, key, parent) { + if (key === void 0) { key = ''; } + if (parent === void 0) { parent = ''; } + function transformPrimitive(typ, val) { + if (typeof typ === typeof val) + return val; + return invalidValue(typ, val, key, parent); + } + function transformUnion(typs, val) { + // val must validate against one typ in typs + var l = typs.length; + for (var i = 0; i < l; i++) { + var typ_1 = typs[i]; + try { + return transform(val, typ_1, getProps); + } + catch (_) { } + } + return invalidValue(typs, val, key, parent); + } + function transformEnum(cases, val) { + if (cases.indexOf(val) !== -1) + return val; + return invalidValue(cases.map(function (a) { return l(a); }), val, key, parent); + } + function transformArray(typ, val) { + // val must be an array with no invalid elements + if (!Array.isArray(val)) + return invalidValue(l("array"), val, key, parent); + return val.map(function (el) { return transform(el, typ, getProps); }); + } + function transformDate(val) { + if (val === null) { + return null; + } + var d = new Date(val); + if (isNaN(d.valueOf())) { + return invalidValue(l("Date"), val, key, parent); + } + return d; + } + function transformObject(props, additional, val) { + if (val === null || typeof val !== "object" || Array.isArray(val)) { + return invalidValue(l(ref || "object"), val, key, parent); + } + var result = {}; + Object.getOwnPropertyNames(props).forEach(function (key) { + var prop = props[key]; + var v = Object.prototype.hasOwnProperty.call(val, key) ? val[key] : undefined; + result[prop.key] = transform(v, prop.typ, getProps, key, ref); + }); + Object.getOwnPropertyNames(val).forEach(function (key) { + if (!Object.prototype.hasOwnProperty.call(props, key)) { + result[key] = transform(val[key], additional, getProps, key, ref); + } + }); + return result; + } + if (typ === "any") + return val; + if (typ === null) { + if (val === null) + return val; + return invalidValue(typ, val, key, parent); + } + if (typ === false) + return invalidValue(typ, val, key, parent); + var ref = undefined; + while (typeof typ === "object" && typ.ref !== undefined) { + ref = typ.ref; + typ = typeMap[typ.ref]; + } + if (Array.isArray(typ)) + return transformEnum(typ, val); + if (typeof typ === "object") { + return typ.hasOwnProperty("unionMembers") ? transformUnion(typ.unionMembers, val) + : typ.hasOwnProperty("arrayItems") ? transformArray(typ.arrayItems, val) + : typ.hasOwnProperty("props") ? transformObject(getProps(typ), typ.additional, val) + : invalidValue(typ, val, key, parent); + } + // Numbers can be parsed by Date but shouldn't be. + if (typ === Date && typeof val !== "number") + return transformDate(val); + return transformPrimitive(typ, val); +} +function cast(val, typ) { + return transform(val, typ, jsonToJSProps); +} +function uncast(val, typ) { + return transform(val, typ, jsToJSONProps); +} +function l(typ) { + return { literal: typ }; +} +function a(typ) { + return { arrayItems: typ }; +} +function u() { + var typs = []; + for (var _i = 0; _i < arguments.length; _i++) { + typs[_i] = arguments[_i]; + } + return { unionMembers: typs }; +} +function o(props, additional) { + return { props: props, additional: additional }; +} +function m(additional) { + return { props: [], additional: additional }; +} +function r(name) { + return { ref: name }; +} +var typeMap = { + "Action": o([ + { json: "app", js: "app", typ: u(undefined, r("ActionTargetApp")) }, + { json: "context", js: "context", typ: r("ContextElement") }, + { json: "intent", js: "intent", typ: u(undefined, "") }, + { json: "title", js: "title", typ: "" }, + { json: "type", js: "type", typ: r("ActionType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ActionTargetApp": o([ + { json: "appId", js: "appId", typ: "" }, + { json: "desktopAgent", js: "desktopAgent", typ: u(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u(undefined, "") }, + ], "any"), + "ContextElement": o([ + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: "" }, + ], "any"), + "Chart": o([ + { json: "instruments", js: "instruments", typ: a(r("InstrumentElement")) }, + { json: "otherConfig", js: "otherConfig", typ: u(undefined, a(r("ContextElement"))) }, + { json: "range", js: "range", typ: u(undefined, r("TimeRangeObject")) }, + { json: "style", js: "style", typ: u(undefined, r("ChartStyle")) }, + { json: "type", js: "type", typ: r("ChartType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "InstrumentElement": o([ + { json: "id", js: "id", typ: r("PurpleInstrumentIdentifiers") }, + { json: "market", js: "market", typ: u(undefined, r("OrganizationMarket")) }, + { json: "type", js: "type", typ: r("PurpleInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "PurpleInstrumentIdentifiers": o([ + { json: "BBG", js: "BBG", typ: u(undefined, "") }, + { json: "CUSIP", js: "CUSIP", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + { json: "FIGI", js: "FIGI", typ: u(undefined, "") }, + { json: "ISIN", js: "ISIN", typ: u(undefined, "") }, + { json: "PERMID", js: "PERMID", typ: u(undefined, "") }, + { json: "RIC", js: "RIC", typ: u(undefined, "") }, + { json: "SEDOL", js: "SEDOL", typ: u(undefined, "") }, + { json: "ticker", js: "ticker", typ: u(undefined, "") }, + ], "any"), + "OrganizationMarket": o([ + { json: "BBG", js: "BBG", typ: u(undefined, "") }, + { json: "COUNTRY_ISOALPHA2", js: "COUNTRY_ISOALPHA2", typ: u(undefined, "") }, + { json: "MIC", js: "MIC", typ: u(undefined, "") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "TimeRangeObject": o([ + { json: "endTime", js: "endTime", typ: u(undefined, Date) }, + { json: "startTime", js: "startTime", typ: u(undefined, Date) }, + { json: "type", js: "type", typ: r("TimeRangeType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ChatInitSettings": o([ + { json: "chatName", js: "chatName", typ: u(undefined, "") }, + { json: "members", js: "members", typ: u(undefined, r("ContactListObject")) }, + { json: "message", js: "message", typ: u(undefined, u(r("MessageObject"), "")) }, + { json: "options", js: "options", typ: u(undefined, r("ChatOptions")) }, + { json: "type", js: "type", typ: r("ChatInitSettingsType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ContactListObject": o([ + { json: "contacts", js: "contacts", typ: a(r("ContactElement")) }, + { json: "type", js: "type", typ: r("ContactListType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ContactElement": o([ + { json: "id", js: "id", typ: r("PurpleContactIdentifiers") }, + { json: "type", js: "type", typ: r("FluffyInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "PurpleContactIdentifiers": o([ + { json: "email", js: "email", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + ], "any"), + "MessageObject": o([ + { json: "entities", js: "entities", typ: u(undefined, m(r("PurpleAction"))) }, + { json: "text", js: "text", typ: u(undefined, r("PurpleMessageText")) }, + { json: "type", js: "type", typ: r("MessageType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "PurpleAction": o([ + { json: "app", js: "app", typ: u(undefined, r("ActionTargetApp")) }, + { json: "context", js: "context", typ: u(undefined, r("ContextElement")) }, + { json: "intent", js: "intent", typ: u(undefined, "") }, + { json: "title", js: "title", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("EntityType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "data", js: "data", typ: u(undefined, r("PurpleData")) }, + ], "any"), + "PurpleData": o([ + { json: "dataUri", js: "dataUri", typ: "" }, + { json: "name", js: "name", typ: "" }, + ], "any"), + "PurpleMessageText": o([ + { json: "text/markdown", js: "text/markdown", typ: u(undefined, "") }, + { json: "text/plain", js: "text/plain", typ: u(undefined, "") }, + ], "any"), + "ChatOptions": o([ + { json: "allowAddUser", js: "allowAddUser", typ: u(undefined, true) }, + { json: "allowHistoryBrowsing", js: "allowHistoryBrowsing", typ: u(undefined, true) }, + { json: "allowMessageCopy", js: "allowMessageCopy", typ: u(undefined, true) }, + { json: "groupRecipients", js: "groupRecipients", typ: u(undefined, true) }, + { json: "isPublic", js: "isPublic", typ: u(undefined, true) }, + ], "any"), + "ChatMessage": o([ + { json: "chatRoom", js: "chatRoom", typ: r("ChatRoomObject") }, + { json: "message", js: "message", typ: r("MessageObject") }, + { json: "type", js: "type", typ: r("ChatMessageType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ChatRoomObject": o([ + { json: "id", js: "id", typ: m("any") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "providerName", js: "providerName", typ: "" }, + { json: "type", js: "type", typ: r("ChatRoomType") }, + { json: "url", js: "url", typ: u(undefined, "") }, + ], "any"), + "ChatRoom": o([ + { json: "id", js: "id", typ: m("any") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "providerName", js: "providerName", typ: "" }, + { json: "type", js: "type", typ: r("ChatRoomType") }, + { json: "url", js: "url", typ: u(undefined, "") }, + ], "any"), + "ChatSearchCriteria": o([ + { json: "criteria", js: "criteria", typ: a(u(r("OrganizationObject"), "")) }, + { json: "type", js: "type", typ: r("ChatSearchCriteriaType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "OrganizationObject": o([ + { json: "id", js: "id", typ: r("Identifiers") }, + { json: "market", js: "market", typ: u(undefined, r("OrganizationMarket")) }, + { json: "type", js: "type", typ: r("TentacledInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Identifiers": o([ + { json: "BBG", js: "BBG", typ: u(undefined, "") }, + { json: "CUSIP", js: "CUSIP", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + { json: "FIGI", js: "FIGI", typ: u(undefined, "") }, + { json: "ISIN", js: "ISIN", typ: u(undefined, "") }, + { json: "PERMID", js: "PERMID", typ: u(undefined, "") }, + { json: "RIC", js: "RIC", typ: u(undefined, "") }, + { json: "SEDOL", js: "SEDOL", typ: u(undefined, "") }, + { json: "ticker", js: "ticker", typ: u(undefined, "") }, + { json: "LEI", js: "LEI", typ: u(undefined, "") }, + { json: "email", js: "email", typ: u(undefined, "") }, + ], "any"), + "Contact": o([ + { json: "id", js: "id", typ: r("FluffyContactIdentifiers") }, + { json: "type", js: "type", typ: r("FluffyInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "FluffyContactIdentifiers": o([ + { json: "email", js: "email", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + ], "any"), + "ContactList": o([ + { json: "contacts", js: "contacts", typ: a(r("ContactElement")) }, + { json: "type", js: "type", typ: r("ContactListType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Context": o([ + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: "" }, + ], "any"), + "Country": o([ + { json: "id", js: "id", typ: r("CountryID") }, + { json: "type", js: "type", typ: r("CountryType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "CountryID": o([ + { json: "COUNTRY_ISOALPHA2", js: "COUNTRY_ISOALPHA2", typ: u(undefined, "") }, + { json: "COUNTRY_ISOALPHA3", js: "COUNTRY_ISOALPHA3", typ: u(undefined, "") }, + { json: "ISOALPHA2", js: "ISOALPHA2", typ: u(undefined, "") }, + { json: "ISOALPHA3", js: "ISOALPHA3", typ: u(undefined, "") }, + ], "any"), + "Currency": o([ + { json: "id", js: "id", typ: r("CurrencyID") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("CurrencyType") }, + ], "any"), + "CurrencyID": o([ + { json: "CURRENCY_ISOCODE", js: "CURRENCY_ISOCODE", typ: u(undefined, "") }, + ], "any"), + "Email": o([ + { json: "recipients", js: "recipients", typ: r("EmailRecipients") }, + { json: "subject", js: "subject", typ: u(undefined, "") }, + { json: "textBody", js: "textBody", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("EmailType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "EmailRecipients": o([ + { json: "id", js: "id", typ: u(undefined, r("EmailRecipientsID")) }, + { json: "type", js: "type", typ: r("EmailRecipientsType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "contacts", js: "contacts", typ: u(undefined, a(r("ContactElement"))) }, + ], "any"), + "EmailRecipientsID": o([ + { json: "email", js: "email", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + ], "any"), + "Instrument": o([ + { json: "id", js: "id", typ: r("FluffyInstrumentIdentifiers") }, + { json: "market", js: "market", typ: u(undefined, r("PurpleMarket")) }, + { json: "type", js: "type", typ: r("PurpleInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "FluffyInstrumentIdentifiers": o([ + { json: "BBG", js: "BBG", typ: u(undefined, "") }, + { json: "CUSIP", js: "CUSIP", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + { json: "FIGI", js: "FIGI", typ: u(undefined, "") }, + { json: "ISIN", js: "ISIN", typ: u(undefined, "") }, + { json: "PERMID", js: "PERMID", typ: u(undefined, "") }, + { json: "RIC", js: "RIC", typ: u(undefined, "") }, + { json: "SEDOL", js: "SEDOL", typ: u(undefined, "") }, + { json: "ticker", js: "ticker", typ: u(undefined, "") }, + ], "any"), + "PurpleMarket": o([ + { json: "BBG", js: "BBG", typ: u(undefined, "") }, + { json: "COUNTRY_ISOALPHA2", js: "COUNTRY_ISOALPHA2", typ: u(undefined, "") }, + { json: "MIC", js: "MIC", typ: u(undefined, "") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "InstrumentList": o([ + { json: "instruments", js: "instruments", typ: a(r("InstrumentElement")) }, + { json: "type", js: "type", typ: r("InstrumentListType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Interaction": o([ + { json: "description", js: "description", typ: "" }, + { json: "id", js: "id", typ: u(undefined, r("InteractionID")) }, + { json: "initiator", js: "initiator", typ: u(undefined, r("ContactElement")) }, + { json: "interactionType", js: "interactionType", typ: "" }, + { json: "origin", js: "origin", typ: u(undefined, "") }, + { json: "participants", js: "participants", typ: r("ContactListObject") }, + { json: "timeRange", js: "timeRange", typ: r("TimeRangeObject") }, + { json: "type", js: "type", typ: r("InteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "InteractionID": o([ + { json: "SALESFORCE", js: "SALESFORCE", typ: u(undefined, "") }, + { json: "SINGLETRACK", js: "SINGLETRACK", typ: u(undefined, "") }, + { json: "URI", js: "URI", typ: u(undefined, "") }, + ], "any"), + "Message": o([ + { json: "entities", js: "entities", typ: u(undefined, m(r("FluffyAction"))) }, + { json: "text", js: "text", typ: u(undefined, r("FluffyMessageText")) }, + { json: "type", js: "type", typ: r("MessageType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "FluffyAction": o([ + { json: "app", js: "app", typ: u(undefined, r("ActionTargetApp")) }, + { json: "context", js: "context", typ: u(undefined, r("ContextElement")) }, + { json: "intent", js: "intent", typ: u(undefined, "") }, + { json: "title", js: "title", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("EntityType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "data", js: "data", typ: u(undefined, r("FluffyData")) }, + ], "any"), + "FluffyData": o([ + { json: "dataUri", js: "dataUri", typ: "" }, + { json: "name", js: "name", typ: "" }, + ], "any"), + "FluffyMessageText": o([ + { json: "text/markdown", js: "text/markdown", typ: u(undefined, "") }, + { json: "text/plain", js: "text/plain", typ: u(undefined, "") }, + ], "any"), + "Nothing": o([ + { json: "type", js: "type", typ: r("NothingType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Order": o([ + { json: "details", js: "details", typ: u(undefined, r("PurpleOrderDetails")) }, + { json: "id", js: "id", typ: m("") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("OrderType") }, + ], "any"), + "PurpleOrderDetails": o([ + { json: "product", js: "product", typ: u(undefined, r("ProductObject")) }, + ], "any"), + "ProductObject": o([ + { json: "id", js: "id", typ: m("") }, + { json: "instrument", js: "instrument", typ: u(undefined, r("InstrumentElement")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("ProductType") }, + ], "any"), + "OrderList": o([ + { json: "orders", js: "orders", typ: a(r("OrderElement")) }, + { json: "type", js: "type", typ: r("OrderListType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "OrderElement": o([ + { json: "details", js: "details", typ: u(undefined, r("FluffyOrderDetails")) }, + { json: "id", js: "id", typ: m("") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("OrderType") }, + ], "any"), + "FluffyOrderDetails": o([ + { json: "product", js: "product", typ: u(undefined, r("ProductObject")) }, + ], "any"), + "Organization": o([ + { json: "id", js: "id", typ: r("OrganizationIdentifiers") }, + { json: "type", js: "type", typ: r("StickyInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "OrganizationIdentifiers": o([ + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + { json: "LEI", js: "LEI", typ: u(undefined, "") }, + { json: "PERMID", js: "PERMID", typ: u(undefined, "") }, + ], "any"), + "Portfolio": o([ + { json: "positions", js: "positions", typ: a(r("PositionElement")) }, + { json: "type", js: "type", typ: r("PortfolioType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "PositionElement": o([ + { json: "holding", js: "holding", typ: 3.14 }, + { json: "instrument", js: "instrument", typ: r("InstrumentElement") }, + { json: "type", js: "type", typ: r("PositionType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Position": o([ + { json: "holding", js: "holding", typ: 3.14 }, + { json: "instrument", js: "instrument", typ: r("InstrumentElement") }, + { json: "type", js: "type", typ: r("PositionType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Product": o([ + { json: "id", js: "id", typ: m("") }, + { json: "instrument", js: "instrument", typ: u(undefined, r("InstrumentElement")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("ProductType") }, + ], "any"), + "TimeRange": o([ + { json: "endTime", js: "endTime", typ: u(undefined, Date) }, + { json: "startTime", js: "startTime", typ: u(undefined, Date) }, + { json: "type", js: "type", typ: r("TimeRangeType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Trade": o([ + { json: "id", js: "id", typ: m("") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "product", js: "product", typ: r("ProductObject") }, + { json: "type", js: "type", typ: r("TradeType") }, + ], "any"), + "TradeList": o([ + { json: "trades", js: "trades", typ: a(r("TradeElement")) }, + { json: "type", js: "type", typ: r("TradeListType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "TradeElement": o([ + { json: "id", js: "id", typ: m("") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "product", js: "product", typ: r("ProductObject") }, + { json: "type", js: "type", typ: r("TradeType") }, + ], "any"), + "TransactionResult": o([ + { json: "context", js: "context", typ: u(undefined, r("ContextElement")) }, + { json: "message", js: "message", typ: u(undefined, "") }, + { json: "status", js: "status", typ: r("TransactionStatus") }, + { json: "type", js: "type", typ: r("TransactionResultType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Valuation": o([ + { json: "CURRENCY_ISOCODE", js: "CURRENCY_ISOCODE", typ: "" }, + { json: "expiryTime", js: "expiryTime", typ: u(undefined, Date) }, + { json: "price", js: "price", typ: u(undefined, 3.14) }, + { json: "type", js: "type", typ: r("ValuationType") }, + { json: "valuationTime", js: "valuationTime", typ: u(undefined, Date) }, + { json: "value", js: "value", typ: 3.14 }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ActionType": [ + "fdc3.action", + ], + "PurpleInteractionType": [ + "fdc3.instrument", + ], + "TimeRangeType": [ + "fdc3.timeRange", + ], + "ChartStyle": [ + "bar", + "candle", + "custom", + "heatmap", + "histogram", + "line", + "mountain", + "pie", + "scatter", + "stacked-bar", + ], + "ChartType": [ + "fdc3.chart", + ], + "FluffyInteractionType": [ + "fdc3.contact", + ], + "ContactListType": [ + "fdc3.contactList", + ], + "EntityType": [ + "fdc3.action", + "fdc3.entity.fileAttachment", + ], + "MessageType": [ + "fdc3.message", + ], + "ChatInitSettingsType": [ + "fdc3.chat.initSettings", + ], + "ChatRoomType": [ + "fdc3.chat.room", + ], + "ChatMessageType": [ + "fdc3.chat.message", + ], + "TentacledInteractionType": [ + "fdc3.contact", + "fdc3.instrument", + "fdc3.organization", + ], + "ChatSearchCriteriaType": [ + "fdc3.chat.searchCriteria", + ], + "CountryType": [ + "fdc3.country", + ], + "CurrencyType": [ + "fdc3.currency", + ], + "EmailRecipientsType": [ + "fdc3.contact", + "fdc3.contactList", + ], + "EmailType": [ + "fdc3.email", + ], + "InstrumentListType": [ + "fdc3.instrumentList", + ], + "InteractionType": [ + "fdc3.interaction", + ], + "NothingType": [ + "fdc3.nothing", + ], + "ProductType": [ + "fdc3.product", + ], + "OrderType": [ + "fdc3.order", + ], + "OrderListType": [ + "fdc3.orderList", + ], + "StickyInteractionType": [ + "fdc3.organization", + ], + "PositionType": [ + "fdc3.position", + ], + "PortfolioType": [ + "fdc3.portfolio", + ], + "TradeType": [ + "fdc3.trade", + ], + "TradeListType": [ + "fdc3.tradeList", + ], + "TransactionStatus": [ + "Created", + "Deleted", + "Failed", + "Updated", + ], + "TransactionResultType": [ + "fdc3.transactionResult", + ], + "ValuationType": [ + "fdc3.valuation", + ] +}; + +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright FINOS FDC3 contributors - see NOTICE file + */ +/** + * @deprecated Use {@link StandardIntent} instead + */ +var Intents; +(function (Intents) { + Intents["CreateInteraction"] = "CreateInteraction"; + Intents["SendChatMessage"] = "SendChatMessage"; + Intents["StartCall"] = "StartCall"; + Intents["StartChat"] = "StartChat"; + Intents["StartEmail"] = "StartEmail"; + Intents["ViewAnalysis"] = "ViewAnalysis"; + Intents["ViewChat"] = "ViewChat"; + Intents["ViewChart"] = "ViewChart"; + Intents["ViewContact"] = "ViewContact"; + Intents["ViewHoldings"] = "ViewHoldings"; + Intents["ViewInstrument"] = "ViewInstrument"; + Intents["ViewInteractions"] = "ViewInteractions"; + Intents["ViewMessages"] = "ViewMessages"; + Intents["ViewNews"] = "ViewNews"; + Intents["ViewOrders"] = "ViewOrders"; + Intents["ViewProfile"] = "ViewProfile"; + Intents["ViewQuote"] = "ViewQuote"; + Intents["ViewResearch"] = "ViewResearch"; +})(Intents || (Intents = {})); + + +//# sourceMappingURL=fdc3.esm.js.map + + +/***/ }), + +/***/ "../../node_modules/@openfin/excel/openfin.excel.mjs": +/*!***********************************************************!*\ + !*** ../../node_modules/@openfin/excel/openfin.excel.mjs ***! + \***********************************************************/ +/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ AdapterError: () => (/* binding */ Ne), +/* harmony export */ ApiError: () => (/* binding */ Se), +/* harmony export */ EventError: () => (/* binding */ De), +/* harmony export */ ExcelCellBorderLineStyle: () => (/* binding */ Ue), +/* harmony export */ ExcelCellHorizontalAlignment: () => (/* binding */ Fe), +/* harmony export */ ExcelCellPattern: () => (/* binding */ Pe), +/* harmony export */ ExcelCellVerticalAlignment: () => (/* binding */ xe), +/* harmony export */ ExcelFilterOperator: () => (/* binding */ Le), +/* harmony export */ InitializationError: () => (/* binding */ Be), +/* harmony export */ InvalidCellRangeAddressError: () => (/* binding */ je), +/* harmony export */ ParameterError: () => (/* binding */ Re), +/* harmony export */ disableLogging: () => (/* binding */ Oe), +/* harmony export */ enableLogging: () => (/* binding */ Ve), +/* harmony export */ getExcelApplication: () => (/* binding */ ze) +/* harmony export */ }); +var e,t,r={d:(e,t)=>{for(var a in t)r.o(t,a)&&!r.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},a={};r.d(a,{dq:()=>AdapterError,MS:()=>ApiError,xQ:()=>EventError,sO:()=>We,Zu:()=>fe,I3:()=>$e,$U:()=>Ge,i0:()=>Ie,cX:()=>InitializationError,gH:()=>InvalidCellRangeAddressError,_W:()=>ParameterError,U$:()=>i,U7:()=>l,rd:()=>be});class ApiError extends Error{constructor(e="An unexpected error has occurred",t){var r;super(e),t&&(this.innerError=t&&t),this.stack=null===(r=this.stack)||void 0===r?void 0:r.replace(/^(\w*Error)/,`${this.constructor.name}`)}}class AdapterError extends ApiError{constructor(e="Failed to execute adapter function",t){super(e,t)}}class EventError extends ApiError{constructor(e="Failed to raise event",t){super(e,t)}}class InitializationError extends ApiError{constructor(e="Failed to initialize adapter",t){super(e,t)}}class InvalidCellRangeAddressError extends ApiError{constructor(e="The cell range address is not valid",t){super(e,t)}}class ParameterError extends ApiError{constructor(e="Invalid parameter value",t){super(e,t)}}!function(e){e.ActivateWorkbook="ActivateWorkbook",e.ActivateWorksheet="ActivateWorksheet",e.AddWorksheet="AddWorksheet",e.CalculateWorkbook="CalculateWorkbook",e.CalculateWorksheet="CalculateWorksheet",e.ClearAllCells="ClearAllCells",e.ClearAllCellValues="ClearAllCellValues",e.ClearAllCellFormatting="ClearAllCellFormatting",e.ClearCellValues="ClearCellValues",e.ClearCellFormatting="ClearCellFormatting",e.ClearCells="ClearCells",e.CloseWorkbook="CloseWorkbook",e.CreateWorkbook="CreateWorkbook",e.DeleteWorksheet="DeleteWorksheet",e.DeregisterEvent="DeregisterEvent",e.EventFired="EventFired",e.FilterCells="FilterCells",e.GetActiveWorksheet="GetActiveWorksheet",e.GetCalculationMode="GetCalculationMode",e.GetCellNames="GetCellNames",e.GetCells="GetCells",e.GetRangeAddress="GetRangeAddress",e.GetWorkbookById="GetWorkbookById",e.GetWorkbookFilePath="GetWorkbookFilePath",e.GetWorkbookName="GetWorkbookName",e.GetWorkbooks="GetWorkbooks",e.GetWorkbookWindowBounds="GetWorkbookWindowBounds",e.GetWorksheetById="GetWorksheetById",e.GetWorksheetByName="GetWorksheetByName",e.GetWorksheetName="GetWorksheetName",e.GetWorksheets="GetWorksheets",e.LogMessage="LogMessage",e.OpenWorkbook="OpenWorkbook",e.ProtectWorksheet="ProtectWorksheet",e.QuitApplication="QuitApplication",e.RegisterEvent="RegisterEvent",e.SaveWorkbook="SaveWorkbook",e.SaveWorkbookAs="SaveWorkbookAs",e.SetCellValues="SetCellValues",e.SetCellFormatting="SetCellFormatting",e.SetCellName="SetCellName",e.SetWorkbookWindowBounds="SetWorkbookWindowBounds",e.SetWorksheetName="SetWorksheetName"}(e||(e={})),function(e){e.Activate="Activate",e.ActivateWorksheet="ActivateWorksheet",e.AddWorksheet="AddWorksheet",e.Change="Change",e.Close="Close",e.Deactivate="Deactivate",e.DeleteWorksheet="DeleteWorksheet"}(t||(t={}));const o="1.5.0";let n=!1;const s="[@openfin/excel]",i=()=>{n=!1},l=()=>{n=!0,d(`v${o}`)},c=(e,t)=>{n&&(e.innerError?console.error(t?`${s} ${t}`:s,e,"\n\n(inner)",e.innerError):console.error(t?`${s} ${t}`:s,e))},d=(...e)=>{n&&console.log(s,...e)},h=(...e)=>{n&&console.warn(s,...e)};"undefined"==typeof fin&&Object.assign(window,{fin:{}}),Object.assign(fin,{Integrations:{Excel:{enableLogging:l,disableLogging:i}}});const w=new Map,p=async(r,a,o,n,s)=>{if(!a||!a.eventTarget||!a.objectId){const e=new EventError("Event registration missing required values");throw c(e),e}const i=Object.keys(t).find((e=>e.toLowerCase()===o.toLowerCase()));if(!i){const e=new EventError(`Unsupported event name: ${o}`);throw c(e),e}const l=Object.assign({eventName:t[i]},a);d("Registering event",l);try{const t=await r.dispatch(e.RegisterEvent,l),a={handler:s,listener:n};w.set(t,a)}catch(e){throw new AdapterError(void 0,e)}},k=(e,t)=>{const{eventRegistrationId:r}=e,a=w.get(r);if(!a)throw new EventError(`No registered event listener found for id: ${r}`);d("Event payload received",e),a.handler(e)},u=t=>async r=>{let a;for(const[e,t]of w)if(t.listener===r){a=e;break}if(!a)throw new EventError;d("Deregistering event:",a);try{await t.dispatch(e.DeregisterEvent,a),w.delete(a)}catch(e){throw new AdapterError}};var g;!function(e){e.Workbook="Workbook",e.Worksheet="Worksheet",e.CellRange="CellRange"}(g||(g={}));const m=()=>void 0!==crypto.randomUUID?crypto.randomUUID():"10000000-1000-4000-8000-100000000000".replace(/[018]/g,(e=>{const t=window.crypto.getRandomValues(new Uint8Array(1))[0]&15>>Number(e)/4;return(Number(e)^t).toString(16)})),C=new Map,y=(e,t)=>async(r,a)=>p(e,t,r,a,W(a)),v=(t,r,a)=>async()=>{d(`Cell range: Clear; address:${a} (${r})`);const o={address:a,objectId:r};try{await t.dispatch(e.ClearCells,o)}catch(e){throw new AdapterError}},b=(t,r,a)=>async()=>{d(`Cell range: Clear formatting; address:${a} (${r})`);const o={address:a,objectId:r};try{await t.dispatch(e.ClearCellFormatting,o)}catch(e){throw new AdapterError}},A=(t,r,a)=>async()=>{d(`Cell range: Clear values; address:${a} (${r})`);const o={address:a,objectId:r};try{await t.dispatch(e.ClearCellValues,o)}catch(e){throw new AdapterError}},E=(e,t,r)=>(a,o=1e3)=>{if(o<=0)throw new ApiError("Update interval must be a positive number");const n=m();d(`Cell range: Create data stream; streamId:${n}; address:${r}; updateInterval:${o} (${t})`);const s={address:r,close:()=>{d(`Closed stream (${n})`),(e=>{var t;try{const r=C.get(e);if(!r)throw new ApiError(`Unable to find registered data stream with id ${e}`);void 0!==(null!==(t=r.timer)&&void 0!==t?t:void 0)&&F(e),C.delete(e)}catch(e){throw c(e),e}})(n)},id:n,start:()=>{d(`Started streaming (${n})`),U(n,a,e,t)},stop:()=>{d(`Stopped streaming (${n})`),F(n)},updateInterval:o,worksheetId:t};return C.set(n,{dataStream:s}),s},W=e=>r=>{var a;try{if((null===(a=r.eventName)||void 0===a?void 0:a.toUpperCase())===t.Change.toUpperCase())return e(r.changedCells);throw new EventError(`Unexpected cell range event: ${r.eventName}`)}catch(e){c(e)}},f=(e,t,r)=>async()=>{d(`Cell range: Get cells; address:${r} (${t})`);const a=await $(e,t,r);return d(`${r}:`,a),a},$=async(t,r,a)=>{const o={address:a,objectId:r};try{return await t.dispatch(e.GetCells,o)}catch(e){throw new AdapterError}},G=(t,r,a)=>async()=>{d(`Cell range: Get name; address:${a} (${r})`);const o={address:a,objectId:r};try{return await t.dispatch(e.GetCellNames,o)}catch(e){throw new AdapterError}},I=(t,r,a)=>async(o,n,s,i,l=!0)=>{d(`Cell range: Set filter; address:${a} (${r})`,{columnIndex:o,filterOperator:n,criteria1:s,criteria2:i,visibleDropDown:l});const c={address:a,criteria1:s,criteria2:i,columnIndex:o,filterOperator:n,objectId:r,visibleDropDown:l};try{await t.dispatch(e.FilterCells,c)}catch(e){throw new AdapterError}},N=(t,r,a)=>async o=>{d(`Cell range: Set formatting; address:${a} (${r})`,o);const n={address:a,formatting:o,objectId:r};try{await t.dispatch(e.SetCellFormatting,n)}catch(e){throw new AdapterError}},S=(t,r,a)=>async o=>{const n=o.trim();let s;if(!n)throw s=new ParameterError("Name cannot be an empty string"),c(s),s;if(n.length>255)throw s=new ParameterError("Name must be 255 characters or less"),c(s),s;if(/[^a-zA-Z0-9_.?\\"']/.test(n))throw s=new ParameterError("Name contains invalid characters"),c(s),s;if(/^\d/.test(n))throw s=new ParameterError("Name cannot start with a number"),c(s),s;d(`Cell range: Set name; address:${a}; newName:${n} (${r})`);const i={address:a,name:n,objectId:r};try{await t.dispatch(e.SetCellName,i)}catch(e){throw new AdapterError}},D=(t,r,a)=>async o=>{d(`Cell range: Set values; address:${a} (${r})`,o);const n={address:a,objectId:r,valuesMap:o};try{await t.dispatch(e.SetCellValues,n)}catch(e){throw new AdapterError}},U=(e,t,r,a)=>{var o;try{const n=C.get(e);if(!n)throw new ApiError(`Unable to find registered data stream with id ${e}`);void 0!==(null!==(o=n.timer)&&void 0!==o?o:void 0)&&F(e);const{address:s,updateInterval:i}=n.dataStream,l=async()=>{const o=await t();try{await D(r,a,s)([[o]])}catch(t){h(`Unable to update cell range for stream with id ${e}: ${null==t?void 0:t.message}`)}},c=window.setInterval(l,i);n.timer=c}catch(e){throw c(e),e}},F=e=>{var t;try{const r=C.get(e);if(!r)throw new ApiError(`Unable to find registered data stream with id ${e}`);if(void 0===(null!==(t=r.timer)&&void 0!==t?t:void 0))return;window.clearInterval(r.timer),r.timer=void 0}catch(e){throw c(e),e}},P=(t,r)=>async()=>{d(`Worksheet: Activate (${r})`);try{await t.dispatch(e.ActivateWorksheet,r)}catch(e){throw new AdapterError}},x=(e,t)=>async(r,a)=>p(e,t,r,a,V(a)),L=(t,r)=>async()=>{d(`Worksheet: Calculate (${r})`);try{await t.dispatch(e.CalculateWorksheet,r)}catch(e){throw new AdapterError}},B=(t,r)=>async()=>{d(`Worksheet: Clear all cell formatting (${r})`);try{await t.dispatch(e.ClearAllCellFormatting,r)}catch(e){throw new AdapterError}},j=(t,r)=>async()=>{d(`Worksheet: Clear all cells (${r})`);try{await t.dispatch(e.ClearAllCells,r)}catch(e){throw new AdapterError}},R=(t,r)=>async()=>{d(`Worksheet: Clear all cell values (${r})`);try{await t.dispatch(e.ClearAllCellValues,r)}catch(e){throw new AdapterError}},O=(e,t)=>{const r={eventTarget:g.Worksheet,objectId:t};return{objectId:t,activate:P(e,t),addEventListener:x(e,r),calculate:L(e,t),clearAllCellFormatting:B(e,t),clearAllCells:j(e,t),clearAllCellValues:R(e,t),clearCellFormatting:r=>b(e,t,r)(),clearCells:r=>v(e,t,r)(),clearCellValues:r=>A(e,t,r)(),createDataStream:(r,a,o)=>E(e,t,r)(a,o),delete:z(e,t),filterCells:(r,a,o,n,s,i)=>I(e,t,r)(a,o,n,s,i),getCellRange:M(e,r),getCells:r=>f(e,t,r)(),getName:T(e,t),protect:H(e,t),removeEventListener:u(e),setCellFormatting:(r,a)=>N(e,t,r)(a),setCellName:(r,a)=>S(e,t,r)(a),setCellValues:(r,a)=>D(e,t,r)(a),setName:Q(e,t)}},V=e=>r=>{var a;try{switch(null===(a=r.eventName)||void 0===a?void 0:a.toUpperCase()){case t.Activate.toUpperCase():case t.Deactivate.toUpperCase():return e();case t.Change.toUpperCase():return e(r.changedCells);default:throw new EventError(`Unexpected worksheet event: ${r.eventName}`)}}catch(e){c(e)}},z=(t,r)=>async()=>{d(`Worksheet: Delete (${r})`);try{await t.dispatch(e.DeleteWorksheet,r)}catch(e){throw new AdapterError}},M=(t,r)=>async a=>{const{objectId:o}=r;d(`Worksheet: Get cell range; address:${a} (${o})`);try{const n={address:a,objectId:o},s=await t.dispatch(e.GetRangeAddress,n);return((e,t,r)=>{const{objectId:a}=t,o={cellRangeAddress:r,eventTarget:g.CellRange,objectId:a};return{addEventListener:y(e,o),address:r,clear:v(e,a,r),clearFormatting:b(e,a,r),clearValues:A(e,a,r),createDataStream:E(e,a,r),getCells:f(e,a,r),getNames:G(e,a,r),removeEventListener:u(e),setFilter:I(e,a,r),setFormatting:N(e,a,r),setName:S(e,a,r),setValues:D(e,a,r)}})(t,r,s)}catch(e){if(e.message.indexOf("Unable to get cell range")>=0){const e=new InvalidCellRangeAddressError;throw c(e),e}throw new AdapterError}},T=(t,r)=>async()=>{d(`Worksheet: Get name (${r})`);try{return await t.dispatch(e.GetWorksheetName,r)}catch(e){throw new AdapterError}},H=(t,r)=>async()=>{d(`Worksheet: Protect (${r})`);try{await t.dispatch(e.ProtectWorksheet,r)}catch(e){throw new AdapterError}},Q=(t,r)=>async a=>{const o=a.slice(0,31).replace(/[:\\/?*[\]]/g,"").trim();let n;if(!o)throw n=new ParameterError("Invalid worksheet name"),c(n),n;d(`Worksheet: Set name; newWorksheetName:${o} (${r})`);const s={newWorksheetName:o,objectId:r};try{return await t.dispatch(e.SetWorksheetName,s)}catch(e){throw new AdapterError}},_=(t,r)=>async()=>{d(`Workbook: Activate (${r})`);try{return await t.dispatch(e.ActivateWorkbook,r)}catch(e){throw new AdapterError}},q=(e,t)=>async(r,a)=>p(e,t,r,a,Y(e,a)),J=(t,r)=>async()=>{let a;d(`Workbook: Add worksheet (${r})`);try{a=await t.dispatch(e.AddWorksheet,r)}catch(e){throw new AdapterError}return O(t,a)},K=(t,r)=>async()=>{d(`Workbook: Calculate (${r})`);try{await t.dispatch(e.CalculateWorkbook,r)}catch(e){throw new AdapterError}},X=(t,r)=>async()=>{d(`Workbook: Close (${r})`);try{return await t.dispatch(e.CloseWorkbook,r)}catch(e){throw new AdapterError}},Z=(e,t)=>{const r={eventTarget:g.Workbook,objectId:t};return{objectId:t,activate:_(e,t),addWorksheet:J(e,t),addEventListener:q(e,r),calculate:K(e,t),close:X(e,t),getActiveWorksheet:ee(e,t),getCalculationMode:te(e,t),getFilePath:re(e,t),getName:ae(e,t),getWindowBounds:oe(e,t),getWorksheetByName:ne(e,t),getWorksheets:se(e,t),removeEventListener:u(e),save:ie(e,t),saveAs:le(e,t),setWindowBounds:ce(e,t)}},Y=(e,r)=>a=>{var o;try{switch(null===(o=a.eventName)||void 0===o?void 0:o.toUpperCase()){case t.Activate.toUpperCase():case t.Close.toUpperCase():case t.Deactivate.toUpperCase():return r();case t.ActivateWorksheet.toUpperCase():case t.AddWorksheet.toUpperCase():return r(O(e,a.worksheetObjectId));case t.DeleteWorksheet.toUpperCase():return r(a.worksheetName);default:throw new EventError(`Unexpected workbook event: ${a.eventName}`)}}catch(e){c(e)}},ee=(t,r)=>async()=>{let a;d(`Workbook: Get active worksheet: (${r})`);try{a=await t.dispatch(e.GetActiveWorksheet,r)}catch(e){throw new AdapterError}return O(t,a)},te=(t,r)=>async()=>{d("Workbook: Get calculation mode");try{return await t.dispatch(e.GetCalculationMode,r)}catch(e){throw new AdapterError}},re=(t,r)=>async()=>{d(`Workbook: Get file path (${r})`);try{return await t.dispatch(e.GetWorkbookFilePath,r)}catch(e){throw new AdapterError}},ae=(t,r)=>async()=>{d(`Workbook: Get name (${r})`);try{return await t.dispatch(e.GetWorkbookName,r)}catch(e){throw new AdapterError}},oe=(t,r)=>async()=>{d(`Workbook: Get window bounds (${r})`);try{return await t.dispatch(e.GetWorkbookWindowBounds,r)}catch(e){throw new AdapterError}},ne=(t,r)=>async a=>{let o;d(`Workbook: Get worksheet by name: ${a} (${r})`);try{if(o=await t.dispatch(e.GetWorksheetByName,{objectId:r,worksheetName:a}),null===o)return null}catch(e){throw new AdapterError}return O(t,o)},se=(t,r)=>async()=>{let a;d(`Workbook: Get worksheets (${r})`);try{a=await t.dispatch(e.GetWorksheets,r)}catch(e){throw new AdapterError}return a.map((e=>O(t,e)))},ie=(t,r)=>async()=>{d(`Workbook: Save (${r})`);try{return await t.dispatch(e.SaveWorkbook,r)}catch(e){throw new AdapterError}},le=(t,r)=>async a=>{d(`Workbook: Save as; filePath:${a} (${r})`);try{return await t.dispatch(e.SaveWorkbookAs,{filePath:a,objectId:r})}catch(e){throw new AdapterError}},ce=(t,r)=>async a=>{d(`Workbook: Set window bounds (${r})`,a);const{height:o,left:n,top:s,width:i}=a;if(null!=o&&(Number.isNaN(o)||o<=0)){const e=new ParameterError("Workbook window height must be a number greater than zero.");throw c(e),e}if(null!=n&&Number.isNaN(n)){const e=new ParameterError("Workbook window left position must be a valid number.");throw c(e),e}if(null!=s&&Number.isNaN(s)){const e=new ParameterError("Workbook window top position must be a valid number.");throw c(e),e}if(null!=i&&(Number.isNaN(i)||i<=0)){const e=new ParameterError("Workbook window width must be a number greater than zero.");throw c(e),e}const l={newWindowBounds:a,objectId:r};try{return await t.dispatch(e.SetWorkbookWindowBounds,l)}catch(e){throw new AdapterError}},de=t=>async r=>{let a;d(`Application: Get workbook; id:${r}`);try{a=await t.dispatch(e.GetWorkbookById,r)}catch(e){throw new AdapterError}return Z(t,a)},he=t=>async()=>{let r;d("Application: Get workbooks");try{r=await t.dispatch(e.GetWorkbooks)}catch(e){throw new AdapterError}return r.map((e=>Z(t,e)))},we=t=>async r=>{d(`Application: Get worksheet; id:${r}`);try{r=await t.dispatch(e.GetWorksheetById,r)}catch(e){throw new AdapterError}return O(t,r)},pe=t=>async r=>{let a;d(`Application: Open workbook; filePath:${r}`);try{a=await t.dispatch(e.OpenWorkbook,r)}catch(e){throw new AdapterError}return Z(t,a)},ke=t=>async(r=!0)=>{d(`Application: Quit; displayAlerts:${r}`);try{return await t.dispatch(e.QuitApplication,r)}catch(e){throw new AdapterError}};var ue,ge;!function(e){e.ExcelApplication="EXCEL-APP"}(ue||(ue={})),function(e){e[e.Info=1]="Info",e[e.Warn=2]="Warn",e[e.Error=3]="Error"}(ge||(ge={}));const me="excel-adapter",Ce=m();let ye;const ve=()=>o,be=async(t=!1)=>{try{if(await(async e=>{try{d("Registering usage"),await fin.System.registerUsage({type:"integration-feature",data:{apiVersion:o,componentName:e}})}catch(t){h(`Unable to register usage for feature ${e}: ${null==t?void 0:t.message}`)}})(ue.ExcelApplication),!await(async e=>(await fin.InterApplicationBus.Channel.getAllChannels()).some((t=>t.channelName===e)))(Ce)){await(async()=>{var e;const t=null===(e=(await fin.Application.getCurrentSync().getManifest()).appAssets)||void 0===e?void 0:e.find((e=>e.alias===me));if(t)return void h("Detected adapter package in app manifest appAssets",t);if(await Ee())return void d("Using existing adapter package");const r={alias:me,src:`https://cdn.openfin.co/release/integrations/excel/${ve()}/OpenFin.Excel.zip`,target:"OpenFin.Excel.exe",version:ve()};d("Downloading adapter package",r);try{await fin.System.downloadAsset(r,(()=>{}))}catch(e){throw c("Unable to download adapter package"),e}})();const{securityRealm:e,port:r}=await fin.System.getRuntimeInfo();let{licenseKey:a}=await fin.Application.getCurrentSync().getManifest();a=null!=a?a:"NO_LICENSE_KEY";const o=fin.me.uuid;d("Initializing adapter",{adapterLoggingEnabled:t,channelName:Ce,licenseKey:a,port:r,securityRealm:e,uuid:o}),fin.System.launchExternalProcess({alias:me,arguments:`${o} ${a} ${r} ${e} ${Ce} ${t}`})}const r=fin.InterApplicationBus.Channel.connect(Ce,{payload:{version:ve()}}),a=new Promise((e=>{setTimeout(e,2e4)})).then((()=>{throw new Error("Connection to adapter timed out")}));ye=await Promise.race([r,a]),d(`Connected to adapter ${ye.providerIdentity.uuid} on channel ${Ce}`),ye.register(e.LogMessage,Ae),ye.register(e.EventFired,k)}catch(e){const t=new InitializationError(void 0,e);throw c(t),t}return{adapter:{channelName:Ce,version:ve()},createWorkbook:(r=ye,async()=>{let t;d("Application: Create workbook");try{t=await r.dispatch(e.CreateWorkbook)}catch(e){throw new AdapterError}return Z(r,t)}),getWorkbookById:de(ye),getWorkbooks:he(ye),getWorksheetById:we(ye),openWorkbook:pe(ye),quit:ke(ye)};var r},Ae=(e,t)=>{const{message:r,type:a}=e,o="[adapter]";switch(a){case ge.Error:c(r,o);break;case ge.Info:d(o,r);break;case ge.Warn:h(o,r);break;default:c(new Error(`Unknown log type: ${a}`))}},Ee=async()=>{try{const e=await fin.System.getAppAssetInfo({alias:me});return e&&e.version===ve()}catch(e){return!1}};var We,fe,$e,Ge,Ie;!function(e){e.Continuous="Continuous",e.Dash="Dash",e.DashDot="DashDot",e.DashDotDot="DashDotDot",e.Dot="Dot",e.Double="Double",e.SlantDashDot="SlantDashDot",e.None="None"}(We||(We={})),function(e){e.Center="Center",e.CenterAcrossSelection="CenterAcrossSelection",e.Distributed="Distributed",e.Fill="Fill",e.General="General",e.Justify="Justify",e.Left="Left",e.Right="Right"}(fe||(fe={})),function(e){e.Automatic="Automatic",e.Checker="Checker",e.CrissCross="CrissCross",e.Down="Down",e.Gray16="Gray16",e.Gray25="Gray25",e.Gray50="Gray50",e.Gray75="Gray75",e.Gray8="Gray8",e.Grid="Grid",e.Horizontal="Horizontal",e.LightDown="LightDown",e.LightHorizontal="LightHorizontal",e.LightUp="LightUp",e.LightVertical="LightVertical",e.LinearGradient="LinearGradient",e.None="None",e.RectangularGradient="RectangularGradient",e.SemiGray75="SemiGray75",e.Solid="Solid",e.Up="Up",e.Vertical="Vertical"}($e||($e={})),function(e){e.Bottom="Bottom",e.Center="Center",e.Distributed="Distributed",e.Justify="Justify",e.Top="Top"}(Ge||(Ge={})),function(e){e.And="And",e.Or="Or",e.Top10Items="Top10Items",e.Bottom10Items="Bottom10Items",e.Top10Percent="Top10Percent",e.Bottom10Percent="Bottom10Percent",e.FilterValues="FilterValues"}(Ie||(Ie={}));var Ne=a.dq,Se=a.MS,De=a.xQ,Ue=a.sO,Fe=a.Zu,Pe=a.I3,xe=a.$U,Le=a.i0,Be=a.cX,je=a.gH,Re=a._W,Oe=a.U$,Ve=a.U7,ze=a.rd; + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!*****************************!*\ + !*** ./client/src/excel.ts ***! + \*****************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _finos_fdc3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @finos/fdc3 */ "../../node_modules/@finos/fdc3/dist/fdc3.esm.js"); +/* harmony import */ var _openfin_excel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @openfin/excel */ "../../node_modules/@openfin/excel/openfin.excel.mjs"); + + +const KNOWN_INSTRUMENTS = ["TSLA", "MSFT", "AAPL"]; +let excel; +let openWorkbooks; +let selectedWorkbookIndex; +let openWorksheets; +let selectedWorksheetIndex; +document.addEventListener("DOMContentLoaded", async () => { + try { + await initDom(); + } + catch (error) { + console.error(error); + } +}); +/** + * Initialize the DOM components. + */ +async function initDom() { + try { + const resultsContainer = document.querySelector("#results-container"); + if (resultsContainer) { + resultsContainer.style.display = "none"; + } + excel = await (0,_openfin_excel__WEBPACK_IMPORTED_MODULE_1__.getExcelApplication)(); + await populateWorkbooks(); + const openExcelButton = document.querySelector("#open-excel"); + if (openExcelButton) { + openExcelButton.addEventListener("click", async () => { + await openExcel(); + }); + } + const refreshWorkbookButton = document.querySelector("#workbook-refresh"); + if (refreshWorkbookButton) { + refreshWorkbookButton.addEventListener("click", async () => populateWorkbooks()); + } + const refreshWorksheetButton = document.querySelector("#worksheet-refresh"); + if (refreshWorksheetButton) { + refreshWorksheetButton.addEventListener("click", async () => populateWorksheets()); + } + const openWorkbooksSelect = document.querySelector("#workbooks"); + if (openWorkbooksSelect) { + openWorkbooksSelect.addEventListener("change", async (e) => selectWorkbook(e.target.value)); + } + const openWorksheetsSelect = document.querySelector("#worksheets"); + if (openWorksheetsSelect) { + openWorksheetsSelect.addEventListener("change", async (e) => selectWorksheet(e.target.value)); + } + const setValueButton = document.querySelector("#set-value"); + if (setValueButton) { + setValueButton.addEventListener("click", async () => { + await setCellValue(); + }); + } + } + catch (err) { + showError(err); + } +} +/** + * Show an error on the UI. + * @param err The error to display. + */ +function showError(err) { + const errDom = document.querySelector("#error"); + if (errDom) { + errDom.innerHTML = err instanceof Error ? err.message : JSON.stringify(err); + } +} +/** + * Open the excel instance. + */ +async function openExcel() { + try { + if (openWorkbooks && + selectedWorkbookIndex !== undefined && + openWorksheets && + selectedWorksheetIndex !== undefined) { + // Open the select work book and sheet + // if anything throws an exception just open a new workbook + await selectWorkbook(openWorkbooks[selectedWorkbookIndex].name); + await selectWorksheet(openWorksheets[selectedWorksheetIndex].name); + } + } + catch { + if (excel) { + await excel.createWorkbook(); + await populateWorkbooks(); + } + } +} +/** + * Populate the list of workbooks. + */ +async function populateWorkbooks() { + if (excel) { + selectedWorkbookIndex = undefined; + const refreshButton = document.querySelector("#workbook-refresh"); + const select = document.querySelector("#workbooks"); + if (refreshButton && select) { + refreshButton.disabled = true; + select.disabled = true; + select.innerHTML = ""; + openWorkbooks = []; + try { + const workbooks = await excel.getWorkbooks(); + for (const book of workbooks) { + const name = await book.getName(); + openWorkbooks.push({ + book, + name + }); + } + const optionEmpty = document.createElement("option"); + optionEmpty.innerHTML = "----Select workbook----"; + optionEmpty.value = ""; + optionEmpty.selected = true; + optionEmpty.disabled = true; + select.append(optionEmpty); + for (const openWorkbook of openWorkbooks) { + const option = document.createElement("option"); + option.innerHTML = openWorkbook.name; + option.value = openWorkbook.name; + select.append(option); + } + } + catch (err) { + console.error(err); + showError(err); + } + finally { + select.disabled = false; + refreshButton.disabled = false; + } + } + } +} +/** + * Select a workbook. + * @param name The name of the workbook to select. + */ +async function selectWorkbook(name) { + if (openWorkbooks) { + const newWorkbookIndex = openWorkbooks.findIndex((w) => w.name === name); + if (newWorkbookIndex !== selectedWorkbookIndex) { + selectedWorkbookIndex = newWorkbookIndex; + if (newWorkbookIndex >= 0) { + await openWorkbooks[selectedWorkbookIndex].book.activate(); + } + } + await populateWorksheets(); + } +} +/** + * Populate the worksheets. + */ +async function populateWorksheets() { + if (excel) { + selectedWorksheetIndex = undefined; + const refreshButton = document.querySelector("#worksheet-refresh"); + const select = document.querySelector("#worksheets"); + if (select && refreshButton && openWorkbooks && selectedWorkbookIndex !== undefined) { + refreshButton.disabled = true; + select.disabled = true; + select.innerHTML = ""; + openWorksheets = []; + const workbook = openWorkbooks[selectedWorkbookIndex]; + if (workbook) { + try { + const sheets = await workbook.book.getWorksheets(); + for (const sheet of sheets) { + const name = await sheet.getName(); + openWorksheets.push({ + sheet, + name + }); + } + const optionEmpty = document.createElement("option"); + optionEmpty.innerHTML = "----Select worksheet----"; + optionEmpty.value = ""; + optionEmpty.selected = true; + optionEmpty.disabled = true; + select.append(optionEmpty); + for (const openWorksheet of openWorksheets) { + const option = document.createElement("option"); + option.innerHTML = openWorksheet.name; + option.value = openWorksheet.name; + select.append(option); + } + } + catch (err) { + console.error(err); + showError(err); + } + finally { + select.disabled = false; + refreshButton.disabled = false; + } + } + } + } +} +/** + * Select a worksheet. + * @param name The name of worksheet to select. + */ +async function selectWorksheet(name) { + if (openWorksheets) { + const newWorksheetIndex = openWorksheets.findIndex((w) => w.name === name); + if (newWorksheetIndex !== selectedWorksheetIndex) { + if (selectedWorksheetIndex !== undefined) { + const oldWorksheet = openWorksheets[selectedWorksheetIndex]; + if (oldWorksheet) { + await oldWorksheet.sheet.removeEventListener(handleCellChange); + } + } + selectedWorksheetIndex = newWorksheetIndex; + if (selectedWorksheetIndex >= 0) { + await openWorksheets[selectedWorksheetIndex].sheet.activate(); + await openWorksheets[selectedWorksheetIndex].sheet.addEventListener("change", handleCellChange); + const resultsContainer = document.querySelector("#results-container"); + if (resultsContainer) { + resultsContainer.style.display = "flex"; + } + const cellLocation = document.querySelector("#cell-location"); + if (cellLocation) { + cellLocation.disabled = false; + } + const cellValue = document.querySelector("#cell-value"); + if (cellValue) { + cellValue.disabled = false; + } + const setValue = document.querySelector("#set-value"); + if (setValue) { + setValue.disabled = false; + } + } + } + } +} +/** + * Handle a change from the excel worksheet. + * @param cells The cells that were changed. + */ +async function handleCellChange(cells) { + const cellContainer = document.querySelector("#cell-changes-container"); + if (cellContainer) { + cellContainer.innerHTML = JSON.stringify(cells, undefined, " "); + for (const cell of cells) { + if (KNOWN_INSTRUMENTS.includes(cell.value)) { + await broadcastInstrument(cell.value); + } + } + } +} +/** + * Set a cell value in excel. + */ +async function setCellValue() { + if (openWorksheets && selectedWorksheetIndex !== undefined) { + const cellLocation = document.querySelector("#cell-location"); + const cellValue = document.querySelector("#cell-value"); + if (cellLocation && cellValue) { + const cells = [[cellValue.value]]; + await openWorksheets[selectedWorksheetIndex].sheet.setCellValues(cellLocation.value, cells); + } + } +} +/** + * Broadcast and FDC3 instrument. + * @param instrument The instrument to broadcast. + */ +async function broadcastInstrument(instrument) { + const broadcastElement = document.querySelector("#broadcast-instrument"); + if (broadcastElement) { + if (window.fdc3) { + try { + const fdcInstrument = { + type: "fdc3.instrument", + id: { + ticker: instrument + } + }; + const channel = await (0,_finos_fdc3__WEBPACK_IMPORTED_MODULE_0__.getCurrentChannel)(); + if (channel) { + await channel.broadcast(fdcInstrument); + } + broadcastElement.value = instrument; + } + catch (err) { + broadcastElement.value = err instanceof Error ? err.message : JSON.stringify(err); + } + } + else { + broadcastElement.textContent = "No FD3 Channel available"; + } + } +} + +})(); + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhjZWwuYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0EsY0FBYywyZ0VBQTJnRTtBQUN6aEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQsNkJBQTZCO0FBQ3pGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyw4QkFBOEI7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxvQ0FBb0M7QUFD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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FB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REFBbUQ7QUFDN0QsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUsMkRBQTJEO0FBQ3JFLFVBQVUsK0RBQStEO0FBQ3pFLFVBQVUscURBQXFEO0FBQy9ELFVBQVUsbURBQW1EO0FBQzdELFVBQVUscUVBQXFFO0FBQy9FLFVBQVUsdUNBQXVDO0FBQ2pELFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLHNCQUFzQjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDBCQUEwQjs7QUFFd2Y7QUFDbmhCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDam1HQSxXQUFXLFVBQVUsK0RBQStELHVCQUF1QixFQUFFLG9EQUFvRCxNQUFNLE9BQU8seU5BQXlOLEVBQUUsNkJBQTZCLG9EQUFvRCxNQUFNLGtIQUFrSCxzQkFBc0IsSUFBSSxvQ0FBb0Msc0RBQXNELFlBQVksa0NBQWtDLHlDQUF5QyxZQUFZLDJDQUEyQyxnREFBZ0QsWUFBWSxvREFBb0QsdURBQXVELFlBQVksc0NBQXNDLDJDQUEyQyxZQUFZLGFBQWEsNGdEQUE0Z0QsU0FBUyxlQUFlLDRMQUE0TCxTQUFTLEdBQUcsZ0JBQWdCLFNBQVMsa0NBQWtDLEtBQUssUUFBUSxXQUFXLEVBQUUsR0FBRyxXQUFXLG9DQUFvQyxHQUFHLEVBQUUsRUFBRSxxREFBcUQsR0FBRyxFQUFFLEVBQUUsUUFBUSxZQUFZLHVCQUF1QixZQUFZLHlCQUF5QiwrQ0FBK0MsT0FBTyxxQkFBcUIsY0FBYyxPQUFPLG1DQUFtQyxFQUFFLHFDQUFxQyxvQ0FBb0MscUVBQXFFLGFBQWEsb0VBQW9FLE9BQU8sa0RBQWtELEVBQUUsR0FBRyxhQUFhLHVCQUF1QixlQUFlLElBQUkseUJBQXlCLElBQUksK0NBQStDLHNCQUFzQixXQUFXLFNBQVMsa0NBQWtDLFdBQVcsTUFBTSxzQkFBc0IsY0FBYyx5RUFBeUUsRUFBRSxHQUFHLDJDQUEyQyxnQkFBZ0IsTUFBTSxzQ0FBc0MsSUFBSSxNQUFNLDJCQUEyQiw0QkFBNEIsSUFBSSxrREFBa0QsU0FBUyx5QkFBeUIsTUFBTSxhQUFhLHNFQUFzRSxTQUFTLEdBQUcsd0hBQXdILDRFQUE0RSxpQ0FBaUMsdUVBQXVFLHNCQUFzQixVQUFVLEdBQUcsR0FBRyxFQUFFLElBQUksU0FBUyxzQkFBc0IsSUFBSSxpQ0FBaUMsU0FBUyx3QkFBd0Isc0JBQXNCLGlDQUFpQyxVQUFVLEdBQUcsR0FBRyxFQUFFLElBQUksU0FBUyxzQkFBc0IsSUFBSSwwQ0FBMEMsU0FBUyx3QkFBd0Isc0JBQXNCLDZCQUE2QixVQUFVLEdBQUcsR0FBRyxFQUFFLElBQUksU0FBUyxzQkFBc0IsSUFBSSxzQ0FBc0MsU0FBUyx3QkFBd0Isd0JBQXdCLHdFQUF3RSxZQUFZLG1DQUFtQyxXQUFXLElBQUksVUFBVSxJQUFJLGlCQUFpQixHQUFHLEdBQUcsRUFBRSxJQUFJLFNBQVMscUJBQXFCLG9CQUFvQixFQUFFLFNBQVMsTUFBTSxJQUFJLGlCQUFpQiwwRUFBMEUsRUFBRSxHQUFHLHFFQUFxRSxTQUFTLGNBQWMsS0FBSyxpQkFBaUIsd0JBQXdCLEVBQUUsZUFBZSxXQUFXLHdCQUF3QixFQUFFLFNBQVMsaUNBQWlDLGdCQUFnQixhQUFhLElBQUksVUFBVSxNQUFNLElBQUksaUhBQWlILHFEQUFxRCxZQUFZLEdBQUcsU0FBUyxNQUFNLHNCQUFzQiwwQkFBMEIsVUFBVSxHQUFHLEdBQUcsRUFBRSxJQUFJLHVCQUF1QixZQUFZLEVBQUUsUUFBUSxrQkFBa0IsU0FBUyxzQkFBc0IsSUFBSSxzQ0FBc0MsU0FBUyx3QkFBd0Isc0JBQXNCLHlCQUF5QixVQUFVLEdBQUcsR0FBRyxFQUFFLElBQUksU0FBUyxzQkFBc0IsSUFBSSwwQ0FBMEMsU0FBUyx3QkFBd0Isa0NBQWtDLDJCQUEyQixVQUFVLEdBQUcsR0FBRyxFQUFFLElBQUkseUVBQXlFLEVBQUUsU0FBUywrRkFBK0YsSUFBSSxrQ0FBa0MsU0FBUyx3QkFBd0Isc0JBQXNCLCtCQUErQixVQUFVLEdBQUcsR0FBRyxFQUFFLE1BQU0sU0FBUyxtQ0FBbUMsSUFBSSx3Q0FBd0MsU0FBUyx3QkFBd0Isc0JBQXNCLGlCQUFpQixNQUFNLDBFQUEwRSx5RkFBeUYsdUdBQXVHLHNGQUFzRix5QkFBeUIsVUFBVSxJQUFJLFVBQVUsR0FBRyxHQUFHLEVBQUUsSUFBSSxTQUFTLDZCQUE2QixJQUFJLGtDQUFrQyxTQUFTLHdCQUF3QixzQkFBc0IsMkJBQTJCLFVBQVUsR0FBRyxHQUFHLEVBQUUsTUFBTSxTQUFTLGtDQUFrQyxJQUFJLG9DQUFvQyxTQUFTLHdCQUF3QixlQUFlLE1BQU0sSUFBSSxpQkFBaUIsMEVBQTBFLEVBQUUsR0FBRyx5REFBeUQsTUFBTSwyQkFBMkIsMEJBQTBCLGtCQUFrQixJQUFJLHNCQUFzQixTQUFTLG9EQUFvRCxFQUFFLElBQUkseUJBQXlCLElBQUksMkJBQTJCLFVBQVUsU0FBUyxjQUFjLE9BQU8sTUFBTSxJQUFJLGlCQUFpQiwwRUFBMEUsRUFBRSxHQUFHLDZEQUE2RCw2Q0FBNkMsU0FBUyxjQUFjLG9CQUFvQiwwQkFBMEIsRUFBRSxJQUFJLElBQUksd0NBQXdDLFNBQVMsd0JBQXdCLHlEQUF5RCwyQkFBMkIsRUFBRSxJQUFJLElBQUkseUNBQXlDLFNBQVMsd0JBQXdCLG9CQUFvQiwyQ0FBMkMsRUFBRSxJQUFJLElBQUksNkNBQTZDLFNBQVMsd0JBQXdCLG9CQUFvQixpQ0FBaUMsRUFBRSxJQUFJLElBQUksb0NBQW9DLFNBQVMsd0JBQXdCLG9CQUFvQix1Q0FBdUMsRUFBRSxJQUFJLElBQUkseUNBQXlDLFNBQVMsd0JBQXdCLFdBQVcsU0FBUyxvQ0FBb0MsT0FBTyxzaUJBQXNpQixVQUFVLE1BQU0sSUFBSSxrRUFBa0UseUVBQXlFLHFEQUFxRCw0REFBNEQsWUFBWSxJQUFJLFNBQVMsTUFBTSxvQkFBb0Isd0JBQXdCLEVBQUUsSUFBSSxJQUFJLHNDQUFzQyxTQUFTLHdCQUF3QixvQkFBb0IsTUFBTSxXQUFXLEdBQUcsOEJBQThCLFVBQVUsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLFNBQVMscUJBQXFCLHlDQUF5QyxpQkFBaUIsTUFBTSxXQUFXLE1BQU0sdURBQXVELE9BQU8scVFBQXFRLFNBQVMsU0FBUyxxREFBcUQseUNBQXlDLGFBQWEsd0JBQXdCLG9CQUFvQiwwQkFBMEIsRUFBRSxJQUFJLElBQUksOENBQThDLFNBQVMsd0JBQXdCLG9CQUFvQix5QkFBeUIsRUFBRSxJQUFJLElBQUksdUNBQXVDLFNBQVMsd0JBQXdCLG9CQUFvQix3REFBd0QsTUFBTSxrRUFBa0Usd0JBQXdCLG1CQUFtQixHQUFHLEdBQUcsRUFBRSxJQUFJLFNBQVMsK0JBQStCLElBQUksOENBQThDLFNBQVMsd0JBQXdCLG9CQUFvQix5QkFBeUIsRUFBRSxJQUFJLElBQUksOENBQThDLFNBQVMsd0JBQXdCLDJEQUEyRCxNQUFNLDhCQUE4QixFQUFFLElBQUksSUFBSSxxQ0FBcUMsU0FBUyx1QkFBdUIsY0FBYyxvQkFBb0IsMEJBQTBCLEVBQUUsSUFBSSxJQUFJLHdDQUF3QyxTQUFTLHdCQUF3QixvQkFBb0Isc0JBQXNCLEVBQUUsSUFBSSxJQUFJLDJDQUEyQyxTQUFTLHdCQUF3QixXQUFXLFNBQVMsbUNBQW1DLE9BQU8sc1ZBQXNWLGNBQWMsTUFBTSxJQUFJLGtFQUFrRSxvR0FBb0csNEdBQTRHLCtEQUErRCwyREFBMkQsWUFBWSxJQUFJLFNBQVMsTUFBTSxxQkFBcUIsTUFBTSxzQ0FBc0MsRUFBRSxJQUFJLElBQUksMkNBQTJDLFNBQVMsdUJBQXVCLGNBQWMscUJBQXFCLG9DQUFvQyxJQUFJLGdEQUFnRCxTQUFTLHdCQUF3QixxQkFBcUIsOEJBQThCLEVBQUUsSUFBSSxJQUFJLGlEQUFpRCxTQUFTLHdCQUF3QixxQkFBcUIseUJBQXlCLEVBQUUsSUFBSSxJQUFJLDZDQUE2QyxTQUFTLHdCQUF3QixxQkFBcUIsa0NBQWtDLEVBQUUsSUFBSSxJQUFJLHFEQUFxRCxTQUFTLHdCQUF3QixxQkFBcUIsTUFBTSxzQ0FBc0MsR0FBRyxHQUFHLEVBQUUsSUFBSSxJQUFJLDRDQUE0QywyQkFBMkIsdUJBQXVCLFNBQVMsdUJBQXVCLGNBQWMscUJBQXFCLE1BQU0sK0JBQStCLEVBQUUsSUFBSSxJQUFJLHNDQUFzQyxTQUFTLHVCQUF1QiwwQkFBMEIscUJBQXFCLHFCQUFxQixFQUFFLElBQUksSUFBSSwwQ0FBMEMsU0FBUyx3QkFBd0IscUJBQXFCLHNCQUFzQixXQUFXLEdBQUcsR0FBRyxFQUFFLElBQUksSUFBSSwwQ0FBMEMsc0JBQXNCLEVBQUUsU0FBUyx3QkFBd0IscUJBQXFCLGtDQUFrQyxFQUFFLE1BQU0sTUFBTSw4QkFBOEIsR0FBRyxxQ0FBcUMseUZBQXlGLGFBQWEsNkJBQTZCLG9GQUFvRixhQUFhLDZCQUE2QixtRkFBbUYsYUFBYSxxQ0FBcUMsd0ZBQXdGLGFBQWEsU0FBUyw4QkFBOEIsSUFBSSxxREFBcUQsU0FBUyx3QkFBd0IsaUJBQWlCLE1BQU0sOEJBQThCLEtBQUssRUFBRSxHQUFHLElBQUksd0NBQXdDLFNBQVMsdUJBQXVCLGNBQWMsaUJBQWlCLE1BQU0sZ0NBQWdDLElBQUksbUNBQW1DLFNBQVMsdUJBQXVCLDBCQUEwQixpQkFBaUIsK0JBQStCLEtBQUssRUFBRSxHQUFHLElBQUkseUNBQXlDLFNBQVMsdUJBQXVCLGNBQWMsaUJBQWlCLE1BQU0sK0JBQStCLFdBQVcsRUFBRSxHQUFHLElBQUkscUNBQXFDLFNBQVMsdUJBQXVCLGNBQWMscUJBQXFCLHNCQUFzQixnQkFBZ0IsRUFBRSxHQUFHLElBQUksNkNBQTZDLFNBQVMseUJBQXlCLFVBQVUsYUFBYSwrQkFBK0IsV0FBVyxlQUFlLDJEQUEyRCxXQUFXLEdBQUcsZ0NBQWdDLE9BQU8sZ0NBQWdDLElBQUksbUJBQW1CLElBQUksdURBQXVELGlDQUFpQyw4QkFBOEIsRUFBRSxTQUFTLDBDQUEwQyxFQUFFLElBQUkseUJBQXlCLElBQUksbUlBQW1JLGdCQUFnQixNQUFNLGlJQUFpSSwyRUFBMkUsOERBQThELFNBQVMsa0VBQWtFLEtBQUssNkRBQTZELG1DQUFtQyxJQUFJLHdDQUF3QyxHQUFHLFNBQVMsaURBQWlELElBQUksTUFBTSx1QkFBdUIsbUNBQW1DLElBQUksYUFBYSxzREFBc0QsNkJBQTZCLG9CQUFvQiwwQkFBMEIsa0ZBQWtGLG9DQUFvQyxzQkFBc0IsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxvREFBb0QsU0FBUyxjQUFjLHFCQUFxQixrQkFBa0IsY0FBYyxtREFBbUQsR0FBRyx1REFBdUQsMEJBQTBCLGFBQWEsR0FBRyw0REFBNEQsU0FBUywwQ0FBMEMsYUFBYSxPQUFPLFNBQVMsNEJBQTRCLGdDQUFnQyxNQUFNLGtDQUFrQyxJQUFJLHFDQUFxQyxTQUFTLHVCQUF1QixjQUFjLHNHQUFzRyxNQUFNLFlBQVksTUFBTSxpQkFBaUIsaUJBQWlCLFVBQVUscUJBQXFCLE1BQU0sb0JBQW9CLE1BQU0sb0JBQW9CLE1BQU0seUNBQXlDLEVBQUUsS0FBSyxjQUFjLElBQUksMENBQTBDLFNBQVMsRUFBRSwyQkFBMkIsU0FBUyxXQUFXLG1CQUFtQixhQUFhLGdLQUFnSyxXQUFXLGVBQWUsa0xBQWtMLFdBQVcsZUFBZSwwZUFBMGUsV0FBVyxlQUFlLGdHQUFnRyxXQUFXLGVBQWUsZ0xBQWdMLFdBQVcsR0FBRzs7Ozs7O1VDQXptbUI7VUFDQTs7VUFFQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTs7VUFFQTtVQUNBOztVQUVBO1VBQ0E7VUFDQTs7Ozs7V0N0QkE7V0FDQTtXQUNBO1dBQ0E7V0FDQSx5Q0FBeUMsd0NBQXdDO1dBQ2pGO1dBQ0E7V0FDQTs7Ozs7V0NQQTs7Ozs7V0NBQTtXQUNBO1dBQ0E7V0FDQSx1REFBdUQsaUJBQWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0Q7Ozs7Ozs7Ozs7Ozs7QUNOZ0Q7QUFPeEI7QUFFeEIsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFFbkQsSUFBSSxLQUFtQyxDQUFDO0FBQ3hDLElBQUksYUFLUSxDQUFDO0FBQ2IsSUFBSSxxQkFBeUMsQ0FBQztBQUM5QyxJQUFJLGNBS1EsQ0FBQztBQUNiLElBQUksc0JBQTBDLENBQUM7QUFFL0MsUUFBUSxDQUFDLGdCQUFnQixDQUFDLGtCQUFrQixFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3hELElBQUksQ0FBQztRQUNKLE1BQU0sT0FBTyxFQUFFLENBQUM7SUFDakIsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDaEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN0QixDQUFDO0FBQ0YsQ0FBQyxDQUFDLENBQUM7QUFFSDs7R0FFRztBQUNILEtBQUssVUFBVSxPQUFPO0lBQ3JCLElBQUksQ0FBQztRQUNKLE1BQU0sZ0JBQWdCLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBYyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ25GLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztZQUN0QixnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQztRQUN6QyxDQUFDO1FBRUQsS0FBSyxHQUFHLE1BQU0sbUVBQW1CLEVBQUUsQ0FBQztRQUVwQyxNQUFNLGlCQUFpQixFQUFFLENBQUM7UUFFMUIsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUM5RCxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ3JCLGVBQWUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ3BELE1BQU0sU0FBUyxFQUFFLENBQUM7WUFDbkIsQ0FBQyxDQUFDLENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxxQkFBcUIsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDMUUsSUFBSSxxQkFBcUIsRUFBRSxDQUFDO1lBQzNCLHFCQUFxQixDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FBQztRQUNsRixDQUFDO1FBRUQsTUFBTSxzQkFBc0IsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDNUUsSUFBSSxzQkFBc0IsRUFBRSxDQUFDO1lBQzVCLHNCQUFzQixDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLGtCQUFrQixFQUFFLENBQUMsQ0FBQztRQUNwRixDQUFDO1FBRUQsTUFBTSxtQkFBbUIsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2pFLElBQUksbUJBQW1CLEVBQUUsQ0FBQztZQUN6QixtQkFBbUIsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQzFELGNBQWMsQ0FBRSxDQUFDLENBQUMsTUFBdUMsQ0FBQyxLQUFLLENBQUMsQ0FDaEUsQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLG9CQUFvQixHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDbkUsSUFBSSxvQkFBb0IsRUFBRSxDQUFDO1lBQzFCLG9CQUFvQixDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FDM0QsZUFBZSxDQUFFLENBQUMsQ0FBQyxNQUF1QyxDQUFDLEtBQUssQ0FBQyxDQUNqRSxDQUFDO1FBQ0gsQ0FBQztRQUVELE1BQU0sY0FBYyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDNUQsSUFBSSxjQUFjLEVBQUUsQ0FBQztZQUNwQixjQUFjLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUNuRCxNQUFNLFlBQVksRUFBRSxDQUFDO1lBQ3RCLENBQUMsQ0FBQyxDQUFDO1FBQ0osQ0FBQztJQUNGLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2QsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2hCLENBQUM7QUFDRixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBUyxTQUFTLENBQUMsR0FBWTtJQUM5QixNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2hELElBQUksTUFBTSxFQUFFLENBQUM7UUFDWixNQUFNLENBQUMsU0FBUyxHQUFHLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDN0UsQ0FBQztBQUNGLENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxTQUFTO0lBQ3ZCLElBQUksQ0FBQztRQUNKLElBQ0MsYUFBYTtZQUNiLHFCQUFxQixLQUFLLFNBQVM7WUFDbkMsY0FBYztZQUNkLHNCQUFzQixLQUFLLFNBQVMsRUFDbkMsQ0FBQztZQUNGLHNDQUFzQztZQUN0QywyREFBMkQ7WUFDM0QsTUFBTSxjQUFjLENBQUMsYUFBYSxDQUFDLHFCQUFxQixDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDaEUsTUFBTSxlQUFlLENBQUMsY0FBYyxDQUFDLHNCQUFzQixDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEUsQ0FBQztJQUNGLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUixJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ1gsTUFBTSxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDN0IsTUFBTSxpQkFBaUIsRUFBRSxDQUFDO1FBQzNCLENBQUM7SUFDRixDQUFDO0FBQ0YsQ0FBQztBQUVEOztHQUVHO0FBQ0gsS0FBSyxVQUFVLGlCQUFpQjtJQUMvQixJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ1gscUJBQXFCLEdBQUcsU0FBUyxDQUFDO1FBQ2xDLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQW9CLG1CQUFtQixDQUFDLENBQUM7UUFDckYsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBb0IsWUFBWSxDQUFDLENBQUM7UUFFdkUsSUFBSSxhQUFhLElBQUksTUFBTSxFQUFFLENBQUM7WUFDN0IsYUFBYSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFFOUIsTUFBTSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDdkIsTUFBTSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7WUFFdEIsYUFBYSxHQUFHLEVBQUUsQ0FBQztZQUVuQixJQUFJLENBQUM7Z0JBQ0osTUFBTSxTQUFTLEdBQUcsTUFBTSxLQUFLLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBRTdDLEtBQUssTUFBTSxJQUFJLElBQUksU0FBUyxFQUFFLENBQUM7b0JBQzlCLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNsQyxhQUFhLENBQUMsSUFBSSxDQUFDO3dCQUNsQixJQUFJO3dCQUNKLElBQUk7cUJBQ0osQ0FBQyxDQUFDO2dCQUNKLENBQUM7Z0JBRUQsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDckQsV0FBVyxDQUFDLFNBQVMsR0FBRyx5QkFBeUIsQ0FBQztnQkFDbEQsV0FBVyxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7Z0JBQ3ZCLFdBQVcsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO2dCQUM1QixXQUFXLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztnQkFDNUIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFFM0IsS0FBSyxNQUFNLFlBQVksSUFBSSxhQUFhLEVBQUUsQ0FBQztvQkFDMUMsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztvQkFDaEQsTUFBTSxDQUFDLFNBQVMsR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDO29CQUNyQyxNQUFNLENBQUMsS0FBSyxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUM7b0JBQ2pDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ3ZCLENBQUM7WUFDRixDQUFDO1lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztnQkFDZCxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNuQixTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDaEIsQ0FBQztvQkFBUyxDQUFDO2dCQUNWLE1BQU0sQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO2dCQUN4QixhQUFhLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztZQUNoQyxDQUFDO1FBQ0YsQ0FBQztJQUNGLENBQUM7QUFDRixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsS0FBSyxVQUFVLGNBQWMsQ0FBQyxJQUFZO0lBQ3pDLElBQUksYUFBYSxFQUFFLENBQUM7UUFDbkIsTUFBTSxnQkFBZ0IsR0FBRyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQyxDQUFDO1FBRXpFLElBQUksZ0JBQWdCLEtBQUsscUJBQXFCLEVBQUUsQ0FBQztZQUNoRCxxQkFBcUIsR0FBRyxnQkFBZ0IsQ0FBQztZQUN6QyxJQUFJLGdCQUFnQixJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUMzQixNQUFNLGFBQWEsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUM1RCxDQUFDO1FBQ0YsQ0FBQztRQUVELE1BQU0sa0JBQWtCLEVBQUUsQ0FBQztJQUM1QixDQUFDO0FBQ0YsQ0FBQztBQUVEOztHQUVHO0FBQ0gsS0FBSyxVQUFVLGtCQUFrQjtJQUNoQyxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ1gsc0JBQXNCLEdBQUcsU0FBUyxDQUFDO1FBQ25DLE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQW9CLG9CQUFvQixDQUFDLENBQUM7UUFDdEYsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBb0IsYUFBYSxDQUFDLENBQUM7UUFFeEUsSUFBSSxNQUFNLElBQUksYUFBYSxJQUFJLGFBQWEsSUFBSSxxQkFBcUIsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNyRixhQUFhLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztZQUU5QixNQUFNLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztZQUN2QixNQUFNLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztZQUV0QixjQUFjLEdBQUcsRUFBRSxDQUFDO1lBRXBCLE1BQU0sUUFBUSxHQUFHLGFBQWEsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBQ3RELElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ2QsSUFBSSxDQUFDO29CQUNKLE1BQU0sTUFBTSxHQUFHLE1BQU0sUUFBUSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztvQkFFbkQsS0FBSyxNQUFNLEtBQUssSUFBSSxNQUFNLEVBQUUsQ0FBQzt3QkFDNUIsTUFBTSxJQUFJLEdBQUcsTUFBTSxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7d0JBQ25DLGNBQWMsQ0FBQyxJQUFJLENBQUM7NEJBQ25CLEtBQUs7NEJBQ0wsSUFBSTt5QkFDSixDQUFDLENBQUM7b0JBQ0osQ0FBQztvQkFFRCxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO29CQUNyRCxXQUFXLENBQUMsU0FBUyxHQUFHLDBCQUEwQixDQUFDO29CQUNuRCxXQUFXLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztvQkFDdkIsV0FBVyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7b0JBQzVCLFdBQVcsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO29CQUM1QixNQUFNLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO29CQUUzQixLQUFLLE1BQU0sYUFBYSxJQUFJLGNBQWMsRUFBRSxDQUFDO3dCQUM1QyxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO3dCQUNoRCxNQUFNLENBQUMsU0FBUyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUM7d0JBQ3RDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FBQzt3QkFDbEMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztvQkFDdkIsQ0FBQztnQkFDRixDQUFDO2dCQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7b0JBQ2QsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDbkIsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNoQixDQUFDO3dCQUFTLENBQUM7b0JBQ1YsTUFBTSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7b0JBQ3hCLGFBQWEsQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO2dCQUNoQyxDQUFDO1lBQ0YsQ0FBQztRQUNGLENBQUM7SUFDRixDQUFDO0FBQ0YsQ0FBQztBQUVEOzs7R0FHRztBQUNILEtBQUssVUFBVSxlQUFlLENBQUMsSUFBWTtJQUMxQyxJQUFJLGNBQWMsRUFBRSxDQUFDO1FBQ3BCLE1BQU0saUJBQWlCLEdBQUcsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQztRQUUzRSxJQUFJLGlCQUFpQixLQUFLLHNCQUFzQixFQUFFLENBQUM7WUFDbEQsSUFBSSxzQkFBc0IsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDMUMsTUFBTSxZQUFZLEdBQUcsY0FBYyxDQUFDLHNCQUFzQixDQUFDLENBQUM7Z0JBQzVELElBQUksWUFBWSxFQUFFLENBQUM7b0JBQ2xCLE1BQU0sWUFBWSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO2dCQUNoRSxDQUFDO1lBQ0YsQ0FBQztZQUVELHNCQUFzQixHQUFHLGlCQUFpQixDQUFDO1lBQzNDLElBQUksc0JBQXNCLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ2pDLE1BQU0sY0FBYyxDQUFDLHNCQUFzQixDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUM5RCxNQUFNLGNBQWMsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztnQkFFaEcsTUFBTSxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFjLG9CQUFvQixDQUFDLENBQUM7Z0JBQ25GLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztvQkFDdEIsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7Z0JBQ3pDLENBQUM7Z0JBRUQsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBbUIsZ0JBQWdCLENBQUMsQ0FBQztnQkFDaEYsSUFBSSxZQUFZLEVBQUUsQ0FBQztvQkFDbEIsWUFBWSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7Z0JBQy9CLENBQUM7Z0JBQ0QsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBbUIsYUFBYSxDQUFDLENBQUM7Z0JBQzFFLElBQUksU0FBUyxFQUFFLENBQUM7b0JBQ2YsU0FBUyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7Z0JBQzVCLENBQUM7Z0JBQ0QsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBbUIsWUFBWSxDQUFDLENBQUM7Z0JBQ3hFLElBQUksUUFBUSxFQUFFLENBQUM7b0JBQ2QsUUFBUSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7Z0JBQzNCLENBQUM7WUFDRixDQUFDO1FBQ0YsQ0FBQztJQUNGLENBQUM7QUFDRixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsS0FBSyxVQUFVLGdCQUFnQixDQUFDLEtBQWE7SUFDNUMsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO0lBQ3hFLElBQUksYUFBYSxFQUFFLENBQUM7UUFDbkIsYUFBYSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFFakUsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUMxQixJQUFJLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDNUMsTUFBTSxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdkMsQ0FBQztRQUNGLENBQUM7SUFDRixDQUFDO0FBQ0YsQ0FBQztBQUVEOztHQUVHO0FBQ0gsS0FBSyxVQUFVLFlBQVk7SUFDMUIsSUFBSSxjQUFjLElBQUksc0JBQXNCLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDNUQsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBbUIsZ0JBQWdCLENBQUMsQ0FBQztRQUNoRixNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFtQixhQUFhLENBQUMsQ0FBQztRQUUxRSxJQUFJLFlBQVksSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUMvQixNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDbEMsTUFBTSxjQUFjLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDN0YsQ0FBQztJQUNGLENBQUM7QUFDRixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsS0FBSyxVQUFVLG1CQUFtQixDQUFDLFVBQWtCO0lBQ3BELE1BQU0sZ0JBQWdCLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBbUIsdUJBQXVCLENBQUMsQ0FBQztJQUMzRixJQUFJLGdCQUFnQixFQUFFLENBQUM7UUFDdEIsSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDakIsSUFBSSxDQUFDO2dCQUNKLE1BQU0sYUFBYSxHQUFHO29CQUNyQixJQUFJLEVBQUUsaUJBQWlCO29CQUN2QixFQUFFLEVBQUU7d0JBQ0gsTUFBTSxFQUFFLFVBQVU7cUJBQ2xCO2lCQUNELENBQUM7Z0JBRUYsTUFBTSxPQUFPLEdBQUcsTUFBTSw4REFBaUIsRUFBRSxDQUFDO2dCQUMxQyxJQUFJLE9BQU8sRUFBRSxDQUFDO29CQUNiLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQztnQkFDeEMsQ0FBQztnQkFFRCxnQkFBZ0IsQ0FBQyxLQUFLLEdBQUcsVUFBVSxDQUFDO1lBQ3JDLENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNkLGdCQUFnQixDQUFDLEtBQUssR0FBRyxHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25GLENBQUM7UUFDRixDQUFDO2FBQU0sQ0FBQztZQUNQLGdCQUFnQixDQUFDLFdBQVcsR0FBRywwQkFBMEIsQ0FBQztRQUMzRCxDQUFDO0lBQ0YsQ0FBQztBQUNGLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC8uLi8uLi9ub2RlX21vZHVsZXMvQGZpbm9zL2ZkYzMvZGlzdC9mZGMzLmVzbS5qcyIsIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC8uLi8uLi9ub2RlX21vZHVsZXMvQG9wZW5maW4vZXhjZWwvb3BlbmZpbi5leGNlbC5tanMiLCJ3ZWJwYWNrOi8vaW50ZWdyYXRpb24tZXhjZWwvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vaW50ZWdyYXRpb24tZXhjZWwvd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzIiwid2VicGFjazovL2ludGVncmF0aW9uLWV4Y2VsL3dlYnBhY2svcnVudGltZS9oYXNPd25Qcm9wZXJ0eSBzaG9ydGhhbmQiLCJ3ZWJwYWNrOi8vaW50ZWdyYXRpb24tZXhjZWwvd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC8uL2NsaWVudC9zcmMvZXhjZWwudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gVG8gcGFyc2UgdGhpcyBkYXRhOlxuLy9cbi8vICAgaW1wb3J0IHsgQ29udmVydCwgQWdlbnRFcnJvclJlc3BvbnNlTWVzc2FnZSwgQWdlbnRSZXF1ZXN0TWVzc2FnZSwgQWdlbnRSZXNwb25zZU1lc3NhZ2UsIEJyaWRnZUVycm9yUmVzcG9uc2VNZXNzYWdlLCBCcmlkZ2VSZXF1ZXN0TWVzc2FnZSwgQnJpZGdlUmVzcG9uc2VNZXNzYWdlLCBCcm9hZGNhc3RBZ2VudFJlcXVlc3QsIEJyb2FkY2FzdEJyaWRnZVJlcXVlc3QsIENvbm5lY3Rpb25TdGVwTWVzc2FnZSwgQ29ubmVjdGlvblN0ZXAySGVsbG8sIENvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZSwgQ29ubmVjdGlvblN0ZXA0QXV0aGVudGljYXRpb25GYWlsZWQsIENvbm5lY3Rpb25TdGVwNkNvbm5lY3RlZEFnZW50c1VwZGF0ZSwgRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZSwgRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdCwgRmluZEluc3RhbmNlc0FnZW50UmVzcG9uc2UsIEZpbmRJbnN0YW5jZXNCcmlkZ2VFcnJvclJlc3BvbnNlLCBGaW5kSW5zdGFuY2VzQnJpZGdlUmVxdWVzdCwgRmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlLCBGaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlLCBGaW5kSW50ZW50QWdlbnRSZXF1ZXN0LCBGaW5kSW50ZW50QWdlbnRSZXNwb25zZSwgRmluZEludGVudEJyaWRnZUVycm9yUmVzcG9uc2UsIEZpbmRJbnRlbnRCcmlkZ2VSZXF1ZXN0LCBGaW5kSW50ZW50QnJpZGdlUmVzcG9uc2UsIEZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlLCBGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdCwgRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlc3BvbnNlLCBGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZUVycm9yUmVzcG9uc2UsIEZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVxdWVzdCwgRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXNwb25zZSwgR2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2UsIEdldEFwcE1ldGFkYXRhQWdlbnRSZXF1ZXN0LCBHZXRBcHBNZXRhZGF0YUFnZW50UmVzcG9uc2UsIEdldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZSwgR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXF1ZXN0LCBHZXRBcHBNZXRhZGF0YUJyaWRnZVJlc3BvbnNlLCBPcGVuQWdlbnRFcnJvclJlc3BvbnNlLCBPcGVuQWdlbnRSZXF1ZXN0LCBPcGVuQWdlbnRSZXNwb25zZSwgT3BlbkJyaWRnZUVycm9yUmVzcG9uc2UsIE9wZW5CcmlkZ2VSZXF1ZXN0LCBPcGVuQnJpZGdlUmVzcG9uc2UsIFByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0LCBQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3QsIFByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0LCBQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEJyaWRnZVJlcXVlc3QsIFByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRBZ2VudFJlcXVlc3QsIFByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRCcmlkZ2VSZXF1ZXN0LCBQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0LCBQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQnJpZGdlUmVxdWVzdCwgUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3QsIFByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QnJpZGdlUmVxdWVzdCwgUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQWdlbnRSZXF1ZXN0LCBQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVCcmlkZ2VSZXF1ZXN0LCBSYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZSwgUmFpc2VJbnRlbnRBZ2VudFJlcXVlc3QsIFJhaXNlSW50ZW50QWdlbnRSZXNwb25zZSwgUmFpc2VJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlLCBSYWlzZUludGVudEJyaWRnZVJlcXVlc3QsIFJhaXNlSW50ZW50QnJpZGdlUmVzcG9uc2UsIFJhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlLCBSYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2UsIFJhaXNlSW50ZW50UmVzdWx0QnJpZGdlRXJyb3JSZXNwb25zZSwgUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VSZXNwb25zZSwgQ29udGV4dCB9IGZyb20gXCIuL2ZpbGVcIjtcbi8vXG4vLyAgIGNvbnN0IGZEQzNEZXNrdG9wQWdlbnRBUElTY2hlbWEgPSBDb252ZXJ0LnRvRkRDM0Rlc2t0b3BBZ2VudEFQSVNjaGVtYShqc29uKTtcbi8vICAgY29uc3QgYWdlbnRFcnJvclJlc3BvbnNlTWVzc2FnZSA9IENvbnZlcnQudG9BZ2VudEVycm9yUmVzcG9uc2VNZXNzYWdlKGpzb24pO1xuLy8gICBjb25zdCBhZ2VudFJlcXVlc3RNZXNzYWdlID0gQ29udmVydC50b0FnZW50UmVxdWVzdE1lc3NhZ2UoanNvbik7XG4vLyAgIGNvbnN0IGFnZW50UmVzcG9uc2VNZXNzYWdlID0gQ29udmVydC50b0FnZW50UmVzcG9uc2VNZXNzYWdlKGpzb24pO1xuLy8gICBjb25zdCBicmlkZ2VFcnJvclJlc3BvbnNlTWVzc2FnZSA9IENvbnZlcnQudG9CcmlkZ2VFcnJvclJlc3BvbnNlTWVzc2FnZShqc29uKTtcbi8vICAgY29uc3QgYnJpZGdlUmVxdWVzdE1lc3NhZ2UgPSBDb252ZXJ0LnRvQnJpZGdlUmVxdWVzdE1lc3NhZ2UoanNvbik7XG4vLyAgIGNvbnN0IGJyaWRnZVJlc3BvbnNlTWVzc2FnZSA9IENvbnZlcnQudG9CcmlkZ2VSZXNwb25zZU1lc3NhZ2UoanNvbik7XG4vLyAgIGNvbnN0IGJyb2FkY2FzdEFnZW50UmVxdWVzdCA9IENvbnZlcnQudG9Ccm9hZGNhc3RBZ2VudFJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IGJyb2FkY2FzdEJyaWRnZVJlcXVlc3QgPSBDb252ZXJ0LnRvQnJvYWRjYXN0QnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgYnJpZGdpbmdDb21tb25zID0gQ29udmVydC50b0JyaWRnaW5nQ29tbW9ucyhqc29uKTtcbi8vICAgY29uc3QgY29ubmVjdGlvblN0ZXBNZXNzYWdlID0gQ29udmVydC50b0Nvbm5lY3Rpb25TdGVwTWVzc2FnZShqc29uKTtcbi8vICAgY29uc3QgY29ubmVjdGlvblN0ZXAySGVsbG8gPSBDb252ZXJ0LnRvQ29ubmVjdGlvblN0ZXAySGVsbG8oanNvbik7XG4vLyAgIGNvbnN0IGNvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZSA9IENvbnZlcnQudG9Db25uZWN0aW9uU3RlcDNIYW5kc2hha2UoanNvbik7XG4vLyAgIGNvbnN0IGNvbm5lY3Rpb25TdGVwNEF1dGhlbnRpY2F0aW9uRmFpbGVkID0gQ29udmVydC50b0Nvbm5lY3Rpb25TdGVwNEF1dGhlbnRpY2F0aW9uRmFpbGVkKGpzb24pO1xuLy8gICBjb25zdCBjb25uZWN0aW9uU3RlcDZDb25uZWN0ZWRBZ2VudHNVcGRhdGUgPSBDb252ZXJ0LnRvQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlKGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGZpbmRJbnN0YW5jZXNBZ2VudFJlcXVlc3QgPSBDb252ZXJ0LnRvRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgZmluZEluc3RhbmNlc0FnZW50UmVzcG9uc2UgPSBDb252ZXJ0LnRvRmluZEluc3RhbmNlc0FnZW50UmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGZpbmRJbnN0YW5jZXNCcmlkZ2VFcnJvclJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnN0YW5jZXNCcmlkZ2VFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW5zdGFuY2VzQnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9GaW5kSW5zdGFuY2VzQnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgZmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnN0YW5jZXNCcmlkZ2VSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgZmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZSA9IENvbnZlcnQudG9GaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW50ZW50QWdlbnRSZXF1ZXN0ID0gQ29udmVydC50b0ZpbmRJbnRlbnRBZ2VudFJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IGZpbmRJbnRlbnRBZ2VudFJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnRlbnRBZ2VudFJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZSA9IENvbnZlcnQudG9GaW5kSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgZmluZEludGVudEJyaWRnZVJlcXVlc3QgPSBDb252ZXJ0LnRvRmluZEludGVudEJyaWRnZVJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IGZpbmRJbnRlbnRCcmlkZ2VSZXNwb25zZSA9IENvbnZlcnQudG9GaW5kSW50ZW50QnJpZGdlUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdCA9IENvbnZlcnQudG9GaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgZmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgZmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VFcnJvclJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlRXJyb3JSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgZmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXF1ZXN0ID0gQ29udmVydC50b0ZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgZmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXNwb25zZSA9IENvbnZlcnQudG9GaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBnZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZSA9IENvbnZlcnQudG9HZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgZ2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3QgPSBDb252ZXJ0LnRvR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IGdldEFwcE1ldGFkYXRhQWdlbnRSZXNwb25zZSA9IENvbnZlcnQudG9HZXRBcHBNZXRhZGF0YUFnZW50UmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGdldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZSA9IENvbnZlcnQudG9HZXRBcHBNZXRhZGF0YUJyaWRnZUVycm9yUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGdldEFwcE1ldGFkYXRhQnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9HZXRBcHBNZXRhZGF0YUJyaWRnZVJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IGdldEFwcE1ldGFkYXRhQnJpZGdlUmVzcG9uc2UgPSBDb252ZXJ0LnRvR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3Qgb3BlbkFnZW50RXJyb3JSZXNwb25zZSA9IENvbnZlcnQudG9PcGVuQWdlbnRFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBvcGVuQWdlbnRSZXF1ZXN0ID0gQ29udmVydC50b09wZW5BZ2VudFJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IG9wZW5BZ2VudFJlc3BvbnNlID0gQ29udmVydC50b09wZW5BZ2VudFJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBvcGVuQnJpZGdlRXJyb3JSZXNwb25zZSA9IENvbnZlcnQudG9PcGVuQnJpZGdlRXJyb3JSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3Qgb3BlbkJyaWRnZVJlcXVlc3QgPSBDb252ZXJ0LnRvT3BlbkJyaWRnZVJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IG9wZW5CcmlkZ2VSZXNwb25zZSA9IENvbnZlcnQudG9PcGVuQnJpZGdlUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IHByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0ID0gQ29udmVydC50b1ByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBwcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3QgPSBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RCcmlkZ2VSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBwcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdCA9IENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgcHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRCcmlkZ2VSZXF1ZXN0ID0gQ29udmVydC50b1ByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgcHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEFnZW50UmVxdWVzdCA9IENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQWdlbnRSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBwcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgcHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdCA9IENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBwcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgcHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3QgPSBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IHByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEJyaWRnZVJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IHByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUFnZW50UmVxdWVzdCA9IENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IHByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUJyaWRnZVJlcXVlc3QgPSBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgcmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2UgPSBDb252ZXJ0LnRvUmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IHJhaXNlSW50ZW50QWdlbnRSZXF1ZXN0ID0gQ29udmVydC50b1JhaXNlSW50ZW50QWdlbnRSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCByYWlzZUludGVudEFnZW50UmVzcG9uc2UgPSBDb252ZXJ0LnRvUmFpc2VJbnRlbnRBZ2VudFJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCByYWlzZUludGVudEJyaWRnZUVycm9yUmVzcG9uc2UgPSBDb252ZXJ0LnRvUmFpc2VJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCByYWlzZUludGVudEJyaWRnZVJlcXVlc3QgPSBDb252ZXJ0LnRvUmFpc2VJbnRlbnRCcmlkZ2VSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCByYWlzZUludGVudEJyaWRnZVJlc3BvbnNlID0gQ29udmVydC50b1JhaXNlSW50ZW50QnJpZGdlUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IHJhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlID0gQ29udmVydC50b1JhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCByYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2UgPSBDb252ZXJ0LnRvUmFpc2VJbnRlbnRSZXN1bHRBZ2VudFJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCByYWlzZUludGVudFJlc3VsdEJyaWRnZUVycm9yUmVzcG9uc2UgPSBDb252ZXJ0LnRvUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCByYWlzZUludGVudFJlc3VsdEJyaWRnZVJlc3BvbnNlID0gQ29udmVydC50b1JhaXNlSW50ZW50UmVzdWx0QnJpZGdlUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGNvbnRleHQgPSBDb252ZXJ0LnRvQ29udGV4dChqc29uKTtcbi8vXG4vLyBUaGVzZSBmdW5jdGlvbnMgd2lsbCB0aHJvdyBhbiBlcnJvciBpZiB0aGUgSlNPTiBkb2Vzbid0XG4vLyBtYXRjaCB0aGUgZXhwZWN0ZWQgaW50ZXJmYWNlLCBldmVuIGlmIHRoZSBKU09OIGlzIHZhbGlkLlxuLy8gQ29udmVydHMgSlNPTiBzdHJpbmdzIHRvL2Zyb20geW91ciB0eXBlc1xuLy8gYW5kIGFzc2VydHMgdGhlIHJlc3VsdHMgb2YgSlNPTi5wYXJzZSBhdCBydW50aW1lXG52YXIgQ29udmVydCQxID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENvbnZlcnQoKSB7XG4gICAgfVxuICAgIENvbnZlcnQudG9GREMzRGVza3RvcEFnZW50QVBJU2NoZW1hID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCBcImFueVwiKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZkRDM0Rlc2t0b3BBZ2VudEFQSVNjaGVtYVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIFwiYW55XCIpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9BZ2VudEVycm9yUmVzcG9uc2VNZXNzYWdlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJBZ2VudEVycm9yUmVzcG9uc2VNZXNzYWdlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuYWdlbnRFcnJvclJlc3BvbnNlTWVzc2FnZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkFnZW50RXJyb3JSZXNwb25zZU1lc3NhZ2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9BZ2VudFJlcXVlc3RNZXNzYWdlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJBZ2VudFJlcXVlc3RNZXNzYWdlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuYWdlbnRSZXF1ZXN0TWVzc2FnZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkFnZW50UmVxdWVzdE1lc3NhZ2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9BZ2VudFJlc3BvbnNlTWVzc2FnZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiQWdlbnRSZXNwb25zZU1lc3NhZ2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5hZ2VudFJlc3BvbnNlTWVzc2FnZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkFnZW50UmVzcG9uc2VNZXNzYWdlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQnJpZGdlRXJyb3JSZXNwb25zZU1lc3NhZ2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkJyaWRnZUVycm9yUmVzcG9uc2VNZXNzYWdlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuYnJpZGdlRXJyb3JSZXNwb25zZU1lc3NhZ2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJCcmlkZ2VFcnJvclJlc3BvbnNlTWVzc2FnZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0JyaWRnZVJlcXVlc3RNZXNzYWdlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJCcmlkZ2VSZXF1ZXN0TWVzc2FnZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmJyaWRnZVJlcXVlc3RNZXNzYWdlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQnJpZGdlUmVxdWVzdE1lc3NhZ2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9CcmlkZ2VSZXNwb25zZU1lc3NhZ2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkJyaWRnZVJlc3BvbnNlTWVzc2FnZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmJyaWRnZVJlc3BvbnNlTWVzc2FnZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkJyaWRnZVJlc3BvbnNlTWVzc2FnZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0Jyb2FkY2FzdEFnZW50UmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiQnJvYWRjYXN0QWdlbnRSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuYnJvYWRjYXN0QWdlbnRSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQnJvYWRjYXN0QWdlbnRSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQnJvYWRjYXN0QnJpZGdlUmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiQnJvYWRjYXN0QnJpZGdlUmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmJyb2FkY2FzdEJyaWRnZVJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJCcm9hZGNhc3RCcmlkZ2VSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQnJpZGdpbmdDb21tb25zID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCBtJDEoXCJhbnlcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5icmlkZ2luZ0NvbW1vbnNUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCBtJDEoXCJhbnlcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Db25uZWN0aW9uU3RlcE1lc3NhZ2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkNvbm5lY3Rpb25TdGVwTWVzc2FnZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNvbm5lY3Rpb25TdGVwTWVzc2FnZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkNvbm5lY3Rpb25TdGVwTWVzc2FnZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0Nvbm5lY3Rpb25TdGVwMkhlbGxvID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJDb25uZWN0aW9uU3RlcDJIZWxsb1wiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNvbm5lY3Rpb25TdGVwMkhlbGxvVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQ29ubmVjdGlvblN0ZXAySGVsbG9cIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Db25uZWN0aW9uU3RlcDNIYW5kc2hha2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkNvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkNvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0Nvbm5lY3Rpb25TdGVwNEF1dGhlbnRpY2F0aW9uRmFpbGVkID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJDb25uZWN0aW9uU3RlcDRBdXRoZW50aWNhdGlvbkZhaWxlZFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNvbm5lY3Rpb25TdGVwNEF1dGhlbnRpY2F0aW9uRmFpbGVkVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQ29ubmVjdGlvblN0ZXA0QXV0aGVudGljYXRpb25GYWlsZWRcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Db25uZWN0aW9uU3RlcDZDb25uZWN0ZWRBZ2VudHNVcGRhdGUgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkNvbm5lY3Rpb25TdGVwNkNvbm5lY3RlZEFnZW50c1VwZGF0ZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNvbm5lY3Rpb25TdGVwNkNvbm5lY3RlZEFnZW50c1VwZGF0ZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkNvbm5lY3Rpb25TdGVwNkNvbm5lY3RlZEFnZW50c1VwZGF0ZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnN0YW5jZXNBZ2VudFJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnN0YW5jZXNBZ2VudFJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW5zdGFuY2VzQWdlbnRSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnN0YW5jZXNBZ2VudFJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnN0YW5jZXNBZ2VudFJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEluc3RhbmNlc0FnZW50UmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW5zdGFuY2VzQnJpZGdlRXJyb3JSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEluc3RhbmNlc0JyaWRnZUVycm9yUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW5zdGFuY2VzQnJpZGdlRXJyb3JSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnN0YW5jZXNCcmlkZ2VFcnJvclJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEluc3RhbmNlc0JyaWRnZVJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnN0YW5jZXNCcmlkZ2VSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZmluZEluc3RhbmNlc0JyaWRnZVJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW5zdGFuY2VzQnJpZGdlUmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnN0YW5jZXNCcmlkZ2VSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEludGVudEFnZW50UmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEludGVudEFnZW50UmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnRlbnRBZ2VudFJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW50ZW50QWdlbnRSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEludGVudEFnZW50UmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnRlbnRBZ2VudFJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZmluZEludGVudEFnZW50UmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW50ZW50QWdlbnRSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEludGVudEJyaWRnZUVycm9yUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW50ZW50QnJpZGdlUmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEludGVudEJyaWRnZVJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW50ZW50QnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnRlbnRCcmlkZ2VSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEludGVudEJyaWRnZVJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW50ZW50QnJpZGdlUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW50ZW50QnJpZGdlUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW50ZW50QnJpZGdlUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW50ZW50c0J5Q29udGV4dEFnZW50RXJyb3JSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudEVycm9yUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW50ZW50c0J5Q29udGV4dEFnZW50RXJyb3JSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZUVycm9yUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZUVycm9yUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZUVycm9yUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0dldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmdldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiR2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9HZXRBcHBNZXRhZGF0YUFnZW50UmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5nZXRBcHBNZXRhZGF0YUFnZW50UmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvR2V0QXBwTWV0YWRhdGFBZ2VudFJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5nZXRBcHBNZXRhZGF0YUFnZW50UmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9HZXRBcHBNZXRhZGF0YUJyaWRnZUVycm9yUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkdldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmdldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkdldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0dldEFwcE1ldGFkYXRhQnJpZGdlUmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZ2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmdldEFwcE1ldGFkYXRhQnJpZGdlUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJHZXRBcHBNZXRhZGF0YUJyaWRnZVJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvT3BlbkFnZW50RXJyb3JSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiT3BlbkFnZW50RXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lm9wZW5BZ2VudEVycm9yUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJPcGVuQWdlbnRFcnJvclJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvT3BlbkFnZW50UmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiT3BlbkFnZW50UmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lm9wZW5BZ2VudFJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJPcGVuQWdlbnRSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvT3BlbkFnZW50UmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIk9wZW5BZ2VudFJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQub3BlbkFnZW50UmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJPcGVuQWdlbnRSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b09wZW5CcmlkZ2VFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJPcGVuQnJpZGdlRXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lm9wZW5CcmlkZ2VFcnJvclJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiT3BlbkJyaWRnZUVycm9yUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9PcGVuQnJpZGdlUmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiT3BlbkJyaWRnZVJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5vcGVuQnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIk9wZW5CcmlkZ2VSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvT3BlbkJyaWRnZVJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJPcGVuQnJpZGdlUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5vcGVuQnJpZGdlUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJPcGVuQnJpZGdlUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEFnZW50UmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RBZ2VudFJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEFnZW50UmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RCcmlkZ2VSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRBZ2VudFJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRCcmlkZ2VSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEJyaWRnZVJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEJyaWRnZVJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEJyaWRnZVJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQWdlbnRSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEFnZW50UmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRBZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQnJpZGdlUmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEJyaWRnZVJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRCcmlkZ2VSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJBZ2VudFJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckJyaWRnZVJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJCcmlkZ2VSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckJyaWRnZVJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQnJpZGdlUmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1ByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEFnZW50UmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QWdlbnRSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEJyaWRnZVJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QnJpZGdlUmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QnJpZGdlUmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1ByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUFnZW50UmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQWdlbnRSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQWdlbnRSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQWdlbnRSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQnJpZGdlUmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQnJpZGdlUmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUJyaWRnZVJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVCcmlkZ2VSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlJhaXNlSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJSYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1JhaXNlSW50ZW50QWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJSYWlzZUludGVudEFnZW50UmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnJhaXNlSW50ZW50QWdlbnRSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUmFpc2VJbnRlbnRBZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9SYWlzZUludGVudEFnZW50UmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlJhaXNlSW50ZW50QWdlbnRSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnJhaXNlSW50ZW50QWdlbnRSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlJhaXNlSW50ZW50QWdlbnRSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1JhaXNlSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUmFpc2VJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucmFpc2VJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUmFpc2VJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUmFpc2VJbnRlbnRCcmlkZ2VSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJSYWlzZUludGVudEJyaWRnZVJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5yYWlzZUludGVudEJyaWRnZVJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJSYWlzZUludGVudEJyaWRnZVJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9SYWlzZUludGVudEJyaWRnZVJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJSYWlzZUludGVudEJyaWRnZVJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucmFpc2VJbnRlbnRCcmlkZ2VSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlJhaXNlSW50ZW50QnJpZGdlUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9SYWlzZUludGVudFJlc3VsdEFnZW50RXJyb3JSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5yYWlzZUludGVudFJlc3VsdEFnZW50RXJyb3JSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUmFpc2VJbnRlbnRSZXN1bHRBZ2VudFJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJSYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5yYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJSYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9SYWlzZUludGVudFJlc3VsdEJyaWRnZUVycm9yUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlRXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnJhaXNlSW50ZW50UmVzdWx0QnJpZGdlRXJyb3JSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlRXJyb3JSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1JhaXNlSW50ZW50UmVzdWx0QnJpZGdlUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5yYWlzZUludGVudFJlc3VsdEJyaWRnZVJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0NvbnRleHQgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkNvbnRleHRcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5jb250ZXh0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQ29udGV4dFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgcmV0dXJuIENvbnZlcnQ7XG59KCkpO1xuZnVuY3Rpb24gaW52YWxpZFZhbHVlJDEodHlwLCB2YWwsIGtleSwgcGFyZW50KSB7XG4gICAgaWYgKHBhcmVudCA9PT0gdm9pZCAwKSB7IHBhcmVudCA9ICcnOyB9XG4gICAgdmFyIHByZXR0eVR5cCA9IHByZXR0eVR5cGVOYW1lJDEodHlwKTtcbiAgICB2YXIgcGFyZW50VGV4dCA9IHBhcmVudCA/IFwiIG9uIFwiLmNvbmNhdChwYXJlbnQpIDogJyc7XG4gICAgdmFyIGtleVRleHQgPSBrZXkgPyBcIiBmb3Iga2V5IFxcXCJcIi5jb25jYXQoa2V5LCBcIlxcXCJcIikgOiAnJztcbiAgICB0aHJvdyBFcnJvcihcIkludmFsaWQgdmFsdWVcIi5jb25jYXQoa2V5VGV4dCkuY29uY2F0KHBhcmVudFRleHQsIFwiLiBFeHBlY3RlZCBcIikuY29uY2F0KHByZXR0eVR5cCwgXCIgYnV0IGdvdCBcIikuY29uY2F0KEpTT04uc3RyaW5naWZ5KHZhbCkpKTtcbn1cbmZ1bmN0aW9uIHByZXR0eVR5cGVOYW1lJDEodHlwKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodHlwKSkge1xuICAgICAgICBpZiAodHlwLmxlbmd0aCA9PT0gMiAmJiB0eXBbMF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIFwiYW4gb3B0aW9uYWwgXCIuY29uY2F0KHByZXR0eVR5cGVOYW1lJDEodHlwWzFdKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gXCJvbmUgb2YgW1wiLmNvbmNhdCh0eXAubWFwKGZ1bmN0aW9uIChhKSB7IHJldHVybiBwcmV0dHlUeXBlTmFtZSQxKGEpOyB9KS5qb2luKFwiLCBcIiksIFwiXVwiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgdHlwID09PSBcIm9iamVjdFwiICYmIHR5cC5saXRlcmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHR5cC5saXRlcmFsO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB0eXA7XG4gICAgfVxufVxuZnVuY3Rpb24ganNvblRvSlNQcm9wcyQxKHR5cCkge1xuICAgIGlmICh0eXAuanNvblRvSlMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB2YXIgbWFwXzEgPSB7fTtcbiAgICAgICAgdHlwLnByb3BzLmZvckVhY2goZnVuY3Rpb24gKHApIHsgcmV0dXJuIG1hcF8xW3AuanNvbl0gPSB7IGtleTogcC5qcywgdHlwOiBwLnR5cCB9OyB9KTtcbiAgICAgICAgdHlwLmpzb25Ub0pTID0gbWFwXzE7XG4gICAgfVxuICAgIHJldHVybiB0eXAuanNvblRvSlM7XG59XG5mdW5jdGlvbiBqc1RvSlNPTlByb3BzJDEodHlwKSB7XG4gICAgaWYgKHR5cC5qc1RvSlNPTiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHZhciBtYXBfMiA9IHt9O1xuICAgICAgICB0eXAucHJvcHMuZm9yRWFjaChmdW5jdGlvbiAocCkgeyByZXR1cm4gbWFwXzJbcC5qc10gPSB7IGtleTogcC5qc29uLCB0eXA6IHAudHlwIH07IH0pO1xuICAgICAgICB0eXAuanNUb0pTT04gPSBtYXBfMjtcbiAgICB9XG4gICAgcmV0dXJuIHR5cC5qc1RvSlNPTjtcbn1cbmZ1bmN0aW9uIHRyYW5zZm9ybSQxKHZhbCwgdHlwLCBnZXRQcm9wcywga2V5LCBwYXJlbnQpIHtcbiAgICBpZiAoa2V5ID09PSB2b2lkIDApIHsga2V5ID0gJyc7IH1cbiAgICBpZiAocGFyZW50ID09PSB2b2lkIDApIHsgcGFyZW50ID0gJyc7IH1cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm1QcmltaXRpdmUodHlwLCB2YWwpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0eXAgPT09IHR5cGVvZiB2YWwpXG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlJDEodHlwLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtVW5pb24odHlwcywgdmFsKSB7XG4gICAgICAgIC8vIHZhbCBtdXN0IHZhbGlkYXRlIGFnYWluc3Qgb25lIHR5cCBpbiB0eXBzXG4gICAgICAgIHZhciBsID0gdHlwcy5sZW5ndGg7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHlwXzEgPSB0eXBzW2ldO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhbnNmb3JtJDEodmFsLCB0eXBfMSwgZ2V0UHJvcHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKF8pIHsgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUkMSh0eXBzLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtRW51bShjYXNlcywgdmFsKSB7XG4gICAgICAgIGlmIChjYXNlcy5pbmRleE9mKHZhbCkgIT09IC0xKVxuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgcmV0dXJuIGludmFsaWRWYWx1ZSQxKGNhc2VzLm1hcChmdW5jdGlvbiAoYSkgeyByZXR1cm4gbCQxKGEpOyB9KSwgdmFsLCBrZXksIHBhcmVudCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybUFycmF5KHR5cCwgdmFsKSB7XG4gICAgICAgIC8vIHZhbCBtdXN0IGJlIGFuIGFycmF5IHdpdGggbm8gaW52YWxpZCBlbGVtZW50c1xuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkodmFsKSlcbiAgICAgICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUkMShsJDEoXCJhcnJheVwiKSwgdmFsLCBrZXksIHBhcmVudCk7XG4gICAgICAgIHJldHVybiB2YWwubWFwKGZ1bmN0aW9uIChlbCkgeyByZXR1cm4gdHJhbnNmb3JtJDEoZWwsIHR5cCwgZ2V0UHJvcHMpOyB9KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtRGF0ZSh2YWwpIHtcbiAgICAgICAgaWYgKHZhbCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGQgPSBuZXcgRGF0ZSh2YWwpO1xuICAgICAgICBpZiAoaXNOYU4oZC52YWx1ZU9mKCkpKSB7XG4gICAgICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlJDEobCQxKFwiRGF0ZVwiKSwgdmFsLCBrZXksIHBhcmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGQ7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybU9iamVjdChwcm9wcywgYWRkaXRpb25hbCwgdmFsKSB7XG4gICAgICAgIGlmICh2YWwgPT09IG51bGwgfHwgdHlwZW9mIHZhbCAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KHZhbCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUkMShsJDEocmVmIHx8IFwib2JqZWN0XCIpLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHByb3BzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHZhciBwcm9wID0gcHJvcHNba2V5XTtcbiAgICAgICAgICAgIHZhciB2ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbCwga2V5KSA/IHZhbFtrZXldIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgcmVzdWx0W3Byb3Aua2V5XSA9IHRyYW5zZm9ybSQxKHYsIHByb3AudHlwLCBnZXRQcm9wcywga2V5LCByZWYpO1xuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModmFsKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHByb3BzLCBrZXkpKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB0cmFuc2Zvcm0kMSh2YWxba2V5XSwgYWRkaXRpb25hbCwgZ2V0UHJvcHMsIGtleSwgcmVmKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIGlmICh0eXAgPT09IFwiYW55XCIpXG4gICAgICAgIHJldHVybiB2YWw7XG4gICAgaWYgKHR5cCA9PT0gbnVsbCkge1xuICAgICAgICBpZiAodmFsID09PSBudWxsKVxuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgcmV0dXJuIGludmFsaWRWYWx1ZSQxKHR5cCwgdmFsLCBrZXksIHBhcmVudCk7XG4gICAgfVxuICAgIGlmICh0eXAgPT09IGZhbHNlKVxuICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlJDEodHlwLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB2YXIgcmVmID0gdW5kZWZpbmVkO1xuICAgIHdoaWxlICh0eXBlb2YgdHlwID09PSBcIm9iamVjdFwiICYmIHR5cC5yZWYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZWYgPSB0eXAucmVmO1xuICAgICAgICB0eXAgPSB0eXBlTWFwJDFbdHlwLnJlZl07XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KHR5cCkpXG4gICAgICAgIHJldHVybiB0cmFuc2Zvcm1FbnVtKHR5cCwgdmFsKTtcbiAgICBpZiAodHlwZW9mIHR5cCA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICByZXR1cm4gdHlwLmhhc093blByb3BlcnR5KFwidW5pb25NZW1iZXJzXCIpID8gdHJhbnNmb3JtVW5pb24odHlwLnVuaW9uTWVtYmVycywgdmFsKVxuICAgICAgICAgICAgOiB0eXAuaGFzT3duUHJvcGVydHkoXCJhcnJheUl0ZW1zXCIpID8gdHJhbnNmb3JtQXJyYXkodHlwLmFycmF5SXRlbXMsIHZhbClcbiAgICAgICAgICAgICAgICA6IHR5cC5oYXNPd25Qcm9wZXJ0eShcInByb3BzXCIpID8gdHJhbnNmb3JtT2JqZWN0KGdldFByb3BzKHR5cCksIHR5cC5hZGRpdGlvbmFsLCB2YWwpXG4gICAgICAgICAgICAgICAgICAgIDogaW52YWxpZFZhbHVlJDEodHlwLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB9XG4gICAgLy8gTnVtYmVycyBjYW4gYmUgcGFyc2VkIGJ5IERhdGUgYnV0IHNob3VsZG4ndCBiZS5cbiAgICBpZiAodHlwID09PSBEYXRlICYmIHR5cGVvZiB2YWwgIT09IFwibnVtYmVyXCIpXG4gICAgICAgIHJldHVybiB0cmFuc2Zvcm1EYXRlKHZhbCk7XG4gICAgcmV0dXJuIHRyYW5zZm9ybVByaW1pdGl2ZSh0eXAsIHZhbCk7XG59XG5mdW5jdGlvbiBjYXN0JDEodmFsLCB0eXApIHtcbiAgICByZXR1cm4gdHJhbnNmb3JtJDEodmFsLCB0eXAsIGpzb25Ub0pTUHJvcHMkMSk7XG59XG5mdW5jdGlvbiB1bmNhc3QkMSh2YWwsIHR5cCkge1xuICAgIHJldHVybiB0cmFuc2Zvcm0kMSh2YWwsIHR5cCwganNUb0pTT05Qcm9wcyQxKTtcbn1cbmZ1bmN0aW9uIGwkMSh0eXApIHtcbiAgICByZXR1cm4geyBsaXRlcmFsOiB0eXAgfTtcbn1cbmZ1bmN0aW9uIGEkMSh0eXApIHtcbiAgICByZXR1cm4geyBhcnJheUl0ZW1zOiB0eXAgfTtcbn1cbmZ1bmN0aW9uIHUkMSgpIHtcbiAgICB2YXIgdHlwcyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHR5cHNbX2ldID0gYXJndW1lbnRzW19pXTtcbiAgICB9XG4gICAgcmV0dXJuIHsgdW5pb25NZW1iZXJzOiB0eXBzIH07XG59XG5mdW5jdGlvbiBvJDEocHJvcHMsIGFkZGl0aW9uYWwpIHtcbiAgICByZXR1cm4geyBwcm9wczogcHJvcHMsIGFkZGl0aW9uYWw6IGFkZGl0aW9uYWwgfTtcbn1cbmZ1bmN0aW9uIG0kMShhZGRpdGlvbmFsKSB7XG4gICAgcmV0dXJuIHsgcHJvcHM6IFtdLCBhZGRpdGlvbmFsOiBhZGRpdGlvbmFsIH07XG59XG5mdW5jdGlvbiByJDEobmFtZSkge1xuICAgIHJldHVybiB7IHJlZjogbmFtZSB9O1xufVxudmFyIHR5cGVNYXAkMSA9IHtcbiAgICBcIkFnZW50RXJyb3JSZXNwb25zZU1lc3NhZ2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkFnZW50UmVzcG9uc2VNZXRhZGF0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRXJyb3JSZXNwb25zZU1lc3NhZ2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJSZXNwb25zZU1lc3NhZ2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQWdlbnRSZXNwb25zZU1ldGFkYXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkVycm9yUmVzcG9uc2VNZXNzYWdlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiByJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJBZ2VudFJlcXVlc3RNZXNzYWdlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJBZ2VudFJlcXVlc3RNZXRhZGF0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogbSQxKFwiYW55XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJSZXF1ZXN0TWVzc2FnZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJBZ2VudFJlcXVlc3RNZXRhZGF0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJCcmlkZ2VQYXJ0aWNpcGFudElkZW50aWZpZXJcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJTb3VyY2VJZGVudGlmaWVyXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJCcmlkZ2VQYXJ0aWNpcGFudElkZW50aWZpZXJcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudFwiLCBqczogXCJkZXNrdG9wQWdlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJhcHBJZFwiLCBqczogXCJhcHBJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiU291cmNlSWRlbnRpZmllclwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSWRcIiwganM6IFwiYXBwSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiZGVza3RvcEFnZW50XCIsIGpzOiBcImRlc2t0b3BBZ2VudFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQWdlbnRSZXNwb25zZU1lc3NhZ2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkFnZW50UmVzcG9uc2VNZXRhZGF0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogbSQxKFwiYW55XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJSZXNwb25zZU1lc3NhZ2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQnJpZGdlRXJyb3JSZXNwb25zZU1lc3NhZ2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkJyaWRnZUVycm9yUmVzcG9uc2VNZXNzYWdlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUmVzcG9uc2VFcnJvck1lc3NhZ2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQnJpZGdlRXJyb3JSZXNwb25zZU1lc3NhZ2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvckRldGFpbHNcIiwganM6IFwiZXJyb3JEZXRhaWxzXCIsIHR5cDogYSQxKHIkMShcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJlcnJvclNvdXJjZXNcIiwganM6IFwiZXJyb3JTb3VyY2VzXCIsIHR5cDogYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudFwiLCBqczogXCJkZXNrdG9wQWdlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJSZXNwb25zZUVycm9yTWVzc2FnZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yXCIsIGpzOiBcImVycm9yXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkJyaWRnZVJlcXVlc3RNZXNzYWdlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJCcmlkZ2VSZXF1ZXN0TWV0YWRhdGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IG0kMShcImFueVwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkJyaWRnZVJlcXVlc3RNZXRhZGF0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJCcmlkZ2VQYXJ0aWNpcGFudElkZW50aWZpZXJcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJCcmlkZ2VQYXJ0aWNpcGFudElkZW50aWZpZXJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQnJpZGdlUmVzcG9uc2VNZXNzYWdlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJCcmlkZ2VSZXNwb25zZU1lc3NhZ2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiBtJDEoXCJhbnlcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IFwiXCIgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJCcmlkZ2VSZXNwb25zZU1lc3NhZ2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvckRldGFpbHNcIiwganM6IFwiZXJyb3JEZXRhaWxzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZXNcIiwganM6IFwic291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQnJvYWRjYXN0QWdlbnRSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJCcm9hZGNhc3RBZ2VudFJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJCcm9hZGNhc3RBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJCcm9hZGNhc3RBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQnJvYWRjYXN0QWdlbnRSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogciQxKFwiU291cmNlT2JqZWN0XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlNvdXJjZU9iamVjdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSWRcIiwganM6IFwiYXBwSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJkZXNrdG9wQWdlbnRcIiwganM6IFwiZGVza3RvcEFnZW50XCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RhbmNlSWRcIiwganM6IFwiaW5zdGFuY2VJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJCcm9hZGNhc3RBZ2VudFJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjaGFubmVsSWRcIiwganM6IFwiY2hhbm5lbElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogciQxKFwiQ29udGV4dEVsZW1lbnRcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb250ZXh0RWxlbWVudFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBtJDEoXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQnJvYWRjYXN0QnJpZGdlUmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiQnJvYWRjYXN0QnJpZGdlUmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkJyb2FkY2FzdEJyaWRnZVJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJCcm9hZGNhc3RBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQnJvYWRjYXN0QnJpZGdlUmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIk1ldGFTb3VyY2VcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiTWV0YVNvdXJjZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSWRcIiwganM6IFwiYXBwSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJkZXNrdG9wQWdlbnRcIiwganM6IFwiZGVza3RvcEFnZW50XCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiaW5zdGFuY2VJZFwiLCBqczogXCJpbnN0YW5jZUlkXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkJyb2FkY2FzdEJyaWRnZVJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjaGFubmVsSWRcIiwganM6IFwiY2hhbm5lbElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogciQxKFwiQ29udGV4dEVsZW1lbnRcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW9uU3RlcE1lc3NhZ2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkNvbm5lY3Rpb25TdGVwTWV0YWRhdGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IG0kMShcImFueVwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXBNZXNzYWdlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwTWV0YWRhdGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW9uU3RlcDJIZWxsb1wiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXAySGVsbG9NZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJDb25uZWN0aW9uU3RlcDJIZWxsb1BheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkNvbm5lY3Rpb25TdGVwMkhlbGxvVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwMkhlbGxvTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW9uU3RlcDJIZWxsb1BheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImF1dGhSZXF1aXJlZFwiLCBqczogXCJhdXRoUmVxdWlyZWRcIiwgdHlwOiB0cnVlIH0sXG4gICAgICAgIHsganNvbjogXCJhdXRoVG9rZW5cIiwganM6IFwiYXV0aFRva2VuXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudEJyaWRnZVZlcnNpb25cIiwganM6IFwiZGVza3RvcEFnZW50QnJpZGdlVmVyc2lvblwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInN1cHBvcnRlZEZEQzNWZXJzaW9uc1wiLCBqczogXCJzdXBwb3J0ZWRGREMzVmVyc2lvbnNcIiwgdHlwOiBhJDEoXCJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW9uU3RlcDNIYW5kc2hha2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkNvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkNvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkNvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW9uU3RlcDNIYW5kc2hha2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQ29ubmVjdGlvblN0ZXAzSGFuZHNoYWtlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXV0aFRva2VuXCIsIGpzOiBcImF1dGhUb2tlblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJjaGFubmVsc1N0YXRlXCIsIGpzOiBcImNoYW5uZWxzU3RhdGVcIiwgdHlwOiBtJDEoYSQxKHIkMShcIkNvbnRleHRFbGVtZW50XCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImltcGxlbWVudGF0aW9uTWV0YWRhdGFcIiwganM6IFwiaW1wbGVtZW50YXRpb25NZXRhZGF0YVwiLCB0eXA6IHIkMShcIkNvbm5lY3RpbmdBZ2VudEltcGxlbWVudGF0aW9uTWV0YWRhdGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RlZE5hbWVcIiwganM6IFwicmVxdWVzdGVkTmFtZVwiLCB0eXA6IFwiXCIgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW5nQWdlbnRJbXBsZW1lbnRhdGlvbk1ldGFkYXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJmZGMzVmVyc2lvblwiLCBqczogXCJmZGMzVmVyc2lvblwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcIm9wdGlvbmFsRmVhdHVyZXNcIiwganM6IFwib3B0aW9uYWxGZWF0dXJlc1wiLCB0eXA6IHIkMShcIk9wdGlvbmFsRmVhdHVyZXNcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInByb3ZpZGVyXCIsIGpzOiBcInByb3ZpZGVyXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicHJvdmlkZXJWZXJzaW9uXCIsIGpzOiBcInByb3ZpZGVyVmVyc2lvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3B0aW9uYWxGZWF0dXJlc1wiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiRGVza3RvcEFnZW50QnJpZGdpbmdcIiwganM6IFwiRGVza3RvcEFnZW50QnJpZGdpbmdcIiwgdHlwOiB0cnVlIH0sXG4gICAgICAgIHsganNvbjogXCJPcmlnaW5hdGluZ0FwcE1ldGFkYXRhXCIsIGpzOiBcIk9yaWdpbmF0aW5nQXBwTWV0YWRhdGFcIiwgdHlwOiB0cnVlIH0sXG4gICAgICAgIHsganNvbjogXCJVc2VyQ2hhbm5lbE1lbWJlcnNoaXBBUElzXCIsIGpzOiBcIlVzZXJDaGFubmVsTWVtYmVyc2hpcEFQSXNcIiwgdHlwOiB0cnVlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQ29ubmVjdGlvblN0ZXA0QXV0aGVudGljYXRpb25GYWlsZWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkNvbm5lY3Rpb25TdGVwNEF1dGhlbnRpY2F0aW9uRmFpbGVkTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXA0QXV0aGVudGljYXRpb25GYWlsZWRQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJDb25uZWN0aW9uU3RlcDRBdXRoZW50aWNhdGlvbkZhaWxlZFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW9uU3RlcDRBdXRoZW50aWNhdGlvbkZhaWxlZE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQ29ubmVjdGlvblN0ZXA0QXV0aGVudGljYXRpb25GYWlsZWRQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXNzYWdlXCIsIGpzOiBcIm1lc3NhZ2VcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwNkNvbm5lY3RlZEFnZW50c1VwZGF0ZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwNkNvbm5lY3RlZEFnZW50c1VwZGF0ZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYWRkQWdlbnRcIiwganM6IFwiYWRkQWdlbnRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiYWxsQWdlbnRzXCIsIGpzOiBcImFsbEFnZW50c1wiLCB0eXA6IGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJbXBsZW1lbnRhdGlvbk1ldGFkYXRhXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiY2hhbm5lbHNTdGF0ZVwiLCBqczogXCJjaGFubmVsc1N0YXRlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgbSQxKGEkMShyJDEoXCJDb250ZXh0RWxlbWVudFwiKSkpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVtb3ZlQWdlbnRcIiwganM6IFwicmVtb3ZlQWdlbnRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkRlc2t0b3BBZ2VudEltcGxlbWVudGF0aW9uTWV0YWRhdGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudFwiLCBqczogXCJkZXNrdG9wQWdlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJmZGMzVmVyc2lvblwiLCBqczogXCJmZGMzVmVyc2lvblwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcIm9wdGlvbmFsRmVhdHVyZXNcIiwganM6IFwib3B0aW9uYWxGZWF0dXJlc1wiLCB0eXA6IHIkMShcIk9wdGlvbmFsRmVhdHVyZXNcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInByb3ZpZGVyXCIsIGpzOiBcInByb3ZpZGVyXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicHJvdmlkZXJWZXJzaW9uXCIsIGpzOiBcInByb3ZpZGVyVmVyc2lvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIkVycm9yTWVzc2FnZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNBZ2VudFJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnN0YW5jZXNBZ2VudFJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW5zdGFuY2VzQWdlbnRSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJEZXN0aW5hdGlvbk9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIlNvdXJjZUlkZW50aWZpZXJcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkRlc3RpbmF0aW9uT2JqZWN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXNrdG9wQWdlbnRcIiwganM6IFwiZGVza3RvcEFnZW50XCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiYXBwSWRcIiwganM6IFwiYXBwSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaW5zdGFuY2VJZFwiLCBqczogXCJpbnN0YW5jZUlkXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNBZ2VudFJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBcIiwganM6IFwiYXBwXCIsIHR5cDogciQxKFwiQXBwSWRlbnRpZmllclwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkFwcElkZW50aWZpZXJcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcElkXCIsIGpzOiBcImFwcElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiZGVza3RvcEFnZW50XCIsIGpzOiBcImRlc2t0b3BBZ2VudFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiRmluZEluc3RhbmNlc0FnZW50UmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnN0YW5jZXNBZ2VudFJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0FnZW50UmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNBZ2VudFJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW5zdGFuY2VzQWdlbnRSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcElkZW50aWZpZXJzXCIsIGpzOiBcImFwcElkZW50aWZpZXJzXCIsIHR5cDogYSQxKHIkMShcIkFwcE1ldGFkYXRhXCIpKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkFwcE1ldGFkYXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBJZFwiLCBqczogXCJhcHBJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImRlc2NyaXB0aW9uXCIsIGpzOiBcImRlc2NyaXB0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudFwiLCBqczogXCJkZXNrdG9wQWdlbnRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWNvbnNcIiwganM6IFwiaWNvbnNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiSWNvblwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaW5zdGFuY2VNZXRhZGF0YVwiLCBqczogXCJpbnN0YW5jZU1ldGFkYXRhXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgbSQxKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3VsdFR5cGVcIiwganM6IFwicmVzdWx0VHlwZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHUkMShudWxsLCBcIlwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInNjcmVlbnNob3RzXCIsIGpzOiBcInNjcmVlbnNob3RzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkltYWdlXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpdGxlXCIsIGpzOiBcInRpdGxlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRvb2x0aXBcIiwganM6IFwidG9vbHRpcFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ2ZXJzaW9uXCIsIGpzOiBcInZlcnNpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkljb25cIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInNpemVcIiwganM6IFwic2l6ZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJzcmNcIiwganM6IFwic3JjXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJJbWFnZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibGFiZWxcIiwganM6IFwibGFiZWxcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwic2l6ZVwiLCBqczogXCJzaXplXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInNyY1wiLCBqczogXCJzcmNcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNCcmlkZ2VFcnJvclJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnN0YW5jZXNCcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW5zdGFuY2VzQnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEluc3RhbmNlc0JyaWRnZUVycm9yUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIkVycm9yTWVzc2FnZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNCcmlkZ2VSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQnJpZGdlUmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnN0YW5jZXNCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW5zdGFuY2VzQnJpZGdlUmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiRGVzdGluYXRpb25PYmplY3RcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJNZXRhU291cmNlT2JqZWN0XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk1ldGFTb3VyY2VPYmplY3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcElkXCIsIGpzOiBcImFwcElkXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudFwiLCBqczogXCJkZXNrdG9wQWdlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiRmluZEluc3RhbmNlc0JyaWRnZVJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBcIiwganM6IFwiYXBwXCIsIHR5cDogciQxKFwiQXBwSWRlbnRpZmllclwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNCcmlkZ2VSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW5zdGFuY2VzQnJpZGdlUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvckRldGFpbHNcIiwganM6IFwiZXJyb3JEZXRhaWxzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZXNcIiwganM6IFwic291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSWRlbnRpZmllcnNcIiwganM6IFwiYXBwSWRlbnRpZmllcnNcIiwgdHlwOiBhJDEociQxKFwiQXBwTWV0YWRhdGFcIikpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIkVycm9yTWVzc2FnZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRBZ2VudFJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRBZ2VudFJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50QWdlbnRSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEludGVudEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50QWdlbnRSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiU291cmNlSWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkJyaWRnZVBhcnRpY2lwYW50SWRlbnRpZmllclwiKSkgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50QWdlbnRSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiQ29udGV4dEVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRcIiwganM6IFwiaW50ZW50XCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzdWx0VHlwZVwiLCBqczogXCJyZXN1bHRUeXBlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50QWdlbnRSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRmluZEludGVudEFnZW50UmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50QWdlbnRSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEFnZW50UmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRBZ2VudFJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSW50ZW50XCIsIGpzOiBcImFwcEludGVudFwiLCB0eXA6IHIkMShcIkFwcEludGVudFwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkFwcEludGVudFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwc1wiLCBqczogXCJhcHBzXCIsIHR5cDogYSQxKHIkMShcIkFwcE1ldGFkYXRhXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiaW50ZW50XCIsIGpzOiBcImludGVudFwiLCB0eXA6IHIkMShcIkludGVudE1ldGFkYXRhXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiSW50ZW50TWV0YWRhdGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRpc3BsYXlOYW1lXCIsIGpzOiBcImRpc3BsYXlOYW1lXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEJyaWRnZUVycm9yUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIkVycm9yTWVzc2FnZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRCcmlkZ2VSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50QnJpZGdlUmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEludGVudEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50QnJpZGdlUmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIkJyaWRnZVBhcnRpY2lwYW50SWRlbnRpZmllclwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiQnJpZGdlUGFydGljaXBhbnRJZGVudGlmaWVyXCIpKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiQ29udGV4dEVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRcIiwganM6IFwiaW50ZW50XCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzdWx0VHlwZVwiLCBqczogXCJyZXN1bHRUeXBlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50QnJpZGdlUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRCcmlkZ2VSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRCcmlkZ2VSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEJyaWRnZVJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JEZXRhaWxzXCIsIGpzOiBcImVycm9yRGV0YWlsc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VzXCIsIGpzOiBcInNvdXJjZXNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRCcmlkZ2VSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcEludGVudFwiLCBqczogXCJhcHBJbnRlbnRcIiwgdHlwOiByJDEoXCJBcHBJbnRlbnRcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50RXJyb3JSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudEVycm9yUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yXCIsIGpzOiBcImVycm9yXCIsIHR5cDogciQxKFwiRXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIlNvdXJjZU9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkJyaWRnZVBhcnRpY2lwYW50SWRlbnRpZmllclwiKSkgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHIkMShcIkNvbnRleHRFbGVtZW50XCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcEludGVudHNcIiwganM6IFwiYXBwSW50ZW50c1wiLCB0eXA6IGEkMShyJDEoXCJBcHBJbnRlbnRcIikpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VFcnJvclJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZUVycm9yUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZUVycm9yUmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZUVycm9yUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvckRldGFpbHNcIiwganM6IFwiZXJyb3JEZXRhaWxzXCIsIHR5cDogYSQxKHIkMShcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJlcnJvclNvdXJjZXNcIiwganM6IFwiZXJyb3JTb3VyY2VzXCIsIHR5cDogYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlRXJyb3JSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yXCIsIGpzOiBcImVycm9yXCIsIHR5cDogciQxKFwiRXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJNZXRhU291cmNlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJCcmlkZ2VQYXJ0aWNpcGFudElkZW50aWZpZXJcIikpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogciQxKFwiQ29udGV4dEVsZW1lbnRcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvckRldGFpbHNcIiwganM6IFwiZXJyb3JEZXRhaWxzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZXNcIiwganM6IFwic291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcEludGVudHNcIiwganM6IFwiYXBwSW50ZW50c1wiLCB0eXA6IGEkMShyJDEoXCJBcHBJbnRlbnRcIikpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIkVycm9yTWVzc2FnZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkRlc3RpbmF0aW9uT2JqZWN0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiU291cmNlSWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBcIiwganM6IFwiYXBwXCIsIHR5cDogciQxKFwiQXBwRGVzdGluYXRpb25JZGVudGlmaWVyXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQXBwRGVzdGluYXRpb25JZGVudGlmaWVyXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXNrdG9wQWdlbnRcIiwganM6IFwiZGVza3RvcEFnZW50XCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiYXBwSWRcIiwganM6IFwiYXBwSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcE1ldGFkYXRhXCIsIGpzOiBcImFwcE1ldGFkYXRhXCIsIHR5cDogciQxKFwiQXBwTWV0YWRhdGFcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUJyaWRnZUVycm9yUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiByJDEoXCJFcnJvck1lc3NhZ2VcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUJyaWRnZVJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQnJpZGdlUmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQnJpZGdlUmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQnJpZGdlUmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiRGVzdGluYXRpb25PYmplY3RcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJNZXRhU291cmNlT2JqZWN0XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQnJpZGdlUmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcFwiLCBqczogXCJhcHBcIiwgdHlwOiByJDEoXCJBcHBEZXN0aW5hdGlvbklkZW50aWZpZXJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUJyaWRnZVJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJHZXRBcHBNZXRhZGF0YUJyaWRnZVJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQnJpZGdlUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvckRldGFpbHNcIiwganM6IFwiZXJyb3JEZXRhaWxzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZXNcIiwganM6IFwic291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcE1ldGFkYXRhXCIsIGpzOiBcImFwcE1ldGFkYXRhXCIsIHR5cDogciQxKFwiQXBwTWV0YWRhdGFcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQWdlbnRFcnJvclJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJPcGVuQWdlbnRFcnJvclJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiT3BlbkFnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIk9wZW5BZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkFnZW50RXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkFnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yXCIsIGpzOiBcImVycm9yXCIsIHR5cDogciQxKFwiT3BlbkVycm9yTWVzc2FnZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5BZ2VudFJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIk9wZW5BZ2VudFJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJPcGVuQWdlbnRSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiT3BlbkFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQWdlbnRSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJEZXN0aW5hdGlvbk9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIlNvdXJjZU9iamVjdFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQWdlbnRSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwXCIsIGpzOiBcImFwcFwiLCB0eXA6IHIkMShcIkFwcFRvT3BlblwiKSB9LFxuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiQ29udGV4dEVsZW1lbnRcIikpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQXBwVG9PcGVuXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXNrdG9wQWdlbnRcIiwganM6IFwiZGVza3RvcEFnZW50XCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiYXBwSWRcIiwganM6IFwiYXBwSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiT3BlbkFnZW50UmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIk9wZW5BZ2VudFJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiT3BlbkFnZW50UmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJPcGVuQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5BZ2VudFJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQWdlbnRSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcElkZW50aWZpZXJcIiwganM6IFwiYXBwSWRlbnRpZmllclwiLCB0eXA6IHIkMShcIkFwcElkZW50aWZpZXJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQnJpZGdlRXJyb3JSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiT3BlbkJyaWRnZUVycm9yUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJPcGVuQnJpZGdlRXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIk9wZW5BZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkJyaWRnZUVycm9yUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvckRldGFpbHNcIiwganM6IFwiZXJyb3JEZXRhaWxzXCIsIHR5cDogYSQxKHIkMShcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJlcnJvclNvdXJjZXNcIiwganM6IFwiZXJyb3JTb3VyY2VzXCIsIHR5cDogYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5CcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiByJDEoXCJPcGVuRXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkJyaWRnZVJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIk9wZW5CcmlkZ2VSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiT3BlbkJyaWRnZVJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJPcGVuQWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5CcmlkZ2VSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJEZXN0aW5hdGlvbk9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIk1ldGFTb3VyY2VcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkJyaWRnZVJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBcIiwganM6IFwiYXBwXCIsIHR5cDogciQxKFwiQXBwVG9PcGVuXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJDb250ZXh0RWxlbWVudFwiKSkgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQnJpZGdlUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIk9wZW5CcmlkZ2VSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIk9wZW5CcmlkZ2VSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIk9wZW5BZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkJyaWRnZVJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JEZXRhaWxzXCIsIGpzOiBcImVycm9yRGV0YWlsc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VzXCIsIGpzOiBcInNvdXJjZXNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5CcmlkZ2VSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcElkZW50aWZpZXJcIiwganM6IFwiYXBwSWRlbnRpZmllclwiLCB0eXA6IHIkMShcIkFwcElkZW50aWZpZXJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEFnZW50UmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RBZ2VudFJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEFnZW50UmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJNZXRhRGVzdGluYXRpb25cIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJTb3VyY2VPYmplY3RcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk1ldGFEZXN0aW5hdGlvblwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVza3RvcEFnZW50XCIsIGpzOiBcImRlc2t0b3BBZ2VudFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImFwcElkXCIsIGpzOiBcImFwcElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiaW5zdGFuY2VJZFwiLCBqczogXCJpbnN0YW5jZUlkXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY2hhbm5lbElkXCIsIGpzOiBcImNoYW5uZWxJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHIkMShcIkNvbnRleHRFbGVtZW50XCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RCcmlkZ2VSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIk1ldGFEZXN0aW5hdGlvblwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIk1ldGFTb3VyY2VcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY2hhbm5lbElkXCIsIGpzOiBcImNoYW5uZWxJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHIkMShcIkNvbnRleHRFbGVtZW50XCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRBZ2VudFJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiTWV0YURlc3RpbmF0aW9uXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiU291cmNlT2JqZWN0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJsaXN0ZW5lclR5cGVcIiwganM6IFwibGlzdGVuZXJUeXBlXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyVHlwZXNcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEJyaWRnZVJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQnJpZGdlUmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQnJpZGdlUmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQnJpZGdlUmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiTWV0YURlc3RpbmF0aW9uXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogciQxKFwiTWV0YVNvdXJjZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEJyaWRnZVJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjaGFubmVsSWRcIiwganM6IFwiY2hhbm5lbElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwibGlzdGVuZXJUeXBlXCIsIGpzOiBcImxpc3RlbmVyVHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclR5cGVzXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEFnZW50UmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEFnZW50UmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRBZ2VudFJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIk1ldGFEZXN0aW5hdGlvblwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIlNvdXJjZU9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEFnZW50UmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJsaXN0ZW5lclR5cGVcIiwganM6IFwibGlzdGVuZXJUeXBlXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyVHlwZXNcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQnJpZGdlUmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEJyaWRnZVJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQnJpZGdlUmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEJyaWRnZVJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIk1ldGFEZXN0aW5hdGlvblwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIk1ldGFTb3VyY2VcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEJyaWRnZVJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjaGFubmVsSWRcIiwganM6IFwiY2hhbm5lbElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwibGlzdGVuZXJUeXBlXCIsIGpzOiBcImxpc3RlbmVyVHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclR5cGVzXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJBZ2VudFJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIk1ldGFEZXN0aW5hdGlvblwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIlNvdXJjZU9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0VHlwZVwiLCBqczogXCJjb250ZXh0VHlwZVwiLCB0eXA6IHUkMShudWxsLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJCcmlkZ2VSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQnJpZGdlUmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQnJpZGdlUmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiTWV0YURlc3RpbmF0aW9uXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogciQxKFwiTWV0YVNvdXJjZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQnJpZGdlUmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0VHlwZVwiLCBqczogXCJjb250ZXh0VHlwZVwiLCB0eXA6IHUkMShudWxsLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QWdlbnRSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEFnZW50UmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QWdlbnRSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIk1ldGFEZXN0aW5hdGlvblwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIlNvdXJjZU9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjaGFubmVsSWRcIiwganM6IFwiY2hhbm5lbElkXCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QnJpZGdlUmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RCcmlkZ2VSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RCcmlkZ2VSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJNZXRhRGVzdGluYXRpb25cIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJNZXRhU291cmNlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QnJpZGdlUmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQWdlbnRSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQWdlbnRSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJNZXRhRGVzdGluYXRpb25cIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJTb3VyY2VPYmplY3RcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUFnZW50UmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0VHlwZVwiLCBqczogXCJjb250ZXh0VHlwZVwiLCB0eXA6IHUkMShudWxsLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUJyaWRnZVJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkVSZXF1ZXN0TWV0YWRhdGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUJyaWRnZVJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRVJlcXVlc3RNZXRhZGF0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJNZXRhRGVzdGluYXRpb25cIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJNZXRhU291cmNlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUJyaWRnZVJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjaGFubmVsSWRcIiwganM6IFwiY2hhbm5lbElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiY29udGV4dFR5cGVcIiwganM6IFwiY29udGV4dFR5cGVcIiwgdHlwOiB1JDEobnVsbCwgXCJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yXCIsIGpzOiBcImVycm9yXCIsIHR5cDogciQxKFwiRXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRBZ2VudFJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QWdlbnRSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEFnZW50UmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogciQxKFwiTWV0YURlc3RpbmF0aW9uXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJTb3VyY2VPYmplY3RcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRBZ2VudFJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBcIiwganM6IFwiYXBwXCIsIHR5cDogciQxKFwiQXBwRGVzdGluYXRpb25JZGVudGlmaWVyXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiByJDEoXCJDb250ZXh0RWxlbWVudFwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaW50ZW50XCIsIGpzOiBcImludGVudFwiLCB0eXA6IFwiXCIgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEFnZW50UmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QWdlbnRSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QWdlbnRSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QWdlbnRSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRBZ2VudFJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiaW50ZW50UmVzb2x1dGlvblwiLCBqczogXCJpbnRlbnRSZXNvbHV0aW9uXCIsIHR5cDogciQxKFwiSW50ZW50UmVzb2x1dGlvblwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkludGVudFJlc29sdXRpb25cIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImludGVudFwiLCBqczogXCJpbnRlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogciQxKFwiQXBwSWRlbnRpZmllclwiKSB9LFxuICAgICAgICB7IGpzb246IFwidmVyc2lvblwiLCBqczogXCJ2ZXJzaW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEJyaWRnZUVycm9yUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiByJDEoXCJFcnJvck1lc3NhZ2VcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEJyaWRnZVJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QnJpZGdlUmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QnJpZGdlUmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QnJpZGdlUmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogciQxKFwiTWV0YURlc3RpbmF0aW9uXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJNZXRhU291cmNlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QnJpZGdlUmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcFwiLCBqczogXCJhcHBcIiwgdHlwOiByJDEoXCJBcHBEZXN0aW5hdGlvbklkZW50aWZpZXJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHIkMShcIkNvbnRleHRFbGVtZW50XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRcIiwganM6IFwiaW50ZW50XCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QnJpZGdlUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QnJpZGdlUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudEJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRCcmlkZ2VSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJlcnJvclNvdXJjZXNcIiwganM6IFwiZXJyb3JTb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlc1wiLCBqczogXCJzb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiaW50ZW50UmVzb2x1dGlvblwiLCBqczogXCJpbnRlbnRSZXNvbHV0aW9uXCIsIHR5cDogciQxKFwiSW50ZW50UmVzb2x1dGlvblwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudFJlc3VsdEFnZW50RXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudFJlc3VsdEVycm9yTWVzc2FnZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50UmVzdWx0QWdlbnRSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudFJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudFJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudFJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRSZXN1bHRcIiwganM6IFwiaW50ZW50UmVzdWx0XCIsIHR5cDogciQxKFwiSW50ZW50UmVzdWx0XCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiSW50ZW50UmVzdWx0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJDb250ZXh0RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxcIiwganM6IFwiY2hhbm5lbFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkNoYW5uZWxcIikpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQ2hhbm5lbFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGlzcGxheU1ldGFkYXRhXCIsIGpzOiBcImRpc3BsYXlNZXRhZGF0YVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkRpc3BsYXlNZXRhZGF0YVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkRpc3BsYXlNZXRhZGF0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY29sb3JcIiwganM6IFwiY29sb3JcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiZ2x5cGhcIiwganM6IFwiZ2x5cGhcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudFJlc3VsdEJyaWRnZUVycm9yUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlRXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudFJlc3VsdEVycm9yTWVzc2FnZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudFJlc3VsdEJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJlcnJvclNvdXJjZXNcIiwganM6IFwiZXJyb3JTb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlc1wiLCBqczogXCJzb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudFJlc3VsdEJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiaW50ZW50UmVzdWx0XCIsIGpzOiBcImludGVudFJlc3VsdFwiLCB0eXA6IHIkMShcIkludGVudFJlc3VsdFwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbnRleHRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgbSQxKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IFwiXCIgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIjogW1xuICAgICAgICBcIkFjY2Vzc0RlbmllZFwiLFxuICAgICAgICBcIkFnZW50RGlzY29ubmVjdGVkXCIsXG4gICAgICAgIFwiQXBwTm90Rm91bmRcIixcbiAgICAgICAgXCJBcHBUaW1lb3V0XCIsXG4gICAgICAgIFwiQ3JlYXRpb25GYWlsZWRcIixcbiAgICAgICAgXCJEZXNrdG9wQWdlbnROb3RGb3VuZFwiLFxuICAgICAgICBcIkVycm9yT25MYXVuY2hcIixcbiAgICAgICAgXCJJbnRlbnREZWxpdmVyeUZhaWxlZFwiLFxuICAgICAgICBcIkludGVudEhhbmRsZXJSZWplY3RlZFwiLFxuICAgICAgICBcIk1hbGZvcm1lZENvbnRleHRcIixcbiAgICAgICAgXCJNYWxmb3JtZWRNZXNzYWdlXCIsXG4gICAgICAgIFwiTm9BcHBzRm91bmRcIixcbiAgICAgICAgXCJOb0NoYW5uZWxGb3VuZFwiLFxuICAgICAgICBcIk5vUmVzdWx0UmV0dXJuZWRcIixcbiAgICAgICAgXCJOb3RDb25uZWN0ZWRUb0JyaWRnZVwiLFxuICAgICAgICBcIlJlc29sdmVyVGltZW91dFwiLFxuICAgICAgICBcIlJlc29sdmVyVW5hdmFpbGFibGVcIixcbiAgICAgICAgXCJSZXNwb25zZVRvQnJpZGdlVGltZWRPdXRcIixcbiAgICAgICAgXCJUYXJnZXRBcHBVbmF2YWlsYWJsZVwiLFxuICAgICAgICBcIlRhcmdldEluc3RhbmNlVW5hdmFpbGFibGVcIixcbiAgICAgICAgXCJVc2VyQ2FuY2VsbGVkUmVzb2x1dGlvblwiLFxuICAgIF0sXG4gICAgXCJSZXNwb25zZU1lc3NhZ2VUeXBlXCI6IFtcbiAgICAgICAgXCJmaW5kSW5zdGFuY2VzUmVzcG9uc2VcIixcbiAgICAgICAgXCJmaW5kSW50ZW50UmVzcG9uc2VcIixcbiAgICAgICAgXCJmaW5kSW50ZW50c0J5Q29udGV4dFJlc3BvbnNlXCIsXG4gICAgICAgIFwiZ2V0QXBwTWV0YWRhdGFSZXNwb25zZVwiLFxuICAgICAgICBcIm9wZW5SZXNwb25zZVwiLFxuICAgICAgICBcInJhaXNlSW50ZW50UmVzcG9uc2VcIixcbiAgICAgICAgXCJyYWlzZUludGVudFJlc3VsdFJlc3BvbnNlXCIsXG4gICAgXSxcbiAgICBcIlJlcXVlc3RNZXNzYWdlVHlwZVwiOiBbXG4gICAgICAgIFwiYnJvYWRjYXN0UmVxdWVzdFwiLFxuICAgICAgICBcImZpbmRJbnN0YW5jZXNSZXF1ZXN0XCIsXG4gICAgICAgIFwiZmluZEludGVudFJlcXVlc3RcIixcbiAgICAgICAgXCJmaW5kSW50ZW50c0J5Q29udGV4dFJlcXVlc3RcIixcbiAgICAgICAgXCJnZXRBcHBNZXRhZGF0YVJlcXVlc3RcIixcbiAgICAgICAgXCJvcGVuUmVxdWVzdFwiLFxuICAgICAgICBcIlByaXZhdGVDaGFubmVsLmJyb2FkY2FzdFwiLFxuICAgICAgICBcIlByaXZhdGVDaGFubmVsLmV2ZW50TGlzdGVuZXJBZGRlZFwiLFxuICAgICAgICBcIlByaXZhdGVDaGFubmVsLmV2ZW50TGlzdGVuZXJSZW1vdmVkXCIsXG4gICAgICAgIFwiUHJpdmF0ZUNoYW5uZWwub25BZGRDb250ZXh0TGlzdGVuZXJcIixcbiAgICAgICAgXCJQcml2YXRlQ2hhbm5lbC5vbkRpc2Nvbm5lY3RcIixcbiAgICAgICAgXCJQcml2YXRlQ2hhbm5lbC5vblVuc3Vic2NyaWJlXCIsXG4gICAgICAgIFwicmFpc2VJbnRlbnRSZXF1ZXN0XCIsXG4gICAgXSxcbiAgICBcIkJyb2FkY2FzdEFnZW50UmVxdWVzdFR5cGVcIjogW1xuICAgICAgICBcImJyb2FkY2FzdFJlcXVlc3RcIixcbiAgICBdLFxuICAgIFwiQ29ubmVjdGlvblN0ZXBNZXNzYWdlVHlwZVwiOiBbXG4gICAgICAgIFwiYXV0aGVudGljYXRpb25GYWlsZWRcIixcbiAgICAgICAgXCJjb25uZWN0ZWRBZ2VudHNVcGRhdGVcIixcbiAgICAgICAgXCJoYW5kc2hha2VcIixcbiAgICAgICAgXCJoZWxsb1wiLFxuICAgIF0sXG4gICAgXCJDb25uZWN0aW9uU3RlcDJIZWxsb1R5cGVcIjogW1xuICAgICAgICBcImhlbGxvXCIsXG4gICAgXSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZVR5cGVcIjogW1xuICAgICAgICBcImhhbmRzaGFrZVwiLFxuICAgIF0sXG4gICAgXCJDb25uZWN0aW9uU3RlcDRBdXRoZW50aWNhdGlvbkZhaWxlZFR5cGVcIjogW1xuICAgICAgICBcImF1dGhlbnRpY2F0aW9uRmFpbGVkXCIsXG4gICAgXSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwNkNvbm5lY3RlZEFnZW50c1VwZGF0ZVR5cGVcIjogW1xuICAgICAgICBcImNvbm5lY3RlZEFnZW50c1VwZGF0ZVwiLFxuICAgIF0sXG4gICAgXCJFcnJvck1lc3NhZ2VcIjogW1xuICAgICAgICBcIkFnZW50RGlzY29ubmVjdGVkXCIsXG4gICAgICAgIFwiRGVza3RvcEFnZW50Tm90Rm91bmRcIixcbiAgICAgICAgXCJJbnRlbnREZWxpdmVyeUZhaWxlZFwiLFxuICAgICAgICBcIk1hbGZvcm1lZENvbnRleHRcIixcbiAgICAgICAgXCJNYWxmb3JtZWRNZXNzYWdlXCIsXG4gICAgICAgIFwiTm9BcHBzRm91bmRcIixcbiAgICAgICAgXCJOb3RDb25uZWN0ZWRUb0JyaWRnZVwiLFxuICAgICAgICBcIlJlc29sdmVyVGltZW91dFwiLFxuICAgICAgICBcIlJlc29sdmVyVW5hdmFpbGFibGVcIixcbiAgICAgICAgXCJSZXNwb25zZVRvQnJpZGdlVGltZWRPdXRcIixcbiAgICAgICAgXCJUYXJnZXRBcHBVbmF2YWlsYWJsZVwiLFxuICAgICAgICBcIlRhcmdldEluc3RhbmNlVW5hdmFpbGFibGVcIixcbiAgICAgICAgXCJVc2VyQ2FuY2VsbGVkUmVzb2x1dGlvblwiLFxuICAgIF0sXG4gICAgXCJGaW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiOiBbXG4gICAgICAgIFwiZmluZEluc3RhbmNlc1Jlc3BvbnNlXCIsXG4gICAgXSxcbiAgICBcIkZpbmRJbnN0YW5jZXNBZ2VudFJlcXVlc3RUeXBlXCI6IFtcbiAgICAgICAgXCJmaW5kSW5zdGFuY2VzUmVxdWVzdFwiLFxuICAgIF0sXG4gICAgXCJGaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiOiBbXG4gICAgICAgIFwiZmluZEludGVudFJlc3BvbnNlXCIsXG4gICAgXSxcbiAgICBcIkZpbmRJbnRlbnRBZ2VudFJlcXVlc3RUeXBlXCI6IFtcbiAgICAgICAgXCJmaW5kSW50ZW50UmVxdWVzdFwiLFxuICAgIF0sXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIjogW1xuICAgICAgICBcImZpbmRJbnRlbnRzQnlDb250ZXh0UmVzcG9uc2VcIixcbiAgICBdLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlcXVlc3RUeXBlXCI6IFtcbiAgICAgICAgXCJmaW5kSW50ZW50c0J5Q29udGV4dFJlcXVlc3RcIixcbiAgICBdLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCI6IFtcbiAgICAgICAgXCJnZXRBcHBNZXRhZGF0YVJlc3BvbnNlXCIsXG4gICAgXSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXF1ZXN0VHlwZVwiOiBbXG4gICAgICAgIFwiZ2V0QXBwTWV0YWRhdGFSZXF1ZXN0XCIsXG4gICAgXSxcbiAgICBcIk9wZW5FcnJvck1lc3NhZ2VcIjogW1xuICAgICAgICBcIkFnZW50RGlzY29ubmVjdGVkXCIsXG4gICAgICAgIFwiQXBwTm90Rm91bmRcIixcbiAgICAgICAgXCJBcHBUaW1lb3V0XCIsXG4gICAgICAgIFwiRGVza3RvcEFnZW50Tm90Rm91bmRcIixcbiAgICAgICAgXCJFcnJvck9uTGF1bmNoXCIsXG4gICAgICAgIFwiTWFsZm9ybWVkQ29udGV4dFwiLFxuICAgICAgICBcIk1hbGZvcm1lZE1lc3NhZ2VcIixcbiAgICAgICAgXCJOb3RDb25uZWN0ZWRUb0JyaWRnZVwiLFxuICAgICAgICBcIlJlc29sdmVyVW5hdmFpbGFibGVcIixcbiAgICAgICAgXCJSZXNwb25zZVRvQnJpZGdlVGltZWRPdXRcIixcbiAgICBdLFxuICAgIFwiT3BlbkFnZW50RXJyb3JSZXNwb25zZVR5cGVcIjogW1xuICAgICAgICBcIm9wZW5SZXNwb25zZVwiLFxuICAgIF0sXG4gICAgXCJPcGVuQWdlbnRSZXF1ZXN0VHlwZVwiOiBbXG4gICAgICAgIFwib3BlblJlcXVlc3RcIixcbiAgICBdLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RBZ2VudFJlcXVlc3RUeXBlXCI6IFtcbiAgICAgICAgXCJQcml2YXRlQ2hhbm5lbC5icm9hZGNhc3RcIixcbiAgICBdLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyVHlwZXNcIjogW1xuICAgICAgICBcIm9uQWRkQ29udGV4dExpc3RlbmVyXCIsXG4gICAgICAgIFwib25EaXNjb25uZWN0XCIsXG4gICAgICAgIFwib25VbnN1YnNjcmliZVwiLFxuICAgIF0sXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdFR5cGVcIjogW1xuICAgICAgICBcIlByaXZhdGVDaGFubmVsLmV2ZW50TGlzdGVuZXJBZGRlZFwiLFxuICAgIF0sXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQWdlbnRSZXF1ZXN0VHlwZVwiOiBbXG4gICAgICAgIFwiUHJpdmF0ZUNoYW5uZWwuZXZlbnRMaXN0ZW5lclJlbW92ZWRcIixcbiAgICBdLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdFR5cGVcIjogW1xuICAgICAgICBcIlByaXZhdGVDaGFubmVsLm9uQWRkQ29udGV4dExpc3RlbmVyXCIsXG4gICAgXSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QWdlbnRSZXF1ZXN0VHlwZVwiOiBbXG4gICAgICAgIFwiUHJpdmF0ZUNoYW5uZWwub25EaXNjb25uZWN0XCIsXG4gICAgXSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUFnZW50UmVxdWVzdFR5cGVcIjogW1xuICAgICAgICBcIlByaXZhdGVDaGFubmVsLm9uVW5zdWJzY3JpYmVcIixcbiAgICBdLFxuICAgIFwiUmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCI6IFtcbiAgICAgICAgXCJyYWlzZUludGVudFJlc3BvbnNlXCIsXG4gICAgXSxcbiAgICBcIlJhaXNlSW50ZW50QWdlbnRSZXF1ZXN0VHlwZVwiOiBbXG4gICAgICAgIFwicmFpc2VJbnRlbnRSZXF1ZXN0XCIsXG4gICAgXSxcbiAgICBcIlJhaXNlSW50ZW50UmVzdWx0RXJyb3JNZXNzYWdlXCI6IFtcbiAgICAgICAgXCJBZ2VudERpc2Nvbm5lY3RlZFwiLFxuICAgICAgICBcIkludGVudEhhbmRsZXJSZWplY3RlZFwiLFxuICAgICAgICBcIk1hbGZvcm1lZE1lc3NhZ2VcIixcbiAgICAgICAgXCJOb1Jlc3VsdFJldHVybmVkXCIsXG4gICAgICAgIFwiTm90Q29ubmVjdGVkVG9CcmlkZ2VcIixcbiAgICAgICAgXCJSZXNwb25zZVRvQnJpZGdlVGltZWRPdXRcIixcbiAgICBdLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCI6IFtcbiAgICAgICAgXCJyYWlzZUludGVudFJlc3VsdFJlc3BvbnNlXCIsXG4gICAgXSxcbiAgICBcIlR5cGVcIjogW1xuICAgICAgICBcImFwcFwiLFxuICAgICAgICBcInByaXZhdGVcIixcbiAgICAgICAgXCJ1c2VyXCIsXG4gICAgXVxufTtcblxudmFyIEJyaWRnaW5nVHlwZXMgPSB7XG4gICAgX19wcm90b19fOiBudWxsLFxuICAgIENvbnZlcnQ6IENvbnZlcnQkMVxufTtcblxuLyoqXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICogQ29weXJpZ2h0IEZJTk9TIEZEQzMgY29udHJpYnV0b3JzIC0gc2VlIE5PVElDRSBmaWxlXG4gKi9cbi8qKiBDb25zdGFudHMgcmVwcmVzZW50aW5nIHRoZSBlcnJvcnMgdGhhdCBjYW4gYmUgZW5jb3VudGVyZWQgd2hlbiBjYWxsaW5nIHRoZSBgb3BlbmAgbWV0aG9kIG9uIHRoZSBEZXNrdG9wQWdlbnQgb2JqZWN0IChgZmRjM2ApLiAqL1xudmFyIE9wZW5FcnJvcjtcbihmdW5jdGlvbiAoT3BlbkVycm9yKSB7XG4gICAgLyoqIFJldHVybmVkIGlmIHRoZSBzcGVjaWZpZWQgYXBwbGljYXRpb24gaXMgbm90IGZvdW5kLiovXG4gICAgT3BlbkVycm9yW1wiQXBwTm90Rm91bmRcIl0gPSBcIkFwcE5vdEZvdW5kXCI7XG4gICAgLyoqIFJldHVybmVkIGlmIHRoZSBzcGVjaWZpZWQgYXBwbGljYXRpb24gZmFpbHMgdG8gbGF1bmNoIGNvcnJlY3RseS4qL1xuICAgIE9wZW5FcnJvcltcIkVycm9yT25MYXVuY2hcIl0gPSBcIkVycm9yT25MYXVuY2hcIjtcbiAgICAvKiogUmV0dXJuZWQgaWYgdGhlIHNwZWNpZmllZCBhcHBsaWNhdGlvbiBsYXVuY2hlcyBidXQgZmFpbHMgdG8gYWRkIGEgY29udGV4dCBsaXN0ZW5lciBpbiBvcmRlciB0byByZWNlaXZlIHRoZSBjb250ZXh0IHBhc3NlZCB0byB0aGUgYGZkYzMub3BlbmAgY2FsbC4qL1xuICAgIE9wZW5FcnJvcltcIkFwcFRpbWVvdXRcIl0gPSBcIkFwcFRpbWVvdXRcIjtcbiAgICAvKiogUmV0dXJuZWQgaWYgdGhlIEZEQzMgZGVza3RvcCBhZ2VudCBpbXBsZW1lbnRhdGlvbiBpcyBub3QgY3VycmVudGx5IGFibGUgdG8gaGFuZGxlIHRoZSByZXF1ZXN0LiovXG4gICAgT3BlbkVycm9yW1wiUmVzb2x2ZXJVbmF2YWlsYWJsZVwiXSA9IFwiUmVzb2x2ZXJVbmF2YWlsYWJsZVwiO1xuICAgIC8qKiBSZXR1cm5lZCBpZiBhIGNhbGwgdG8gdGhlIGBvcGVuYCBmdW5jdGlvbiBpcyBtYWRlIHdpdGggYW4gaW52YWxpZCBjb250ZXh0IGFyZ3VtZW50LiBDb250ZXh0cyBzaG91bGQgYmUgT2JqZWN0cyB3aXRoIGF0IGxlYXN0IGEgYHR5cGVgIGZpZWxkIHRoYXQgaGFzIGEgYHN0cmluZ2AgdmFsdWUuKi9cbiAgICBPcGVuRXJyb3JbXCJNYWxmb3JtZWRDb250ZXh0XCJdID0gXCJNYWxmb3JtZWRDb250ZXh0XCI7XG4gICAgLyoqIEBleHBlcmltZW50YWwgUmV0dXJuZWQgaWYgdGhlIHNwZWNpZmllZCBEZXNrdG9wIEFnZW50IGlzIG5vdCBmb3VuZCwgdmlhIGEgY29ubmVjdGVkIERlc2t0b3AgQWdlbnQgQnJpZGdlLiovXG4gICAgT3BlbkVycm9yW1wiRGVza3RvcEFnZW50Tm90Rm91bmRcIl0gPSBcIkRlc2t0b3BBZ2VudE5vdEZvdW5kXCI7XG59KShPcGVuRXJyb3IgfHwgKE9wZW5FcnJvciA9IHt9KSk7XG4vKiogQ29uc3RhbnRzIHJlcHJlc2VudGluZyB0aGUgZXJyb3JzIHRoYXQgY2FuIGJlIGVuY291bnRlcmVkIHdoZW4gY2FsbGluZyB0aGUgYGZpbmRJbnRlbnRgLCBgZmluZEludGVudHNCeUNvbnRleHRgLCBgcmFpc2VJbnRlbnRgIG9yIGByYWlzZUludGVudEZvckNvbnRleHRgIG1ldGhvZHMgb24gdGhlIERlc2t0b3BBZ2VudCAoYGZkYzNgKS4gKi9cbnZhciBSZXNvbHZlRXJyb3I7XG4oZnVuY3Rpb24gKFJlc29sdmVFcnJvcikge1xuICAgIC8qKiBTSE9VTEQgYmUgcmV0dXJuZWQgaWYgbm8gYXBwcyBhcmUgYXZhaWxhYmxlIHRoYXQgY2FuIHJlc29sdmUgdGhlIGludGVudCBhbmQgY29udGV4dCBjb21iaW5hdGlvbi4qL1xuICAgIFJlc29sdmVFcnJvcltcIk5vQXBwc0ZvdW5kXCJdID0gXCJOb0FwcHNGb3VuZFwiO1xuICAgIC8qKiBSZXR1cm5lZCBpZiB0aGUgRkRDMyBkZXNrdG9wIGFnZW50IGltcGxlbWVudGF0aW9uIGlzIG5vdCBjdXJyZW50bHkgYWJsZSB0byBoYW5kbGUgdGhlIHJlcXVlc3QuKi9cbiAgICBSZXNvbHZlRXJyb3JbXCJSZXNvbHZlclVuYXZhaWxhYmxlXCJdID0gXCJSZXNvbHZlclVuYXZhaWxhYmxlXCI7XG4gICAgLyoqIFJldHVybmVkIGlmIHRoZSB1c2VyIGNhbmNlbGxlZCB0aGUgcmVzb2x1dGlvbiByZXF1ZXN0LCBmb3IgZXhhbXBsZSBieSBjbG9zaW5nIG9yIGNhbmNlbGxpbmcgYSByZXNvbHZlciBVSS4qL1xuICAgIFJlc29sdmVFcnJvcltcIlVzZXJDYW5jZWxsZWRcIl0gPSBcIlVzZXJDYW5jZWxsZWRSZXNvbHV0aW9uXCI7XG4gICAgLyoqIFNIT1VMRCBiZSByZXR1cm5lZCBpZiBhIHRpbWVvdXQgY2FuY2VscyBhbiBpbnRlbnQgcmVzb2x1dGlvbiB0aGF0IHJlcXVpcmVkIHVzZXIgaW50ZXJhY3Rpb24uIFBsZWFzZSB1c2UgYFJlc29sdmVyVW5hdmFpbGFibGVgIGluc3RlYWQgZm9yIHNpdHVhdGlvbnMgd2hlcmUgYSByZXNvbHZlciBVSSBvciBzaW1pbGFyIGZhaWxzLiovXG4gICAgUmVzb2x2ZUVycm9yW1wiUmVzb2x2ZXJUaW1lb3V0XCJdID0gXCJSZXNvbHZlclRpbWVvdXRcIjtcbiAgICAvKiogUmV0dXJuZWQgaWYgYSBzcGVjaWZpZWQgdGFyZ2V0IGFwcGxpY2F0aW9uIGlzIG5vdCBhdmFpbGFibGUgb3IgYSBuZXcgaW5zdGFuY2Ugb2YgaXQgY2Fubm90IGJlIG9wZW5lZC4gKi9cbiAgICBSZXNvbHZlRXJyb3JbXCJUYXJnZXRBcHBVbmF2YWlsYWJsZVwiXSA9IFwiVGFyZ2V0QXBwVW5hdmFpbGFibGVcIjtcbiAgICAvKiogUmV0dXJuZWQgaWYgYSBzcGVjaWZpZWQgdGFyZ2V0IGFwcGxpY2F0aW9uIGluc3RhbmNlIGlzIG5vdCBhdmFpbGFibGUsIGZvciBleGFtcGxlIGJlY2F1c2UgaXQgaGFzIGJlZW4gY2xvc2VkLiAqL1xuICAgIFJlc29sdmVFcnJvcltcIlRhcmdldEluc3RhbmNlVW5hdmFpbGFibGVcIl0gPSBcIlRhcmdldEluc3RhbmNlVW5hdmFpbGFibGVcIjtcbiAgICAvKiogUmV0dXJuZWQgaWYgdGhlIGludGVudCBhbmQgY29udGV4dCBjb3VsZCBub3QgYmUgZGVsaXZlcmVkIHRvIHRoZSBzZWxlY3RlZCBhcHBsaWNhdGlvbiBvciBpbnN0YW5jZSwgZm9yIGV4YW1wbGUgYmVjYXVzZSBpdCBoYXMgbm90IGFkZGVkIGFuIGludGVudCBoYW5kbGVyIHdpdGhpbiBhIHRpbWVvdXQuKi9cbiAgICBSZXNvbHZlRXJyb3JbXCJJbnRlbnREZWxpdmVyeUZhaWxlZFwiXSA9IFwiSW50ZW50RGVsaXZlcnlGYWlsZWRcIjtcbiAgICAvKiogUmV0dXJuZWQgaWYgYSBjYWxsIHRvIG9uZSBvZiB0aGUgYHJhaXNlSW50ZW50YCBmdW5jdGlvbnMgaXMgbWFkZSB3aXRoIGFuIGludmFsaWQgY29udGV4dCBhcmd1bWVudC4gQ29udGV4dHMgc2hvdWxkIGJlIE9iamVjdHMgd2l0aCBhdCBsZWFzdCBhIGB0eXBlYCBmaWVsZCB0aGF0IGhhcyBhIGBzdHJpbmdgIHZhbHVlLiovXG4gICAgUmVzb2x2ZUVycm9yW1wiTWFsZm9ybWVkQ29udGV4dFwiXSA9IFwiTWFsZm9ybWVkQ29udGV4dFwiO1xuICAgIC8qKiBAZXhwZXJpbWVudGFsIFJldHVybmVkIGlmIHRoZSBzcGVjaWZpZWQgRGVza3RvcCBBZ2VudCBpcyBub3QgZm91bmQsIHZpYSBhIGNvbm5lY3RlZCBEZXNrdG9wIEFnZW50IEJyaWRnZS4qL1xuICAgIFJlc29sdmVFcnJvcltcIkRlc2t0b3BBZ2VudE5vdEZvdW5kXCJdID0gXCJEZXNrdG9wQWdlbnROb3RGb3VuZFwiO1xufSkoUmVzb2x2ZUVycm9yIHx8IChSZXNvbHZlRXJyb3IgPSB7fSkpO1xudmFyIFJlc3VsdEVycm9yO1xuKGZ1bmN0aW9uIChSZXN1bHRFcnJvcikge1xuICAgIC8qKiBSZXR1cm5lZCBpZiB0aGUgaW50ZW50IGhhbmRsZXIgZXhpdGVkIHdpdGhvdXQgcmV0dXJuaW5nIGEgdmFsaWQgcmVzdWx0IChhIHByb21pc2UgcmVzb2x2aW5nIHRvIGEgQ29udGV4dCwgQ2hhbm5lbCBvYmplY3Qgb3Igdm9pZCkuICovXG4gICAgUmVzdWx0RXJyb3JbXCJOb1Jlc3VsdFJldHVybmVkXCJdID0gXCJOb1Jlc3VsdFJldHVybmVkXCI7XG4gICAgLyoqIFJldHVybmVkIGlmIHRoZSBJbnRlbnQgaGFuZGxlciBmdW5jdGlvbiBwcm9jZXNzaW5nIHRoZSByYWlzZWQgaW50ZW50IHRocm93cyBhbiBlcnJvciBvciByZWplY3RzIHRoZSBQcm9taXNlIGl0IHJldHVybmVkLiAqL1xuICAgIFJlc3VsdEVycm9yW1wiSW50ZW50SGFuZGxlclJlamVjdGVkXCJdID0gXCJJbnRlbnRIYW5kbGVyUmVqZWN0ZWRcIjtcbn0pKFJlc3VsdEVycm9yIHx8IChSZXN1bHRFcnJvciA9IHt9KSk7XG52YXIgQ2hhbm5lbEVycm9yO1xuKGZ1bmN0aW9uIChDaGFubmVsRXJyb3IpIHtcbiAgICAvKiogUmV0dXJuZWQgaWYgdGhlIHNwZWNpZmllZCBjaGFubmVsIGlzIG5vdCBmb3VuZCB3aGVuIGF0dGVtcHRpbmcgdG8gam9pbiBhIGNoYW5uZWwgdmlhIHRoZSBgam9pblVzZXJDaGFubmVsYCBmdW5jdGlvbiAgb2YgdGhlIERlc2t0b3BBZ2VudCAoYGZkYzNgKS4qL1xuICAgIENoYW5uZWxFcnJvcltcIk5vQ2hhbm5lbEZvdW5kXCJdID0gXCJOb0NoYW5uZWxGb3VuZFwiO1xuICAgIC8qKiBTSE9VTEQgYmUgcmV0dXJuZWQgd2hlbiBhIHJlcXVlc3QgdG8gam9pbiBhIHVzZXIgY2hhbm5lbCBvciB0byBhIHJldHJpZXZlIGEgQ2hhbm5lbCBvYmplY3QgdmlhIHRoZSBgam9pblVzZXJDaGFubmVsYCBvciBgZ2V0T3JDcmVhdGVDaGFubmVsYCBtZXRob2RzIG9mIHRoZSBEZXNrdG9wQWdlbnQgKGBmZGMzYCkgb2JqZWN0IGlzIGRlbmllZC4gKi9cbiAgICBDaGFubmVsRXJyb3JbXCJBY2Nlc3NEZW5pZWRcIl0gPSBcIkFjY2Vzc0RlbmllZFwiO1xuICAgIC8qKiBTSE9VTEQgYmUgcmV0dXJuZWQgd2hlbiBhIGNoYW5uZWwgY2Fubm90IGJlIGNyZWF0ZWQgb3IgcmV0cmlldmVkIHZpYSB0aGUgYGdldE9yQ3JlYXRlQ2hhbm5lbGAgbWV0aG9kIG9mIHRoZSBEZXNrdG9wQWdlbnQgKGBmZGMzYCkuKi9cbiAgICBDaGFubmVsRXJyb3JbXCJDcmVhdGlvbkZhaWxlZFwiXSA9IFwiQ3JlYXRpb25GYWlsZWRcIjtcbiAgICAvKiogUmV0dXJuZWQgaWYgYSBjYWxsIHRvIHRoZSBgYnJvYWRjYXN0YCBmdW5jdGlvbnMgaXMgbWFkZSB3aXRoIGFuIGludmFsaWQgY29udGV4dCBhcmd1bWVudC4gQ29udGV4dHMgc2hvdWxkIGJlIE9iamVjdHMgd2l0aCBhdCBsZWFzdCBhIGB0eXBlYCBmaWVsZCB0aGF0IGhhcyBhIGBzdHJpbmdgIHZhbHVlLiovXG4gICAgQ2hhbm5lbEVycm9yW1wiTWFsZm9ybWVkQ29udGV4dFwiXSA9IFwiTWFsZm9ybWVkQ29udGV4dFwiO1xufSkoQ2hhbm5lbEVycm9yIHx8IChDaGFubmVsRXJyb3IgPSB7fSkpO1xudmFyIEJyaWRnaW5nRXJyb3I7XG4oZnVuY3Rpb24gKEJyaWRnaW5nRXJyb3IpIHtcbiAgICAvKiogQGV4cGVyaW1lbnRhbCBSZXR1cm5lZCBpZiBhIERlc2t0b3AgQWdlbnQgZGlkIG5vdCByZXR1cm4gYSByZXNwb25zZSwgdmlhIERlc2t0b3AgQWdlbnQgQnJpZGdpbmcsIHdpdGhpbiB0aGUgYWxsb3RlZCB0aW1lb3V0LiAqL1xuICAgIEJyaWRnaW5nRXJyb3JbXCJSZXNwb25zZVRpbWVkT3V0XCJdID0gXCJSZXNwb25zZVRvQnJpZGdlVGltZWRPdXRcIjtcbiAgICAvKiogQGV4cGVyaW1lbnRhbCBSZXR1cm5lZCBpZiBhIERlc2t0b3AgQWdlbnQgdGhhdCBoYXMgYmVlbiB0YXJnZXRlZCBieSBhIHBhcnRpY3VsYXIgcmVxdWVzdCBoYXMgYmVlbiBkaXNjb25uZWN0ZWQgZnJvbSB0aGUgQnJpZGdlIGJlZm9yZSBhIHJlc3BvbnNlIGhhcyBiZWVuIHJlY2VpdmVkIGZyb20gaXQuICovXG4gICAgQnJpZGdpbmdFcnJvcltcIkFnZW50RGlzY29ubmVjdGVkXCJdID0gXCJBZ2VudERpc2Nvbm5lY3RlZFwiO1xuICAgIC8qKiBAZXhwZXJpbWVudGFsIFJldHVybmVkIGZvciBGREMzIEFQSSBjYWxscyB0aGF0IGFyZSBzcGVjaWZpZWQgd2l0aCBhcmd1bWVudHMgaW5kaWNhdGluZyB0aGF0IGEgcmVtb3RlIERlc2t0b3AgYWdlbnQgc2hvdWxkIGJlIHRhcmdldGVkIChlLmcuIHJhaXNlSW50ZW50IHdpdGggYW4gYXBwIG9uIGEgcmVtb3RlIERlc2t0b3BBZ2VudCB0YXJnZXRlZCksIHdoZW4gdGhlIGxvY2FsIERlc2t0b3AgQWdlbnQgaXMgbm90IGNvbm5lY3RlZCB0byBhIGJyaWRnZS4gKi9cbiAgICBCcmlkZ2luZ0Vycm9yW1wiTm90Q29ubmVjdGVkVG9CcmlkZ2VcIl0gPSBcIk5vdENvbm5lY3RlZFRvQnJpZGdlXCI7XG4gICAgLyoqIEBleHBlcmltZW50YWwgUmV0dXJuZWQgaWYgYSBtZXNzYWdlIHRvIGEgQnJpZGdlIGRldmlhdGVzIGZyb20gdGhlIHNjaGVtYSBmb3IgdGhhdCBtZXNzYWdlIHN1ZmZpY2llbnRseSB0aGF0IGl0IGNvdWxkIG5vdCBiZSBwcm9jZXNzZWQuICovXG4gICAgQnJpZGdpbmdFcnJvcltcIk1hbGZvcm1lZE1lc3NhZ2VcIl0gPSBcIk1hbGZvcm1lZE1lc3NhZ2VcIjtcbn0pKEJyaWRnaW5nRXJyb3IgfHwgKEJyaWRnaW5nRXJyb3IgPSB7fSkpO1xuXG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxyXG5cclxuUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55XHJcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZC5cclxuXHJcblRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEhcclxuUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZXHJcbkFORCBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcclxuSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NXHJcbkxPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SXHJcbk9USEVSIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1JcclxuUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UsIFN1cHByZXNzZWRFcnJvciwgU3ltYm9sICovXHJcblxyXG5cclxuZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZnVuY3Rpb24gX19nZW5lcmF0b3IodGhpc0FyZywgYm9keSkge1xyXG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcclxuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XHJcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xyXG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcclxuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XHJcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cclxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcclxuICAgIH1cclxufVxyXG5cclxudHlwZW9mIFN1cHByZXNzZWRFcnJvciA9PT0gXCJmdW5jdGlvblwiID8gU3VwcHJlc3NlZEVycm9yIDogZnVuY3Rpb24gKGVycm9yLCBzdXBwcmVzc2VkLCBtZXNzYWdlKSB7XHJcbiAgICB2YXIgZSA9IG5ldyBFcnJvcihtZXNzYWdlKTtcclxuICAgIHJldHVybiBlLm5hbWUgPSBcIlN1cHByZXNzZWRFcnJvclwiLCBlLmVycm9yID0gZXJyb3IsIGUuc3VwcHJlc3NlZCA9IHN1cHByZXNzZWQsIGU7XHJcbn07XG5cbi8qKlxuICogRW5zdXJlcyBhdCBjb21waWxlIHRpbWUgdGhhdCB0aGUgZ2l2ZW4gc3RyaW5nIHR1cGxlIGlzIGV4aGF1c3RpdmUgb24gYSBnaXZlbiB1bmlvbiB0eXBlLCBpLmUuIGNvbnRhaW5zIEFMTCBwb3NzaWJsZSB2YWx1ZXMgb2YgdGhlIGdpdmVuIFVOSU9OX1RZUEUuXG4gKi9cbnZhciBleGhhdXN0aXZlU3RyaW5nVHVwbGUgPSBmdW5jdGlvbiAoKSB7IHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHR1cGxlID0gW107XG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdHVwbGVbX2ldID0gYXJndW1lbnRzW19pXTtcbiAgICB9XG4gICAgcmV0dXJuIHR1cGxlO1xufTsgfTtcblxudmFyIFNUQU5EQVJEX0NPTlRFWFRfVFlQRVMgPSBleGhhdXN0aXZlU3RyaW5nVHVwbGUoKSgnZmRjMy5hY3Rpb24nLCAnZmRjMy5jaGFydCcsICdmZGMzLmNoYXQuaW5pdFNldHRpbmdzJywgJ2ZkYzMuY2hhdC5tZXNzYWdlJywgJ2ZkYzMuY2hhdC5yb29tJywgJ2ZkYzMuY2hhdC5zZWFyY2hDcml0ZXJpYScsICdmZGMzLmNvbnRhY3QnLCAnZmRjMy5jb250YWN0TGlzdCcsICdmZGMzLmNvdW50cnknLCAnZmRjMy5jdXJyZW5jeScsICdmZGMzLmVtYWlsJywgJ2ZkYzMuaW5zdHJ1bWVudCcsICdmZGMzLmluc3RydW1lbnRMaXN0JywgJ2ZkYzMuaW50ZXJhY3Rpb24nLCAnZmRjMy5tZXNzYWdlJywgJ2ZkYzMub3JnYW5pemF0aW9uJywgJ2ZkYzMucG9ydGZvbGlvJywgJ2ZkYzMucG9zaXRpb24nLCAnZmRjMy5ub3RoaW5nJywgJ2ZkYzMudGltZVJhbmdlJywgJ2ZkYzMudHJhbnNhY3Rpb25SZXN1bHQnLCAnZmRjMy52YWx1YXRpb24nKTtcbi8vIHVzZWQgaW50ZXJuYWxseSB0byBjaGVjayBpZiBhIGdpdmVuIGludGVudC9jb250ZXh0IGlzIGEgc3RhbmRhcmQgb25lXG52YXIgU3RhbmRhcmRDb250ZXh0c1NldCA9IG5ldyBTZXQoU1RBTkRBUkRfQ09OVEVYVF9UWVBFUyk7XG5cbnZhciBTVEFOREFSRF9JTlRFTlRTID0gZXhoYXVzdGl2ZVN0cmluZ1R1cGxlKCkoJ0NyZWF0ZUludGVyYWN0aW9uJywgJ1NlbmRDaGF0TWVzc2FnZScsICdTdGFydENhbGwnLCAnU3RhcnRDaGF0JywgJ1N0YXJ0RW1haWwnLCAnVmlld0FuYWx5c2lzJywgJ1ZpZXdDaGF0JywgJ1ZpZXdDaGFydCcsICdWaWV3Q29udGFjdCcsICdWaWV3SG9sZGluZ3MnLCAnVmlld0luc3RydW1lbnQnLCAnVmlld0ludGVyYWN0aW9ucycsICdWaWV3TWVzc2FnZXMnLCAnVmlld05ld3MnLCAnVmlld09yZGVycycsICdWaWV3UHJvZmlsZScsICdWaWV3UXVvdGUnLCAnVmlld1Jlc2VhcmNoJyk7XG4vLyB1c2VkIGludGVybmFsbHkgdG8gY2hlY2sgaWYgYSBnaXZlbiBpbnRlbnQvY29udGV4dCBpcyBhIHN0YW5kYXJkIG9uZVxudmFyIFN0YW5kYXJkSW50ZW50c1NldCA9IG5ldyBTZXQoU1RBTkRBUkRfSU5URU5UUyk7XG5cbnZhciBERUZBVUxUX1RJTUVPVVQgPSA1MDAwO1xudmFyIFVuYXZhaWxhYmxlRXJyb3IgPSBuZXcgRXJyb3IoJ0ZEQzMgRGVza3RvcEFnZW50IG5vdCBhdmFpbGFibGUgYXQgYHdpbmRvdy5mZGMzYC4nKTtcbnZhciBUaW1lb3V0RXJyb3IgPSBuZXcgRXJyb3IoJ1RpbWVkIG91dCB3YWl0aW5nIGZvciBgZmRjM1JlYWR5YCBldmVudC4nKTtcbnZhciBVbmV4cGVjdGVkRXJyb3IgPSBuZXcgRXJyb3IoJ2BmZGMzUmVhZHlgIGV2ZW50IGZpcmVkLCBidXQgYHdpbmRvdy5mZGMzYCBub3Qgc2V0IHRvIERlc2t0b3BBZ2VudC4nKTtcbmZ1bmN0aW9uIHJlamVjdElmTm9HbG9iYWwoZikge1xuICAgIHJldHVybiB3aW5kb3cuZmRjMyA/IGYoKSA6IFByb21pc2UucmVqZWN0KFVuYXZhaWxhYmxlRXJyb3IpO1xufVxuLyoqXG4gKiBVdGlsaXR5IGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIHByb21pc2UgdGhhdCB3aWxsIHJlc29sdmUgaW1tZWFkaWF0ZWx5XG4gKiBpZiB0aGUgZGVza3RvcCBhZ2VudCBBUEkgaXMgZm91bmQgYXQgYHdpbmRvdy5mZGMzYC4gSWYgdGhlIEFQSSBpcyBmb3VuZCxcbiAqIHRoZSBwcm9taXNlIHdpbGwgcmVzb2x2ZSB3aGVuIHRoZSBgZmRjM1JlYWR5YCBldmVudCBpcyByZWNlaXZlZCBvciBpZiBpdFxuICogaXMgZm91bmQgYXQgdGhlIGVuZCBvZiB0aGUgc3BlY2lmaWVkIHRpbWVvdXQuIElmIHRoZSBBUEkgaXMgbm90IGZvdW5kLCBpdFxuICogd2lsbCByZWplY3Qgd2l0aCBhbiBlcnJvci5cbiAqXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBhd2FpdCBmZGMzUmVhZHkoKTtcbiAqIGNvbnN0IGludGVudExpc3RlbmVyID0gYXdhaXQgYWRkSW50ZW50TGlzdGVuZXIoXCJWaWV3Q2hhcnRcIiwgaW50ZW50SGFuZGxlckZuKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB3YWl0Rm9yTXMgVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gd2FpdCBmb3IgdGhlIEZEQzMgQVBJIHRvIGJlXG4gKiByZWFkeS4gRGVmYXVsdHMgdG8gNSBzZWNvbmRzLlxuICovXG52YXIgZmRjM1JlYWR5ID0gZnVuY3Rpb24gKHdhaXRGb3JNcykge1xuICAgIGlmICh3YWl0Rm9yTXMgPT09IHZvaWQgMCkgeyB3YWl0Rm9yTXMgPSBERUZBVUxUX1RJTUVPVVQ7IH1cbiAgICByZXR1cm4gX19hd2FpdGVyKHZvaWQgMCwgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgcmV0dXJuIFsyIC8qcmV0dXJuKi8sIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIGdsb2JhbCBpcyBhbHJlYWR5IGF2YWlsYWJsZSByZXNvbHZlIGltbWVkaWF0ZWx5XG4gICAgICAgICAgICAgICAgICAgIGlmICh3aW5kb3cuZmRjMykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgaXRzIG5vdCBhdmFpbGFibGUgc2V0dXAgYSB0aW1lb3V0IHRvIHJldHVybiBhIHJlamVjdGVkIHByb21pc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0aW1lb3V0XzEgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgcmV0dXJuICh3aW5kb3cuZmRjMyA/IHJlc29sdmUoKSA6IHJlamVjdChUaW1lb3V0RXJyb3IpKTsgfSwgd2FpdEZvck1zKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGxpc3RlbiBmb3IgdGhlIGZkYzNSZWFkeSBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2ZkYzNSZWFkeScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dF8xKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cuZmRjMyA/IHJlc29sdmUoKSA6IHJlamVjdChVbmV4cGVjdGVkRXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSwgeyBvbmNlOiB0cnVlIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSldO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn07XG5mdW5jdGlvbiBpc1N0cmluZyhhcHApIHtcbiAgICByZXR1cm4gISFhcHAgJiYgdHlwZW9mIGFwcCA9PT0gJ3N0cmluZyc7XG59XG5mdW5jdGlvbiBvcGVuKGFwcCwgY29udGV4dCkge1xuICAgIGlmIChpc1N0cmluZyhhcHApKSB7XG4gICAgICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLm9wZW4oYXBwLCBjb250ZXh0KTsgfSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5vcGVuKGFwcCwgY29udGV4dCk7IH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGZpbmRJbnRlbnQoaW50ZW50LCBjb250ZXh0LCByZXN1bHRUeXBlKSB7XG4gICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMuZmluZEludGVudChpbnRlbnQsIGNvbnRleHQsIHJlc3VsdFR5cGUpOyB9KTtcbn1cbmZ1bmN0aW9uIGZpbmRJbnRlbnRzQnlDb250ZXh0KGNvbnRleHQsIHJlc3VsdFR5cGUpIHtcbiAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5maW5kSW50ZW50c0J5Q29udGV4dChjb250ZXh0LCByZXN1bHRUeXBlKTsgfSk7XG59XG5mdW5jdGlvbiBicm9hZGNhc3QoY29udGV4dCkge1xuICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLmJyb2FkY2FzdChjb250ZXh0KTsgfSk7XG59XG5mdW5jdGlvbiByYWlzZUludGVudChpbnRlbnQsIGNvbnRleHQsIGFwcCkge1xuICAgIGlmIChpc1N0cmluZyhhcHApKSB7XG4gICAgICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLnJhaXNlSW50ZW50KGludGVudCwgY29udGV4dCwgYXBwKTsgfSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5yYWlzZUludGVudChpbnRlbnQsIGNvbnRleHQsIGFwcCk7IH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHJhaXNlSW50ZW50Rm9yQ29udGV4dChjb250ZXh0LCBhcHApIHtcbiAgICBpZiAoaXNTdHJpbmcoYXBwKSkge1xuICAgICAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5yYWlzZUludGVudEZvckNvbnRleHQoY29udGV4dCwgYXBwKTsgfSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5yYWlzZUludGVudEZvckNvbnRleHQoY29udGV4dCwgYXBwKTsgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gYWRkSW50ZW50TGlzdGVuZXIoaW50ZW50LCBoYW5kbGVyKSB7XG4gICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMuYWRkSW50ZW50TGlzdGVuZXIoaW50ZW50LCBoYW5kbGVyKTsgfSk7XG59XG5mdW5jdGlvbiBhZGRDb250ZXh0TGlzdGVuZXIoY29udGV4dFR5cGVPckhhbmRsZXIsIGhhbmRsZXIpIHtcbiAgICAvL0hhbmRsZSAoZGVwcmVjYXRlZCkgZnVuY3Rpb24gc2lnbmF0dXJlIHRoYXQgYWxsb3dlZCBjb250ZXh0VHlwZSBhcmd1bWVudCB0byBiZSBvbWl0dGVkXG4gICAgaWYgKHR5cGVvZiBjb250ZXh0VHlwZU9ySGFuZGxlciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5hZGRDb250ZXh0TGlzdGVuZXIoY29udGV4dFR5cGVPckhhbmRsZXIsIGhhbmRsZXIpOyB9KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLmFkZENvbnRleHRMaXN0ZW5lcihudWxsLCBjb250ZXh0VHlwZU9ySGFuZGxlcik7IH0pO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGdldFVzZXJDaGFubmVscygpIHtcbiAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vZmFsbGJhY2sgdG8gZ2V0U3lzdGVtQ2hhbm5lbHMgZm9yIEZEQzMgPDIuMCBpbXBsZW1lbnRhdGlvbnNcbiAgICAgICAgaWYgKHdpbmRvdy5mZGMzLmdldFVzZXJDaGFubmVscykge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5mZGMzLmdldFVzZXJDaGFubmVscygpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHdpbmRvdy5mZGMzLmdldFN5c3RlbUNoYW5uZWxzKCk7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cbmZ1bmN0aW9uIGdldFN5c3RlbUNoYW5uZWxzKCkge1xuICAgIC8vZmFsbGZvcndhcmQgdG8gZ2V0VXNlckNoYW5uZWxzIGZvciBGREMzIDIuMCsgaW1wbGVtZW50YXRpb25zXG4gICAgcmV0dXJuIGdldFVzZXJDaGFubmVscygpO1xufVxuZnVuY3Rpb24gam9pblVzZXJDaGFubmVsKGNoYW5uZWxJZCkge1xuICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy9mYWxsYmFjayB0byBqb2luQ2hhbm5lbCBmb3IgRkRDMyA8Mi4wIGltcGxlbWVudGF0aW9uc1xuICAgICAgICBpZiAod2luZG93LmZkYzMuam9pblVzZXJDaGFubmVsKSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LmZkYzMuam9pblVzZXJDaGFubmVsKGNoYW5uZWxJZCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LmZkYzMuam9pbkNoYW5uZWwoY2hhbm5lbElkKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuZnVuY3Rpb24gam9pbkNoYW5uZWwoY2hhbm5lbElkKSB7XG4gICAgLy9mYWxsZm9yd2FyZCB0byBqb2luVXNlckNoYW5uZWwgZm9yIEZEQzMgMi4wKyBpbXBsZW1lbnRhdGlvbnNcbiAgICByZXR1cm4gam9pblVzZXJDaGFubmVsKGNoYW5uZWxJZCk7XG59XG5mdW5jdGlvbiBnZXRPckNyZWF0ZUNoYW5uZWwoY2hhbm5lbElkKSB7XG4gICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMuZ2V0T3JDcmVhdGVDaGFubmVsKGNoYW5uZWxJZCk7IH0pO1xufVxuZnVuY3Rpb24gZ2V0Q3VycmVudENoYW5uZWwoKSB7XG4gICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMuZ2V0Q3VycmVudENoYW5uZWwoKTsgfSk7XG59XG5mdW5jdGlvbiBsZWF2ZUN1cnJlbnRDaGFubmVsKCkge1xuICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLmxlYXZlQ3VycmVudENoYW5uZWwoKTsgfSk7XG59XG5mdW5jdGlvbiBjcmVhdGVQcml2YXRlQ2hhbm5lbCgpIHtcbiAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5jcmVhdGVQcml2YXRlQ2hhbm5lbCgpOyB9KTtcbn1cbmZ1bmN0aW9uIGdldEluZm8oKSB7XG4gICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMuZ2V0SW5mbygpOyB9KTtcbn1cbmZ1bmN0aW9uIGdldEFwcE1ldGFkYXRhKGFwcCkge1xuICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLmdldEFwcE1ldGFkYXRhKGFwcCk7IH0pO1xufVxuZnVuY3Rpb24gZmluZEluc3RhbmNlcyhhcHApIHtcbiAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5maW5kSW5zdGFuY2VzKGFwcCk7IH0pO1xufVxuLyoqXG4gKiBDaGVjayBpZiB0aGUgZ2l2ZW4gY29udGV4dCBpcyBhIHN0YW5kYXJkIGNvbnRleHQgdHlwZS5cbiAqIEBwYXJhbSBjb250ZXh0VHlwZVxuICovXG5mdW5jdGlvbiBpc1N0YW5kYXJkQ29udGV4dFR5cGUoY29udGV4dFR5cGUpIHtcbiAgICByZXR1cm4gU3RhbmRhcmRDb250ZXh0c1NldC5oYXMoY29udGV4dFR5cGUpO1xufVxuLyoqXG4gKiBDaGVjayBpZiB0aGUgZ2l2ZW4gaW50ZW50IGlzIGEgc3RhbmRhcmQgaW50ZW50LlxuICogQHBhcmFtIGludGVudFxuICovXG5mdW5jdGlvbiBpc1N0YW5kYXJkSW50ZW50KGludGVudCkge1xuICAgIHJldHVybiBTdGFuZGFyZEludGVudHNTZXQuaGFzKGludGVudCk7XG59XG4vKipcbiAqIENvbXBhcmUgbnVtZXJpYyBzZW12ZXIgdmVyc2lvbiBudW1iZXIgc3RyaW5ncyAoaW4gdGhlIGZvcm0gYDEuMi4zYCkuXG4gKlxuICogUmV0dXJucyBgLTFgIGlmIHRoZSBmaXJzdCBhcmd1bWVudCBpcyBhIGxvd2VyIHZlcnNpb24gbnVtYmVyIHRoYW4gdGhlIHNlY29uZCxcbiAqIGAxYCBpZiB0aGUgZmlyc3QgYXJndW1lbnQgaXMgZ3JlYXRlciB0aGFuIHRoZSBzZWNvbmQsIDAgaWYgdGhlIGFyZ3VtZW50cyBhcmVcbiAqIGVxdWFsIGFuZCBgbnVsbGAgaWYgYW4gZXJyb3Igb2NjdXJyZWQgZHVyaW5nIHRoZSBjb21wYXJpc29uLlxuICpcbiAqIEBwYXJhbSBhXG4gKiBAcGFyYW0gYlxuICovXG52YXIgY29tcGFyZVZlcnNpb25OdW1iZXJzID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICB0cnkge1xuICAgICAgICB2YXIgYVZlckFyciA9IGEuc3BsaXQoJy4nKS5tYXAoTnVtYmVyKTtcbiAgICAgICAgdmFyIGJWZXJBcnIgPSBiLnNwbGl0KCcuJykubWFwKE51bWJlcik7XG4gICAgICAgIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBNYXRoLm1heChhVmVyQXJyLmxlbmd0aCwgYlZlckFyci5sZW5ndGgpOyBpbmRleCsrKSB7XG4gICAgICAgICAgICAvKiBJZiBvbmUgdmVyc2lvbiBudW1iZXIgaGFzIG1vcmUgZGlnaXRzIGFuZCB0aGUgb3RoZXIgZG9lcyBub3QsIGFuZCB0aGV5IGFyZSBvdGhlcndpc2UgZXF1YWwsXG4gICAgICAgICAgICAgICBhc3N1bWUgdGhlIGxvbmdlciBpcyBncmVhdGVyLiBFLmcuIDEuMS4xID4gMS4xICovXG4gICAgICAgICAgICBpZiAoaW5kZXggPT09IGFWZXJBcnIubGVuZ3RoIHx8IGFWZXJBcnJbaW5kZXhdIDwgYlZlckFycltpbmRleF0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpbmRleCA9PT0gYlZlckFyci5sZW5ndGggfHwgYVZlckFycltpbmRleF0gPiBiVmVyQXJyW2luZGV4XSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gY29tcGFyZSB2ZXJzaW9uIHN0cmluZ3MnLCBlKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufTtcbi8qKlxuICogQ2hlY2sgaWYgdGhlIEZEQzMgdmVyc2lvbiBpbiBhbiBJbXBsZW1lbnRhdGlvbk1ldGFkYXRhIG9iamVjdCBpcyBncmVhdGVyIHRoYW5cbiAqIG9yIGVxdWFsIHRvIHRoZSBzdXBwbGllZCBudW1lcmljIHNlbXZlciB2ZXJzaW9uIG51bWJlciBzdHJpbmcgKGluIHRoZSBmb3JtIGAxLjIuM2ApLlxuICpcbiAqIFJldHVybnMgYSBib29sZWFuIG9yIG51bGwgaWYgYW4gZXJyb3Igb2NjdXJyZWQgd2hpbGUgY29tcGFyaW5nIHRoZSB2ZXJzaW9uIG51bWJlcnMuXG4gKlxuICogQHBhcmFtIG1ldGFkYXRhXG4gKiBAcGFyYW0gdmVyc2lvblxuICovXG52YXIgdmVyc2lvbklzQXRMZWFzdCA9IGZ1bmN0aW9uIChtZXRhZGF0YSwgdmVyc2lvbikge1xuICAgIHZhciBjb21wYXJpc29uID0gY29tcGFyZVZlcnNpb25OdW1iZXJzKG1ldGFkYXRhLmZkYzNWZXJzaW9uLCB2ZXJzaW9uKTtcbiAgICByZXR1cm4gY29tcGFyaXNvbiA9PT0gbnVsbCA/IG51bGwgOiBjb21wYXJpc29uID49IDAgPyB0cnVlIDogZmFsc2U7XG59O1xuXG4vKipcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKiBDb3B5cmlnaHQgRklOT1MgRkRDMyBjb250cmlidXRvcnMgLSBzZWUgTk9USUNFIGZpbGVcbiAqL1xuLyoqXG4gKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rIFN0YW5kYXJkQ29udGV4dFR5cGV9IGluc3RlYWRcbiAqL1xudmFyIENvbnRleHRUeXBlcztcbihmdW5jdGlvbiAoQ29udGV4dFR5cGVzKSB7XG4gICAgQ29udGV4dFR5cGVzW1wiQ2hhcnRcIl0gPSBcImZkYzMuY2hhcnRcIjtcbiAgICBDb250ZXh0VHlwZXNbXCJDaGF0SW5pdFNldHRpbmdzXCJdID0gXCJmZGMzLmNoYXQuaW5pdFNldHRpbmdzXCI7XG4gICAgQ29udGV4dFR5cGVzW1wiQ2hhdFJvb21cIl0gPSBcImZkYzMuY2hhdC5yb29tXCI7XG4gICAgQ29udGV4dFR5cGVzW1wiQ29udGFjdFwiXSA9IFwiZmRjMy5jb250YWN0XCI7XG4gICAgQ29udGV4dFR5cGVzW1wiQ29udGFjdExpc3RcIl0gPSBcImZkYzMuY29udGFjdExpc3RcIjtcbiAgICBDb250ZXh0VHlwZXNbXCJDb3VudHJ5XCJdID0gXCJmZGMzLmNvdW50cnlcIjtcbiAgICBDb250ZXh0VHlwZXNbXCJDdXJyZW5jeVwiXSA9IFwiZmRjMy5jdXJyZW5jeVwiO1xuICAgIENvbnRleHRUeXBlc1tcIkVtYWlsXCJdID0gXCJmZGMzLmVtYWlsXCI7XG4gICAgQ29udGV4dFR5cGVzW1wiSW5zdHJ1bWVudFwiXSA9IFwiZmRjMy5pbnN0cnVtZW50XCI7XG4gICAgQ29udGV4dFR5cGVzW1wiSW5zdHJ1bWVudExpc3RcIl0gPSBcImZkYzMuaW5zdHJ1bWVudExpc3RcIjtcbiAgICBDb250ZXh0VHlwZXNbXCJJbnRlcmFjdGlvblwiXSA9IFwiZmRjMy5pbnRlcmFjdGlvblwiO1xuICAgIENvbnRleHRUeXBlc1tcIk5vdGhpbmdcIl0gPSBcImZkYzMubm90aGluZ1wiO1xuICAgIENvbnRleHRUeXBlc1tcIk9yZ2FuaXphdGlvblwiXSA9IFwiZmRjMy5vcmdhbml6YXRpb25cIjtcbiAgICBDb250ZXh0VHlwZXNbXCJQb3J0Zm9saW9cIl0gPSBcImZkYzMucG9ydGZvbGlvXCI7XG4gICAgQ29udGV4dFR5cGVzW1wiUG9zaXRpb25cIl0gPSBcImZkYzMucG9zaXRpb25cIjtcbiAgICBDb250ZXh0VHlwZXNbXCJDaGF0U2VhcmNoQ3JpdGVyaWFcIl0gPSBcImZkYzMuY2hhdC5zZWFyY2hDcml0ZXJpYVwiO1xuICAgIENvbnRleHRUeXBlc1tcIlRpbWVSYW5nZVwiXSA9IFwiZmRjMy50aW1lUmFuZ2VcIjtcbiAgICBDb250ZXh0VHlwZXNbXCJUcmFuc2FjdGlvblJlc3VsdFwiXSA9IFwiZmRjMy50cmFuc2FjdGlvblJlc3VsdFwiO1xuICAgIENvbnRleHRUeXBlc1tcIlZhbHVhdGlvblwiXSA9IFwiZmRjMy52YWx1YXRpb25cIjtcbn0pKENvbnRleHRUeXBlcyB8fCAoQ29udGV4dFR5cGVzID0ge30pKTtcblxuLy8gVG8gcGFyc2UgdGhpcyBkYXRhOlxuLy9cbi8vICAgaW1wb3J0IHsgQ29udmVydCwgQWN0aW9uLCBDaGFydCwgQ2hhdEluaXRTZXR0aW5ncywgQ2hhdE1lc3NhZ2UsIENoYXRSb29tLCBDaGF0U2VhcmNoQ3JpdGVyaWEsIENvbnRhY3QsIENvbnRhY3RMaXN0LCBDb250ZXh0LCBDb3VudHJ5LCBDdXJyZW5jeSwgRW1haWwsIEluc3RydW1lbnQsIEluc3RydW1lbnRMaXN0LCBJbnRlcmFjdGlvbiwgTWVzc2FnZSwgTm90aGluZywgT3JkZXIsIE9yZGVyTGlzdCwgT3JnYW5pemF0aW9uLCBQb3J0Zm9saW8sIFBvc2l0aW9uLCBQcm9kdWN0LCBUaW1lUmFuZ2UsIFRyYWRlLCBUcmFkZUxpc3QsIFRyYW5zYWN0aW9uUmVzdWx0LCBWYWx1YXRpb24gfSBmcm9tIFwiLi9maWxlXCI7XG4vL1xuLy8gICBjb25zdCBhY3Rpb24gPSBDb252ZXJ0LnRvQWN0aW9uKGpzb24pO1xuLy8gICBjb25zdCBjaGFydCA9IENvbnZlcnQudG9DaGFydChqc29uKTtcbi8vICAgY29uc3QgY2hhdEluaXRTZXR0aW5ncyA9IENvbnZlcnQudG9DaGF0SW5pdFNldHRpbmdzKGpzb24pO1xuLy8gICBjb25zdCBjaGF0TWVzc2FnZSA9IENvbnZlcnQudG9DaGF0TWVzc2FnZShqc29uKTtcbi8vICAgY29uc3QgY2hhdFJvb20gPSBDb252ZXJ0LnRvQ2hhdFJvb20oanNvbik7XG4vLyAgIGNvbnN0IGNoYXRTZWFyY2hDcml0ZXJpYSA9IENvbnZlcnQudG9DaGF0U2VhcmNoQ3JpdGVyaWEoanNvbik7XG4vLyAgIGNvbnN0IGNvbnRhY3QgPSBDb252ZXJ0LnRvQ29udGFjdChqc29uKTtcbi8vICAgY29uc3QgY29udGFjdExpc3QgPSBDb252ZXJ0LnRvQ29udGFjdExpc3QoanNvbik7XG4vLyAgIGNvbnN0IGNvbnRleHQgPSBDb252ZXJ0LnRvQ29udGV4dChqc29uKTtcbi8vICAgY29uc3QgY291bnRyeSA9IENvbnZlcnQudG9Db3VudHJ5KGpzb24pO1xuLy8gICBjb25zdCBjdXJyZW5jeSA9IENvbnZlcnQudG9DdXJyZW5jeShqc29uKTtcbi8vICAgY29uc3QgZW1haWwgPSBDb252ZXJ0LnRvRW1haWwoanNvbik7XG4vLyAgIGNvbnN0IGluc3RydW1lbnQgPSBDb252ZXJ0LnRvSW5zdHJ1bWVudChqc29uKTtcbi8vICAgY29uc3QgaW5zdHJ1bWVudExpc3QgPSBDb252ZXJ0LnRvSW5zdHJ1bWVudExpc3QoanNvbik7XG4vLyAgIGNvbnN0IGludGVyYWN0aW9uID0gQ29udmVydC50b0ludGVyYWN0aW9uKGpzb24pO1xuLy8gICBjb25zdCBtZXNzYWdlID0gQ29udmVydC50b01lc3NhZ2UoanNvbik7XG4vLyAgIGNvbnN0IG5vdGhpbmcgPSBDb252ZXJ0LnRvTm90aGluZyhqc29uKTtcbi8vICAgY29uc3Qgb3JkZXIgPSBDb252ZXJ0LnRvT3JkZXIoanNvbik7XG4vLyAgIGNvbnN0IG9yZGVyTGlzdCA9IENvbnZlcnQudG9PcmRlckxpc3QoanNvbik7XG4vLyAgIGNvbnN0IG9yZ2FuaXphdGlvbiA9IENvbnZlcnQudG9Pcmdhbml6YXRpb24oanNvbik7XG4vLyAgIGNvbnN0IHBvcnRmb2xpbyA9IENvbnZlcnQudG9Qb3J0Zm9saW8oanNvbik7XG4vLyAgIGNvbnN0IHBvc2l0aW9uID0gQ29udmVydC50b1Bvc2l0aW9uKGpzb24pO1xuLy8gICBjb25zdCBwcm9kdWN0ID0gQ29udmVydC50b1Byb2R1Y3QoanNvbik7XG4vLyAgIGNvbnN0IHRpbWVSYW5nZSA9IENvbnZlcnQudG9UaW1lUmFuZ2UoanNvbik7XG4vLyAgIGNvbnN0IHRyYWRlID0gQ29udmVydC50b1RyYWRlKGpzb24pO1xuLy8gICBjb25zdCB0cmFkZUxpc3QgPSBDb252ZXJ0LnRvVHJhZGVMaXN0KGpzb24pO1xuLy8gICBjb25zdCB0cmFuc2FjdGlvblJlc3VsdCA9IENvbnZlcnQudG9UcmFuc2FjdGlvblJlc3VsdChqc29uKTtcbi8vICAgY29uc3QgdmFsdWF0aW9uID0gQ29udmVydC50b1ZhbHVhdGlvbihqc29uKTtcbi8vXG4vLyBUaGVzZSBmdW5jdGlvbnMgd2lsbCB0aHJvdyBhbiBlcnJvciBpZiB0aGUgSlNPTiBkb2Vzbid0XG4vLyBtYXRjaCB0aGUgZXhwZWN0ZWQgaW50ZXJmYWNlLCBldmVuIGlmIHRoZSBKU09OIGlzIHZhbGlkLlxuLyoqXG4gKiBGcmVlIHRleHQgdG8gYmUgdXNlZCBmb3IgYSBrZXl3b3JkIHNlYXJjaFxuICpcbiAqIGBpbnRlcmFjdGlvblR5cGVgIFNIT1VMRCBiZSBvbmUgb2YgYCdJbnN0YW50IE1lc3NhZ2UnYCwgYCdFbWFpbCdgLCBgJ0NhbGwnYCwgb3JcbiAqIGAnTWVldGluZydgIGFsdGhvdWdoIG90aGVyIHN0cmluZyB2YWx1ZXMgYXJlIHBlcm1pdHRlZC5cbiAqL1xuLy8gQ29udmVydHMgSlNPTiBzdHJpbmdzIHRvL2Zyb20geW91ciB0eXBlc1xuLy8gYW5kIGFzc2VydHMgdGhlIHJlc3VsdHMgb2YgSlNPTi5wYXJzZSBhdCBydW50aW1lXG52YXIgQ29udmVydCA9IC8qKiBAY2xhc3MgKi8gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDb252ZXJ0KCkge1xuICAgIH1cbiAgICBDb252ZXJ0LnRvQWN0aW9uID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIkFjdGlvblwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmFjdGlvblRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiQWN0aW9uXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQ2hhcnQgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiQ2hhcnRcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5jaGFydFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiQ2hhcnRcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9DaGF0SW5pdFNldHRpbmdzID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIkNoYXRJbml0U2V0dGluZ3NcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5jaGF0SW5pdFNldHRpbmdzVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJDaGF0SW5pdFNldHRpbmdzXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQ2hhdE1lc3NhZ2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiQ2hhdE1lc3NhZ2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5jaGF0TWVzc2FnZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiQ2hhdE1lc3NhZ2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9DaGF0Um9vbSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJDaGF0Um9vbVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNoYXRSb29tVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJDaGF0Um9vbVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0NoYXRTZWFyY2hDcml0ZXJpYSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJDaGF0U2VhcmNoQ3JpdGVyaWFcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5jaGF0U2VhcmNoQ3JpdGVyaWFUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkNoYXRTZWFyY2hDcml0ZXJpYVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0NvbnRhY3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiQ29udGFjdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNvbnRhY3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkNvbnRhY3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Db250YWN0TGlzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJDb250YWN0TGlzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNvbnRhY3RMaXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJDb250YWN0TGlzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0NvbnRleHQgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiQ29udGV4dFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNvbnRleHRUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkNvbnRleHRcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Db3VudHJ5ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIkNvdW50cnlcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5jb3VudHJ5VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJDb3VudHJ5XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQ3VycmVuY3kgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiQ3VycmVuY3lcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5jdXJyZW5jeVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiQ3VycmVuY3lcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9FbWFpbCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJFbWFpbFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmVtYWlsVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJFbWFpbFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0luc3RydW1lbnQgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiSW5zdHJ1bWVudFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lmluc3RydW1lbnRUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkluc3RydW1lbnRcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9JbnN0cnVtZW50TGlzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJJbnN0cnVtZW50TGlzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lmluc3RydW1lbnRMaXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJJbnN0cnVtZW50TGlzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ludGVyYWN0aW9uID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIkludGVyYWN0aW9uXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuaW50ZXJhY3Rpb25Ub0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkludGVyYWN0aW9uXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvTWVzc2FnZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJNZXNzYWdlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQubWVzc2FnZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiTWVzc2FnZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b05vdGhpbmcgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiTm90aGluZ1wiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lm5vdGhpbmdUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIk5vdGhpbmdcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9PcmRlciA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJPcmRlclwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lm9yZGVyVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJPcmRlclwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b09yZGVyTGlzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJPcmRlckxpc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5vcmRlckxpc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIk9yZGVyTGlzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b09yZ2FuaXphdGlvbiA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJPcmdhbml6YXRpb25cIikpO1xuICAgIH07XG4gICAgQ29udmVydC5vcmdhbml6YXRpb25Ub0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIk9yZ2FuaXphdGlvblwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1BvcnRmb2xpbyA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJQb3J0Zm9saW9cIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wb3J0Zm9saW9Ub0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIlBvcnRmb2xpb1wiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1Bvc2l0aW9uID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIlBvc2l0aW9uXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucG9zaXRpb25Ub0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIlBvc2l0aW9uXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUHJvZHVjdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJQcm9kdWN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucHJvZHVjdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiUHJvZHVjdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1RpbWVSYW5nZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJUaW1lUmFuZ2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC50aW1lUmFuZ2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIlRpbWVSYW5nZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1RyYWRlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIlRyYWRlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQudHJhZGVUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIlRyYWRlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvVHJhZGVMaXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIlRyYWRlTGlzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRyYWRlTGlzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiVHJhZGVMaXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvVHJhbnNhY3Rpb25SZXN1bHQgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiVHJhbnNhY3Rpb25SZXN1bHRcIikpO1xuICAgIH07XG4gICAgQ29udmVydC50cmFuc2FjdGlvblJlc3VsdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiVHJhbnNhY3Rpb25SZXN1bHRcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9WYWx1YXRpb24gPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiVmFsdWF0aW9uXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQudmFsdWF0aW9uVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJWYWx1YXRpb25cIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIHJldHVybiBDb252ZXJ0O1xufSgpKTtcbmZ1bmN0aW9uIGludmFsaWRWYWx1ZSh0eXAsIHZhbCwga2V5LCBwYXJlbnQpIHtcbiAgICBpZiAocGFyZW50ID09PSB2b2lkIDApIHsgcGFyZW50ID0gJyc7IH1cbiAgICB2YXIgcHJldHR5VHlwID0gcHJldHR5VHlwZU5hbWUodHlwKTtcbiAgICB2YXIgcGFyZW50VGV4dCA9IHBhcmVudCA/IFwiIG9uIFwiLmNvbmNhdChwYXJlbnQpIDogJyc7XG4gICAgdmFyIGtleVRleHQgPSBrZXkgPyBcIiBmb3Iga2V5IFxcXCJcIi5jb25jYXQoa2V5LCBcIlxcXCJcIikgOiAnJztcbiAgICB0aHJvdyBFcnJvcihcIkludmFsaWQgdmFsdWVcIi5jb25jYXQoa2V5VGV4dCkuY29uY2F0KHBhcmVudFRleHQsIFwiLiBFeHBlY3RlZCBcIikuY29uY2F0KHByZXR0eVR5cCwgXCIgYnV0IGdvdCBcIikuY29uY2F0KEpTT04uc3RyaW5naWZ5KHZhbCkpKTtcbn1cbmZ1bmN0aW9uIHByZXR0eVR5cGVOYW1lKHR5cCkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHR5cCkpIHtcbiAgICAgICAgaWYgKHR5cC5sZW5ndGggPT09IDIgJiYgdHlwWzBdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBcImFuIG9wdGlvbmFsIFwiLmNvbmNhdChwcmV0dHlUeXBlTmFtZSh0eXBbMV0pKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBcIm9uZSBvZiBbXCIuY29uY2F0KHR5cC5tYXAoZnVuY3Rpb24gKGEpIHsgcmV0dXJuIHByZXR0eVR5cGVOYW1lKGEpOyB9KS5qb2luKFwiLCBcIiksIFwiXVwiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgdHlwID09PSBcIm9iamVjdFwiICYmIHR5cC5saXRlcmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHR5cC5saXRlcmFsO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB0eXA7XG4gICAgfVxufVxuZnVuY3Rpb24ganNvblRvSlNQcm9wcyh0eXApIHtcbiAgICBpZiAodHlwLmpzb25Ub0pTID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyIG1hcF8xID0ge307XG4gICAgICAgIHR5cC5wcm9wcy5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7IHJldHVybiBtYXBfMVtwLmpzb25dID0geyBrZXk6IHAuanMsIHR5cDogcC50eXAgfTsgfSk7XG4gICAgICAgIHR5cC5qc29uVG9KUyA9IG1hcF8xO1xuICAgIH1cbiAgICByZXR1cm4gdHlwLmpzb25Ub0pTO1xufVxuZnVuY3Rpb24ganNUb0pTT05Qcm9wcyh0eXApIHtcbiAgICBpZiAodHlwLmpzVG9KU09OID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyIG1hcF8yID0ge307XG4gICAgICAgIHR5cC5wcm9wcy5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7IHJldHVybiBtYXBfMltwLmpzXSA9IHsga2V5OiBwLmpzb24sIHR5cDogcC50eXAgfTsgfSk7XG4gICAgICAgIHR5cC5qc1RvSlNPTiA9IG1hcF8yO1xuICAgIH1cbiAgICByZXR1cm4gdHlwLmpzVG9KU09OO1xufVxuZnVuY3Rpb24gdHJhbnNmb3JtKHZhbCwgdHlwLCBnZXRQcm9wcywga2V5LCBwYXJlbnQpIHtcbiAgICBpZiAoa2V5ID09PSB2b2lkIDApIHsga2V5ID0gJyc7IH1cbiAgICBpZiAocGFyZW50ID09PSB2b2lkIDApIHsgcGFyZW50ID0gJyc7IH1cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm1QcmltaXRpdmUodHlwLCB2YWwpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB0eXAgPT09IHR5cGVvZiB2YWwpXG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlKHR5cCwgdmFsLCBrZXksIHBhcmVudCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVVuaW9uKHR5cHMsIHZhbCkge1xuICAgICAgICAvLyB2YWwgbXVzdCB2YWxpZGF0ZSBhZ2FpbnN0IG9uZSB0eXAgaW4gdHlwc1xuICAgICAgICB2YXIgbCA9IHR5cHMubGVuZ3RoO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgdmFyIHR5cF8xID0gdHlwc1tpXTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyYW5zZm9ybSh2YWwsIHR5cF8xLCBnZXRQcm9wcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoXykgeyB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGludmFsaWRWYWx1ZSh0eXBzLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtRW51bShjYXNlcywgdmFsKSB7XG4gICAgICAgIGlmIChjYXNlcy5pbmRleE9mKHZhbCkgIT09IC0xKVxuICAgICAgICAgICAgcmV0dXJuIHZhbDtcbiAgICAgICAgcmV0dXJuIGludmFsaWRWYWx1ZShjYXNlcy5tYXAoZnVuY3Rpb24gKGEpIHsgcmV0dXJuIGwoYSk7IH0pLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtQXJyYXkodHlwLCB2YWwpIHtcbiAgICAgICAgLy8gdmFsIG11c3QgYmUgYW4gYXJyYXkgd2l0aCBubyBpbnZhbGlkIGVsZW1lbnRzXG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWwpKVxuICAgICAgICAgICAgcmV0dXJuIGludmFsaWRWYWx1ZShsKFwiYXJyYXlcIiksIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgICAgICByZXR1cm4gdmFsLm1hcChmdW5jdGlvbiAoZWwpIHsgcmV0dXJuIHRyYW5zZm9ybShlbCwgdHlwLCBnZXRQcm9wcyk7IH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm1EYXRlKHZhbCkge1xuICAgICAgICBpZiAodmFsID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZCA9IG5ldyBEYXRlKHZhbCk7XG4gICAgICAgIGlmIChpc05hTihkLnZhbHVlT2YoKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUobChcIkRhdGVcIiksIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm1PYmplY3QocHJvcHMsIGFkZGl0aW9uYWwsIHZhbCkge1xuICAgICAgICBpZiAodmFsID09PSBudWxsIHx8IHR5cGVvZiB2YWwgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheSh2YWwpKSB7XG4gICAgICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlKGwocmVmIHx8IFwib2JqZWN0XCIpLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHByb3BzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIHZhciBwcm9wID0gcHJvcHNba2V5XTtcbiAgICAgICAgICAgIHZhciB2ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbCwga2V5KSA/IHZhbFtrZXldIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgcmVzdWx0W3Byb3Aua2V5XSA9IHRyYW5zZm9ybSh2LCBwcm9wLnR5cCwgZ2V0UHJvcHMsIGtleSwgcmVmKTtcbiAgICAgICAgfSk7XG4gICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHZhbCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwcm9wcywga2V5KSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdHJhbnNmb3JtKHZhbFtrZXldLCBhZGRpdGlvbmFsLCBnZXRQcm9wcywga2V5LCByZWYpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgaWYgKHR5cCA9PT0gXCJhbnlcIilcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICBpZiAodHlwID09PSBudWxsKSB7XG4gICAgICAgIGlmICh2YWwgPT09IG51bGwpXG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlKHR5cCwgdmFsLCBrZXksIHBhcmVudCk7XG4gICAgfVxuICAgIGlmICh0eXAgPT09IGZhbHNlKVxuICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlKHR5cCwgdmFsLCBrZXksIHBhcmVudCk7XG4gICAgdmFyIHJlZiA9IHVuZGVmaW5lZDtcbiAgICB3aGlsZSAodHlwZW9mIHR5cCA9PT0gXCJvYmplY3RcIiAmJiB0eXAucmVmICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmVmID0gdHlwLnJlZjtcbiAgICAgICAgdHlwID0gdHlwZU1hcFt0eXAucmVmXTtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodHlwKSlcbiAgICAgICAgcmV0dXJuIHRyYW5zZm9ybUVudW0odHlwLCB2YWwpO1xuICAgIGlmICh0eXBlb2YgdHlwID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHJldHVybiB0eXAuaGFzT3duUHJvcGVydHkoXCJ1bmlvbk1lbWJlcnNcIikgPyB0cmFuc2Zvcm1Vbmlvbih0eXAudW5pb25NZW1iZXJzLCB2YWwpXG4gICAgICAgICAgICA6IHR5cC5oYXNPd25Qcm9wZXJ0eShcImFycmF5SXRlbXNcIikgPyB0cmFuc2Zvcm1BcnJheSh0eXAuYXJyYXlJdGVtcywgdmFsKVxuICAgICAgICAgICAgICAgIDogdHlwLmhhc093blByb3BlcnR5KFwicHJvcHNcIikgPyB0cmFuc2Zvcm1PYmplY3QoZ2V0UHJvcHModHlwKSwgdHlwLmFkZGl0aW9uYWwsIHZhbClcbiAgICAgICAgICAgICAgICAgICAgOiBpbnZhbGlkVmFsdWUodHlwLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB9XG4gICAgLy8gTnVtYmVycyBjYW4gYmUgcGFyc2VkIGJ5IERhdGUgYnV0IHNob3VsZG4ndCBiZS5cbiAgICBpZiAodHlwID09PSBEYXRlICYmIHR5cGVvZiB2YWwgIT09IFwibnVtYmVyXCIpXG4gICAgICAgIHJldHVybiB0cmFuc2Zvcm1EYXRlKHZhbCk7XG4gICAgcmV0dXJuIHRyYW5zZm9ybVByaW1pdGl2ZSh0eXAsIHZhbCk7XG59XG5mdW5jdGlvbiBjYXN0KHZhbCwgdHlwKSB7XG4gICAgcmV0dXJuIHRyYW5zZm9ybSh2YWwsIHR5cCwganNvblRvSlNQcm9wcyk7XG59XG5mdW5jdGlvbiB1bmNhc3QodmFsLCB0eXApIHtcbiAgICByZXR1cm4gdHJhbnNmb3JtKHZhbCwgdHlwLCBqc1RvSlNPTlByb3BzKTtcbn1cbmZ1bmN0aW9uIGwodHlwKSB7XG4gICAgcmV0dXJuIHsgbGl0ZXJhbDogdHlwIH07XG59XG5mdW5jdGlvbiBhKHR5cCkge1xuICAgIHJldHVybiB7IGFycmF5SXRlbXM6IHR5cCB9O1xufVxuZnVuY3Rpb24gdSgpIHtcbiAgICB2YXIgdHlwcyA9IFtdO1xuICAgIGZvciAodmFyIF9pID0gMDsgX2kgPCBhcmd1bWVudHMubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHR5cHNbX2ldID0gYXJndW1lbnRzW19pXTtcbiAgICB9XG4gICAgcmV0dXJuIHsgdW5pb25NZW1iZXJzOiB0eXBzIH07XG59XG5mdW5jdGlvbiBvKHByb3BzLCBhZGRpdGlvbmFsKSB7XG4gICAgcmV0dXJuIHsgcHJvcHM6IHByb3BzLCBhZGRpdGlvbmFsOiBhZGRpdGlvbmFsIH07XG59XG5mdW5jdGlvbiBtKGFkZGl0aW9uYWwpIHtcbiAgICByZXR1cm4geyBwcm9wczogW10sIGFkZGl0aW9uYWw6IGFkZGl0aW9uYWwgfTtcbn1cbmZ1bmN0aW9uIHIobmFtZSkge1xuICAgIHJldHVybiB7IHJlZjogbmFtZSB9O1xufVxudmFyIHR5cGVNYXAgPSB7XG4gICAgXCJBY3Rpb25cIjogbyhbXG4gICAgICAgIHsganNvbjogXCJhcHBcIiwganM6IFwiYXBwXCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJBY3Rpb25UYXJnZXRBcHBcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiByKFwiQ29udGV4dEVsZW1lbnRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImludGVudFwiLCBqczogXCJpbnRlbnRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpdGxlXCIsIGpzOiBcInRpdGxlXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkFjdGlvblR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkFjdGlvblRhcmdldEFwcFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImFwcElkXCIsIGpzOiBcImFwcElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiZGVza3RvcEFnZW50XCIsIGpzOiBcImRlc2t0b3BBZ2VudFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaW5zdGFuY2VJZFwiLCBqczogXCJpbnN0YW5jZUlkXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJDb250ZXh0RWxlbWVudFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IFwiXCIgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNoYXJ0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaW5zdHJ1bWVudHNcIiwganM6IFwiaW5zdHJ1bWVudHNcIiwgdHlwOiBhKHIoXCJJbnN0cnVtZW50RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm90aGVyQ29uZmlnXCIsIGpzOiBcIm90aGVyQ29uZmlnXCIsIHR5cDogdSh1bmRlZmluZWQsIGEocihcIkNvbnRleHRFbGVtZW50XCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJhbmdlXCIsIGpzOiBcInJhbmdlXCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJUaW1lUmFuZ2VPYmplY3RcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJzdHlsZVwiLCBqczogXCJzdHlsZVwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiQ2hhcnRTdHlsZVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJDaGFydFR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkluc3RydW1lbnRFbGVtZW50XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiByKFwiUHVycGxlSW5zdHJ1bWVudElkZW50aWZpZXJzXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJtYXJrZXRcIiwganM6IFwibWFya2V0XCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJPcmdhbml6YXRpb25NYXJrZXRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiUHVycGxlSW50ZXJhY3Rpb25UeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlB1cnBsZUluc3RydW1lbnRJZGVudGlmaWVyc1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcIkJCR1wiLCBqczogXCJCQkdcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkNVU0lQXCIsIGpzOiBcIkNVU0lQXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJGRFNfSURcIiwganM6IFwiRkRTX0lEXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJGSUdJXCIsIGpzOiBcIkZJR0lcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIklTSU5cIiwganM6IFwiSVNJTlwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiUEVSTUlEXCIsIGpzOiBcIlBFUk1JRFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiUklDXCIsIGpzOiBcIlJJQ1wiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiU0VET0xcIiwganM6IFwiU0VET0xcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpY2tlclwiLCBqczogXCJ0aWNrZXJcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIk9yZ2FuaXphdGlvbk1hcmtldFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcIkJCR1wiLCBqczogXCJCQkdcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkNPVU5UUllfSVNPQUxQSEEyXCIsIGpzOiBcIkNPVU5UUllfSVNPQUxQSEEyXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJNSUNcIiwganM6IFwiTUlDXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlRpbWVSYW5nZU9iamVjdFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImVuZFRpbWVcIiwganM6IFwiZW5kVGltZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBEYXRlKSB9LFxuICAgICAgICB7IGpzb246IFwic3RhcnRUaW1lXCIsIGpzOiBcInN0YXJ0VGltZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBEYXRlKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlRpbWVSYW5nZVR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNoYXRJbml0U2V0dGluZ3NcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJjaGF0TmFtZVwiLCBqczogXCJjaGF0TmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwibWVtYmVyc1wiLCBqczogXCJtZW1iZXJzXCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJDb250YWN0TGlzdE9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm1lc3NhZ2VcIiwganM6IFwibWVzc2FnZVwiLCB0eXA6IHUodW5kZWZpbmVkLCB1KHIoXCJNZXNzYWdlT2JqZWN0XCIpLCBcIlwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm9wdGlvbnNcIiwganM6IFwib3B0aW9uc1wiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiQ2hhdE9wdGlvbnNcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiQ2hhdEluaXRTZXR0aW5nc1R5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNvbnRhY3RMaXN0T2JqZWN0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiY29udGFjdHNcIiwganM6IFwiY29udGFjdHNcIiwgdHlwOiBhKHIoXCJDb250YWN0RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJDb250YWN0TGlzdFR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNvbnRhY3RFbGVtZW50XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiByKFwiUHVycGxlQ29udGFjdElkZW50aWZpZXJzXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiRmx1ZmZ5SW50ZXJhY3Rpb25UeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlB1cnBsZUNvbnRhY3RJZGVudGlmaWVyc1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImVtYWlsXCIsIGpzOiBcImVtYWlsXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJGRFNfSURcIiwganM6IFwiRkRTX0lEXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJNZXNzYWdlT2JqZWN0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiZW50aXRpZXNcIiwganM6IFwiZW50aXRpZXNcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShyKFwiUHVycGxlQWN0aW9uXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRleHRcIiwganM6IFwidGV4dFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiUHVycGxlTWVzc2FnZVRleHRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiTWVzc2FnZVR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlB1cnBsZUFjdGlvblwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImFwcFwiLCBqczogXCJhcHBcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkFjdGlvblRhcmdldEFwcFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiQ29udGV4dEVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRcIiwganM6IFwiaW50ZW50XCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aXRsZVwiLCBqczogXCJ0aXRsZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkVudGl0eVR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImRhdGFcIiwganM6IFwiZGF0YVwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiUHVycGxlRGF0YVwiKSkgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlB1cnBsZURhdGFcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJkYXRhVXJpXCIsIGpzOiBcImRhdGFVcmlcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJQdXJwbGVNZXNzYWdlVGV4dFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcInRleHQvbWFya2Rvd25cIiwganM6IFwidGV4dC9tYXJrZG93blwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGV4dC9wbGFpblwiLCBqczogXCJ0ZXh0L3BsYWluXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJDaGF0T3B0aW9uc1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImFsbG93QWRkVXNlclwiLCBqczogXCJhbGxvd0FkZFVzZXJcIiwgdHlwOiB1KHVuZGVmaW5lZCwgdHJ1ZSkgfSxcbiAgICAgICAgeyBqc29uOiBcImFsbG93SGlzdG9yeUJyb3dzaW5nXCIsIGpzOiBcImFsbG93SGlzdG9yeUJyb3dzaW5nXCIsIHR5cDogdSh1bmRlZmluZWQsIHRydWUpIH0sXG4gICAgICAgIHsganNvbjogXCJhbGxvd01lc3NhZ2VDb3B5XCIsIGpzOiBcImFsbG93TWVzc2FnZUNvcHlcIiwgdHlwOiB1KHVuZGVmaW5lZCwgdHJ1ZSkgfSxcbiAgICAgICAgeyBqc29uOiBcImdyb3VwUmVjaXBpZW50c1wiLCBqczogXCJncm91cFJlY2lwaWVudHNcIiwgdHlwOiB1KHVuZGVmaW5lZCwgdHJ1ZSkgfSxcbiAgICAgICAgeyBqc29uOiBcImlzUHVibGljXCIsIGpzOiBcImlzUHVibGljXCIsIHR5cDogdSh1bmRlZmluZWQsIHRydWUpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJDaGF0TWVzc2FnZVwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImNoYXRSb29tXCIsIGpzOiBcImNoYXRSb29tXCIsIHR5cDogcihcIkNoYXRSb29tT2JqZWN0XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJtZXNzYWdlXCIsIGpzOiBcIm1lc3NhZ2VcIiwgdHlwOiByKFwiTWVzc2FnZU9iamVjdFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkNoYXRNZXNzYWdlVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQ2hhdFJvb21PYmplY3RcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IG0oXCJhbnlcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwicHJvdmlkZXJOYW1lXCIsIGpzOiBcInByb3ZpZGVyTmFtZVwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJDaGF0Um9vbVR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInVybFwiLCBqczogXCJ1cmxcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNoYXRSb29tXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiBtKFwiYW55XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInByb3ZpZGVyTmFtZVwiLCBqczogXCJwcm92aWRlck5hbWVcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiQ2hhdFJvb21UeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ1cmxcIiwganM6IFwidXJsXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJDaGF0U2VhcmNoQ3JpdGVyaWFcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJjcml0ZXJpYVwiLCBqczogXCJjcml0ZXJpYVwiLCB0eXA6IGEodShyKFwiT3JnYW5pemF0aW9uT2JqZWN0XCIpLCBcIlwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJDaGF0U2VhcmNoQ3JpdGVyaWFUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJPcmdhbml6YXRpb25PYmplY3RcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHIoXCJJZGVudGlmaWVyc1wiKSB9LFxuICAgICAgICB7IGpzb246IFwibWFya2V0XCIsIGpzOiBcIm1hcmtldFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiT3JnYW5pemF0aW9uTWFya2V0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlRlbnRhY2xlZEludGVyYWN0aW9uVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJJZGVudGlmaWVyc1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcIkJCR1wiLCBqczogXCJCQkdcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkNVU0lQXCIsIGpzOiBcIkNVU0lQXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJGRFNfSURcIiwganM6IFwiRkRTX0lEXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJGSUdJXCIsIGpzOiBcIkZJR0lcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIklTSU5cIiwganM6IFwiSVNJTlwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiUEVSTUlEXCIsIGpzOiBcIlBFUk1JRFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiUklDXCIsIGpzOiBcIlJJQ1wiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiU0VET0xcIiwganM6IFwiU0VET0xcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpY2tlclwiLCBqczogXCJ0aWNrZXJcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkxFSVwiLCBqczogXCJMRUlcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImVtYWlsXCIsIGpzOiBcImVtYWlsXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJDb250YWN0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiByKFwiRmx1ZmZ5Q29udGFjdElkZW50aWZpZXJzXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiRmx1ZmZ5SW50ZXJhY3Rpb25UeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkZsdWZmeUNvbnRhY3RJZGVudGlmaWVyc1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImVtYWlsXCIsIGpzOiBcImVtYWlsXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJGRFNfSURcIiwganM6IFwiRkRTX0lEXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJDb250YWN0TGlzdFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImNvbnRhY3RzXCIsIGpzOiBcImNvbnRhY3RzXCIsIHR5cDogYShyKFwiQ29udGFjdEVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiQ29udGFjdExpc3RUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJDb250ZXh0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQ291bnRyeVwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogcihcIkNvdW50cnlJRFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkNvdW50cnlUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNvdW50cnlJRFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcIkNPVU5UUllfSVNPQUxQSEEyXCIsIGpzOiBcIkNPVU5UUllfSVNPQUxQSEEyXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJDT1VOVFJZX0lTT0FMUEhBM1wiLCBqczogXCJDT1VOVFJZX0lTT0FMUEhBM1wiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiSVNPQUxQSEEyXCIsIGpzOiBcIklTT0FMUEhBMlwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiSVNPQUxQSEEzXCIsIGpzOiBcIklTT0FMUEhBM1wiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQ3VycmVuY3lcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHIoXCJDdXJyZW5jeUlEXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJDdXJyZW5jeVR5cGVcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkN1cnJlbmN5SURcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJDVVJSRU5DWV9JU09DT0RFXCIsIGpzOiBcIkNVUlJFTkNZX0lTT0NPREVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkVtYWlsXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwicmVjaXBpZW50c1wiLCBqczogXCJyZWNpcGllbnRzXCIsIHR5cDogcihcIkVtYWlsUmVjaXBpZW50c1wiKSB9LFxuICAgICAgICB7IGpzb246IFwic3ViamVjdFwiLCBqczogXCJzdWJqZWN0XCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0ZXh0Qm9keVwiLCBqczogXCJ0ZXh0Qm9keVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkVtYWlsVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiRW1haWxSZWNpcGllbnRzXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkVtYWlsUmVjaXBpZW50c0lEXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkVtYWlsUmVjaXBpZW50c1R5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiY29udGFjdHNcIiwganM6IFwiY29udGFjdHNcIiwgdHlwOiB1KHVuZGVmaW5lZCwgYShyKFwiQ29udGFjdEVsZW1lbnRcIikpKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiRW1haWxSZWNpcGllbnRzSURcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJlbWFpbFwiLCBqczogXCJlbWFpbFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiRkRTX0lEXCIsIGpzOiBcIkZEU19JRFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiSW5zdHJ1bWVudFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogcihcIkZsdWZmeUluc3RydW1lbnRJZGVudGlmaWVyc1wiKSB9LFxuICAgICAgICB7IGpzb246IFwibWFya2V0XCIsIGpzOiBcIm1hcmtldFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiUHVycGxlTWFya2V0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlB1cnBsZUludGVyYWN0aW9uVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJGbHVmZnlJbnN0cnVtZW50SWRlbnRpZmllcnNcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJCQkdcIiwganM6IFwiQkJHXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJDVVNJUFwiLCBqczogXCJDVVNJUFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiRkRTX0lEXCIsIGpzOiBcIkZEU19JRFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiRklHSVwiLCBqczogXCJGSUdJXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJJU0lOXCIsIGpzOiBcIklTSU5cIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIlBFUk1JRFwiLCBqczogXCJQRVJNSURcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIlJJQ1wiLCBqczogXCJSSUNcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIlNFRE9MXCIsIGpzOiBcIlNFRE9MXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aWNrZXJcIiwganM6IFwidGlja2VyXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJQdXJwbGVNYXJrZXRcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJCQkdcIiwganM6IFwiQkJHXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJDT1VOVFJZX0lTT0FMUEhBMlwiLCBqczogXCJDT1VOVFJZX0lTT0FMUEhBMlwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiTUlDXCIsIGpzOiBcIk1JQ1wiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJJbnN0cnVtZW50TGlzdFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImluc3RydW1lbnRzXCIsIGpzOiBcImluc3RydW1lbnRzXCIsIHR5cDogYShyKFwiSW5zdHJ1bWVudEVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiSW5zdHJ1bWVudExpc3RUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJJbnRlcmFjdGlvblwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImRlc2NyaXB0aW9uXCIsIGpzOiBcImRlc2NyaXB0aW9uXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkludGVyYWN0aW9uSURcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJpbml0aWF0b3JcIiwganM6IFwiaW5pdGlhdG9yXCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJDb250YWN0RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImludGVyYWN0aW9uVHlwZVwiLCBqczogXCJpbnRlcmFjdGlvblR5cGVcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJvcmlnaW5cIiwganM6IFwib3JpZ2luXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXJ0aWNpcGFudHNcIiwganM6IFwicGFydGljaXBhbnRzXCIsIHR5cDogcihcIkNvbnRhY3RMaXN0T2JqZWN0XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lUmFuZ2VcIiwganM6IFwidGltZVJhbmdlXCIsIHR5cDogcihcIlRpbWVSYW5nZU9iamVjdFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkludGVyYWN0aW9uVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJJbnRlcmFjdGlvbklEXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiU0FMRVNGT1JDRVwiLCBqczogXCJTQUxFU0ZPUkNFXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJTSU5HTEVUUkFDS1wiLCBqczogXCJTSU5HTEVUUkFDS1wiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiVVJJXCIsIGpzOiBcIlVSSVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiTWVzc2FnZVwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImVudGl0aWVzXCIsIGpzOiBcImVudGl0aWVzXCIsIHR5cDogdSh1bmRlZmluZWQsIG0ocihcIkZsdWZmeUFjdGlvblwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJ0ZXh0XCIsIGpzOiBcInRleHRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkZsdWZmeU1lc3NhZ2VUZXh0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIk1lc3NhZ2VUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJGbHVmZnlBY3Rpb25cIjogbyhbXG4gICAgICAgIHsganNvbjogXCJhcHBcIiwganM6IFwiYXBwXCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJBY3Rpb25UYXJnZXRBcHBcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkNvbnRleHRFbGVtZW50XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiaW50ZW50XCIsIGpzOiBcImludGVudFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGl0bGVcIiwganM6IFwidGl0bGVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJFbnRpdHlUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJkYXRhXCIsIGpzOiBcImRhdGFcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkZsdWZmeURhdGFcIikpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJGbHVmZnlEYXRhXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiZGF0YVVyaVwiLCBqczogXCJkYXRhVXJpXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiRmx1ZmZ5TWVzc2FnZVRleHRcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJ0ZXh0L21hcmtkb3duXCIsIGpzOiBcInRleHQvbWFya2Rvd25cIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRleHQvcGxhaW5cIiwganM6IFwidGV4dC9wbGFpblwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiTm90aGluZ1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJOb3RoaW5nVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiT3JkZXJcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJkZXRhaWxzXCIsIGpzOiBcImRldGFpbHNcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIlB1cnBsZU9yZGVyRGV0YWlsc1wiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogbShcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiT3JkZXJUeXBlXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJQdXJwbGVPcmRlckRldGFpbHNcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJwcm9kdWN0XCIsIGpzOiBcInByb2R1Y3RcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIlByb2R1Y3RPYmplY3RcIikpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJQcm9kdWN0T2JqZWN0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiBtKFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0cnVtZW50XCIsIGpzOiBcImluc3RydW1lbnRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkluc3RydW1lbnRFbGVtZW50XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiUHJvZHVjdFR5cGVcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIk9yZGVyTGlzdFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcIm9yZGVyc1wiLCBqczogXCJvcmRlcnNcIiwgdHlwOiBhKHIoXCJPcmRlckVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiT3JkZXJMaXN0VHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiT3JkZXJFbGVtZW50XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiZGV0YWlsc1wiLCBqczogXCJkZXRhaWxzXCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJGbHVmZnlPcmRlckRldGFpbHNcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IG0oXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIk9yZGVyVHlwZVwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiRmx1ZmZ5T3JkZXJEZXRhaWxzXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwicHJvZHVjdFwiLCBqczogXCJwcm9kdWN0XCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJQcm9kdWN0T2JqZWN0XCIpKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiT3JnYW5pemF0aW9uXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiByKFwiT3JnYW5pemF0aW9uSWRlbnRpZmllcnNcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJTdGlja3lJbnRlcmFjdGlvblR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiT3JnYW5pemF0aW9uSWRlbnRpZmllcnNcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJGRFNfSURcIiwganM6IFwiRkRTX0lEXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJMRUlcIiwganM6IFwiTEVJXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJQRVJNSURcIiwganM6IFwiUEVSTUlEXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJQb3J0Zm9saW9cIjogbyhbXG4gICAgICAgIHsganNvbjogXCJwb3NpdGlvbnNcIiwganM6IFwicG9zaXRpb25zXCIsIHR5cDogYShyKFwiUG9zaXRpb25FbGVtZW50XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlBvcnRmb2xpb1R5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlBvc2l0aW9uRWxlbWVudFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImhvbGRpbmdcIiwganM6IFwiaG9sZGluZ1wiLCB0eXA6IDMuMTQgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RydW1lbnRcIiwganM6IFwiaW5zdHJ1bWVudFwiLCB0eXA6IHIoXCJJbnN0cnVtZW50RWxlbWVudFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlBvc2l0aW9uVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiUG9zaXRpb25cIjogbyhbXG4gICAgICAgIHsganNvbjogXCJob2xkaW5nXCIsIGpzOiBcImhvbGRpbmdcIiwgdHlwOiAzLjE0IH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0cnVtZW50XCIsIGpzOiBcImluc3RydW1lbnRcIiwgdHlwOiByKFwiSW5zdHJ1bWVudEVsZW1lbnRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJQb3NpdGlvblR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlByb2R1Y3RcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IG0oXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RydW1lbnRcIiwganM6IFwiaW5zdHJ1bWVudFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiSW5zdHJ1bWVudEVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJQcm9kdWN0VHlwZVwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiVGltZVJhbmdlXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiZW5kVGltZVwiLCBqczogXCJlbmRUaW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIERhdGUpIH0sXG4gICAgICAgIHsganNvbjogXCJzdGFydFRpbWVcIiwganM6IFwic3RhcnRUaW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIERhdGUpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiVGltZVJhbmdlVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiVHJhZGVcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IG0oXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwicHJvZHVjdFwiLCBqczogXCJwcm9kdWN0XCIsIHR5cDogcihcIlByb2R1Y3RPYmplY3RcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJUcmFkZVR5cGVcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlRyYWRlTGlzdFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcInRyYWRlc1wiLCBqczogXCJ0cmFkZXNcIiwgdHlwOiBhKHIoXCJUcmFkZUVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiVHJhZGVMaXN0VHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiVHJhZGVFbGVtZW50XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiBtKFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInByb2R1Y3RcIiwganM6IFwicHJvZHVjdFwiLCB0eXA6IHIoXCJQcm9kdWN0T2JqZWN0XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiVHJhZGVUeXBlXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJUcmFuc2FjdGlvblJlc3VsdFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiQ29udGV4dEVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJtZXNzYWdlXCIsIGpzOiBcIm1lc3NhZ2VcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInN0YXR1c1wiLCBqczogXCJzdGF0dXNcIiwgdHlwOiByKFwiVHJhbnNhY3Rpb25TdGF0dXNcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJUcmFuc2FjdGlvblJlc3VsdFR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlZhbHVhdGlvblwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcIkNVUlJFTkNZX0lTT0NPREVcIiwganM6IFwiQ1VSUkVOQ1lfSVNPQ09ERVwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImV4cGlyeVRpbWVcIiwganM6IFwiZXhwaXJ5VGltZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBEYXRlKSB9LFxuICAgICAgICB7IGpzb246IFwicHJpY2VcIiwganM6IFwicHJpY2VcIiwgdHlwOiB1KHVuZGVmaW5lZCwgMy4xNCkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJWYWx1YXRpb25UeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ2YWx1YXRpb25UaW1lXCIsIGpzOiBcInZhbHVhdGlvblRpbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgRGF0ZSkgfSxcbiAgICAgICAgeyBqc29uOiBcInZhbHVlXCIsIGpzOiBcInZhbHVlXCIsIHR5cDogMy4xNCB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQWN0aW9uVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5hY3Rpb25cIixcbiAgICBdLFxuICAgIFwiUHVycGxlSW50ZXJhY3Rpb25UeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmluc3RydW1lbnRcIixcbiAgICBdLFxuICAgIFwiVGltZVJhbmdlVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy50aW1lUmFuZ2VcIixcbiAgICBdLFxuICAgIFwiQ2hhcnRTdHlsZVwiOiBbXG4gICAgICAgIFwiYmFyXCIsXG4gICAgICAgIFwiY2FuZGxlXCIsXG4gICAgICAgIFwiY3VzdG9tXCIsXG4gICAgICAgIFwiaGVhdG1hcFwiLFxuICAgICAgICBcImhpc3RvZ3JhbVwiLFxuICAgICAgICBcImxpbmVcIixcbiAgICAgICAgXCJtb3VudGFpblwiLFxuICAgICAgICBcInBpZVwiLFxuICAgICAgICBcInNjYXR0ZXJcIixcbiAgICAgICAgXCJzdGFja2VkLWJhclwiLFxuICAgIF0sXG4gICAgXCJDaGFydFR5cGVcIjogW1xuICAgICAgICBcImZkYzMuY2hhcnRcIixcbiAgICBdLFxuICAgIFwiRmx1ZmZ5SW50ZXJhY3Rpb25UeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmNvbnRhY3RcIixcbiAgICBdLFxuICAgIFwiQ29udGFjdExpc3RUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmNvbnRhY3RMaXN0XCIsXG4gICAgXSxcbiAgICBcIkVudGl0eVR5cGVcIjogW1xuICAgICAgICBcImZkYzMuYWN0aW9uXCIsXG4gICAgICAgIFwiZmRjMy5lbnRpdHkuZmlsZUF0dGFjaG1lbnRcIixcbiAgICBdLFxuICAgIFwiTWVzc2FnZVR5cGVcIjogW1xuICAgICAgICBcImZkYzMubWVzc2FnZVwiLFxuICAgIF0sXG4gICAgXCJDaGF0SW5pdFNldHRpbmdzVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5jaGF0LmluaXRTZXR0aW5nc1wiLFxuICAgIF0sXG4gICAgXCJDaGF0Um9vbVR5cGVcIjogW1xuICAgICAgICBcImZkYzMuY2hhdC5yb29tXCIsXG4gICAgXSxcbiAgICBcIkNoYXRNZXNzYWdlVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5jaGF0Lm1lc3NhZ2VcIixcbiAgICBdLFxuICAgIFwiVGVudGFjbGVkSW50ZXJhY3Rpb25UeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmNvbnRhY3RcIixcbiAgICAgICAgXCJmZGMzLmluc3RydW1lbnRcIixcbiAgICAgICAgXCJmZGMzLm9yZ2FuaXphdGlvblwiLFxuICAgIF0sXG4gICAgXCJDaGF0U2VhcmNoQ3JpdGVyaWFUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmNoYXQuc2VhcmNoQ3JpdGVyaWFcIixcbiAgICBdLFxuICAgIFwiQ291bnRyeVR5cGVcIjogW1xuICAgICAgICBcImZkYzMuY291bnRyeVwiLFxuICAgIF0sXG4gICAgXCJDdXJyZW5jeVR5cGVcIjogW1xuICAgICAgICBcImZkYzMuY3VycmVuY3lcIixcbiAgICBdLFxuICAgIFwiRW1haWxSZWNpcGllbnRzVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5jb250YWN0XCIsXG4gICAgICAgIFwiZmRjMy5jb250YWN0TGlzdFwiLFxuICAgIF0sXG4gICAgXCJFbWFpbFR5cGVcIjogW1xuICAgICAgICBcImZkYzMuZW1haWxcIixcbiAgICBdLFxuICAgIFwiSW5zdHJ1bWVudExpc3RUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmluc3RydW1lbnRMaXN0XCIsXG4gICAgXSxcbiAgICBcIkludGVyYWN0aW9uVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5pbnRlcmFjdGlvblwiLFxuICAgIF0sXG4gICAgXCJOb3RoaW5nVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5ub3RoaW5nXCIsXG4gICAgXSxcbiAgICBcIlByb2R1Y3RUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLnByb2R1Y3RcIixcbiAgICBdLFxuICAgIFwiT3JkZXJUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLm9yZGVyXCIsXG4gICAgXSxcbiAgICBcIk9yZGVyTGlzdFR5cGVcIjogW1xuICAgICAgICBcImZkYzMub3JkZXJMaXN0XCIsXG4gICAgXSxcbiAgICBcIlN0aWNreUludGVyYWN0aW9uVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5vcmdhbml6YXRpb25cIixcbiAgICBdLFxuICAgIFwiUG9zaXRpb25UeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLnBvc2l0aW9uXCIsXG4gICAgXSxcbiAgICBcIlBvcnRmb2xpb1R5cGVcIjogW1xuICAgICAgICBcImZkYzMucG9ydGZvbGlvXCIsXG4gICAgXSxcbiAgICBcIlRyYWRlVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy50cmFkZVwiLFxuICAgIF0sXG4gICAgXCJUcmFkZUxpc3RUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLnRyYWRlTGlzdFwiLFxuICAgIF0sXG4gICAgXCJUcmFuc2FjdGlvblN0YXR1c1wiOiBbXG4gICAgICAgIFwiQ3JlYXRlZFwiLFxuICAgICAgICBcIkRlbGV0ZWRcIixcbiAgICAgICAgXCJGYWlsZWRcIixcbiAgICAgICAgXCJVcGRhdGVkXCIsXG4gICAgXSxcbiAgICBcIlRyYW5zYWN0aW9uUmVzdWx0VHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy50cmFuc2FjdGlvblJlc3VsdFwiLFxuICAgIF0sXG4gICAgXCJWYWx1YXRpb25UeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLnZhbHVhdGlvblwiLFxuICAgIF1cbn07XG5cbi8qKlxuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqIENvcHlyaWdodCBGSU5PUyBGREMzIGNvbnRyaWJ1dG9ycyAtIHNlZSBOT1RJQ0UgZmlsZVxuICovXG4vKipcbiAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgU3RhbmRhcmRJbnRlbnR9IGluc3RlYWRcbiAqL1xudmFyIEludGVudHM7XG4oZnVuY3Rpb24gKEludGVudHMpIHtcbiAgICBJbnRlbnRzW1wiQ3JlYXRlSW50ZXJhY3Rpb25cIl0gPSBcIkNyZWF0ZUludGVyYWN0aW9uXCI7XG4gICAgSW50ZW50c1tcIlNlbmRDaGF0TWVzc2FnZVwiXSA9IFwiU2VuZENoYXRNZXNzYWdlXCI7XG4gICAgSW50ZW50c1tcIlN0YXJ0Q2FsbFwiXSA9IFwiU3RhcnRDYWxsXCI7XG4gICAgSW50ZW50c1tcIlN0YXJ0Q2hhdFwiXSA9IFwiU3RhcnRDaGF0XCI7XG4gICAgSW50ZW50c1tcIlN0YXJ0RW1haWxcIl0gPSBcIlN0YXJ0RW1haWxcIjtcbiAgICBJbnRlbnRzW1wiVmlld0FuYWx5c2lzXCJdID0gXCJWaWV3QW5hbHlzaXNcIjtcbiAgICBJbnRlbnRzW1wiVmlld0NoYXRcIl0gPSBcIlZpZXdDaGF0XCI7XG4gICAgSW50ZW50c1tcIlZpZXdDaGFydFwiXSA9IFwiVmlld0NoYXJ0XCI7XG4gICAgSW50ZW50c1tcIlZpZXdDb250YWN0XCJdID0gXCJWaWV3Q29udGFjdFwiO1xuICAgIEludGVudHNbXCJWaWV3SG9sZGluZ3NcIl0gPSBcIlZpZXdIb2xkaW5nc1wiO1xuICAgIEludGVudHNbXCJWaWV3SW5zdHJ1bWVudFwiXSA9IFwiVmlld0luc3RydW1lbnRcIjtcbiAgICBJbnRlbnRzW1wiVmlld0ludGVyYWN0aW9uc1wiXSA9IFwiVmlld0ludGVyYWN0aW9uc1wiO1xuICAgIEludGVudHNbXCJWaWV3TWVzc2FnZXNcIl0gPSBcIlZpZXdNZXNzYWdlc1wiO1xuICAgIEludGVudHNbXCJWaWV3TmV3c1wiXSA9IFwiVmlld05ld3NcIjtcbiAgICBJbnRlbnRzW1wiVmlld09yZGVyc1wiXSA9IFwiVmlld09yZGVyc1wiO1xuICAgIEludGVudHNbXCJWaWV3UHJvZmlsZVwiXSA9IFwiVmlld1Byb2ZpbGVcIjtcbiAgICBJbnRlbnRzW1wiVmlld1F1b3RlXCJdID0gXCJWaWV3UXVvdGVcIjtcbiAgICBJbnRlbnRzW1wiVmlld1Jlc2VhcmNoXCJdID0gXCJWaWV3UmVzZWFyY2hcIjtcbn0pKEludGVudHMgfHwgKEludGVudHMgPSB7fSkpO1xuXG5leHBvcnQgeyBCcmlkZ2luZ0Vycm9yLCBCcmlkZ2luZ1R5cGVzLCBDaGFubmVsRXJyb3IsIENvbnRleHRUeXBlcywgQ29udmVydCwgSW50ZW50cywgT3BlbkVycm9yLCBSZXNvbHZlRXJyb3IsIFJlc3VsdEVycm9yLCBhZGRDb250ZXh0TGlzdGVuZXIsIGFkZEludGVudExpc3RlbmVyLCBicm9hZGNhc3QsIGNvbXBhcmVWZXJzaW9uTnVtYmVycywgY3JlYXRlUHJpdmF0ZUNoYW5uZWwsIGZkYzNSZWFkeSwgZmluZEluc3RhbmNlcywgZmluZEludGVudCwgZmluZEludGVudHNCeUNvbnRleHQsIGdldEFwcE1ldGFkYXRhLCBnZXRDdXJyZW50Q2hhbm5lbCwgZ2V0SW5mbywgZ2V0T3JDcmVhdGVDaGFubmVsLCBnZXRTeXN0ZW1DaGFubmVscywgZ2V0VXNlckNoYW5uZWxzLCBpc1N0YW5kYXJkQ29udGV4dFR5cGUsIGlzU3RhbmRhcmRJbnRlbnQsIGpvaW5DaGFubmVsLCBqb2luVXNlckNoYW5uZWwsIGxlYXZlQ3VycmVudENoYW5uZWwsIG9wZW4sIHJhaXNlSW50ZW50LCByYWlzZUludGVudEZvckNvbnRleHQsIHZlcnNpb25Jc0F0TGVhc3QgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWZkYzMuZXNtLmpzLm1hcFxuIiwidmFyIGUsdCxyPXtkOihlLHQpPT57Zm9yKHZhciBhIGluIHQpci5vKHQsYSkmJiFyLm8oZSxhKSYmT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsYSx7ZW51bWVyYWJsZTohMCxnZXQ6dFthXX0pfSxvOihlLHQpPT5PYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZSx0KX0sYT17fTtyLmQoYSx7ZHE6KCk9PkFkYXB0ZXJFcnJvcixNUzooKT0+QXBpRXJyb3IseFE6KCk9PkV2ZW50RXJyb3Isc086KCk9PldlLFp1OigpPT5mZSxJMzooKT0+JGUsJFU6KCk9PkdlLGkwOigpPT5JZSxjWDooKT0+SW5pdGlhbGl6YXRpb25FcnJvcixnSDooKT0+SW52YWxpZENlbGxSYW5nZUFkZHJlc3NFcnJvcixfVzooKT0+UGFyYW1ldGVyRXJyb3IsVSQ6KCk9PmksVTc6KCk9PmwscmQ6KCk9PmJlfSk7Y2xhc3MgQXBpRXJyb3IgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihlPVwiQW4gdW5leHBlY3RlZCBlcnJvciBoYXMgb2NjdXJyZWRcIix0KXt2YXIgcjtzdXBlcihlKSx0JiYodGhpcy5pbm5lckVycm9yPXQmJnQpLHRoaXMuc3RhY2s9bnVsbD09PShyPXRoaXMuc3RhY2spfHx2b2lkIDA9PT1yP3ZvaWQgMDpyLnJlcGxhY2UoL14oXFx3KkVycm9yKS8sYCR7dGhpcy5jb25zdHJ1Y3Rvci5uYW1lfWApfX1jbGFzcyBBZGFwdGVyRXJyb3IgZXh0ZW5kcyBBcGlFcnJvcntjb25zdHJ1Y3RvcihlPVwiRmFpbGVkIHRvIGV4ZWN1dGUgYWRhcHRlciBmdW5jdGlvblwiLHQpe3N1cGVyKGUsdCl9fWNsYXNzIEV2ZW50RXJyb3IgZXh0ZW5kcyBBcGlFcnJvcntjb25zdHJ1Y3RvcihlPVwiRmFpbGVkIHRvIHJhaXNlIGV2ZW50XCIsdCl7c3VwZXIoZSx0KX19Y2xhc3MgSW5pdGlhbGl6YXRpb25FcnJvciBleHRlbmRzIEFwaUVycm9ye2NvbnN0cnVjdG9yKGU9XCJGYWlsZWQgdG8gaW5pdGlhbGl6ZSBhZGFwdGVyXCIsdCl7c3VwZXIoZSx0KX19Y2xhc3MgSW52YWxpZENlbGxSYW5nZUFkZHJlc3NFcnJvciBleHRlbmRzIEFwaUVycm9ye2NvbnN0cnVjdG9yKGU9XCJUaGUgY2VsbCByYW5nZSBhZGRyZXNzIGlzIG5vdCB2YWxpZFwiLHQpe3N1cGVyKGUsdCl9fWNsYXNzIFBhcmFtZXRlckVycm9yIGV4dGVuZHMgQXBpRXJyb3J7Y29uc3RydWN0b3IoZT1cIkludmFsaWQgcGFyYW1ldGVyIHZhbHVlXCIsdCl7c3VwZXIoZSx0KX19IWZ1bmN0aW9uKGUpe2UuQWN0aXZhdGVXb3JrYm9vaz1cIkFjdGl2YXRlV29ya2Jvb2tcIixlLkFjdGl2YXRlV29ya3NoZWV0PVwiQWN0aXZhdGVXb3Jrc2hlZXRcIixlLkFkZFdvcmtzaGVldD1cIkFkZFdvcmtzaGVldFwiLGUuQ2FsY3VsYXRlV29ya2Jvb2s9XCJDYWxjdWxhdGVXb3JrYm9va1wiLGUuQ2FsY3VsYXRlV29ya3NoZWV0PVwiQ2FsY3VsYXRlV29ya3NoZWV0XCIsZS5DbGVhckFsbENlbGxzPVwiQ2xlYXJBbGxDZWxsc1wiLGUuQ2xlYXJBbGxDZWxsVmFsdWVzPVwiQ2xlYXJBbGxDZWxsVmFsdWVzXCIsZS5DbGVhckFsbENlbGxGb3JtYXR0aW5nPVwiQ2xlYXJBbGxDZWxsRm9ybWF0dGluZ1wiLGUuQ2xlYXJDZWxsVmFsdWVzPVwiQ2xlYXJDZWxsVmFsdWVzXCIsZS5DbGVhckNlbGxGb3JtYXR0aW5nPVwiQ2xlYXJDZWxsRm9ybWF0dGluZ1wiLGUuQ2xlYXJDZWxscz1cIkNsZWFyQ2VsbHNcIixlLkNsb3NlV29ya2Jvb2s9XCJDbG9zZVdvcmtib29rXCIsZS5DcmVhdGVXb3JrYm9vaz1cIkNyZWF0ZVdvcmtib29rXCIsZS5EZWxldGVXb3Jrc2hlZXQ9XCJEZWxldGVXb3Jrc2hlZXRcIixlLkRlcmVnaXN0ZXJFdmVudD1cIkRlcmVnaXN0ZXJFdmVudFwiLGUuRXZlbnRGaXJlZD1cIkV2ZW50RmlyZWRcIixlLkZpbHRlckNlbGxzPVwiRmlsdGVyQ2VsbHNcIixlLkdldEFjdGl2ZVdvcmtzaGVldD1cIkdldEFjdGl2ZVdvcmtzaGVldFwiLGUuR2V0Q2FsY3VsYXRpb25Nb2RlPVwiR2V0Q2FsY3VsYXRpb25Nb2RlXCIsZS5HZXRDZWxsTmFtZXM9XCJHZXRDZWxsTmFtZXNcIixlLkdldENlbGxzPVwiR2V0Q2VsbHNcIixlLkdldFJhbmdlQWRkcmVzcz1cIkdldFJhbmdlQWRkcmVzc1wiLGUuR2V0V29ya2Jvb2tCeUlkPVwiR2V0V29ya2Jvb2tCeUlkXCIsZS5HZXRXb3JrYm9va0ZpbGVQYXRoPVwiR2V0V29ya2Jvb2tGaWxlUGF0aFwiLGUuR2V0V29ya2Jvb2tOYW1lPVwiR2V0V29ya2Jvb2tOYW1lXCIsZS5HZXRXb3JrYm9va3M9XCJHZXRXb3JrYm9va3NcIixlLkdldFdvcmtib29rV2luZG93Qm91bmRzPVwiR2V0V29ya2Jvb2tXaW5kb3dCb3VuZHNcIixlLkdldFdvcmtzaGVldEJ5SWQ9XCJHZXRXb3Jrc2hlZXRCeUlkXCIsZS5HZXRXb3Jrc2hlZXRCeU5hbWU9XCJHZXRXb3Jrc2hlZXRCeU5hbWVcIixlLkdldFdvcmtzaGVldE5hbWU9XCJHZXRXb3Jrc2hlZXROYW1lXCIsZS5HZXRXb3Jrc2hlZXRzPVwiR2V0V29ya3NoZWV0c1wiLGUuTG9nTWVzc2FnZT1cIkxvZ01lc3NhZ2VcIixlLk9wZW5Xb3JrYm9vaz1cIk9wZW5Xb3JrYm9va1wiLGUuUHJvdGVjdFdvcmtzaGVldD1cIlByb3RlY3RXb3Jrc2hlZXRcIixlLlF1aXRBcHBsaWNhdGlvbj1cIlF1aXRBcHBsaWNhdGlvblwiLGUuUmVnaXN0ZXJFdmVudD1cIlJlZ2lzdGVyRXZlbnRcIixlLlNhdmVXb3JrYm9vaz1cIlNhdmVXb3JrYm9va1wiLGUuU2F2ZVdvcmtib29rQXM9XCJTYXZlV29ya2Jvb2tBc1wiLGUuU2V0Q2VsbFZhbHVlcz1cIlNldENlbGxWYWx1ZXNcIixlLlNldENlbGxGb3JtYXR0aW5nPVwiU2V0Q2VsbEZvcm1hdHRpbmdcIixlLlNldENlbGxOYW1lPVwiU2V0Q2VsbE5hbWVcIixlLlNldFdvcmtib29rV2luZG93Qm91bmRzPVwiU2V0V29ya2Jvb2tXaW5kb3dCb3VuZHNcIixlLlNldFdvcmtzaGVldE5hbWU9XCJTZXRXb3Jrc2hlZXROYW1lXCJ9KGV8fChlPXt9KSksZnVuY3Rpb24oZSl7ZS5BY3RpdmF0ZT1cIkFjdGl2YXRlXCIsZS5BY3RpdmF0ZVdvcmtzaGVldD1cIkFjdGl2YXRlV29ya3NoZWV0XCIsZS5BZGRXb3Jrc2hlZXQ9XCJBZGRXb3Jrc2hlZXRcIixlLkNoYW5nZT1cIkNoYW5nZVwiLGUuQ2xvc2U9XCJDbG9zZVwiLGUuRGVhY3RpdmF0ZT1cIkRlYWN0aXZhdGVcIixlLkRlbGV0ZVdvcmtzaGVldD1cIkRlbGV0ZVdvcmtzaGVldFwifSh0fHwodD17fSkpO2NvbnN0IG89XCIxLjUuMFwiO2xldCBuPSExO2NvbnN0IHM9XCJbQG9wZW5maW4vZXhjZWxdXCIsaT0oKT0+e249ITF9LGw9KCk9PntuPSEwLGQoYHYke299YCl9LGM9KGUsdCk9PntuJiYoZS5pbm5lckVycm9yP2NvbnNvbGUuZXJyb3IodD9gJHtzfSAke3R9YDpzLGUsXCJcXG5cXG4oaW5uZXIpXCIsZS5pbm5lckVycm9yKTpjb25zb2xlLmVycm9yKHQ/YCR7c30gJHt0fWA6cyxlKSl9LGQ9KC4uLmUpPT57biYmY29uc29sZS5sb2cocywuLi5lKX0saD0oLi4uZSk9PntuJiZjb25zb2xlLndhcm4ocywuLi5lKX07XCJ1bmRlZmluZWRcIj09dHlwZW9mIGZpbiYmT2JqZWN0LmFzc2lnbih3aW5kb3cse2Zpbjp7fX0pLE9iamVjdC5hc3NpZ24oZmluLHtJbnRlZ3JhdGlvbnM6e0V4Y2VsOntlbmFibGVMb2dnaW5nOmwsZGlzYWJsZUxvZ2dpbmc6aX19fSk7Y29uc3Qgdz1uZXcgTWFwLHA9YXN5bmMocixhLG8sbixzKT0+e2lmKCFhfHwhYS5ldmVudFRhcmdldHx8IWEub2JqZWN0SWQpe2NvbnN0IGU9bmV3IEV2ZW50RXJyb3IoXCJFdmVudCByZWdpc3RyYXRpb24gbWlzc2luZyByZXF1aXJlZCB2YWx1ZXNcIik7dGhyb3cgYyhlKSxlfWNvbnN0IGk9T2JqZWN0LmtleXModCkuZmluZCgoZT0+ZS50b0xvd2VyQ2FzZSgpPT09by50b0xvd2VyQ2FzZSgpKSk7aWYoIWkpe2NvbnN0IGU9bmV3IEV2ZW50RXJyb3IoYFVuc3VwcG9ydGVkIGV2ZW50IG5hbWU6ICR7b31gKTt0aHJvdyBjKGUpLGV9Y29uc3QgbD1PYmplY3QuYXNzaWduKHtldmVudE5hbWU6dFtpXX0sYSk7ZChcIlJlZ2lzdGVyaW5nIGV2ZW50XCIsbCk7dHJ5e2NvbnN0IHQ9YXdhaXQgci5kaXNwYXRjaChlLlJlZ2lzdGVyRXZlbnQsbCksYT17aGFuZGxlcjpzLGxpc3RlbmVyOm59O3cuc2V0KHQsYSl9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcih2b2lkIDAsZSl9fSxrPShlLHQpPT57Y29uc3R7ZXZlbnRSZWdpc3RyYXRpb25JZDpyfT1lLGE9dy5nZXQocik7aWYoIWEpdGhyb3cgbmV3IEV2ZW50RXJyb3IoYE5vIHJlZ2lzdGVyZWQgZXZlbnQgbGlzdGVuZXIgZm91bmQgZm9yIGlkOiAke3J9YCk7ZChcIkV2ZW50IHBheWxvYWQgcmVjZWl2ZWRcIixlKSxhLmhhbmRsZXIoZSl9LHU9dD0+YXN5bmMgcj0+e2xldCBhO2Zvcihjb25zdFtlLHRdb2YgdylpZih0Lmxpc3RlbmVyPT09cil7YT1lO2JyZWFrfWlmKCFhKXRocm93IG5ldyBFdmVudEVycm9yO2QoXCJEZXJlZ2lzdGVyaW5nIGV2ZW50OlwiLGEpO3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuRGVyZWdpc3RlckV2ZW50LGEpLHcuZGVsZXRlKGEpfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fTt2YXIgZzshZnVuY3Rpb24oZSl7ZS5Xb3JrYm9vaz1cIldvcmtib29rXCIsZS5Xb3Jrc2hlZXQ9XCJXb3Jrc2hlZXRcIixlLkNlbGxSYW5nZT1cIkNlbGxSYW5nZVwifShnfHwoZz17fSkpO2NvbnN0IG09KCk9PnZvaWQgMCE9PWNyeXB0by5yYW5kb21VVUlEP2NyeXB0by5yYW5kb21VVUlEKCk6XCIxMDAwMDAwMC0xMDAwLTQwMDAtODAwMC0xMDAwMDAwMDAwMDBcIi5yZXBsYWNlKC9bMDE4XS9nLChlPT57Y29uc3QgdD13aW5kb3cuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhuZXcgVWludDhBcnJheSgxKSlbMF0mMTU+Pk51bWJlcihlKS80O3JldHVybihOdW1iZXIoZSledCkudG9TdHJpbmcoMTYpfSkpLEM9bmV3IE1hcCx5PShlLHQpPT5hc3luYyhyLGEpPT5wKGUsdCxyLGEsVyhhKSksdj0odCxyLGEpPT5hc3luYygpPT57ZChgQ2VsbCByYW5nZTogQ2xlYXI7IGFkZHJlc3M6JHthfSAoJHtyfSlgKTtjb25zdCBvPXthZGRyZXNzOmEsb2JqZWN0SWQ6cn07dHJ5e2F3YWl0IHQuZGlzcGF0Y2goZS5DbGVhckNlbGxzLG8pfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fSxiPSh0LHIsYSk9PmFzeW5jKCk9PntkKGBDZWxsIHJhbmdlOiBDbGVhciBmb3JtYXR0aW5nOyBhZGRyZXNzOiR7YX0gKCR7cn0pYCk7Y29uc3Qgbz17YWRkcmVzczphLG9iamVjdElkOnJ9O3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuQ2xlYXJDZWxsRm9ybWF0dGluZyxvKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfX0sQT0odCxyLGEpPT5hc3luYygpPT57ZChgQ2VsbCByYW5nZTogQ2xlYXIgdmFsdWVzOyBhZGRyZXNzOiR7YX0gKCR7cn0pYCk7Y29uc3Qgbz17YWRkcmVzczphLG9iamVjdElkOnJ9O3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuQ2xlYXJDZWxsVmFsdWVzLG8pfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fSxFPShlLHQscik9PihhLG89MWUzKT0+e2lmKG88PTApdGhyb3cgbmV3IEFwaUVycm9yKFwiVXBkYXRlIGludGVydmFsIG11c3QgYmUgYSBwb3NpdGl2ZSBudW1iZXJcIik7Y29uc3Qgbj1tKCk7ZChgQ2VsbCByYW5nZTogQ3JlYXRlIGRhdGEgc3RyZWFtOyBzdHJlYW1JZDoke259OyBhZGRyZXNzOiR7cn07IHVwZGF0ZUludGVydmFsOiR7b30gKCR7dH0pYCk7Y29uc3Qgcz17YWRkcmVzczpyLGNsb3NlOigpPT57ZChgQ2xvc2VkIHN0cmVhbSAoJHtufSlgKSwoZT0+e3ZhciB0O3RyeXtjb25zdCByPUMuZ2V0KGUpO2lmKCFyKXRocm93IG5ldyBBcGlFcnJvcihgVW5hYmxlIHRvIGZpbmQgcmVnaXN0ZXJlZCBkYXRhIHN0cmVhbSB3aXRoIGlkICR7ZX1gKTt2b2lkIDAhPT0obnVsbCE9PSh0PXIudGltZXIpJiZ2b2lkIDAhPT10P3Q6dm9pZCAwKSYmRihlKSxDLmRlbGV0ZShlKX1jYXRjaChlKXt0aHJvdyBjKGUpLGV9fSkobil9LGlkOm4sc3RhcnQ6KCk9PntkKGBTdGFydGVkIHN0cmVhbWluZyAoJHtufSlgKSxVKG4sYSxlLHQpfSxzdG9wOigpPT57ZChgU3RvcHBlZCBzdHJlYW1pbmcgKCR7bn0pYCksRihuKX0sdXBkYXRlSW50ZXJ2YWw6byx3b3Jrc2hlZXRJZDp0fTtyZXR1cm4gQy5zZXQobix7ZGF0YVN0cmVhbTpzfSksc30sVz1lPT5yPT57dmFyIGE7dHJ5e2lmKChudWxsPT09KGE9ci5ldmVudE5hbWUpfHx2b2lkIDA9PT1hP3ZvaWQgMDphLnRvVXBwZXJDYXNlKCkpPT09dC5DaGFuZ2UudG9VcHBlckNhc2UoKSlyZXR1cm4gZShyLmNoYW5nZWRDZWxscyk7dGhyb3cgbmV3IEV2ZW50RXJyb3IoYFVuZXhwZWN0ZWQgY2VsbCByYW5nZSBldmVudDogJHtyLmV2ZW50TmFtZX1gKX1jYXRjaChlKXtjKGUpfX0sZj0oZSx0LHIpPT5hc3luYygpPT57ZChgQ2VsbCByYW5nZTogR2V0IGNlbGxzOyBhZGRyZXNzOiR7cn0gKCR7dH0pYCk7Y29uc3QgYT1hd2FpdCAkKGUsdCxyKTtyZXR1cm4gZChgJHtyfTpgLGEpLGF9LCQ9YXN5bmModCxyLGEpPT57Y29uc3Qgbz17YWRkcmVzczphLG9iamVjdElkOnJ9O3RyeXtyZXR1cm4gYXdhaXQgdC5kaXNwYXRjaChlLkdldENlbGxzLG8pfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fSxHPSh0LHIsYSk9PmFzeW5jKCk9PntkKGBDZWxsIHJhbmdlOiBHZXQgbmFtZTsgYWRkcmVzczoke2F9ICgke3J9KWApO2NvbnN0IG89e2FkZHJlc3M6YSxvYmplY3RJZDpyfTt0cnl7cmV0dXJuIGF3YWl0IHQuZGlzcGF0Y2goZS5HZXRDZWxsTmFtZXMsbyl9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn19LEk9KHQscixhKT0+YXN5bmMobyxuLHMsaSxsPSEwKT0+e2QoYENlbGwgcmFuZ2U6IFNldCBmaWx0ZXI7IGFkZHJlc3M6JHthfSAoJHtyfSlgLHtjb2x1bW5JbmRleDpvLGZpbHRlck9wZXJhdG9yOm4sY3JpdGVyaWExOnMsY3JpdGVyaWEyOmksdmlzaWJsZURyb3BEb3duOmx9KTtjb25zdCBjPXthZGRyZXNzOmEsY3JpdGVyaWExOnMsY3JpdGVyaWEyOmksY29sdW1uSW5kZXg6byxmaWx0ZXJPcGVyYXRvcjpuLG9iamVjdElkOnIsdmlzaWJsZURyb3BEb3duOmx9O3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuRmlsdGVyQ2VsbHMsYyl9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn19LE49KHQscixhKT0+YXN5bmMgbz0+e2QoYENlbGwgcmFuZ2U6IFNldCBmb3JtYXR0aW5nOyBhZGRyZXNzOiR7YX0gKCR7cn0pYCxvKTtjb25zdCBuPXthZGRyZXNzOmEsZm9ybWF0dGluZzpvLG9iamVjdElkOnJ9O3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuU2V0Q2VsbEZvcm1hdHRpbmcsbil9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn19LFM9KHQscixhKT0+YXN5bmMgbz0+e2NvbnN0IG49by50cmltKCk7bGV0IHM7aWYoIW4pdGhyb3cgcz1uZXcgUGFyYW1ldGVyRXJyb3IoXCJOYW1lIGNhbm5vdCBiZSBhbiBlbXB0eSBzdHJpbmdcIiksYyhzKSxzO2lmKG4ubGVuZ3RoPjI1NSl0aHJvdyBzPW5ldyBQYXJhbWV0ZXJFcnJvcihcIk5hbWUgbXVzdCBiZSAyNTUgY2hhcmFjdGVycyBvciBsZXNzXCIpLGMocykscztpZigvW15hLXpBLVowLTlfLj9cXFxcXCInXS8udGVzdChuKSl0aHJvdyBzPW5ldyBQYXJhbWV0ZXJFcnJvcihcIk5hbWUgY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzXCIpLGMocykscztpZigvXlxcZC8udGVzdChuKSl0aHJvdyBzPW5ldyBQYXJhbWV0ZXJFcnJvcihcIk5hbWUgY2Fubm90IHN0YXJ0IHdpdGggYSBudW1iZXJcIiksYyhzKSxzO2QoYENlbGwgcmFuZ2U6IFNldCBuYW1lOyBhZGRyZXNzOiR7YX07IG5ld05hbWU6JHtufSAoJHtyfSlgKTtjb25zdCBpPXthZGRyZXNzOmEsbmFtZTpuLG9iamVjdElkOnJ9O3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuU2V0Q2VsbE5hbWUsaSl9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn19LEQ9KHQscixhKT0+YXN5bmMgbz0+e2QoYENlbGwgcmFuZ2U6IFNldCB2YWx1ZXM7IGFkZHJlc3M6JHthfSAoJHtyfSlgLG8pO2NvbnN0IG49e2FkZHJlc3M6YSxvYmplY3RJZDpyLHZhbHVlc01hcDpvfTt0cnl7YXdhaXQgdC5kaXNwYXRjaChlLlNldENlbGxWYWx1ZXMsbil9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn19LFU9KGUsdCxyLGEpPT57dmFyIG87dHJ5e2NvbnN0IG49Qy5nZXQoZSk7aWYoIW4pdGhyb3cgbmV3IEFwaUVycm9yKGBVbmFibGUgdG8gZmluZCByZWdpc3RlcmVkIGRhdGEgc3RyZWFtIHdpdGggaWQgJHtlfWApO3ZvaWQgMCE9PShudWxsIT09KG89bi50aW1lcikmJnZvaWQgMCE9PW8/bzp2b2lkIDApJiZGKGUpO2NvbnN0e2FkZHJlc3M6cyx1cGRhdGVJbnRlcnZhbDppfT1uLmRhdGFTdHJlYW0sbD1hc3luYygpPT57Y29uc3Qgbz1hd2FpdCB0KCk7dHJ5e2F3YWl0IEQocixhLHMpKFtbb11dKX1jYXRjaCh0KXtoKGBVbmFibGUgdG8gdXBkYXRlIGNlbGwgcmFuZ2UgZm9yIHN0cmVhbSB3aXRoIGlkICR7ZX06ICR7bnVsbD09dD92b2lkIDA6dC5tZXNzYWdlfWApfX0sYz13aW5kb3cuc2V0SW50ZXJ2YWwobCxpKTtuLnRpbWVyPWN9Y2F0Y2goZSl7dGhyb3cgYyhlKSxlfX0sRj1lPT57dmFyIHQ7dHJ5e2NvbnN0IHI9Qy5nZXQoZSk7aWYoIXIpdGhyb3cgbmV3IEFwaUVycm9yKGBVbmFibGUgdG8gZmluZCByZWdpc3RlcmVkIGRhdGEgc3RyZWFtIHdpdGggaWQgJHtlfWApO2lmKHZvaWQgMD09PShudWxsIT09KHQ9ci50aW1lcikmJnZvaWQgMCE9PXQ/dDp2b2lkIDApKXJldHVybjt3aW5kb3cuY2xlYXJJbnRlcnZhbChyLnRpbWVyKSxyLnRpbWVyPXZvaWQgMH1jYXRjaChlKXt0aHJvdyBjKGUpLGV9fSxQPSh0LHIpPT5hc3luYygpPT57ZChgV29ya3NoZWV0OiBBY3RpdmF0ZSAoJHtyfSlgKTt0cnl7YXdhaXQgdC5kaXNwYXRjaChlLkFjdGl2YXRlV29ya3NoZWV0LHIpfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fSx4PShlLHQpPT5hc3luYyhyLGEpPT5wKGUsdCxyLGEsVihhKSksTD0odCxyKT0+YXN5bmMoKT0+e2QoYFdvcmtzaGVldDogQ2FsY3VsYXRlICgke3J9KWApO3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuQ2FsY3VsYXRlV29ya3NoZWV0LHIpfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fSxCPSh0LHIpPT5hc3luYygpPT57ZChgV29ya3NoZWV0OiBDbGVhciBhbGwgY2VsbCBmb3JtYXR0aW5nICgke3J9KWApO3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuQ2xlYXJBbGxDZWxsRm9ybWF0dGluZyxyKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfX0saj0odCxyKT0+YXN5bmMoKT0+e2QoYFdvcmtzaGVldDogQ2xlYXIgYWxsIGNlbGxzICgke3J9KWApO3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuQ2xlYXJBbGxDZWxscyxyKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfX0sUj0odCxyKT0+YXN5bmMoKT0+e2QoYFdvcmtzaGVldDogQ2xlYXIgYWxsIGNlbGwgdmFsdWVzICgke3J9KWApO3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuQ2xlYXJBbGxDZWxsVmFsdWVzLHIpfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fSxPPShlLHQpPT57Y29uc3Qgcj17ZXZlbnRUYXJnZXQ6Zy5Xb3Jrc2hlZXQsb2JqZWN0SWQ6dH07cmV0dXJue29iamVjdElkOnQsYWN0aXZhdGU6UChlLHQpLGFkZEV2ZW50TGlzdGVuZXI6eChlLHIpLGNhbGN1bGF0ZTpMKGUsdCksY2xlYXJBbGxDZWxsRm9ybWF0dGluZzpCKGUsdCksY2xlYXJBbGxDZWxsczpqKGUsdCksY2xlYXJBbGxDZWxsVmFsdWVzOlIoZSx0KSxjbGVhckNlbGxGb3JtYXR0aW5nOnI9PmIoZSx0LHIpKCksY2xlYXJDZWxsczpyPT52KGUsdCxyKSgpLGNsZWFyQ2VsbFZhbHVlczpyPT5BKGUsdCxyKSgpLGNyZWF0ZURhdGFTdHJlYW06KHIsYSxvKT0+RShlLHQscikoYSxvKSxkZWxldGU6eihlLHQpLGZpbHRlckNlbGxzOihyLGEsbyxuLHMsaSk9PkkoZSx0LHIpKGEsbyxuLHMsaSksZ2V0Q2VsbFJhbmdlOk0oZSxyKSxnZXRDZWxsczpyPT5mKGUsdCxyKSgpLGdldE5hbWU6VChlLHQpLHByb3RlY3Q6SChlLHQpLHJlbW92ZUV2ZW50TGlzdGVuZXI6dShlKSxzZXRDZWxsRm9ybWF0dGluZzoocixhKT0+TihlLHQscikoYSksc2V0Q2VsbE5hbWU6KHIsYSk9PlMoZSx0LHIpKGEpLHNldENlbGxWYWx1ZXM6KHIsYSk9PkQoZSx0LHIpKGEpLHNldE5hbWU6UShlLHQpfX0sVj1lPT5yPT57dmFyIGE7dHJ5e3N3aXRjaChudWxsPT09KGE9ci5ldmVudE5hbWUpfHx2b2lkIDA9PT1hP3ZvaWQgMDphLnRvVXBwZXJDYXNlKCkpe2Nhc2UgdC5BY3RpdmF0ZS50b1VwcGVyQ2FzZSgpOmNhc2UgdC5EZWFjdGl2YXRlLnRvVXBwZXJDYXNlKCk6cmV0dXJuIGUoKTtjYXNlIHQuQ2hhbmdlLnRvVXBwZXJDYXNlKCk6cmV0dXJuIGUoci5jaGFuZ2VkQ2VsbHMpO2RlZmF1bHQ6dGhyb3cgbmV3IEV2ZW50RXJyb3IoYFVuZXhwZWN0ZWQgd29ya3NoZWV0IGV2ZW50OiAke3IuZXZlbnROYW1lfWApfX1jYXRjaChlKXtjKGUpfX0sej0odCxyKT0+YXN5bmMoKT0+e2QoYFdvcmtzaGVldDogRGVsZXRlICgke3J9KWApO3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuRGVsZXRlV29ya3NoZWV0LHIpfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fSxNPSh0LHIpPT5hc3luYyBhPT57Y29uc3R7b2JqZWN0SWQ6b309cjtkKGBXb3Jrc2hlZXQ6IEdldCBjZWxsIHJhbmdlOyBhZGRyZXNzOiR7YX0gKCR7b30pYCk7dHJ5e2NvbnN0IG49e2FkZHJlc3M6YSxvYmplY3RJZDpvfSxzPWF3YWl0IHQuZGlzcGF0Y2goZS5HZXRSYW5nZUFkZHJlc3Msbik7cmV0dXJuKChlLHQscik9Pntjb25zdHtvYmplY3RJZDphfT10LG89e2NlbGxSYW5nZUFkZHJlc3M6cixldmVudFRhcmdldDpnLkNlbGxSYW5nZSxvYmplY3RJZDphfTtyZXR1cm57YWRkRXZlbnRMaXN0ZW5lcjp5KGUsbyksYWRkcmVzczpyLGNsZWFyOnYoZSxhLHIpLGNsZWFyRm9ybWF0dGluZzpiKGUsYSxyKSxjbGVhclZhbHVlczpBKGUsYSxyKSxjcmVhdGVEYXRhU3RyZWFtOkUoZSxhLHIpLGdldENlbGxzOmYoZSxhLHIpLGdldE5hbWVzOkcoZSxhLHIpLHJlbW92ZUV2ZW50TGlzdGVuZXI6dShlKSxzZXRGaWx0ZXI6SShlLGEsciksc2V0Rm9ybWF0dGluZzpOKGUsYSxyKSxzZXROYW1lOlMoZSxhLHIpLHNldFZhbHVlczpEKGUsYSxyKX19KSh0LHIscyl9Y2F0Y2goZSl7aWYoZS5tZXNzYWdlLmluZGV4T2YoXCJVbmFibGUgdG8gZ2V0IGNlbGwgcmFuZ2VcIik+PTApe2NvbnN0IGU9bmV3IEludmFsaWRDZWxsUmFuZ2VBZGRyZXNzRXJyb3I7dGhyb3cgYyhlKSxlfXRocm93IG5ldyBBZGFwdGVyRXJyb3J9fSxUPSh0LHIpPT5hc3luYygpPT57ZChgV29ya3NoZWV0OiBHZXQgbmFtZSAoJHtyfSlgKTt0cnl7cmV0dXJuIGF3YWl0IHQuZGlzcGF0Y2goZS5HZXRXb3Jrc2hlZXROYW1lLHIpfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fSxIPSh0LHIpPT5hc3luYygpPT57ZChgV29ya3NoZWV0OiBQcm90ZWN0ICgke3J9KWApO3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuUHJvdGVjdFdvcmtzaGVldCxyKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfX0sUT0odCxyKT0+YXN5bmMgYT0+e2NvbnN0IG89YS5zbGljZSgwLDMxKS5yZXBsYWNlKC9bOlxcXFwvPypbXFxdXS9nLFwiXCIpLnRyaW0oKTtsZXQgbjtpZighbyl0aHJvdyBuPW5ldyBQYXJhbWV0ZXJFcnJvcihcIkludmFsaWQgd29ya3NoZWV0IG5hbWVcIiksYyhuKSxuO2QoYFdvcmtzaGVldDogU2V0IG5hbWU7IG5ld1dvcmtzaGVldE5hbWU6JHtvfSAoJHtyfSlgKTtjb25zdCBzPXtuZXdXb3Jrc2hlZXROYW1lOm8sb2JqZWN0SWQ6cn07dHJ5e3JldHVybiBhd2FpdCB0LmRpc3BhdGNoKGUuU2V0V29ya3NoZWV0TmFtZSxzKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfX0sXz0odCxyKT0+YXN5bmMoKT0+e2QoYFdvcmtib29rOiBBY3RpdmF0ZSAoJHtyfSlgKTt0cnl7cmV0dXJuIGF3YWl0IHQuZGlzcGF0Y2goZS5BY3RpdmF0ZVdvcmtib29rLHIpfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fSxxPShlLHQpPT5hc3luYyhyLGEpPT5wKGUsdCxyLGEsWShlLGEpKSxKPSh0LHIpPT5hc3luYygpPT57bGV0IGE7ZChgV29ya2Jvb2s6IEFkZCB3b3Jrc2hlZXQgKCR7cn0pYCk7dHJ5e2E9YXdhaXQgdC5kaXNwYXRjaChlLkFkZFdvcmtzaGVldCxyKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfXJldHVybiBPKHQsYSl9LEs9KHQscik9PmFzeW5jKCk9PntkKGBXb3JrYm9vazogQ2FsY3VsYXRlICgke3J9KWApO3RyeXthd2FpdCB0LmRpc3BhdGNoKGUuQ2FsY3VsYXRlV29ya2Jvb2sscil9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn19LFg9KHQscik9PmFzeW5jKCk9PntkKGBXb3JrYm9vazogQ2xvc2UgKCR7cn0pYCk7dHJ5e3JldHVybiBhd2FpdCB0LmRpc3BhdGNoKGUuQ2xvc2VXb3JrYm9vayxyKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfX0sWj0oZSx0KT0+e2NvbnN0IHI9e2V2ZW50VGFyZ2V0OmcuV29ya2Jvb2ssb2JqZWN0SWQ6dH07cmV0dXJue29iamVjdElkOnQsYWN0aXZhdGU6XyhlLHQpLGFkZFdvcmtzaGVldDpKKGUsdCksYWRkRXZlbnRMaXN0ZW5lcjpxKGUsciksY2FsY3VsYXRlOksoZSx0KSxjbG9zZTpYKGUsdCksZ2V0QWN0aXZlV29ya3NoZWV0OmVlKGUsdCksZ2V0Q2FsY3VsYXRpb25Nb2RlOnRlKGUsdCksZ2V0RmlsZVBhdGg6cmUoZSx0KSxnZXROYW1lOmFlKGUsdCksZ2V0V2luZG93Qm91bmRzOm9lKGUsdCksZ2V0V29ya3NoZWV0QnlOYW1lOm5lKGUsdCksZ2V0V29ya3NoZWV0czpzZShlLHQpLHJlbW92ZUV2ZW50TGlzdGVuZXI6dShlKSxzYXZlOmllKGUsdCksc2F2ZUFzOmxlKGUsdCksc2V0V2luZG93Qm91bmRzOmNlKGUsdCl9fSxZPShlLHIpPT5hPT57dmFyIG87dHJ5e3N3aXRjaChudWxsPT09KG89YS5ldmVudE5hbWUpfHx2b2lkIDA9PT1vP3ZvaWQgMDpvLnRvVXBwZXJDYXNlKCkpe2Nhc2UgdC5BY3RpdmF0ZS50b1VwcGVyQ2FzZSgpOmNhc2UgdC5DbG9zZS50b1VwcGVyQ2FzZSgpOmNhc2UgdC5EZWFjdGl2YXRlLnRvVXBwZXJDYXNlKCk6cmV0dXJuIHIoKTtjYXNlIHQuQWN0aXZhdGVXb3Jrc2hlZXQudG9VcHBlckNhc2UoKTpjYXNlIHQuQWRkV29ya3NoZWV0LnRvVXBwZXJDYXNlKCk6cmV0dXJuIHIoTyhlLGEud29ya3NoZWV0T2JqZWN0SWQpKTtjYXNlIHQuRGVsZXRlV29ya3NoZWV0LnRvVXBwZXJDYXNlKCk6cmV0dXJuIHIoYS53b3Jrc2hlZXROYW1lKTtkZWZhdWx0OnRocm93IG5ldyBFdmVudEVycm9yKGBVbmV4cGVjdGVkIHdvcmtib29rIGV2ZW50OiAke2EuZXZlbnROYW1lfWApfX1jYXRjaChlKXtjKGUpfX0sZWU9KHQscik9PmFzeW5jKCk9PntsZXQgYTtkKGBXb3JrYm9vazogR2V0IGFjdGl2ZSB3b3Jrc2hlZXQ6ICgke3J9KWApO3RyeXthPWF3YWl0IHQuZGlzcGF0Y2goZS5HZXRBY3RpdmVXb3Jrc2hlZXQscil9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn1yZXR1cm4gTyh0LGEpfSx0ZT0odCxyKT0+YXN5bmMoKT0+e2QoXCJXb3JrYm9vazogR2V0IGNhbGN1bGF0aW9uIG1vZGVcIik7dHJ5e3JldHVybiBhd2FpdCB0LmRpc3BhdGNoKGUuR2V0Q2FsY3VsYXRpb25Nb2RlLHIpfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9fSxyZT0odCxyKT0+YXN5bmMoKT0+e2QoYFdvcmtib29rOiBHZXQgZmlsZSBwYXRoICgke3J9KWApO3RyeXtyZXR1cm4gYXdhaXQgdC5kaXNwYXRjaChlLkdldFdvcmtib29rRmlsZVBhdGgscil9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn19LGFlPSh0LHIpPT5hc3luYygpPT57ZChgV29ya2Jvb2s6IEdldCBuYW1lICgke3J9KWApO3RyeXtyZXR1cm4gYXdhaXQgdC5kaXNwYXRjaChlLkdldFdvcmtib29rTmFtZSxyKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfX0sb2U9KHQscik9PmFzeW5jKCk9PntkKGBXb3JrYm9vazogR2V0IHdpbmRvdyBib3VuZHMgKCR7cn0pYCk7dHJ5e3JldHVybiBhd2FpdCB0LmRpc3BhdGNoKGUuR2V0V29ya2Jvb2tXaW5kb3dCb3VuZHMscil9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn19LG5lPSh0LHIpPT5hc3luYyBhPT57bGV0IG87ZChgV29ya2Jvb2s6IEdldCB3b3Jrc2hlZXQgYnkgbmFtZTogJHthfSAoJHtyfSlgKTt0cnl7aWYobz1hd2FpdCB0LmRpc3BhdGNoKGUuR2V0V29ya3NoZWV0QnlOYW1lLHtvYmplY3RJZDpyLHdvcmtzaGVldE5hbWU6YX0pLG51bGw9PT1vKXJldHVybiBudWxsfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9cmV0dXJuIE8odCxvKX0sc2U9KHQscik9PmFzeW5jKCk9PntsZXQgYTtkKGBXb3JrYm9vazogR2V0IHdvcmtzaGVldHMgKCR7cn0pYCk7dHJ5e2E9YXdhaXQgdC5kaXNwYXRjaChlLkdldFdvcmtzaGVldHMscil9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn1yZXR1cm4gYS5tYXAoKGU9Pk8odCxlKSkpfSxpZT0odCxyKT0+YXN5bmMoKT0+e2QoYFdvcmtib29rOiBTYXZlICgke3J9KWApO3RyeXtyZXR1cm4gYXdhaXQgdC5kaXNwYXRjaChlLlNhdmVXb3JrYm9vayxyKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfX0sbGU9KHQscik9PmFzeW5jIGE9PntkKGBXb3JrYm9vazogU2F2ZSBhczsgZmlsZVBhdGg6JHthfSAoJHtyfSlgKTt0cnl7cmV0dXJuIGF3YWl0IHQuZGlzcGF0Y2goZS5TYXZlV29ya2Jvb2tBcyx7ZmlsZVBhdGg6YSxvYmplY3RJZDpyfSl9Y2F0Y2goZSl7dGhyb3cgbmV3IEFkYXB0ZXJFcnJvcn19LGNlPSh0LHIpPT5hc3luYyBhPT57ZChgV29ya2Jvb2s6IFNldCB3aW5kb3cgYm91bmRzICgke3J9KWAsYSk7Y29uc3R7aGVpZ2h0Om8sbGVmdDpuLHRvcDpzLHdpZHRoOml9PWE7aWYobnVsbCE9byYmKE51bWJlci5pc05hTihvKXx8bzw9MCkpe2NvbnN0IGU9bmV3IFBhcmFtZXRlckVycm9yKFwiV29ya2Jvb2sgd2luZG93IGhlaWdodCBtdXN0IGJlIGEgbnVtYmVyIGdyZWF0ZXIgdGhhbiB6ZXJvLlwiKTt0aHJvdyBjKGUpLGV9aWYobnVsbCE9biYmTnVtYmVyLmlzTmFOKG4pKXtjb25zdCBlPW5ldyBQYXJhbWV0ZXJFcnJvcihcIldvcmtib29rIHdpbmRvdyBsZWZ0IHBvc2l0aW9uIG11c3QgYmUgYSB2YWxpZCBudW1iZXIuXCIpO3Rocm93IGMoZSksZX1pZihudWxsIT1zJiZOdW1iZXIuaXNOYU4ocykpe2NvbnN0IGU9bmV3IFBhcmFtZXRlckVycm9yKFwiV29ya2Jvb2sgd2luZG93IHRvcCBwb3NpdGlvbiBtdXN0IGJlIGEgdmFsaWQgbnVtYmVyLlwiKTt0aHJvdyBjKGUpLGV9aWYobnVsbCE9aSYmKE51bWJlci5pc05hTihpKXx8aTw9MCkpe2NvbnN0IGU9bmV3IFBhcmFtZXRlckVycm9yKFwiV29ya2Jvb2sgd2luZG93IHdpZHRoIG11c3QgYmUgYSBudW1iZXIgZ3JlYXRlciB0aGFuIHplcm8uXCIpO3Rocm93IGMoZSksZX1jb25zdCBsPXtuZXdXaW5kb3dCb3VuZHM6YSxvYmplY3RJZDpyfTt0cnl7cmV0dXJuIGF3YWl0IHQuZGlzcGF0Y2goZS5TZXRXb3JrYm9va1dpbmRvd0JvdW5kcyxsKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfX0sZGU9dD0+YXN5bmMgcj0+e2xldCBhO2QoYEFwcGxpY2F0aW9uOiBHZXQgd29ya2Jvb2s7IGlkOiR7cn1gKTt0cnl7YT1hd2FpdCB0LmRpc3BhdGNoKGUuR2V0V29ya2Jvb2tCeUlkLHIpfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9cmV0dXJuIFoodCxhKX0saGU9dD0+YXN5bmMoKT0+e2xldCByO2QoXCJBcHBsaWNhdGlvbjogR2V0IHdvcmtib29rc1wiKTt0cnl7cj1hd2FpdCB0LmRpc3BhdGNoKGUuR2V0V29ya2Jvb2tzKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfXJldHVybiByLm1hcCgoZT0+Wih0LGUpKSl9LHdlPXQ9PmFzeW5jIHI9PntkKGBBcHBsaWNhdGlvbjogR2V0IHdvcmtzaGVldDsgaWQ6JHtyfWApO3RyeXtyPWF3YWl0IHQuZGlzcGF0Y2goZS5HZXRXb3Jrc2hlZXRCeUlkLHIpfWNhdGNoKGUpe3Rocm93IG5ldyBBZGFwdGVyRXJyb3J9cmV0dXJuIE8odCxyKX0scGU9dD0+YXN5bmMgcj0+e2xldCBhO2QoYEFwcGxpY2F0aW9uOiBPcGVuIHdvcmtib29rOyBmaWxlUGF0aDoke3J9YCk7dHJ5e2E9YXdhaXQgdC5kaXNwYXRjaChlLk9wZW5Xb3JrYm9vayxyKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfXJldHVybiBaKHQsYSl9LGtlPXQ9PmFzeW5jKHI9ITApPT57ZChgQXBwbGljYXRpb246IFF1aXQ7IGRpc3BsYXlBbGVydHM6JHtyfWApO3RyeXtyZXR1cm4gYXdhaXQgdC5kaXNwYXRjaChlLlF1aXRBcHBsaWNhdGlvbixyKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfX07dmFyIHVlLGdlOyFmdW5jdGlvbihlKXtlLkV4Y2VsQXBwbGljYXRpb249XCJFWENFTC1BUFBcIn0odWV8fCh1ZT17fSkpLGZ1bmN0aW9uKGUpe2VbZS5JbmZvPTFdPVwiSW5mb1wiLGVbZS5XYXJuPTJdPVwiV2FyblwiLGVbZS5FcnJvcj0zXT1cIkVycm9yXCJ9KGdlfHwoZ2U9e30pKTtjb25zdCBtZT1cImV4Y2VsLWFkYXB0ZXJcIixDZT1tKCk7bGV0IHllO2NvbnN0IHZlPSgpPT5vLGJlPWFzeW5jKHQ9ITEpPT57dHJ5e2lmKGF3YWl0KGFzeW5jIGU9Pnt0cnl7ZChcIlJlZ2lzdGVyaW5nIHVzYWdlXCIpLGF3YWl0IGZpbi5TeXN0ZW0ucmVnaXN0ZXJVc2FnZSh7dHlwZTpcImludGVncmF0aW9uLWZlYXR1cmVcIixkYXRhOnthcGlWZXJzaW9uOm8sY29tcG9uZW50TmFtZTplfX0pfWNhdGNoKHQpe2goYFVuYWJsZSB0byByZWdpc3RlciB1c2FnZSBmb3IgZmVhdHVyZSAke2V9OiAke251bGw9PXQ/dm9pZCAwOnQubWVzc2FnZX1gKX19KSh1ZS5FeGNlbEFwcGxpY2F0aW9uKSwhYXdhaXQoYXN5bmMgZT0+KGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuZ2V0QWxsQ2hhbm5lbHMoKSkuc29tZSgodD0+dC5jaGFubmVsTmFtZT09PWUpKSkoQ2UpKXthd2FpdChhc3luYygpPT57dmFyIGU7Y29uc3QgdD1udWxsPT09KGU9KGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50U3luYygpLmdldE1hbmlmZXN0KCkpLmFwcEFzc2V0cyl8fHZvaWQgMD09PWU/dm9pZCAwOmUuZmluZCgoZT0+ZS5hbGlhcz09PW1lKSk7aWYodClyZXR1cm4gdm9pZCBoKFwiRGV0ZWN0ZWQgYWRhcHRlciBwYWNrYWdlIGluIGFwcCBtYW5pZmVzdCBhcHBBc3NldHNcIix0KTtpZihhd2FpdCBFZSgpKXJldHVybiB2b2lkIGQoXCJVc2luZyBleGlzdGluZyBhZGFwdGVyIHBhY2thZ2VcIik7Y29uc3Qgcj17YWxpYXM6bWUsc3JjOmBodHRwczovL2Nkbi5vcGVuZmluLmNvL3JlbGVhc2UvaW50ZWdyYXRpb25zL2V4Y2VsLyR7dmUoKX0vT3BlbkZpbi5FeGNlbC56aXBgLHRhcmdldDpcIk9wZW5GaW4uRXhjZWwuZXhlXCIsdmVyc2lvbjp2ZSgpfTtkKFwiRG93bmxvYWRpbmcgYWRhcHRlciBwYWNrYWdlXCIscik7dHJ5e2F3YWl0IGZpbi5TeXN0ZW0uZG93bmxvYWRBc3NldChyLCgoKT0+e30pKX1jYXRjaChlKXt0aHJvdyBjKFwiVW5hYmxlIHRvIGRvd25sb2FkIGFkYXB0ZXIgcGFja2FnZVwiKSxlfX0pKCk7Y29uc3R7c2VjdXJpdHlSZWFsbTplLHBvcnQ6cn09YXdhaXQgZmluLlN5c3RlbS5nZXRSdW50aW1lSW5mbygpO2xldHtsaWNlbnNlS2V5OmF9PWF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50U3luYygpLmdldE1hbmlmZXN0KCk7YT1udWxsIT1hP2E6XCJOT19MSUNFTlNFX0tFWVwiO2NvbnN0IG89ZmluLm1lLnV1aWQ7ZChcIkluaXRpYWxpemluZyBhZGFwdGVyXCIse2FkYXB0ZXJMb2dnaW5nRW5hYmxlZDp0LGNoYW5uZWxOYW1lOkNlLGxpY2Vuc2VLZXk6YSxwb3J0OnIsc2VjdXJpdHlSZWFsbTplLHV1aWQ6b30pLGZpbi5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKHthbGlhczptZSxhcmd1bWVudHM6YCR7b30gJHthfSAke3J9ICR7ZX0gJHtDZX0gJHt0fWB9KX1jb25zdCByPWZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY29ubmVjdChDZSx7cGF5bG9hZDp7dmVyc2lvbjp2ZSgpfX0pLGE9bmV3IFByb21pc2UoKGU9PntzZXRUaW1lb3V0KGUsMmU0KX0pKS50aGVuKCgoKT0+e3Rocm93IG5ldyBFcnJvcihcIkNvbm5lY3Rpb24gdG8gYWRhcHRlciB0aW1lZCBvdXRcIil9KSk7eWU9YXdhaXQgUHJvbWlzZS5yYWNlKFtyLGFdKSxkKGBDb25uZWN0ZWQgdG8gYWRhcHRlciAke3llLnByb3ZpZGVySWRlbnRpdHkudXVpZH0gb24gY2hhbm5lbCAke0NlfWApLHllLnJlZ2lzdGVyKGUuTG9nTWVzc2FnZSxBZSkseWUucmVnaXN0ZXIoZS5FdmVudEZpcmVkLGspfWNhdGNoKGUpe2NvbnN0IHQ9bmV3IEluaXRpYWxpemF0aW9uRXJyb3Iodm9pZCAwLGUpO3Rocm93IGModCksdH1yZXR1cm57YWRhcHRlcjp7Y2hhbm5lbE5hbWU6Q2UsdmVyc2lvbjp2ZSgpfSxjcmVhdGVXb3JrYm9vazoocj15ZSxhc3luYygpPT57bGV0IHQ7ZChcIkFwcGxpY2F0aW9uOiBDcmVhdGUgd29ya2Jvb2tcIik7dHJ5e3Q9YXdhaXQgci5kaXNwYXRjaChlLkNyZWF0ZVdvcmtib29rKX1jYXRjaChlKXt0aHJvdyBuZXcgQWRhcHRlckVycm9yfXJldHVybiBaKHIsdCl9KSxnZXRXb3JrYm9va0J5SWQ6ZGUoeWUpLGdldFdvcmtib29rczpoZSh5ZSksZ2V0V29ya3NoZWV0QnlJZDp3ZSh5ZSksb3Blbldvcmtib29rOnBlKHllKSxxdWl0OmtlKHllKX07dmFyIHJ9LEFlPShlLHQpPT57Y29uc3R7bWVzc2FnZTpyLHR5cGU6YX09ZSxvPVwiW2FkYXB0ZXJdXCI7c3dpdGNoKGEpe2Nhc2UgZ2UuRXJyb3I6YyhyLG8pO2JyZWFrO2Nhc2UgZ2UuSW5mbzpkKG8scik7YnJlYWs7Y2FzZSBnZS5XYXJuOmgobyxyKTticmVhaztkZWZhdWx0OmMobmV3IEVycm9yKGBVbmtub3duIGxvZyB0eXBlOiAke2F9YCkpfX0sRWU9YXN5bmMoKT0+e3RyeXtjb25zdCBlPWF3YWl0IGZpbi5TeXN0ZW0uZ2V0QXBwQXNzZXRJbmZvKHthbGlhczptZX0pO3JldHVybiBlJiZlLnZlcnNpb249PT12ZSgpfWNhdGNoKGUpe3JldHVybiExfX07dmFyIFdlLGZlLCRlLEdlLEllOyFmdW5jdGlvbihlKXtlLkNvbnRpbnVvdXM9XCJDb250aW51b3VzXCIsZS5EYXNoPVwiRGFzaFwiLGUuRGFzaERvdD1cIkRhc2hEb3RcIixlLkRhc2hEb3REb3Q9XCJEYXNoRG90RG90XCIsZS5Eb3Q9XCJEb3RcIixlLkRvdWJsZT1cIkRvdWJsZVwiLGUuU2xhbnREYXNoRG90PVwiU2xhbnREYXNoRG90XCIsZS5Ob25lPVwiTm9uZVwifShXZXx8KFdlPXt9KSksZnVuY3Rpb24oZSl7ZS5DZW50ZXI9XCJDZW50ZXJcIixlLkNlbnRlckFjcm9zc1NlbGVjdGlvbj1cIkNlbnRlckFjcm9zc1NlbGVjdGlvblwiLGUuRGlzdHJpYnV0ZWQ9XCJEaXN0cmlidXRlZFwiLGUuRmlsbD1cIkZpbGxcIixlLkdlbmVyYWw9XCJHZW5lcmFsXCIsZS5KdXN0aWZ5PVwiSnVzdGlmeVwiLGUuTGVmdD1cIkxlZnRcIixlLlJpZ2h0PVwiUmlnaHRcIn0oZmV8fChmZT17fSkpLGZ1bmN0aW9uKGUpe2UuQXV0b21hdGljPVwiQXV0b21hdGljXCIsZS5DaGVja2VyPVwiQ2hlY2tlclwiLGUuQ3Jpc3NDcm9zcz1cIkNyaXNzQ3Jvc3NcIixlLkRvd249XCJEb3duXCIsZS5HcmF5MTY9XCJHcmF5MTZcIixlLkdyYXkyNT1cIkdyYXkyNVwiLGUuR3JheTUwPVwiR3JheTUwXCIsZS5HcmF5NzU9XCJHcmF5NzVcIixlLkdyYXk4PVwiR3JheThcIixlLkdyaWQ9XCJHcmlkXCIsZS5Ib3Jpem9udGFsPVwiSG9yaXpvbnRhbFwiLGUuTGlnaHREb3duPVwiTGlnaHREb3duXCIsZS5MaWdodEhvcml6b250YWw9XCJMaWdodEhvcml6b250YWxcIixlLkxpZ2h0VXA9XCJMaWdodFVwXCIsZS5MaWdodFZlcnRpY2FsPVwiTGlnaHRWZXJ0aWNhbFwiLGUuTGluZWFyR3JhZGllbnQ9XCJMaW5lYXJHcmFkaWVudFwiLGUuTm9uZT1cIk5vbmVcIixlLlJlY3Rhbmd1bGFyR3JhZGllbnQ9XCJSZWN0YW5ndWxhckdyYWRpZW50XCIsZS5TZW1pR3JheTc1PVwiU2VtaUdyYXk3NVwiLGUuU29saWQ9XCJTb2xpZFwiLGUuVXA9XCJVcFwiLGUuVmVydGljYWw9XCJWZXJ0aWNhbFwifSgkZXx8KCRlPXt9KSksZnVuY3Rpb24oZSl7ZS5Cb3R0b209XCJCb3R0b21cIixlLkNlbnRlcj1cIkNlbnRlclwiLGUuRGlzdHJpYnV0ZWQ9XCJEaXN0cmlidXRlZFwiLGUuSnVzdGlmeT1cIkp1c3RpZnlcIixlLlRvcD1cIlRvcFwifShHZXx8KEdlPXt9KSksZnVuY3Rpb24oZSl7ZS5BbmQ9XCJBbmRcIixlLk9yPVwiT3JcIixlLlRvcDEwSXRlbXM9XCJUb3AxMEl0ZW1zXCIsZS5Cb3R0b20xMEl0ZW1zPVwiQm90dG9tMTBJdGVtc1wiLGUuVG9wMTBQZXJjZW50PVwiVG9wMTBQZXJjZW50XCIsZS5Cb3R0b20xMFBlcmNlbnQ9XCJCb3R0b20xMFBlcmNlbnRcIixlLkZpbHRlclZhbHVlcz1cIkZpbHRlclZhbHVlc1wifShJZXx8KEllPXt9KSk7dmFyIE5lPWEuZHEsU2U9YS5NUyxEZT1hLnhRLFVlPWEuc08sRmU9YS5adSxQZT1hLkkzLHhlPWEuJFUsTGU9YS5pMCxCZT1hLmNYLGplPWEuZ0gsUmU9YS5fVyxPZT1hLlUkLFZlPWEuVTcsemU9YS5yZDtleHBvcnR7TmUgYXMgQWRhcHRlckVycm9yLFNlIGFzIEFwaUVycm9yLERlIGFzIEV2ZW50RXJyb3IsVWUgYXMgRXhjZWxDZWxsQm9yZGVyTGluZVN0eWxlLEZlIGFzIEV4Y2VsQ2VsbEhvcml6b250YWxBbGlnbm1lbnQsUGUgYXMgRXhjZWxDZWxsUGF0dGVybix4ZSBhcyBFeGNlbENlbGxWZXJ0aWNhbEFsaWdubWVudCxMZSBhcyBFeGNlbEZpbHRlck9wZXJhdG9yLEJlIGFzIEluaXRpYWxpemF0aW9uRXJyb3IsamUgYXMgSW52YWxpZENlbGxSYW5nZUFkZHJlc3NFcnJvcixSZSBhcyBQYXJhbWV0ZXJFcnJvcixPZSBhcyBkaXNhYmxlTG9nZ2luZyxWZSBhcyBlbmFibGVMb2dnaW5nLHplIGFzIGdldEV4Y2VsQXBwbGljYXRpb259OyIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxuXHRcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0obW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCIvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9ucyBmb3IgaGFybW9ueSBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSAoZXhwb3J0cywgZGVmaW5pdGlvbikgPT4ge1xuXHRmb3IodmFyIGtleSBpbiBkZWZpbml0aW9uKSB7XG5cdFx0aWYoX193ZWJwYWNrX3JlcXVpcmVfXy5vKGRlZmluaXRpb24sIGtleSkgJiYgIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBrZXkpKSB7XG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywga2V5LCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZGVmaW5pdGlvbltrZXldIH0pO1xuXHRcdH1cblx0fVxufTsiLCJfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSAob2JqLCBwcm9wKSA9PiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCkpIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHsgZ2V0Q3VycmVudENoYW5uZWwgfSBmcm9tIFwiQGZpbm9zL2ZkYzNcIjtcbmltcG9ydCB7XG5cdHR5cGUgQ2VsbCxcblx0dHlwZSBFeGNlbEFwcGxpY2F0aW9uLFxuXHR0eXBlIEV4Y2VsV29ya2Jvb2ssXG5cdHR5cGUgRXhjZWxXb3Jrc2hlZXQsXG5cdGdldEV4Y2VsQXBwbGljYXRpb25cbn0gZnJvbSBcIkBvcGVuZmluL2V4Y2VsXCI7XG5cbmNvbnN0IEtOT1dOX0lOU1RSVU1FTlRTID0gW1wiVFNMQVwiLCBcIk1TRlRcIiwgXCJBQVBMXCJdO1xuXG5sZXQgZXhjZWw6IEV4Y2VsQXBwbGljYXRpb24gfCB1bmRlZmluZWQ7XG5sZXQgb3Blbldvcmtib29rczpcblx0fCB7XG5cdFx0XHRib29rOiBFeGNlbFdvcmtib29rO1xuXHRcdFx0bmFtZTogc3RyaW5nO1xuXHQgIH1bXVxuXHR8IHVuZGVmaW5lZDtcbmxldCBzZWxlY3RlZFdvcmtib29rSW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZDtcbmxldCBvcGVuV29ya3NoZWV0czpcblx0fCB7XG5cdFx0XHRzaGVldDogRXhjZWxXb3Jrc2hlZXQ7XG5cdFx0XHRuYW1lOiBzdHJpbmc7XG5cdCAgfVtdXG5cdHwgdW5kZWZpbmVkO1xubGV0IHNlbGVjdGVkV29ya3NoZWV0SW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZDtcblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgYXN5bmMgKCkgPT4ge1xuXHR0cnkge1xuXHRcdGF3YWl0IGluaXREb20oKTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTtcblx0fVxufSk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgRE9NIGNvbXBvbmVudHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluaXREb20oKTogUHJvbWlzZTx2b2lkPiB7XG5cdHRyeSB7XG5cdFx0Y29uc3QgcmVzdWx0c0NvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KFwiI3Jlc3VsdHMtY29udGFpbmVyXCIpO1xuXHRcdGlmIChyZXN1bHRzQ29udGFpbmVyKSB7XG5cdFx0XHRyZXN1bHRzQ29udGFpbmVyLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcblx0XHR9XG5cblx0XHRleGNlbCA9IGF3YWl0IGdldEV4Y2VsQXBwbGljYXRpb24oKTtcblxuXHRcdGF3YWl0IHBvcHVsYXRlV29ya2Jvb2tzKCk7XG5cblx0XHRjb25zdCBvcGVuRXhjZWxCdXR0b24gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI29wZW4tZXhjZWxcIik7XG5cdFx0aWYgKG9wZW5FeGNlbEJ1dHRvbikge1xuXHRcdFx0b3BlbkV4Y2VsQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdGF3YWl0IG9wZW5FeGNlbCgpO1xuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgcmVmcmVzaFdvcmtib29rQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiN3b3JrYm9vay1yZWZyZXNoXCIpO1xuXHRcdGlmIChyZWZyZXNoV29ya2Jvb2tCdXR0b24pIHtcblx0XHRcdHJlZnJlc2hXb3JrYm9va0J1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKCkgPT4gcG9wdWxhdGVXb3JrYm9va3MoKSk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgcmVmcmVzaFdvcmtzaGVldEJ1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjd29ya3NoZWV0LXJlZnJlc2hcIik7XG5cdFx0aWYgKHJlZnJlc2hXb3Jrc2hlZXRCdXR0b24pIHtcblx0XHRcdHJlZnJlc2hXb3Jrc2hlZXRCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGFzeW5jICgpID0+IHBvcHVsYXRlV29ya3NoZWV0cygpKTtcblx0XHR9XG5cblx0XHRjb25zdCBvcGVuV29ya2Jvb2tzU2VsZWN0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiN3b3JrYm9va3NcIik7XG5cdFx0aWYgKG9wZW5Xb3JrYm9va3NTZWxlY3QpIHtcblx0XHRcdG9wZW5Xb3JrYm9va3NTZWxlY3QuYWRkRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCBhc3luYyAoZSkgPT5cblx0XHRcdFx0c2VsZWN0V29ya2Jvb2soKGUudGFyZ2V0IGFzIHVua25vd24gYXMgeyB2YWx1ZTogc3RyaW5nIH0pLnZhbHVlKVxuXHRcdFx0KTtcblx0XHR9XG5cblx0XHRjb25zdCBvcGVuV29ya3NoZWV0c1NlbGVjdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjd29ya3NoZWV0c1wiKTtcblx0XHRpZiAob3BlbldvcmtzaGVldHNTZWxlY3QpIHtcblx0XHRcdG9wZW5Xb3Jrc2hlZXRzU2VsZWN0LmFkZEV2ZW50TGlzdGVuZXIoXCJjaGFuZ2VcIiwgYXN5bmMgKGUpID0+XG5cdFx0XHRcdHNlbGVjdFdvcmtzaGVldCgoZS50YXJnZXQgYXMgdW5rbm93biBhcyB7IHZhbHVlOiBzdHJpbmcgfSkudmFsdWUpXG5cdFx0XHQpO1xuXHRcdH1cblxuXHRcdGNvbnN0IHNldFZhbHVlQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNzZXQtdmFsdWVcIik7XG5cdFx0aWYgKHNldFZhbHVlQnV0dG9uKSB7XG5cdFx0XHRzZXRWYWx1ZUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRhd2FpdCBzZXRDZWxsVmFsdWUoKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0c2hvd0Vycm9yKGVycik7XG5cdH1cbn1cblxuLyoqXG4gKiBTaG93IGFuIGVycm9yIG9uIHRoZSBVSS5cbiAqIEBwYXJhbSBlcnIgVGhlIGVycm9yIHRvIGRpc3BsYXkuXG4gKi9cbmZ1bmN0aW9uIHNob3dFcnJvcihlcnI6IHVua25vd24pOiB2b2lkIHtcblx0Y29uc3QgZXJyRG9tID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNlcnJvclwiKTtcblx0aWYgKGVyckRvbSkge1xuXHRcdGVyckRvbS5pbm5lckhUTUwgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogSlNPTi5zdHJpbmdpZnkoZXJyKTtcblx0fVxufVxuXG4vKipcbiAqIE9wZW4gdGhlIGV4Y2VsIGluc3RhbmNlLlxuICovXG5hc3luYyBmdW5jdGlvbiBvcGVuRXhjZWwoKTogUHJvbWlzZTx2b2lkPiB7XG5cdHRyeSB7XG5cdFx0aWYgKFxuXHRcdFx0b3Blbldvcmtib29rcyAmJlxuXHRcdFx0c2VsZWN0ZWRXb3JrYm9va0luZGV4ICE9PSB1bmRlZmluZWQgJiZcblx0XHRcdG9wZW5Xb3Jrc2hlZXRzICYmXG5cdFx0XHRzZWxlY3RlZFdvcmtzaGVldEluZGV4ICE9PSB1bmRlZmluZWRcblx0XHQpIHtcblx0XHRcdC8vIE9wZW4gdGhlIHNlbGVjdCB3b3JrIGJvb2sgYW5kIHNoZWV0XG5cdFx0XHQvLyBpZiBhbnl0aGluZyB0aHJvd3MgYW4gZXhjZXB0aW9uIGp1c3Qgb3BlbiBhIG5ldyB3b3JrYm9va1xuXHRcdFx0YXdhaXQgc2VsZWN0V29ya2Jvb2sob3Blbldvcmtib29rc1tzZWxlY3RlZFdvcmtib29rSW5kZXhdLm5hbWUpO1xuXHRcdFx0YXdhaXQgc2VsZWN0V29ya3NoZWV0KG9wZW5Xb3Jrc2hlZXRzW3NlbGVjdGVkV29ya3NoZWV0SW5kZXhdLm5hbWUpO1xuXHRcdH1cblx0fSBjYXRjaCB7XG5cdFx0aWYgKGV4Y2VsKSB7XG5cdFx0XHRhd2FpdCBleGNlbC5jcmVhdGVXb3JrYm9vaygpO1xuXHRcdFx0YXdhaXQgcG9wdWxhdGVXb3JrYm9va3MoKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBQb3B1bGF0ZSB0aGUgbGlzdCBvZiB3b3JrYm9va3MuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHBvcHVsYXRlV29ya2Jvb2tzKCk6IFByb21pc2U8dm9pZD4ge1xuXHRpZiAoZXhjZWwpIHtcblx0XHRzZWxlY3RlZFdvcmtib29rSW5kZXggPSB1bmRlZmluZWQ7XG5cdFx0Y29uc3QgcmVmcmVzaEJ1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEJ1dHRvbkVsZW1lbnQ+KFwiI3dvcmtib29rLXJlZnJlc2hcIik7XG5cdFx0Y29uc3Qgc2VsZWN0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MU2VsZWN0RWxlbWVudD4oXCIjd29ya2Jvb2tzXCIpO1xuXG5cdFx0aWYgKHJlZnJlc2hCdXR0b24gJiYgc2VsZWN0KSB7XG5cdFx0XHRyZWZyZXNoQnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcblxuXHRcdFx0c2VsZWN0LmRpc2FibGVkID0gdHJ1ZTtcblx0XHRcdHNlbGVjdC5pbm5lckhUTUwgPSBcIlwiO1xuXG5cdFx0XHRvcGVuV29ya2Jvb2tzID0gW107XG5cblx0XHRcdHRyeSB7XG5cdFx0XHRcdGNvbnN0IHdvcmtib29rcyA9IGF3YWl0IGV4Y2VsLmdldFdvcmtib29rcygpO1xuXG5cdFx0XHRcdGZvciAoY29uc3QgYm9vayBvZiB3b3JrYm9va3MpIHtcblx0XHRcdFx0XHRjb25zdCBuYW1lID0gYXdhaXQgYm9vay5nZXROYW1lKCk7XG5cdFx0XHRcdFx0b3Blbldvcmtib29rcy5wdXNoKHtcblx0XHRcdFx0XHRcdGJvb2ssXG5cdFx0XHRcdFx0XHRuYW1lXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb25zdCBvcHRpb25FbXB0eSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG5cdFx0XHRcdG9wdGlvbkVtcHR5LmlubmVySFRNTCA9IFwiLS0tLVNlbGVjdCB3b3JrYm9vay0tLS1cIjtcblx0XHRcdFx0b3B0aW9uRW1wdHkudmFsdWUgPSBcIlwiO1xuXHRcdFx0XHRvcHRpb25FbXB0eS5zZWxlY3RlZCA9IHRydWU7XG5cdFx0XHRcdG9wdGlvbkVtcHR5LmRpc2FibGVkID0gdHJ1ZTtcblx0XHRcdFx0c2VsZWN0LmFwcGVuZChvcHRpb25FbXB0eSk7XG5cblx0XHRcdFx0Zm9yIChjb25zdCBvcGVuV29ya2Jvb2sgb2Ygb3Blbldvcmtib29rcykge1xuXHRcdFx0XHRcdGNvbnN0IG9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG5cdFx0XHRcdFx0b3B0aW9uLmlubmVySFRNTCA9IG9wZW5Xb3JrYm9vay5uYW1lO1xuXHRcdFx0XHRcdG9wdGlvbi52YWx1ZSA9IG9wZW5Xb3JrYm9vay5uYW1lO1xuXHRcdFx0XHRcdHNlbGVjdC5hcHBlbmQob3B0aW9uKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRcdGNvbnNvbGUuZXJyb3IoZXJyKTtcblx0XHRcdFx0c2hvd0Vycm9yKGVycik7XG5cdFx0XHR9IGZpbmFsbHkge1xuXHRcdFx0XHRzZWxlY3QuZGlzYWJsZWQgPSBmYWxzZTtcblx0XHRcdFx0cmVmcmVzaEJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIFNlbGVjdCBhIHdvcmtib29rLlxuICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2YgdGhlIHdvcmtib29rIHRvIHNlbGVjdC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2VsZWN0V29ya2Jvb2sobmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG5cdGlmIChvcGVuV29ya2Jvb2tzKSB7XG5cdFx0Y29uc3QgbmV3V29ya2Jvb2tJbmRleCA9IG9wZW5Xb3JrYm9va3MuZmluZEluZGV4KCh3KSA9PiB3Lm5hbWUgPT09IG5hbWUpO1xuXG5cdFx0aWYgKG5ld1dvcmtib29rSW5kZXggIT09IHNlbGVjdGVkV29ya2Jvb2tJbmRleCkge1xuXHRcdFx0c2VsZWN0ZWRXb3JrYm9va0luZGV4ID0gbmV3V29ya2Jvb2tJbmRleDtcblx0XHRcdGlmIChuZXdXb3JrYm9va0luZGV4ID49IDApIHtcblx0XHRcdFx0YXdhaXQgb3Blbldvcmtib29rc1tzZWxlY3RlZFdvcmtib29rSW5kZXhdLmJvb2suYWN0aXZhdGUoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRhd2FpdCBwb3B1bGF0ZVdvcmtzaGVldHMoKTtcblx0fVxufVxuXG4vKipcbiAqIFBvcHVsYXRlIHRoZSB3b3Jrc2hlZXRzLlxuICovXG5hc3luYyBmdW5jdGlvbiBwb3B1bGF0ZVdvcmtzaGVldHMoKTogUHJvbWlzZTx2b2lkPiB7XG5cdGlmIChleGNlbCkge1xuXHRcdHNlbGVjdGVkV29ya3NoZWV0SW5kZXggPSB1bmRlZmluZWQ7XG5cdFx0Y29uc3QgcmVmcmVzaEJ1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEJ1dHRvbkVsZW1lbnQ+KFwiI3dvcmtzaGVldC1yZWZyZXNoXCIpO1xuXHRcdGNvbnN0IHNlbGVjdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTFNlbGVjdEVsZW1lbnQ+KFwiI3dvcmtzaGVldHNcIik7XG5cblx0XHRpZiAoc2VsZWN0ICYmIHJlZnJlc2hCdXR0b24gJiYgb3Blbldvcmtib29rcyAmJiBzZWxlY3RlZFdvcmtib29rSW5kZXggIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0cmVmcmVzaEJ1dHRvbi5kaXNhYmxlZCA9IHRydWU7XG5cblx0XHRcdHNlbGVjdC5kaXNhYmxlZCA9IHRydWU7XG5cdFx0XHRzZWxlY3QuaW5uZXJIVE1MID0gXCJcIjtcblxuXHRcdFx0b3BlbldvcmtzaGVldHMgPSBbXTtcblxuXHRcdFx0Y29uc3Qgd29ya2Jvb2sgPSBvcGVuV29ya2Jvb2tzW3NlbGVjdGVkV29ya2Jvb2tJbmRleF07XG5cdFx0XHRpZiAod29ya2Jvb2spIHtcblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRjb25zdCBzaGVldHMgPSBhd2FpdCB3b3JrYm9vay5ib29rLmdldFdvcmtzaGVldHMoKTtcblxuXHRcdFx0XHRcdGZvciAoY29uc3Qgc2hlZXQgb2Ygc2hlZXRzKSB7XG5cdFx0XHRcdFx0XHRjb25zdCBuYW1lID0gYXdhaXQgc2hlZXQuZ2V0TmFtZSgpO1xuXHRcdFx0XHRcdFx0b3BlbldvcmtzaGVldHMucHVzaCh7XG5cdFx0XHRcdFx0XHRcdHNoZWV0LFxuXHRcdFx0XHRcdFx0XHRuYW1lXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRjb25zdCBvcHRpb25FbXB0eSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG5cdFx0XHRcdFx0b3B0aW9uRW1wdHkuaW5uZXJIVE1MID0gXCItLS0tU2VsZWN0IHdvcmtzaGVldC0tLS1cIjtcblx0XHRcdFx0XHRvcHRpb25FbXB0eS52YWx1ZSA9IFwiXCI7XG5cdFx0XHRcdFx0b3B0aW9uRW1wdHkuc2VsZWN0ZWQgPSB0cnVlO1xuXHRcdFx0XHRcdG9wdGlvbkVtcHR5LmRpc2FibGVkID0gdHJ1ZTtcblx0XHRcdFx0XHRzZWxlY3QuYXBwZW5kKG9wdGlvbkVtcHR5KTtcblxuXHRcdFx0XHRcdGZvciAoY29uc3Qgb3BlbldvcmtzaGVldCBvZiBvcGVuV29ya3NoZWV0cykge1xuXHRcdFx0XHRcdFx0Y29uc3Qgb3B0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIm9wdGlvblwiKTtcblx0XHRcdFx0XHRcdG9wdGlvbi5pbm5lckhUTUwgPSBvcGVuV29ya3NoZWV0Lm5hbWU7XG5cdFx0XHRcdFx0XHRvcHRpb24udmFsdWUgPSBvcGVuV29ya3NoZWV0Lm5hbWU7XG5cdFx0XHRcdFx0XHRzZWxlY3QuYXBwZW5kKG9wdGlvbik7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdFx0XHRjb25zb2xlLmVycm9yKGVycik7XG5cdFx0XHRcdFx0c2hvd0Vycm9yKGVycik7XG5cdFx0XHRcdH0gZmluYWxseSB7XG5cdFx0XHRcdFx0c2VsZWN0LmRpc2FibGVkID0gZmFsc2U7XG5cdFx0XHRcdFx0cmVmcmVzaEJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogU2VsZWN0IGEgd29ya3NoZWV0LlxuICogQHBhcmFtIG5hbWUgVGhlIG5hbWUgb2Ygd29ya3NoZWV0IHRvIHNlbGVjdC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2VsZWN0V29ya3NoZWV0KG5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHRpZiAob3BlbldvcmtzaGVldHMpIHtcblx0XHRjb25zdCBuZXdXb3Jrc2hlZXRJbmRleCA9IG9wZW5Xb3Jrc2hlZXRzLmZpbmRJbmRleCgodykgPT4gdy5uYW1lID09PSBuYW1lKTtcblxuXHRcdGlmIChuZXdXb3Jrc2hlZXRJbmRleCAhPT0gc2VsZWN0ZWRXb3Jrc2hlZXRJbmRleCkge1xuXHRcdFx0aWYgKHNlbGVjdGVkV29ya3NoZWV0SW5kZXggIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRjb25zdCBvbGRXb3Jrc2hlZXQgPSBvcGVuV29ya3NoZWV0c1tzZWxlY3RlZFdvcmtzaGVldEluZGV4XTtcblx0XHRcdFx0aWYgKG9sZFdvcmtzaGVldCkge1xuXHRcdFx0XHRcdGF3YWl0IG9sZFdvcmtzaGVldC5zaGVldC5yZW1vdmVFdmVudExpc3RlbmVyKGhhbmRsZUNlbGxDaGFuZ2UpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHNlbGVjdGVkV29ya3NoZWV0SW5kZXggPSBuZXdXb3Jrc2hlZXRJbmRleDtcblx0XHRcdGlmIChzZWxlY3RlZFdvcmtzaGVldEluZGV4ID49IDApIHtcblx0XHRcdFx0YXdhaXQgb3BlbldvcmtzaGVldHNbc2VsZWN0ZWRXb3Jrc2hlZXRJbmRleF0uc2hlZXQuYWN0aXZhdGUoKTtcblx0XHRcdFx0YXdhaXQgb3BlbldvcmtzaGVldHNbc2VsZWN0ZWRXb3Jrc2hlZXRJbmRleF0uc2hlZXQuYWRkRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCBoYW5kbGVDZWxsQ2hhbmdlKTtcblxuXHRcdFx0XHRjb25zdCByZXN1bHRzQ29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MRWxlbWVudD4oXCIjcmVzdWx0cy1jb250YWluZXJcIik7XG5cdFx0XHRcdGlmIChyZXN1bHRzQ29udGFpbmVyKSB7XG5cdFx0XHRcdFx0cmVzdWx0c0NvbnRhaW5lci5zdHlsZS5kaXNwbGF5ID0gXCJmbGV4XCI7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb25zdCBjZWxsTG9jYXRpb24gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxJbnB1dEVsZW1lbnQ+KFwiI2NlbGwtbG9jYXRpb25cIik7XG5cdFx0XHRcdGlmIChjZWxsTG9jYXRpb24pIHtcblx0XHRcdFx0XHRjZWxsTG9jYXRpb24uZGlzYWJsZWQgPSBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb25zdCBjZWxsVmFsdWUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxJbnB1dEVsZW1lbnQ+KFwiI2NlbGwtdmFsdWVcIik7XG5cdFx0XHRcdGlmIChjZWxsVmFsdWUpIHtcblx0XHRcdFx0XHRjZWxsVmFsdWUuZGlzYWJsZWQgPSBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb25zdCBzZXRWYWx1ZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTElucHV0RWxlbWVudD4oXCIjc2V0LXZhbHVlXCIpO1xuXHRcdFx0XHRpZiAoc2V0VmFsdWUpIHtcblx0XHRcdFx0XHRzZXRWYWx1ZS5kaXNhYmxlZCA9IGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogSGFuZGxlIGEgY2hhbmdlIGZyb20gdGhlIGV4Y2VsIHdvcmtzaGVldC5cbiAqIEBwYXJhbSBjZWxscyBUaGUgY2VsbHMgdGhhdCB3ZXJlIGNoYW5nZWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZUNlbGxDaGFuZ2UoY2VsbHM6IENlbGxbXSk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBjZWxsQ29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNjZWxsLWNoYW5nZXMtY29udGFpbmVyXCIpO1xuXHRpZiAoY2VsbENvbnRhaW5lcikge1xuXHRcdGNlbGxDb250YWluZXIuaW5uZXJIVE1MID0gSlNPTi5zdHJpbmdpZnkoY2VsbHMsIHVuZGVmaW5lZCwgXCIgIFwiKTtcblxuXHRcdGZvciAoY29uc3QgY2VsbCBvZiBjZWxscykge1xuXHRcdFx0aWYgKEtOT1dOX0lOU1RSVU1FTlRTLmluY2x1ZGVzKGNlbGwudmFsdWUpKSB7XG5cdFx0XHRcdGF3YWl0IGJyb2FkY2FzdEluc3RydW1lbnQoY2VsbC52YWx1ZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogU2V0IGEgY2VsbCB2YWx1ZSBpbiBleGNlbC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2V0Q2VsbFZhbHVlKCk6IFByb21pc2U8dm9pZD4ge1xuXHRpZiAob3BlbldvcmtzaGVldHMgJiYgc2VsZWN0ZWRXb3Jrc2hlZXRJbmRleCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0Y29uc3QgY2VsbExvY2F0aW9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MSW5wdXRFbGVtZW50PihcIiNjZWxsLWxvY2F0aW9uXCIpO1xuXHRcdGNvbnN0IGNlbGxWYWx1ZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTElucHV0RWxlbWVudD4oXCIjY2VsbC12YWx1ZVwiKTtcblxuXHRcdGlmIChjZWxsTG9jYXRpb24gJiYgY2VsbFZhbHVlKSB7XG5cdFx0XHRjb25zdCBjZWxscyA9IFtbY2VsbFZhbHVlLnZhbHVlXV07XG5cdFx0XHRhd2FpdCBvcGVuV29ya3NoZWV0c1tzZWxlY3RlZFdvcmtzaGVldEluZGV4XS5zaGVldC5zZXRDZWxsVmFsdWVzKGNlbGxMb2NhdGlvbi52YWx1ZSwgY2VsbHMpO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIEJyb2FkY2FzdCBhbmQgRkRDMyBpbnN0cnVtZW50LlxuICogQHBhcmFtIGluc3RydW1lbnQgVGhlIGluc3RydW1lbnQgdG8gYnJvYWRjYXN0LlxuICovXG5hc3luYyBmdW5jdGlvbiBicm9hZGNhc3RJbnN0cnVtZW50KGluc3RydW1lbnQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBicm9hZGNhc3RFbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MSW5wdXRFbGVtZW50PihcIiNicm9hZGNhc3QtaW5zdHJ1bWVudFwiKTtcblx0aWYgKGJyb2FkY2FzdEVsZW1lbnQpIHtcblx0XHRpZiAod2luZG93LmZkYzMpIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGNvbnN0IGZkY0luc3RydW1lbnQgPSB7XG5cdFx0XHRcdFx0dHlwZTogXCJmZGMzLmluc3RydW1lbnRcIixcblx0XHRcdFx0XHRpZDoge1xuXHRcdFx0XHRcdFx0dGlja2VyOiBpbnN0cnVtZW50XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdGNvbnN0IGNoYW5uZWwgPSBhd2FpdCBnZXRDdXJyZW50Q2hhbm5lbCgpO1xuXHRcdFx0XHRpZiAoY2hhbm5lbCkge1xuXHRcdFx0XHRcdGF3YWl0IGNoYW5uZWwuYnJvYWRjYXN0KGZkY0luc3RydW1lbnQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0YnJvYWRjYXN0RWxlbWVudC52YWx1ZSA9IGluc3RydW1lbnQ7XG5cdFx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdFx0YnJvYWRjYXN0RWxlbWVudC52YWx1ZSA9IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBKU09OLnN0cmluZ2lmeShlcnIpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRicm9hZGNhc3RFbGVtZW50LnRleHRDb250ZW50ID0gXCJObyBGRDMgQ2hhbm5lbCBhdmFpbGFibGVcIjtcblx0XHR9XG5cdH1cbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/integration-excel/js/fdc3monitor.bundle.js b/dev/john/update-logging-example/integration-excel/js/fdc3monitor.bundle.js new file mode 100644 index 00000000..5333659d --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/js/fdc3monitor.bundle.js @@ -0,0 +1,3330 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ "../../node_modules/@finos/fdc3/dist/fdc3.esm.js": +/*!*******************************************************!*\ + !*** ../../node_modules/@finos/fdc3/dist/fdc3.esm.js ***! + \*******************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ BridgingError: () => (/* binding */ BridgingError), +/* harmony export */ BridgingTypes: () => (/* binding */ BridgingTypes), +/* harmony export */ ChannelError: () => (/* binding */ ChannelError), +/* harmony export */ ContextTypes: () => (/* binding */ ContextTypes), +/* harmony export */ Convert: () => (/* binding */ Convert), +/* harmony export */ Intents: () => (/* binding */ Intents), +/* harmony export */ OpenError: () => (/* binding */ OpenError), +/* harmony export */ ResolveError: () => (/* binding */ ResolveError), +/* harmony export */ ResultError: () => (/* binding */ ResultError), +/* harmony export */ addContextListener: () => (/* binding */ addContextListener), +/* harmony export */ addIntentListener: () => (/* binding */ addIntentListener), +/* harmony export */ broadcast: () => (/* binding */ broadcast), +/* harmony export */ compareVersionNumbers: () => (/* binding */ compareVersionNumbers), +/* harmony export */ createPrivateChannel: () => (/* binding */ createPrivateChannel), +/* harmony export */ fdc3Ready: () => (/* binding */ fdc3Ready), +/* harmony export */ findInstances: () => (/* binding */ findInstances), +/* harmony export */ findIntent: () => (/* binding */ findIntent), +/* harmony export */ findIntentsByContext: () => (/* binding */ findIntentsByContext), +/* harmony export */ getAppMetadata: () => (/* binding */ getAppMetadata), +/* harmony export */ getCurrentChannel: () => (/* binding */ getCurrentChannel), +/* harmony export */ getInfo: () => (/* binding */ getInfo), +/* harmony export */ getOrCreateChannel: () => (/* binding */ getOrCreateChannel), +/* harmony export */ getSystemChannels: () => (/* binding */ getSystemChannels), +/* harmony export */ getUserChannels: () => (/* binding */ getUserChannels), +/* harmony export */ isStandardContextType: () => (/* binding */ isStandardContextType), +/* harmony export */ isStandardIntent: () => (/* binding */ isStandardIntent), +/* harmony export */ joinChannel: () => (/* binding */ joinChannel), +/* harmony export */ joinUserChannel: () => (/* binding */ joinUserChannel), +/* harmony export */ leaveCurrentChannel: () => (/* binding */ leaveCurrentChannel), +/* harmony export */ open: () => (/* binding */ open), +/* harmony export */ raiseIntent: () => (/* binding */ raiseIntent), +/* harmony export */ raiseIntentForContext: () => (/* binding */ raiseIntentForContext), +/* harmony export */ versionIsAtLeast: () => (/* binding */ versionIsAtLeast) +/* harmony export */ }); +// To parse this data: +// +// import { Convert, AgentErrorResponseMessage, AgentRequestMessage, AgentResponseMessage, BridgeErrorResponseMessage, BridgeRequestMessage, BridgeResponseMessage, BroadcastAgentRequest, BroadcastBridgeRequest, ConnectionStepMessage, ConnectionStep2Hello, ConnectionStep3Handshake, ConnectionStep4AuthenticationFailed, ConnectionStep6ConnectedAgentsUpdate, FindInstancesAgentErrorResponse, FindInstancesAgentRequest, FindInstancesAgentResponse, FindInstancesBridgeErrorResponse, FindInstancesBridgeRequest, FindInstancesBridgeResponse, FindIntentAgentErrorResponse, FindIntentAgentRequest, FindIntentAgentResponse, FindIntentBridgeErrorResponse, FindIntentBridgeRequest, FindIntentBridgeResponse, FindIntentsByContextAgentErrorResponse, FindIntentsByContextAgentRequest, FindIntentsByContextAgentResponse, FindIntentsByContextBridgeErrorResponse, FindIntentsByContextBridgeRequest, FindIntentsByContextBridgeResponse, GetAppMetadataAgentErrorResponse, GetAppMetadataAgentRequest, GetAppMetadataAgentResponse, GetAppMetadataBridgeErrorResponse, GetAppMetadataBridgeRequest, GetAppMetadataBridgeResponse, OpenAgentErrorResponse, OpenAgentRequest, OpenAgentResponse, OpenBridgeErrorResponse, OpenBridgeRequest, OpenBridgeResponse, PrivateChannelBroadcastAgentRequest, PrivateChannelBroadcastBridgeRequest, PrivateChannelEventListenerAddedAgentRequest, PrivateChannelEventListenerAddedBridgeRequest, PrivateChannelEventListenerRemovedAgentRequest, PrivateChannelEventListenerRemovedBridgeRequest, PrivateChannelOnAddContextListenerAgentRequest, PrivateChannelOnAddContextListenerBridgeRequest, PrivateChannelOnDisconnectAgentRequest, PrivateChannelOnDisconnectBridgeRequest, PrivateChannelOnUnsubscribeAgentRequest, PrivateChannelOnUnsubscribeBridgeRequest, RaiseIntentAgentErrorResponse, RaiseIntentAgentRequest, RaiseIntentAgentResponse, RaiseIntentBridgeErrorResponse, RaiseIntentBridgeRequest, RaiseIntentBridgeResponse, RaiseIntentResultAgentErrorResponse, RaiseIntentResultAgentResponse, RaiseIntentResultBridgeErrorResponse, RaiseIntentResultBridgeResponse, Context } from "./file"; +// +// const fDC3DesktopAgentAPISchema = Convert.toFDC3DesktopAgentAPISchema(json); +// const agentErrorResponseMessage = Convert.toAgentErrorResponseMessage(json); +// const agentRequestMessage = Convert.toAgentRequestMessage(json); +// const agentResponseMessage = Convert.toAgentResponseMessage(json); +// const bridgeErrorResponseMessage = Convert.toBridgeErrorResponseMessage(json); +// const bridgeRequestMessage = Convert.toBridgeRequestMessage(json); +// const bridgeResponseMessage = Convert.toBridgeResponseMessage(json); +// const broadcastAgentRequest = Convert.toBroadcastAgentRequest(json); +// const broadcastBridgeRequest = Convert.toBroadcastBridgeRequest(json); +// const bridgingCommons = Convert.toBridgingCommons(json); +// const connectionStepMessage = Convert.toConnectionStepMessage(json); +// const connectionStep2Hello = Convert.toConnectionStep2Hello(json); +// const connectionStep3Handshake = Convert.toConnectionStep3Handshake(json); +// const connectionStep4AuthenticationFailed = Convert.toConnectionStep4AuthenticationFailed(json); +// const connectionStep6ConnectedAgentsUpdate = Convert.toConnectionStep6ConnectedAgentsUpdate(json); +// const findInstancesAgentErrorResponse = Convert.toFindInstancesAgentErrorResponse(json); +// const findInstancesAgentRequest = Convert.toFindInstancesAgentRequest(json); +// const findInstancesAgentResponse = Convert.toFindInstancesAgentResponse(json); +// const findInstancesBridgeErrorResponse = Convert.toFindInstancesBridgeErrorResponse(json); +// const findInstancesBridgeRequest = Convert.toFindInstancesBridgeRequest(json); +// const findInstancesBridgeResponse = Convert.toFindInstancesBridgeResponse(json); +// const findIntentAgentErrorResponse = Convert.toFindIntentAgentErrorResponse(json); +// const findIntentAgentRequest = Convert.toFindIntentAgentRequest(json); +// const findIntentAgentResponse = Convert.toFindIntentAgentResponse(json); +// const findIntentBridgeErrorResponse = Convert.toFindIntentBridgeErrorResponse(json); +// const findIntentBridgeRequest = Convert.toFindIntentBridgeRequest(json); +// const findIntentBridgeResponse = Convert.toFindIntentBridgeResponse(json); +// const findIntentsByContextAgentErrorResponse = Convert.toFindIntentsByContextAgentErrorResponse(json); +// const findIntentsByContextAgentRequest = Convert.toFindIntentsByContextAgentRequest(json); +// const findIntentsByContextAgentResponse = Convert.toFindIntentsByContextAgentResponse(json); +// const findIntentsByContextBridgeErrorResponse = Convert.toFindIntentsByContextBridgeErrorResponse(json); +// const findIntentsByContextBridgeRequest = Convert.toFindIntentsByContextBridgeRequest(json); +// const findIntentsByContextBridgeResponse = Convert.toFindIntentsByContextBridgeResponse(json); +// const getAppMetadataAgentErrorResponse = Convert.toGetAppMetadataAgentErrorResponse(json); +// const getAppMetadataAgentRequest = Convert.toGetAppMetadataAgentRequest(json); +// const getAppMetadataAgentResponse = Convert.toGetAppMetadataAgentResponse(json); +// const getAppMetadataBridgeErrorResponse = Convert.toGetAppMetadataBridgeErrorResponse(json); +// const getAppMetadataBridgeRequest = Convert.toGetAppMetadataBridgeRequest(json); +// const getAppMetadataBridgeResponse = Convert.toGetAppMetadataBridgeResponse(json); +// const openAgentErrorResponse = Convert.toOpenAgentErrorResponse(json); +// const openAgentRequest = Convert.toOpenAgentRequest(json); +// const openAgentResponse = Convert.toOpenAgentResponse(json); +// const openBridgeErrorResponse = Convert.toOpenBridgeErrorResponse(json); +// const openBridgeRequest = Convert.toOpenBridgeRequest(json); +// const openBridgeResponse = Convert.toOpenBridgeResponse(json); +// const privateChannelBroadcastAgentRequest = Convert.toPrivateChannelBroadcastAgentRequest(json); +// const privateChannelBroadcastBridgeRequest = Convert.toPrivateChannelBroadcastBridgeRequest(json); +// const privateChannelEventListenerAddedAgentRequest = Convert.toPrivateChannelEventListenerAddedAgentRequest(json); +// const privateChannelEventListenerAddedBridgeRequest = Convert.toPrivateChannelEventListenerAddedBridgeRequest(json); +// const privateChannelEventListenerRemovedAgentRequest = Convert.toPrivateChannelEventListenerRemovedAgentRequest(json); +// const privateChannelEventListenerRemovedBridgeRequest = Convert.toPrivateChannelEventListenerRemovedBridgeRequest(json); +// const privateChannelOnAddContextListenerAgentRequest = Convert.toPrivateChannelOnAddContextListenerAgentRequest(json); +// const privateChannelOnAddContextListenerBridgeRequest = Convert.toPrivateChannelOnAddContextListenerBridgeRequest(json); +// const privateChannelOnDisconnectAgentRequest = Convert.toPrivateChannelOnDisconnectAgentRequest(json); +// const privateChannelOnDisconnectBridgeRequest = Convert.toPrivateChannelOnDisconnectBridgeRequest(json); +// const privateChannelOnUnsubscribeAgentRequest = Convert.toPrivateChannelOnUnsubscribeAgentRequest(json); +// const privateChannelOnUnsubscribeBridgeRequest = Convert.toPrivateChannelOnUnsubscribeBridgeRequest(json); +// const raiseIntentAgentErrorResponse = Convert.toRaiseIntentAgentErrorResponse(json); +// const raiseIntentAgentRequest = Convert.toRaiseIntentAgentRequest(json); +// const raiseIntentAgentResponse = Convert.toRaiseIntentAgentResponse(json); +// const raiseIntentBridgeErrorResponse = Convert.toRaiseIntentBridgeErrorResponse(json); +// const raiseIntentBridgeRequest = Convert.toRaiseIntentBridgeRequest(json); +// const raiseIntentBridgeResponse = Convert.toRaiseIntentBridgeResponse(json); +// const raiseIntentResultAgentErrorResponse = Convert.toRaiseIntentResultAgentErrorResponse(json); +// const raiseIntentResultAgentResponse = Convert.toRaiseIntentResultAgentResponse(json); +// const raiseIntentResultBridgeErrorResponse = Convert.toRaiseIntentResultBridgeErrorResponse(json); +// const raiseIntentResultBridgeResponse = Convert.toRaiseIntentResultBridgeResponse(json); +// const context = Convert.toContext(json); +// +// These functions will throw an error if the JSON doesn't +// match the expected interface, even if the JSON is valid. +// Converts JSON strings to/from your types +// and asserts the results of JSON.parse at runtime +var Convert$1 = /** @class */ (function () { + function Convert() { + } + Convert.toFDC3DesktopAgentAPISchema = function (json) { + return cast$1(JSON.parse(json), "any"); + }; + Convert.fDC3DesktopAgentAPISchemaToJson = function (value) { + return JSON.stringify(uncast$1(value, "any"), null, 2); + }; + Convert.toAgentErrorResponseMessage = function (json) { + return cast$1(JSON.parse(json), r$1("AgentErrorResponseMessage")); + }; + Convert.agentErrorResponseMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("AgentErrorResponseMessage")), null, 2); + }; + Convert.toAgentRequestMessage = function (json) { + return cast$1(JSON.parse(json), r$1("AgentRequestMessage")); + }; + Convert.agentRequestMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("AgentRequestMessage")), null, 2); + }; + Convert.toAgentResponseMessage = function (json) { + return cast$1(JSON.parse(json), r$1("AgentResponseMessage")); + }; + Convert.agentResponseMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("AgentResponseMessage")), null, 2); + }; + Convert.toBridgeErrorResponseMessage = function (json) { + return cast$1(JSON.parse(json), r$1("BridgeErrorResponseMessage")); + }; + Convert.bridgeErrorResponseMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("BridgeErrorResponseMessage")), null, 2); + }; + Convert.toBridgeRequestMessage = function (json) { + return cast$1(JSON.parse(json), r$1("BridgeRequestMessage")); + }; + Convert.bridgeRequestMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("BridgeRequestMessage")), null, 2); + }; + Convert.toBridgeResponseMessage = function (json) { + return cast$1(JSON.parse(json), r$1("BridgeResponseMessage")); + }; + Convert.bridgeResponseMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("BridgeResponseMessage")), null, 2); + }; + Convert.toBroadcastAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("BroadcastAgentRequest")); + }; + Convert.broadcastAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("BroadcastAgentRequest")), null, 2); + }; + Convert.toBroadcastBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("BroadcastBridgeRequest")); + }; + Convert.broadcastBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("BroadcastBridgeRequest")), null, 2); + }; + Convert.toBridgingCommons = function (json) { + return cast$1(JSON.parse(json), m$1("any")); + }; + Convert.bridgingCommonsToJson = function (value) { + return JSON.stringify(uncast$1(value, m$1("any")), null, 2); + }; + Convert.toConnectionStepMessage = function (json) { + return cast$1(JSON.parse(json), r$1("ConnectionStepMessage")); + }; + Convert.connectionStepMessageToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("ConnectionStepMessage")), null, 2); + }; + Convert.toConnectionStep2Hello = function (json) { + return cast$1(JSON.parse(json), r$1("ConnectionStep2Hello")); + }; + Convert.connectionStep2HelloToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("ConnectionStep2Hello")), null, 2); + }; + Convert.toConnectionStep3Handshake = function (json) { + return cast$1(JSON.parse(json), r$1("ConnectionStep3Handshake")); + }; + Convert.connectionStep3HandshakeToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("ConnectionStep3Handshake")), null, 2); + }; + Convert.toConnectionStep4AuthenticationFailed = function (json) { + return cast$1(JSON.parse(json), r$1("ConnectionStep4AuthenticationFailed")); + }; + Convert.connectionStep4AuthenticationFailedToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("ConnectionStep4AuthenticationFailed")), null, 2); + }; + Convert.toConnectionStep6ConnectedAgentsUpdate = function (json) { + return cast$1(JSON.parse(json), r$1("ConnectionStep6ConnectedAgentsUpdate")); + }; + Convert.connectionStep6ConnectedAgentsUpdateToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("ConnectionStep6ConnectedAgentsUpdate")), null, 2); + }; + Convert.toFindInstancesAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesAgentErrorResponse")); + }; + Convert.findInstancesAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesAgentErrorResponse")), null, 2); + }; + Convert.toFindInstancesAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesAgentRequest")); + }; + Convert.findInstancesAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesAgentRequest")), null, 2); + }; + Convert.toFindInstancesAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesAgentResponse")); + }; + Convert.findInstancesAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesAgentResponse")), null, 2); + }; + Convert.toFindInstancesBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesBridgeErrorResponse")); + }; + Convert.findInstancesBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesBridgeErrorResponse")), null, 2); + }; + Convert.toFindInstancesBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesBridgeRequest")); + }; + Convert.findInstancesBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesBridgeRequest")), null, 2); + }; + Convert.toFindInstancesBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindInstancesBridgeResponse")); + }; + Convert.findInstancesBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindInstancesBridgeResponse")), null, 2); + }; + Convert.toFindIntentAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentAgentErrorResponse")); + }; + Convert.findIntentAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentAgentErrorResponse")), null, 2); + }; + Convert.toFindIntentAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentAgentRequest")); + }; + Convert.findIntentAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentAgentRequest")), null, 2); + }; + Convert.toFindIntentAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentAgentResponse")); + }; + Convert.findIntentAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentAgentResponse")), null, 2); + }; + Convert.toFindIntentBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentBridgeErrorResponse")); + }; + Convert.findIntentBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentBridgeErrorResponse")), null, 2); + }; + Convert.toFindIntentBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentBridgeRequest")); + }; + Convert.findIntentBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentBridgeRequest")), null, 2); + }; + Convert.toFindIntentBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentBridgeResponse")); + }; + Convert.findIntentBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentBridgeResponse")), null, 2); + }; + Convert.toFindIntentsByContextAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextAgentErrorResponse")); + }; + Convert.findIntentsByContextAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextAgentErrorResponse")), null, 2); + }; + Convert.toFindIntentsByContextAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextAgentRequest")); + }; + Convert.findIntentsByContextAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextAgentRequest")), null, 2); + }; + Convert.toFindIntentsByContextAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextAgentResponse")); + }; + Convert.findIntentsByContextAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextAgentResponse")), null, 2); + }; + Convert.toFindIntentsByContextBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextBridgeErrorResponse")); + }; + Convert.findIntentsByContextBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextBridgeErrorResponse")), null, 2); + }; + Convert.toFindIntentsByContextBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextBridgeRequest")); + }; + Convert.findIntentsByContextBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextBridgeRequest")), null, 2); + }; + Convert.toFindIntentsByContextBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("FindIntentsByContextBridgeResponse")); + }; + Convert.findIntentsByContextBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("FindIntentsByContextBridgeResponse")), null, 2); + }; + Convert.toGetAppMetadataAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataAgentErrorResponse")); + }; + Convert.getAppMetadataAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataAgentErrorResponse")), null, 2); + }; + Convert.toGetAppMetadataAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataAgentRequest")); + }; + Convert.getAppMetadataAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataAgentRequest")), null, 2); + }; + Convert.toGetAppMetadataAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataAgentResponse")); + }; + Convert.getAppMetadataAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataAgentResponse")), null, 2); + }; + Convert.toGetAppMetadataBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataBridgeErrorResponse")); + }; + Convert.getAppMetadataBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataBridgeErrorResponse")), null, 2); + }; + Convert.toGetAppMetadataBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataBridgeRequest")); + }; + Convert.getAppMetadataBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataBridgeRequest")), null, 2); + }; + Convert.toGetAppMetadataBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("GetAppMetadataBridgeResponse")); + }; + Convert.getAppMetadataBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("GetAppMetadataBridgeResponse")), null, 2); + }; + Convert.toOpenAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("OpenAgentErrorResponse")); + }; + Convert.openAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenAgentErrorResponse")), null, 2); + }; + Convert.toOpenAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("OpenAgentRequest")); + }; + Convert.openAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenAgentRequest")), null, 2); + }; + Convert.toOpenAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("OpenAgentResponse")); + }; + Convert.openAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenAgentResponse")), null, 2); + }; + Convert.toOpenBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("OpenBridgeErrorResponse")); + }; + Convert.openBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenBridgeErrorResponse")), null, 2); + }; + Convert.toOpenBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("OpenBridgeRequest")); + }; + Convert.openBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenBridgeRequest")), null, 2); + }; + Convert.toOpenBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("OpenBridgeResponse")); + }; + Convert.openBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("OpenBridgeResponse")), null, 2); + }; + Convert.toPrivateChannelBroadcastAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelBroadcastAgentRequest")); + }; + Convert.privateChannelBroadcastAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelBroadcastAgentRequest")), null, 2); + }; + Convert.toPrivateChannelBroadcastBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelBroadcastBridgeRequest")); + }; + Convert.privateChannelBroadcastBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelBroadcastBridgeRequest")), null, 2); + }; + Convert.toPrivateChannelEventListenerAddedAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelEventListenerAddedAgentRequest")); + }; + Convert.privateChannelEventListenerAddedAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelEventListenerAddedAgentRequest")), null, 2); + }; + Convert.toPrivateChannelEventListenerAddedBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelEventListenerAddedBridgeRequest")); + }; + Convert.privateChannelEventListenerAddedBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelEventListenerAddedBridgeRequest")), null, 2); + }; + Convert.toPrivateChannelEventListenerRemovedAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelEventListenerRemovedAgentRequest")); + }; + Convert.privateChannelEventListenerRemovedAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelEventListenerRemovedAgentRequest")), null, 2); + }; + Convert.toPrivateChannelEventListenerRemovedBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelEventListenerRemovedBridgeRequest")); + }; + Convert.privateChannelEventListenerRemovedBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelEventListenerRemovedBridgeRequest")), null, 2); + }; + Convert.toPrivateChannelOnAddContextListenerAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnAddContextListenerAgentRequest")); + }; + Convert.privateChannelOnAddContextListenerAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnAddContextListenerAgentRequest")), null, 2); + }; + Convert.toPrivateChannelOnAddContextListenerBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnAddContextListenerBridgeRequest")); + }; + Convert.privateChannelOnAddContextListenerBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnAddContextListenerBridgeRequest")), null, 2); + }; + Convert.toPrivateChannelOnDisconnectAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnDisconnectAgentRequest")); + }; + Convert.privateChannelOnDisconnectAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnDisconnectAgentRequest")), null, 2); + }; + Convert.toPrivateChannelOnDisconnectBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnDisconnectBridgeRequest")); + }; + Convert.privateChannelOnDisconnectBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnDisconnectBridgeRequest")), null, 2); + }; + Convert.toPrivateChannelOnUnsubscribeAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnUnsubscribeAgentRequest")); + }; + Convert.privateChannelOnUnsubscribeAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnUnsubscribeAgentRequest")), null, 2); + }; + Convert.toPrivateChannelOnUnsubscribeBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("PrivateChannelOnUnsubscribeBridgeRequest")); + }; + Convert.privateChannelOnUnsubscribeBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("PrivateChannelOnUnsubscribeBridgeRequest")), null, 2); + }; + Convert.toRaiseIntentAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentAgentErrorResponse")); + }; + Convert.raiseIntentAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentAgentErrorResponse")), null, 2); + }; + Convert.toRaiseIntentAgentRequest = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentAgentRequest")); + }; + Convert.raiseIntentAgentRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentAgentRequest")), null, 2); + }; + Convert.toRaiseIntentAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentAgentResponse")); + }; + Convert.raiseIntentAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentAgentResponse")), null, 2); + }; + Convert.toRaiseIntentBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentBridgeErrorResponse")); + }; + Convert.raiseIntentBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentBridgeErrorResponse")), null, 2); + }; + Convert.toRaiseIntentBridgeRequest = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentBridgeRequest")); + }; + Convert.raiseIntentBridgeRequestToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentBridgeRequest")), null, 2); + }; + Convert.toRaiseIntentBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentBridgeResponse")); + }; + Convert.raiseIntentBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentBridgeResponse")), null, 2); + }; + Convert.toRaiseIntentResultAgentErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentResultAgentErrorResponse")); + }; + Convert.raiseIntentResultAgentErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentResultAgentErrorResponse")), null, 2); + }; + Convert.toRaiseIntentResultAgentResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentResultAgentResponse")); + }; + Convert.raiseIntentResultAgentResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentResultAgentResponse")), null, 2); + }; + Convert.toRaiseIntentResultBridgeErrorResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentResultBridgeErrorResponse")); + }; + Convert.raiseIntentResultBridgeErrorResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentResultBridgeErrorResponse")), null, 2); + }; + Convert.toRaiseIntentResultBridgeResponse = function (json) { + return cast$1(JSON.parse(json), r$1("RaiseIntentResultBridgeResponse")); + }; + Convert.raiseIntentResultBridgeResponseToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("RaiseIntentResultBridgeResponse")), null, 2); + }; + Convert.toContext = function (json) { + return cast$1(JSON.parse(json), r$1("Context")); + }; + Convert.contextToJson = function (value) { + return JSON.stringify(uncast$1(value, r$1("Context")), null, 2); + }; + return Convert; +}()); +function invalidValue$1(typ, val, key, parent) { + if (parent === void 0) { parent = ''; } + var prettyTyp = prettyTypeName$1(typ); + var parentText = parent ? " on ".concat(parent) : ''; + var keyText = key ? " for key \"".concat(key, "\"") : ''; + throw Error("Invalid value".concat(keyText).concat(parentText, ". Expected ").concat(prettyTyp, " but got ").concat(JSON.stringify(val))); +} +function prettyTypeName$1(typ) { + if (Array.isArray(typ)) { + if (typ.length === 2 && typ[0] === undefined) { + return "an optional ".concat(prettyTypeName$1(typ[1])); + } + else { + return "one of [".concat(typ.map(function (a) { return prettyTypeName$1(a); }).join(", "), "]"); + } + } + else if (typeof typ === "object" && typ.literal !== undefined) { + return typ.literal; + } + else { + return typeof typ; + } +} +function jsonToJSProps$1(typ) { + if (typ.jsonToJS === undefined) { + var map_1 = {}; + typ.props.forEach(function (p) { return map_1[p.json] = { key: p.js, typ: p.typ }; }); + typ.jsonToJS = map_1; + } + return typ.jsonToJS; +} +function jsToJSONProps$1(typ) { + if (typ.jsToJSON === undefined) { + var map_2 = {}; + typ.props.forEach(function (p) { return map_2[p.js] = { key: p.json, typ: p.typ }; }); + typ.jsToJSON = map_2; + } + return typ.jsToJSON; +} +function transform$1(val, typ, getProps, key, parent) { + if (key === void 0) { key = ''; } + if (parent === void 0) { parent = ''; } + function transformPrimitive(typ, val) { + if (typeof typ === typeof val) + return val; + return invalidValue$1(typ, val, key, parent); + } + function transformUnion(typs, val) { + // val must validate against one typ in typs + var l = typs.length; + for (var i = 0; i < l; i++) { + var typ_1 = typs[i]; + try { + return transform$1(val, typ_1, getProps); + } + catch (_) { } + } + return invalidValue$1(typs, val, key, parent); + } + function transformEnum(cases, val) { + if (cases.indexOf(val) !== -1) + return val; + return invalidValue$1(cases.map(function (a) { return l$1(a); }), val, key, parent); + } + function transformArray(typ, val) { + // val must be an array with no invalid elements + if (!Array.isArray(val)) + return invalidValue$1(l$1("array"), val, key, parent); + return val.map(function (el) { return transform$1(el, typ, getProps); }); + } + function transformDate(val) { + if (val === null) { + return null; + } + var d = new Date(val); + if (isNaN(d.valueOf())) { + return invalidValue$1(l$1("Date"), val, key, parent); + } + return d; + } + function transformObject(props, additional, val) { + if (val === null || typeof val !== "object" || Array.isArray(val)) { + return invalidValue$1(l$1(ref || "object"), val, key, parent); + } + var result = {}; + Object.getOwnPropertyNames(props).forEach(function (key) { + var prop = props[key]; + var v = Object.prototype.hasOwnProperty.call(val, key) ? val[key] : undefined; + result[prop.key] = transform$1(v, prop.typ, getProps, key, ref); + }); + Object.getOwnPropertyNames(val).forEach(function (key) { + if (!Object.prototype.hasOwnProperty.call(props, key)) { + result[key] = transform$1(val[key], additional, getProps, key, ref); + } + }); + return result; + } + if (typ === "any") + return val; + if (typ === null) { + if (val === null) + return val; + return invalidValue$1(typ, val, key, parent); + } + if (typ === false) + return invalidValue$1(typ, val, key, parent); + var ref = undefined; + while (typeof typ === "object" && typ.ref !== undefined) { + ref = typ.ref; + typ = typeMap$1[typ.ref]; + } + if (Array.isArray(typ)) + return transformEnum(typ, val); + if (typeof typ === "object") { + return typ.hasOwnProperty("unionMembers") ? transformUnion(typ.unionMembers, val) + : typ.hasOwnProperty("arrayItems") ? transformArray(typ.arrayItems, val) + : typ.hasOwnProperty("props") ? transformObject(getProps(typ), typ.additional, val) + : invalidValue$1(typ, val, key, parent); + } + // Numbers can be parsed by Date but shouldn't be. + if (typ === Date && typeof val !== "number") + return transformDate(val); + return transformPrimitive(typ, val); +} +function cast$1(val, typ) { + return transform$1(val, typ, jsonToJSProps$1); +} +function uncast$1(val, typ) { + return transform$1(val, typ, jsToJSONProps$1); +} +function l$1(typ) { + return { literal: typ }; +} +function a$1(typ) { + return { arrayItems: typ }; +} +function u$1() { + var typs = []; + for (var _i = 0; _i < arguments.length; _i++) { + typs[_i] = arguments[_i]; + } + return { unionMembers: typs }; +} +function o$1(props, additional) { + return { props: props, additional: additional }; +} +function m$1(additional) { + return { props: [], additional: additional }; +} +function r$1(name) { + return { ref: name }; +} +var typeMap$1 = { + "AgentErrorResponseMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("AgentResponseMetadata") }, + { json: "payload", js: "payload", typ: r$1("ErrorResponseMessagePayload") }, + { json: "type", js: "type", typ: r$1("ResponseMessageType") }, + ], false), + "AgentResponseMetadata": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ErrorResponseMessagePayload": o$1([ + { json: "error", js: "error", typ: r$1("ResponseErrorDetail") }, + ], "any"), + "AgentRequestMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("AgentRequestMetadata") }, + { json: "payload", js: "payload", typ: m$1("any") }, + { json: "type", js: "type", typ: r$1("RequestMessageType") }, + ], false), + "AgentRequestMetadata": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceIdentifier")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "BridgeParticipantIdentifier": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "appId", js: "appId", typ: u$1(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "SourceIdentifier": o$1([ + { json: "appId", js: "appId", typ: u$1(undefined, "") }, + { json: "desktopAgent", js: "desktopAgent", typ: u$1(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "AgentResponseMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("AgentResponseMetadata") }, + { json: "payload", js: "payload", typ: m$1("any") }, + { json: "type", js: "type", typ: r$1("ResponseMessageType") }, + ], false), + "BridgeErrorResponseMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("BridgeErrorResponseMessageMeta") }, + { json: "payload", js: "payload", typ: r$1("ResponseErrorMessagePayload") }, + { json: "type", js: "type", typ: "" }, + ], false), + "BridgeErrorResponseMessageMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "DesktopAgentIdentifier": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + ], "any"), + "ResponseErrorMessagePayload": o$1([ + { json: "error", js: "error", typ: u$1(undefined, r$1("ResponseErrorDetail")) }, + ], "any"), + "BridgeRequestMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("BridgeRequestMetadata") }, + { json: "payload", js: "payload", typ: m$1("any") }, + { json: "type", js: "type", typ: "" }, + ], false), + "BridgeRequestMetadata": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("BridgeParticipantIdentifier") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "BridgeResponseMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("BridgeResponseMessageMeta") }, + { json: "payload", js: "payload", typ: m$1("any") }, + { json: "type", js: "type", typ: "" }, + ], false), + "BridgeResponseMessageMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "BroadcastAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("BroadcastAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("BroadcastAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("BroadcastAgentRequestType") }, + ], false), + "BroadcastAgentRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("SourceObject") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "SourceObject": o$1([ + { json: "appId", js: "appId", typ: "" }, + { json: "desktopAgent", js: "desktopAgent", typ: u$1(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "BroadcastAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "ContextElement": o$1([ + { json: "id", js: "id", typ: u$1(undefined, m$1("any")) }, + { json: "name", js: "name", typ: u$1(undefined, "") }, + { json: "type", js: "type", typ: "" }, + ], "any"), + "BroadcastBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("BroadcastBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("BroadcastBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("BroadcastAgentRequestType") }, + ], false), + "BroadcastBridgeRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "MetaSource": o$1([ + { json: "appId", js: "appId", typ: "" }, + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "BroadcastBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "ConnectionStepMessage": o$1([ + { json: "meta", js: "meta", typ: r$1("ConnectionStepMetadata") }, + { json: "payload", js: "payload", typ: m$1("any") }, + { json: "type", js: "type", typ: r$1("ConnectionStepMessageType") }, + ], false), + "ConnectionStepMetadata": o$1([ + { json: "requestUuid", js: "requestUuid", typ: u$1(undefined, "") }, + { json: "responseUuid", js: "responseUuid", typ: u$1(undefined, "") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ConnectionStep2Hello": o$1([ + { json: "meta", js: "meta", typ: r$1("ConnectionStep2HelloMeta") }, + { json: "payload", js: "payload", typ: r$1("ConnectionStep2HelloPayload") }, + { json: "type", js: "type", typ: r$1("ConnectionStep2HelloType") }, + ], false), + "ConnectionStep2HelloMeta": o$1([ + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ConnectionStep2HelloPayload": o$1([ + { json: "authRequired", js: "authRequired", typ: true }, + { json: "authToken", js: "authToken", typ: u$1(undefined, "") }, + { json: "desktopAgentBridgeVersion", js: "desktopAgentBridgeVersion", typ: "" }, + { json: "supportedFDC3Versions", js: "supportedFDC3Versions", typ: a$1("") }, + ], false), + "ConnectionStep3Handshake": o$1([ + { json: "meta", js: "meta", typ: r$1("ConnectionStep3HandshakeMeta") }, + { json: "payload", js: "payload", typ: r$1("ConnectionStep3HandshakePayload") }, + { json: "type", js: "type", typ: r$1("ConnectionStep3HandshakeType") }, + ], false), + "ConnectionStep3HandshakeMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ConnectionStep3HandshakePayload": o$1([ + { json: "authToken", js: "authToken", typ: u$1(undefined, "") }, + { json: "channelsState", js: "channelsState", typ: m$1(a$1(r$1("ContextElement"))) }, + { json: "implementationMetadata", js: "implementationMetadata", typ: r$1("ConnectingAgentImplementationMetadata") }, + { json: "requestedName", js: "requestedName", typ: "" }, + ], false), + "ConnectingAgentImplementationMetadata": o$1([ + { json: "fdc3Version", js: "fdc3Version", typ: "" }, + { json: "optionalFeatures", js: "optionalFeatures", typ: r$1("OptionalFeatures") }, + { json: "provider", js: "provider", typ: "" }, + { json: "providerVersion", js: "providerVersion", typ: u$1(undefined, "") }, + ], false), + "OptionalFeatures": o$1([ + { json: "DesktopAgentBridging", js: "DesktopAgentBridging", typ: true }, + { json: "OriginatingAppMetadata", js: "OriginatingAppMetadata", typ: true }, + { json: "UserChannelMembershipAPIs", js: "UserChannelMembershipAPIs", typ: true }, + ], false), + "ConnectionStep4AuthenticationFailed": o$1([ + { json: "meta", js: "meta", typ: r$1("ConnectionStep4AuthenticationFailedMeta") }, + { json: "payload", js: "payload", typ: r$1("ConnectionStep4AuthenticationFailedPayload") }, + { json: "type", js: "type", typ: r$1("ConnectionStep4AuthenticationFailedType") }, + ], false), + "ConnectionStep4AuthenticationFailedMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ConnectionStep4AuthenticationFailedPayload": o$1([ + { json: "message", js: "message", typ: u$1(undefined, "") }, + ], false), + "ConnectionStep6ConnectedAgentsUpdate": o$1([ + { json: "meta", js: "meta", typ: r$1("ConnectionStep6ConnectedAgentsUpdateMeta") }, + { json: "payload", js: "payload", typ: r$1("ConnectionStep6ConnectedAgentsUpdatePayload") }, + { json: "type", js: "type", typ: r$1("ConnectionStep6ConnectedAgentsUpdateType") }, + ], false), + "ConnectionStep6ConnectedAgentsUpdateMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "ConnectionStep6ConnectedAgentsUpdatePayload": o$1([ + { json: "addAgent", js: "addAgent", typ: u$1(undefined, "") }, + { json: "allAgents", js: "allAgents", typ: a$1(r$1("DesktopAgentImplementationMetadata")) }, + { json: "channelsState", js: "channelsState", typ: u$1(undefined, m$1(a$1(r$1("ContextElement")))) }, + { json: "removeAgent", js: "removeAgent", typ: u$1(undefined, "") }, + ], false), + "DesktopAgentImplementationMetadata": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "fdc3Version", js: "fdc3Version", typ: "" }, + { json: "optionalFeatures", js: "optionalFeatures", typ: r$1("OptionalFeatures") }, + { json: "provider", js: "provider", typ: "" }, + { json: "providerVersion", js: "providerVersion", typ: u$1(undefined, "") }, + ], false), + "FindInstancesAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentErrorResponseType") }, + ], false), + "FindInstancesAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindInstancesAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindInstancesAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentRequestType") }, + ], false), + "FindInstancesAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceIdentifier")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "DestinationObject": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "appId", js: "appId", typ: u$1(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "FindInstancesAgentRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppIdentifier") }, + ], false), + "AppIdentifier": o$1([ + { json: "appId", js: "appId", typ: "" }, + { json: "desktopAgent", js: "desktopAgent", typ: u$1(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "FindInstancesAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentErrorResponseType") }, + ], false), + "FindInstancesAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindInstancesAgentResponsePayload": o$1([ + { json: "appIdentifiers", js: "appIdentifiers", typ: a$1(r$1("AppMetadata")) }, + ], false), + "AppMetadata": o$1([ + { json: "appId", js: "appId", typ: "" }, + { json: "description", js: "description", typ: u$1(undefined, "") }, + { json: "desktopAgent", js: "desktopAgent", typ: u$1(undefined, "") }, + { json: "icons", js: "icons", typ: u$1(undefined, a$1(r$1("Icon"))) }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + { json: "instanceMetadata", js: "instanceMetadata", typ: u$1(undefined, m$1("any")) }, + { json: "name", js: "name", typ: u$1(undefined, "") }, + { json: "resultType", js: "resultType", typ: u$1(undefined, u$1(null, "")) }, + { json: "screenshots", js: "screenshots", typ: u$1(undefined, a$1(r$1("Image"))) }, + { json: "title", js: "title", typ: u$1(undefined, "") }, + { json: "tooltip", js: "tooltip", typ: u$1(undefined, "") }, + { json: "version", js: "version", typ: u$1(undefined, "") }, + ], false), + "Icon": o$1([ + { json: "size", js: "size", typ: u$1(undefined, "") }, + { json: "src", js: "src", typ: "" }, + { json: "type", js: "type", typ: u$1(undefined, "") }, + ], false), + "Image": o$1([ + { json: "label", js: "label", typ: u$1(undefined, "") }, + { json: "size", js: "size", typ: u$1(undefined, "") }, + { json: "src", js: "src", typ: "" }, + { json: "type", js: "type", typ: u$1(undefined, "") }, + ], false), + "FindInstancesBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentErrorResponseType") }, + ], false), + "FindInstancesBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindInstancesBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindInstancesBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentRequestType") }, + ], false), + "FindInstancesBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSourceObject") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "MetaSourceObject": o$1([ + { json: "appId", js: "appId", typ: u$1(undefined, "") }, + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "FindInstancesBridgeRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppIdentifier") }, + ], false), + "FindInstancesBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindInstancesBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindInstancesBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindInstancesAgentErrorResponseType") }, + ], false), + "FindInstancesBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindInstancesBridgeResponsePayload": o$1([ + { json: "appIdentifiers", js: "appIdentifiers", typ: a$1(r$1("AppMetadata")) }, + ], false), + "FindIntentAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentErrorResponseType") }, + ], false), + "FindIntentAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindIntentAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentRequestType") }, + ], false), + "FindIntentAgentRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceIdentifier")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + ], false), + "FindIntentAgentRequestPayload": o$1([ + { json: "context", js: "context", typ: u$1(undefined, r$1("ContextElement")) }, + { json: "intent", js: "intent", typ: "" }, + { json: "resultType", js: "resultType", typ: u$1(undefined, "") }, + ], false), + "FindIntentAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentErrorResponseType") }, + ], false), + "FindIntentAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentAgentResponsePayload": o$1([ + { json: "appIntent", js: "appIntent", typ: r$1("AppIntent") }, + ], false), + "AppIntent": o$1([ + { json: "apps", js: "apps", typ: a$1(r$1("AppMetadata")) }, + { json: "intent", js: "intent", typ: r$1("IntentMetadata") }, + ], false), + "IntentMetadata": o$1([ + { json: "displayName", js: "displayName", typ: "" }, + { json: "name", js: "name", typ: "" }, + ], false), + "FindIntentBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentErrorResponseType") }, + ], false), + "FindIntentBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindIntentBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentRequestType") }, + ], false), + "FindIntentBridgeRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("BridgeParticipantIdentifier") }, + { json: "timestamp", js: "timestamp", typ: Date }, + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + ], false), + "FindIntentBridgeRequestPayload": o$1([ + { json: "context", js: "context", typ: u$1(undefined, r$1("ContextElement")) }, + { json: "intent", js: "intent", typ: "" }, + { json: "resultType", js: "resultType", typ: u$1(undefined, "") }, + ], false), + "FindIntentBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentAgentErrorResponseType") }, + ], false), + "FindIntentBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentBridgeResponsePayload": o$1([ + { json: "appIntent", js: "appIntent", typ: r$1("AppIntent") }, + ], false), + "FindIntentsByContextAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentErrorResponseType") }, + ], false), + "FindIntentsByContextAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentsByContextAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindIntentsByContextAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentRequestType") }, + ], false), + "FindIntentsByContextAgentRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + ], false), + "FindIntentsByContextAgentRequestPayload": o$1([ + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "FindIntentsByContextAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentErrorResponseType") }, + ], false), + "FindIntentsByContextAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentsByContextAgentResponsePayload": o$1([ + { json: "appIntents", js: "appIntents", typ: a$1(r$1("AppIntent")) }, + ], false), + "FindIntentsByContextBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentErrorResponseType") }, + ], false), + "FindIntentsByContextBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentsByContextBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "FindIntentsByContextBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentRequestType") }, + ], false), + "FindIntentsByContextBridgeRequestMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + { json: "destination", js: "destination", typ: u$1(undefined, r$1("BridgeParticipantIdentifier")) }, + ], false), + "FindIntentsByContextBridgeRequestPayload": o$1([ + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "FindIntentsByContextBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("FindIntentsByContextBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("FindIntentsByContextBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("FindIntentsByContextAgentErrorResponseType") }, + ], false), + "FindIntentsByContextBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "FindIntentsByContextBridgeResponsePayload": o$1([ + { json: "appIntents", js: "appIntents", typ: a$1(r$1("AppIntent")) }, + ], false), + "GetAppMetadataAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentErrorResponseType") }, + ], false), + "GetAppMetadataAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "GetAppMetadataAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentRequestType") }, + ], false), + "GetAppMetadataAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceIdentifier")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataAgentRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppDestinationIdentifier") }, + ], false), + "AppDestinationIdentifier": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "appId", js: "appId", typ: "" }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "GetAppMetadataAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentErrorResponseType") }, + ], false), + "GetAppMetadataAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataAgentResponsePayload": o$1([ + { json: "appMetadata", js: "appMetadata", typ: r$1("AppMetadata") }, + ], false), + "GetAppMetadataBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentErrorResponseType") }, + ], false), + "GetAppMetadataBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "GetAppMetadataBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentRequestType") }, + ], false), + "GetAppMetadataBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSourceObject") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataBridgeRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppDestinationIdentifier") }, + ], false), + "GetAppMetadataBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("GetAppMetadataBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("GetAppMetadataBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("GetAppMetadataAgentErrorResponseType") }, + ], false), + "GetAppMetadataBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "GetAppMetadataBridgeResponsePayload": o$1([ + { json: "appMetadata", js: "appMetadata", typ: r$1("AppMetadata") }, + ], false), + "OpenAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentErrorResponseType") }, + ], false), + "OpenAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("OpenErrorMessage") }, + ], false), + "OpenAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentRequestType") }, + ], false), + "OpenAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("SourceObject") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenAgentRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppToOpen") }, + { json: "context", js: "context", typ: u$1(undefined, r$1("ContextElement")) }, + ], false), + "AppToOpen": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "appId", js: "appId", typ: "" }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "OpenAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentErrorResponseType") }, + ], false), + "OpenAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenAgentResponsePayload": o$1([ + { json: "appIdentifier", js: "appIdentifier", typ: r$1("AppIdentifier") }, + ], false), + "OpenBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentErrorResponseType") }, + ], false), + "OpenBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("OpenErrorMessage") }, + ], false), + "OpenBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentRequestType") }, + ], false), + "OpenBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("DestinationObject")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenBridgeRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppToOpen") }, + { json: "context", js: "context", typ: u$1(undefined, r$1("ContextElement")) }, + ], false), + "OpenBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("OpenBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("OpenBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("OpenAgentErrorResponseType") }, + ], false), + "OpenBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "OpenBridgeResponsePayload": o$1([ + { json: "appIdentifier", js: "appIdentifier", typ: r$1("AppIdentifier") }, + ], false), + "PrivateChannelBroadcastAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelBroadcastAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelBroadcastAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelBroadcastAgentRequestType") }, + ], false), + "PrivateChannelBroadcastAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "MetaDestination": o$1([ + { json: "desktopAgent", js: "desktopAgent", typ: "" }, + { json: "appId", js: "appId", typ: "" }, + { json: "instanceId", js: "instanceId", typ: u$1(undefined, "") }, + ], "any"), + "PrivateChannelBroadcastAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "PrivateChannelBroadcastBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelBroadcastBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelBroadcastBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelBroadcastAgentRequestType") }, + ], false), + "PrivateChannelBroadcastBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelBroadcastBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + ], false), + "PrivateChannelEventListenerAddedAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelEventListenerAddedAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelEventListenerAddedAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelEventListenerAddedAgentRequestType") }, + ], false), + "PrivateChannelEventListenerAddedAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelEventListenerAddedAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "listenerType", js: "listenerType", typ: r$1("PrivateChannelEventListenerTypes") }, + ], false), + "PrivateChannelEventListenerAddedBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelEventListenerAddedBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelEventListenerAddedBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelEventListenerAddedAgentRequestType") }, + ], false), + "PrivateChannelEventListenerAddedBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelEventListenerAddedBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "listenerType", js: "listenerType", typ: r$1("PrivateChannelEventListenerTypes") }, + ], false), + "PrivateChannelEventListenerRemovedAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelEventListenerRemovedAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelEventListenerRemovedAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelEventListenerRemovedAgentRequestType") }, + ], false), + "PrivateChannelEventListenerRemovedAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelEventListenerRemovedAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "listenerType", js: "listenerType", typ: r$1("PrivateChannelEventListenerTypes") }, + ], false), + "PrivateChannelEventListenerRemovedBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelEventListenerRemovedBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelEventListenerRemovedBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelEventListenerRemovedAgentRequestType") }, + ], false), + "PrivateChannelEventListenerRemovedBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelEventListenerRemovedBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "listenerType", js: "listenerType", typ: r$1("PrivateChannelEventListenerTypes") }, + ], false), + "PrivateChannelOnAddContextListenerAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelOnAddContextListenerAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnAddContextListenerAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnAddContextListenerAgentRequestType") }, + ], false), + "PrivateChannelOnAddContextListenerAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnAddContextListenerAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "contextType", js: "contextType", typ: u$1(null, "") }, + ], false), + "PrivateChannelOnAddContextListenerBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelOnAddContextListenerBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnAddContextListenerBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnAddContextListenerAgentRequestType") }, + ], false), + "PrivateChannelOnAddContextListenerBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnAddContextListenerBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "contextType", js: "contextType", typ: u$1(null, "") }, + ], false), + "PrivateChannelOnDisconnectAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelOnDisconnectAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnDisconnectAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnDisconnectAgentRequestType") }, + ], false), + "PrivateChannelOnDisconnectAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnDisconnectAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + ], false), + "PrivateChannelOnDisconnectBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelOnDisconnectBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnDisconnectBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnDisconnectAgentRequestType") }, + ], false), + "PrivateChannelOnDisconnectBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnDisconnectBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + ], false), + "PrivateChannelOnUnsubscribeAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("PrivateChannelOnUnsubscribeAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnUnsubscribeAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnUnsubscribeAgentRequestType") }, + ], false), + "PrivateChannelOnUnsubscribeAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: u$1(undefined, r$1("SourceObject")) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnUnsubscribeAgentRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "contextType", js: "contextType", typ: u$1(null, "") }, + ], false), + "PrivateChannelOnUnsubscribeBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("ERequestMetadata") }, + { json: "payload", js: "payload", typ: r$1("PrivateChannelOnUnsubscribeBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("PrivateChannelOnUnsubscribeAgentRequestType") }, + ], false), + "ERequestMetadata": o$1([ + { json: "destination", js: "destination", typ: u$1(undefined, r$1("MetaDestination")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "PrivateChannelOnUnsubscribeBridgeRequestPayload": o$1([ + { json: "channelId", js: "channelId", typ: "" }, + { json: "contextType", js: "contextType", typ: u$1(null, "") }, + ], false), + "RaiseIntentAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentErrorResponseType") }, + ], false), + "RaiseIntentAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "RaiseIntentAgentRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentAgentRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentAgentRequestPayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentRequestType") }, + ], false), + "RaiseIntentAgentRequestMeta": o$1([ + { json: "destination", js: "destination", typ: r$1("MetaDestination") }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("SourceObject") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentAgentRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppDestinationIdentifier") }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + { json: "intent", js: "intent", typ: "" }, + ], false), + "RaiseIntentAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentErrorResponseType") }, + ], false), + "RaiseIntentAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentAgentResponsePayload": o$1([ + { json: "intentResolution", js: "intentResolution", typ: r$1("IntentResolution") }, + ], false), + "IntentResolution": o$1([ + { json: "intent", js: "intent", typ: "" }, + { json: "source", js: "source", typ: r$1("AppIdentifier") }, + { json: "version", js: "version", typ: u$1(undefined, "") }, + ], false), + "RaiseIntentBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentErrorResponseType") }, + ], false), + "RaiseIntentBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("ErrorMessage") }, + ], false), + "RaiseIntentBridgeRequest": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentBridgeRequestMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentBridgeRequestPayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentRequestType") }, + ], false), + "RaiseIntentBridgeRequestMeta": o$1([ + { json: "destination", js: "destination", typ: r$1("MetaDestination") }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "source", js: "source", typ: r$1("MetaSource") }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentBridgeRequestPayload": o$1([ + { json: "app", js: "app", typ: r$1("AppDestinationIdentifier") }, + { json: "context", js: "context", typ: r$1("ContextElement") }, + { json: "intent", js: "intent", typ: "" }, + ], false), + "RaiseIntentBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentAgentErrorResponseType") }, + ], false), + "RaiseIntentBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentBridgeResponsePayload": o$1([ + { json: "intentResolution", js: "intentResolution", typ: r$1("IntentResolution") }, + ], false), + "RaiseIntentResultAgentErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentResultAgentErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentResultAgentErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentResultAgentErrorResponseType") }, + ], false), + "RaiseIntentResultAgentErrorResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentResultAgentErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("RaiseIntentResultErrorMessage") }, + ], false), + "RaiseIntentResultAgentResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentResultAgentResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentResultAgentResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentResultAgentErrorResponseType") }, + ], false), + "RaiseIntentResultAgentResponseMeta": o$1([ + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentResultAgentResponsePayload": o$1([ + { json: "intentResult", js: "intentResult", typ: r$1("IntentResult") }, + ], false), + "IntentResult": o$1([ + { json: "context", js: "context", typ: u$1(undefined, r$1("ContextElement")) }, + { json: "channel", js: "channel", typ: u$1(undefined, r$1("Channel")) }, + ], false), + "Channel": o$1([ + { json: "displayMetadata", js: "displayMetadata", typ: u$1(undefined, r$1("DisplayMetadata")) }, + { json: "id", js: "id", typ: "" }, + { json: "type", js: "type", typ: r$1("Type") }, + ], false), + "DisplayMetadata": o$1([ + { json: "color", js: "color", typ: u$1(undefined, "") }, + { json: "glyph", js: "glyph", typ: u$1(undefined, "") }, + { json: "name", js: "name", typ: u$1(undefined, "") }, + ], false), + "RaiseIntentResultBridgeErrorResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentResultBridgeErrorResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentResultBridgeErrorResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentResultAgentErrorResponseType") }, + ], false), + "RaiseIntentResultBridgeErrorResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: a$1(r$1("ResponseErrorDetail")) }, + { json: "errorSources", js: "errorSources", typ: a$1(r$1("DesktopAgentIdentifier")) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentResultBridgeErrorResponsePayload": o$1([ + { json: "error", js: "error", typ: r$1("RaiseIntentResultErrorMessage") }, + ], false), + "RaiseIntentResultBridgeResponse": o$1([ + { json: "meta", js: "meta", typ: r$1("RaiseIntentResultBridgeResponseMeta") }, + { json: "payload", js: "payload", typ: r$1("RaiseIntentResultBridgeResponsePayload") }, + { json: "type", js: "type", typ: r$1("RaiseIntentResultAgentErrorResponseType") }, + ], false), + "RaiseIntentResultBridgeResponseMeta": o$1([ + { json: "errorDetails", js: "errorDetails", typ: u$1(undefined, a$1(r$1("ResponseErrorDetail"))) }, + { json: "errorSources", js: "errorSources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "requestUuid", js: "requestUuid", typ: "" }, + { json: "responseUuid", js: "responseUuid", typ: "" }, + { json: "sources", js: "sources", typ: u$1(undefined, a$1(r$1("DesktopAgentIdentifier"))) }, + { json: "timestamp", js: "timestamp", typ: Date }, + ], false), + "RaiseIntentResultBridgeResponsePayload": o$1([ + { json: "intentResult", js: "intentResult", typ: r$1("IntentResult") }, + ], false), + "Context": o$1([ + { json: "id", js: "id", typ: u$1(undefined, m$1("any")) }, + { json: "name", js: "name", typ: u$1(undefined, "") }, + { json: "type", js: "type", typ: "" }, + ], "any"), + "ResponseErrorDetail": [ + "AccessDenied", + "AgentDisconnected", + "AppNotFound", + "AppTimeout", + "CreationFailed", + "DesktopAgentNotFound", + "ErrorOnLaunch", + "IntentDeliveryFailed", + "IntentHandlerRejected", + "MalformedContext", + "MalformedMessage", + "NoAppsFound", + "NoChannelFound", + "NoResultReturned", + "NotConnectedToBridge", + "ResolverTimeout", + "ResolverUnavailable", + "ResponseToBridgeTimedOut", + "TargetAppUnavailable", + "TargetInstanceUnavailable", + "UserCancelledResolution", + ], + "ResponseMessageType": [ + "findInstancesResponse", + "findIntentResponse", + "findIntentsByContextResponse", + "getAppMetadataResponse", + "openResponse", + "raiseIntentResponse", + "raiseIntentResultResponse", + ], + "RequestMessageType": [ + "broadcastRequest", + "findInstancesRequest", + "findIntentRequest", + "findIntentsByContextRequest", + "getAppMetadataRequest", + "openRequest", + "PrivateChannel.broadcast", + "PrivateChannel.eventListenerAdded", + "PrivateChannel.eventListenerRemoved", + "PrivateChannel.onAddContextListener", + "PrivateChannel.onDisconnect", + "PrivateChannel.onUnsubscribe", + "raiseIntentRequest", + ], + "BroadcastAgentRequestType": [ + "broadcastRequest", + ], + "ConnectionStepMessageType": [ + "authenticationFailed", + "connectedAgentsUpdate", + "handshake", + "hello", + ], + "ConnectionStep2HelloType": [ + "hello", + ], + "ConnectionStep3HandshakeType": [ + "handshake", + ], + "ConnectionStep4AuthenticationFailedType": [ + "authenticationFailed", + ], + "ConnectionStep6ConnectedAgentsUpdateType": [ + "connectedAgentsUpdate", + ], + "ErrorMessage": [ + "AgentDisconnected", + "DesktopAgentNotFound", + "IntentDeliveryFailed", + "MalformedContext", + "MalformedMessage", + "NoAppsFound", + "NotConnectedToBridge", + "ResolverTimeout", + "ResolverUnavailable", + "ResponseToBridgeTimedOut", + "TargetAppUnavailable", + "TargetInstanceUnavailable", + "UserCancelledResolution", + ], + "FindInstancesAgentErrorResponseType": [ + "findInstancesResponse", + ], + "FindInstancesAgentRequestType": [ + "findInstancesRequest", + ], + "FindIntentAgentErrorResponseType": [ + "findIntentResponse", + ], + "FindIntentAgentRequestType": [ + "findIntentRequest", + ], + "FindIntentsByContextAgentErrorResponseType": [ + "findIntentsByContextResponse", + ], + "FindIntentsByContextAgentRequestType": [ + "findIntentsByContextRequest", + ], + "GetAppMetadataAgentErrorResponseType": [ + "getAppMetadataResponse", + ], + "GetAppMetadataAgentRequestType": [ + "getAppMetadataRequest", + ], + "OpenErrorMessage": [ + "AgentDisconnected", + "AppNotFound", + "AppTimeout", + "DesktopAgentNotFound", + "ErrorOnLaunch", + "MalformedContext", + "MalformedMessage", + "NotConnectedToBridge", + "ResolverUnavailable", + "ResponseToBridgeTimedOut", + ], + "OpenAgentErrorResponseType": [ + "openResponse", + ], + "OpenAgentRequestType": [ + "openRequest", + ], + "PrivateChannelBroadcastAgentRequestType": [ + "PrivateChannel.broadcast", + ], + "PrivateChannelEventListenerTypes": [ + "onAddContextListener", + "onDisconnect", + "onUnsubscribe", + ], + "PrivateChannelEventListenerAddedAgentRequestType": [ + "PrivateChannel.eventListenerAdded", + ], + "PrivateChannelEventListenerRemovedAgentRequestType": [ + "PrivateChannel.eventListenerRemoved", + ], + "PrivateChannelOnAddContextListenerAgentRequestType": [ + "PrivateChannel.onAddContextListener", + ], + "PrivateChannelOnDisconnectAgentRequestType": [ + "PrivateChannel.onDisconnect", + ], + "PrivateChannelOnUnsubscribeAgentRequestType": [ + "PrivateChannel.onUnsubscribe", + ], + "RaiseIntentAgentErrorResponseType": [ + "raiseIntentResponse", + ], + "RaiseIntentAgentRequestType": [ + "raiseIntentRequest", + ], + "RaiseIntentResultErrorMessage": [ + "AgentDisconnected", + "IntentHandlerRejected", + "MalformedMessage", + "NoResultReturned", + "NotConnectedToBridge", + "ResponseToBridgeTimedOut", + ], + "RaiseIntentResultAgentErrorResponseType": [ + "raiseIntentResultResponse", + ], + "Type": [ + "app", + "private", + "user", + ] +}; + +var BridgingTypes = { + __proto__: null, + Convert: Convert$1 +}; + +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright FINOS FDC3 contributors - see NOTICE file + */ +/** Constants representing the errors that can be encountered when calling the `open` method on the DesktopAgent object (`fdc3`). */ +var OpenError; +(function (OpenError) { + /** Returned if the specified application is not found.*/ + OpenError["AppNotFound"] = "AppNotFound"; + /** Returned if the specified application fails to launch correctly.*/ + OpenError["ErrorOnLaunch"] = "ErrorOnLaunch"; + /** Returned if the specified application launches but fails to add a context listener in order to receive the context passed to the `fdc3.open` call.*/ + OpenError["AppTimeout"] = "AppTimeout"; + /** Returned if the FDC3 desktop agent implementation is not currently able to handle the request.*/ + OpenError["ResolverUnavailable"] = "ResolverUnavailable"; + /** Returned if a call to the `open` function is made with an invalid context argument. Contexts should be Objects with at least a `type` field that has a `string` value.*/ + OpenError["MalformedContext"] = "MalformedContext"; + /** @experimental Returned if the specified Desktop Agent is not found, via a connected Desktop Agent Bridge.*/ + OpenError["DesktopAgentNotFound"] = "DesktopAgentNotFound"; +})(OpenError || (OpenError = {})); +/** Constants representing the errors that can be encountered when calling the `findIntent`, `findIntentsByContext`, `raiseIntent` or `raiseIntentForContext` methods on the DesktopAgent (`fdc3`). */ +var ResolveError; +(function (ResolveError) { + /** SHOULD be returned if no apps are available that can resolve the intent and context combination.*/ + ResolveError["NoAppsFound"] = "NoAppsFound"; + /** Returned if the FDC3 desktop agent implementation is not currently able to handle the request.*/ + ResolveError["ResolverUnavailable"] = "ResolverUnavailable"; + /** Returned if the user cancelled the resolution request, for example by closing or cancelling a resolver UI.*/ + ResolveError["UserCancelled"] = "UserCancelledResolution"; + /** SHOULD be returned if a timeout cancels an intent resolution that required user interaction. Please use `ResolverUnavailable` instead for situations where a resolver UI or similar fails.*/ + ResolveError["ResolverTimeout"] = "ResolverTimeout"; + /** Returned if a specified target application is not available or a new instance of it cannot be opened. */ + ResolveError["TargetAppUnavailable"] = "TargetAppUnavailable"; + /** Returned if a specified target application instance is not available, for example because it has been closed. */ + ResolveError["TargetInstanceUnavailable"] = "TargetInstanceUnavailable"; + /** Returned if the intent and context could not be delivered to the selected application or instance, for example because it has not added an intent handler within a timeout.*/ + ResolveError["IntentDeliveryFailed"] = "IntentDeliveryFailed"; + /** Returned if a call to one of the `raiseIntent` functions is made with an invalid context argument. Contexts should be Objects with at least a `type` field that has a `string` value.*/ + ResolveError["MalformedContext"] = "MalformedContext"; + /** @experimental Returned if the specified Desktop Agent is not found, via a connected Desktop Agent Bridge.*/ + ResolveError["DesktopAgentNotFound"] = "DesktopAgentNotFound"; +})(ResolveError || (ResolveError = {})); +var ResultError; +(function (ResultError) { + /** Returned if the intent handler exited without returning a valid result (a promise resolving to a Context, Channel object or void). */ + ResultError["NoResultReturned"] = "NoResultReturned"; + /** Returned if the Intent handler function processing the raised intent throws an error or rejects the Promise it returned. */ + ResultError["IntentHandlerRejected"] = "IntentHandlerRejected"; +})(ResultError || (ResultError = {})); +var ChannelError; +(function (ChannelError) { + /** Returned if the specified channel is not found when attempting to join a channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`).*/ + ChannelError["NoChannelFound"] = "NoChannelFound"; + /** SHOULD be returned when a request to join a user channel or to a retrieve a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods of the DesktopAgent (`fdc3`) object is denied. */ + ChannelError["AccessDenied"] = "AccessDenied"; + /** SHOULD be returned when a channel cannot be created or retrieved via the `getOrCreateChannel` method of the DesktopAgent (`fdc3`).*/ + ChannelError["CreationFailed"] = "CreationFailed"; + /** Returned if a call to the `broadcast` functions is made with an invalid context argument. Contexts should be Objects with at least a `type` field that has a `string` value.*/ + ChannelError["MalformedContext"] = "MalformedContext"; +})(ChannelError || (ChannelError = {})); +var BridgingError; +(function (BridgingError) { + /** @experimental Returned if a Desktop Agent did not return a response, via Desktop Agent Bridging, within the alloted timeout. */ + BridgingError["ResponseTimedOut"] = "ResponseToBridgeTimedOut"; + /** @experimental Returned if a Desktop Agent that has been targeted by a particular request has been disconnected from the Bridge before a response has been received from it. */ + BridgingError["AgentDisconnected"] = "AgentDisconnected"; + /** @experimental Returned for FDC3 API calls that are specified with arguments indicating that a remote Desktop agent should be targeted (e.g. raiseIntent with an app on a remote DesktopAgent targeted), when the local Desktop Agent is not connected to a bridge. */ + BridgingError["NotConnectedToBridge"] = "NotConnectedToBridge"; + /** @experimental Returned if a message to a Bridge deviates from the schema for that message sufficiently that it could not be processed. */ + BridgingError["MalformedMessage"] = "MalformedMessage"; +})(BridgingError || (BridgingError = {})); + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global Reflect, Promise, SuppressedError, Symbol */ + + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +} + +typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}; + +/** + * Ensures at compile time that the given string tuple is exhaustive on a given union type, i.e. contains ALL possible values of the given UNION_TYPE. + */ +var exhaustiveStringTuple = function () { return function () { + var tuple = []; + for (var _i = 0; _i < arguments.length; _i++) { + tuple[_i] = arguments[_i]; + } + return tuple; +}; }; + +var STANDARD_CONTEXT_TYPES = exhaustiveStringTuple()('fdc3.action', 'fdc3.chart', 'fdc3.chat.initSettings', 'fdc3.chat.message', 'fdc3.chat.room', 'fdc3.chat.searchCriteria', 'fdc3.contact', 'fdc3.contactList', 'fdc3.country', 'fdc3.currency', 'fdc3.email', 'fdc3.instrument', 'fdc3.instrumentList', 'fdc3.interaction', 'fdc3.message', 'fdc3.organization', 'fdc3.portfolio', 'fdc3.position', 'fdc3.nothing', 'fdc3.timeRange', 'fdc3.transactionResult', 'fdc3.valuation'); +// used internally to check if a given intent/context is a standard one +var StandardContextsSet = new Set(STANDARD_CONTEXT_TYPES); + +var STANDARD_INTENTS = exhaustiveStringTuple()('CreateInteraction', 'SendChatMessage', 'StartCall', 'StartChat', 'StartEmail', 'ViewAnalysis', 'ViewChat', 'ViewChart', 'ViewContact', 'ViewHoldings', 'ViewInstrument', 'ViewInteractions', 'ViewMessages', 'ViewNews', 'ViewOrders', 'ViewProfile', 'ViewQuote', 'ViewResearch'); +// used internally to check if a given intent/context is a standard one +var StandardIntentsSet = new Set(STANDARD_INTENTS); + +var DEFAULT_TIMEOUT = 5000; +var UnavailableError = new Error('FDC3 DesktopAgent not available at `window.fdc3`.'); +var TimeoutError = new Error('Timed out waiting for `fdc3Ready` event.'); +var UnexpectedError = new Error('`fdc3Ready` event fired, but `window.fdc3` not set to DesktopAgent.'); +function rejectIfNoGlobal(f) { + return window.fdc3 ? f() : Promise.reject(UnavailableError); +} +/** + * Utility function that returns a promise that will resolve immeadiately + * if the desktop agent API is found at `window.fdc3`. If the API is found, + * the promise will resolve when the `fdc3Ready` event is received or if it + * is found at the end of the specified timeout. If the API is not found, it + * will reject with an error. + * + * ```javascript + * await fdc3Ready(); + * const intentListener = await addIntentListener("ViewChart", intentHandlerFn); + * ``` + * + * @param waitForMs The number of milliseconds to wait for the FDC3 API to be + * ready. Defaults to 5 seconds. + */ +var fdc3Ready = function (waitForMs) { + if (waitForMs === void 0) { waitForMs = DEFAULT_TIMEOUT; } + return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, new Promise(function (resolve, reject) { + // if the global is already available resolve immediately + if (window.fdc3) { + resolve(); + } + else { + // if its not available setup a timeout to return a rejected promise + var timeout_1 = setTimeout(function () { return (window.fdc3 ? resolve() : reject(TimeoutError)); }, waitForMs); + // listen for the fdc3Ready event + window.addEventListener('fdc3Ready', function () { + clearTimeout(timeout_1); + window.fdc3 ? resolve() : reject(UnexpectedError); + }, { once: true }); + } + })]; + }); + }); +}; +function isString(app) { + return !!app && typeof app === 'string'; +} +function open(app, context) { + if (isString(app)) { + return rejectIfNoGlobal(function () { return window.fdc3.open(app, context); }); + } + else { + return rejectIfNoGlobal(function () { return window.fdc3.open(app, context); }); + } +} +function findIntent(intent, context, resultType) { + return rejectIfNoGlobal(function () { return window.fdc3.findIntent(intent, context, resultType); }); +} +function findIntentsByContext(context, resultType) { + return rejectIfNoGlobal(function () { return window.fdc3.findIntentsByContext(context, resultType); }); +} +function broadcast(context) { + return rejectIfNoGlobal(function () { return window.fdc3.broadcast(context); }); +} +function raiseIntent(intent, context, app) { + if (isString(app)) { + return rejectIfNoGlobal(function () { return window.fdc3.raiseIntent(intent, context, app); }); + } + else { + return rejectIfNoGlobal(function () { return window.fdc3.raiseIntent(intent, context, app); }); + } +} +function raiseIntentForContext(context, app) { + if (isString(app)) { + return rejectIfNoGlobal(function () { return window.fdc3.raiseIntentForContext(context, app); }); + } + else { + return rejectIfNoGlobal(function () { return window.fdc3.raiseIntentForContext(context, app); }); + } +} +function addIntentListener(intent, handler) { + return rejectIfNoGlobal(function () { return window.fdc3.addIntentListener(intent, handler); }); +} +function addContextListener(contextTypeOrHandler, handler) { + //Handle (deprecated) function signature that allowed contextType argument to be omitted + if (typeof contextTypeOrHandler !== 'function') { + return rejectIfNoGlobal(function () { return window.fdc3.addContextListener(contextTypeOrHandler, handler); }); + } + else { + return rejectIfNoGlobal(function () { return window.fdc3.addContextListener(null, contextTypeOrHandler); }); + } +} +function getUserChannels() { + return rejectIfNoGlobal(function () { + //fallback to getSystemChannels for FDC3 <2.0 implementations + if (window.fdc3.getUserChannels) { + return window.fdc3.getUserChannels(); + } + else { + return window.fdc3.getSystemChannels(); + } + }); +} +function getSystemChannels() { + //fallforward to getUserChannels for FDC3 2.0+ implementations + return getUserChannels(); +} +function joinUserChannel(channelId) { + return rejectIfNoGlobal(function () { + //fallback to joinChannel for FDC3 <2.0 implementations + if (window.fdc3.joinUserChannel) { + return window.fdc3.joinUserChannel(channelId); + } + else { + return window.fdc3.joinChannel(channelId); + } + }); +} +function joinChannel(channelId) { + //fallforward to joinUserChannel for FDC3 2.0+ implementations + return joinUserChannel(channelId); +} +function getOrCreateChannel(channelId) { + return rejectIfNoGlobal(function () { return window.fdc3.getOrCreateChannel(channelId); }); +} +function getCurrentChannel() { + return rejectIfNoGlobal(function () { return window.fdc3.getCurrentChannel(); }); +} +function leaveCurrentChannel() { + return rejectIfNoGlobal(function () { return window.fdc3.leaveCurrentChannel(); }); +} +function createPrivateChannel() { + return rejectIfNoGlobal(function () { return window.fdc3.createPrivateChannel(); }); +} +function getInfo() { + return rejectIfNoGlobal(function () { return window.fdc3.getInfo(); }); +} +function getAppMetadata(app) { + return rejectIfNoGlobal(function () { return window.fdc3.getAppMetadata(app); }); +} +function findInstances(app) { + return rejectIfNoGlobal(function () { return window.fdc3.findInstances(app); }); +} +/** + * Check if the given context is a standard context type. + * @param contextType + */ +function isStandardContextType(contextType) { + return StandardContextsSet.has(contextType); +} +/** + * Check if the given intent is a standard intent. + * @param intent + */ +function isStandardIntent(intent) { + return StandardIntentsSet.has(intent); +} +/** + * Compare numeric semver version number strings (in the form `1.2.3`). + * + * Returns `-1` if the first argument is a lower version number than the second, + * `1` if the first argument is greater than the second, 0 if the arguments are + * equal and `null` if an error occurred during the comparison. + * + * @param a + * @param b + */ +var compareVersionNumbers = function (a, b) { + try { + var aVerArr = a.split('.').map(Number); + var bVerArr = b.split('.').map(Number); + for (var index = 0; index < Math.max(aVerArr.length, bVerArr.length); index++) { + /* If one version number has more digits and the other does not, and they are otherwise equal, + assume the longer is greater. E.g. 1.1.1 > 1.1 */ + if (index === aVerArr.length || aVerArr[index] < bVerArr[index]) { + return -1; + } + else if (index === bVerArr.length || aVerArr[index] > bVerArr[index]) { + return 1; + } + } + return 0; + } + catch (e) { + console.error('Failed to compare version strings', e); + return null; + } +}; +/** + * Check if the FDC3 version in an ImplementationMetadata object is greater than + * or equal to the supplied numeric semver version number string (in the form `1.2.3`). + * + * Returns a boolean or null if an error occurred while comparing the version numbers. + * + * @param metadata + * @param version + */ +var versionIsAtLeast = function (metadata, version) { + var comparison = compareVersionNumbers(metadata.fdc3Version, version); + return comparison === null ? null : comparison >= 0 ? true : false; +}; + +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright FINOS FDC3 contributors - see NOTICE file + */ +/** + * @deprecated Use {@link StandardContextType} instead + */ +var ContextTypes; +(function (ContextTypes) { + ContextTypes["Chart"] = "fdc3.chart"; + ContextTypes["ChatInitSettings"] = "fdc3.chat.initSettings"; + ContextTypes["ChatRoom"] = "fdc3.chat.room"; + ContextTypes["Contact"] = "fdc3.contact"; + ContextTypes["ContactList"] = "fdc3.contactList"; + ContextTypes["Country"] = "fdc3.country"; + ContextTypes["Currency"] = "fdc3.currency"; + ContextTypes["Email"] = "fdc3.email"; + ContextTypes["Instrument"] = "fdc3.instrument"; + ContextTypes["InstrumentList"] = "fdc3.instrumentList"; + ContextTypes["Interaction"] = "fdc3.interaction"; + ContextTypes["Nothing"] = "fdc3.nothing"; + ContextTypes["Organization"] = "fdc3.organization"; + ContextTypes["Portfolio"] = "fdc3.portfolio"; + ContextTypes["Position"] = "fdc3.position"; + ContextTypes["ChatSearchCriteria"] = "fdc3.chat.searchCriteria"; + ContextTypes["TimeRange"] = "fdc3.timeRange"; + ContextTypes["TransactionResult"] = "fdc3.transactionResult"; + ContextTypes["Valuation"] = "fdc3.valuation"; +})(ContextTypes || (ContextTypes = {})); + +// To parse this data: +// +// import { Convert, Action, Chart, ChatInitSettings, ChatMessage, ChatRoom, ChatSearchCriteria, Contact, ContactList, Context, Country, Currency, Email, Instrument, InstrumentList, Interaction, Message, Nothing, Order, OrderList, Organization, Portfolio, Position, Product, TimeRange, Trade, TradeList, TransactionResult, Valuation } from "./file"; +// +// const action = Convert.toAction(json); +// const chart = Convert.toChart(json); +// const chatInitSettings = Convert.toChatInitSettings(json); +// const chatMessage = Convert.toChatMessage(json); +// const chatRoom = Convert.toChatRoom(json); +// const chatSearchCriteria = Convert.toChatSearchCriteria(json); +// const contact = Convert.toContact(json); +// const contactList = Convert.toContactList(json); +// const context = Convert.toContext(json); +// const country = Convert.toCountry(json); +// const currency = Convert.toCurrency(json); +// const email = Convert.toEmail(json); +// const instrument = Convert.toInstrument(json); +// const instrumentList = Convert.toInstrumentList(json); +// const interaction = Convert.toInteraction(json); +// const message = Convert.toMessage(json); +// const nothing = Convert.toNothing(json); +// const order = Convert.toOrder(json); +// const orderList = Convert.toOrderList(json); +// const organization = Convert.toOrganization(json); +// const portfolio = Convert.toPortfolio(json); +// const position = Convert.toPosition(json); +// const product = Convert.toProduct(json); +// const timeRange = Convert.toTimeRange(json); +// const trade = Convert.toTrade(json); +// const tradeList = Convert.toTradeList(json); +// const transactionResult = Convert.toTransactionResult(json); +// const valuation = Convert.toValuation(json); +// +// These functions will throw an error if the JSON doesn't +// match the expected interface, even if the JSON is valid. +/** + * Free text to be used for a keyword search + * + * `interactionType` SHOULD be one of `'Instant Message'`, `'Email'`, `'Call'`, or + * `'Meeting'` although other string values are permitted. + */ +// Converts JSON strings to/from your types +// and asserts the results of JSON.parse at runtime +var Convert = /** @class */ (function () { + function Convert() { + } + Convert.toAction = function (json) { + return cast(JSON.parse(json), r("Action")); + }; + Convert.actionToJson = function (value) { + return JSON.stringify(uncast(value, r("Action")), null, 2); + }; + Convert.toChart = function (json) { + return cast(JSON.parse(json), r("Chart")); + }; + Convert.chartToJson = function (value) { + return JSON.stringify(uncast(value, r("Chart")), null, 2); + }; + Convert.toChatInitSettings = function (json) { + return cast(JSON.parse(json), r("ChatInitSettings")); + }; + Convert.chatInitSettingsToJson = function (value) { + return JSON.stringify(uncast(value, r("ChatInitSettings")), null, 2); + }; + Convert.toChatMessage = function (json) { + return cast(JSON.parse(json), r("ChatMessage")); + }; + Convert.chatMessageToJson = function (value) { + return JSON.stringify(uncast(value, r("ChatMessage")), null, 2); + }; + Convert.toChatRoom = function (json) { + return cast(JSON.parse(json), r("ChatRoom")); + }; + Convert.chatRoomToJson = function (value) { + return JSON.stringify(uncast(value, r("ChatRoom")), null, 2); + }; + Convert.toChatSearchCriteria = function (json) { + return cast(JSON.parse(json), r("ChatSearchCriteria")); + }; + Convert.chatSearchCriteriaToJson = function (value) { + return JSON.stringify(uncast(value, r("ChatSearchCriteria")), null, 2); + }; + Convert.toContact = function (json) { + return cast(JSON.parse(json), r("Contact")); + }; + Convert.contactToJson = function (value) { + return JSON.stringify(uncast(value, r("Contact")), null, 2); + }; + Convert.toContactList = function (json) { + return cast(JSON.parse(json), r("ContactList")); + }; + Convert.contactListToJson = function (value) { + return JSON.stringify(uncast(value, r("ContactList")), null, 2); + }; + Convert.toContext = function (json) { + return cast(JSON.parse(json), r("Context")); + }; + Convert.contextToJson = function (value) { + return JSON.stringify(uncast(value, r("Context")), null, 2); + }; + Convert.toCountry = function (json) { + return cast(JSON.parse(json), r("Country")); + }; + Convert.countryToJson = function (value) { + return JSON.stringify(uncast(value, r("Country")), null, 2); + }; + Convert.toCurrency = function (json) { + return cast(JSON.parse(json), r("Currency")); + }; + Convert.currencyToJson = function (value) { + return JSON.stringify(uncast(value, r("Currency")), null, 2); + }; + Convert.toEmail = function (json) { + return cast(JSON.parse(json), r("Email")); + }; + Convert.emailToJson = function (value) { + return JSON.stringify(uncast(value, r("Email")), null, 2); + }; + Convert.toInstrument = function (json) { + return cast(JSON.parse(json), r("Instrument")); + }; + Convert.instrumentToJson = function (value) { + return JSON.stringify(uncast(value, r("Instrument")), null, 2); + }; + Convert.toInstrumentList = function (json) { + return cast(JSON.parse(json), r("InstrumentList")); + }; + Convert.instrumentListToJson = function (value) { + return JSON.stringify(uncast(value, r("InstrumentList")), null, 2); + }; + Convert.toInteraction = function (json) { + return cast(JSON.parse(json), r("Interaction")); + }; + Convert.interactionToJson = function (value) { + return JSON.stringify(uncast(value, r("Interaction")), null, 2); + }; + Convert.toMessage = function (json) { + return cast(JSON.parse(json), r("Message")); + }; + Convert.messageToJson = function (value) { + return JSON.stringify(uncast(value, r("Message")), null, 2); + }; + Convert.toNothing = function (json) { + return cast(JSON.parse(json), r("Nothing")); + }; + Convert.nothingToJson = function (value) { + return JSON.stringify(uncast(value, r("Nothing")), null, 2); + }; + Convert.toOrder = function (json) { + return cast(JSON.parse(json), r("Order")); + }; + Convert.orderToJson = function (value) { + return JSON.stringify(uncast(value, r("Order")), null, 2); + }; + Convert.toOrderList = function (json) { + return cast(JSON.parse(json), r("OrderList")); + }; + Convert.orderListToJson = function (value) { + return JSON.stringify(uncast(value, r("OrderList")), null, 2); + }; + Convert.toOrganization = function (json) { + return cast(JSON.parse(json), r("Organization")); + }; + Convert.organizationToJson = function (value) { + return JSON.stringify(uncast(value, r("Organization")), null, 2); + }; + Convert.toPortfolio = function (json) { + return cast(JSON.parse(json), r("Portfolio")); + }; + Convert.portfolioToJson = function (value) { + return JSON.stringify(uncast(value, r("Portfolio")), null, 2); + }; + Convert.toPosition = function (json) { + return cast(JSON.parse(json), r("Position")); + }; + Convert.positionToJson = function (value) { + return JSON.stringify(uncast(value, r("Position")), null, 2); + }; + Convert.toProduct = function (json) { + return cast(JSON.parse(json), r("Product")); + }; + Convert.productToJson = function (value) { + return JSON.stringify(uncast(value, r("Product")), null, 2); + }; + Convert.toTimeRange = function (json) { + return cast(JSON.parse(json), r("TimeRange")); + }; + Convert.timeRangeToJson = function (value) { + return JSON.stringify(uncast(value, r("TimeRange")), null, 2); + }; + Convert.toTrade = function (json) { + return cast(JSON.parse(json), r("Trade")); + }; + Convert.tradeToJson = function (value) { + return JSON.stringify(uncast(value, r("Trade")), null, 2); + }; + Convert.toTradeList = function (json) { + return cast(JSON.parse(json), r("TradeList")); + }; + Convert.tradeListToJson = function (value) { + return JSON.stringify(uncast(value, r("TradeList")), null, 2); + }; + Convert.toTransactionResult = function (json) { + return cast(JSON.parse(json), r("TransactionResult")); + }; + Convert.transactionResultToJson = function (value) { + return JSON.stringify(uncast(value, r("TransactionResult")), null, 2); + }; + Convert.toValuation = function (json) { + return cast(JSON.parse(json), r("Valuation")); + }; + Convert.valuationToJson = function (value) { + return JSON.stringify(uncast(value, r("Valuation")), null, 2); + }; + return Convert; +}()); +function invalidValue(typ, val, key, parent) { + if (parent === void 0) { parent = ''; } + var prettyTyp = prettyTypeName(typ); + var parentText = parent ? " on ".concat(parent) : ''; + var keyText = key ? " for key \"".concat(key, "\"") : ''; + throw Error("Invalid value".concat(keyText).concat(parentText, ". Expected ").concat(prettyTyp, " but got ").concat(JSON.stringify(val))); +} +function prettyTypeName(typ) { + if (Array.isArray(typ)) { + if (typ.length === 2 && typ[0] === undefined) { + return "an optional ".concat(prettyTypeName(typ[1])); + } + else { + return "one of [".concat(typ.map(function (a) { return prettyTypeName(a); }).join(", "), "]"); + } + } + else if (typeof typ === "object" && typ.literal !== undefined) { + return typ.literal; + } + else { + return typeof typ; + } +} +function jsonToJSProps(typ) { + if (typ.jsonToJS === undefined) { + var map_1 = {}; + typ.props.forEach(function (p) { return map_1[p.json] = { key: p.js, typ: p.typ }; }); + typ.jsonToJS = map_1; + } + return typ.jsonToJS; +} +function jsToJSONProps(typ) { + if (typ.jsToJSON === undefined) { + var map_2 = {}; + typ.props.forEach(function (p) { return map_2[p.js] = { key: p.json, typ: p.typ }; }); + typ.jsToJSON = map_2; + } + return typ.jsToJSON; +} +function transform(val, typ, getProps, key, parent) { + if (key === void 0) { key = ''; } + if (parent === void 0) { parent = ''; } + function transformPrimitive(typ, val) { + if (typeof typ === typeof val) + return val; + return invalidValue(typ, val, key, parent); + } + function transformUnion(typs, val) { + // val must validate against one typ in typs + var l = typs.length; + for (var i = 0; i < l; i++) { + var typ_1 = typs[i]; + try { + return transform(val, typ_1, getProps); + } + catch (_) { } + } + return invalidValue(typs, val, key, parent); + } + function transformEnum(cases, val) { + if (cases.indexOf(val) !== -1) + return val; + return invalidValue(cases.map(function (a) { return l(a); }), val, key, parent); + } + function transformArray(typ, val) { + // val must be an array with no invalid elements + if (!Array.isArray(val)) + return invalidValue(l("array"), val, key, parent); + return val.map(function (el) { return transform(el, typ, getProps); }); + } + function transformDate(val) { + if (val === null) { + return null; + } + var d = new Date(val); + if (isNaN(d.valueOf())) { + return invalidValue(l("Date"), val, key, parent); + } + return d; + } + function transformObject(props, additional, val) { + if (val === null || typeof val !== "object" || Array.isArray(val)) { + return invalidValue(l(ref || "object"), val, key, parent); + } + var result = {}; + Object.getOwnPropertyNames(props).forEach(function (key) { + var prop = props[key]; + var v = Object.prototype.hasOwnProperty.call(val, key) ? val[key] : undefined; + result[prop.key] = transform(v, prop.typ, getProps, key, ref); + }); + Object.getOwnPropertyNames(val).forEach(function (key) { + if (!Object.prototype.hasOwnProperty.call(props, key)) { + result[key] = transform(val[key], additional, getProps, key, ref); + } + }); + return result; + } + if (typ === "any") + return val; + if (typ === null) { + if (val === null) + return val; + return invalidValue(typ, val, key, parent); + } + if (typ === false) + return invalidValue(typ, val, key, parent); + var ref = undefined; + while (typeof typ === "object" && typ.ref !== undefined) { + ref = typ.ref; + typ = typeMap[typ.ref]; + } + if (Array.isArray(typ)) + return transformEnum(typ, val); + if (typeof typ === "object") { + return typ.hasOwnProperty("unionMembers") ? transformUnion(typ.unionMembers, val) + : typ.hasOwnProperty("arrayItems") ? transformArray(typ.arrayItems, val) + : typ.hasOwnProperty("props") ? transformObject(getProps(typ), typ.additional, val) + : invalidValue(typ, val, key, parent); + } + // Numbers can be parsed by Date but shouldn't be. + if (typ === Date && typeof val !== "number") + return transformDate(val); + return transformPrimitive(typ, val); +} +function cast(val, typ) { + return transform(val, typ, jsonToJSProps); +} +function uncast(val, typ) { + return transform(val, typ, jsToJSONProps); +} +function l(typ) { + return { literal: typ }; +} +function a(typ) { + return { arrayItems: typ }; +} +function u() { + var typs = []; + for (var _i = 0; _i < arguments.length; _i++) { + typs[_i] = arguments[_i]; + } + return { unionMembers: typs }; +} +function o(props, additional) { + return { props: props, additional: additional }; +} +function m(additional) { + return { props: [], additional: additional }; +} +function r(name) { + return { ref: name }; +} +var typeMap = { + "Action": o([ + { json: "app", js: "app", typ: u(undefined, r("ActionTargetApp")) }, + { json: "context", js: "context", typ: r("ContextElement") }, + { json: "intent", js: "intent", typ: u(undefined, "") }, + { json: "title", js: "title", typ: "" }, + { json: "type", js: "type", typ: r("ActionType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ActionTargetApp": o([ + { json: "appId", js: "appId", typ: "" }, + { json: "desktopAgent", js: "desktopAgent", typ: u(undefined, "") }, + { json: "instanceId", js: "instanceId", typ: u(undefined, "") }, + ], "any"), + "ContextElement": o([ + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: "" }, + ], "any"), + "Chart": o([ + { json: "instruments", js: "instruments", typ: a(r("InstrumentElement")) }, + { json: "otherConfig", js: "otherConfig", typ: u(undefined, a(r("ContextElement"))) }, + { json: "range", js: "range", typ: u(undefined, r("TimeRangeObject")) }, + { json: "style", js: "style", typ: u(undefined, r("ChartStyle")) }, + { json: "type", js: "type", typ: r("ChartType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "InstrumentElement": o([ + { json: "id", js: "id", typ: r("PurpleInstrumentIdentifiers") }, + { json: "market", js: "market", typ: u(undefined, r("OrganizationMarket")) }, + { json: "type", js: "type", typ: r("PurpleInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "PurpleInstrumentIdentifiers": o([ + { json: "BBG", js: "BBG", typ: u(undefined, "") }, + { json: "CUSIP", js: "CUSIP", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + { json: "FIGI", js: "FIGI", typ: u(undefined, "") }, + { json: "ISIN", js: "ISIN", typ: u(undefined, "") }, + { json: "PERMID", js: "PERMID", typ: u(undefined, "") }, + { json: "RIC", js: "RIC", typ: u(undefined, "") }, + { json: "SEDOL", js: "SEDOL", typ: u(undefined, "") }, + { json: "ticker", js: "ticker", typ: u(undefined, "") }, + ], "any"), + "OrganizationMarket": o([ + { json: "BBG", js: "BBG", typ: u(undefined, "") }, + { json: "COUNTRY_ISOALPHA2", js: "COUNTRY_ISOALPHA2", typ: u(undefined, "") }, + { json: "MIC", js: "MIC", typ: u(undefined, "") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "TimeRangeObject": o([ + { json: "endTime", js: "endTime", typ: u(undefined, Date) }, + { json: "startTime", js: "startTime", typ: u(undefined, Date) }, + { json: "type", js: "type", typ: r("TimeRangeType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ChatInitSettings": o([ + { json: "chatName", js: "chatName", typ: u(undefined, "") }, + { json: "members", js: "members", typ: u(undefined, r("ContactListObject")) }, + { json: "message", js: "message", typ: u(undefined, u(r("MessageObject"), "")) }, + { json: "options", js: "options", typ: u(undefined, r("ChatOptions")) }, + { json: "type", js: "type", typ: r("ChatInitSettingsType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ContactListObject": o([ + { json: "contacts", js: "contacts", typ: a(r("ContactElement")) }, + { json: "type", js: "type", typ: r("ContactListType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ContactElement": o([ + { json: "id", js: "id", typ: r("PurpleContactIdentifiers") }, + { json: "type", js: "type", typ: r("FluffyInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "PurpleContactIdentifiers": o([ + { json: "email", js: "email", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + ], "any"), + "MessageObject": o([ + { json: "entities", js: "entities", typ: u(undefined, m(r("PurpleAction"))) }, + { json: "text", js: "text", typ: u(undefined, r("PurpleMessageText")) }, + { json: "type", js: "type", typ: r("MessageType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "PurpleAction": o([ + { json: "app", js: "app", typ: u(undefined, r("ActionTargetApp")) }, + { json: "context", js: "context", typ: u(undefined, r("ContextElement")) }, + { json: "intent", js: "intent", typ: u(undefined, "") }, + { json: "title", js: "title", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("EntityType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "data", js: "data", typ: u(undefined, r("PurpleData")) }, + ], "any"), + "PurpleData": o([ + { json: "dataUri", js: "dataUri", typ: "" }, + { json: "name", js: "name", typ: "" }, + ], "any"), + "PurpleMessageText": o([ + { json: "text/markdown", js: "text/markdown", typ: u(undefined, "") }, + { json: "text/plain", js: "text/plain", typ: u(undefined, "") }, + ], "any"), + "ChatOptions": o([ + { json: "allowAddUser", js: "allowAddUser", typ: u(undefined, true) }, + { json: "allowHistoryBrowsing", js: "allowHistoryBrowsing", typ: u(undefined, true) }, + { json: "allowMessageCopy", js: "allowMessageCopy", typ: u(undefined, true) }, + { json: "groupRecipients", js: "groupRecipients", typ: u(undefined, true) }, + { json: "isPublic", js: "isPublic", typ: u(undefined, true) }, + ], "any"), + "ChatMessage": o([ + { json: "chatRoom", js: "chatRoom", typ: r("ChatRoomObject") }, + { json: "message", js: "message", typ: r("MessageObject") }, + { json: "type", js: "type", typ: r("ChatMessageType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ChatRoomObject": o([ + { json: "id", js: "id", typ: m("any") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "providerName", js: "providerName", typ: "" }, + { json: "type", js: "type", typ: r("ChatRoomType") }, + { json: "url", js: "url", typ: u(undefined, "") }, + ], "any"), + "ChatRoom": o([ + { json: "id", js: "id", typ: m("any") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "providerName", js: "providerName", typ: "" }, + { json: "type", js: "type", typ: r("ChatRoomType") }, + { json: "url", js: "url", typ: u(undefined, "") }, + ], "any"), + "ChatSearchCriteria": o([ + { json: "criteria", js: "criteria", typ: a(u(r("OrganizationObject"), "")) }, + { json: "type", js: "type", typ: r("ChatSearchCriteriaType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "OrganizationObject": o([ + { json: "id", js: "id", typ: r("Identifiers") }, + { json: "market", js: "market", typ: u(undefined, r("OrganizationMarket")) }, + { json: "type", js: "type", typ: r("TentacledInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Identifiers": o([ + { json: "BBG", js: "BBG", typ: u(undefined, "") }, + { json: "CUSIP", js: "CUSIP", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + { json: "FIGI", js: "FIGI", typ: u(undefined, "") }, + { json: "ISIN", js: "ISIN", typ: u(undefined, "") }, + { json: "PERMID", js: "PERMID", typ: u(undefined, "") }, + { json: "RIC", js: "RIC", typ: u(undefined, "") }, + { json: "SEDOL", js: "SEDOL", typ: u(undefined, "") }, + { json: "ticker", js: "ticker", typ: u(undefined, "") }, + { json: "LEI", js: "LEI", typ: u(undefined, "") }, + { json: "email", js: "email", typ: u(undefined, "") }, + ], "any"), + "Contact": o([ + { json: "id", js: "id", typ: r("FluffyContactIdentifiers") }, + { json: "type", js: "type", typ: r("FluffyInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "FluffyContactIdentifiers": o([ + { json: "email", js: "email", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + ], "any"), + "ContactList": o([ + { json: "contacts", js: "contacts", typ: a(r("ContactElement")) }, + { json: "type", js: "type", typ: r("ContactListType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Context": o([ + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: "" }, + ], "any"), + "Country": o([ + { json: "id", js: "id", typ: r("CountryID") }, + { json: "type", js: "type", typ: r("CountryType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "CountryID": o([ + { json: "COUNTRY_ISOALPHA2", js: "COUNTRY_ISOALPHA2", typ: u(undefined, "") }, + { json: "COUNTRY_ISOALPHA3", js: "COUNTRY_ISOALPHA3", typ: u(undefined, "") }, + { json: "ISOALPHA2", js: "ISOALPHA2", typ: u(undefined, "") }, + { json: "ISOALPHA3", js: "ISOALPHA3", typ: u(undefined, "") }, + ], "any"), + "Currency": o([ + { json: "id", js: "id", typ: r("CurrencyID") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("CurrencyType") }, + ], "any"), + "CurrencyID": o([ + { json: "CURRENCY_ISOCODE", js: "CURRENCY_ISOCODE", typ: u(undefined, "") }, + ], "any"), + "Email": o([ + { json: "recipients", js: "recipients", typ: r("EmailRecipients") }, + { json: "subject", js: "subject", typ: u(undefined, "") }, + { json: "textBody", js: "textBody", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("EmailType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "EmailRecipients": o([ + { json: "id", js: "id", typ: u(undefined, r("EmailRecipientsID")) }, + { json: "type", js: "type", typ: r("EmailRecipientsType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "contacts", js: "contacts", typ: u(undefined, a(r("ContactElement"))) }, + ], "any"), + "EmailRecipientsID": o([ + { json: "email", js: "email", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + ], "any"), + "Instrument": o([ + { json: "id", js: "id", typ: r("FluffyInstrumentIdentifiers") }, + { json: "market", js: "market", typ: u(undefined, r("PurpleMarket")) }, + { json: "type", js: "type", typ: r("PurpleInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "FluffyInstrumentIdentifiers": o([ + { json: "BBG", js: "BBG", typ: u(undefined, "") }, + { json: "CUSIP", js: "CUSIP", typ: u(undefined, "") }, + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + { json: "FIGI", js: "FIGI", typ: u(undefined, "") }, + { json: "ISIN", js: "ISIN", typ: u(undefined, "") }, + { json: "PERMID", js: "PERMID", typ: u(undefined, "") }, + { json: "RIC", js: "RIC", typ: u(undefined, "") }, + { json: "SEDOL", js: "SEDOL", typ: u(undefined, "") }, + { json: "ticker", js: "ticker", typ: u(undefined, "") }, + ], "any"), + "PurpleMarket": o([ + { json: "BBG", js: "BBG", typ: u(undefined, "") }, + { json: "COUNTRY_ISOALPHA2", js: "COUNTRY_ISOALPHA2", typ: u(undefined, "") }, + { json: "MIC", js: "MIC", typ: u(undefined, "") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "InstrumentList": o([ + { json: "instruments", js: "instruments", typ: a(r("InstrumentElement")) }, + { json: "type", js: "type", typ: r("InstrumentListType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Interaction": o([ + { json: "description", js: "description", typ: "" }, + { json: "id", js: "id", typ: u(undefined, r("InteractionID")) }, + { json: "initiator", js: "initiator", typ: u(undefined, r("ContactElement")) }, + { json: "interactionType", js: "interactionType", typ: "" }, + { json: "origin", js: "origin", typ: u(undefined, "") }, + { json: "participants", js: "participants", typ: r("ContactListObject") }, + { json: "timeRange", js: "timeRange", typ: r("TimeRangeObject") }, + { json: "type", js: "type", typ: r("InteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "InteractionID": o([ + { json: "SALESFORCE", js: "SALESFORCE", typ: u(undefined, "") }, + { json: "SINGLETRACK", js: "SINGLETRACK", typ: u(undefined, "") }, + { json: "URI", js: "URI", typ: u(undefined, "") }, + ], "any"), + "Message": o([ + { json: "entities", js: "entities", typ: u(undefined, m(r("FluffyAction"))) }, + { json: "text", js: "text", typ: u(undefined, r("FluffyMessageText")) }, + { json: "type", js: "type", typ: r("MessageType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "FluffyAction": o([ + { json: "app", js: "app", typ: u(undefined, r("ActionTargetApp")) }, + { json: "context", js: "context", typ: u(undefined, r("ContextElement")) }, + { json: "intent", js: "intent", typ: u(undefined, "") }, + { json: "title", js: "title", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("EntityType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "data", js: "data", typ: u(undefined, r("FluffyData")) }, + ], "any"), + "FluffyData": o([ + { json: "dataUri", js: "dataUri", typ: "" }, + { json: "name", js: "name", typ: "" }, + ], "any"), + "FluffyMessageText": o([ + { json: "text/markdown", js: "text/markdown", typ: u(undefined, "") }, + { json: "text/plain", js: "text/plain", typ: u(undefined, "") }, + ], "any"), + "Nothing": o([ + { json: "type", js: "type", typ: r("NothingType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Order": o([ + { json: "details", js: "details", typ: u(undefined, r("PurpleOrderDetails")) }, + { json: "id", js: "id", typ: m("") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("OrderType") }, + ], "any"), + "PurpleOrderDetails": o([ + { json: "product", js: "product", typ: u(undefined, r("ProductObject")) }, + ], "any"), + "ProductObject": o([ + { json: "id", js: "id", typ: m("") }, + { json: "instrument", js: "instrument", typ: u(undefined, r("InstrumentElement")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("ProductType") }, + ], "any"), + "OrderList": o([ + { json: "orders", js: "orders", typ: a(r("OrderElement")) }, + { json: "type", js: "type", typ: r("OrderListType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "OrderElement": o([ + { json: "details", js: "details", typ: u(undefined, r("FluffyOrderDetails")) }, + { json: "id", js: "id", typ: m("") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("OrderType") }, + ], "any"), + "FluffyOrderDetails": o([ + { json: "product", js: "product", typ: u(undefined, r("ProductObject")) }, + ], "any"), + "Organization": o([ + { json: "id", js: "id", typ: r("OrganizationIdentifiers") }, + { json: "type", js: "type", typ: r("StickyInteractionType") }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "OrganizationIdentifiers": o([ + { json: "FDS_ID", js: "FDS_ID", typ: u(undefined, "") }, + { json: "LEI", js: "LEI", typ: u(undefined, "") }, + { json: "PERMID", js: "PERMID", typ: u(undefined, "") }, + ], "any"), + "Portfolio": o([ + { json: "positions", js: "positions", typ: a(r("PositionElement")) }, + { json: "type", js: "type", typ: r("PortfolioType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "PositionElement": o([ + { json: "holding", js: "holding", typ: 3.14 }, + { json: "instrument", js: "instrument", typ: r("InstrumentElement") }, + { json: "type", js: "type", typ: r("PositionType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Position": o([ + { json: "holding", js: "holding", typ: 3.14 }, + { json: "instrument", js: "instrument", typ: r("InstrumentElement") }, + { json: "type", js: "type", typ: r("PositionType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Product": o([ + { json: "id", js: "id", typ: m("") }, + { json: "instrument", js: "instrument", typ: u(undefined, r("InstrumentElement")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "type", js: "type", typ: r("ProductType") }, + ], "any"), + "TimeRange": o([ + { json: "endTime", js: "endTime", typ: u(undefined, Date) }, + { json: "startTime", js: "startTime", typ: u(undefined, Date) }, + { json: "type", js: "type", typ: r("TimeRangeType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Trade": o([ + { json: "id", js: "id", typ: m("") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "product", js: "product", typ: r("ProductObject") }, + { json: "type", js: "type", typ: r("TradeType") }, + ], "any"), + "TradeList": o([ + { json: "trades", js: "trades", typ: a(r("TradeElement")) }, + { json: "type", js: "type", typ: r("TradeListType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "TradeElement": o([ + { json: "id", js: "id", typ: m("") }, + { json: "name", js: "name", typ: u(undefined, "") }, + { json: "product", js: "product", typ: r("ProductObject") }, + { json: "type", js: "type", typ: r("TradeType") }, + ], "any"), + "TransactionResult": o([ + { json: "context", js: "context", typ: u(undefined, r("ContextElement")) }, + { json: "message", js: "message", typ: u(undefined, "") }, + { json: "status", js: "status", typ: r("TransactionStatus") }, + { json: "type", js: "type", typ: r("TransactionResultType") }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "Valuation": o([ + { json: "CURRENCY_ISOCODE", js: "CURRENCY_ISOCODE", typ: "" }, + { json: "expiryTime", js: "expiryTime", typ: u(undefined, Date) }, + { json: "price", js: "price", typ: u(undefined, 3.14) }, + { json: "type", js: "type", typ: r("ValuationType") }, + { json: "valuationTime", js: "valuationTime", typ: u(undefined, Date) }, + { json: "value", js: "value", typ: 3.14 }, + { json: "id", js: "id", typ: u(undefined, m("any")) }, + { json: "name", js: "name", typ: u(undefined, "") }, + ], "any"), + "ActionType": [ + "fdc3.action", + ], + "PurpleInteractionType": [ + "fdc3.instrument", + ], + "TimeRangeType": [ + "fdc3.timeRange", + ], + "ChartStyle": [ + "bar", + "candle", + "custom", + "heatmap", + "histogram", + "line", + "mountain", + "pie", + "scatter", + "stacked-bar", + ], + "ChartType": [ + "fdc3.chart", + ], + "FluffyInteractionType": [ + "fdc3.contact", + ], + "ContactListType": [ + "fdc3.contactList", + ], + "EntityType": [ + "fdc3.action", + "fdc3.entity.fileAttachment", + ], + "MessageType": [ + "fdc3.message", + ], + "ChatInitSettingsType": [ + "fdc3.chat.initSettings", + ], + "ChatRoomType": [ + "fdc3.chat.room", + ], + "ChatMessageType": [ + "fdc3.chat.message", + ], + "TentacledInteractionType": [ + "fdc3.contact", + "fdc3.instrument", + "fdc3.organization", + ], + "ChatSearchCriteriaType": [ + "fdc3.chat.searchCriteria", + ], + "CountryType": [ + "fdc3.country", + ], + "CurrencyType": [ + "fdc3.currency", + ], + "EmailRecipientsType": [ + "fdc3.contact", + "fdc3.contactList", + ], + "EmailType": [ + "fdc3.email", + ], + "InstrumentListType": [ + "fdc3.instrumentList", + ], + "InteractionType": [ + "fdc3.interaction", + ], + "NothingType": [ + "fdc3.nothing", + ], + "ProductType": [ + "fdc3.product", + ], + "OrderType": [ + "fdc3.order", + ], + "OrderListType": [ + "fdc3.orderList", + ], + "StickyInteractionType": [ + "fdc3.organization", + ], + "PositionType": [ + "fdc3.position", + ], + "PortfolioType": [ + "fdc3.portfolio", + ], + "TradeType": [ + "fdc3.trade", + ], + "TradeListType": [ + "fdc3.tradeList", + ], + "TransactionStatus": [ + "Created", + "Deleted", + "Failed", + "Updated", + ], + "TransactionResultType": [ + "fdc3.transactionResult", + ], + "ValuationType": [ + "fdc3.valuation", + ] +}; + +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright FINOS FDC3 contributors - see NOTICE file + */ +/** + * @deprecated Use {@link StandardIntent} instead + */ +var Intents; +(function (Intents) { + Intents["CreateInteraction"] = "CreateInteraction"; + Intents["SendChatMessage"] = "SendChatMessage"; + Intents["StartCall"] = "StartCall"; + Intents["StartChat"] = "StartChat"; + Intents["StartEmail"] = "StartEmail"; + Intents["ViewAnalysis"] = "ViewAnalysis"; + Intents["ViewChat"] = "ViewChat"; + Intents["ViewChart"] = "ViewChart"; + Intents["ViewContact"] = "ViewContact"; + Intents["ViewHoldings"] = "ViewHoldings"; + Intents["ViewInstrument"] = "ViewInstrument"; + Intents["ViewInteractions"] = "ViewInteractions"; + Intents["ViewMessages"] = "ViewMessages"; + Intents["ViewNews"] = "ViewNews"; + Intents["ViewOrders"] = "ViewOrders"; + Intents["ViewProfile"] = "ViewProfile"; + Intents["ViewQuote"] = "ViewQuote"; + Intents["ViewResearch"] = "ViewResearch"; +})(Intents || (Intents = {})); + + +//# sourceMappingURL=fdc3.esm.js.map + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!***********************************!*\ + !*** ./client/src/fdc3monitor.ts ***! + \***********************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _finos_fdc3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @finos/fdc3 */ "../../node_modules/@finos/fdc3/dist/fdc3.esm.js"); + +document.addEventListener("DOMContentLoaded", async () => { + try { + await initDom(); + } + catch (error) { + console.error(error); + } +}); +/** + * Initialize the DOM elements. + */ +async function initDom() { + try { + const appChannel = await (0,_finos_fdc3__WEBPACK_IMPORTED_MODULE_0__.getCurrentChannel)(); + if (appChannel) { + await appChannel.addContextListener(null, (ctx) => { + if (ctx.type === "fdc3.instrument") { + const receiveElement = document.querySelector("#received-instrument"); + if (receiveElement) { + receiveElement.value = ctx.id?.ticker; + } + } + }); + } + } + catch (err) { + showError(err); + } +} +/** + * Show an error on the UI. + * @param err The error to display. + */ +function showError(err) { + const errDom = document.querySelector("#error"); + if (errDom) { + errDom.innerHTML = err instanceof Error ? err.message : JSON.stringify(err); + } +} + +})(); + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmRjM21vbml0b3IuYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0EsY0FBYywyZ0VBQTJnRTtBQUN6aEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQsNkJBQTZCO0FBQ3pGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyw4QkFBOEI7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxvQ0FB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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQsMkJBQTJCO0FBQ3ZGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5Qyx5QkFBeUIsMEJBQTBCO0FBQzVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDLHVCQUF1Qiw0QkFBNEI7QUFDNUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQiw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QixPQUFPO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxREFBcUQsY0FBYztBQUNuRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLHNDQUFzQztBQUM3RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQix1QkFBdUI7QUFDNUM7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxVQUFVLGlFQUFpRTtBQUMzRSxVQUFVLDBEQUEwRDtBQUNwRSxVQUFVLHFEQUFxRDtBQUMvRCxVQUFVLHFDQUFxQztBQUMvQyxVQUFVLGdEQUFnRDtBQUMxRCxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSxxQ0FBcUM7QUFDL0MsVUFBVSxpRUFBaUU7QUFDM0UsVUFBVSw2REFBNkQ7QUFDdkU7QUFDQTtBQUNBLFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNELFVBQVUsbUNBQW1DO0FBQzdDO0FBQ0E7QUFDQSxVQUFVLHdFQUF3RTtBQUNsRixVQUFVLG1GQUFtRjtBQUM3RixVQUFVLHFFQUFxRTtBQUMvRSxVQUFVLGdFQUFnRTtBQUMxRSxVQUFVLCtDQUErQztBQUN6RCxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSw2REFBNkQ7QUFDdkUsVUFBVSwwRUFBMEU7QUFDcEYsVUFBVSwyREFBMkQ7QUFDckUsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUsK0NBQStDO0FBQ3pELFVBQVUsbURBQW1EO0FBQzdELFVBQVUscURBQXFEO0FBQy9ELFVBQVUsaURBQWlEO0FBQzNELFVBQVUsaURBQWlEO0FBQzNELFVBQVUscURBQXFEO0FBQy9ELFVBQVUsK0NBQStDO0FBQ3pELFVBQVUsbURBQW1EO0FBQzdELFVBQVUscURBQXFEO0FBQy9EO0FBQ0E7QUFDQSxVQUFVLCtDQUErQztBQUN6RCxVQUFVLDJFQUEyRTtBQUNyRixVQUFVLCtDQUErQztBQUN6RCxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSx5REFBeUQ7QUFDbkUsVUFBVSw2REFBNkQ7QUFDdkUsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUseURBQXlEO0FBQ25FLFVBQVUsMkVBQTJFO0FBQ3JGLFVBQVUsOEVBQThFO0FBQ3hGLFVBQVUscUVBQXFFO0FBQy9FLFVBQVUsMERBQTBEO0FBQ3BFLFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQSxVQUFVLCtEQUErRDtBQUN6RSxVQUFVLHFEQUFxRDtBQUMvRCxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSwwREFBMEQ7QUFDcEUsVUFBVSwyREFBMkQ7QUFDckUsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUsbURBQW1EO0FBQzdELFVBQVUscURBQXFEO0FBQy9EO0FBQ0E7QUFDQSxVQUFVLDJFQUEyRTtBQUNyRixVQUFVLHFFQUFxRTtBQUMvRSxVQUFVLGlEQUFpRDtBQUMzRCxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSxpRUFBaUU7QUFDM0UsVUFBVSx3RUFBd0U7QUFDbEYsVUFBVSxxREFBcUQ7QUFDL0QsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxnREFBZ0Q7QUFDMUQsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxpREFBaUQ7QUFDM0QsVUFBVSw4REFBOEQ7QUFDeEU7QUFDQTtBQUNBLFVBQVUseUNBQXlDO0FBQ25ELFVBQVUsbUNBQW1DO0FBQzdDO0FBQ0E7QUFDQSxVQUFVLG1FQUFtRTtBQUM3RSxVQUFVLDZEQUE2RDtBQUN2RTtBQUNBO0FBQ0EsVUFBVSxtRUFBbUU7QUFDN0UsVUFBVSxtRkFBbUY7QUFDN0YsVUFBVSwyRUFBMkU7QUFDckYsVUFBVSx5RUFBeUU7QUFDbkYsVUFBVSwyREFBMkQ7QUFDckU7QUFDQTtBQUNBLFVBQVUsNERBQTREO0FBQ3RFLFVBQVUseURBQXlEO0FBQ25FLFVBQVUscURBQXFEO0FBQy9ELFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQSxVQUFVLHFDQUFxQztBQUMvQyxVQUFVLGlEQUFpRDtBQUMzRCxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLGtEQUFrRDtBQUM1RCxVQUFVLCtDQUErQztBQUN6RDtBQUNBO0FBQ0EsVUFBVSxxQ0FBcUM7QUFDL0MsVUFBVSxpREFBaUQ7QUFDM0QsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxrREFBa0Q7QUFDNUQsVUFBVSwrQ0FBK0M7QUFDekQ7QUFDQTtBQUNBLFVBQVUsMEVBQTBFO0FBQ3BGLFVBQVUsNERBQTREO0FBQ3RFLFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQSxVQUFVLDZDQUE2QztBQUN2RCxVQUFVLDBFQUEwRTtBQUNwRixVQUFVLDhEQUE4RDtBQUN4RSxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSwrQ0FBK0M7QUFDekQsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxxREFBcUQ7QUFDL0QsVUFBVSxpREFBaUQ7QUFDM0QsVUFBVSxpREFBaUQ7QUFDM0QsVUFBVSxxREFBcUQ7QUFDL0QsVUFBVSwrQ0FBK0M7QUFDekQsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxxREFBcUQ7QUFDL0QsVUFBVSwrQ0FBK0M7QUFDekQsVUFBVSxtREFBbUQ7QUFDN0Q7QUFDQTtBQUNBLFVBQVUsMERBQTBEO0FBQ3BFLFVBQVUsMkRBQTJEO0FBQ3JFLFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQSxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLHFEQUFxRDtBQUMvRDtBQUNBO0FBQ0EsVUFBVSwrREFBK0Q7QUFDekUsVUFBVSxxREFBcUQ7QUFDL0QsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNELFVBQVUsbUNBQW1DO0FBQzdDO0FBQ0E7QUFDQSxVQUFVLDJDQUEyQztBQUNyRCxVQUFVLGlEQUFpRDtBQUMzRCxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSwyRUFBMkU7QUFDckYsVUFBVSwyRUFBMkU7QUFDckYsVUFBVSwyREFBMkQ7QUFDckUsVUFBVSwyREFBMkQ7QUFDckU7QUFDQTtBQUNBLFVBQVUsNENBQTRDO0FBQ3RELFVBQVUsaURBQWlEO0FBQzNELFVBQVUsa0RBQWtEO0FBQzVEO0FBQ0E7QUFDQSxVQUFVLHlFQUF5RTtBQUNuRjtBQUNBO0FBQ0EsVUFBVSxpRUFBaUU7QUFDM0UsVUFBVSx1REFBdUQ7QUFDakUsVUFBVSx5REFBeUQ7QUFDbkUsVUFBVSwrQ0FBK0M7QUFDekQsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUsaUVBQWlFO0FBQzNFLFVBQVUseURBQXlEO0FBQ25FLFVBQVUsaURBQWlEO0FBQzNELFVBQVUsNkVBQTZFO0FBQ3ZGO0FBQ0E7QUFDQSxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLHFEQUFxRDtBQUMvRDtBQUNBO0FBQ0EsVUFBVSw2REFBNkQ7QUFDdkUsVUFBVSxvRUFBb0U7QUFDOUUsVUFBVSwyREFBMkQ7QUFDckUsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUsK0NBQStDO0FBQ3pELFVBQVUsbURBQW1EO0FBQzdELFVBQVUscURBQXFEO0FBQy9ELFVBQVUsaURBQWlEO0FBQzNELFVBQVUsaURBQWlEO0FBQzNELFVBQVUscURBQXFEO0FBQy9ELFVBQVUsK0NBQStDO0FBQ3pELFVBQVUsbURBQW1EO0FBQzdELFVBQVUscURBQXFEO0FBQy9EO0FBQ0E7QUFDQSxVQUFVLCtDQUErQztBQUN6RCxVQUFVLDJFQUEyRTtBQUNyRixVQUFVLCtDQUErQztBQUN6RCxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSx3RUFBd0U7QUFDbEYsVUFBVSx3REFBd0Q7QUFDbEUsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUsaURBQWlEO0FBQzNELFVBQVUsNkRBQTZEO0FBQ3ZFLFVBQVUsNEVBQTRFO0FBQ3RGLFVBQVUseURBQXlEO0FBQ25FLFVBQVUscURBQXFEO0FBQy9ELFVBQVUsdUVBQXVFO0FBQ2pGLFVBQVUsK0RBQStEO0FBQ3pFLFVBQVUscURBQXFEO0FBQy9ELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQSxVQUFVLDZEQUE2RDtBQUN2RSxVQUFVLCtEQUErRDtBQUN6RSxVQUFVLCtDQUErQztBQUN6RDtBQUNBO0FBQ0EsVUFBVSwyRUFBMkU7QUFDckYsVUFBVSxxRUFBcUU7QUFDL0UsVUFBVSxpREFBaUQ7QUFDM0QsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUsaUVBQWlFO0FBQzNFLFVBQVUsd0VBQXdFO0FBQ2xGLFVBQVUscURBQXFEO0FBQy9ELFVBQVUsbURBQW1EO0FBQzdELFVBQVUsZ0RBQWdEO0FBQzFELFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNELFVBQVUsOERBQThEO0FBQ3hFO0FBQ0E7QUFDQSxVQUFVLHlDQUF5QztBQUNuRCxVQUFVLG1DQUFtQztBQUM3QztBQUNBO0FBQ0EsVUFBVSxtRUFBbUU7QUFDN0UsVUFBVSw2REFBNkQ7QUFDdkU7QUFDQTtBQUNBLFVBQVUsaURBQWlEO0FBQzNELFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQSxVQUFVLDRFQUE0RTtBQUN0RixVQUFVLGtDQUFrQztBQUM1QyxVQUFVLGlEQUFpRDtBQUMzRCxVQUFVLCtDQUErQztBQUN6RDtBQUNBO0FBQ0EsVUFBVSx1RUFBdUU7QUFDakY7QUFDQTtBQUNBLFVBQVUsa0NBQWtDO0FBQzVDLFVBQVUsaUZBQWlGO0FBQzNGLFVBQVUsaURBQWlEO0FBQzNELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQSxVQUFVLHlEQUF5RDtBQUNuRSxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSw0RUFBNEU7QUFDdEYsVUFBVSxrQ0FBa0M7QUFDNUMsVUFBVSxpREFBaUQ7QUFDM0QsVUFBVSwrQ0FBK0M7QUFDekQ7QUFDQTtBQUNBLFVBQVUsdUVBQXVFO0FBQ2pGO0FBQ0E7QUFDQSxVQUFVLHlEQUF5RDtBQUNuRSxVQUFVLDJEQUEyRDtBQUNyRSxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSxxREFBcUQ7QUFDL0QsVUFBVSwrQ0FBK0M7QUFDekQsVUFBVSxxREFBcUQ7QUFDL0Q7QUFDQTtBQUNBLFVBQVUsa0VBQWtFO0FBQzVFLFVBQVUsbURBQW1EO0FBQzdELFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQSxVQUFVLDJDQUEyQztBQUNyRCxVQUFVLG1FQUFtRTtBQUM3RSxVQUFVLGtEQUFrRDtBQUM1RCxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSwyQ0FBMkM7QUFDckQsVUFBVSxtRUFBbUU7QUFDN0UsVUFBVSxrREFBa0Q7QUFDNUQsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUsa0NBQWtDO0FBQzVDLFVBQVUsaUZBQWlGO0FBQzNGLFVBQVUsaURBQWlEO0FBQzNELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQSxVQUFVLHlEQUF5RDtBQUNuRSxVQUFVLDZEQUE2RDtBQUN2RSxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLG1EQUFtRDtBQUM3RCxVQUFVLGlEQUFpRDtBQUMzRDtBQUNBO0FBQ0EsVUFBVSxrQ0FBa0M7QUFDNUMsVUFBVSxpREFBaUQ7QUFDM0QsVUFBVSx5REFBeUQ7QUFDbkUsVUFBVSwrQ0FBK0M7QUFDekQ7QUFDQTtBQUNBLFVBQVUseURBQXlEO0FBQ25FLFVBQVUsbURBQW1EO0FBQzdELFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQSxVQUFVLGtDQUFrQztBQUM1QyxVQUFVLGlEQUFpRDtBQUMzRCxVQUFVLHlEQUF5RDtBQUNuRSxVQUFVLCtDQUErQztBQUN6RDtBQUNBO0FBQ0EsVUFBVSx3RUFBd0U7QUFDbEYsVUFBVSx1REFBdUQ7QUFDakUsVUFBVSwyREFBMkQ7QUFDckUsVUFBVSwyREFBMkQ7QUFDckUsVUFBVSxtREFBbUQ7QUFDN0QsVUFBVSxpREFBaUQ7QUFDM0Q7QUFDQTtBQUNBLFVBQVUsMkRBQTJEO0FBQ3JFLFVBQVUsK0RBQStEO0FBQ3pFLFVBQVUscURBQXFEO0FBQy9ELFVBQVUsbURBQW1EO0FBQzdELFVBQVUscUVBQXFFO0FBQy9FLFVBQVUsdUNBQXVDO0FBQ2pELFVBQVUsbURBQW1EO0FBQzdELFVBQVUsaURBQWlEO0FBQzNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLHNCQUFzQjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDBCQUEwQjs7QUFFd2Y7QUFDbmhCOzs7Ozs7O1VDam1HQTtVQUNBOztVQUVBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBOztVQUVBO1VBQ0E7O1VBRUE7VUFDQTtVQUNBOzs7OztXQ3RCQTtXQUNBO1dBQ0E7V0FDQTtXQUNBLHlDQUF5Qyx3Q0FBd0M7V0FDakY7V0FDQTtXQUNBOzs7OztXQ1BBOzs7OztXQ0FBO1dBQ0E7V0FDQTtXQUNBLHVEQUF1RCxpQkFBaUI7V0FDeEU7V0FDQSxnREFBZ0QsYUFBYTtXQUM3RDs7Ozs7Ozs7Ozs7O0FDTmdEO0FBRWhELFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN4RCxJQUFJLENBQUM7UUFDSixNQUFNLE9BQU8sRUFBRSxDQUFDO0lBQ2pCLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2hCLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdEIsQ0FBQztBQUNGLENBQUMsQ0FBQyxDQUFDO0FBRUg7O0dBRUc7QUFDSCxLQUFLLFVBQVUsT0FBTztJQUNyQixJQUFJLENBQUM7UUFDSixNQUFNLFVBQVUsR0FBRyxNQUFNLDhEQUFpQixFQUFFLENBQUM7UUFFN0MsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNoQixNQUFNLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRTtnQkFDakQsSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLGlCQUFpQixFQUFFLENBQUM7b0JBQ3BDLE1BQU0sY0FBYyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQW1CLHNCQUFzQixDQUFDLENBQUM7b0JBQ3hGLElBQUksY0FBYyxFQUFFLENBQUM7d0JBQ3BCLGNBQWMsQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUM7b0JBQ3ZDLENBQUM7Z0JBQ0YsQ0FBQztZQUNGLENBQUMsQ0FBQyxDQUFDO1FBQ0osQ0FBQztJQUNGLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2QsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2hCLENBQUM7QUFDRixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBUyxTQUFTLENBQUMsR0FBWTtJQUM5QixNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2hELElBQUksTUFBTSxFQUFFLENBQUM7UUFDWixNQUFNLENBQUMsU0FBUyxHQUFHLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDN0UsQ0FBQztBQUNGLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC8uLi8uLi9ub2RlX21vZHVsZXMvQGZpbm9zL2ZkYzMvZGlzdC9mZGMzLmVzbS5qcyIsIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC93ZWJwYWNrL3J1bnRpbWUvZGVmaW5lIHByb3BlcnR5IGdldHRlcnMiLCJ3ZWJwYWNrOi8vaW50ZWdyYXRpb24tZXhjZWwvd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCIsIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL2ludGVncmF0aW9uLWV4Y2VsLy4vY2xpZW50L3NyYy9mZGMzbW9uaXRvci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUbyBwYXJzZSB0aGlzIGRhdGE6XG4vL1xuLy8gICBpbXBvcnQgeyBDb252ZXJ0LCBBZ2VudEVycm9yUmVzcG9uc2VNZXNzYWdlLCBBZ2VudFJlcXVlc3RNZXNzYWdlLCBBZ2VudFJlc3BvbnNlTWVzc2FnZSwgQnJpZGdlRXJyb3JSZXNwb25zZU1lc3NhZ2UsIEJyaWRnZVJlcXVlc3RNZXNzYWdlLCBCcmlkZ2VSZXNwb25zZU1lc3NhZ2UsIEJyb2FkY2FzdEFnZW50UmVxdWVzdCwgQnJvYWRjYXN0QnJpZGdlUmVxdWVzdCwgQ29ubmVjdGlvblN0ZXBNZXNzYWdlLCBDb25uZWN0aW9uU3RlcDJIZWxsbywgQ29ubmVjdGlvblN0ZXAzSGFuZHNoYWtlLCBDb25uZWN0aW9uU3RlcDRBdXRoZW50aWNhdGlvbkZhaWxlZCwgQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlLCBGaW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlLCBGaW5kSW5zdGFuY2VzQWdlbnRSZXF1ZXN0LCBGaW5kSW5zdGFuY2VzQWdlbnRSZXNwb25zZSwgRmluZEluc3RhbmNlc0JyaWRnZUVycm9yUmVzcG9uc2UsIEZpbmRJbnN0YW5jZXNCcmlkZ2VSZXF1ZXN0LCBGaW5kSW5zdGFuY2VzQnJpZGdlUmVzcG9uc2UsIEZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2UsIEZpbmRJbnRlbnRBZ2VudFJlcXVlc3QsIEZpbmRJbnRlbnRBZ2VudFJlc3BvbnNlLCBGaW5kSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZSwgRmluZEludGVudEJyaWRnZVJlcXVlc3QsIEZpbmRJbnRlbnRCcmlkZ2VSZXNwb25zZSwgRmluZEludGVudHNCeUNvbnRleHRBZ2VudEVycm9yUmVzcG9uc2UsIEZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXF1ZXN0LCBGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVzcG9uc2UsIEZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlRXJyb3JSZXNwb25zZSwgRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXF1ZXN0LCBGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlc3BvbnNlLCBHZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZSwgR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3QsIEdldEFwcE1ldGFkYXRhQWdlbnRSZXNwb25zZSwgR2V0QXBwTWV0YWRhdGFCcmlkZ2VFcnJvclJlc3BvbnNlLCBHZXRBcHBNZXRhZGF0YUJyaWRnZVJlcXVlc3QsIEdldEFwcE1ldGFkYXRhQnJpZGdlUmVzcG9uc2UsIE9wZW5BZ2VudEVycm9yUmVzcG9uc2UsIE9wZW5BZ2VudFJlcXVlc3QsIE9wZW5BZ2VudFJlc3BvbnNlLCBPcGVuQnJpZGdlRXJyb3JSZXNwb25zZSwgT3BlbkJyaWRnZVJlcXVlc3QsIE9wZW5CcmlkZ2VSZXNwb25zZSwgUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RBZ2VudFJlcXVlc3QsIFByaXZhdGVDaGFubmVsQnJvYWRjYXN0QnJpZGdlUmVxdWVzdCwgUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRBZ2VudFJlcXVlc3QsIFByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQnJpZGdlUmVxdWVzdCwgUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEFnZW50UmVxdWVzdCwgUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEJyaWRnZVJlcXVlc3QsIFByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJBZ2VudFJlcXVlc3QsIFByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJCcmlkZ2VSZXF1ZXN0LCBQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEFnZW50UmVxdWVzdCwgUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RCcmlkZ2VSZXF1ZXN0LCBQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3QsIFByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUJyaWRnZVJlcXVlc3QsIFJhaXNlSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlLCBSYWlzZUludGVudEFnZW50UmVxdWVzdCwgUmFpc2VJbnRlbnRBZ2VudFJlc3BvbnNlLCBSYWlzZUludGVudEJyaWRnZUVycm9yUmVzcG9uc2UsIFJhaXNlSW50ZW50QnJpZGdlUmVxdWVzdCwgUmFpc2VJbnRlbnRCcmlkZ2VSZXNwb25zZSwgUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2UsIFJhaXNlSW50ZW50UmVzdWx0QWdlbnRSZXNwb25zZSwgUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VFcnJvclJlc3BvbnNlLCBSYWlzZUludGVudFJlc3VsdEJyaWRnZVJlc3BvbnNlLCBDb250ZXh0IH0gZnJvbSBcIi4vZmlsZVwiO1xuLy9cbi8vICAgY29uc3QgZkRDM0Rlc2t0b3BBZ2VudEFQSVNjaGVtYSA9IENvbnZlcnQudG9GREMzRGVza3RvcEFnZW50QVBJU2NoZW1hKGpzb24pO1xuLy8gICBjb25zdCBhZ2VudEVycm9yUmVzcG9uc2VNZXNzYWdlID0gQ29udmVydC50b0FnZW50RXJyb3JSZXNwb25zZU1lc3NhZ2UoanNvbik7XG4vLyAgIGNvbnN0IGFnZW50UmVxdWVzdE1lc3NhZ2UgPSBDb252ZXJ0LnRvQWdlbnRSZXF1ZXN0TWVzc2FnZShqc29uKTtcbi8vICAgY29uc3QgYWdlbnRSZXNwb25zZU1lc3NhZ2UgPSBDb252ZXJ0LnRvQWdlbnRSZXNwb25zZU1lc3NhZ2UoanNvbik7XG4vLyAgIGNvbnN0IGJyaWRnZUVycm9yUmVzcG9uc2VNZXNzYWdlID0gQ29udmVydC50b0JyaWRnZUVycm9yUmVzcG9uc2VNZXNzYWdlKGpzb24pO1xuLy8gICBjb25zdCBicmlkZ2VSZXF1ZXN0TWVzc2FnZSA9IENvbnZlcnQudG9CcmlkZ2VSZXF1ZXN0TWVzc2FnZShqc29uKTtcbi8vICAgY29uc3QgYnJpZGdlUmVzcG9uc2VNZXNzYWdlID0gQ29udmVydC50b0JyaWRnZVJlc3BvbnNlTWVzc2FnZShqc29uKTtcbi8vICAgY29uc3QgYnJvYWRjYXN0QWdlbnRSZXF1ZXN0ID0gQ29udmVydC50b0Jyb2FkY2FzdEFnZW50UmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgYnJvYWRjYXN0QnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9Ccm9hZGNhc3RCcmlkZ2VSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBicmlkZ2luZ0NvbW1vbnMgPSBDb252ZXJ0LnRvQnJpZGdpbmdDb21tb25zKGpzb24pO1xuLy8gICBjb25zdCBjb25uZWN0aW9uU3RlcE1lc3NhZ2UgPSBDb252ZXJ0LnRvQ29ubmVjdGlvblN0ZXBNZXNzYWdlKGpzb24pO1xuLy8gICBjb25zdCBjb25uZWN0aW9uU3RlcDJIZWxsbyA9IENvbnZlcnQudG9Db25uZWN0aW9uU3RlcDJIZWxsbyhqc29uKTtcbi8vICAgY29uc3QgY29ubmVjdGlvblN0ZXAzSGFuZHNoYWtlID0gQ29udmVydC50b0Nvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZShqc29uKTtcbi8vICAgY29uc3QgY29ubmVjdGlvblN0ZXA0QXV0aGVudGljYXRpb25GYWlsZWQgPSBDb252ZXJ0LnRvQ29ubmVjdGlvblN0ZXA0QXV0aGVudGljYXRpb25GYWlsZWQoanNvbik7XG4vLyAgIGNvbnN0IGNvbm5lY3Rpb25TdGVwNkNvbm5lY3RlZEFnZW50c1VwZGF0ZSA9IENvbnZlcnQudG9Db25uZWN0aW9uU3RlcDZDb25uZWN0ZWRBZ2VudHNVcGRhdGUoanNvbik7XG4vLyAgIGNvbnN0IGZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2UgPSBDb252ZXJ0LnRvRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgZmluZEluc3RhbmNlc0FnZW50UmVxdWVzdCA9IENvbnZlcnQudG9GaW5kSW5zdGFuY2VzQWdlbnRSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW5zdGFuY2VzQWdlbnRSZXNwb25zZSA9IENvbnZlcnQudG9GaW5kSW5zdGFuY2VzQWdlbnRSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgZmluZEluc3RhbmNlc0JyaWRnZUVycm9yUmVzcG9uc2UgPSBDb252ZXJ0LnRvRmluZEluc3RhbmNlc0JyaWRnZUVycm9yUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGZpbmRJbnN0YW5jZXNCcmlkZ2VSZXF1ZXN0ID0gQ29udmVydC50b0ZpbmRJbnN0YW5jZXNCcmlkZ2VSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW5zdGFuY2VzQnJpZGdlUmVzcG9uc2UgPSBDb252ZXJ0LnRvRmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGZpbmRJbnRlbnRBZ2VudFJlcXVlc3QgPSBDb252ZXJ0LnRvRmluZEludGVudEFnZW50UmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgZmluZEludGVudEFnZW50UmVzcG9uc2UgPSBDb252ZXJ0LnRvRmluZEludGVudEFnZW50UmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGZpbmRJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW50ZW50QnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9GaW5kSW50ZW50QnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgZmluZEludGVudEJyaWRnZVJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnRlbnRCcmlkZ2VSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgZmluZEludGVudHNCeUNvbnRleHRBZ2VudEVycm9yUmVzcG9uc2UgPSBDb252ZXJ0LnRvRmluZEludGVudHNCeUNvbnRleHRBZ2VudEVycm9yUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXF1ZXN0ID0gQ29udmVydC50b0ZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVzcG9uc2UgPSBDb252ZXJ0LnRvRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZUVycm9yUmVzcG9uc2UgPSBDb252ZXJ0LnRvRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlcXVlc3QgPSBDb252ZXJ0LnRvRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBmaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlc3BvbnNlID0gQ29udmVydC50b0ZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IGdldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlID0gQ29udmVydC50b0dldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBnZXRBcHBNZXRhZGF0YUFnZW50UmVxdWVzdCA9IENvbnZlcnQudG9HZXRBcHBNZXRhZGF0YUFnZW50UmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgZ2V0QXBwTWV0YWRhdGFBZ2VudFJlc3BvbnNlID0gQ29udmVydC50b0dldEFwcE1ldGFkYXRhQWdlbnRSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgZ2V0QXBwTWV0YWRhdGFCcmlkZ2VFcnJvclJlc3BvbnNlID0gQ29udmVydC50b0dldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgZ2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXF1ZXN0ID0gQ29udmVydC50b0dldEFwcE1ldGFkYXRhQnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgZ2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXNwb25zZSA9IENvbnZlcnQudG9HZXRBcHBNZXRhZGF0YUJyaWRnZVJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBvcGVuQWdlbnRFcnJvclJlc3BvbnNlID0gQ29udmVydC50b09wZW5BZ2VudEVycm9yUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IG9wZW5BZ2VudFJlcXVlc3QgPSBDb252ZXJ0LnRvT3BlbkFnZW50UmVxdWVzdChqc29uKTtcbi8vICAgY29uc3Qgb3BlbkFnZW50UmVzcG9uc2UgPSBDb252ZXJ0LnRvT3BlbkFnZW50UmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IG9wZW5CcmlkZ2VFcnJvclJlc3BvbnNlID0gQ29udmVydC50b09wZW5CcmlkZ2VFcnJvclJlc3BvbnNlKGpzb24pO1xuLy8gICBjb25zdCBvcGVuQnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9PcGVuQnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3Qgb3BlbkJyaWRnZVJlc3BvbnNlID0gQ29udmVydC50b09wZW5CcmlkZ2VSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgcHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RBZ2VudFJlcXVlc3QgPSBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RBZ2VudFJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IHByaXZhdGVDaGFubmVsQnJvYWRjYXN0QnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IHByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0ID0gQ29udmVydC50b1ByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBwcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEJyaWRnZVJlcXVlc3QgPSBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRCcmlkZ2VSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBwcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQWdlbnRSZXF1ZXN0ID0gQ29udmVydC50b1ByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRBZ2VudFJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IHByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRCcmlkZ2VSZXF1ZXN0ID0gQ29udmVydC50b1ByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRCcmlkZ2VSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBwcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0ID0gQ29udmVydC50b1ByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJBZ2VudFJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IHByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJCcmlkZ2VSZXF1ZXN0ID0gQ29udmVydC50b1ByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJCcmlkZ2VSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCBwcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEFnZW50UmVxdWVzdCA9IENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEFnZW50UmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgcHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RCcmlkZ2VSZXF1ZXN0ID0gQ29udmVydC50b1ByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QnJpZGdlUmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgcHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQWdlbnRSZXF1ZXN0ID0gQ29udmVydC50b1ByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUFnZW50UmVxdWVzdChqc29uKTtcbi8vICAgY29uc3QgcHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVCcmlkZ2VSZXF1ZXN0KGpzb24pO1xuLy8gICBjb25zdCByYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZSA9IENvbnZlcnQudG9SYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgcmFpc2VJbnRlbnRBZ2VudFJlcXVlc3QgPSBDb252ZXJ0LnRvUmFpc2VJbnRlbnRBZ2VudFJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IHJhaXNlSW50ZW50QWdlbnRSZXNwb25zZSA9IENvbnZlcnQudG9SYWlzZUludGVudEFnZW50UmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IHJhaXNlSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZSA9IENvbnZlcnQudG9SYWlzZUludGVudEJyaWRnZUVycm9yUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IHJhaXNlSW50ZW50QnJpZGdlUmVxdWVzdCA9IENvbnZlcnQudG9SYWlzZUludGVudEJyaWRnZVJlcXVlc3QoanNvbik7XG4vLyAgIGNvbnN0IHJhaXNlSW50ZW50QnJpZGdlUmVzcG9uc2UgPSBDb252ZXJ0LnRvUmFpc2VJbnRlbnRCcmlkZ2VSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgcmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2UgPSBDb252ZXJ0LnRvUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IHJhaXNlSW50ZW50UmVzdWx0QWdlbnRSZXNwb25zZSA9IENvbnZlcnQudG9SYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IHJhaXNlSW50ZW50UmVzdWx0QnJpZGdlRXJyb3JSZXNwb25zZSA9IENvbnZlcnQudG9SYWlzZUludGVudFJlc3VsdEJyaWRnZUVycm9yUmVzcG9uc2UoanNvbik7XG4vLyAgIGNvbnN0IHJhaXNlSW50ZW50UmVzdWx0QnJpZGdlUmVzcG9uc2UgPSBDb252ZXJ0LnRvUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VSZXNwb25zZShqc29uKTtcbi8vICAgY29uc3QgY29udGV4dCA9IENvbnZlcnQudG9Db250ZXh0KGpzb24pO1xuLy9cbi8vIFRoZXNlIGZ1bmN0aW9ucyB3aWxsIHRocm93IGFuIGVycm9yIGlmIHRoZSBKU09OIGRvZXNuJ3Rcbi8vIG1hdGNoIHRoZSBleHBlY3RlZCBpbnRlcmZhY2UsIGV2ZW4gaWYgdGhlIEpTT04gaXMgdmFsaWQuXG4vLyBDb252ZXJ0cyBKU09OIHN0cmluZ3MgdG8vZnJvbSB5b3VyIHR5cGVzXG4vLyBhbmQgYXNzZXJ0cyB0aGUgcmVzdWx0cyBvZiBKU09OLnBhcnNlIGF0IHJ1bnRpbWVcbnZhciBDb252ZXJ0JDEgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ29udmVydCgpIHtcbiAgICB9XG4gICAgQ29udmVydC50b0ZEQzNEZXNrdG9wQWdlbnRBUElTY2hlbWEgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIFwiYW55XCIpO1xuICAgIH07XG4gICAgQ29udmVydC5mREMzRGVza3RvcEFnZW50QVBJU2NoZW1hVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgXCJhbnlcIiksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0FnZW50RXJyb3JSZXNwb25zZU1lc3NhZ2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkFnZW50RXJyb3JSZXNwb25zZU1lc3NhZ2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5hZ2VudEVycm9yUmVzcG9uc2VNZXNzYWdlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQWdlbnRFcnJvclJlc3BvbnNlTWVzc2FnZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0FnZW50UmVxdWVzdE1lc3NhZ2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkFnZW50UmVxdWVzdE1lc3NhZ2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5hZ2VudFJlcXVlc3RNZXNzYWdlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQWdlbnRSZXF1ZXN0TWVzc2FnZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0FnZW50UmVzcG9uc2VNZXNzYWdlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJBZ2VudFJlc3BvbnNlTWVzc2FnZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmFnZW50UmVzcG9uc2VNZXNzYWdlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQWdlbnRSZXNwb25zZU1lc3NhZ2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9CcmlkZ2VFcnJvclJlc3BvbnNlTWVzc2FnZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiQnJpZGdlRXJyb3JSZXNwb25zZU1lc3NhZ2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5icmlkZ2VFcnJvclJlc3BvbnNlTWVzc2FnZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkJyaWRnZUVycm9yUmVzcG9uc2VNZXNzYWdlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQnJpZGdlUmVxdWVzdE1lc3NhZ2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkJyaWRnZVJlcXVlc3RNZXNzYWdlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuYnJpZGdlUmVxdWVzdE1lc3NhZ2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJCcmlkZ2VSZXF1ZXN0TWVzc2FnZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0JyaWRnZVJlc3BvbnNlTWVzc2FnZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiQnJpZGdlUmVzcG9uc2VNZXNzYWdlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuYnJpZGdlUmVzcG9uc2VNZXNzYWdlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQnJpZGdlUmVzcG9uc2VNZXNzYWdlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQnJvYWRjYXN0QWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJCcm9hZGNhc3RBZ2VudFJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5icm9hZGNhc3RBZ2VudFJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJCcm9hZGNhc3RBZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Ccm9hZGNhc3RCcmlkZ2VSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJCcm9hZGNhc3RCcmlkZ2VSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuYnJvYWRjYXN0QnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkJyb2FkY2FzdEJyaWRnZVJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9CcmlkZ2luZ0NvbW1vbnMgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIG0kMShcImFueVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmJyaWRnaW5nQ29tbW9uc1RvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIG0kMShcImFueVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0Nvbm5lY3Rpb25TdGVwTWVzc2FnZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiQ29ubmVjdGlvblN0ZXBNZXNzYWdlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuY29ubmVjdGlvblN0ZXBNZXNzYWdlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQ29ubmVjdGlvblN0ZXBNZXNzYWdlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQ29ubmVjdGlvblN0ZXAySGVsbG8gPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkNvbm5lY3Rpb25TdGVwMkhlbGxvXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuY29ubmVjdGlvblN0ZXAySGVsbG9Ub0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJDb25uZWN0aW9uU3RlcDJIZWxsb1wiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0Nvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiQ29ubmVjdGlvblN0ZXAzSGFuZHNoYWtlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuY29ubmVjdGlvblN0ZXAzSGFuZHNoYWtlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQ29ubmVjdGlvblN0ZXAzSGFuZHNoYWtlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQ29ubmVjdGlvblN0ZXA0QXV0aGVudGljYXRpb25GYWlsZWQgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkNvbm5lY3Rpb25TdGVwNEF1dGhlbnRpY2F0aW9uRmFpbGVkXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuY29ubmVjdGlvblN0ZXA0QXV0aGVudGljYXRpb25GYWlsZWRUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJDb25uZWN0aW9uU3RlcDRBdXRoZW50aWNhdGlvbkZhaWxlZFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0Nvbm5lY3Rpb25TdGVwNkNvbm5lY3RlZEFnZW50c1VwZGF0ZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuY29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnN0YW5jZXNBZ2VudFJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEluc3RhbmNlc0FnZW50UmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnN0YW5jZXNBZ2VudFJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZmluZEluc3RhbmNlc0FnZW50UmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnN0YW5jZXNCcmlkZ2VFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW5zdGFuY2VzQnJpZGdlRXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnN0YW5jZXNCcmlkZ2VFcnJvclJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEluc3RhbmNlc0JyaWRnZUVycm9yUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW5zdGFuY2VzQnJpZGdlUmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEluc3RhbmNlc0JyaWRnZVJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW5zdGFuY2VzQnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnN0YW5jZXNCcmlkZ2VSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW5zdGFuY2VzQnJpZGdlUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW5zdGFuY2VzQnJpZGdlUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW5zdGFuY2VzQnJpZGdlUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW50ZW50QWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW50ZW50QWdlbnRSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZmluZEludGVudEFnZW50UmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnRlbnRBZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW50ZW50QWdlbnRSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEludGVudEFnZW50UmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW50ZW50QWdlbnRSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnRlbnRBZ2VudFJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEludGVudEJyaWRnZUVycm9yUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZmluZEludGVudEJyaWRnZUVycm9yUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnRlbnRCcmlkZ2VSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW50ZW50QnJpZGdlUmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnRlbnRCcmlkZ2VSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEludGVudEJyaWRnZVJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW50ZW50QnJpZGdlUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnRlbnRCcmlkZ2VSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnRlbnRCcmlkZ2VSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnRlbnRCcmlkZ2VSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50RXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudEVycm9yUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5maW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9GaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZUVycm9yUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlRXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlRXJyb3JSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlRXJyb3JSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0ZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvR2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZ2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0dldEFwcE1ldGFkYXRhQWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmdldEFwcE1ldGFkYXRhQWdlbnRSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9HZXRBcHBNZXRhZGF0YUFnZW50UmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmdldEFwcE1ldGFkYXRhQWdlbnRSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0dldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VFcnJvclJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZ2V0QXBwTWV0YWRhdGFCcmlkZ2VFcnJvclJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VFcnJvclJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJHZXRBcHBNZXRhZGF0YUJyaWRnZVJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5nZXRBcHBNZXRhZGF0YUJyaWRnZVJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJHZXRBcHBNZXRhZGF0YUJyaWRnZVJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9HZXRBcHBNZXRhZGF0YUJyaWRnZVJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJHZXRBcHBNZXRhZGF0YUJyaWRnZVJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZ2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIkdldEFwcE1ldGFkYXRhQnJpZGdlUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9PcGVuQWdlbnRFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJPcGVuQWdlbnRFcnJvclJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQub3BlbkFnZW50RXJyb3JSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIk9wZW5BZ2VudEVycm9yUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9PcGVuQWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJPcGVuQWdlbnRSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQub3BlbkFnZW50UmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIk9wZW5BZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9PcGVuQWdlbnRSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiT3BlbkFnZW50UmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5vcGVuQWdlbnRSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIk9wZW5BZ2VudFJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvT3BlbkJyaWRnZUVycm9yUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIk9wZW5CcmlkZ2VFcnJvclJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQub3BlbkJyaWRnZUVycm9yUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJPcGVuQnJpZGdlRXJyb3JSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b09wZW5CcmlkZ2VSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJPcGVuQnJpZGdlUmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lm9wZW5CcmlkZ2VSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiT3BlbkJyaWRnZVJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9PcGVuQnJpZGdlUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIk9wZW5CcmlkZ2VSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lm9wZW5CcmlkZ2VSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIk9wZW5CcmlkZ2VSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1ByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEFnZW50UmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RBZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QnJpZGdlUmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnByaXZhdGVDaGFubmVsQnJvYWRjYXN0QnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QnJpZGdlUmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1ByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRBZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEJyaWRnZVJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQnJpZGdlUmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQnJpZGdlUmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1ByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRBZ2VudFJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRBZ2VudFJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQWdlbnRSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEFnZW50UmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1ByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRCcmlkZ2VSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQnJpZGdlUmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRCcmlkZ2VSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEJyaWRnZVJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJBZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQnJpZGdlUmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckJyaWRnZVJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJCcmlkZ2VSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QWdlbnRSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEFnZW50UmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1ByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QnJpZGdlUmVxdWVzdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RCcmlkZ2VSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RCcmlkZ2VSZXF1ZXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RCcmlkZ2VSZXF1ZXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQWdlbnRSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVCcmlkZ2VSZXF1ZXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVCcmlkZ2VSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUJyaWRnZVJlcXVlc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9SYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5yYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlJhaXNlSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUmFpc2VJbnRlbnRBZ2VudFJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlJhaXNlSW50ZW50QWdlbnRSZXF1ZXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucmFpc2VJbnRlbnRBZ2VudFJlcXVlc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJSYWlzZUludGVudEFnZW50UmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1JhaXNlSW50ZW50QWdlbnRSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUmFpc2VJbnRlbnRBZ2VudFJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucmFpc2VJbnRlbnRBZ2VudFJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUmFpc2VJbnRlbnRBZ2VudFJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUmFpc2VJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJSYWlzZUludGVudEJyaWRnZUVycm9yUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5yYWlzZUludGVudEJyaWRnZUVycm9yUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJSYWlzZUludGVudEJyaWRnZUVycm9yUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9SYWlzZUludGVudEJyaWRnZVJlcXVlc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlJhaXNlSW50ZW50QnJpZGdlUmVxdWVzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnJhaXNlSW50ZW50QnJpZGdlUmVxdWVzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlJhaXNlSW50ZW50QnJpZGdlUmVxdWVzdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1JhaXNlSW50ZW50QnJpZGdlUmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlJhaXNlSW50ZW50QnJpZGdlUmVzcG9uc2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5yYWlzZUludGVudEJyaWRnZVJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUmFpc2VJbnRlbnRCcmlkZ2VSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1JhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QkMShKU09OLnBhcnNlKGpzb24pLCByJDEoXCJSYWlzZUludGVudFJlc3VsdEFnZW50RXJyb3JSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnJhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9SYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2UgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdCQxKEpTT04ucGFyc2UoanNvbiksIHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QWdlbnRSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnJhaXNlSW50ZW50UmVzdWx0QWdlbnRSZXNwb25zZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0JDEodmFsdWUsIHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QWdlbnRSZXNwb25zZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1JhaXNlSW50ZW50UmVzdWx0QnJpZGdlRXJyb3JSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VFcnJvclJlc3BvbnNlXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQucmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VFcnJvclJlc3BvbnNlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QkMSh2YWx1ZSwgciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VFcnJvclJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VSZXNwb25zZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VSZXNwb25zZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnJhaXNlSW50ZW50UmVzdWx0QnJpZGdlUmVzcG9uc2VUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJSYWlzZUludGVudFJlc3VsdEJyaWRnZVJlc3BvbnNlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQ29udGV4dCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0JDEoSlNPTi5wYXJzZShqc29uKSwgciQxKFwiQ29udGV4dFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNvbnRleHRUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCQxKHZhbHVlLCByJDEoXCJDb250ZXh0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICByZXR1cm4gQ29udmVydDtcbn0oKSk7XG5mdW5jdGlvbiBpbnZhbGlkVmFsdWUkMSh0eXAsIHZhbCwga2V5LCBwYXJlbnQpIHtcbiAgICBpZiAocGFyZW50ID09PSB2b2lkIDApIHsgcGFyZW50ID0gJyc7IH1cbiAgICB2YXIgcHJldHR5VHlwID0gcHJldHR5VHlwZU5hbWUkMSh0eXApO1xuICAgIHZhciBwYXJlbnRUZXh0ID0gcGFyZW50ID8gXCIgb24gXCIuY29uY2F0KHBhcmVudCkgOiAnJztcbiAgICB2YXIga2V5VGV4dCA9IGtleSA/IFwiIGZvciBrZXkgXFxcIlwiLmNvbmNhdChrZXksIFwiXFxcIlwiKSA6ICcnO1xuICAgIHRocm93IEVycm9yKFwiSW52YWxpZCB2YWx1ZVwiLmNvbmNhdChrZXlUZXh0KS5jb25jYXQocGFyZW50VGV4dCwgXCIuIEV4cGVjdGVkIFwiKS5jb25jYXQocHJldHR5VHlwLCBcIiBidXQgZ290IFwiKS5jb25jYXQoSlNPTi5zdHJpbmdpZnkodmFsKSkpO1xufVxuZnVuY3Rpb24gcHJldHR5VHlwZU5hbWUkMSh0eXApIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh0eXApKSB7XG4gICAgICAgIGlmICh0eXAubGVuZ3RoID09PSAyICYmIHR5cFswXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJhbiBvcHRpb25hbCBcIi5jb25jYXQocHJldHR5VHlwZU5hbWUkMSh0eXBbMV0pKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBcIm9uZSBvZiBbXCIuY29uY2F0KHR5cC5tYXAoZnVuY3Rpb24gKGEpIHsgcmV0dXJuIHByZXR0eVR5cGVOYW1lJDEoYSk7IH0pLmpvaW4oXCIsIFwiKSwgXCJdXCIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiB0eXAgPT09IFwib2JqZWN0XCIgJiYgdHlwLmxpdGVyYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdHlwLmxpdGVyYWw7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHR5cDtcbiAgICB9XG59XG5mdW5jdGlvbiBqc29uVG9KU1Byb3BzJDEodHlwKSB7XG4gICAgaWYgKHR5cC5qc29uVG9KUyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHZhciBtYXBfMSA9IHt9O1xuICAgICAgICB0eXAucHJvcHMuZm9yRWFjaChmdW5jdGlvbiAocCkgeyByZXR1cm4gbWFwXzFbcC5qc29uXSA9IHsga2V5OiBwLmpzLCB0eXA6IHAudHlwIH07IH0pO1xuICAgICAgICB0eXAuanNvblRvSlMgPSBtYXBfMTtcbiAgICB9XG4gICAgcmV0dXJuIHR5cC5qc29uVG9KUztcbn1cbmZ1bmN0aW9uIGpzVG9KU09OUHJvcHMkMSh0eXApIHtcbiAgICBpZiAodHlwLmpzVG9KU09OID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyIG1hcF8yID0ge307XG4gICAgICAgIHR5cC5wcm9wcy5mb3JFYWNoKGZ1bmN0aW9uIChwKSB7IHJldHVybiBtYXBfMltwLmpzXSA9IHsga2V5OiBwLmpzb24sIHR5cDogcC50eXAgfTsgfSk7XG4gICAgICAgIHR5cC5qc1RvSlNPTiA9IG1hcF8yO1xuICAgIH1cbiAgICByZXR1cm4gdHlwLmpzVG9KU09OO1xufVxuZnVuY3Rpb24gdHJhbnNmb3JtJDEodmFsLCB0eXAsIGdldFByb3BzLCBrZXksIHBhcmVudCkge1xuICAgIGlmIChrZXkgPT09IHZvaWQgMCkgeyBrZXkgPSAnJzsgfVxuICAgIGlmIChwYXJlbnQgPT09IHZvaWQgMCkgeyBwYXJlbnQgPSAnJzsgfVxuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByaW1pdGl2ZSh0eXAsIHZhbCkge1xuICAgICAgICBpZiAodHlwZW9mIHR5cCA9PT0gdHlwZW9mIHZhbClcbiAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUkMSh0eXAsIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Vbmlvbih0eXBzLCB2YWwpIHtcbiAgICAgICAgLy8gdmFsIG11c3QgdmFsaWRhdGUgYWdhaW5zdCBvbmUgdHlwIGluIHR5cHNcbiAgICAgICAgdmFyIGwgPSB0eXBzLmxlbmd0aDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB0eXBfMSA9IHR5cHNbaV07XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cmFuc2Zvcm0kMSh2YWwsIHR5cF8xLCBnZXRQcm9wcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoXykgeyB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGludmFsaWRWYWx1ZSQxKHR5cHMsIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm1FbnVtKGNhc2VzLCB2YWwpIHtcbiAgICAgICAgaWYgKGNhc2VzLmluZGV4T2YodmFsKSAhPT0gLTEpXG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlJDEoY2FzZXMubWFwKGZ1bmN0aW9uIChhKSB7IHJldHVybiBsJDEoYSk7IH0pLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtQXJyYXkodHlwLCB2YWwpIHtcbiAgICAgICAgLy8gdmFsIG11c3QgYmUgYW4gYXJyYXkgd2l0aCBubyBpbnZhbGlkIGVsZW1lbnRzXG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWwpKVxuICAgICAgICAgICAgcmV0dXJuIGludmFsaWRWYWx1ZSQxKGwkMShcImFycmF5XCIpLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICAgICAgcmV0dXJuIHZhbC5tYXAoZnVuY3Rpb24gKGVsKSB7IHJldHVybiB0cmFuc2Zvcm0kMShlbCwgdHlwLCBnZXRQcm9wcyk7IH0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm1EYXRlKHZhbCkge1xuICAgICAgICBpZiAodmFsID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZCA9IG5ldyBEYXRlKHZhbCk7XG4gICAgICAgIGlmIChpc05hTihkLnZhbHVlT2YoKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUkMShsJDEoXCJEYXRlXCIpLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZDtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtT2JqZWN0KHByb3BzLCBhZGRpdGlvbmFsLCB2YWwpIHtcbiAgICAgICAgaWYgKHZhbCA9PT0gbnVsbCB8fCB0eXBlb2YgdmFsICE9PSBcIm9iamVjdFwiIHx8IEFycmF5LmlzQXJyYXkodmFsKSkge1xuICAgICAgICAgICAgcmV0dXJuIGludmFsaWRWYWx1ZSQxKGwkMShyZWYgfHwgXCJvYmplY3RcIiksIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMocHJvcHMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgdmFyIHByb3AgPSBwcm9wc1trZXldO1xuICAgICAgICAgICAgdmFyIHYgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodmFsLCBrZXkpID8gdmFsW2tleV0gOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICByZXN1bHRbcHJvcC5rZXldID0gdHJhbnNmb3JtJDEodiwgcHJvcC50eXAsIGdldFByb3BzLCBrZXksIHJlZik7XG4gICAgICAgIH0pO1xuICAgICAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh2YWwpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocHJvcHMsIGtleSkpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHRyYW5zZm9ybSQxKHZhbFtrZXldLCBhZGRpdGlvbmFsLCBnZXRQcm9wcywga2V5LCByZWYpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgaWYgKHR5cCA9PT0gXCJhbnlcIilcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICBpZiAodHlwID09PSBudWxsKSB7XG4gICAgICAgIGlmICh2YWwgPT09IG51bGwpXG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlJDEodHlwLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB9XG4gICAgaWYgKHR5cCA9PT0gZmFsc2UpXG4gICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUkMSh0eXAsIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgIHZhciByZWYgPSB1bmRlZmluZWQ7XG4gICAgd2hpbGUgKHR5cGVvZiB0eXAgPT09IFwib2JqZWN0XCIgJiYgdHlwLnJlZiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlZiA9IHR5cC5yZWY7XG4gICAgICAgIHR5cCA9IHR5cGVNYXAkMVt0eXAucmVmXTtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodHlwKSlcbiAgICAgICAgcmV0dXJuIHRyYW5zZm9ybUVudW0odHlwLCB2YWwpO1xuICAgIGlmICh0eXBlb2YgdHlwID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHJldHVybiB0eXAuaGFzT3duUHJvcGVydHkoXCJ1bmlvbk1lbWJlcnNcIikgPyB0cmFuc2Zvcm1Vbmlvbih0eXAudW5pb25NZW1iZXJzLCB2YWwpXG4gICAgICAgICAgICA6IHR5cC5oYXNPd25Qcm9wZXJ0eShcImFycmF5SXRlbXNcIikgPyB0cmFuc2Zvcm1BcnJheSh0eXAuYXJyYXlJdGVtcywgdmFsKVxuICAgICAgICAgICAgICAgIDogdHlwLmhhc093blByb3BlcnR5KFwicHJvcHNcIikgPyB0cmFuc2Zvcm1PYmplY3QoZ2V0UHJvcHModHlwKSwgdHlwLmFkZGl0aW9uYWwsIHZhbClcbiAgICAgICAgICAgICAgICAgICAgOiBpbnZhbGlkVmFsdWUkMSh0eXAsIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgIH1cbiAgICAvLyBOdW1iZXJzIGNhbiBiZSBwYXJzZWQgYnkgRGF0ZSBidXQgc2hvdWxkbid0IGJlLlxuICAgIGlmICh0eXAgPT09IERhdGUgJiYgdHlwZW9mIHZhbCAhPT0gXCJudW1iZXJcIilcbiAgICAgICAgcmV0dXJuIHRyYW5zZm9ybURhdGUodmFsKTtcbiAgICByZXR1cm4gdHJhbnNmb3JtUHJpbWl0aXZlKHR5cCwgdmFsKTtcbn1cbmZ1bmN0aW9uIGNhc3QkMSh2YWwsIHR5cCkge1xuICAgIHJldHVybiB0cmFuc2Zvcm0kMSh2YWwsIHR5cCwganNvblRvSlNQcm9wcyQxKTtcbn1cbmZ1bmN0aW9uIHVuY2FzdCQxKHZhbCwgdHlwKSB7XG4gICAgcmV0dXJuIHRyYW5zZm9ybSQxKHZhbCwgdHlwLCBqc1RvSlNPTlByb3BzJDEpO1xufVxuZnVuY3Rpb24gbCQxKHR5cCkge1xuICAgIHJldHVybiB7IGxpdGVyYWw6IHR5cCB9O1xufVxuZnVuY3Rpb24gYSQxKHR5cCkge1xuICAgIHJldHVybiB7IGFycmF5SXRlbXM6IHR5cCB9O1xufVxuZnVuY3Rpb24gdSQxKCkge1xuICAgIHZhciB0eXBzID0gW107XG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdHlwc1tfaV0gPSBhcmd1bWVudHNbX2ldO1xuICAgIH1cbiAgICByZXR1cm4geyB1bmlvbk1lbWJlcnM6IHR5cHMgfTtcbn1cbmZ1bmN0aW9uIG8kMShwcm9wcywgYWRkaXRpb25hbCkge1xuICAgIHJldHVybiB7IHByb3BzOiBwcm9wcywgYWRkaXRpb25hbDogYWRkaXRpb25hbCB9O1xufVxuZnVuY3Rpb24gbSQxKGFkZGl0aW9uYWwpIHtcbiAgICByZXR1cm4geyBwcm9wczogW10sIGFkZGl0aW9uYWw6IGFkZGl0aW9uYWwgfTtcbn1cbmZ1bmN0aW9uIHIkMShuYW1lKSB7XG4gICAgcmV0dXJuIHsgcmVmOiBuYW1lIH07XG59XG52YXIgdHlwZU1hcCQxID0ge1xuICAgIFwiQWdlbnRFcnJvclJlc3BvbnNlTWVzc2FnZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiQWdlbnRSZXNwb25zZU1ldGFkYXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJFcnJvclJlc3BvbnNlTWVzc2FnZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlJlc3BvbnNlTWVzc2FnZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJBZ2VudFJlc3BvbnNlTWV0YWRhdGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRXJyb3JSZXNwb25zZU1lc3NhZ2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkFnZW50UmVxdWVzdE1lc3NhZ2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkFnZW50UmVxdWVzdE1ldGFkYXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiBtJDEoXCJhbnlcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlJlcXVlc3RNZXNzYWdlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkFnZW50UmVxdWVzdE1ldGFkYXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkJyaWRnZVBhcnRpY2lwYW50SWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIlNvdXJjZUlkZW50aWZpZXJcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkJyaWRnZVBhcnRpY2lwYW50SWRlbnRpZmllclwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVza3RvcEFnZW50XCIsIGpzOiBcImRlc2t0b3BBZ2VudFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImFwcElkXCIsIGpzOiBcImFwcElkXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RhbmNlSWRcIiwganM6IFwiaW5zdGFuY2VJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJTb3VyY2VJZGVudGlmaWVyXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBJZFwiLCBqczogXCJhcHBJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJkZXNrdG9wQWdlbnRcIiwganM6IFwiZGVza3RvcEFnZW50XCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RhbmNlSWRcIiwganM6IFwiaW5zdGFuY2VJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJBZ2VudFJlc3BvbnNlTWVzc2FnZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiQWdlbnRSZXNwb25zZU1ldGFkYXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiBtJDEoXCJhbnlcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlJlc3BvbnNlTWVzc2FnZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJCcmlkZ2VFcnJvclJlc3BvbnNlTWVzc2FnZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiQnJpZGdlRXJyb3JSZXNwb25zZU1lc3NhZ2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJSZXNwb25zZUVycm9yTWVzc2FnZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IFwiXCIgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJCcmlkZ2VFcnJvclJlc3BvbnNlTWVzc2FnZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVza3RvcEFnZW50XCIsIGpzOiBcImRlc2t0b3BBZ2VudFwiLCB0eXA6IFwiXCIgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlJlc3BvbnNlRXJyb3JNZXNzYWdlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQnJpZGdlUmVxdWVzdE1lc3NhZ2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkJyaWRnZVJlcXVlc3RNZXRhZGF0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogbSQxKFwiYW55XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQnJpZGdlUmVxdWVzdE1ldGFkYXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkJyaWRnZVBhcnRpY2lwYW50SWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIkJyaWRnZVBhcnRpY2lwYW50SWRlbnRpZmllclwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJCcmlkZ2VSZXNwb25zZU1lc3NhZ2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkJyaWRnZVJlc3BvbnNlTWVzc2FnZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IG0kMShcImFueVwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkJyaWRnZVJlc3BvbnNlTWVzc2FnZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJlcnJvclNvdXJjZXNcIiwganM6IFwiZXJyb3JTb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlc1wiLCBqczogXCJzb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJCcm9hZGNhc3RBZ2VudFJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkJyb2FkY2FzdEFnZW50UmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkJyb2FkY2FzdEFnZW50UmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkJyb2FkY2FzdEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJCcm9hZGNhc3RBZ2VudFJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJTb3VyY2VPYmplY3RcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiU291cmNlT2JqZWN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBJZFwiLCBqczogXCJhcHBJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudFwiLCBqczogXCJkZXNrdG9wQWdlbnRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaW5zdGFuY2VJZFwiLCBqczogXCJpbnN0YW5jZUlkXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkJyb2FkY2FzdEFnZW50UmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiByJDEoXCJDb250ZXh0RWxlbWVudFwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbnRleHRFbGVtZW50XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIG0kMShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJCcm9hZGNhc3RCcmlkZ2VSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJCcm9hZGNhc3RCcmlkZ2VSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiQnJvYWRjYXN0QnJpZGdlUmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkJyb2FkY2FzdEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJCcm9hZGNhc3RCcmlkZ2VSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogciQxKFwiTWV0YVNvdXJjZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJNZXRhU291cmNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBJZFwiLCBqczogXCJhcHBJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudFwiLCBqczogXCJkZXNrdG9wQWdlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQnJvYWRjYXN0QnJpZGdlUmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiByJDEoXCJDb250ZXh0RWxlbWVudFwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwTWVzc2FnZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXBNZXRhZGF0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogbSQxKFwiYW55XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJDb25uZWN0aW9uU3RlcE1lc3NhZ2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQ29ubmVjdGlvblN0ZXBNZXRhZGF0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwMkhlbGxvXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJDb25uZWN0aW9uU3RlcDJIZWxsb01ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkNvbm5lY3Rpb25TdGVwMkhlbGxvUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXAySGVsbG9UeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQ29ubmVjdGlvblN0ZXAySGVsbG9NZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwMkhlbGxvUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXV0aFJlcXVpcmVkXCIsIGpzOiBcImF1dGhSZXF1aXJlZFwiLCB0eXA6IHRydWUgfSxcbiAgICAgICAgeyBqc29uOiBcImF1dGhUb2tlblwiLCBqczogXCJhdXRoVG9rZW5cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiZGVza3RvcEFnZW50QnJpZGdlVmVyc2lvblwiLCBqczogXCJkZXNrdG9wQWdlbnRCcmlkZ2VWZXJzaW9uXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic3VwcG9ydGVkRkRDM1ZlcnNpb25zXCIsIGpzOiBcInN1cHBvcnRlZEZEQzNWZXJzaW9uc1wiLCB0eXA6IGEkMShcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXAzSGFuZHNoYWtlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXAzSGFuZHNoYWtlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXAzSGFuZHNoYWtlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwM0hhbmRzaGFrZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW9uU3RlcDNIYW5kc2hha2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhdXRoVG9rZW5cIiwganM6IFwiYXV0aFRva2VuXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxzU3RhdGVcIiwganM6IFwiY2hhbm5lbHNTdGF0ZVwiLCB0eXA6IG0kMShhJDEociQxKFwiQ29udGV4dEVsZW1lbnRcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwiaW1wbGVtZW50YXRpb25NZXRhZGF0YVwiLCBqczogXCJpbXBsZW1lbnRhdGlvbk1ldGFkYXRhXCIsIHR5cDogciQxKFwiQ29ubmVjdGluZ0FnZW50SW1wbGVtZW50YXRpb25NZXRhZGF0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdGVkTmFtZVwiLCBqczogXCJyZXF1ZXN0ZWROYW1lXCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3RpbmdBZ2VudEltcGxlbWVudGF0aW9uTWV0YWRhdGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImZkYzNWZXJzaW9uXCIsIGpzOiBcImZkYzNWZXJzaW9uXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwib3B0aW9uYWxGZWF0dXJlc1wiLCBqczogXCJvcHRpb25hbEZlYXR1cmVzXCIsIHR5cDogciQxKFwiT3B0aW9uYWxGZWF0dXJlc1wiKSB9LFxuICAgICAgICB7IGpzb246IFwicHJvdmlkZXJcIiwganM6IFwicHJvdmlkZXJcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJwcm92aWRlclZlcnNpb25cIiwganM6IFwicHJvdmlkZXJWZXJzaW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcHRpb25hbEZlYXR1cmVzXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJEZXNrdG9wQWdlbnRCcmlkZ2luZ1wiLCBqczogXCJEZXNrdG9wQWdlbnRCcmlkZ2luZ1wiLCB0eXA6IHRydWUgfSxcbiAgICAgICAgeyBqc29uOiBcIk9yaWdpbmF0aW5nQXBwTWV0YWRhdGFcIiwganM6IFwiT3JpZ2luYXRpbmdBcHBNZXRhZGF0YVwiLCB0eXA6IHRydWUgfSxcbiAgICAgICAgeyBqc29uOiBcIlVzZXJDaGFubmVsTWVtYmVyc2hpcEFQSXNcIiwganM6IFwiVXNlckNoYW5uZWxNZW1iZXJzaGlwQVBJc1wiLCB0eXA6IHRydWUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW9uU3RlcDRBdXRoZW50aWNhdGlvbkZhaWxlZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiQ29ubmVjdGlvblN0ZXA0QXV0aGVudGljYXRpb25GYWlsZWRNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJDb25uZWN0aW9uU3RlcDRBdXRoZW50aWNhdGlvbkZhaWxlZFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkNvbm5lY3Rpb25TdGVwNEF1dGhlbnRpY2F0aW9uRmFpbGVkVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwNEF1dGhlbnRpY2F0aW9uRmFpbGVkTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW9uU3RlcDRBdXRoZW50aWNhdGlvbkZhaWxlZFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1lc3NhZ2VcIiwganM6IFwibWVzc2FnZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJDb25uZWN0aW9uU3RlcDZDb25uZWN0ZWRBZ2VudHNVcGRhdGVNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJDb25uZWN0aW9uU3RlcDZDb25uZWN0ZWRBZ2VudHNVcGRhdGVQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJDb25uZWN0aW9uU3RlcDZDb25uZWN0ZWRBZ2VudHNVcGRhdGVUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDb25uZWN0aW9uU3RlcDZDb25uZWN0ZWRBZ2VudHNVcGRhdGVQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhZGRBZ2VudFwiLCBqczogXCJhZGRBZ2VudFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJhbGxBZ2VudHNcIiwganM6IFwiYWxsQWdlbnRzXCIsIHR5cDogYSQxKHIkMShcIkRlc2t0b3BBZ2VudEltcGxlbWVudGF0aW9uTWV0YWRhdGFcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJjaGFubmVsc1N0YXRlXCIsIGpzOiBcImNoYW5uZWxzU3RhdGVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBtJDEoYSQxKHIkMShcIkNvbnRleHRFbGVtZW50XCIpKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJyZW1vdmVBZ2VudFwiLCBqczogXCJyZW1vdmVBZ2VudFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRGVza3RvcEFnZW50SW1wbGVtZW50YXRpb25NZXRhZGF0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVza3RvcEFnZW50XCIsIGpzOiBcImRlc2t0b3BBZ2VudFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImZkYzNWZXJzaW9uXCIsIGpzOiBcImZkYzNWZXJzaW9uXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwib3B0aW9uYWxGZWF0dXJlc1wiLCBqczogXCJvcHRpb25hbEZlYXR1cmVzXCIsIHR5cDogciQxKFwiT3B0aW9uYWxGZWF0dXJlc1wiKSB9LFxuICAgICAgICB7IGpzb246IFwicHJvdmlkZXJcIiwganM6IFwicHJvdmlkZXJcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJwcm92aWRlclZlcnNpb25cIiwganM6IFwicHJvdmlkZXJWZXJzaW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEluc3RhbmNlc0FnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yXCIsIGpzOiBcImVycm9yXCIsIHR5cDogciQxKFwiRXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnN0YW5jZXNBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNBZ2VudFJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkRlc3RpbmF0aW9uT2JqZWN0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiU291cmNlSWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRGVzdGluYXRpb25PYmplY3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudFwiLCBqczogXCJkZXNrdG9wQWdlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJhcHBJZFwiLCBqczogXCJhcHBJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcFwiLCBqczogXCJhcHBcIiwgdHlwOiByJDEoXCJBcHBJZGVudGlmaWVyXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQXBwSWRlbnRpZmllclwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSWRcIiwganM6IFwiYXBwSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJkZXNrdG9wQWdlbnRcIiwganM6IFwiZGVza3RvcEFnZW50XCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RhbmNlSWRcIiwganM6IFwiaW5zdGFuY2VJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJGaW5kSW5zdGFuY2VzQWdlbnRSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0FnZW50UmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEluc3RhbmNlc0FnZW50UmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNBZ2VudFJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSWRlbnRpZmllcnNcIiwganM6IFwiYXBwSWRlbnRpZmllcnNcIiwgdHlwOiBhJDEociQxKFwiQXBwTWV0YWRhdGFcIikpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQXBwTWV0YWRhdGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcElkXCIsIGpzOiBcImFwcElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiZGVzY3JpcHRpb25cIiwganM6IFwiZGVzY3JpcHRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiZGVza3RvcEFnZW50XCIsIGpzOiBcImRlc2t0b3BBZ2VudFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpY29uc1wiLCBqczogXCJpY29uc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJJY29uXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RhbmNlSWRcIiwganM6IFwiaW5zdGFuY2VJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZU1ldGFkYXRhXCIsIGpzOiBcImluc3RhbmNlTWV0YWRhdGFcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBtJDEoXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwicmVzdWx0VHlwZVwiLCBqczogXCJyZXN1bHRUeXBlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgdSQxKG51bGwsIFwiXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwic2NyZWVuc2hvdHNcIiwganM6IFwic2NyZWVuc2hvdHNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiSW1hZ2VcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwidGl0bGVcIiwganM6IFwidGl0bGVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidG9vbHRpcFwiLCBqczogXCJ0b29sdGlwXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInZlcnNpb25cIiwganM6IFwidmVyc2lvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiSWNvblwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwic2l6ZVwiLCBqczogXCJzaXplXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInNyY1wiLCBqczogXCJzcmNcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkltYWdlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJsYWJlbFwiLCBqczogXCJsYWJlbFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJzaXplXCIsIGpzOiBcInNpemVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwic3JjXCIsIGpzOiBcInNyY1wiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEluc3RhbmNlc0JyaWRnZUVycm9yUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnN0YW5jZXNCcmlkZ2VFcnJvclJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0JyaWRnZUVycm9yUmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNCcmlkZ2VFcnJvclJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JEZXRhaWxzXCIsIGpzOiBcImVycm9yRGV0YWlsc1wiLCB0eXA6IGEkMShyJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW5zdGFuY2VzQnJpZGdlRXJyb3JSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yXCIsIGpzOiBcImVycm9yXCIsIHR5cDogciQxKFwiRXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEluc3RhbmNlc0JyaWRnZVJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnN0YW5jZXNCcmlkZ2VSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEluc3RhbmNlc0JyaWRnZVJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNCcmlkZ2VSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJEZXN0aW5hdGlvbk9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIk1ldGFTb3VyY2VPYmplY3RcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiTWV0YVNvdXJjZU9iamVjdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSWRcIiwganM6IFwiYXBwSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiZGVza3RvcEFnZW50XCIsIGpzOiBcImRlc2t0b3BBZ2VudFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RhbmNlSWRcIiwganM6IFwiaW5zdGFuY2VJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJGaW5kSW5zdGFuY2VzQnJpZGdlUmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcFwiLCBqczogXCJhcHBcIiwgdHlwOiByJDEoXCJBcHBJZGVudGlmaWVyXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEluc3RhbmNlc0JyaWRnZVJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQnJpZGdlUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQnJpZGdlUmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW5zdGFuY2VzQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnN0YW5jZXNCcmlkZ2VSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJlcnJvclNvdXJjZXNcIiwganM6IFwiZXJyb3JTb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlc1wiLCBqczogXCJzb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW5zdGFuY2VzQnJpZGdlUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBJZGVudGlmaWVyc1wiLCBqczogXCJhcHBJZGVudGlmaWVyc1wiLCB0eXA6IGEkMShyJDEoXCJBcHBNZXRhZGF0YVwiKSkgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yXCIsIGpzOiBcImVycm9yXCIsIHR5cDogciQxKFwiRXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEFnZW50UmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRmluZEludGVudEFnZW50UmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50QWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRBZ2VudFJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJTb3VyY2VJZGVudGlmaWVyXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiQnJpZGdlUGFydGljaXBhbnRJZGVudGlmaWVyXCIpKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRBZ2VudFJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJDb250ZXh0RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImludGVudFwiLCBqczogXCJpbnRlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXN1bHRUeXBlXCIsIGpzOiBcInJlc3VsdFR5cGVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRBZ2VudFJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50QWdlbnRSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRBZ2VudFJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50QWdlbnRSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEFnZW50UmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBJbnRlbnRcIiwganM6IFwiYXBwSW50ZW50XCIsIHR5cDogciQxKFwiQXBwSW50ZW50XCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQXBwSW50ZW50XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBzXCIsIGpzOiBcImFwcHNcIiwgdHlwOiBhJDEociQxKFwiQXBwTWV0YWRhdGFcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRcIiwganM6IFwiaW50ZW50XCIsIHR5cDogciQxKFwiSW50ZW50TWV0YWRhdGFcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJJbnRlbnRNZXRhZGF0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGlzcGxheU5hbWVcIiwganM6IFwiZGlzcGxheU5hbWVcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEJyaWRnZUVycm9yUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEludGVudEJyaWRnZUVycm9yUmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JEZXRhaWxzXCIsIGpzOiBcImVycm9yRGV0YWlsc1wiLCB0eXA6IGEkMShyJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yXCIsIGpzOiBcImVycm9yXCIsIHR5cDogciQxKFwiRXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEJyaWRnZVJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRCcmlkZ2VSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEludGVudEJyaWRnZVJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50QWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRCcmlkZ2VSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogciQxKFwiQnJpZGdlUGFydGljaXBhbnRJZGVudGlmaWVyXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJCcmlkZ2VQYXJ0aWNpcGFudElkZW50aWZpZXJcIikpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEJyaWRnZVJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJDb250ZXh0RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImludGVudFwiLCBqczogXCJpbnRlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXN1bHRUeXBlXCIsIGpzOiBcInJlc3VsdFR5cGVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRCcmlkZ2VSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRmluZEludGVudEJyaWRnZVJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiRmluZEludGVudEJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEludGVudEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50QnJpZGdlUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvckRldGFpbHNcIiwganM6IFwiZXJyb3JEZXRhaWxzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZXNcIiwganM6IFwic291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudEJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSW50ZW50XCIsIGpzOiBcImFwcEludGVudFwiLCB0eXA6IHIkMShcIkFwcEludGVudFwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50RXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudEVycm9yUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiByJDEoXCJFcnJvck1lc3NhZ2VcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiU291cmNlT2JqZWN0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiQnJpZGdlUGFydGljaXBhbnRJZGVudGlmaWVyXCIpKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogciQxKFwiQ29udGV4dEVsZW1lbnRcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudFJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSW50ZW50c1wiLCBqczogXCJhcHBJbnRlbnRzXCIsIHR5cDogYSQxKHIkMShcIkFwcEludGVudFwiKSkgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZUVycm9yUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlRXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiByJDEoXCJFcnJvck1lc3NhZ2VcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIk1ldGFTb3VyY2VcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkJyaWRnZVBhcnRpY2lwYW50SWRlbnRpZmllclwiKSkgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiByJDEoXCJDb250ZXh0RWxlbWVudFwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkZpbmRJbnRlbnRzQnlDb250ZXh0QnJpZGdlUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiRmluZEludGVudHNCeUNvbnRleHRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRmluZEludGVudHNCeUNvbnRleHRCcmlkZ2VSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJlcnJvclNvdXJjZXNcIiwganM6IFwiZXJyb3JTb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlc1wiLCBqczogXCJzb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSW50ZW50c1wiLCBqczogXCJhcHBJbnRlbnRzXCIsIHR5cDogYSQxKHIkMShcIkFwcEludGVudFwiKSkgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yXCIsIGpzOiBcImVycm9yXCIsIHR5cDogciQxKFwiRXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiRGVzdGluYXRpb25PYmplY3RcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJTb3VyY2VJZGVudGlmaWVyXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcFwiLCBqczogXCJhcHBcIiwgdHlwOiByJDEoXCJBcHBEZXN0aW5hdGlvbklkZW50aWZpZXJcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJBcHBEZXN0aW5hdGlvbklkZW50aWZpZXJcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudFwiLCBqczogXCJkZXNrdG9wQWdlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJhcHBJZFwiLCBqczogXCJhcHBJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RhbmNlSWRcIiwganM6IFwiaW5zdGFuY2VJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUFnZW50UmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQWdlbnRSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwTWV0YWRhdGFcIiwganM6IFwiYXBwTWV0YWRhdGFcIiwgdHlwOiByJDEoXCJBcHBNZXRhZGF0YVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQnJpZGdlRXJyb3JSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VFcnJvclJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VFcnJvclJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JEZXRhaWxzXCIsIGpzOiBcImVycm9yRGV0YWlsc1wiLCB0eXA6IGEkMShyJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUJyaWRnZUVycm9yUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIkVycm9yTWVzc2FnZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQnJpZGdlUmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJEZXN0aW5hdGlvbk9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIk1ldGFTb3VyY2VPYmplY3RcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwXCIsIGpzOiBcImFwcFwiLCB0eXA6IHIkMShcIkFwcERlc3RpbmF0aW9uSWRlbnRpZmllclwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIkdldEFwcE1ldGFkYXRhQnJpZGdlUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIkdldEFwcE1ldGFkYXRhQnJpZGdlUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJHZXRBcHBNZXRhZGF0YUJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiR2V0QXBwTWV0YWRhdGFBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFCcmlkZ2VSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJlcnJvclNvdXJjZXNcIiwganM6IFwiZXJyb3JTb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlc1wiLCBqczogXCJzb3VyY2VzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIkRlc2t0b3BBZ2VudElkZW50aWZpZXJcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJHZXRBcHBNZXRhZGF0YUJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwTWV0YWRhdGFcIiwganM6IFwiYXBwTWV0YWRhdGFcIiwgdHlwOiByJDEoXCJBcHBNZXRhZGF0YVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5BZ2VudEVycm9yUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIk9wZW5BZ2VudEVycm9yUmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJPcGVuQWdlbnRFcnJvclJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiT3BlbkFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQWdlbnRFcnJvclJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQWdlbnRFcnJvclJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiByJDEoXCJPcGVuRXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkFnZW50UmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiT3BlbkFnZW50UmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIk9wZW5BZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJPcGVuQWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5BZ2VudFJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkRlc3RpbmF0aW9uT2JqZWN0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogciQxKFwiU291cmNlT2JqZWN0XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5BZ2VudFJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJhcHBcIiwganM6IFwiYXBwXCIsIHR5cDogciQxKFwiQXBwVG9PcGVuXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0XCIsIGpzOiBcImNvbnRleHRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJDb250ZXh0RWxlbWVudFwiKSkgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJBcHBUb09wZW5cIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc2t0b3BBZ2VudFwiLCBqczogXCJkZXNrdG9wQWdlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJhcHBJZFwiLCBqczogXCJhcHBJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RhbmNlSWRcIiwganM6IFwiaW5zdGFuY2VJZFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJPcGVuQWdlbnRSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiT3BlbkFnZW50UmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJPcGVuQWdlbnRSZXNwb25zZVBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIk9wZW5BZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkFnZW50UmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5BZ2VudFJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSWRlbnRpZmllclwiLCBqczogXCJhcHBJZGVudGlmaWVyXCIsIHR5cDogciQxKFwiQXBwSWRlbnRpZmllclwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5CcmlkZ2VFcnJvclJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJPcGVuQnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIk9wZW5CcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiT3BlbkFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQnJpZGdlRXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImVycm9yRGV0YWlsc1wiLCBqczogXCJlcnJvckRldGFpbHNcIiwgdHlwOiBhJDEociQxKFwiUmVzcG9uc2VFcnJvckRldGFpbFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkJyaWRnZUVycm9yUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIk9wZW5FcnJvck1lc3NhZ2VcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQnJpZGdlUmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiT3BlbkJyaWRnZVJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJPcGVuQnJpZGdlUmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIk9wZW5BZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkJyaWRnZVJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkRlc3RpbmF0aW9uT2JqZWN0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogciQxKFwiTWV0YVNvdXJjZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQnJpZGdlUmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcFwiLCBqczogXCJhcHBcIiwgdHlwOiByJDEoXCJBcHBUb09wZW5cIikgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkNvbnRleHRFbGVtZW50XCIpKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIk9wZW5CcmlkZ2VSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiT3BlbkJyaWRnZVJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiT3BlbkJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiT3BlbkFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJPcGVuQnJpZGdlUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvckRldGFpbHNcIiwganM6IFwiZXJyb3JEZXRhaWxzXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgYSQxKHIkMShcIlJlc3BvbnNlRXJyb3JEZXRhaWxcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZXNcIiwganM6IFwic291cmNlc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiT3BlbkJyaWRnZVJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwSWRlbnRpZmllclwiLCBqczogXCJhcHBJZGVudGlmaWVyXCIsIHR5cDogciQxKFwiQXBwSWRlbnRpZmllclwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEFnZW50UmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RBZ2VudFJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIk1ldGFEZXN0aW5hdGlvblwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIlNvdXJjZU9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiTWV0YURlc3RpbmF0aW9uXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXNrdG9wQWdlbnRcIiwganM6IFwiZGVza3RvcEFnZW50XCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiYXBwSWRcIiwganM6IFwiYXBwSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxCcm9hZGNhc3RBZ2VudFJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjaGFubmVsSWRcIiwganM6IFwiY2hhbm5lbElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogciQxKFwiQ29udGV4dEVsZW1lbnRcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QnJpZGdlUmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QnJpZGdlUmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsQnJvYWRjYXN0QnJpZGdlUmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiTWV0YURlc3RpbmF0aW9uXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogciQxKFwiTWV0YVNvdXJjZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEJyaWRnZVJlcXVlc3RQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjaGFubmVsSWRcIiwganM6IFwiY2hhbm5lbElkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogciQxKFwiQ29udGV4dEVsZW1lbnRcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRBZ2VudFJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJBZGRlZEFnZW50UmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJNZXRhRGVzdGluYXRpb25cIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJTb3VyY2VPYmplY3RcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY2hhbm5lbElkXCIsIGpzOiBcImNoYW5uZWxJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImxpc3RlbmVyVHlwZVwiLCBqczogXCJsaXN0ZW5lclR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJUeXBlc1wiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQnJpZGdlUmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRCcmlkZ2VSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyQWRkZWRCcmlkZ2VSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJNZXRhRGVzdGluYXRpb25cIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJNZXRhU291cmNlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQnJpZGdlUmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJsaXN0ZW5lclR5cGVcIiwganM6IFwibGlzdGVuZXJUeXBlXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyVHlwZXNcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQWdlbnRSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQWdlbnRSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEFnZW50UmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEFnZW50UmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiTWV0YURlc3RpbmF0aW9uXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiU291cmNlT2JqZWN0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQWdlbnRSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY2hhbm5lbElkXCIsIGpzOiBcImNoYW5uZWxJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImxpc3RlbmVyVHlwZVwiLCBqczogXCJsaXN0ZW5lclR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJUeXBlc1wiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRCcmlkZ2VSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQnJpZGdlUmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyUmVtb3ZlZEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQnJpZGdlUmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiTWV0YURlc3RpbmF0aW9uXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogciQxKFwiTWV0YVNvdXJjZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJSZW1vdmVkQnJpZGdlUmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJsaXN0ZW5lclR5cGVcIiwganM6IFwibGlzdGVuZXJUeXBlXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxFdmVudExpc3RlbmVyVHlwZXNcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckFnZW50UmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiTWV0YURlc3RpbmF0aW9uXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiU291cmNlT2JqZWN0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY2hhbm5lbElkXCIsIGpzOiBcImNoYW5uZWxJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRUeXBlXCIsIGpzOiBcImNvbnRleHRUeXBlXCIsIHR5cDogdSQxKG51bGwsIFwiXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckJyaWRnZVJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJCcmlkZ2VSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkFkZENvbnRleHRMaXN0ZW5lckJyaWRnZVJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJCcmlkZ2VSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCByJDEoXCJNZXRhRGVzdGluYXRpb25cIikpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJNZXRhU291cmNlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlByaXZhdGVDaGFubmVsT25BZGRDb250ZXh0TGlzdGVuZXJCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY2hhbm5lbElkXCIsIGpzOiBcImNoYW5uZWxJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRUeXBlXCIsIGpzOiBcImNvbnRleHRUeXBlXCIsIHR5cDogdSQxKG51bGwsIFwiXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25EaXNjb25uZWN0QWdlbnRSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEFnZW50UmVxdWVzdE1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImRlc3RpbmF0aW9uXCIsIGpzOiBcImRlc3RpbmF0aW9uXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiTWV0YURlc3RpbmF0aW9uXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VcIiwganM6IFwic291cmNlXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiU291cmNlT2JqZWN0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEFnZW50UmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RCcmlkZ2VSZXF1ZXN0XCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEJyaWRnZVJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEJyaWRnZVJlcXVlc3RQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbE9uRGlzY29ubmVjdEJyaWRnZVJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIk1ldGFEZXN0aW5hdGlvblwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIk1ldGFTb3VyY2VcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY2hhbm5lbElkXCIsIGpzOiBcImNoYW5uZWxJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3RcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUFnZW50UmVxdWVzdE1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUFnZW50UmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJQcml2YXRlQ2hhbm5lbE9uVW5zdWJzY3JpYmVBZ2VudFJlcXVlc3RNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIk1ldGFEZXN0aW5hdGlvblwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIlNvdXJjZU9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQWdlbnRSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiY2hhbm5lbElkXCIsIGpzOiBcImNoYW5uZWxJZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRUeXBlXCIsIGpzOiBcImNvbnRleHRUeXBlXCIsIHR5cDogdSQxKG51bGwsIFwiXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQnJpZGdlUmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiRVJlcXVlc3RNZXRhZGF0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQnJpZGdlUmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlByaXZhdGVDaGFubmVsT25VbnN1YnNjcmliZUFnZW50UmVxdWVzdFR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJFUmVxdWVzdE1ldGFkYXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkZXN0aW5hdGlvblwiLCBqczogXCJkZXN0aW5hdGlvblwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIk1ldGFEZXN0aW5hdGlvblwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIk1ldGFTb3VyY2VcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQnJpZGdlUmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNoYW5uZWxJZFwiLCBqczogXCJjaGFubmVsSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJjb250ZXh0VHlwZVwiLCBqczogXCJjb250ZXh0VHlwZVwiLCB0eXA6IHUkMShudWxsLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QWdlbnRFcnJvclJlc3BvbnNlUGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JcIiwganM6IFwiZXJyb3JcIiwgdHlwOiByJDEoXCJFcnJvck1lc3NhZ2VcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEFnZW50UmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRBZ2VudFJlcXVlc3RNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudEFnZW50UmVxdWVzdFBheWxvYWRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QWdlbnRSZXF1ZXN0VHlwZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QWdlbnRSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiByJDEoXCJNZXRhRGVzdGluYXRpb25cIikgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIlNvdXJjZU9iamVjdFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEFnZW50UmVxdWVzdFBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImFwcFwiLCBqczogXCJhcHBcIiwgdHlwOiByJDEoXCJBcHBEZXN0aW5hdGlvbklkZW50aWZpZXJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHIkMShcIkNvbnRleHRFbGVtZW50XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRcIiwganM6IFwiaW50ZW50XCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QWdlbnRSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRBZ2VudFJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRBZ2VudFJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRBZ2VudFJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEFnZW50UmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRSZXNvbHV0aW9uXCIsIGpzOiBcImludGVudFJlc29sdXRpb25cIiwgdHlwOiByJDEoXCJJbnRlbnRSZXNvbHV0aW9uXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiSW50ZW50UmVzb2x1dGlvblwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiaW50ZW50XCIsIGpzOiBcImludGVudFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInNvdXJjZVwiLCBqczogXCJzb3VyY2VcIiwgdHlwOiByJDEoXCJBcHBJZGVudGlmaWVyXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ2ZXJzaW9uXCIsIGpzOiBcInZlcnNpb25cIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QnJpZGdlRXJyb3JSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRCcmlkZ2VFcnJvclJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JEZXRhaWxzXCIsIGpzOiBcImVycm9yRGV0YWlsc1wiLCB0eXA6IGEkMShyJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEJyaWRnZUVycm9yUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIkVycm9yTWVzc2FnZVwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QnJpZGdlUmVxdWVzdFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRCcmlkZ2VSZXF1ZXN0TWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRBZ2VudFJlcXVlc3RUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRCcmlkZ2VSZXF1ZXN0TWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZGVzdGluYXRpb25cIiwganM6IFwiZGVzdGluYXRpb25cIiwgdHlwOiByJDEoXCJNZXRhRGVzdGluYXRpb25cIikgfSxcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwic291cmNlXCIsIGpzOiBcInNvdXJjZVwiLCB0eXA6IHIkMShcIk1ldGFTb3VyY2VcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRCcmlkZ2VSZXF1ZXN0UGF5bG9hZFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiYXBwXCIsIGpzOiBcImFwcFwiLCB0eXA6IHIkMShcIkFwcERlc3RpbmF0aW9uSWRlbnRpZmllclwiKSB9LFxuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogciQxKFwiQ29udGV4dEVsZW1lbnRcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImludGVudFwiLCBqczogXCJpbnRlbnRcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRCcmlkZ2VSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRCcmlkZ2VSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50QnJpZGdlUmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudEJyaWRnZVJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JEZXRhaWxzXCIsIGpzOiBcImVycm9yRGV0YWlsc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VzXCIsIGpzOiBcInNvdXJjZXNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50QnJpZGdlUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRSZXNvbHV0aW9uXCIsIGpzOiBcImludGVudFJlc29sdXRpb25cIiwgdHlwOiByJDEoXCJJbnRlbnRSZXNvbHV0aW9uXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcIm1ldGFcIiwganM6IFwibWV0YVwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QWdlbnRFcnJvclJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudFJlc3VsdEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudFJlc3VsdEFnZW50RXJyb3JSZXNwb25zZU1ldGFcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcInJlcXVlc3RVdWlkXCIsIGpzOiBcInJlcXVlc3RVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwicmVzcG9uc2VVdWlkXCIsIGpzOiBcInJlc3BvbnNlVXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVzdGFtcFwiLCBqczogXCJ0aW1lc3RhbXBcIiwgdHlwOiBEYXRlIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50UmVzdWx0RXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudFJlc3BvbnNlXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJtZXRhXCIsIGpzOiBcIm1ldGFcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2VNZXRhXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwYXlsb2FkXCIsIGpzOiBcInBheWxvYWRcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudFJlc3VsdEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudFJlc3VsdEFnZW50UmVzcG9uc2VNZXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50UmVzdWx0QWdlbnRSZXNwb25zZVBheWxvYWRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImludGVudFJlc3VsdFwiLCBqczogXCJpbnRlbnRSZXN1bHRcIiwgdHlwOiByJDEoXCJJbnRlbnRSZXN1bHRcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJJbnRlbnRSZXN1bHRcIjogbyQxKFtcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIHIkMShcIkNvbnRleHRFbGVtZW50XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiY2hhbm5lbFwiLCBqczogXCJjaGFubmVsXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiQ2hhbm5lbFwiKSkgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJDaGFubmVsXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJkaXNwbGF5TWV0YWRhdGFcIiwganM6IFwiZGlzcGxheU1ldGFkYXRhXCIsIHR5cDogdSQxKHVuZGVmaW5lZCwgciQxKFwiRGlzcGxheU1ldGFkYXRhXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiRGlzcGxheU1ldGFkYXRhXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJjb2xvclwiLCBqczogXCJjb2xvclwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJnbHlwaFwiLCBqczogXCJnbHlwaFwiLCB0eXA6IHUkMSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlRXJyb3JSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VFcnJvclJlc3BvbnNlTWV0YVwiKSB9LFxuICAgICAgICB7IGpzb246IFwicGF5bG9hZFwiLCBqczogXCJwYXlsb2FkXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VFcnJvclJlc3BvbnNlUGF5bG9hZFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VFcnJvclJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JEZXRhaWxzXCIsIGpzOiBcImVycm9yRGV0YWlsc1wiLCB0eXA6IGEkMShyJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiZXJyb3JTb3VyY2VzXCIsIGpzOiBcImVycm9yU291cmNlc1wiLCB0eXA6IGEkMShyJDEoXCJEZXNrdG9wQWdlbnRJZGVudGlmaWVyXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwicmVxdWVzdFV1aWRcIiwganM6IFwicmVxdWVzdFV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJyZXNwb25zZVV1aWRcIiwganM6IFwicmVzcG9uc2VVdWlkXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidGltZXN0YW1wXCIsIGpzOiBcInRpbWVzdGFtcFwiLCB0eXA6IERhdGUgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudFJlc3VsdEJyaWRnZUVycm9yUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJlcnJvclwiLCBqczogXCJlcnJvclwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50UmVzdWx0RXJyb3JNZXNzYWdlXCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VSZXNwb25zZVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwibWV0YVwiLCBqczogXCJtZXRhXCIsIHR5cDogciQxKFwiUmFpc2VJbnRlbnRSZXN1bHRCcmlkZ2VSZXNwb25zZU1ldGFcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBheWxvYWRcIiwganM6IFwicGF5bG9hZFwiLCB0eXA6IHIkMShcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlUmVzcG9uc2VQYXlsb2FkXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByJDEoXCJSYWlzZUludGVudFJlc3VsdEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIikgfSxcbiAgICBdLCBmYWxzZSksXG4gICAgXCJSYWlzZUludGVudFJlc3VsdEJyaWRnZVJlc3BvbnNlTWV0YVwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiZXJyb3JEZXRhaWxzXCIsIGpzOiBcImVycm9yRGV0YWlsc1wiLCB0eXA6IHUkMSh1bmRlZmluZWQsIGEkMShyJDEoXCJSZXNwb25zZUVycm9yRGV0YWlsXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImVycm9yU291cmNlc1wiLCBqczogXCJlcnJvclNvdXJjZXNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJyZXF1ZXN0VXVpZFwiLCBqczogXCJyZXF1ZXN0VXVpZFwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInJlc3BvbnNlVXVpZFwiLCBqczogXCJyZXNwb25zZVV1aWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJzb3VyY2VzXCIsIGpzOiBcInNvdXJjZXNcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBhJDEociQxKFwiRGVza3RvcEFnZW50SWRlbnRpZmllclwiKSkpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aW1lc3RhbXBcIiwganM6IFwidGltZXN0YW1wXCIsIHR5cDogRGF0ZSB9LFxuICAgIF0sIGZhbHNlKSxcbiAgICBcIlJhaXNlSW50ZW50UmVzdWx0QnJpZGdlUmVzcG9uc2VQYXlsb2FkXCI6IG8kMShbXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRSZXN1bHRcIiwganM6IFwiaW50ZW50UmVzdWx0XCIsIHR5cDogciQxKFwiSW50ZW50UmVzdWx0XCIpIH0sXG4gICAgXSwgZmFsc2UpLFxuICAgIFwiQ29udGV4dFwiOiBvJDEoW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBtJDEoXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1JDEodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiUmVzcG9uc2VFcnJvckRldGFpbFwiOiBbXG4gICAgICAgIFwiQWNjZXNzRGVuaWVkXCIsXG4gICAgICAgIFwiQWdlbnREaXNjb25uZWN0ZWRcIixcbiAgICAgICAgXCJBcHBOb3RGb3VuZFwiLFxuICAgICAgICBcIkFwcFRpbWVvdXRcIixcbiAgICAgICAgXCJDcmVhdGlvbkZhaWxlZFwiLFxuICAgICAgICBcIkRlc2t0b3BBZ2VudE5vdEZvdW5kXCIsXG4gICAgICAgIFwiRXJyb3JPbkxhdW5jaFwiLFxuICAgICAgICBcIkludGVudERlbGl2ZXJ5RmFpbGVkXCIsXG4gICAgICAgIFwiSW50ZW50SGFuZGxlclJlamVjdGVkXCIsXG4gICAgICAgIFwiTWFsZm9ybWVkQ29udGV4dFwiLFxuICAgICAgICBcIk1hbGZvcm1lZE1lc3NhZ2VcIixcbiAgICAgICAgXCJOb0FwcHNGb3VuZFwiLFxuICAgICAgICBcIk5vQ2hhbm5lbEZvdW5kXCIsXG4gICAgICAgIFwiTm9SZXN1bHRSZXR1cm5lZFwiLFxuICAgICAgICBcIk5vdENvbm5lY3RlZFRvQnJpZGdlXCIsXG4gICAgICAgIFwiUmVzb2x2ZXJUaW1lb3V0XCIsXG4gICAgICAgIFwiUmVzb2x2ZXJVbmF2YWlsYWJsZVwiLFxuICAgICAgICBcIlJlc3BvbnNlVG9CcmlkZ2VUaW1lZE91dFwiLFxuICAgICAgICBcIlRhcmdldEFwcFVuYXZhaWxhYmxlXCIsXG4gICAgICAgIFwiVGFyZ2V0SW5zdGFuY2VVbmF2YWlsYWJsZVwiLFxuICAgICAgICBcIlVzZXJDYW5jZWxsZWRSZXNvbHV0aW9uXCIsXG4gICAgXSxcbiAgICBcIlJlc3BvbnNlTWVzc2FnZVR5cGVcIjogW1xuICAgICAgICBcImZpbmRJbnN0YW5jZXNSZXNwb25zZVwiLFxuICAgICAgICBcImZpbmRJbnRlbnRSZXNwb25zZVwiLFxuICAgICAgICBcImZpbmRJbnRlbnRzQnlDb250ZXh0UmVzcG9uc2VcIixcbiAgICAgICAgXCJnZXRBcHBNZXRhZGF0YVJlc3BvbnNlXCIsXG4gICAgICAgIFwib3BlblJlc3BvbnNlXCIsXG4gICAgICAgIFwicmFpc2VJbnRlbnRSZXNwb25zZVwiLFxuICAgICAgICBcInJhaXNlSW50ZW50UmVzdWx0UmVzcG9uc2VcIixcbiAgICBdLFxuICAgIFwiUmVxdWVzdE1lc3NhZ2VUeXBlXCI6IFtcbiAgICAgICAgXCJicm9hZGNhc3RSZXF1ZXN0XCIsXG4gICAgICAgIFwiZmluZEluc3RhbmNlc1JlcXVlc3RcIixcbiAgICAgICAgXCJmaW5kSW50ZW50UmVxdWVzdFwiLFxuICAgICAgICBcImZpbmRJbnRlbnRzQnlDb250ZXh0UmVxdWVzdFwiLFxuICAgICAgICBcImdldEFwcE1ldGFkYXRhUmVxdWVzdFwiLFxuICAgICAgICBcIm9wZW5SZXF1ZXN0XCIsXG4gICAgICAgIFwiUHJpdmF0ZUNoYW5uZWwuYnJvYWRjYXN0XCIsXG4gICAgICAgIFwiUHJpdmF0ZUNoYW5uZWwuZXZlbnRMaXN0ZW5lckFkZGVkXCIsXG4gICAgICAgIFwiUHJpdmF0ZUNoYW5uZWwuZXZlbnRMaXN0ZW5lclJlbW92ZWRcIixcbiAgICAgICAgXCJQcml2YXRlQ2hhbm5lbC5vbkFkZENvbnRleHRMaXN0ZW5lclwiLFxuICAgICAgICBcIlByaXZhdGVDaGFubmVsLm9uRGlzY29ubmVjdFwiLFxuICAgICAgICBcIlByaXZhdGVDaGFubmVsLm9uVW5zdWJzY3JpYmVcIixcbiAgICAgICAgXCJyYWlzZUludGVudFJlcXVlc3RcIixcbiAgICBdLFxuICAgIFwiQnJvYWRjYXN0QWdlbnRSZXF1ZXN0VHlwZVwiOiBbXG4gICAgICAgIFwiYnJvYWRjYXN0UmVxdWVzdFwiLFxuICAgIF0sXG4gICAgXCJDb25uZWN0aW9uU3RlcE1lc3NhZ2VUeXBlXCI6IFtcbiAgICAgICAgXCJhdXRoZW50aWNhdGlvbkZhaWxlZFwiLFxuICAgICAgICBcImNvbm5lY3RlZEFnZW50c1VwZGF0ZVwiLFxuICAgICAgICBcImhhbmRzaGFrZVwiLFxuICAgICAgICBcImhlbGxvXCIsXG4gICAgXSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwMkhlbGxvVHlwZVwiOiBbXG4gICAgICAgIFwiaGVsbG9cIixcbiAgICBdLFxuICAgIFwiQ29ubmVjdGlvblN0ZXAzSGFuZHNoYWtlVHlwZVwiOiBbXG4gICAgICAgIFwiaGFuZHNoYWtlXCIsXG4gICAgXSxcbiAgICBcIkNvbm5lY3Rpb25TdGVwNEF1dGhlbnRpY2F0aW9uRmFpbGVkVHlwZVwiOiBbXG4gICAgICAgIFwiYXV0aGVudGljYXRpb25GYWlsZWRcIixcbiAgICBdLFxuICAgIFwiQ29ubmVjdGlvblN0ZXA2Q29ubmVjdGVkQWdlbnRzVXBkYXRlVHlwZVwiOiBbXG4gICAgICAgIFwiY29ubmVjdGVkQWdlbnRzVXBkYXRlXCIsXG4gICAgXSxcbiAgICBcIkVycm9yTWVzc2FnZVwiOiBbXG4gICAgICAgIFwiQWdlbnREaXNjb25uZWN0ZWRcIixcbiAgICAgICAgXCJEZXNrdG9wQWdlbnROb3RGb3VuZFwiLFxuICAgICAgICBcIkludGVudERlbGl2ZXJ5RmFpbGVkXCIsXG4gICAgICAgIFwiTWFsZm9ybWVkQ29udGV4dFwiLFxuICAgICAgICBcIk1hbGZvcm1lZE1lc3NhZ2VcIixcbiAgICAgICAgXCJOb0FwcHNGb3VuZFwiLFxuICAgICAgICBcIk5vdENvbm5lY3RlZFRvQnJpZGdlXCIsXG4gICAgICAgIFwiUmVzb2x2ZXJUaW1lb3V0XCIsXG4gICAgICAgIFwiUmVzb2x2ZXJVbmF2YWlsYWJsZVwiLFxuICAgICAgICBcIlJlc3BvbnNlVG9CcmlkZ2VUaW1lZE91dFwiLFxuICAgICAgICBcIlRhcmdldEFwcFVuYXZhaWxhYmxlXCIsXG4gICAgICAgIFwiVGFyZ2V0SW5zdGFuY2VVbmF2YWlsYWJsZVwiLFxuICAgICAgICBcIlVzZXJDYW5jZWxsZWRSZXNvbHV0aW9uXCIsXG4gICAgXSxcbiAgICBcIkZpbmRJbnN0YW5jZXNBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCI6IFtcbiAgICAgICAgXCJmaW5kSW5zdGFuY2VzUmVzcG9uc2VcIixcbiAgICBdLFxuICAgIFwiRmluZEluc3RhbmNlc0FnZW50UmVxdWVzdFR5cGVcIjogW1xuICAgICAgICBcImZpbmRJbnN0YW5jZXNSZXF1ZXN0XCIsXG4gICAgXSxcbiAgICBcIkZpbmRJbnRlbnRBZ2VudEVycm9yUmVzcG9uc2VUeXBlXCI6IFtcbiAgICAgICAgXCJmaW5kSW50ZW50UmVzcG9uc2VcIixcbiAgICBdLFxuICAgIFwiRmluZEludGVudEFnZW50UmVxdWVzdFR5cGVcIjogW1xuICAgICAgICBcImZpbmRJbnRlbnRSZXF1ZXN0XCIsXG4gICAgXSxcbiAgICBcIkZpbmRJbnRlbnRzQnlDb250ZXh0QWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiOiBbXG4gICAgICAgIFwiZmluZEludGVudHNCeUNvbnRleHRSZXNwb25zZVwiLFxuICAgIF0sXG4gICAgXCJGaW5kSW50ZW50c0J5Q29udGV4dEFnZW50UmVxdWVzdFR5cGVcIjogW1xuICAgICAgICBcImZpbmRJbnRlbnRzQnlDb250ZXh0UmVxdWVzdFwiLFxuICAgIF0sXG4gICAgXCJHZXRBcHBNZXRhZGF0YUFnZW50RXJyb3JSZXNwb25zZVR5cGVcIjogW1xuICAgICAgICBcImdldEFwcE1ldGFkYXRhUmVzcG9uc2VcIixcbiAgICBdLFxuICAgIFwiR2V0QXBwTWV0YWRhdGFBZ2VudFJlcXVlc3RUeXBlXCI6IFtcbiAgICAgICAgXCJnZXRBcHBNZXRhZGF0YVJlcXVlc3RcIixcbiAgICBdLFxuICAgIFwiT3BlbkVycm9yTWVzc2FnZVwiOiBbXG4gICAgICAgIFwiQWdlbnREaXNjb25uZWN0ZWRcIixcbiAgICAgICAgXCJBcHBOb3RGb3VuZFwiLFxuICAgICAgICBcIkFwcFRpbWVvdXRcIixcbiAgICAgICAgXCJEZXNrdG9wQWdlbnROb3RGb3VuZFwiLFxuICAgICAgICBcIkVycm9yT25MYXVuY2hcIixcbiAgICAgICAgXCJNYWxmb3JtZWRDb250ZXh0XCIsXG4gICAgICAgIFwiTWFsZm9ybWVkTWVzc2FnZVwiLFxuICAgICAgICBcIk5vdENvbm5lY3RlZFRvQnJpZGdlXCIsXG4gICAgICAgIFwiUmVzb2x2ZXJVbmF2YWlsYWJsZVwiLFxuICAgICAgICBcIlJlc3BvbnNlVG9CcmlkZ2VUaW1lZE91dFwiLFxuICAgIF0sXG4gICAgXCJPcGVuQWdlbnRFcnJvclJlc3BvbnNlVHlwZVwiOiBbXG4gICAgICAgIFwib3BlblJlc3BvbnNlXCIsXG4gICAgXSxcbiAgICBcIk9wZW5BZ2VudFJlcXVlc3RUeXBlXCI6IFtcbiAgICAgICAgXCJvcGVuUmVxdWVzdFwiLFxuICAgIF0sXG4gICAgXCJQcml2YXRlQ2hhbm5lbEJyb2FkY2FzdEFnZW50UmVxdWVzdFR5cGVcIjogW1xuICAgICAgICBcIlByaXZhdGVDaGFubmVsLmJyb2FkY2FzdFwiLFxuICAgIF0sXG4gICAgXCJQcml2YXRlQ2hhbm5lbEV2ZW50TGlzdGVuZXJUeXBlc1wiOiBbXG4gICAgICAgIFwib25BZGRDb250ZXh0TGlzdGVuZXJcIixcbiAgICAgICAgXCJvbkRpc2Nvbm5lY3RcIixcbiAgICAgICAgXCJvblVuc3Vic2NyaWJlXCIsXG4gICAgXSxcbiAgICBcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lckFkZGVkQWdlbnRSZXF1ZXN0VHlwZVwiOiBbXG4gICAgICAgIFwiUHJpdmF0ZUNoYW5uZWwuZXZlbnRMaXN0ZW5lckFkZGVkXCIsXG4gICAgXSxcbiAgICBcIlByaXZhdGVDaGFubmVsRXZlbnRMaXN0ZW5lclJlbW92ZWRBZ2VudFJlcXVlc3RUeXBlXCI6IFtcbiAgICAgICAgXCJQcml2YXRlQ2hhbm5lbC5ldmVudExpc3RlbmVyUmVtb3ZlZFwiLFxuICAgIF0sXG4gICAgXCJQcml2YXRlQ2hhbm5lbE9uQWRkQ29udGV4dExpc3RlbmVyQWdlbnRSZXF1ZXN0VHlwZVwiOiBbXG4gICAgICAgIFwiUHJpdmF0ZUNoYW5uZWwub25BZGRDb250ZXh0TGlzdGVuZXJcIixcbiAgICBdLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPbkRpc2Nvbm5lY3RBZ2VudFJlcXVlc3RUeXBlXCI6IFtcbiAgICAgICAgXCJQcml2YXRlQ2hhbm5lbC5vbkRpc2Nvbm5lY3RcIixcbiAgICBdLFxuICAgIFwiUHJpdmF0ZUNoYW5uZWxPblVuc3Vic2NyaWJlQWdlbnRSZXF1ZXN0VHlwZVwiOiBbXG4gICAgICAgIFwiUHJpdmF0ZUNoYW5uZWwub25VbnN1YnNjcmliZVwiLFxuICAgIF0sXG4gICAgXCJSYWlzZUludGVudEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIjogW1xuICAgICAgICBcInJhaXNlSW50ZW50UmVzcG9uc2VcIixcbiAgICBdLFxuICAgIFwiUmFpc2VJbnRlbnRBZ2VudFJlcXVlc3RUeXBlXCI6IFtcbiAgICAgICAgXCJyYWlzZUludGVudFJlcXVlc3RcIixcbiAgICBdLFxuICAgIFwiUmFpc2VJbnRlbnRSZXN1bHRFcnJvck1lc3NhZ2VcIjogW1xuICAgICAgICBcIkFnZW50RGlzY29ubmVjdGVkXCIsXG4gICAgICAgIFwiSW50ZW50SGFuZGxlclJlamVjdGVkXCIsXG4gICAgICAgIFwiTWFsZm9ybWVkTWVzc2FnZVwiLFxuICAgICAgICBcIk5vUmVzdWx0UmV0dXJuZWRcIixcbiAgICAgICAgXCJOb3RDb25uZWN0ZWRUb0JyaWRnZVwiLFxuICAgICAgICBcIlJlc3BvbnNlVG9CcmlkZ2VUaW1lZE91dFwiLFxuICAgIF0sXG4gICAgXCJSYWlzZUludGVudFJlc3VsdEFnZW50RXJyb3JSZXNwb25zZVR5cGVcIjogW1xuICAgICAgICBcInJhaXNlSW50ZW50UmVzdWx0UmVzcG9uc2VcIixcbiAgICBdLFxuICAgIFwiVHlwZVwiOiBbXG4gICAgICAgIFwiYXBwXCIsXG4gICAgICAgIFwicHJpdmF0ZVwiLFxuICAgICAgICBcInVzZXJcIixcbiAgICBdXG59O1xuXG52YXIgQnJpZGdpbmdUeXBlcyA9IHtcbiAgICBfX3Byb3RvX186IG51bGwsXG4gICAgQ29udmVydDogQ29udmVydCQxXG59O1xuXG4vKipcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKiBDb3B5cmlnaHQgRklOT1MgRkRDMyBjb250cmlidXRvcnMgLSBzZWUgTk9USUNFIGZpbGVcbiAqL1xuLyoqIENvbnN0YW50cyByZXByZXNlbnRpbmcgdGhlIGVycm9ycyB0aGF0IGNhbiBiZSBlbmNvdW50ZXJlZCB3aGVuIGNhbGxpbmcgdGhlIGBvcGVuYCBtZXRob2Qgb24gdGhlIERlc2t0b3BBZ2VudCBvYmplY3QgKGBmZGMzYCkuICovXG52YXIgT3BlbkVycm9yO1xuKGZ1bmN0aW9uIChPcGVuRXJyb3IpIHtcbiAgICAvKiogUmV0dXJuZWQgaWYgdGhlIHNwZWNpZmllZCBhcHBsaWNhdGlvbiBpcyBub3QgZm91bmQuKi9cbiAgICBPcGVuRXJyb3JbXCJBcHBOb3RGb3VuZFwiXSA9IFwiQXBwTm90Rm91bmRcIjtcbiAgICAvKiogUmV0dXJuZWQgaWYgdGhlIHNwZWNpZmllZCBhcHBsaWNhdGlvbiBmYWlscyB0byBsYXVuY2ggY29ycmVjdGx5LiovXG4gICAgT3BlbkVycm9yW1wiRXJyb3JPbkxhdW5jaFwiXSA9IFwiRXJyb3JPbkxhdW5jaFwiO1xuICAgIC8qKiBSZXR1cm5lZCBpZiB0aGUgc3BlY2lmaWVkIGFwcGxpY2F0aW9uIGxhdW5jaGVzIGJ1dCBmYWlscyB0byBhZGQgYSBjb250ZXh0IGxpc3RlbmVyIGluIG9yZGVyIHRvIHJlY2VpdmUgdGhlIGNvbnRleHQgcGFzc2VkIHRvIHRoZSBgZmRjMy5vcGVuYCBjYWxsLiovXG4gICAgT3BlbkVycm9yW1wiQXBwVGltZW91dFwiXSA9IFwiQXBwVGltZW91dFwiO1xuICAgIC8qKiBSZXR1cm5lZCBpZiB0aGUgRkRDMyBkZXNrdG9wIGFnZW50IGltcGxlbWVudGF0aW9uIGlzIG5vdCBjdXJyZW50bHkgYWJsZSB0byBoYW5kbGUgdGhlIHJlcXVlc3QuKi9cbiAgICBPcGVuRXJyb3JbXCJSZXNvbHZlclVuYXZhaWxhYmxlXCJdID0gXCJSZXNvbHZlclVuYXZhaWxhYmxlXCI7XG4gICAgLyoqIFJldHVybmVkIGlmIGEgY2FsbCB0byB0aGUgYG9wZW5gIGZ1bmN0aW9uIGlzIG1hZGUgd2l0aCBhbiBpbnZhbGlkIGNvbnRleHQgYXJndW1lbnQuIENvbnRleHRzIHNob3VsZCBiZSBPYmplY3RzIHdpdGggYXQgbGVhc3QgYSBgdHlwZWAgZmllbGQgdGhhdCBoYXMgYSBgc3RyaW5nYCB2YWx1ZS4qL1xuICAgIE9wZW5FcnJvcltcIk1hbGZvcm1lZENvbnRleHRcIl0gPSBcIk1hbGZvcm1lZENvbnRleHRcIjtcbiAgICAvKiogQGV4cGVyaW1lbnRhbCBSZXR1cm5lZCBpZiB0aGUgc3BlY2lmaWVkIERlc2t0b3AgQWdlbnQgaXMgbm90IGZvdW5kLCB2aWEgYSBjb25uZWN0ZWQgRGVza3RvcCBBZ2VudCBCcmlkZ2UuKi9cbiAgICBPcGVuRXJyb3JbXCJEZXNrdG9wQWdlbnROb3RGb3VuZFwiXSA9IFwiRGVza3RvcEFnZW50Tm90Rm91bmRcIjtcbn0pKE9wZW5FcnJvciB8fCAoT3BlbkVycm9yID0ge30pKTtcbi8qKiBDb25zdGFudHMgcmVwcmVzZW50aW5nIHRoZSBlcnJvcnMgdGhhdCBjYW4gYmUgZW5jb3VudGVyZWQgd2hlbiBjYWxsaW5nIHRoZSBgZmluZEludGVudGAsIGBmaW5kSW50ZW50c0J5Q29udGV4dGAsIGByYWlzZUludGVudGAgb3IgYHJhaXNlSW50ZW50Rm9yQ29udGV4dGAgbWV0aG9kcyBvbiB0aGUgRGVza3RvcEFnZW50IChgZmRjM2ApLiAqL1xudmFyIFJlc29sdmVFcnJvcjtcbihmdW5jdGlvbiAoUmVzb2x2ZUVycm9yKSB7XG4gICAgLyoqIFNIT1VMRCBiZSByZXR1cm5lZCBpZiBubyBhcHBzIGFyZSBhdmFpbGFibGUgdGhhdCBjYW4gcmVzb2x2ZSB0aGUgaW50ZW50IGFuZCBjb250ZXh0IGNvbWJpbmF0aW9uLiovXG4gICAgUmVzb2x2ZUVycm9yW1wiTm9BcHBzRm91bmRcIl0gPSBcIk5vQXBwc0ZvdW5kXCI7XG4gICAgLyoqIFJldHVybmVkIGlmIHRoZSBGREMzIGRlc2t0b3AgYWdlbnQgaW1wbGVtZW50YXRpb24gaXMgbm90IGN1cnJlbnRseSBhYmxlIHRvIGhhbmRsZSB0aGUgcmVxdWVzdC4qL1xuICAgIFJlc29sdmVFcnJvcltcIlJlc29sdmVyVW5hdmFpbGFibGVcIl0gPSBcIlJlc29sdmVyVW5hdmFpbGFibGVcIjtcbiAgICAvKiogUmV0dXJuZWQgaWYgdGhlIHVzZXIgY2FuY2VsbGVkIHRoZSByZXNvbHV0aW9uIHJlcXVlc3QsIGZvciBleGFtcGxlIGJ5IGNsb3Npbmcgb3IgY2FuY2VsbGluZyBhIHJlc29sdmVyIFVJLiovXG4gICAgUmVzb2x2ZUVycm9yW1wiVXNlckNhbmNlbGxlZFwiXSA9IFwiVXNlckNhbmNlbGxlZFJlc29sdXRpb25cIjtcbiAgICAvKiogU0hPVUxEIGJlIHJldHVybmVkIGlmIGEgdGltZW91dCBjYW5jZWxzIGFuIGludGVudCByZXNvbHV0aW9uIHRoYXQgcmVxdWlyZWQgdXNlciBpbnRlcmFjdGlvbi4gUGxlYXNlIHVzZSBgUmVzb2x2ZXJVbmF2YWlsYWJsZWAgaW5zdGVhZCBmb3Igc2l0dWF0aW9ucyB3aGVyZSBhIHJlc29sdmVyIFVJIG9yIHNpbWlsYXIgZmFpbHMuKi9cbiAgICBSZXNvbHZlRXJyb3JbXCJSZXNvbHZlclRpbWVvdXRcIl0gPSBcIlJlc29sdmVyVGltZW91dFwiO1xuICAgIC8qKiBSZXR1cm5lZCBpZiBhIHNwZWNpZmllZCB0YXJnZXQgYXBwbGljYXRpb24gaXMgbm90IGF2YWlsYWJsZSBvciBhIG5ldyBpbnN0YW5jZSBvZiBpdCBjYW5ub3QgYmUgb3BlbmVkLiAqL1xuICAgIFJlc29sdmVFcnJvcltcIlRhcmdldEFwcFVuYXZhaWxhYmxlXCJdID0gXCJUYXJnZXRBcHBVbmF2YWlsYWJsZVwiO1xuICAgIC8qKiBSZXR1cm5lZCBpZiBhIHNwZWNpZmllZCB0YXJnZXQgYXBwbGljYXRpb24gaW5zdGFuY2UgaXMgbm90IGF2YWlsYWJsZSwgZm9yIGV4YW1wbGUgYmVjYXVzZSBpdCBoYXMgYmVlbiBjbG9zZWQuICovXG4gICAgUmVzb2x2ZUVycm9yW1wiVGFyZ2V0SW5zdGFuY2VVbmF2YWlsYWJsZVwiXSA9IFwiVGFyZ2V0SW5zdGFuY2VVbmF2YWlsYWJsZVwiO1xuICAgIC8qKiBSZXR1cm5lZCBpZiB0aGUgaW50ZW50IGFuZCBjb250ZXh0IGNvdWxkIG5vdCBiZSBkZWxpdmVyZWQgdG8gdGhlIHNlbGVjdGVkIGFwcGxpY2F0aW9uIG9yIGluc3RhbmNlLCBmb3IgZXhhbXBsZSBiZWNhdXNlIGl0IGhhcyBub3QgYWRkZWQgYW4gaW50ZW50IGhhbmRsZXIgd2l0aGluIGEgdGltZW91dC4qL1xuICAgIFJlc29sdmVFcnJvcltcIkludGVudERlbGl2ZXJ5RmFpbGVkXCJdID0gXCJJbnRlbnREZWxpdmVyeUZhaWxlZFwiO1xuICAgIC8qKiBSZXR1cm5lZCBpZiBhIGNhbGwgdG8gb25lIG9mIHRoZSBgcmFpc2VJbnRlbnRgIGZ1bmN0aW9ucyBpcyBtYWRlIHdpdGggYW4gaW52YWxpZCBjb250ZXh0IGFyZ3VtZW50LiBDb250ZXh0cyBzaG91bGQgYmUgT2JqZWN0cyB3aXRoIGF0IGxlYXN0IGEgYHR5cGVgIGZpZWxkIHRoYXQgaGFzIGEgYHN0cmluZ2AgdmFsdWUuKi9cbiAgICBSZXNvbHZlRXJyb3JbXCJNYWxmb3JtZWRDb250ZXh0XCJdID0gXCJNYWxmb3JtZWRDb250ZXh0XCI7XG4gICAgLyoqIEBleHBlcmltZW50YWwgUmV0dXJuZWQgaWYgdGhlIHNwZWNpZmllZCBEZXNrdG9wIEFnZW50IGlzIG5vdCBmb3VuZCwgdmlhIGEgY29ubmVjdGVkIERlc2t0b3AgQWdlbnQgQnJpZGdlLiovXG4gICAgUmVzb2x2ZUVycm9yW1wiRGVza3RvcEFnZW50Tm90Rm91bmRcIl0gPSBcIkRlc2t0b3BBZ2VudE5vdEZvdW5kXCI7XG59KShSZXNvbHZlRXJyb3IgfHwgKFJlc29sdmVFcnJvciA9IHt9KSk7XG52YXIgUmVzdWx0RXJyb3I7XG4oZnVuY3Rpb24gKFJlc3VsdEVycm9yKSB7XG4gICAgLyoqIFJldHVybmVkIGlmIHRoZSBpbnRlbnQgaGFuZGxlciBleGl0ZWQgd2l0aG91dCByZXR1cm5pbmcgYSB2YWxpZCByZXN1bHQgKGEgcHJvbWlzZSByZXNvbHZpbmcgdG8gYSBDb250ZXh0LCBDaGFubmVsIG9iamVjdCBvciB2b2lkKS4gKi9cbiAgICBSZXN1bHRFcnJvcltcIk5vUmVzdWx0UmV0dXJuZWRcIl0gPSBcIk5vUmVzdWx0UmV0dXJuZWRcIjtcbiAgICAvKiogUmV0dXJuZWQgaWYgdGhlIEludGVudCBoYW5kbGVyIGZ1bmN0aW9uIHByb2Nlc3NpbmcgdGhlIHJhaXNlZCBpbnRlbnQgdGhyb3dzIGFuIGVycm9yIG9yIHJlamVjdHMgdGhlIFByb21pc2UgaXQgcmV0dXJuZWQuICovXG4gICAgUmVzdWx0RXJyb3JbXCJJbnRlbnRIYW5kbGVyUmVqZWN0ZWRcIl0gPSBcIkludGVudEhhbmRsZXJSZWplY3RlZFwiO1xufSkoUmVzdWx0RXJyb3IgfHwgKFJlc3VsdEVycm9yID0ge30pKTtcbnZhciBDaGFubmVsRXJyb3I7XG4oZnVuY3Rpb24gKENoYW5uZWxFcnJvcikge1xuICAgIC8qKiBSZXR1cm5lZCBpZiB0aGUgc3BlY2lmaWVkIGNoYW5uZWwgaXMgbm90IGZvdW5kIHdoZW4gYXR0ZW1wdGluZyB0byBqb2luIGEgY2hhbm5lbCB2aWEgdGhlIGBqb2luVXNlckNoYW5uZWxgIGZ1bmN0aW9uICBvZiB0aGUgRGVza3RvcEFnZW50IChgZmRjM2ApLiovXG4gICAgQ2hhbm5lbEVycm9yW1wiTm9DaGFubmVsRm91bmRcIl0gPSBcIk5vQ2hhbm5lbEZvdW5kXCI7XG4gICAgLyoqIFNIT1VMRCBiZSByZXR1cm5lZCB3aGVuIGEgcmVxdWVzdCB0byBqb2luIGEgdXNlciBjaGFubmVsIG9yIHRvIGEgcmV0cmlldmUgYSBDaGFubmVsIG9iamVjdCB2aWEgdGhlIGBqb2luVXNlckNoYW5uZWxgIG9yIGBnZXRPckNyZWF0ZUNoYW5uZWxgIG1ldGhvZHMgb2YgdGhlIERlc2t0b3BBZ2VudCAoYGZkYzNgKSBvYmplY3QgaXMgZGVuaWVkLiAqL1xuICAgIENoYW5uZWxFcnJvcltcIkFjY2Vzc0RlbmllZFwiXSA9IFwiQWNjZXNzRGVuaWVkXCI7XG4gICAgLyoqIFNIT1VMRCBiZSByZXR1cm5lZCB3aGVuIGEgY2hhbm5lbCBjYW5ub3QgYmUgY3JlYXRlZCBvciByZXRyaWV2ZWQgdmlhIHRoZSBgZ2V0T3JDcmVhdGVDaGFubmVsYCBtZXRob2Qgb2YgdGhlIERlc2t0b3BBZ2VudCAoYGZkYzNgKS4qL1xuICAgIENoYW5uZWxFcnJvcltcIkNyZWF0aW9uRmFpbGVkXCJdID0gXCJDcmVhdGlvbkZhaWxlZFwiO1xuICAgIC8qKiBSZXR1cm5lZCBpZiBhIGNhbGwgdG8gdGhlIGBicm9hZGNhc3RgIGZ1bmN0aW9ucyBpcyBtYWRlIHdpdGggYW4gaW52YWxpZCBjb250ZXh0IGFyZ3VtZW50LiBDb250ZXh0cyBzaG91bGQgYmUgT2JqZWN0cyB3aXRoIGF0IGxlYXN0IGEgYHR5cGVgIGZpZWxkIHRoYXQgaGFzIGEgYHN0cmluZ2AgdmFsdWUuKi9cbiAgICBDaGFubmVsRXJyb3JbXCJNYWxmb3JtZWRDb250ZXh0XCJdID0gXCJNYWxmb3JtZWRDb250ZXh0XCI7XG59KShDaGFubmVsRXJyb3IgfHwgKENoYW5uZWxFcnJvciA9IHt9KSk7XG52YXIgQnJpZGdpbmdFcnJvcjtcbihmdW5jdGlvbiAoQnJpZGdpbmdFcnJvcikge1xuICAgIC8qKiBAZXhwZXJpbWVudGFsIFJldHVybmVkIGlmIGEgRGVza3RvcCBBZ2VudCBkaWQgbm90IHJldHVybiBhIHJlc3BvbnNlLCB2aWEgRGVza3RvcCBBZ2VudCBCcmlkZ2luZywgd2l0aGluIHRoZSBhbGxvdGVkIHRpbWVvdXQuICovXG4gICAgQnJpZGdpbmdFcnJvcltcIlJlc3BvbnNlVGltZWRPdXRcIl0gPSBcIlJlc3BvbnNlVG9CcmlkZ2VUaW1lZE91dFwiO1xuICAgIC8qKiBAZXhwZXJpbWVudGFsIFJldHVybmVkIGlmIGEgRGVza3RvcCBBZ2VudCB0aGF0IGhhcyBiZWVuIHRhcmdldGVkIGJ5IGEgcGFydGljdWxhciByZXF1ZXN0IGhhcyBiZWVuIGRpc2Nvbm5lY3RlZCBmcm9tIHRoZSBCcmlkZ2UgYmVmb3JlIGEgcmVzcG9uc2UgaGFzIGJlZW4gcmVjZWl2ZWQgZnJvbSBpdC4gKi9cbiAgICBCcmlkZ2luZ0Vycm9yW1wiQWdlbnREaXNjb25uZWN0ZWRcIl0gPSBcIkFnZW50RGlzY29ubmVjdGVkXCI7XG4gICAgLyoqIEBleHBlcmltZW50YWwgUmV0dXJuZWQgZm9yIEZEQzMgQVBJIGNhbGxzIHRoYXQgYXJlIHNwZWNpZmllZCB3aXRoIGFyZ3VtZW50cyBpbmRpY2F0aW5nIHRoYXQgYSByZW1vdGUgRGVza3RvcCBhZ2VudCBzaG91bGQgYmUgdGFyZ2V0ZWQgKGUuZy4gcmFpc2VJbnRlbnQgd2l0aCBhbiBhcHAgb24gYSByZW1vdGUgRGVza3RvcEFnZW50IHRhcmdldGVkKSwgd2hlbiB0aGUgbG9jYWwgRGVza3RvcCBBZ2VudCBpcyBub3QgY29ubmVjdGVkIHRvIGEgYnJpZGdlLiAqL1xuICAgIEJyaWRnaW5nRXJyb3JbXCJOb3RDb25uZWN0ZWRUb0JyaWRnZVwiXSA9IFwiTm90Q29ubmVjdGVkVG9CcmlkZ2VcIjtcbiAgICAvKiogQGV4cGVyaW1lbnRhbCBSZXR1cm5lZCBpZiBhIG1lc3NhZ2UgdG8gYSBCcmlkZ2UgZGV2aWF0ZXMgZnJvbSB0aGUgc2NoZW1hIGZvciB0aGF0IG1lc3NhZ2Ugc3VmZmljaWVudGx5IHRoYXQgaXQgY291bGQgbm90IGJlIHByb2Nlc3NlZC4gKi9cbiAgICBCcmlkZ2luZ0Vycm9yW1wiTWFsZm9ybWVkTWVzc2FnZVwiXSA9IFwiTWFsZm9ybWVkTWVzc2FnZVwiO1xufSkoQnJpZGdpbmdFcnJvciB8fCAoQnJpZGdpbmdFcnJvciA9IHt9KSk7XG5cbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uXHJcblxyXG5QZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnlcclxucHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLlxyXG5cclxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSFxyXG5SRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFlcclxuQU5EIEZJVE5FU1MuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgRElSRUNULFxyXG5JTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST01cclxuTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1JcclxuT1RIRVIgVE9SVElPVVMgQUNUSU9OLCBBUklTSU5HIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUlxyXG5QRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSwgU3VwcHJlc3NlZEVycm9yLCBTeW1ib2wgKi9cclxuXHJcblxyXG5mdW5jdGlvbiBfX2F3YWl0ZXIodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cclxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxyXG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBfX2dlbmVyYXRvcih0aGlzQXJnLCBib2R5KSB7XHJcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xyXG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG50eXBlb2YgU3VwcHJlc3NlZEVycm9yID09PSBcImZ1bmN0aW9uXCIgPyBTdXBwcmVzc2VkRXJyb3IgOiBmdW5jdGlvbiAoZXJyb3IsIHN1cHByZXNzZWQsIG1lc3NhZ2UpIHtcclxuICAgIHZhciBlID0gbmV3IEVycm9yKG1lc3NhZ2UpO1xyXG4gICAgcmV0dXJuIGUubmFtZSA9IFwiU3VwcHJlc3NlZEVycm9yXCIsIGUuZXJyb3IgPSBlcnJvciwgZS5zdXBwcmVzc2VkID0gc3VwcHJlc3NlZCwgZTtcclxufTtcblxuLyoqXG4gKiBFbnN1cmVzIGF0IGNvbXBpbGUgdGltZSB0aGF0IHRoZSBnaXZlbiBzdHJpbmcgdHVwbGUgaXMgZXhoYXVzdGl2ZSBvbiBhIGdpdmVuIHVuaW9uIHR5cGUsIGkuZS4gY29udGFpbnMgQUxMIHBvc3NpYmxlIHZhbHVlcyBvZiB0aGUgZ2l2ZW4gVU5JT05fVFlQRS5cbiAqL1xudmFyIGV4aGF1c3RpdmVTdHJpbmdUdXBsZSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgdHVwbGUgPSBbXTtcbiAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgYXJndW1lbnRzLmxlbmd0aDsgX2krKykge1xuICAgICAgICB0dXBsZVtfaV0gPSBhcmd1bWVudHNbX2ldO1xuICAgIH1cbiAgICByZXR1cm4gdHVwbGU7XG59OyB9O1xuXG52YXIgU1RBTkRBUkRfQ09OVEVYVF9UWVBFUyA9IGV4aGF1c3RpdmVTdHJpbmdUdXBsZSgpKCdmZGMzLmFjdGlvbicsICdmZGMzLmNoYXJ0JywgJ2ZkYzMuY2hhdC5pbml0U2V0dGluZ3MnLCAnZmRjMy5jaGF0Lm1lc3NhZ2UnLCAnZmRjMy5jaGF0LnJvb20nLCAnZmRjMy5jaGF0LnNlYXJjaENyaXRlcmlhJywgJ2ZkYzMuY29udGFjdCcsICdmZGMzLmNvbnRhY3RMaXN0JywgJ2ZkYzMuY291bnRyeScsICdmZGMzLmN1cnJlbmN5JywgJ2ZkYzMuZW1haWwnLCAnZmRjMy5pbnN0cnVtZW50JywgJ2ZkYzMuaW5zdHJ1bWVudExpc3QnLCAnZmRjMy5pbnRlcmFjdGlvbicsICdmZGMzLm1lc3NhZ2UnLCAnZmRjMy5vcmdhbml6YXRpb24nLCAnZmRjMy5wb3J0Zm9saW8nLCAnZmRjMy5wb3NpdGlvbicsICdmZGMzLm5vdGhpbmcnLCAnZmRjMy50aW1lUmFuZ2UnLCAnZmRjMy50cmFuc2FjdGlvblJlc3VsdCcsICdmZGMzLnZhbHVhdGlvbicpO1xuLy8gdXNlZCBpbnRlcm5hbGx5IHRvIGNoZWNrIGlmIGEgZ2l2ZW4gaW50ZW50L2NvbnRleHQgaXMgYSBzdGFuZGFyZCBvbmVcbnZhciBTdGFuZGFyZENvbnRleHRzU2V0ID0gbmV3IFNldChTVEFOREFSRF9DT05URVhUX1RZUEVTKTtcblxudmFyIFNUQU5EQVJEX0lOVEVOVFMgPSBleGhhdXN0aXZlU3RyaW5nVHVwbGUoKSgnQ3JlYXRlSW50ZXJhY3Rpb24nLCAnU2VuZENoYXRNZXNzYWdlJywgJ1N0YXJ0Q2FsbCcsICdTdGFydENoYXQnLCAnU3RhcnRFbWFpbCcsICdWaWV3QW5hbHlzaXMnLCAnVmlld0NoYXQnLCAnVmlld0NoYXJ0JywgJ1ZpZXdDb250YWN0JywgJ1ZpZXdIb2xkaW5ncycsICdWaWV3SW5zdHJ1bWVudCcsICdWaWV3SW50ZXJhY3Rpb25zJywgJ1ZpZXdNZXNzYWdlcycsICdWaWV3TmV3cycsICdWaWV3T3JkZXJzJywgJ1ZpZXdQcm9maWxlJywgJ1ZpZXdRdW90ZScsICdWaWV3UmVzZWFyY2gnKTtcbi8vIHVzZWQgaW50ZXJuYWxseSB0byBjaGVjayBpZiBhIGdpdmVuIGludGVudC9jb250ZXh0IGlzIGEgc3RhbmRhcmQgb25lXG52YXIgU3RhbmRhcmRJbnRlbnRzU2V0ID0gbmV3IFNldChTVEFOREFSRF9JTlRFTlRTKTtcblxudmFyIERFRkFVTFRfVElNRU9VVCA9IDUwMDA7XG52YXIgVW5hdmFpbGFibGVFcnJvciA9IG5ldyBFcnJvcignRkRDMyBEZXNrdG9wQWdlbnQgbm90IGF2YWlsYWJsZSBhdCBgd2luZG93LmZkYzNgLicpO1xudmFyIFRpbWVvdXRFcnJvciA9IG5ldyBFcnJvcignVGltZWQgb3V0IHdhaXRpbmcgZm9yIGBmZGMzUmVhZHlgIGV2ZW50LicpO1xudmFyIFVuZXhwZWN0ZWRFcnJvciA9IG5ldyBFcnJvcignYGZkYzNSZWFkeWAgZXZlbnQgZmlyZWQsIGJ1dCBgd2luZG93LmZkYzNgIG5vdCBzZXQgdG8gRGVza3RvcEFnZW50LicpO1xuZnVuY3Rpb24gcmVqZWN0SWZOb0dsb2JhbChmKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5mZGMzID8gZigpIDogUHJvbWlzZS5yZWplY3QoVW5hdmFpbGFibGVFcnJvcik7XG59XG4vKipcbiAqIFV0aWxpdHkgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHdpbGwgcmVzb2x2ZSBpbW1lYWRpYXRlbHlcbiAqIGlmIHRoZSBkZXNrdG9wIGFnZW50IEFQSSBpcyBmb3VuZCBhdCBgd2luZG93LmZkYzNgLiBJZiB0aGUgQVBJIGlzIGZvdW5kLFxuICogdGhlIHByb21pc2Ugd2lsbCByZXNvbHZlIHdoZW4gdGhlIGBmZGMzUmVhZHlgIGV2ZW50IGlzIHJlY2VpdmVkIG9yIGlmIGl0XG4gKiBpcyBmb3VuZCBhdCB0aGUgZW5kIG9mIHRoZSBzcGVjaWZpZWQgdGltZW91dC4gSWYgdGhlIEFQSSBpcyBub3QgZm91bmQsIGl0XG4gKiB3aWxsIHJlamVjdCB3aXRoIGFuIGVycm9yLlxuICpcbiAqIGBgYGphdmFzY3JpcHRcbiAqIGF3YWl0IGZkYzNSZWFkeSgpO1xuICogY29uc3QgaW50ZW50TGlzdGVuZXIgPSBhd2FpdCBhZGRJbnRlbnRMaXN0ZW5lcihcIlZpZXdDaGFydFwiLCBpbnRlbnRIYW5kbGVyRm4pO1xuICogYGBgXG4gKlxuICogQHBhcmFtIHdhaXRGb3JNcyBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB3YWl0IGZvciB0aGUgRkRDMyBBUEkgdG8gYmVcbiAqIHJlYWR5LiBEZWZhdWx0cyB0byA1IHNlY29uZHMuXG4gKi9cbnZhciBmZGMzUmVhZHkgPSBmdW5jdGlvbiAod2FpdEZvck1zKSB7XG4gICAgaWYgKHdhaXRGb3JNcyA9PT0gdm9pZCAwKSB7IHdhaXRGb3JNcyA9IERFRkFVTFRfVElNRU9VVDsgfVxuICAgIHJldHVybiBfX2F3YWl0ZXIodm9pZCAwLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICByZXR1cm4gWzIgLypyZXR1cm4qLywgbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgZ2xvYmFsIGlzIGFscmVhZHkgYXZhaWxhYmxlIHJlc29sdmUgaW1tZWRpYXRlbHlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdpbmRvdy5mZGMzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBpdHMgbm90IGF2YWlsYWJsZSBzZXR1cCBhIHRpbWVvdXQgdG8gcmV0dXJuIGEgcmVqZWN0ZWQgcHJvbWlzZVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRpbWVvdXRfMSA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkgeyByZXR1cm4gKHdpbmRvdy5mZGMzID8gcmVzb2x2ZSgpIDogcmVqZWN0KFRpbWVvdXRFcnJvcikpOyB9LCB3YWl0Rm9yTXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGlzdGVuIGZvciB0aGUgZmRjM1JlYWR5IGV2ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignZmRjM1JlYWR5JywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0XzEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5mZGMzID8gcmVzb2x2ZSgpIDogcmVqZWN0KFVuZXhwZWN0ZWRFcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCB7IG9uY2U6IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KV07XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcbmZ1bmN0aW9uIGlzU3RyaW5nKGFwcCkge1xuICAgIHJldHVybiAhIWFwcCAmJiB0eXBlb2YgYXBwID09PSAnc3RyaW5nJztcbn1cbmZ1bmN0aW9uIG9wZW4oYXBwLCBjb250ZXh0KSB7XG4gICAgaWYgKGlzU3RyaW5nKGFwcCkpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMub3BlbihhcHAsIGNvbnRleHQpOyB9KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLm9wZW4oYXBwLCBjb250ZXh0KTsgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gZmluZEludGVudChpbnRlbnQsIGNvbnRleHQsIHJlc3VsdFR5cGUpIHtcbiAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5maW5kSW50ZW50KGludGVudCwgY29udGV4dCwgcmVzdWx0VHlwZSk7IH0pO1xufVxuZnVuY3Rpb24gZmluZEludGVudHNCeUNvbnRleHQoY29udGV4dCwgcmVzdWx0VHlwZSkge1xuICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLmZpbmRJbnRlbnRzQnlDb250ZXh0KGNvbnRleHQsIHJlc3VsdFR5cGUpOyB9KTtcbn1cbmZ1bmN0aW9uIGJyb2FkY2FzdChjb250ZXh0KSB7XG4gICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMuYnJvYWRjYXN0KGNvbnRleHQpOyB9KTtcbn1cbmZ1bmN0aW9uIHJhaXNlSW50ZW50KGludGVudCwgY29udGV4dCwgYXBwKSB7XG4gICAgaWYgKGlzU3RyaW5nKGFwcCkpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMucmFpc2VJbnRlbnQoaW50ZW50LCBjb250ZXh0LCBhcHApOyB9KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLnJhaXNlSW50ZW50KGludGVudCwgY29udGV4dCwgYXBwKTsgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gcmFpc2VJbnRlbnRGb3JDb250ZXh0KGNvbnRleHQsIGFwcCkge1xuICAgIGlmIChpc1N0cmluZyhhcHApKSB7XG4gICAgICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLnJhaXNlSW50ZW50Rm9yQ29udGV4dChjb250ZXh0LCBhcHApOyB9KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLnJhaXNlSW50ZW50Rm9yQ29udGV4dChjb250ZXh0LCBhcHApOyB9KTtcbiAgICB9XG59XG5mdW5jdGlvbiBhZGRJbnRlbnRMaXN0ZW5lcihpbnRlbnQsIGhhbmRsZXIpIHtcbiAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5hZGRJbnRlbnRMaXN0ZW5lcihpbnRlbnQsIGhhbmRsZXIpOyB9KTtcbn1cbmZ1bmN0aW9uIGFkZENvbnRleHRMaXN0ZW5lcihjb250ZXh0VHlwZU9ySGFuZGxlciwgaGFuZGxlcikge1xuICAgIC8vSGFuZGxlIChkZXByZWNhdGVkKSBmdW5jdGlvbiBzaWduYXR1cmUgdGhhdCBhbGxvd2VkIGNvbnRleHRUeXBlIGFyZ3VtZW50IHRvIGJlIG9taXR0ZWRcbiAgICBpZiAodHlwZW9mIGNvbnRleHRUeXBlT3JIYW5kbGVyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLmFkZENvbnRleHRMaXN0ZW5lcihjb250ZXh0VHlwZU9ySGFuZGxlciwgaGFuZGxlcik7IH0pO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMuYWRkQ29udGV4dExpc3RlbmVyKG51bGwsIGNvbnRleHRUeXBlT3JIYW5kbGVyKTsgfSk7XG4gICAgfVxufVxuZnVuY3Rpb24gZ2V0VXNlckNoYW5uZWxzKCkge1xuICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy9mYWxsYmFjayB0byBnZXRTeXN0ZW1DaGFubmVscyBmb3IgRkRDMyA8Mi4wIGltcGxlbWVudGF0aW9uc1xuICAgICAgICBpZiAod2luZG93LmZkYzMuZ2V0VXNlckNoYW5uZWxzKSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LmZkYzMuZ2V0VXNlckNoYW5uZWxzKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LmZkYzMuZ2V0U3lzdGVtQ2hhbm5lbHMoKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuZnVuY3Rpb24gZ2V0U3lzdGVtQ2hhbm5lbHMoKSB7XG4gICAgLy9mYWxsZm9yd2FyZCB0byBnZXRVc2VyQ2hhbm5lbHMgZm9yIEZEQzMgMi4wKyBpbXBsZW1lbnRhdGlvbnNcbiAgICByZXR1cm4gZ2V0VXNlckNoYW5uZWxzKCk7XG59XG5mdW5jdGlvbiBqb2luVXNlckNoYW5uZWwoY2hhbm5lbElkKSB7XG4gICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAvL2ZhbGxiYWNrIHRvIGpvaW5DaGFubmVsIGZvciBGREMzIDwyLjAgaW1wbGVtZW50YXRpb25zXG4gICAgICAgIGlmICh3aW5kb3cuZmRjMy5qb2luVXNlckNoYW5uZWwpIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3cuZmRjMy5qb2luVXNlckNoYW5uZWwoY2hhbm5lbElkKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3cuZmRjMy5qb2luQ2hhbm5lbChjaGFubmVsSWQpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5mdW5jdGlvbiBqb2luQ2hhbm5lbChjaGFubmVsSWQpIHtcbiAgICAvL2ZhbGxmb3J3YXJkIHRvIGpvaW5Vc2VyQ2hhbm5lbCBmb3IgRkRDMyAyLjArIGltcGxlbWVudGF0aW9uc1xuICAgIHJldHVybiBqb2luVXNlckNoYW5uZWwoY2hhbm5lbElkKTtcbn1cbmZ1bmN0aW9uIGdldE9yQ3JlYXRlQ2hhbm5lbChjaGFubmVsSWQpIHtcbiAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5nZXRPckNyZWF0ZUNoYW5uZWwoY2hhbm5lbElkKTsgfSk7XG59XG5mdW5jdGlvbiBnZXRDdXJyZW50Q2hhbm5lbCgpIHtcbiAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5nZXRDdXJyZW50Q2hhbm5lbCgpOyB9KTtcbn1cbmZ1bmN0aW9uIGxlYXZlQ3VycmVudENoYW5uZWwoKSB7XG4gICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMubGVhdmVDdXJyZW50Q2hhbm5lbCgpOyB9KTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVByaXZhdGVDaGFubmVsKCkge1xuICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLmNyZWF0ZVByaXZhdGVDaGFubmVsKCk7IH0pO1xufVxuZnVuY3Rpb24gZ2V0SW5mbygpIHtcbiAgICByZXR1cm4gcmVqZWN0SWZOb0dsb2JhbChmdW5jdGlvbiAoKSB7IHJldHVybiB3aW5kb3cuZmRjMy5nZXRJbmZvKCk7IH0pO1xufVxuZnVuY3Rpb24gZ2V0QXBwTWV0YWRhdGEoYXBwKSB7XG4gICAgcmV0dXJuIHJlamVjdElmTm9HbG9iYWwoZnVuY3Rpb24gKCkgeyByZXR1cm4gd2luZG93LmZkYzMuZ2V0QXBwTWV0YWRhdGEoYXBwKTsgfSk7XG59XG5mdW5jdGlvbiBmaW5kSW5zdGFuY2VzKGFwcCkge1xuICAgIHJldHVybiByZWplY3RJZk5vR2xvYmFsKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHdpbmRvdy5mZGMzLmZpbmRJbnN0YW5jZXMoYXBwKTsgfSk7XG59XG4vKipcbiAqIENoZWNrIGlmIHRoZSBnaXZlbiBjb250ZXh0IGlzIGEgc3RhbmRhcmQgY29udGV4dCB0eXBlLlxuICogQHBhcmFtIGNvbnRleHRUeXBlXG4gKi9cbmZ1bmN0aW9uIGlzU3RhbmRhcmRDb250ZXh0VHlwZShjb250ZXh0VHlwZSkge1xuICAgIHJldHVybiBTdGFuZGFyZENvbnRleHRzU2V0Lmhhcyhjb250ZXh0VHlwZSk7XG59XG4vKipcbiAqIENoZWNrIGlmIHRoZSBnaXZlbiBpbnRlbnQgaXMgYSBzdGFuZGFyZCBpbnRlbnQuXG4gKiBAcGFyYW0gaW50ZW50XG4gKi9cbmZ1bmN0aW9uIGlzU3RhbmRhcmRJbnRlbnQoaW50ZW50KSB7XG4gICAgcmV0dXJuIFN0YW5kYXJkSW50ZW50c1NldC5oYXMoaW50ZW50KTtcbn1cbi8qKlxuICogQ29tcGFyZSBudW1lcmljIHNlbXZlciB2ZXJzaW9uIG51bWJlciBzdHJpbmdzIChpbiB0aGUgZm9ybSBgMS4yLjNgKS5cbiAqXG4gKiBSZXR1cm5zIGAtMWAgaWYgdGhlIGZpcnN0IGFyZ3VtZW50IGlzIGEgbG93ZXIgdmVyc2lvbiBudW1iZXIgdGhhbiB0aGUgc2Vjb25kLFxuICogYDFgIGlmIHRoZSBmaXJzdCBhcmd1bWVudCBpcyBncmVhdGVyIHRoYW4gdGhlIHNlY29uZCwgMCBpZiB0aGUgYXJndW1lbnRzIGFyZVxuICogZXF1YWwgYW5kIGBudWxsYCBpZiBhbiBlcnJvciBvY2N1cnJlZCBkdXJpbmcgdGhlIGNvbXBhcmlzb24uXG4gKlxuICogQHBhcmFtIGFcbiAqIEBwYXJhbSBiXG4gKi9cbnZhciBjb21wYXJlVmVyc2lvbk51bWJlcnMgPSBmdW5jdGlvbiAoYSwgYikge1xuICAgIHRyeSB7XG4gICAgICAgIHZhciBhVmVyQXJyID0gYS5zcGxpdCgnLicpLm1hcChOdW1iZXIpO1xuICAgICAgICB2YXIgYlZlckFyciA9IGIuc3BsaXQoJy4nKS5tYXAoTnVtYmVyKTtcbiAgICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IE1hdGgubWF4KGFWZXJBcnIubGVuZ3RoLCBiVmVyQXJyLmxlbmd0aCk7IGluZGV4KyspIHtcbiAgICAgICAgICAgIC8qIElmIG9uZSB2ZXJzaW9uIG51bWJlciBoYXMgbW9yZSBkaWdpdHMgYW5kIHRoZSBvdGhlciBkb2VzIG5vdCwgYW5kIHRoZXkgYXJlIG90aGVyd2lzZSBlcXVhbCxcbiAgICAgICAgICAgICAgIGFzc3VtZSB0aGUgbG9uZ2VyIGlzIGdyZWF0ZXIuIEUuZy4gMS4xLjEgPiAxLjEgKi9cbiAgICAgICAgICAgIGlmIChpbmRleCA9PT0gYVZlckFyci5sZW5ndGggfHwgYVZlckFycltpbmRleF0gPCBiVmVyQXJyW2luZGV4XSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGluZGV4ID09PSBiVmVyQXJyLmxlbmd0aCB8fCBhVmVyQXJyW2luZGV4XSA+IGJWZXJBcnJbaW5kZXhdKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBjb21wYXJlIHZlcnNpb24gc3RyaW5ncycsIGUpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59O1xuLyoqXG4gKiBDaGVjayBpZiB0aGUgRkRDMyB2ZXJzaW9uIGluIGFuIEltcGxlbWVudGF0aW9uTWV0YWRhdGEgb2JqZWN0IGlzIGdyZWF0ZXIgdGhhblxuICogb3IgZXF1YWwgdG8gdGhlIHN1cHBsaWVkIG51bWVyaWMgc2VtdmVyIHZlcnNpb24gbnVtYmVyIHN0cmluZyAoaW4gdGhlIGZvcm0gYDEuMi4zYCkuXG4gKlxuICogUmV0dXJucyBhIGJvb2xlYW4gb3IgbnVsbCBpZiBhbiBlcnJvciBvY2N1cnJlZCB3aGlsZSBjb21wYXJpbmcgdGhlIHZlcnNpb24gbnVtYmVycy5cbiAqXG4gKiBAcGFyYW0gbWV0YWRhdGFcbiAqIEBwYXJhbSB2ZXJzaW9uXG4gKi9cbnZhciB2ZXJzaW9uSXNBdExlYXN0ID0gZnVuY3Rpb24gKG1ldGFkYXRhLCB2ZXJzaW9uKSB7XG4gICAgdmFyIGNvbXBhcmlzb24gPSBjb21wYXJlVmVyc2lvbk51bWJlcnMobWV0YWRhdGEuZmRjM1ZlcnNpb24sIHZlcnNpb24pO1xuICAgIHJldHVybiBjb21wYXJpc29uID09PSBudWxsID8gbnVsbCA6IGNvbXBhcmlzb24gPj0gMCA/IHRydWUgOiBmYWxzZTtcbn07XG5cbi8qKlxuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqIENvcHlyaWdodCBGSU5PUyBGREMzIGNvbnRyaWJ1dG9ycyAtIHNlZSBOT1RJQ0UgZmlsZVxuICovXG4vKipcbiAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgU3RhbmRhcmRDb250ZXh0VHlwZX0gaW5zdGVhZFxuICovXG52YXIgQ29udGV4dFR5cGVzO1xuKGZ1bmN0aW9uIChDb250ZXh0VHlwZXMpIHtcbiAgICBDb250ZXh0VHlwZXNbXCJDaGFydFwiXSA9IFwiZmRjMy5jaGFydFwiO1xuICAgIENvbnRleHRUeXBlc1tcIkNoYXRJbml0U2V0dGluZ3NcIl0gPSBcImZkYzMuY2hhdC5pbml0U2V0dGluZ3NcIjtcbiAgICBDb250ZXh0VHlwZXNbXCJDaGF0Um9vbVwiXSA9IFwiZmRjMy5jaGF0LnJvb21cIjtcbiAgICBDb250ZXh0VHlwZXNbXCJDb250YWN0XCJdID0gXCJmZGMzLmNvbnRhY3RcIjtcbiAgICBDb250ZXh0VHlwZXNbXCJDb250YWN0TGlzdFwiXSA9IFwiZmRjMy5jb250YWN0TGlzdFwiO1xuICAgIENvbnRleHRUeXBlc1tcIkNvdW50cnlcIl0gPSBcImZkYzMuY291bnRyeVwiO1xuICAgIENvbnRleHRUeXBlc1tcIkN1cnJlbmN5XCJdID0gXCJmZGMzLmN1cnJlbmN5XCI7XG4gICAgQ29udGV4dFR5cGVzW1wiRW1haWxcIl0gPSBcImZkYzMuZW1haWxcIjtcbiAgICBDb250ZXh0VHlwZXNbXCJJbnN0cnVtZW50XCJdID0gXCJmZGMzLmluc3RydW1lbnRcIjtcbiAgICBDb250ZXh0VHlwZXNbXCJJbnN0cnVtZW50TGlzdFwiXSA9IFwiZmRjMy5pbnN0cnVtZW50TGlzdFwiO1xuICAgIENvbnRleHRUeXBlc1tcIkludGVyYWN0aW9uXCJdID0gXCJmZGMzLmludGVyYWN0aW9uXCI7XG4gICAgQ29udGV4dFR5cGVzW1wiTm90aGluZ1wiXSA9IFwiZmRjMy5ub3RoaW5nXCI7XG4gICAgQ29udGV4dFR5cGVzW1wiT3JnYW5pemF0aW9uXCJdID0gXCJmZGMzLm9yZ2FuaXphdGlvblwiO1xuICAgIENvbnRleHRUeXBlc1tcIlBvcnRmb2xpb1wiXSA9IFwiZmRjMy5wb3J0Zm9saW9cIjtcbiAgICBDb250ZXh0VHlwZXNbXCJQb3NpdGlvblwiXSA9IFwiZmRjMy5wb3NpdGlvblwiO1xuICAgIENvbnRleHRUeXBlc1tcIkNoYXRTZWFyY2hDcml0ZXJpYVwiXSA9IFwiZmRjMy5jaGF0LnNlYXJjaENyaXRlcmlhXCI7XG4gICAgQ29udGV4dFR5cGVzW1wiVGltZVJhbmdlXCJdID0gXCJmZGMzLnRpbWVSYW5nZVwiO1xuICAgIENvbnRleHRUeXBlc1tcIlRyYW5zYWN0aW9uUmVzdWx0XCJdID0gXCJmZGMzLnRyYW5zYWN0aW9uUmVzdWx0XCI7XG4gICAgQ29udGV4dFR5cGVzW1wiVmFsdWF0aW9uXCJdID0gXCJmZGMzLnZhbHVhdGlvblwiO1xufSkoQ29udGV4dFR5cGVzIHx8IChDb250ZXh0VHlwZXMgPSB7fSkpO1xuXG4vLyBUbyBwYXJzZSB0aGlzIGRhdGE6XG4vL1xuLy8gICBpbXBvcnQgeyBDb252ZXJ0LCBBY3Rpb24sIENoYXJ0LCBDaGF0SW5pdFNldHRpbmdzLCBDaGF0TWVzc2FnZSwgQ2hhdFJvb20sIENoYXRTZWFyY2hDcml0ZXJpYSwgQ29udGFjdCwgQ29udGFjdExpc3QsIENvbnRleHQsIENvdW50cnksIEN1cnJlbmN5LCBFbWFpbCwgSW5zdHJ1bWVudCwgSW5zdHJ1bWVudExpc3QsIEludGVyYWN0aW9uLCBNZXNzYWdlLCBOb3RoaW5nLCBPcmRlciwgT3JkZXJMaXN0LCBPcmdhbml6YXRpb24sIFBvcnRmb2xpbywgUG9zaXRpb24sIFByb2R1Y3QsIFRpbWVSYW5nZSwgVHJhZGUsIFRyYWRlTGlzdCwgVHJhbnNhY3Rpb25SZXN1bHQsIFZhbHVhdGlvbiB9IGZyb20gXCIuL2ZpbGVcIjtcbi8vXG4vLyAgIGNvbnN0IGFjdGlvbiA9IENvbnZlcnQudG9BY3Rpb24oanNvbik7XG4vLyAgIGNvbnN0IGNoYXJ0ID0gQ29udmVydC50b0NoYXJ0KGpzb24pO1xuLy8gICBjb25zdCBjaGF0SW5pdFNldHRpbmdzID0gQ29udmVydC50b0NoYXRJbml0U2V0dGluZ3MoanNvbik7XG4vLyAgIGNvbnN0IGNoYXRNZXNzYWdlID0gQ29udmVydC50b0NoYXRNZXNzYWdlKGpzb24pO1xuLy8gICBjb25zdCBjaGF0Um9vbSA9IENvbnZlcnQudG9DaGF0Um9vbShqc29uKTtcbi8vICAgY29uc3QgY2hhdFNlYXJjaENyaXRlcmlhID0gQ29udmVydC50b0NoYXRTZWFyY2hDcml0ZXJpYShqc29uKTtcbi8vICAgY29uc3QgY29udGFjdCA9IENvbnZlcnQudG9Db250YWN0KGpzb24pO1xuLy8gICBjb25zdCBjb250YWN0TGlzdCA9IENvbnZlcnQudG9Db250YWN0TGlzdChqc29uKTtcbi8vICAgY29uc3QgY29udGV4dCA9IENvbnZlcnQudG9Db250ZXh0KGpzb24pO1xuLy8gICBjb25zdCBjb3VudHJ5ID0gQ29udmVydC50b0NvdW50cnkoanNvbik7XG4vLyAgIGNvbnN0IGN1cnJlbmN5ID0gQ29udmVydC50b0N1cnJlbmN5KGpzb24pO1xuLy8gICBjb25zdCBlbWFpbCA9IENvbnZlcnQudG9FbWFpbChqc29uKTtcbi8vICAgY29uc3QgaW5zdHJ1bWVudCA9IENvbnZlcnQudG9JbnN0cnVtZW50KGpzb24pO1xuLy8gICBjb25zdCBpbnN0cnVtZW50TGlzdCA9IENvbnZlcnQudG9JbnN0cnVtZW50TGlzdChqc29uKTtcbi8vICAgY29uc3QgaW50ZXJhY3Rpb24gPSBDb252ZXJ0LnRvSW50ZXJhY3Rpb24oanNvbik7XG4vLyAgIGNvbnN0IG1lc3NhZ2UgPSBDb252ZXJ0LnRvTWVzc2FnZShqc29uKTtcbi8vICAgY29uc3Qgbm90aGluZyA9IENvbnZlcnQudG9Ob3RoaW5nKGpzb24pO1xuLy8gICBjb25zdCBvcmRlciA9IENvbnZlcnQudG9PcmRlcihqc29uKTtcbi8vICAgY29uc3Qgb3JkZXJMaXN0ID0gQ29udmVydC50b09yZGVyTGlzdChqc29uKTtcbi8vICAgY29uc3Qgb3JnYW5pemF0aW9uID0gQ29udmVydC50b09yZ2FuaXphdGlvbihqc29uKTtcbi8vICAgY29uc3QgcG9ydGZvbGlvID0gQ29udmVydC50b1BvcnRmb2xpbyhqc29uKTtcbi8vICAgY29uc3QgcG9zaXRpb24gPSBDb252ZXJ0LnRvUG9zaXRpb24oanNvbik7XG4vLyAgIGNvbnN0IHByb2R1Y3QgPSBDb252ZXJ0LnRvUHJvZHVjdChqc29uKTtcbi8vICAgY29uc3QgdGltZVJhbmdlID0gQ29udmVydC50b1RpbWVSYW5nZShqc29uKTtcbi8vICAgY29uc3QgdHJhZGUgPSBDb252ZXJ0LnRvVHJhZGUoanNvbik7XG4vLyAgIGNvbnN0IHRyYWRlTGlzdCA9IENvbnZlcnQudG9UcmFkZUxpc3QoanNvbik7XG4vLyAgIGNvbnN0IHRyYW5zYWN0aW9uUmVzdWx0ID0gQ29udmVydC50b1RyYW5zYWN0aW9uUmVzdWx0KGpzb24pO1xuLy8gICBjb25zdCB2YWx1YXRpb24gPSBDb252ZXJ0LnRvVmFsdWF0aW9uKGpzb24pO1xuLy9cbi8vIFRoZXNlIGZ1bmN0aW9ucyB3aWxsIHRocm93IGFuIGVycm9yIGlmIHRoZSBKU09OIGRvZXNuJ3Rcbi8vIG1hdGNoIHRoZSBleHBlY3RlZCBpbnRlcmZhY2UsIGV2ZW4gaWYgdGhlIEpTT04gaXMgdmFsaWQuXG4vKipcbiAqIEZyZWUgdGV4dCB0byBiZSB1c2VkIGZvciBhIGtleXdvcmQgc2VhcmNoXG4gKlxuICogYGludGVyYWN0aW9uVHlwZWAgU0hPVUxEIGJlIG9uZSBvZiBgJ0luc3RhbnQgTWVzc2FnZSdgLCBgJ0VtYWlsJ2AsIGAnQ2FsbCdgLCBvclxuICogYCdNZWV0aW5nJ2AgYWx0aG91Z2ggb3RoZXIgc3RyaW5nIHZhbHVlcyBhcmUgcGVybWl0dGVkLlxuICovXG4vLyBDb252ZXJ0cyBKU09OIHN0cmluZ3MgdG8vZnJvbSB5b3VyIHR5cGVzXG4vLyBhbmQgYXNzZXJ0cyB0aGUgcmVzdWx0cyBvZiBKU09OLnBhcnNlIGF0IHJ1bnRpbWVcbnZhciBDb252ZXJ0ID0gLyoqIEBjbGFzcyAqLyAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENvbnZlcnQoKSB7XG4gICAgfVxuICAgIENvbnZlcnQudG9BY3Rpb24gPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiQWN0aW9uXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuYWN0aW9uVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJBY3Rpb25cIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9DaGFydCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJDaGFydFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNoYXJ0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJDaGFydFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0NoYXRJbml0U2V0dGluZ3MgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiQ2hhdEluaXRTZXR0aW5nc1wiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNoYXRJbml0U2V0dGluZ3NUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkNoYXRJbml0U2V0dGluZ3NcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9DaGF0TWVzc2FnZSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJDaGF0TWVzc2FnZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNoYXRNZXNzYWdlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJDaGF0TWVzc2FnZVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0NoYXRSb29tID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIkNoYXRSb29tXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuY2hhdFJvb21Ub0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkNoYXRSb29tXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQ2hhdFNlYXJjaENyaXRlcmlhID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIkNoYXRTZWFyY2hDcml0ZXJpYVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNoYXRTZWFyY2hDcml0ZXJpYVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiQ2hhdFNlYXJjaENyaXRlcmlhXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQ29udGFjdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJDb250YWN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuY29udGFjdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiQ29udGFjdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0NvbnRhY3RMaXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIkNvbnRhY3RMaXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuY29udGFjdExpc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkNvbnRhY3RMaXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvQ29udGV4dCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJDb250ZXh0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuY29udGV4dFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiQ29udGV4dFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0NvdW50cnkgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiQ291bnRyeVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmNvdW50cnlUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkNvdW50cnlcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9DdXJyZW5jeSA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJDdXJyZW5jeVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LmN1cnJlbmN5VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJDdXJyZW5jeVwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0VtYWlsID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIkVtYWlsXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuZW1haWxUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkVtYWlsXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvSW5zdHJ1bWVudCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJJbnN0cnVtZW50XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuaW5zdHJ1bWVudFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiSW5zdHJ1bWVudFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b0luc3RydW1lbnRMaXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIkluc3RydW1lbnRMaXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQuaW5zdHJ1bWVudExpc3RUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIkluc3RydW1lbnRMaXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvSW50ZXJhY3Rpb24gPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiSW50ZXJhY3Rpb25cIikpO1xuICAgIH07XG4gICAgQ29udmVydC5pbnRlcmFjdGlvblRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiSW50ZXJhY3Rpb25cIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9NZXNzYWdlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIk1lc3NhZ2VcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5tZXNzYWdlVG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJNZXNzYWdlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvTm90aGluZyA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJOb3RoaW5nXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQubm90aGluZ1RvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiTm90aGluZ1wiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b09yZGVyID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIk9yZGVyXCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQub3JkZXJUb0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIk9yZGVyXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvT3JkZXJMaXN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIk9yZGVyTGlzdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lm9yZGVyTGlzdFRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiT3JkZXJMaXN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvT3JnYW5pemF0aW9uID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIk9yZ2FuaXphdGlvblwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0Lm9yZ2FuaXphdGlvblRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiT3JnYW5pemF0aW9uXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUG9ydGZvbGlvID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIlBvcnRmb2xpb1wiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnBvcnRmb2xpb1RvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiUG9ydGZvbGlvXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvUG9zaXRpb24gPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiUG9zaXRpb25cIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wb3NpdGlvblRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiUG9zaXRpb25cIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9Qcm9kdWN0ID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIlByb2R1Y3RcIikpO1xuICAgIH07XG4gICAgQ29udmVydC5wcm9kdWN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJQcm9kdWN0XCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvVGltZVJhbmdlID0gZnVuY3Rpb24gKGpzb24pIHtcbiAgICAgICAgcmV0dXJuIGNhc3QoSlNPTi5wYXJzZShqc29uKSwgcihcIlRpbWVSYW5nZVwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRpbWVSYW5nZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiVGltZVJhbmdlXCIpKSwgbnVsbCwgMik7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRvVHJhZGUgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiVHJhZGVcIikpO1xuICAgIH07XG4gICAgQ29udmVydC50cmFkZVRvSnNvbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodW5jYXN0KHZhbHVlLCByKFwiVHJhZGVcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9UcmFkZUxpc3QgPSBmdW5jdGlvbiAoanNvbikge1xuICAgICAgICByZXR1cm4gY2FzdChKU09OLnBhcnNlKGpzb24pLCByKFwiVHJhZGVMaXN0XCIpKTtcbiAgICB9O1xuICAgIENvbnZlcnQudHJhZGVMaXN0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJUcmFkZUxpc3RcIikpLCBudWxsLCAyKTtcbiAgICB9O1xuICAgIENvbnZlcnQudG9UcmFuc2FjdGlvblJlc3VsdCA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJUcmFuc2FjdGlvblJlc3VsdFwiKSk7XG4gICAgfTtcbiAgICBDb252ZXJ0LnRyYW5zYWN0aW9uUmVzdWx0VG9Kc29uID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh1bmNhc3QodmFsdWUsIHIoXCJUcmFuc2FjdGlvblJlc3VsdFwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgQ29udmVydC50b1ZhbHVhdGlvbiA9IGZ1bmN0aW9uIChqc29uKSB7XG4gICAgICAgIHJldHVybiBjYXN0KEpTT04ucGFyc2UoanNvbiksIHIoXCJWYWx1YXRpb25cIikpO1xuICAgIH07XG4gICAgQ29udmVydC52YWx1YXRpb25Ub0pzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHVuY2FzdCh2YWx1ZSwgcihcIlZhbHVhdGlvblwiKSksIG51bGwsIDIpO1xuICAgIH07XG4gICAgcmV0dXJuIENvbnZlcnQ7XG59KCkpO1xuZnVuY3Rpb24gaW52YWxpZFZhbHVlKHR5cCwgdmFsLCBrZXksIHBhcmVudCkge1xuICAgIGlmIChwYXJlbnQgPT09IHZvaWQgMCkgeyBwYXJlbnQgPSAnJzsgfVxuICAgIHZhciBwcmV0dHlUeXAgPSBwcmV0dHlUeXBlTmFtZSh0eXApO1xuICAgIHZhciBwYXJlbnRUZXh0ID0gcGFyZW50ID8gXCIgb24gXCIuY29uY2F0KHBhcmVudCkgOiAnJztcbiAgICB2YXIga2V5VGV4dCA9IGtleSA/IFwiIGZvciBrZXkgXFxcIlwiLmNvbmNhdChrZXksIFwiXFxcIlwiKSA6ICcnO1xuICAgIHRocm93IEVycm9yKFwiSW52YWxpZCB2YWx1ZVwiLmNvbmNhdChrZXlUZXh0KS5jb25jYXQocGFyZW50VGV4dCwgXCIuIEV4cGVjdGVkIFwiKS5jb25jYXQocHJldHR5VHlwLCBcIiBidXQgZ290IFwiKS5jb25jYXQoSlNPTi5zdHJpbmdpZnkodmFsKSkpO1xufVxuZnVuY3Rpb24gcHJldHR5VHlwZU5hbWUodHlwKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodHlwKSkge1xuICAgICAgICBpZiAodHlwLmxlbmd0aCA9PT0gMiAmJiB0eXBbMF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIFwiYW4gb3B0aW9uYWwgXCIuY29uY2F0KHByZXR0eVR5cGVOYW1lKHR5cFsxXSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIFwib25lIG9mIFtcIi5jb25jYXQodHlwLm1hcChmdW5jdGlvbiAoYSkgeyByZXR1cm4gcHJldHR5VHlwZU5hbWUoYSk7IH0pLmpvaW4oXCIsIFwiKSwgXCJdXCIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiB0eXAgPT09IFwib2JqZWN0XCIgJiYgdHlwLmxpdGVyYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdHlwLmxpdGVyYWw7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHR5cDtcbiAgICB9XG59XG5mdW5jdGlvbiBqc29uVG9KU1Byb3BzKHR5cCkge1xuICAgIGlmICh0eXAuanNvblRvSlMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB2YXIgbWFwXzEgPSB7fTtcbiAgICAgICAgdHlwLnByb3BzLmZvckVhY2goZnVuY3Rpb24gKHApIHsgcmV0dXJuIG1hcF8xW3AuanNvbl0gPSB7IGtleTogcC5qcywgdHlwOiBwLnR5cCB9OyB9KTtcbiAgICAgICAgdHlwLmpzb25Ub0pTID0gbWFwXzE7XG4gICAgfVxuICAgIHJldHVybiB0eXAuanNvblRvSlM7XG59XG5mdW5jdGlvbiBqc1RvSlNPTlByb3BzKHR5cCkge1xuICAgIGlmICh0eXAuanNUb0pTT04gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB2YXIgbWFwXzIgPSB7fTtcbiAgICAgICAgdHlwLnByb3BzLmZvckVhY2goZnVuY3Rpb24gKHApIHsgcmV0dXJuIG1hcF8yW3AuanNdID0geyBrZXk6IHAuanNvbiwgdHlwOiBwLnR5cCB9OyB9KTtcbiAgICAgICAgdHlwLmpzVG9KU09OID0gbWFwXzI7XG4gICAgfVxuICAgIHJldHVybiB0eXAuanNUb0pTT047XG59XG5mdW5jdGlvbiB0cmFuc2Zvcm0odmFsLCB0eXAsIGdldFByb3BzLCBrZXksIHBhcmVudCkge1xuICAgIGlmIChrZXkgPT09IHZvaWQgMCkgeyBrZXkgPSAnJzsgfVxuICAgIGlmIChwYXJlbnQgPT09IHZvaWQgMCkgeyBwYXJlbnQgPSAnJzsgfVxuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByaW1pdGl2ZSh0eXAsIHZhbCkge1xuICAgICAgICBpZiAodHlwZW9mIHR5cCA9PT0gdHlwZW9mIHZhbClcbiAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUodHlwLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdHJhbnNmb3JtVW5pb24odHlwcywgdmFsKSB7XG4gICAgICAgIC8vIHZhbCBtdXN0IHZhbGlkYXRlIGFnYWluc3Qgb25lIHR5cCBpbiB0eXBzXG4gICAgICAgIHZhciBsID0gdHlwcy5sZW5ndGg7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgdHlwXzEgPSB0eXBzW2ldO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhbnNmb3JtKHZhbCwgdHlwXzEsIGdldFByb3BzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChfKSB7IH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlKHR5cHMsIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm1FbnVtKGNhc2VzLCB2YWwpIHtcbiAgICAgICAgaWYgKGNhc2VzLmluZGV4T2YodmFsKSAhPT0gLTEpXG4gICAgICAgICAgICByZXR1cm4gdmFsO1xuICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlKGNhc2VzLm1hcChmdW5jdGlvbiAoYSkgeyByZXR1cm4gbChhKTsgfSksIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgIH1cbiAgICBmdW5jdGlvbiB0cmFuc2Zvcm1BcnJheSh0eXAsIHZhbCkge1xuICAgICAgICAvLyB2YWwgbXVzdCBiZSBhbiBhcnJheSB3aXRoIG5vIGludmFsaWQgZWxlbWVudHNcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbCkpXG4gICAgICAgICAgICByZXR1cm4gaW52YWxpZFZhbHVlKGwoXCJhcnJheVwiKSwgdmFsLCBrZXksIHBhcmVudCk7XG4gICAgICAgIHJldHVybiB2YWwubWFwKGZ1bmN0aW9uIChlbCkgeyByZXR1cm4gdHJhbnNmb3JtKGVsLCB0eXAsIGdldFByb3BzKTsgfSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybURhdGUodmFsKSB7XG4gICAgICAgIGlmICh2YWwgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciBkID0gbmV3IERhdGUodmFsKTtcbiAgICAgICAgaWYgKGlzTmFOKGQudmFsdWVPZigpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGludmFsaWRWYWx1ZShsKFwiRGF0ZVwiKSwgdmFsLCBrZXksIHBhcmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGQ7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybU9iamVjdChwcm9wcywgYWRkaXRpb25hbCwgdmFsKSB7XG4gICAgICAgIGlmICh2YWwgPT09IG51bGwgfHwgdHlwZW9mIHZhbCAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KHZhbCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUobChyZWYgfHwgXCJvYmplY3RcIiksIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMocHJvcHMpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgdmFyIHByb3AgPSBwcm9wc1trZXldO1xuICAgICAgICAgICAgdmFyIHYgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodmFsLCBrZXkpID8gdmFsW2tleV0gOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICByZXN1bHRbcHJvcC5rZXldID0gdHJhbnNmb3JtKHYsIHByb3AudHlwLCBnZXRQcm9wcywga2V5LCByZWYpO1xuICAgICAgICB9KTtcbiAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModmFsKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHByb3BzLCBrZXkpKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB0cmFuc2Zvcm0odmFsW2tleV0sIGFkZGl0aW9uYWwsIGdldFByb3BzLCBrZXksIHJlZik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICBpZiAodHlwID09PSBcImFueVwiKVxuICAgICAgICByZXR1cm4gdmFsO1xuICAgIGlmICh0eXAgPT09IG51bGwpIHtcbiAgICAgICAgaWYgKHZhbCA9PT0gbnVsbClcbiAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUodHlwLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB9XG4gICAgaWYgKHR5cCA9PT0gZmFsc2UpXG4gICAgICAgIHJldHVybiBpbnZhbGlkVmFsdWUodHlwLCB2YWwsIGtleSwgcGFyZW50KTtcbiAgICB2YXIgcmVmID0gdW5kZWZpbmVkO1xuICAgIHdoaWxlICh0eXBlb2YgdHlwID09PSBcIm9iamVjdFwiICYmIHR5cC5yZWYgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZWYgPSB0eXAucmVmO1xuICAgICAgICB0eXAgPSB0eXBlTWFwW3R5cC5yZWZdO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh0eXApKVxuICAgICAgICByZXR1cm4gdHJhbnNmb3JtRW51bSh0eXAsIHZhbCk7XG4gICAgaWYgKHR5cGVvZiB0eXAgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgcmV0dXJuIHR5cC5oYXNPd25Qcm9wZXJ0eShcInVuaW9uTWVtYmVyc1wiKSA/IHRyYW5zZm9ybVVuaW9uKHR5cC51bmlvbk1lbWJlcnMsIHZhbClcbiAgICAgICAgICAgIDogdHlwLmhhc093blByb3BlcnR5KFwiYXJyYXlJdGVtc1wiKSA/IHRyYW5zZm9ybUFycmF5KHR5cC5hcnJheUl0ZW1zLCB2YWwpXG4gICAgICAgICAgICAgICAgOiB0eXAuaGFzT3duUHJvcGVydHkoXCJwcm9wc1wiKSA/IHRyYW5zZm9ybU9iamVjdChnZXRQcm9wcyh0eXApLCB0eXAuYWRkaXRpb25hbCwgdmFsKVxuICAgICAgICAgICAgICAgICAgICA6IGludmFsaWRWYWx1ZSh0eXAsIHZhbCwga2V5LCBwYXJlbnQpO1xuICAgIH1cbiAgICAvLyBOdW1iZXJzIGNhbiBiZSBwYXJzZWQgYnkgRGF0ZSBidXQgc2hvdWxkbid0IGJlLlxuICAgIGlmICh0eXAgPT09IERhdGUgJiYgdHlwZW9mIHZhbCAhPT0gXCJudW1iZXJcIilcbiAgICAgICAgcmV0dXJuIHRyYW5zZm9ybURhdGUodmFsKTtcbiAgICByZXR1cm4gdHJhbnNmb3JtUHJpbWl0aXZlKHR5cCwgdmFsKTtcbn1cbmZ1bmN0aW9uIGNhc3QodmFsLCB0eXApIHtcbiAgICByZXR1cm4gdHJhbnNmb3JtKHZhbCwgdHlwLCBqc29uVG9KU1Byb3BzKTtcbn1cbmZ1bmN0aW9uIHVuY2FzdCh2YWwsIHR5cCkge1xuICAgIHJldHVybiB0cmFuc2Zvcm0odmFsLCB0eXAsIGpzVG9KU09OUHJvcHMpO1xufVxuZnVuY3Rpb24gbCh0eXApIHtcbiAgICByZXR1cm4geyBsaXRlcmFsOiB0eXAgfTtcbn1cbmZ1bmN0aW9uIGEodHlwKSB7XG4gICAgcmV0dXJuIHsgYXJyYXlJdGVtczogdHlwIH07XG59XG5mdW5jdGlvbiB1KCkge1xuICAgIHZhciB0eXBzID0gW107XG4gICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IGFyZ3VtZW50cy5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgdHlwc1tfaV0gPSBhcmd1bWVudHNbX2ldO1xuICAgIH1cbiAgICByZXR1cm4geyB1bmlvbk1lbWJlcnM6IHR5cHMgfTtcbn1cbmZ1bmN0aW9uIG8ocHJvcHMsIGFkZGl0aW9uYWwpIHtcbiAgICByZXR1cm4geyBwcm9wczogcHJvcHMsIGFkZGl0aW9uYWw6IGFkZGl0aW9uYWwgfTtcbn1cbmZ1bmN0aW9uIG0oYWRkaXRpb25hbCkge1xuICAgIHJldHVybiB7IHByb3BzOiBbXSwgYWRkaXRpb25hbDogYWRkaXRpb25hbCB9O1xufVxuZnVuY3Rpb24gcihuYW1lKSB7XG4gICAgcmV0dXJuIHsgcmVmOiBuYW1lIH07XG59XG52YXIgdHlwZU1hcCA9IHtcbiAgICBcIkFjdGlvblwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImFwcFwiLCBqczogXCJhcHBcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkFjdGlvblRhcmdldEFwcFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHIoXCJDb250ZXh0RWxlbWVudFwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaW50ZW50XCIsIGpzOiBcImludGVudFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGl0bGVcIiwganM6IFwidGl0bGVcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiQWN0aW9uVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQWN0aW9uVGFyZ2V0QXBwXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiYXBwSWRcIiwganM6IFwiYXBwSWRcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJkZXNrdG9wQWdlbnRcIiwganM6IFwiZGVza3RvcEFnZW50XCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnN0YW5jZUlkXCIsIGpzOiBcImluc3RhbmNlSWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNvbnRleHRFbGVtZW50XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogXCJcIiB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQ2hhcnRcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpbnN0cnVtZW50c1wiLCBqczogXCJpbnN0cnVtZW50c1wiLCB0eXA6IGEocihcIkluc3RydW1lbnRFbGVtZW50XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwib3RoZXJDb25maWdcIiwganM6IFwib3RoZXJDb25maWdcIiwgdHlwOiB1KHVuZGVmaW5lZCwgYShyKFwiQ29udGV4dEVsZW1lbnRcIikpKSB9LFxuICAgICAgICB7IGpzb246IFwicmFuZ2VcIiwganM6IFwicmFuZ2VcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIlRpbWVSYW5nZU9iamVjdFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInN0eWxlXCIsIGpzOiBcInN0eWxlXCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJDaGFydFN0eWxlXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkNoYXJ0VHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiSW5zdHJ1bWVudEVsZW1lbnRcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHIoXCJQdXJwbGVJbnN0cnVtZW50SWRlbnRpZmllcnNcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm1hcmtldFwiLCBqczogXCJtYXJrZXRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIk9yZ2FuaXphdGlvbk1hcmtldFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJQdXJwbGVJbnRlcmFjdGlvblR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiUHVycGxlSW5zdHJ1bWVudElkZW50aWZpZXJzXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiQkJHXCIsIGpzOiBcIkJCR1wiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiQ1VTSVBcIiwganM6IFwiQ1VTSVBcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkZEU19JRFwiLCBqczogXCJGRFNfSURcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkZJR0lcIiwganM6IFwiRklHSVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiSVNJTlwiLCBqczogXCJJU0lOXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJQRVJNSURcIiwganM6IFwiUEVSTUlEXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJSSUNcIiwganM6IFwiUklDXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJTRURPTFwiLCBqczogXCJTRURPTFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGlja2VyXCIsIGpzOiBcInRpY2tlclwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiT3JnYW5pemF0aW9uTWFya2V0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiQkJHXCIsIGpzOiBcIkJCR1wiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiQ09VTlRSWV9JU09BTFBIQTJcIiwganM6IFwiQ09VTlRSWV9JU09BTFBIQTJcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIk1JQ1wiLCBqczogXCJNSUNcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiVGltZVJhbmdlT2JqZWN0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiZW5kVGltZVwiLCBqczogXCJlbmRUaW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIERhdGUpIH0sXG4gICAgICAgIHsganNvbjogXCJzdGFydFRpbWVcIiwganM6IFwic3RhcnRUaW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIERhdGUpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiVGltZVJhbmdlVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQ2hhdEluaXRTZXR0aW5nc1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImNoYXROYW1lXCIsIGpzOiBcImNoYXROYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJtZW1iZXJzXCIsIGpzOiBcIm1lbWJlcnNcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkNvbnRhY3RMaXN0T2JqZWN0XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibWVzc2FnZVwiLCBqczogXCJtZXNzYWdlXCIsIHR5cDogdSh1bmRlZmluZWQsIHUocihcIk1lc3NhZ2VPYmplY3RcIiksIFwiXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwib3B0aW9uc1wiLCBqczogXCJvcHRpb25zXCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJDaGF0T3B0aW9uc1wiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJDaGF0SW5pdFNldHRpbmdzVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQ29udGFjdExpc3RPYmplY3RcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJjb250YWN0c1wiLCBqczogXCJjb250YWN0c1wiLCB0eXA6IGEocihcIkNvbnRhY3RFbGVtZW50XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkNvbnRhY3RMaXN0VHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQ29udGFjdEVsZW1lbnRcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHIoXCJQdXJwbGVDb250YWN0SWRlbnRpZmllcnNcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJGbHVmZnlJbnRlcmFjdGlvblR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiUHVycGxlQ29udGFjdElkZW50aWZpZXJzXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiZW1haWxcIiwganM6IFwiZW1haWxcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkZEU19JRFwiLCBqczogXCJGRFNfSURcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIk1lc3NhZ2VPYmplY3RcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJlbnRpdGllc1wiLCBqczogXCJlbnRpdGllc1wiLCB0eXA6IHUodW5kZWZpbmVkLCBtKHIoXCJQdXJwbGVBY3Rpb25cIikpKSB9LFxuICAgICAgICB7IGpzb246IFwidGV4dFwiLCBqczogXCJ0ZXh0XCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJQdXJwbGVNZXNzYWdlVGV4dFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJNZXNzYWdlVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiUHVycGxlQWN0aW9uXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiYXBwXCIsIGpzOiBcImFwcFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiQWN0aW9uVGFyZ2V0QXBwXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJDb250ZXh0RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImludGVudFwiLCBqczogXCJpbnRlbnRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpdGxlXCIsIGpzOiBcInRpdGxlXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiRW50aXR5VHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiZGF0YVwiLCBqczogXCJkYXRhXCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJQdXJwbGVEYXRhXCIpKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiUHVycGxlRGF0YVwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImRhdGFVcmlcIiwganM6IFwiZGF0YVVyaVwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IFwiXCIgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlB1cnBsZU1lc3NhZ2VUZXh0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwidGV4dC9tYXJrZG93blwiLCBqczogXCJ0ZXh0L21hcmtkb3duXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0ZXh0L3BsYWluXCIsIGpzOiBcInRleHQvcGxhaW5cIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNoYXRPcHRpb25zXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiYWxsb3dBZGRVc2VyXCIsIGpzOiBcImFsbG93QWRkVXNlclwiLCB0eXA6IHUodW5kZWZpbmVkLCB0cnVlKSB9LFxuICAgICAgICB7IGpzb246IFwiYWxsb3dIaXN0b3J5QnJvd3NpbmdcIiwganM6IFwiYWxsb3dIaXN0b3J5QnJvd3NpbmdcIiwgdHlwOiB1KHVuZGVmaW5lZCwgdHJ1ZSkgfSxcbiAgICAgICAgeyBqc29uOiBcImFsbG93TWVzc2FnZUNvcHlcIiwganM6IFwiYWxsb3dNZXNzYWdlQ29weVwiLCB0eXA6IHUodW5kZWZpbmVkLCB0cnVlKSB9LFxuICAgICAgICB7IGpzb246IFwiZ3JvdXBSZWNpcGllbnRzXCIsIGpzOiBcImdyb3VwUmVjaXBpZW50c1wiLCB0eXA6IHUodW5kZWZpbmVkLCB0cnVlKSB9LFxuICAgICAgICB7IGpzb246IFwiaXNQdWJsaWNcIiwganM6IFwiaXNQdWJsaWNcIiwgdHlwOiB1KHVuZGVmaW5lZCwgdHJ1ZSkgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNoYXRNZXNzYWdlXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiY2hhdFJvb21cIiwganM6IFwiY2hhdFJvb21cIiwgdHlwOiByKFwiQ2hhdFJvb21PYmplY3RcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm1lc3NhZ2VcIiwganM6IFwibWVzc2FnZVwiLCB0eXA6IHIoXCJNZXNzYWdlT2JqZWN0XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiQ2hhdE1lc3NhZ2VUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJDaGF0Um9vbU9iamVjdFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogbShcImFueVwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwcm92aWRlck5hbWVcIiwganM6IFwicHJvdmlkZXJOYW1lXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkNoYXRSb29tVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwidXJsXCIsIGpzOiBcInVybFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQ2hhdFJvb21cIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IG0oXCJhbnlcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwicHJvdmlkZXJOYW1lXCIsIGpzOiBcInByb3ZpZGVyTmFtZVwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJDaGF0Um9vbVR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInVybFwiLCBqczogXCJ1cmxcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNoYXRTZWFyY2hDcml0ZXJpYVwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImNyaXRlcmlhXCIsIGpzOiBcImNyaXRlcmlhXCIsIHR5cDogYSh1KHIoXCJPcmdhbml6YXRpb25PYmplY3RcIiksIFwiXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkNoYXRTZWFyY2hDcml0ZXJpYVR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIk9yZ2FuaXphdGlvbk9iamVjdFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogcihcIklkZW50aWZpZXJzXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJtYXJrZXRcIiwganM6IFwibWFya2V0XCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJPcmdhbml6YXRpb25NYXJrZXRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiVGVudGFjbGVkSW50ZXJhY3Rpb25UeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIklkZW50aWZpZXJzXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiQkJHXCIsIGpzOiBcIkJCR1wiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiQ1VTSVBcIiwganM6IFwiQ1VTSVBcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkZEU19JRFwiLCBqczogXCJGRFNfSURcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkZJR0lcIiwganM6IFwiRklHSVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiSVNJTlwiLCBqczogXCJJU0lOXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJQRVJNSURcIiwganM6IFwiUEVSTUlEXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJSSUNcIiwganM6IFwiUklDXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJTRURPTFwiLCBqczogXCJTRURPTFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGlja2VyXCIsIGpzOiBcInRpY2tlclwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiTEVJXCIsIGpzOiBcIkxFSVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiZW1haWxcIiwganM6IFwiZW1haWxcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNvbnRhY3RcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHIoXCJGbHVmZnlDb250YWN0SWRlbnRpZmllcnNcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJGbHVmZnlJbnRlcmFjdGlvblR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiRmx1ZmZ5Q29udGFjdElkZW50aWZpZXJzXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiZW1haWxcIiwganM6IFwiZW1haWxcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkZEU19JRFwiLCBqczogXCJGRFNfSURcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNvbnRhY3RMaXN0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiY29udGFjdHNcIiwganM6IFwiY29udGFjdHNcIiwgdHlwOiBhKHIoXCJDb250YWN0RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJDb250YWN0TGlzdFR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkNvbnRleHRcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJDb3VudHJ5XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiByKFwiQ291bnRyeUlEXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiQ291bnRyeVR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQ291bnRyeUlEXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiQ09VTlRSWV9JU09BTFBIQTJcIiwganM6IFwiQ09VTlRSWV9JU09BTFBIQTJcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkNPVU5UUllfSVNPQUxQSEEzXCIsIGpzOiBcIkNPVU5UUllfSVNPQUxQSEEzXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJJU09BTFBIQTJcIiwganM6IFwiSVNPQUxQSEEyXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJJU09BTFBIQTNcIiwganM6IFwiSVNPQUxQSEEzXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJDdXJyZW5jeVwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogcihcIkN1cnJlbmN5SURcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkN1cnJlbmN5VHlwZVwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiQ3VycmVuY3lJRFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcIkNVUlJFTkNZX0lTT0NPREVcIiwganM6IFwiQ1VSUkVOQ1lfSVNPQ09ERVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiRW1haWxcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJyZWNpcGllbnRzXCIsIGpzOiBcInJlY2lwaWVudHNcIiwgdHlwOiByKFwiRW1haWxSZWNpcGllbnRzXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJzdWJqZWN0XCIsIGpzOiBcInN1YmplY3RcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRleHRCb2R5XCIsIGpzOiBcInRleHRCb2R5XCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiRW1haWxUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJFbWFpbFJlY2lwaWVudHNcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiRW1haWxSZWNpcGllbnRzSURcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiRW1haWxSZWNpcGllbnRzVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJjb250YWN0c1wiLCBqczogXCJjb250YWN0c1wiLCB0eXA6IHUodW5kZWZpbmVkLCBhKHIoXCJDb250YWN0RWxlbWVudFwiKSkpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJFbWFpbFJlY2lwaWVudHNJRFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImVtYWlsXCIsIGpzOiBcImVtYWlsXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJGRFNfSURcIiwganM6IFwiRkRTX0lEXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJJbnN0cnVtZW50XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiByKFwiRmx1ZmZ5SW5zdHJ1bWVudElkZW50aWZpZXJzXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJtYXJrZXRcIiwganM6IFwibWFya2V0XCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJQdXJwbGVNYXJrZXRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiUHVycGxlSW50ZXJhY3Rpb25UeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkZsdWZmeUluc3RydW1lbnRJZGVudGlmaWVyc1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcIkJCR1wiLCBqczogXCJCQkdcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkNVU0lQXCIsIGpzOiBcIkNVU0lQXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJGRFNfSURcIiwganM6IFwiRkRTX0lEXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJGSUdJXCIsIGpzOiBcIkZJR0lcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIklTSU5cIiwganM6IFwiSVNJTlwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiUEVSTUlEXCIsIGpzOiBcIlBFUk1JRFwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiUklDXCIsIGpzOiBcIlJJQ1wiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiU0VET0xcIiwganM6IFwiU0VET0xcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpY2tlclwiLCBqczogXCJ0aWNrZXJcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlB1cnBsZU1hcmtldFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcIkJCR1wiLCBqczogXCJCQkdcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkNPVU5UUllfSVNPQUxQSEEyXCIsIGpzOiBcIkNPVU5UUllfSVNPQUxQSEEyXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJNSUNcIiwganM6IFwiTUlDXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkluc3RydW1lbnRMaXN0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaW5zdHJ1bWVudHNcIiwganM6IFwiaW5zdHJ1bWVudHNcIiwgdHlwOiBhKHIoXCJJbnN0cnVtZW50RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJJbnN0cnVtZW50TGlzdFR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkludGVyYWN0aW9uXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiZGVzY3JpcHRpb25cIiwganM6IFwiZGVzY3JpcHRpb25cIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiSW50ZXJhY3Rpb25JRFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImluaXRpYXRvclwiLCBqczogXCJpbml0aWF0b3JcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkNvbnRhY3RFbGVtZW50XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiaW50ZXJhY3Rpb25UeXBlXCIsIGpzOiBcImludGVyYWN0aW9uVHlwZVwiLCB0eXA6IFwiXCIgfSxcbiAgICAgICAgeyBqc29uOiBcIm9yaWdpblwiLCBqczogXCJvcmlnaW5cIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInBhcnRpY2lwYW50c1wiLCBqczogXCJwYXJ0aWNpcGFudHNcIiwgdHlwOiByKFwiQ29udGFjdExpc3RPYmplY3RcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInRpbWVSYW5nZVwiLCBqczogXCJ0aW1lUmFuZ2VcIiwgdHlwOiByKFwiVGltZVJhbmdlT2JqZWN0XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiSW50ZXJhY3Rpb25UeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkludGVyYWN0aW9uSURcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJTQUxFU0ZPUkNFXCIsIGpzOiBcIlNBTEVTRk9SQ0VcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIlNJTkdMRVRSQUNLXCIsIGpzOiBcIlNJTkdMRVRSQUNLXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJVUklcIiwganM6IFwiVVJJXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJNZXNzYWdlXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiZW50aXRpZXNcIiwganM6IFwiZW50aXRpZXNcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShyKFwiRmx1ZmZ5QWN0aW9uXCIpKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInRleHRcIiwganM6IFwidGV4dFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiRmx1ZmZ5TWVzc2FnZVRleHRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiTWVzc2FnZVR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkZsdWZmeUFjdGlvblwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImFwcFwiLCBqczogXCJhcHBcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkFjdGlvblRhcmdldEFwcFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImNvbnRleHRcIiwganM6IFwiY29udGV4dFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiQ29udGV4dEVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJpbnRlbnRcIiwganM6IFwiaW50ZW50XCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0aXRsZVwiLCBqczogXCJ0aXRsZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIkVudGl0eVR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogdSh1bmRlZmluZWQsIG0oXCJhbnlcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImRhdGFcIiwganM6IFwiZGF0YVwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiRmx1ZmZ5RGF0YVwiKSkgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIkZsdWZmeURhdGFcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJkYXRhVXJpXCIsIGpzOiBcImRhdGFVcmlcIiwgdHlwOiBcIlwiIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiBcIlwiIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJGbHVmZnlNZXNzYWdlVGV4dFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcInRleHQvbWFya2Rvd25cIiwganM6IFwidGV4dC9tYXJrZG93blwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidGV4dC9wbGFpblwiLCBqczogXCJ0ZXh0L3BsYWluXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJOb3RoaW5nXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIk5vdGhpbmdUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJPcmRlclwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImRldGFpbHNcIiwganM6IFwiZGV0YWlsc1wiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiUHVycGxlT3JkZXJEZXRhaWxzXCIpKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiBtKFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJPcmRlclR5cGVcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlB1cnBsZU9yZGVyRGV0YWlsc1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcInByb2R1Y3RcIiwganM6IFwicHJvZHVjdFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiUHJvZHVjdE9iamVjdFwiKSkgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlByb2R1Y3RPYmplY3RcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IG0oXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RydW1lbnRcIiwganM6IFwiaW5zdHJ1bWVudFwiLCB0eXA6IHUodW5kZWZpbmVkLCByKFwiSW5zdHJ1bWVudEVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJuYW1lXCIsIGpzOiBcIm5hbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJQcm9kdWN0VHlwZVwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiT3JkZXJMaXN0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwib3JkZXJzXCIsIGpzOiBcIm9yZGVyc1wiLCB0eXA6IGEocihcIk9yZGVyRWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJPcmRlckxpc3RUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJPcmRlckVsZW1lbnRcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJkZXRhaWxzXCIsIGpzOiBcImRldGFpbHNcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIkZsdWZmeU9yZGVyRGV0YWlsc1wiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogbShcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiT3JkZXJUeXBlXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJGbHVmZnlPcmRlckRldGFpbHNcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJwcm9kdWN0XCIsIGpzOiBcInByb2R1Y3RcIiwgdHlwOiB1KHVuZGVmaW5lZCwgcihcIlByb2R1Y3RPYmplY3RcIikpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJPcmdhbml6YXRpb25cIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHIoXCJPcmdhbml6YXRpb25JZGVudGlmaWVyc1wiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlN0aWNreUludGVyYWN0aW9uVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJPcmdhbml6YXRpb25JZGVudGlmaWVyc1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcIkZEU19JRFwiLCBqczogXCJGRFNfSURcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIkxFSVwiLCBqczogXCJMRUlcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIlBFUk1JRFwiLCBqczogXCJQRVJNSURcIiwgdHlwOiB1KHVuZGVmaW5lZCwgXCJcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlBvcnRmb2xpb1wiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcInBvc2l0aW9uc1wiLCBqczogXCJwb3NpdGlvbnNcIiwgdHlwOiBhKHIoXCJQb3NpdGlvbkVsZW1lbnRcIikpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiUG9ydGZvbGlvVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiUG9zaXRpb25FbGVtZW50XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiaG9sZGluZ1wiLCBqczogXCJob2xkaW5nXCIsIHR5cDogMy4xNCB9LFxuICAgICAgICB7IGpzb246IFwiaW5zdHJ1bWVudFwiLCBqczogXCJpbnN0cnVtZW50XCIsIHR5cDogcihcIkluc3RydW1lbnRFbGVtZW50XCIpIH0sXG4gICAgICAgIHsganNvbjogXCJ0eXBlXCIsIGpzOiBcInR5cGVcIiwgdHlwOiByKFwiUG9zaXRpb25UeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJQb3NpdGlvblwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImhvbGRpbmdcIiwganM6IFwiaG9sZGluZ1wiLCB0eXA6IDMuMTQgfSxcbiAgICAgICAgeyBqc29uOiBcImluc3RydW1lbnRcIiwganM6IFwiaW5zdHJ1bWVudFwiLCB0eXA6IHIoXCJJbnN0cnVtZW50RWxlbWVudFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlBvc2l0aW9uVHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiUHJvZHVjdFwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogbShcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaW5zdHJ1bWVudFwiLCBqczogXCJpbnN0cnVtZW50XCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJJbnN0cnVtZW50RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlByb2R1Y3RUeXBlXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJUaW1lUmFuZ2VcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJlbmRUaW1lXCIsIGpzOiBcImVuZFRpbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgRGF0ZSkgfSxcbiAgICAgICAgeyBqc29uOiBcInN0YXJ0VGltZVwiLCBqczogXCJzdGFydFRpbWVcIiwgdHlwOiB1KHVuZGVmaW5lZCwgRGF0ZSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJUaW1lUmFuZ2VUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJUcmFkZVwiOiBvKFtcbiAgICAgICAgeyBqc29uOiBcImlkXCIsIGpzOiBcImlkXCIsIHR5cDogbShcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJwcm9kdWN0XCIsIGpzOiBcInByb2R1Y3RcIiwgdHlwOiByKFwiUHJvZHVjdE9iamVjdFwiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlRyYWRlVHlwZVwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiVHJhZGVMaXN0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwidHJhZGVzXCIsIGpzOiBcInRyYWRlc1wiLCB0eXA6IGEocihcIlRyYWRlRWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJUcmFkZUxpc3RUeXBlXCIpIH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJUcmFkZUVsZW1lbnRcIjogbyhbXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IG0oXCJcIikgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwicHJvZHVjdFwiLCBqczogXCJwcm9kdWN0XCIsIHR5cDogcihcIlByb2R1Y3RPYmplY3RcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInR5cGVcIiwganM6IFwidHlwZVwiLCB0eXA6IHIoXCJUcmFkZVR5cGVcIikgfSxcbiAgICBdLCBcImFueVwiKSxcbiAgICBcIlRyYW5zYWN0aW9uUmVzdWx0XCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiY29udGV4dFwiLCBqczogXCJjb250ZXh0XCIsIHR5cDogdSh1bmRlZmluZWQsIHIoXCJDb250ZXh0RWxlbWVudFwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm1lc3NhZ2VcIiwganM6IFwibWVzc2FnZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgICAgICB7IGpzb246IFwic3RhdHVzXCIsIGpzOiBcInN0YXR1c1wiLCB0eXA6IHIoXCJUcmFuc2FjdGlvblN0YXR1c1wiKSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlRyYW5zYWN0aW9uUmVzdWx0VHlwZVwiKSB9LFxuICAgICAgICB7IGpzb246IFwiaWRcIiwganM6IFwiaWRcIiwgdHlwOiB1KHVuZGVmaW5lZCwgbShcImFueVwiKSkgfSxcbiAgICAgICAgeyBqc29uOiBcIm5hbWVcIiwganM6IFwibmFtZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBcIlwiKSB9LFxuICAgIF0sIFwiYW55XCIpLFxuICAgIFwiVmFsdWF0aW9uXCI6IG8oW1xuICAgICAgICB7IGpzb246IFwiQ1VSUkVOQ1lfSVNPQ09ERVwiLCBqczogXCJDVVJSRU5DWV9JU09DT0RFXCIsIHR5cDogXCJcIiB9LFxuICAgICAgICB7IGpzb246IFwiZXhwaXJ5VGltZVwiLCBqczogXCJleHBpcnlUaW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIERhdGUpIH0sXG4gICAgICAgIHsganNvbjogXCJwcmljZVwiLCBqczogXCJwcmljZVwiLCB0eXA6IHUodW5kZWZpbmVkLCAzLjE0KSB9LFxuICAgICAgICB7IGpzb246IFwidHlwZVwiLCBqczogXCJ0eXBlXCIsIHR5cDogcihcIlZhbHVhdGlvblR5cGVcIikgfSxcbiAgICAgICAgeyBqc29uOiBcInZhbHVhdGlvblRpbWVcIiwganM6IFwidmFsdWF0aW9uVGltZVwiLCB0eXA6IHUodW5kZWZpbmVkLCBEYXRlKSB9LFxuICAgICAgICB7IGpzb246IFwidmFsdWVcIiwganM6IFwidmFsdWVcIiwgdHlwOiAzLjE0IH0sXG4gICAgICAgIHsganNvbjogXCJpZFwiLCBqczogXCJpZFwiLCB0eXA6IHUodW5kZWZpbmVkLCBtKFwiYW55XCIpKSB9LFxuICAgICAgICB7IGpzb246IFwibmFtZVwiLCBqczogXCJuYW1lXCIsIHR5cDogdSh1bmRlZmluZWQsIFwiXCIpIH0sXG4gICAgXSwgXCJhbnlcIiksXG4gICAgXCJBY3Rpb25UeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmFjdGlvblwiLFxuICAgIF0sXG4gICAgXCJQdXJwbGVJbnRlcmFjdGlvblR5cGVcIjogW1xuICAgICAgICBcImZkYzMuaW5zdHJ1bWVudFwiLFxuICAgIF0sXG4gICAgXCJUaW1lUmFuZ2VUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLnRpbWVSYW5nZVwiLFxuICAgIF0sXG4gICAgXCJDaGFydFN0eWxlXCI6IFtcbiAgICAgICAgXCJiYXJcIixcbiAgICAgICAgXCJjYW5kbGVcIixcbiAgICAgICAgXCJjdXN0b21cIixcbiAgICAgICAgXCJoZWF0bWFwXCIsXG4gICAgICAgIFwiaGlzdG9ncmFtXCIsXG4gICAgICAgIFwibGluZVwiLFxuICAgICAgICBcIm1vdW50YWluXCIsXG4gICAgICAgIFwicGllXCIsXG4gICAgICAgIFwic2NhdHRlclwiLFxuICAgICAgICBcInN0YWNrZWQtYmFyXCIsXG4gICAgXSxcbiAgICBcIkNoYXJ0VHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5jaGFydFwiLFxuICAgIF0sXG4gICAgXCJGbHVmZnlJbnRlcmFjdGlvblR5cGVcIjogW1xuICAgICAgICBcImZkYzMuY29udGFjdFwiLFxuICAgIF0sXG4gICAgXCJDb250YWN0TGlzdFR5cGVcIjogW1xuICAgICAgICBcImZkYzMuY29udGFjdExpc3RcIixcbiAgICBdLFxuICAgIFwiRW50aXR5VHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5hY3Rpb25cIixcbiAgICAgICAgXCJmZGMzLmVudGl0eS5maWxlQXR0YWNobWVudFwiLFxuICAgIF0sXG4gICAgXCJNZXNzYWdlVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5tZXNzYWdlXCIsXG4gICAgXSxcbiAgICBcIkNoYXRJbml0U2V0dGluZ3NUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmNoYXQuaW5pdFNldHRpbmdzXCIsXG4gICAgXSxcbiAgICBcIkNoYXRSb29tVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5jaGF0LnJvb21cIixcbiAgICBdLFxuICAgIFwiQ2hhdE1lc3NhZ2VUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmNoYXQubWVzc2FnZVwiLFxuICAgIF0sXG4gICAgXCJUZW50YWNsZWRJbnRlcmFjdGlvblR5cGVcIjogW1xuICAgICAgICBcImZkYzMuY29udGFjdFwiLFxuICAgICAgICBcImZkYzMuaW5zdHJ1bWVudFwiLFxuICAgICAgICBcImZkYzMub3JnYW5pemF0aW9uXCIsXG4gICAgXSxcbiAgICBcIkNoYXRTZWFyY2hDcml0ZXJpYVR5cGVcIjogW1xuICAgICAgICBcImZkYzMuY2hhdC5zZWFyY2hDcml0ZXJpYVwiLFxuICAgIF0sXG4gICAgXCJDb3VudHJ5VHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5jb3VudHJ5XCIsXG4gICAgXSxcbiAgICBcIkN1cnJlbmN5VHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5jdXJyZW5jeVwiLFxuICAgIF0sXG4gICAgXCJFbWFpbFJlY2lwaWVudHNUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmNvbnRhY3RcIixcbiAgICAgICAgXCJmZGMzLmNvbnRhY3RMaXN0XCIsXG4gICAgXSxcbiAgICBcIkVtYWlsVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5lbWFpbFwiLFxuICAgIF0sXG4gICAgXCJJbnN0cnVtZW50TGlzdFR5cGVcIjogW1xuICAgICAgICBcImZkYzMuaW5zdHJ1bWVudExpc3RcIixcbiAgICBdLFxuICAgIFwiSW50ZXJhY3Rpb25UeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLmludGVyYWN0aW9uXCIsXG4gICAgXSxcbiAgICBcIk5vdGhpbmdUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLm5vdGhpbmdcIixcbiAgICBdLFxuICAgIFwiUHJvZHVjdFR5cGVcIjogW1xuICAgICAgICBcImZkYzMucHJvZHVjdFwiLFxuICAgIF0sXG4gICAgXCJPcmRlclR5cGVcIjogW1xuICAgICAgICBcImZkYzMub3JkZXJcIixcbiAgICBdLFxuICAgIFwiT3JkZXJMaXN0VHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5vcmRlckxpc3RcIixcbiAgICBdLFxuICAgIFwiU3RpY2t5SW50ZXJhY3Rpb25UeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLm9yZ2FuaXphdGlvblwiLFxuICAgIF0sXG4gICAgXCJQb3NpdGlvblR5cGVcIjogW1xuICAgICAgICBcImZkYzMucG9zaXRpb25cIixcbiAgICBdLFxuICAgIFwiUG9ydGZvbGlvVHlwZVwiOiBbXG4gICAgICAgIFwiZmRjMy5wb3J0Zm9saW9cIixcbiAgICBdLFxuICAgIFwiVHJhZGVUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLnRyYWRlXCIsXG4gICAgXSxcbiAgICBcIlRyYWRlTGlzdFR5cGVcIjogW1xuICAgICAgICBcImZkYzMudHJhZGVMaXN0XCIsXG4gICAgXSxcbiAgICBcIlRyYW5zYWN0aW9uU3RhdHVzXCI6IFtcbiAgICAgICAgXCJDcmVhdGVkXCIsXG4gICAgICAgIFwiRGVsZXRlZFwiLFxuICAgICAgICBcIkZhaWxlZFwiLFxuICAgICAgICBcIlVwZGF0ZWRcIixcbiAgICBdLFxuICAgIFwiVHJhbnNhY3Rpb25SZXN1bHRUeXBlXCI6IFtcbiAgICAgICAgXCJmZGMzLnRyYW5zYWN0aW9uUmVzdWx0XCIsXG4gICAgXSxcbiAgICBcIlZhbHVhdGlvblR5cGVcIjogW1xuICAgICAgICBcImZkYzMudmFsdWF0aW9uXCIsXG4gICAgXVxufTtcblxuLyoqXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICogQ29weXJpZ2h0IEZJTk9TIEZEQzMgY29udHJpYnV0b3JzIC0gc2VlIE5PVElDRSBmaWxlXG4gKi9cbi8qKlxuICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayBTdGFuZGFyZEludGVudH0gaW5zdGVhZFxuICovXG52YXIgSW50ZW50cztcbihmdW5jdGlvbiAoSW50ZW50cykge1xuICAgIEludGVudHNbXCJDcmVhdGVJbnRlcmFjdGlvblwiXSA9IFwiQ3JlYXRlSW50ZXJhY3Rpb25cIjtcbiAgICBJbnRlbnRzW1wiU2VuZENoYXRNZXNzYWdlXCJdID0gXCJTZW5kQ2hhdE1lc3NhZ2VcIjtcbiAgICBJbnRlbnRzW1wiU3RhcnRDYWxsXCJdID0gXCJTdGFydENhbGxcIjtcbiAgICBJbnRlbnRzW1wiU3RhcnRDaGF0XCJdID0gXCJTdGFydENoYXRcIjtcbiAgICBJbnRlbnRzW1wiU3RhcnRFbWFpbFwiXSA9IFwiU3RhcnRFbWFpbFwiO1xuICAgIEludGVudHNbXCJWaWV3QW5hbHlzaXNcIl0gPSBcIlZpZXdBbmFseXNpc1wiO1xuICAgIEludGVudHNbXCJWaWV3Q2hhdFwiXSA9IFwiVmlld0NoYXRcIjtcbiAgICBJbnRlbnRzW1wiVmlld0NoYXJ0XCJdID0gXCJWaWV3Q2hhcnRcIjtcbiAgICBJbnRlbnRzW1wiVmlld0NvbnRhY3RcIl0gPSBcIlZpZXdDb250YWN0XCI7XG4gICAgSW50ZW50c1tcIlZpZXdIb2xkaW5nc1wiXSA9IFwiVmlld0hvbGRpbmdzXCI7XG4gICAgSW50ZW50c1tcIlZpZXdJbnN0cnVtZW50XCJdID0gXCJWaWV3SW5zdHJ1bWVudFwiO1xuICAgIEludGVudHNbXCJWaWV3SW50ZXJhY3Rpb25zXCJdID0gXCJWaWV3SW50ZXJhY3Rpb25zXCI7XG4gICAgSW50ZW50c1tcIlZpZXdNZXNzYWdlc1wiXSA9IFwiVmlld01lc3NhZ2VzXCI7XG4gICAgSW50ZW50c1tcIlZpZXdOZXdzXCJdID0gXCJWaWV3TmV3c1wiO1xuICAgIEludGVudHNbXCJWaWV3T3JkZXJzXCJdID0gXCJWaWV3T3JkZXJzXCI7XG4gICAgSW50ZW50c1tcIlZpZXdQcm9maWxlXCJdID0gXCJWaWV3UHJvZmlsZVwiO1xuICAgIEludGVudHNbXCJWaWV3UXVvdGVcIl0gPSBcIlZpZXdRdW90ZVwiO1xuICAgIEludGVudHNbXCJWaWV3UmVzZWFyY2hcIl0gPSBcIlZpZXdSZXNlYXJjaFwiO1xufSkoSW50ZW50cyB8fCAoSW50ZW50cyA9IHt9KSk7XG5cbmV4cG9ydCB7IEJyaWRnaW5nRXJyb3IsIEJyaWRnaW5nVHlwZXMsIENoYW5uZWxFcnJvciwgQ29udGV4dFR5cGVzLCBDb252ZXJ0LCBJbnRlbnRzLCBPcGVuRXJyb3IsIFJlc29sdmVFcnJvciwgUmVzdWx0RXJyb3IsIGFkZENvbnRleHRMaXN0ZW5lciwgYWRkSW50ZW50TGlzdGVuZXIsIGJyb2FkY2FzdCwgY29tcGFyZVZlcnNpb25OdW1iZXJzLCBjcmVhdGVQcml2YXRlQ2hhbm5lbCwgZmRjM1JlYWR5LCBmaW5kSW5zdGFuY2VzLCBmaW5kSW50ZW50LCBmaW5kSW50ZW50c0J5Q29udGV4dCwgZ2V0QXBwTWV0YWRhdGEsIGdldEN1cnJlbnRDaGFubmVsLCBnZXRJbmZvLCBnZXRPckNyZWF0ZUNoYW5uZWwsIGdldFN5c3RlbUNoYW5uZWxzLCBnZXRVc2VyQ2hhbm5lbHMsIGlzU3RhbmRhcmRDb250ZXh0VHlwZSwgaXNTdGFuZGFyZEludGVudCwgam9pbkNoYW5uZWwsIGpvaW5Vc2VyQ2hhbm5lbCwgbGVhdmVDdXJyZW50Q2hhbm5lbCwgb3BlbiwgcmFpc2VJbnRlbnQsIHJhaXNlSW50ZW50Rm9yQ29udGV4dCwgdmVyc2lvbklzQXRMZWFzdCB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZmRjMy5lc20uanMubWFwXG4iLCIvLyBUaGUgbW9kdWxlIGNhY2hlXG52YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307XG5cbi8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG5mdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuXHR2YXIgY2FjaGVkTW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXTtcblx0aWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzO1xuXHR9XG5cdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG5cdHZhciBtb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdID0ge1xuXHRcdC8vIG5vIG1vZHVsZS5pZCBuZWVkZWRcblx0XHQvLyBubyBtb2R1bGUubG9hZGVkIG5lZWRlZFxuXHRcdGV4cG9ydHM6IHt9XG5cdH07XG5cblx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG5cdF9fd2VicGFja19tb2R1bGVzX19bbW9kdWxlSWRdKG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG5cdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG5cdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbn1cblxuIiwiLy8gZGVmaW5lIGdldHRlciBmdW5jdGlvbnMgZm9yIGhhcm1vbnkgZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5kID0gKGV4cG9ydHMsIGRlZmluaXRpb24pID0+IHtcblx0Zm9yKHZhciBrZXkgaW4gZGVmaW5pdGlvbikge1xuXHRcdGlmKF9fd2VicGFja19yZXF1aXJlX18ubyhkZWZpbml0aW9uLCBrZXkpICYmICFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywga2V5KSkge1xuXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIGtleSwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGRlZmluaXRpb25ba2V5XSB9KTtcblx0XHR9XG5cdH1cbn07IiwiX193ZWJwYWNrX3JlcXVpcmVfXy5vID0gKG9iaiwgcHJvcCkgPT4gKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKSIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsImltcG9ydCB7IGdldEN1cnJlbnRDaGFubmVsIH0gZnJvbSBcIkBmaW5vcy9mZGMzXCI7XG5cbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJET01Db250ZW50TG9hZGVkXCIsIGFzeW5jICgpID0+IHtcblx0dHJ5IHtcblx0XHRhd2FpdCBpbml0RG9tKCk7XG5cdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0Y29uc29sZS5lcnJvcihlcnJvcik7XG5cdH1cbn0pO1xuXG4vKipcbiAqIEluaXRpYWxpemUgdGhlIERPTSBlbGVtZW50cy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gaW5pdERvbSgpOiBQcm9taXNlPHZvaWQ+IHtcblx0dHJ5IHtcblx0XHRjb25zdCBhcHBDaGFubmVsID0gYXdhaXQgZ2V0Q3VycmVudENoYW5uZWwoKTtcblxuXHRcdGlmIChhcHBDaGFubmVsKSB7XG5cdFx0XHRhd2FpdCBhcHBDaGFubmVsLmFkZENvbnRleHRMaXN0ZW5lcihudWxsLCAoY3R4KSA9PiB7XG5cdFx0XHRcdGlmIChjdHgudHlwZSA9PT0gXCJmZGMzLmluc3RydW1lbnRcIikge1xuXHRcdFx0XHRcdGNvbnN0IHJlY2VpdmVFbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MSW5wdXRFbGVtZW50PihcIiNyZWNlaXZlZC1pbnN0cnVtZW50XCIpO1xuXHRcdFx0XHRcdGlmIChyZWNlaXZlRWxlbWVudCkge1xuXHRcdFx0XHRcdFx0cmVjZWl2ZUVsZW1lbnQudmFsdWUgPSBjdHguaWQ/LnRpY2tlcjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0c2hvd0Vycm9yKGVycik7XG5cdH1cbn1cblxuLyoqXG4gKiBTaG93IGFuIGVycm9yIG9uIHRoZSBVSS5cbiAqIEBwYXJhbSBlcnIgVGhlIGVycm9yIHRvIGRpc3BsYXkuXG4gKi9cbmZ1bmN0aW9uIHNob3dFcnJvcihlcnI6IHVua25vd24pOiB2b2lkIHtcblx0Y29uc3QgZXJyRG9tID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNlcnJvclwiKTtcblx0aWYgKGVyckRvbSkge1xuXHRcdGVyckRvbS5pbm5lckhUTUwgPSBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogSlNPTi5zdHJpbmdpZnkoZXJyKTtcblx0fVxufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dev/john/update-logging-example/integration-excel/js/platform-tray.bundle.js b/dev/john/update-logging-example/integration-excel/js/platform-tray.bundle.js new file mode 100644 index 00000000..40836b2b --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/js/platform-tray.bundle.js @@ -0,0 +1,112 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!*************************************!*\ + !*** ./client/src/provider-tray.ts ***! + \*************************************/ +__webpack_require__.r(__webpack_exports__); +window.addEventListener("DOMContentLoaded", async () => { + const platform = fin.Platform.getCurrentSync(); + await platform.once("platform-api-ready", async () => initDom()); +}); +fin.Platform.init().catch(() => { }); +/** + * Initialize the DOM elements. + */ +async function initDom() { + console.log("Platform Init"); + const application = await fin.Application.getCurrent(); + await application.setTrayIcon("https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/integration-excel/favicon.ico"); + let visible = false; + let win; + await application.addListener("tray-icon-clicked", async (trayInfo) => { + if (!visible) { + if (win) { + try { + // Try showing window, if it fails we need to create it + await win.show(); + } + catch { + win = undefined; + } + } + if (!win) { + // Work out which monitor the tray icon is on + const monitors = [ + trayInfo.monitorInfo.primaryMonitor, + ...trayInfo.monitorInfo.nonPrimaryMonitors + ]; + const foundMonitor = monitors.find((mi) => pointInRect(mi.monitorRect, { x: trayInfo.x, y: trayInfo.y })); + const winWidth = 250; + const winOption = { + name: "excel-tray-view", + includeInSnapshot: false, + showTaskbarIcon: false, + saveWindowState: false, + defaultTop: foundMonitor?.availableRect.top, + defaultLeft: foundMonitor ? foundMonitor?.availableRect?.right - winWidth : undefined, + defaultWidth: winWidth, + defaultHeight: foundMonitor + ? foundMonitor.availableRect.bottom - foundMonitor.availableRect.top + : undefined, + url: "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/integration-excel/views/excel.html", + frame: false, + autoShow: true, + alwaysOnTop: true, + resizable: false, + permissions: { + System: { + launchExternalProcess: true, + downloadAsset: true, + openUrlWithBrowser: { + enabled: true, + protocols: ["mailto"] + } + } + } + }; + win = await fin.Window.create(winOption); + } + } + else if (win) { + await win.hide(); + } + visible = !visible; + }); +} +/** + * Is the point inside the rectangle. + * @param rect The rectangle to test. + * @param rect.left The rectangle left position. + * @param rect.top The rectangle top position. + * @param rect.right The rectangle right position. + * @param rect.bottom The rectangle bottom position. + * @param pt The point to check. + * @param pt.x The point x position. + * @param pt.y The point y position. + * @returns True if the point is in the rect. + */ +function pointInRect(rect, pt) { + return pt.x > rect.left && pt.x < rect.right && pt.y > rect.top && pt.y < rect.bottom; +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QixXQUFXLEVBQUU7d0JBQ1osTUFBTSxFQUFFOzRCQUNQLHFCQUFxQixFQUFFLElBQUk7NEJBQzNCLGFBQWEsRUFBRSxJQUFJOzRCQUNuQixrQkFBa0IsRUFBRTtnQ0FDbkIsT0FBTyxFQUFFLElBQUk7Z0NBQ2IsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDOzZCQUNyQjt5QkFDRDtxQkFDRDtpQkFDRCxDQUFDO2dCQUVGLEdBQUcsR0FBRyxNQUFNLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQzFDLENBQUM7UUFDRixDQUFDO2FBQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNoQixNQUFNLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsQixDQUFDO1FBRUQsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDO0lBQ3BCLENBQUMsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsU0FBUyxXQUFXLENBQ25CLElBQWtFLEVBQ2xFLEVBQTRCO0lBRTVCLE9BQU8sRUFBRSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0FBQ3ZGLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL2ludGVncmF0aW9uLWV4Y2VsLy4vY2xpZW50L3NyYy9wcm92aWRlci10cmF5LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSByZXF1aXJlIHNjb3BlXG52YXIgX193ZWJwYWNrX3JlcXVpcmVfXyA9IHt9O1xuXG4iLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgdHlwZSBPcGVuRmluIGZyb20gXCJAb3BlbmZpbi9jb3JlXCI7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBhc3luYyAoKSA9PiB7XG5cdGNvbnN0IHBsYXRmb3JtOiBPcGVuRmluLlBsYXRmb3JtID0gZmluLlBsYXRmb3JtLmdldEN1cnJlbnRTeW5jKCk7XG5cdGF3YWl0IHBsYXRmb3JtLm9uY2UoXCJwbGF0Zm9ybS1hcGktcmVhZHlcIiwgYXN5bmMgKCkgPT4gaW5pdERvbSgpKTtcbn0pO1xuXG5maW4uUGxhdGZvcm0uaW5pdCgpLmNhdGNoKCgpID0+IHt9KTtcblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSBET00gZWxlbWVudHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluaXREb20oKTogUHJvbWlzZTx2b2lkPiB7XG5cdGNvbnNvbGUubG9nKFwiUGxhdGZvcm0gSW5pdFwiKTtcblxuXHRjb25zdCBhcHBsaWNhdGlvbiA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdGF3YWl0IGFwcGxpY2F0aW9uLnNldFRyYXlJY29uKFwiaHR0cDovL2xvY2FsaG9zdDo1MDUwL2Zhdmljb24uaWNvXCIpO1xuXG5cdGxldCB2aXNpYmxlID0gZmFsc2U7XG5cdGxldCB3aW46IE9wZW5GaW4uV2luZG93IHwgdW5kZWZpbmVkO1xuXG5cdGF3YWl0IGFwcGxpY2F0aW9uLmFkZExpc3RlbmVyKFwidHJheS1pY29uLWNsaWNrZWRcIiwgYXN5bmMgKHRyYXlJbmZvOiBPcGVuRmluLlRyYXlJbmZvKSA9PiB7XG5cdFx0aWYgKCF2aXNpYmxlKSB7XG5cdFx0XHRpZiAod2luKSB7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Ly8gVHJ5IHNob3dpbmcgd2luZG93LCBpZiBpdCBmYWlscyB3ZSBuZWVkIHRvIGNyZWF0ZSBpdFxuXHRcdFx0XHRcdGF3YWl0IHdpbi5zaG93KCk7XG5cdFx0XHRcdH0gY2F0Y2gge1xuXHRcdFx0XHRcdHdpbiA9IHVuZGVmaW5lZDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIXdpbikge1xuXHRcdFx0XHQvLyBXb3JrIG91dCB3aGljaCBtb25pdG9yIHRoZSB0cmF5IGljb24gaXMgb25cblx0XHRcdFx0Y29uc3QgbW9uaXRvcnM6IE9wZW5GaW4uTW9uaXRvckRldGFpbHNbXSA9IFtcblx0XHRcdFx0XHR0cmF5SW5mby5tb25pdG9ySW5mby5wcmltYXJ5TW9uaXRvcixcblx0XHRcdFx0XHQuLi50cmF5SW5mby5tb25pdG9ySW5mby5ub25QcmltYXJ5TW9uaXRvcnNcblx0XHRcdFx0XTtcblxuXHRcdFx0XHRjb25zdCBmb3VuZE1vbml0b3IgPSBtb25pdG9ycy5maW5kKChtaSkgPT5cblx0XHRcdFx0XHRwb2ludEluUmVjdChtaS5tb25pdG9yUmVjdCwgeyB4OiB0cmF5SW5mby54LCB5OiB0cmF5SW5mby55IH0pXG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0Y29uc3Qgd2luV2lkdGggPSAyNTA7XG5cblx0XHRcdFx0Y29uc3Qgd2luT3B0aW9uID0ge1xuXHRcdFx0XHRcdG5hbWU6IFwiZXhjZWwtdHJheS12aWV3XCIsXG5cdFx0XHRcdFx0aW5jbHVkZUluU25hcHNob3Q6IGZhbHNlLFxuXHRcdFx0XHRcdHNob3dUYXNrYmFySWNvbjogZmFsc2UsXG5cdFx0XHRcdFx0c2F2ZVdpbmRvd1N0YXRlOiBmYWxzZSxcblx0XHRcdFx0XHRkZWZhdWx0VG9wOiBmb3VuZE1vbml0b3I/LmF2YWlsYWJsZVJlY3QudG9wLFxuXHRcdFx0XHRcdGRlZmF1bHRMZWZ0OiBmb3VuZE1vbml0b3IgPyBmb3VuZE1vbml0b3I/LmF2YWlsYWJsZVJlY3Q/LnJpZ2h0IC0gd2luV2lkdGggOiB1bmRlZmluZWQsXG5cdFx0XHRcdFx0ZGVmYXVsdFdpZHRoOiB3aW5XaWR0aCxcblx0XHRcdFx0XHRkZWZhdWx0SGVpZ2h0OiBmb3VuZE1vbml0b3Jcblx0XHRcdFx0XHRcdD8gZm91bmRNb25pdG9yLmF2YWlsYWJsZVJlY3QuYm90dG9tIC0gZm91bmRNb25pdG9yLmF2YWlsYWJsZVJlY3QudG9wXG5cdFx0XHRcdFx0XHQ6IHVuZGVmaW5lZCxcblx0XHRcdFx0XHR1cmw6IFwiaHR0cDovL2xvY2FsaG9zdDo1MDUwL3ZpZXdzL2V4Y2VsLmh0bWxcIixcblx0XHRcdFx0XHRmcmFtZTogZmFsc2UsXG5cdFx0XHRcdFx0YXV0b1Nob3c6IHRydWUsXG5cdFx0XHRcdFx0YWx3YXlzT25Ub3A6IHRydWUsXG5cdFx0XHRcdFx0cmVzaXphYmxlOiBmYWxzZSxcblx0XHRcdFx0XHRwZXJtaXNzaW9uczoge1xuXHRcdFx0XHRcdFx0U3lzdGVtOiB7XG5cdFx0XHRcdFx0XHRcdGxhdW5jaEV4dGVybmFsUHJvY2VzczogdHJ1ZSxcblx0XHRcdFx0XHRcdFx0ZG93bmxvYWRBc3NldDogdHJ1ZSxcblx0XHRcdFx0XHRcdFx0b3BlblVybFdpdGhCcm93c2VyOiB7XG5cdFx0XHRcdFx0XHRcdFx0ZW5hYmxlZDogdHJ1ZSxcblx0XHRcdFx0XHRcdFx0XHRwcm90b2NvbHM6IFtcIm1haWx0b1wiXVxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuY3JlYXRlKHdpbk9wdGlvbik7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIGlmICh3aW4pIHtcblx0XHRcdGF3YWl0IHdpbi5oaWRlKCk7XG5cdFx0fVxuXG5cdFx0dmlzaWJsZSA9ICF2aXNpYmxlO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBJcyB0aGUgcG9pbnQgaW5zaWRlIHRoZSByZWN0YW5nbGUuXG4gKiBAcGFyYW0gcmVjdCBUaGUgcmVjdGFuZ2xlIHRvIHRlc3QuXG4gKiBAcGFyYW0gcmVjdC5sZWZ0IFRoZSByZWN0YW5nbGUgbGVmdCBwb3NpdGlvbi5cbiAqIEBwYXJhbSByZWN0LnRvcCBUaGUgcmVjdGFuZ2xlIHRvcCBwb3NpdGlvbi5cbiAqIEBwYXJhbSByZWN0LnJpZ2h0IFRoZSByZWN0YW5nbGUgcmlnaHQgcG9zaXRpb24uXG4gKiBAcGFyYW0gcmVjdC5ib3R0b20gVGhlIHJlY3RhbmdsZSBib3R0b20gcG9zaXRpb24uXG4gKiBAcGFyYW0gcHQgVGhlIHBvaW50IHRvIGNoZWNrLlxuICogQHBhcmFtIHB0LnggVGhlIHBvaW50IHggcG9zaXRpb24uXG4gKiBAcGFyYW0gcHQueSBUaGUgcG9pbnQgeSBwb3NpdGlvbi5cbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHBvaW50IGlzIGluIHRoZSByZWN0LlxuICovXG5mdW5jdGlvbiBwb2ludEluUmVjdChcblx0cmVjdDogeyBsZWZ0OiBudW1iZXI7IHRvcDogbnVtYmVyOyByaWdodDogbnVtYmVyOyBib3R0b206IG51bWJlciB9LFxuXHRwdDogeyB4OiBudW1iZXI7IHk6IG51bWJlciB9XG4pOiBib29sZWFuIHtcblx0cmV0dXJuIHB0LnggPiByZWN0LmxlZnQgJiYgcHQueCA8IHJlY3QucmlnaHQgJiYgcHQueSA+IHJlY3QudG9wICYmIHB0LnkgPCByZWN0LmJvdHRvbTtcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/integration-excel/js/platform.bundle.js b/dev/john/update-logging-example/integration-excel/js/platform.bundle.js new file mode 100644 index 00000000..94717a97 --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/js/platform.bundle.js @@ -0,0 +1,39 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!********************************!*\ + !*** ./client/src/provider.ts ***! + \********************************/ +__webpack_require__.r(__webpack_exports__); +window.addEventListener("DOMContentLoaded", async () => { + const platform = fin.Platform.getCurrentSync(); + await platform.once("platform-api-ready", async () => initDom()); +}); +fin.Platform.init().catch(() => { }); +/** + * Initialize the DOM elements. + */ +async function initDom() { + console.log("Platform Init"); +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhdGZvcm0uYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7O1VBQUE7VUFDQTs7Ozs7V0NEQTtXQUNBO1dBQ0E7V0FDQSx1REFBdUQsaUJBQWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0Q7Ozs7Ozs7OztBQ0pBLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN0RCxNQUFNLFFBQVEsR0FBcUIsR0FBRyxDQUFDLFFBQVEsQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUNqRSxNQUFNLFFBQVEsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0FBQ2xFLENBQUMsQ0FBQyxDQUFDO0FBRUgsR0FBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7QUFFcEM7O0dBRUc7QUFDSCxLQUFLLFVBQVUsT0FBTztJQUNyQixPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0FBQzlCLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9pbnRlZ3JhdGlvbi1leGNlbC93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL2ludGVncmF0aW9uLWV4Y2VsLy4vY2xpZW50L3NyYy9wcm92aWRlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgYXN5bmMgKCkgPT4ge1xuXHRjb25zdCBwbGF0Zm9ybTogT3BlbkZpbi5QbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuXHRhd2FpdCBwbGF0Zm9ybS5vbmNlKFwicGxhdGZvcm0tYXBpLXJlYWR5XCIsIGFzeW5jICgpID0+IGluaXREb20oKSk7XG59KTtcblxuZmluLlBsYXRmb3JtLmluaXQoKS5jYXRjaCgoKSA9PiB7fSk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgRE9NIGVsZW1lbnRzLlxuICovXG5hc3luYyBmdW5jdGlvbiBpbml0RG9tKCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zb2xlLmxvZyhcIlBsYXRmb3JtIEluaXRcIik7XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/integration-excel/manifest.fin.json b/dev/john/update-logging-example/integration-excel/manifest.fin.json new file mode 100644 index 00000000..6a6aeefa --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/manifest.fin.json @@ -0,0 +1,107 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "integration-excel", + "applicationIcon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/integration-excel/favicon.ico", + "providerUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/integration-excel/provider/provider.html", + "autoShow": false, + "permissions": { + "System": { + "launchExternalProcess": true, + "downloadAsset": true, + "openUrlWithBrowser": { + "enabled": true, + "protocols": ["mailto"] + } + } + } + }, + "snapshot": { + "windows": [ + { + "defaultWidth": 800, + "defaultHeight": 900, + "defaultLeft": 0, + "defaultTop": 0, + "saveWindowState": false, + "backgroundThrottling": true, + "layout": { + "content": [ + { + "type": "column", + "id": "mainRow", + "isClosable": true, + "reorderEnabled": true, + "title": "", + "content": [ + { + "type": "stack", + "width": 100, + "isClosable": true, + "reorderEnabled": true, + "title": "", + "activeItemIndex": 0, + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/integration-excel/views/excel.html", + "name": "excel-view", + "fdc3InteropApi": "1.2", + "interop": { + "currentContextGroup": "green" + }, + "permissions": { + "System": { + "launchExternalProcess": true, + "downloadAsset": true, + "openUrlWithBrowser": { + "enabled": true, + "protocols": ["mailto"] + } + } + } + }, + "isClosable": true, + "reorderEnabled": true, + "title": "view" + } + ] + }, + { + "type": "stack", + "width": 100, + "isClosable": true, + "reorderEnabled": true, + "title": "", + "activeItemIndex": 0, + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/integration-excel/views/fdc3monitor.html", + "name": "fdc3-view", + "fdc3InteropApi": "1.2", + "interop": { + "currentContextGroup": "green" + } + }, + "isClosable": true, + "reorderEnabled": true, + "title": "view" + } + ] + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/integration-excel/provider/provider-tray.html b/dev/john/update-logging-example/integration-excel/provider/provider-tray.html new file mode 100644 index 00000000..ef4949aa --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/provider/provider-tray.html @@ -0,0 +1,15 @@ + + + + + + OpenFin Provider + + + + + +

OpenFin Provider

+
Custom Provider...
+ + diff --git a/dev/john/update-logging-example/integration-excel/provider/provider.html b/dev/john/update-logging-example/integration-excel/provider/provider.html new file mode 100644 index 00000000..ad96ad81 --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/provider/provider.html @@ -0,0 +1,15 @@ + + + + + + OpenFin Provider + + + + + +

OpenFin Provider

+
Custom Provider...
+ + diff --git a/dev/john/update-logging-example/integration-excel/second.manifest.fin.json b/dev/john/update-logging-example/integration-excel/second.manifest.fin.json new file mode 100644 index 00000000..74149351 --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/second.manifest.fin.json @@ -0,0 +1,22 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "integration-excel-tray", + "applicationIcon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/integration-excel/favicon.ico", + "providerUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/integration-excel/provider/provider-tray.html", + "autoShow": false, + "permissions": { + "System": { + "launchExternalProcess": true, + "downloadAsset": true, + "openUrlWithBrowser": { + "enabled": true, + "protocols": ["mailto"] + } + } + } + } +} diff --git a/dev/john/update-logging-example/integration-excel/views/excel.html b/dev/john/update-logging-example/integration-excel/views/excel.html new file mode 100644 index 00000000..b722e090 --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/views/excel.html @@ -0,0 +1,103 @@ + + + + + + + Integrate with Excel + + + + + + +
+
+

Integrate with Excel

+

Demonstrate integration with Excel.

+
+
+ OpenFin +
+
+ +
+
+
+

Excel

+ +
+

Open Excel and select Workbook and Worksheet below to start view changes to it's cells.

+

+ This example application listens for cell changes and when the value is TSLA, MSFT or AAPL it will + create an fdc3.instrument context object with the value as the ticker and broadcast it. +

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

Results

+
+ +
+

+					
+ + +
+
+
+
+ + diff --git a/dev/john/update-logging-example/integration-excel/views/fdc3monitor.html b/dev/john/update-logging-example/integration-excel/views/fdc3monitor.html new file mode 100644 index 00000000..4599ff89 --- /dev/null +++ b/dev/john/update-logging-example/integration-excel/views/fdc3monitor.html @@ -0,0 +1,32 @@ + + + + + + + FDC3 Monitor + + + + + +
+
+

Monitor FDC3 Messages

+

Demonstrate monitoring messages from Excel.

+
+
+ OpenFin +
+
+ +
+

When an fdc3.instrument context is received the ticker value will be shown below.

+ +
+ + +
+
+ + diff --git a/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/images/icon-blue.png b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/images/style/test-image.webp b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/images/style/test-image.webp new file mode 100644 index 00000000..e566f7ac Binary files /dev/null and b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/images/style/test-image.webp differ diff --git a/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/style/app.css b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/style/style.html b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/style/style.html new file mode 100644 index 00000000..900e9730 --- /dev/null +++ b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/style/style.html @@ -0,0 +1,410 @@ + + + + + + + Style Examples + + + + + +
+
+

This is the main title in the header

+

The is the title tag in the header.

+
+
+ OpenFin +
+
+ +
+

Header 1

+

Header 2

+

Header 3

+

Header 4

+
Header 5
+

A paragraph of text.

+

A primary element.

+

An errored element.

+

A success element.

+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + + +
+
+ + + + +
+
+ Link + Link [Disabled] + Link Button + Link Button [Disabled] +
+
+ +
Blah blah
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Title 1Title 2Title 3Action
Data 1Data 2Data 3 + + + +
Data 4Data 5Data 6 + + + +
Data 7Data 8Data 9 + + + +
+
+
+ +
+
+
Tag
+
Title
+
Actions
+
+
+
Tag Data 1
+
Title Data 1
+
+
+
+
Tag Data 2
+
Title Data 2
+
+
+
+
+
+ + Test Image +
+
+ + Test Image +
+
+
+ + + + diff --git a/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/favicon.ico b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/favicon.ico differ diff --git a/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/manifest.fin.json b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/manifest.fin.json new file mode 100644 index 00000000..c1f9bebd --- /dev/null +++ b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/manifest.fin.json @@ -0,0 +1,47 @@ +{ + "licenseKey": "openfin-demo-license-key", + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79", + "autoShow": false + }, + "platform": { + "uuid": "how-to-use-a-manifest-create-a-single-page-platform", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/favicon.ico", + "defaultWindowOptions": { + "stylesheetUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/window-override.css" + } + }, + "snapshot": { + "windows": [ + { + "defaultWidth": 800, + "defaultHeight": 600, + "defaultCentered": true, + "saveWindowState": true, + "backgroundThrottling": true, + "layout": { + "content": [ + { + "type": "stack", + "width": 100, + "isClosable": false, + "reorderEnabled": false, + "hasHeaders": false, + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/style/style.html" + }, + "title": "view" + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/second.manifest.fin.json b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/second.manifest.fin.json new file mode 100644 index 00000000..a1a2ad5f --- /dev/null +++ b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/second.manifest.fin.json @@ -0,0 +1,24 @@ +{ + "licenseKey": "openfin-demo-license-key", + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79", + "autoShow": false + }, + "platform": { + "uuid": "second-how-to-use-a-manifest-create-a-single-page-platform", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/favicon.ico" + }, + "snapshot": { + "windows": [ + { + "defaultWidth": 800, + "defaultHeight": 600, + "defaultCentered": true, + "saveWindowState": true, + "backgroundThrottling": false, + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/common/style/style.html" + } + ] + } +} diff --git a/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/window-override.css b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/window-override.css new file mode 100644 index 00000000..1304a393 --- /dev/null +++ b/dev/john/update-logging-example/use-a-manifest-create-a-single-page-platform/window-override.css @@ -0,0 +1,33 @@ +/* + * Example of css to override default platform window + * Start of css override + */ + +/* + * This root removes the layout padding. Useful for this example when you have a single view and you want the view + * to take all available space. Uncomment to enable. + */ + +/* + :root { + --layout-container-padding-top: 0px; + --layout-container-padding-right: 0px; + --layout-container-padding-bottom: 0px; + --layout-container-padding-left: 0px; + } +*/ + +/* + * This sets the border of the layout to indigo. If you wish to test the above setting + * comment out the root section above (if it isn't commented) and uncomment this. + * Launch the platform and you will see the padding of the layout in indigo. + * Quit the platform, uncomment the above, re-launch the platform and the indigo will be hidden. +*/ +/* +#layout-container { + background-color: indigo; +} +*/ +/* + * End of css override +*/ diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/common/images/icon-blue.png b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/common/style/app.css b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/favicon.ico b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/favicon.ico differ diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/app.html b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/app.html new file mode 100644 index 00000000..a0f13e62 --- /dev/null +++ b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/app.html @@ -0,0 +1,30 @@ + + + + + + + Launched View + + + + + +
+
+

Launched View

+
+
+ OpenFin +
+
+
+

+ This is a basic example showing how a view can be launched from another application and passed + context: +

+

The following data was passed:

+

+
+ + diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/provider.html b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/provider.html new file mode 100644 index 00000000..87bf91c8 --- /dev/null +++ b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/provider.html @@ -0,0 +1,30 @@ + + + + + + OpenFin Provider + + + + + + + +
+
+

OpenFin Provider

+
+
+ OpenFin +
+
+
+

This provider represents the window that is generally hidden by default.

+

+ It sets up the channel and checks connecting clients before allowing them to issue commands such as + createView. +

+
+ + diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/window.html b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/window.html new file mode 100644 index 00000000..e3a87125 --- /dev/null +++ b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/window.html @@ -0,0 +1,47 @@ + + + + + + + Window App - Example + + + + + +
+
+

Issue Commands To a Platform

+

Use the channel API to send command to a platform.

+
+
+ OpenFin +
+
+
+

+ This is a basic window app to represent an external app issuing commands to a platform to launch a + view. This app could be a java or a .net application as well as a web based application. +

+

The buttons below let you:

+ +

+ When the platform is launched you will see the provider window show (it is generally hidden by + default). Once shown you can issue the createView commands from this application. +

+ + + +
+ + diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/js/app.bundle.js b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/js/app.bundle.js new file mode 100644 index 00000000..1f5b2f94 --- /dev/null +++ b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/js/app.bundle.js @@ -0,0 +1,46 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +if (document.readyState === "complete") { + initApp().catch(() => { }); +} +else { + window.addEventListener("load", async () => { + await initApp(); + }); +} +/** + * Initialize the application. + */ +async function initApp() { + const container = document.querySelector("#context-container"); + if (container) { + const viewOptions = await fin.me.getOptions(); + container.textContent = JSON.stringify(viewOptions.customData); + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOztVQUFBO1VBQ0E7Ozs7O1dDREE7V0FDQTtXQUNBO1dBQ0EsdURBQXVELGlCQUFpQjtXQUN4RTtXQUNBLGdEQUFnRCxhQUFhO1dBQzdEOzs7Ozs7Ozs7QUNKQSxJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssVUFBVSxFQUFFLENBQUM7SUFDeEMsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDO0FBQzNCLENBQUM7S0FBTSxDQUFDO0lBQ1AsTUFBTSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxLQUFLLElBQUksRUFBRTtRQUMxQyxNQUFNLE9BQU8sRUFBRSxDQUFDO0lBQ2pCLENBQUMsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsS0FBSyxVQUFVLE9BQU87SUFDckIsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBQy9ELElBQUksU0FBUyxFQUFFLENBQUM7UUFDZixNQUFNLFdBQVcsR0FBRyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDOUMsU0FBUyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNoRSxDQUFDO0FBQ0YsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL3VzZS1jaGFubmVsLWFwaS1pc3N1ZS1jb21tYW5kcy10by1hLXBsYXRmb3JtL3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL3VzZS1jaGFubmVsLWFwaS1pc3N1ZS1jb21tYW5kcy10by1hLXBsYXRmb3JtL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vdXNlLWNoYW5uZWwtYXBpLWlzc3VlLWNvbW1hbmRzLXRvLWEtcGxhdGZvcm0vLi9jbGllbnQvc3JjL2FwcC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiZXhwb3J0IHt9O1xuXG5pZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gXCJjb21wbGV0ZVwiKSB7XG5cdGluaXRBcHAoKS5jYXRjaCgoKSA9PiB7fSk7XG59IGVsc2Uge1xuXHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImxvYWRcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdGF3YWl0IGluaXRBcHAoKTtcblx0fSk7XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgYXBwbGljYXRpb24uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluaXRBcHAoKTogUHJvbWlzZTx2b2lkPiB7XG5cdGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjY29udGV4dC1jb250YWluZXJcIik7XG5cdGlmIChjb250YWluZXIpIHtcblx0XHRjb25zdCB2aWV3T3B0aW9ucyA9IGF3YWl0IGZpbi5tZS5nZXRPcHRpb25zKCk7XG5cdFx0Y29udGFpbmVyLnRleHRDb250ZW50ID0gSlNPTi5zdHJpbmdpZnkodmlld09wdGlvbnMuY3VzdG9tRGF0YSk7XG5cdH1cbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/js/platform.bundle.js b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/js/platform.bundle.js new file mode 100644 index 00000000..93a47472 --- /dev/null +++ b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/js/platform.bundle.js @@ -0,0 +1,92 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!********************************!*\ + !*** ./client/src/provider.ts ***! + \********************************/ +__webpack_require__.r(__webpack_exports__); +window.addEventListener("DOMContentLoaded", async () => { + const platform = fin.Platform.getCurrentSync(); + await platform.once("platform-api-ready", async () => init()); +}); +/** + * Initialize the components. + */ +async function init() { + // create a channel to receive commands from external apps + const actionChannel = await fin.InterApplicationBus.Channel.create("platform-command"); + actionChannel.onConnection((identity, payload) => { + // on connection you can validate the identity and optionally specify that a payload to prove id needs to be passed + // if you wanted to deny a connection you can throw an exception here + console.log("Application connecting to action channel:", identity); + console.log("Payload passed by connecting application:", payload); + }); + // an example of a command you wish to expose. + // alternatively you could have a single command function exposed which could have an action type + actionChannel.register("createView", async (unknownPayload, identity) => { + const payload = unknownPayload; + // there would likely be validation and additional logic here. + const platform = fin.Platform.getCurrentSync(); + let targetWindow; + let targetView; + const viewOptions = { target: undefined }; + Object.assign(viewOptions, payload.viewOptions); + if (payload.target?.window !== undefined) { + targetWindow = { uuid: fin.me.identity.uuid, name: payload.target.window }; + } + if (payload.target?.view !== undefined) { + targetView = { uuid: fin.me.identity.uuid, name: payload.target.view }; + } + const createdView = await platform.createView(viewOptions, targetWindow, targetView); + const currentWindow = await createdView.getCurrentWindow(); + if (currentWindow.identity.name === undefined || currentWindow.identity.name === fin.me.identity.uuid) { + const windowAllocation = new Promise((resolve, reject) => { + createdView + .once("target-changed", async () => { + const hostWindow = await createdView.getCurrentWindow(); + resolve({ + view: createdView.identity.name, + window: hostWindow.identity.name + }); + }) + .catch(() => { }); + }); + return windowAllocation; + } + return { + view: createdView.identity.name, + window: currentWindow.identity.name + }; + }); +} +fin.Platform.init({ + overrideCallback: async (Provider) => { + /** + * Override the provider class. + */ + class Override extends Provider { + } + return new Override(); + } +}).catch(() => { }); + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUNsQyxNQUFNLFVBQVUsR0FBRyxNQUFNLFdBQVcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO29CQUN4RCxPQUFPLENBQUM7d0JBQ1AsSUFBSSxFQUFFLFdBQVcsQ0FBQyxRQUFRLENBQUMsSUFBSTt3QkFDL0IsTUFBTSxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSTtxQkFDaEMsQ0FBQyxDQUFDO2dCQUNKLENBQUMsQ0FBQztxQkFDRCxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7WUFDbkIsQ0FBQyxDQUFDLENBQUM7WUFFSCxPQUFPLGdCQUFnQixDQUFDO1FBQ3pCLENBQUM7UUFDRCxPQUFPO1lBQ04sSUFBSSxFQUFFLFdBQVcsQ0FBQyxRQUFRLENBQUMsSUFBSTtZQUMvQixNQUFNLEVBQUUsYUFBYSxDQUFDLFFBQVEsQ0FBQyxJQUFJO1NBQ25DLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNKLENBQUM7QUFFRCxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztJQUNqQixnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEVBQUU7UUFDcEM7O1dBRUc7UUFDSCxNQUFNLFFBQVMsU0FBUSxRQUFRO1NBQUc7UUFDbEMsT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7Q0FDRCxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vdXNlLWNoYW5uZWwtYXBpLWlzc3VlLWNvbW1hbmRzLXRvLWEtcGxhdGZvcm0vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vdXNlLWNoYW5uZWwtYXBpLWlzc3VlLWNvbW1hbmRzLXRvLWEtcGxhdGZvcm0vd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly91c2UtY2hhbm5lbC1hcGktaXNzdWUtY29tbWFuZHMtdG8tYS1wbGF0Zm9ybS8uL2NsaWVudC9zcmMvcHJvdmlkZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gVGhlIHJlcXVpcmUgc2NvcGVcbnZhciBfX3dlYnBhY2tfcmVxdWlyZV9fID0ge307XG5cbiIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsImltcG9ydCB0eXBlIE9wZW5GaW4gZnJvbSBcIkBvcGVuZmluL2NvcmVcIjtcblxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJET01Db250ZW50TG9hZGVkXCIsIGFzeW5jICgpID0+IHtcblx0Y29uc3QgcGxhdGZvcm06IE9wZW5GaW4uUGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcblx0YXdhaXQgcGxhdGZvcm0ub25jZShcInBsYXRmb3JtLWFwaS1yZWFkeVwiLCBhc3luYyAoKSA9PiBpbml0KCkpO1xufSk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgY29tcG9uZW50cy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gaW5pdCgpOiBQcm9taXNlPHZvaWQ+IHtcblx0Ly8gY3JlYXRlIGEgY2hhbm5lbCB0byByZWNlaXZlIGNvbW1hbmRzIGZyb20gZXh0ZXJuYWwgYXBwc1xuXHRjb25zdCBhY3Rpb25DaGFubmVsOiBPcGVuRmluLkNoYW5uZWxQcm92aWRlciA9XG5cdFx0YXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoXCJwbGF0Zm9ybS1jb21tYW5kXCIpO1xuXG5cdGFjdGlvbkNoYW5uZWwub25Db25uZWN0aW9uKChpZGVudGl0eSwgcGF5bG9hZCkgPT4ge1xuXHRcdC8vIG9uIGNvbm5lY3Rpb24geW91IGNhbiB2YWxpZGF0ZSB0aGUgaWRlbnRpdHkgYW5kIG9wdGlvbmFsbHkgc3BlY2lmeSB0aGF0IGEgcGF5bG9hZCB0byBwcm92ZSBpZCBuZWVkcyB0byBiZSBwYXNzZWRcblx0XHQvLyBpZiB5b3Ugd2FudGVkIHRvIGRlbnkgYSBjb25uZWN0aW9uIHlvdSBjYW4gdGhyb3cgYW4gZXhjZXB0aW9uIGhlcmVcblx0XHRjb25zb2xlLmxvZyhcIkFwcGxpY2F0aW9uIGNvbm5lY3RpbmcgdG8gYWN0aW9uIGNoYW5uZWw6XCIsIGlkZW50aXR5KTtcblx0XHRjb25zb2xlLmxvZyhcIlBheWxvYWQgcGFzc2VkIGJ5IGNvbm5lY3RpbmcgYXBwbGljYXRpb246XCIsIHBheWxvYWQpO1xuXHR9KTtcblxuXHQvLyBhbiBleGFtcGxlIG9mIGEgY29tbWFuZCB5b3Ugd2lzaCB0byBleHBvc2UuXG5cdC8vIGFsdGVybmF0aXZlbHkgeW91IGNvdWxkIGhhdmUgYSBzaW5nbGUgY29tbWFuZCBmdW5jdGlvbiBleHBvc2VkIHdoaWNoIGNvdWxkIGhhdmUgYW4gYWN0aW9uIHR5cGVcblx0YWN0aW9uQ2hhbm5lbC5yZWdpc3RlcihcImNyZWF0ZVZpZXdcIiwgYXN5bmMgKHVua25vd25QYXlsb2FkOiB1bmtub3duLCBpZGVudGl0eSkgPT4ge1xuXHRcdGNvbnN0IHBheWxvYWQgPSB1bmtub3duUGF5bG9hZCBhcyB7XG5cdFx0XHR0YXJnZXQ6IHsgd2luZG93Pzogc3RyaW5nOyB2aWV3Pzogc3RyaW5nIH07XG5cdFx0XHR2aWV3T3B0aW9uczogT3BlbkZpbi5WaWV3T3B0aW9ucztcblx0XHR9O1xuXHRcdC8vIHRoZXJlIHdvdWxkIGxpa2VseSBiZSB2YWxpZGF0aW9uIGFuZCBhZGRpdGlvbmFsIGxvZ2ljIGhlcmUuXG5cdFx0Y29uc3QgcGxhdGZvcm06IE9wZW5GaW4uUGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcblx0XHRsZXQgdGFyZ2V0V2luZG93OiBPcGVuRmluLklkZW50aXR5IHwgdW5kZWZpbmVkO1xuXHRcdGxldCB0YXJnZXRWaWV3OiBPcGVuRmluLklkZW50aXR5IHwgdW5kZWZpbmVkO1xuXHRcdGNvbnN0IHZpZXdPcHRpb25zOiBQYXJ0aWFsPE9wZW5GaW4uVmlld09wdGlvbnM+ID0geyB0YXJnZXQ6IHVuZGVmaW5lZCB9O1xuXHRcdE9iamVjdC5hc3NpZ24odmlld09wdGlvbnMsIHBheWxvYWQudmlld09wdGlvbnMpO1xuXG5cdFx0aWYgKHBheWxvYWQudGFyZ2V0Py53aW5kb3cgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0dGFyZ2V0V2luZG93ID0geyB1dWlkOiBmaW4ubWUuaWRlbnRpdHkudXVpZCwgbmFtZTogcGF5bG9hZC50YXJnZXQud2luZG93IH07XG5cdFx0fVxuXG5cdFx0aWYgKHBheWxvYWQudGFyZ2V0Py52aWV3ICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdHRhcmdldFZpZXcgPSB7IHV1aWQ6IGZpbi5tZS5pZGVudGl0eS51dWlkLCBuYW1lOiBwYXlsb2FkLnRhcmdldC52aWV3IH07XG5cdFx0fVxuXG5cdFx0Y29uc3QgY3JlYXRlZFZpZXcgPSBhd2FpdCBwbGF0Zm9ybS5jcmVhdGVWaWV3KFxuXHRcdFx0dmlld09wdGlvbnMgYXMgT3BlbkZpbi5WaWV3T3B0aW9ucyxcblx0XHRcdHRhcmdldFdpbmRvdyxcblx0XHRcdHRhcmdldFZpZXdcblx0XHQpO1xuXHRcdGNvbnN0IGN1cnJlbnRXaW5kb3cgPSBhd2FpdCBjcmVhdGVkVmlldy5nZXRDdXJyZW50V2luZG93KCk7XG5cblx0XHRpZiAoY3VycmVudFdpbmRvdy5pZGVudGl0eS5uYW1lID09PSB1bmRlZmluZWQgfHwgY3VycmVudFdpbmRvdy5pZGVudGl0eS5uYW1lID09PSBmaW4ubWUuaWRlbnRpdHkudXVpZCkge1xuXHRcdFx0Y29uc3Qgd2luZG93QWxsb2NhdGlvbiA9IG5ldyBQcm9taXNlPHsgdmlldzogc3RyaW5nOyB3aW5kb3c6IHN0cmluZyB9PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cdFx0XHRcdGNyZWF0ZWRWaWV3XG5cdFx0XHRcdFx0Lm9uY2UoXCJ0YXJnZXQtY2hhbmdlZFwiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0XHRjb25zdCBob3N0V2luZG93ID0gYXdhaXQgY3JlYXRlZFZpZXcuZ2V0Q3VycmVudFdpbmRvdygpO1xuXHRcdFx0XHRcdFx0cmVzb2x2ZSh7XG5cdFx0XHRcdFx0XHRcdHZpZXc6IGNyZWF0ZWRWaWV3LmlkZW50aXR5Lm5hbWUsXG5cdFx0XHRcdFx0XHRcdHdpbmRvdzogaG9zdFdpbmRvdy5pZGVudGl0eS5uYW1lXG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdC5jYXRjaCgoKSA9PiB7fSk7XG5cdFx0XHR9KTtcblxuXHRcdFx0cmV0dXJuIHdpbmRvd0FsbG9jYXRpb247XG5cdFx0fVxuXHRcdHJldHVybiB7XG5cdFx0XHR2aWV3OiBjcmVhdGVkVmlldy5pZGVudGl0eS5uYW1lLFxuXHRcdFx0d2luZG93OiBjdXJyZW50V2luZG93LmlkZW50aXR5Lm5hbWVcblx0XHR9O1xuXHR9KTtcbn1cblxuZmluLlBsYXRmb3JtLmluaXQoe1xuXHRvdmVycmlkZUNhbGxiYWNrOiBhc3luYyAoUHJvdmlkZXIpID0+IHtcblx0XHQvKipcblx0XHQgKiBPdmVycmlkZSB0aGUgcHJvdmlkZXIgY2xhc3MuXG5cdFx0ICovXG5cdFx0Y2xhc3MgT3ZlcnJpZGUgZXh0ZW5kcyBQcm92aWRlciB7fVxuXHRcdHJldHVybiBuZXcgT3ZlcnJpZGUoKTtcblx0fVxufSkuY2F0Y2goKCkgPT4ge30pO1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/js/window.bundle.js b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/js/window.bundle.js new file mode 100644 index 00000000..e66a4f84 --- /dev/null +++ b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/js/window.bundle.js @@ -0,0 +1,115 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!******************************!*\ + !*** ./client/src/window.ts ***! + \******************************/ +__webpack_require__.r(__webpack_exports__); +document.addEventListener("DOMContentLoaded", async () => { + try { + await initDom(); + } + catch (error) { + console.error(error); + } +}); +let lastCreatedView; +let channelClient; +/** + * Initialize the DOM elements. + */ +async function initDom() { + const launchPlatformButton = document.querySelector("#launch-platform"); + const requestViewButton = document.querySelector("#request-view"); + const requestViewInSameWindowButton = document.querySelector("#request-view-same-window"); + if (launchPlatformButton) { + launchPlatformButton.addEventListener("click", launchPlatform); + } + if (requestViewButton) { + requestViewButton.addEventListener("click", requestView); + } + if (requestViewInSameWindowButton) { + requestViewInSameWindowButton.addEventListener("click", requestViewInLastWindow); + } +} +/** + * Launch a platform from a manifest. + */ +async function launchPlatform() { + try { + await fin.System.launchManifest("https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/platform.fin.json"); + } + catch (error) { + console.error("Error launching target platform app:", error); + } + try { + channelClient = await fin.InterApplicationBus.Channel.connect("platform-command", { + payload: { token: "an example token" } + }); + } + catch (error) { + console.error("Error launching target platform app:", error); + } +} +/** + * Create a view using a channel. + */ +async function requestView() { + try { + // you have the option of letting the connected app to provide view options or maybe you will provide a more restrictive option where they can just specify an id of a view to load + // and the platform app does a lookup. + lastCreatedView = await channelClient.dispatch("createView", { + viewOptions: { + url: "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/app.html", + customData: { + dateNow: Date.now() + } + } + }); + } + catch (error) { + console.error("Error issuing command to platform:", error); + } +} +/** + * Create a view using a channel with a specific target. + */ +async function requestViewInLastWindow() { + try { + // you have the option of letting the connected app to provide view options or maybe you will provide a more restrictive option where they can just specify an id of a view to load + // and the platform app does a lookup. + lastCreatedView = await channelClient.dispatch("createView", { + viewOptions: { + url: "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/app.html", + customData: { + dateNow: Date.now() + } + }, + target: lastCreatedView + }); + } + catch (error) { + console.error("Error issuing command to platform:", error); + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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LFFBQVEsQ0FBQyxZQUFZLEVBQUU7WUFDNUQsV0FBVyxFQUFFO2dCQUNaLEdBQUcsRUFBRSxxQ0FBcUM7Z0JBQzFDLFVBQVUsRUFBRTtvQkFDWCxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtpQkFDbkI7YUFDRDtZQUNELE1BQU0sRUFBRSxlQUFlO1NBQ3ZCLENBQUMsQ0FBQztJQUNKLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2hCLE9BQU8sQ0FBQyxLQUFLLENBQUMsb0NBQW9DLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDNUQsQ0FBQztBQUNGLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly91c2UtY2hhbm5lbC1hcGktaXNzdWUtY29tbWFuZHMtdG8tYS1wbGF0Zm9ybS93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly91c2UtY2hhbm5lbC1hcGktaXNzdWUtY29tbWFuZHMtdG8tYS1wbGF0Zm9ybS93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3VzZS1jaGFubmVsLWFwaS1pc3N1ZS1jb21tYW5kcy10by1hLXBsYXRmb3JtLy4vY2xpZW50L3NyYy93aW5kb3cudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gVGhlIHJlcXVpcmUgc2NvcGVcbnZhciBfX3dlYnBhY2tfcmVxdWlyZV9fID0ge307XG5cbiIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsImltcG9ydCB0eXBlIE9wZW5GaW4gZnJvbSBcIkBvcGVuZmluL2NvcmVcIjtcblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgYXN5bmMgKCkgPT4ge1xuXHR0cnkge1xuXHRcdGF3YWl0IGluaXREb20oKTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTtcblx0fVxufSk7XG5cbmxldCBsYXN0Q3JlYXRlZFZpZXc6XG5cdHwge1xuXHRcdFx0dmlldzogc3RyaW5nO1xuXHRcdFx0d2luZG93OiBzdHJpbmc7XG5cdCAgfVxuXHR8IHVuZGVmaW5lZDtcbmxldCBjaGFubmVsQ2xpZW50OiBPcGVuRmluLkNoYW5uZWxDbGllbnQ7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgRE9NIGVsZW1lbnRzLlxuICovXG5hc3luYyBmdW5jdGlvbiBpbml0RG9tKCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBsYXVuY2hQbGF0Zm9ybUJ1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjbGF1bmNoLXBsYXRmb3JtXCIpO1xuXHRjb25zdCByZXF1ZXN0Vmlld0J1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjcmVxdWVzdC12aWV3XCIpO1xuXHRjb25zdCByZXF1ZXN0Vmlld0luU2FtZVdpbmRvd0J1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjcmVxdWVzdC12aWV3LXNhbWUtd2luZG93XCIpO1xuXHRpZiAobGF1bmNoUGxhdGZvcm1CdXR0b24pIHtcblx0XHRsYXVuY2hQbGF0Zm9ybUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgbGF1bmNoUGxhdGZvcm0pO1xuXHR9XG5cdGlmIChyZXF1ZXN0Vmlld0J1dHRvbikge1xuXHRcdHJlcXVlc3RWaWV3QnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCByZXF1ZXN0Vmlldyk7XG5cdH1cblx0aWYgKHJlcXVlc3RWaWV3SW5TYW1lV2luZG93QnV0dG9uKSB7XG5cdFx0cmVxdWVzdFZpZXdJblNhbWVXaW5kb3dCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHJlcXVlc3RWaWV3SW5MYXN0V2luZG93KTtcblx0fVxufVxuXG4vKipcbiAqIExhdW5jaCBhIHBsYXRmb3JtIGZyb20gYSBtYW5pZmVzdC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbGF1bmNoUGxhdGZvcm0oKTogUHJvbWlzZTx2b2lkPiB7XG5cdHRyeSB7XG5cdFx0YXdhaXQgZmluLlN5c3RlbS5sYXVuY2hNYW5pZmVzdChcImh0dHA6Ly9sb2NhbGhvc3Q6NTA1MC9wbGF0Zm9ybS5maW4uanNvblwiKTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKFwiRXJyb3IgbGF1bmNoaW5nIHRhcmdldCBwbGF0Zm9ybSBhcHA6XCIsIGVycm9yKTtcblx0fVxuXHR0cnkge1xuXHRcdGNoYW5uZWxDbGllbnQgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3QoXCJwbGF0Zm9ybS1jb21tYW5kXCIsIHtcblx0XHRcdHBheWxvYWQ6IHsgdG9rZW46IFwiYW4gZXhhbXBsZSB0b2tlblwiIH1cblx0XHR9KTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKFwiRXJyb3IgbGF1bmNoaW5nIHRhcmdldCBwbGF0Zm9ybSBhcHA6XCIsIGVycm9yKTtcblx0fVxufVxuXG4vKipcbiAqIENyZWF0ZSBhIHZpZXcgdXNpbmcgYSBjaGFubmVsLlxuICovXG5hc3luYyBmdW5jdGlvbiByZXF1ZXN0VmlldygpOiBQcm9taXNlPHZvaWQ+IHtcblx0dHJ5IHtcblx0XHQvLyB5b3UgaGF2ZSB0aGUgb3B0aW9uIG9mIGxldHRpbmcgdGhlIGNvbm5lY3RlZCBhcHAgdG8gcHJvdmlkZSB2aWV3IG9wdGlvbnMgb3IgbWF5YmUgeW91IHdpbGwgcHJvdmlkZSBhIG1vcmUgcmVzdHJpY3RpdmUgb3B0aW9uIHdoZXJlIHRoZXkgY2FuIGp1c3Qgc3BlY2lmeSBhbiBpZCBvZiBhIHZpZXcgdG8gbG9hZFxuXHRcdC8vIGFuZCB0aGUgcGxhdGZvcm0gYXBwIGRvZXMgYSBsb29rdXAuXG5cdFx0bGFzdENyZWF0ZWRWaWV3ID0gYXdhaXQgY2hhbm5lbENsaWVudC5kaXNwYXRjaChcImNyZWF0ZVZpZXdcIiwge1xuXHRcdFx0dmlld09wdGlvbnM6IHtcblx0XHRcdFx0dXJsOiBcImh0dHA6Ly9sb2NhbGhvc3Q6NTA1MC9odG1sL2FwcC5odG1sXCIsXG5cdFx0XHRcdGN1c3RvbURhdGE6IHtcblx0XHRcdFx0XHRkYXRlTm93OiBEYXRlLm5vdygpXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKFwiRXJyb3IgaXNzdWluZyBjb21tYW5kIHRvIHBsYXRmb3JtOlwiLCBlcnJvcik7XG5cdH1cbn1cblxuLyoqXG4gKiBDcmVhdGUgYSB2aWV3IHVzaW5nIGEgY2hhbm5lbCB3aXRoIGEgc3BlY2lmaWMgdGFyZ2V0LlxuICovXG5hc3luYyBmdW5jdGlvbiByZXF1ZXN0Vmlld0luTGFzdFdpbmRvdygpOiBQcm9taXNlPHZvaWQ+IHtcblx0dHJ5IHtcblx0XHQvLyB5b3UgaGF2ZSB0aGUgb3B0aW9uIG9mIGxldHRpbmcgdGhlIGNvbm5lY3RlZCBhcHAgdG8gcHJvdmlkZSB2aWV3IG9wdGlvbnMgb3IgbWF5YmUgeW91IHdpbGwgcHJvdmlkZSBhIG1vcmUgcmVzdHJpY3RpdmUgb3B0aW9uIHdoZXJlIHRoZXkgY2FuIGp1c3Qgc3BlY2lmeSBhbiBpZCBvZiBhIHZpZXcgdG8gbG9hZFxuXHRcdC8vIGFuZCB0aGUgcGxhdGZvcm0gYXBwIGRvZXMgYSBsb29rdXAuXG5cdFx0bGFzdENyZWF0ZWRWaWV3ID0gYXdhaXQgY2hhbm5lbENsaWVudC5kaXNwYXRjaChcImNyZWF0ZVZpZXdcIiwge1xuXHRcdFx0dmlld09wdGlvbnM6IHtcblx0XHRcdFx0dXJsOiBcImh0dHA6Ly9sb2NhbGhvc3Q6NTA1MC9odG1sL2FwcC5odG1sXCIsXG5cdFx0XHRcdGN1c3RvbURhdGE6IHtcblx0XHRcdFx0XHRkYXRlTm93OiBEYXRlLm5vdygpXG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHR0YXJnZXQ6IGxhc3RDcmVhdGVkVmlld1xuXHRcdH0pO1xuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoXCJFcnJvciBpc3N1aW5nIGNvbW1hbmQgdG8gcGxhdGZvcm06XCIsIGVycm9yKTtcblx0fVxufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/manifest.fin.json b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/manifest.fin.json new file mode 100644 index 00000000..4a14d445 --- /dev/null +++ b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/manifest.fin.json @@ -0,0 +1,14 @@ +{ + "licenseKey": "openfin-demo-license-key", + "runtime": { + "version": "38.126.83.79", + "arguments": "--v=1" + }, + "startup_app": { + "name": "issue-commands-to-platform", + "uuid": "issue-commands-to-platform", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/window.html", + "autoShow": true, + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/favicon.ico" + } +} diff --git a/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/platform.fin.json b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/platform.fin.json new file mode 100644 index 00000000..41290ae0 --- /dev/null +++ b/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/platform.fin.json @@ -0,0 +1,12 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "how-to-use-channel-api-issue-commands-to-a-platform", + "autoShow": true, + "providerUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/html/provider.html", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-channel-api-issue-commands-to-a-platform/favicon.ico" + } +} diff --git a/dev/john/update-logging-example/use-content-creation-rules/assets/content-creation-rules.gif b/dev/john/update-logging-example/use-content-creation-rules/assets/content-creation-rules.gif new file mode 100644 index 00000000..29543a53 Binary files /dev/null and b/dev/john/update-logging-example/use-content-creation-rules/assets/content-creation-rules.gif differ diff --git a/dev/john/update-logging-example/use-content-creation-rules/common/style/app.css b/dev/john/update-logging-example/use-content-creation-rules/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-content-creation-rules/favicon.ico b/dev/john/update-logging-example/use-content-creation-rules/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-content-creation-rules/favicon.ico differ diff --git a/dev/john/update-logging-example/use-content-creation-rules/html/app.html b/dev/john/update-logging-example/use-content-creation-rules/html/app.html new file mode 100644 index 00000000..a81e59da --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/html/app.html @@ -0,0 +1,40 @@ + + + + + + + + Content Creation Test App + + + +

Content Creation Rules

+
+
+ +

Open a View with www.google.com

+
+
+ +

Open a View using a target with rotating urls

+
+
+ +

Open a Window with www.bing.com

+
+
+ +

Open a Window using a target with rotating urls

+
+
+ +

Open a Browser Window with www.microsoft.com

+
+
+ +

Opening is Blocked

+
+
+ + diff --git a/dev/john/update-logging-example/use-content-creation-rules/html/default-platform-window.html b/dev/john/update-logging-example/use-content-creation-rules/html/default-platform-window.html new file mode 100644 index 00000000..48046bb3 --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/html/default-platform-window.html @@ -0,0 +1,31 @@ + + + + + + OpenFin Template + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/dev/john/update-logging-example/use-content-creation-rules/html/platform-provider.html b/dev/john/update-logging-example/use-content-creation-rules/html/platform-provider.html new file mode 100644 index 00000000..ef86f4e5 --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/html/platform-provider.html @@ -0,0 +1,14 @@ + + + + + + Platform Provider + + + + + +
Custom Provider...
+ + diff --git a/dev/john/update-logging-example/use-content-creation-rules/js/app.bundle.js b/dev/john/update-logging-example/use-content-creation-rules/js/app.bundle.js new file mode 100644 index 00000000..c514ec32 --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/js/app.bundle.js @@ -0,0 +1,106 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +document.addEventListener("DOMContentLoaded", async () => { + await initDom(); +}); +/** + * Initialize the DOM elements. + */ +async function initDom() { + const openView = document.querySelector("#open-view"); + if (openView) { + openView.addEventListener("click", (e) => { + const win = window.open("https://www.google.com"); + logWindowResult(win); + }); + } + const openViewTarget = document.querySelector("#open-view-target"); + const viewTargets = [ + "https://www.examples.com/category/business/advertising", + "https://www.examples.com/category/business/agenda", + "https://www.examples.com/category/business/agreement" + ]; + let viewTargetIndex = 0; + if (openViewTarget) { + openViewTarget.addEventListener("click", (e) => { + const win = window.open(viewTargets[viewTargetIndex++ % viewTargets.length], "examples", "blah=foo"); + logWindowResult(win); + }); + } + const openWindow = document.querySelector("#open-window"); + if (openWindow) { + openWindow.addEventListener("click", (e) => { + const win = window.open("https://www.bing.com"); + logWindowResult(win); + }); + } + const openWindowTarget = document.querySelector("#open-window-target"); + const windowTargets = [ + "https://www.examples.com/category/education/case-study", + "https://www.examples.com/category/education/essays", + "https://www.examples.com/category/education/finance" + ]; + let windowTargetIndex = 0; + if (openWindowTarget) { + openWindowTarget.addEventListener("click", (e) => { + const win = window.open(windowTargets[windowTargetIndex++ % windowTargets.length], "examples2"); + logWindowResult(win); + }); + } + const openBrowser = document.querySelector("#open-browser"); + if (openBrowser) { + openBrowser.addEventListener("click", (e) => { + const win = window.open("https://www.microsoft.com"); + logWindowResult(win); + }); + } + const openBlocked = document.querySelector("#open-blocked"); + if (openBlocked) { + openBlocked.addEventListener("click", (e) => { + const win = window.open("https://www.apple.com"); + logWindowResult(win); + }); + } +} +/** + * Display a result when the window content has loaded. + * @param win The window to wire up the event. + */ +function logWindowResult(win) { + try { + if (win) { + win.addEventListener("DOMContentLoaded", () => { + console.log("Window Location", win.location); + }); + } + } + catch (err) { + console.error("Error logging window results", err); + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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Q0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBQ3JELGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN0QixDQUFDLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQzVELElBQUksV0FBVyxFQUFFLENBQUM7UUFDakIsV0FBVyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFO1lBQzNDLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsQ0FBQztZQUNqRCxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdEIsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0FBQ0YsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsZUFBZSxDQUFDLEdBQXVCO0lBQy9DLElBQUksQ0FBQztRQUNKLElBQUksR0FBRyxFQUFFLENBQUM7WUFDVCxHQUFHLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxFQUFFO2dCQUM3QyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM5QyxDQUFDLENBQUMsQ0FBQztRQUNKLENBQUM7SUFDRixDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNkLE9BQU8sQ0FBQyxLQUFLLENBQUMsOEJBQThCLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDcEQsQ0FBQztBQUNGLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly91c2UtY29udGVudC1jcmVhdGlvbi1ydWxlcy93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly91c2UtY29udGVudC1jcmVhdGlvbi1ydWxlcy93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3VzZS1jb250ZW50LWNyZWF0aW9uLXJ1bGVzLy4vY2xpZW50L3NyYy9hcHAudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gVGhlIHJlcXVpcmUgc2NvcGVcbnZhciBfX3dlYnBhY2tfcmVxdWlyZV9fID0ge307XG5cbiIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsImV4cG9ydCB7fTtcblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgYXN5bmMgKCkgPT4ge1xuXHRhd2FpdCBpbml0RG9tKCk7XG59KTtcblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSBET00gZWxlbWVudHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluaXREb20oKTogUHJvbWlzZTx2b2lkPiB7XG5cdGNvbnN0IG9wZW5WaWV3ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNvcGVuLXZpZXdcIik7XG5cdGlmIChvcGVuVmlldykge1xuXHRcdG9wZW5WaWV3LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuXHRcdFx0Y29uc3Qgd2luID0gd2luZG93Lm9wZW4oXCJodHRwczovL3d3dy5nb29nbGUuY29tXCIpO1xuXHRcdFx0bG9nV2luZG93UmVzdWx0KHdpbik7XG5cdFx0fSk7XG5cdH1cblxuXHRjb25zdCBvcGVuVmlld1RhcmdldCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjb3Blbi12aWV3LXRhcmdldFwiKTtcblx0Y29uc3Qgdmlld1RhcmdldHMgPSBbXG5cdFx0XCJodHRwczovL3d3dy5leGFtcGxlcy5jb20vY2F0ZWdvcnkvYnVzaW5lc3MvYWR2ZXJ0aXNpbmdcIixcblx0XHRcImh0dHBzOi8vd3d3LmV4YW1wbGVzLmNvbS9jYXRlZ29yeS9idXNpbmVzcy9hZ2VuZGFcIixcblx0XHRcImh0dHBzOi8vd3d3LmV4YW1wbGVzLmNvbS9jYXRlZ29yeS9idXNpbmVzcy9hZ3JlZW1lbnRcIlxuXHRdO1xuXG5cdGxldCB2aWV3VGFyZ2V0SW5kZXggPSAwO1xuXHRpZiAob3BlblZpZXdUYXJnZXQpIHtcblx0XHRvcGVuVmlld1RhcmdldC5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcblx0XHRcdGNvbnN0IHdpbiA9IHdpbmRvdy5vcGVuKHZpZXdUYXJnZXRzW3ZpZXdUYXJnZXRJbmRleCsrICUgdmlld1RhcmdldHMubGVuZ3RoXSwgXCJleGFtcGxlc1wiLCBcImJsYWg9Zm9vXCIpO1xuXHRcdFx0bG9nV2luZG93UmVzdWx0KHdpbik7XG5cdFx0fSk7XG5cdH1cblxuXHRjb25zdCBvcGVuV2luZG93ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNvcGVuLXdpbmRvd1wiKTtcblx0aWYgKG9wZW5XaW5kb3cpIHtcblx0XHRvcGVuV2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoZSkgPT4ge1xuXHRcdFx0Y29uc3Qgd2luID0gd2luZG93Lm9wZW4oXCJodHRwczovL3d3dy5iaW5nLmNvbVwiKTtcblx0XHRcdGxvZ1dpbmRvd1Jlc3VsdCh3aW4pO1xuXHRcdH0pO1xuXHR9XG5cblx0Y29uc3Qgb3BlbldpbmRvd1RhcmdldCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjb3Blbi13aW5kb3ctdGFyZ2V0XCIpO1xuXHRjb25zdCB3aW5kb3dUYXJnZXRzID0gW1xuXHRcdFwiaHR0cHM6Ly93d3cuZXhhbXBsZXMuY29tL2NhdGVnb3J5L2VkdWNhdGlvbi9jYXNlLXN0dWR5XCIsXG5cdFx0XCJodHRwczovL3d3dy5leGFtcGxlcy5jb20vY2F0ZWdvcnkvZWR1Y2F0aW9uL2Vzc2F5c1wiLFxuXHRcdFwiaHR0cHM6Ly93d3cuZXhhbXBsZXMuY29tL2NhdGVnb3J5L2VkdWNhdGlvbi9maW5hbmNlXCJcblx0XTtcblxuXHRsZXQgd2luZG93VGFyZ2V0SW5kZXggPSAwO1xuXHRpZiAob3BlbldpbmRvd1RhcmdldCkge1xuXHRcdG9wZW5XaW5kb3dUYXJnZXQuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG5cdFx0XHRjb25zdCB3aW4gPSB3aW5kb3cub3Blbih3aW5kb3dUYXJnZXRzW3dpbmRvd1RhcmdldEluZGV4KysgJSB3aW5kb3dUYXJnZXRzLmxlbmd0aF0sIFwiZXhhbXBsZXMyXCIpO1xuXHRcdFx0bG9nV2luZG93UmVzdWx0KHdpbik7XG5cdFx0fSk7XG5cdH1cblxuXHRjb25zdCBvcGVuQnJvd3NlciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjb3Blbi1icm93c2VyXCIpO1xuXHRpZiAob3BlbkJyb3dzZXIpIHtcblx0XHRvcGVuQnJvd3Nlci5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgKGUpID0+IHtcblx0XHRcdGNvbnN0IHdpbiA9IHdpbmRvdy5vcGVuKFwiaHR0cHM6Ly93d3cubWljcm9zb2Z0LmNvbVwiKTtcblx0XHRcdGxvZ1dpbmRvd1Jlc3VsdCh3aW4pO1xuXHRcdH0pO1xuXHR9XG5cblx0Y29uc3Qgb3BlbkJsb2NrZWQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI29wZW4tYmxvY2tlZFwiKTtcblx0aWYgKG9wZW5CbG9ja2VkKSB7XG5cdFx0b3BlbkJsb2NrZWQuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChlKSA9PiB7XG5cdFx0XHRjb25zdCB3aW4gPSB3aW5kb3cub3BlbihcImh0dHBzOi8vd3d3LmFwcGxlLmNvbVwiKTtcblx0XHRcdGxvZ1dpbmRvd1Jlc3VsdCh3aW4pO1xuXHRcdH0pO1xuXHR9XG59XG5cbi8qKlxuICogRGlzcGxheSBhIHJlc3VsdCB3aGVuIHRoZSB3aW5kb3cgY29udGVudCBoYXMgbG9hZGVkLlxuICogQHBhcmFtIHdpbiBUaGUgd2luZG93IHRvIHdpcmUgdXAgdGhlIGV2ZW50LlxuICovXG5mdW5jdGlvbiBsb2dXaW5kb3dSZXN1bHQod2luOiBXaW5kb3dQcm94eSB8IG51bGwpOiB2b2lkIHtcblx0dHJ5IHtcblx0XHRpZiAod2luKSB7XG5cdFx0XHR3aW4uYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgKCkgPT4ge1xuXHRcdFx0XHRjb25zb2xlLmxvZyhcIldpbmRvdyBMb2NhdGlvblwiLCB3aW4ubG9jYXRpb24pO1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9IGNhdGNoIChlcnIpIHtcblx0XHRjb25zb2xlLmVycm9yKFwiRXJyb3IgbG9nZ2luZyB3aW5kb3cgcmVzdWx0c1wiLCBlcnIpO1xuXHR9XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-content-creation-rules/js/default-platform-window.bundle.js b/dev/john/update-logging-example/use-content-creation-rules/js/default-platform-window.bundle.js new file mode 100644 index 00000000..6b2fdedb --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/js/default-platform-window.bundle.js @@ -0,0 +1,133 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***********************************************!*\ + !*** ./client/src/default-platform-window.ts ***! + \***********************************************/ +__webpack_require__.r(__webpack_exports__); +document.addEventListener("DOMContentLoaded", async () => { + await initDom(); +}); +/** + * Initialize the DOM elements. + */ +async function initDom() { + const platform = fin.Platform.getCurrentSync(); + const me = fin.me; + const CONTAINER_ID = "layout-container"; + await fin.Platform.Layout.init({ containerId: CONTAINER_ID }); + const minimizeBtn = document.querySelector("#minimize-button"); + if (minimizeBtn) { + minimizeBtn.addEventListener("click", async () => { + await me.minimize().catch(console.error); + }); + } + const maximizeBtn = document.querySelector("#expand-button"); + if (maximizeBtn) { + maximizeBtn.addEventListener("click", async () => { + await maxOrRestore(me).catch(console.error); + }); + } + const closeBtn = document.querySelector("#close-button"); + if (closeBtn) { + closeBtn.addEventListener("click", async (e) => { + await me.close(); + }); + } + await me.on("view-child-view-created", async (e) => { + // The content creation rules construct the options for the view in the childOptions + // The view has been created but not yet attached or navigated + console.log(e); + const viewOptions = e.childOptions; + let originalTargetName; + let create = true; + // If the window.open contained a target it is the viewOptions.name, + // the name starts internal-generated if a target wasn't specified + if (!viewOptions.name?.startsWith("internal-generated")) { + // This is a window.open with a target, but we can't use the original target name + // as the view name, because this would not allow it to be re-used, so we + // substitute a derived view name and then remove the old view later + // Store the original view name so that we can destroy it later + originalTargetName = viewOptions.name; + // Set a new derived name for the view based on the original name + viewOptions.name = `${viewOptions.name}-view`; + try { + // See if we can get the derived reusable view name + const currentView = fin.View.wrapSync({ uuid: fin.me.identity.uuid, name: viewOptions.name }); + // If we have it then navigate to the requested url + await currentView.navigate(viewOptions.url); + // And focus it, which will switch to the tab if its not active + await currentView.focus(); + // We have reused so no need to create + create = false; + } + catch { + // Something failed, most likely the view does not exist + // so the create flag will still be set + } + } + // The create flag is set because we couldn't find the existing view + if (create) { + // Create the view using the original view options, this will just attach the + // view created for us by the content creation rules + // Or if it had the name swapped due to a target specified in the original + // window.open it will create a new view with the derived name + const view = await platform.createView(viewOptions, e.target); + // We must explicitly navigate the view created by the content creation rules + await view.navigate(viewOptions.url); + } + // Cleanup the view that was created with the original target name if it had one + // as we have substituted a view with a derived name + if (originalTargetName) { + try { + const targetView = fin.View.wrapSync({ uuid: fin.me.identity.uuid, name: originalTargetName }); + await targetView.destroy(); + } + catch { } + } + }); + await me.on("view-child-window-created", async (e) => { + // Called when content is opened in a window + console.log(e); + }); + await me.on("view-child-content-opened-in-browser", async (e) => { + // Called when content is opened in the browser + console.log(e); + }); + await me.on("view-child-content-blocked", async (e) => { + // Called when content is blocked + console.log(e); + }); +} +/** + * Maximize of restore the window. + * @param win The window to perform the action on. + * @returns Nothing. + */ +async function maxOrRestore(win) { + if ((await win.getState()) === "normal") { + return win.maximize(); + } + return win.restore(); +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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RSxFQUFFO1FBQ3BELDRDQUE0QztRQUM1QyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2hCLENBQUMsQ0FBQyxDQUFDO0lBRUgsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUMvRCwrQ0FBK0M7UUFDL0MsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNoQixDQUFDLENBQUMsQ0FBQztJQUVILE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDckQsaUNBQWlDO1FBQ2pDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEIsQ0FBQyxDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILEtBQUssVUFBVSxZQUFZLENBQUMsR0FBbUI7SUFDOUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDekMsT0FBTyxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUVELE9BQU8sR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO0FBQ3RCLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly91c2UtY29udGVudC1jcmVhdGlvbi1ydWxlcy93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly91c2UtY29udGVudC1jcmVhdGlvbi1ydWxlcy93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3VzZS1jb250ZW50LWNyZWF0aW9uLXJ1bGVzLy4vY2xpZW50L3NyYy9kZWZhdWx0LXBsYXRmb3JtLXdpbmRvdy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBhc3luYyAoKSA9PiB7XG5cdGF3YWl0IGluaXREb20oKTtcbn0pO1xuXG4vKipcbiAqIEluaXRpYWxpemUgdGhlIERPTSBlbGVtZW50cy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gaW5pdERvbSgpOiBQcm9taXNlPHZvaWQ+IHtcblx0Y29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcblx0Y29uc3QgbWUgPSBmaW4ubWUgYXMgT3BlbkZpbi5XaW5kb3c7XG5cdGNvbnN0IENPTlRBSU5FUl9JRCA9IFwibGF5b3V0LWNvbnRhaW5lclwiO1xuXHRhd2FpdCBmaW4uUGxhdGZvcm0uTGF5b3V0LmluaXQoeyBjb250YWluZXJJZDogQ09OVEFJTkVSX0lEIH0pO1xuXG5cdGNvbnN0IG1pbmltaXplQnRuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNtaW5pbWl6ZS1idXR0b25cIik7XG5cdGlmIChtaW5pbWl6ZUJ0bikge1xuXHRcdG1pbmltaXplQnRuLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCBtZS5taW5pbWl6ZSgpLmNhdGNoKGNvbnNvbGUuZXJyb3IpO1xuXHRcdH0pO1xuXHR9XG5cblx0Y29uc3QgbWF4aW1pemVCdG4gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2V4cGFuZC1idXR0b25cIik7XG5cdGlmIChtYXhpbWl6ZUJ0bikge1xuXHRcdG1heGltaXplQnRuLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCBtYXhPclJlc3RvcmUobWUpLmNhdGNoKGNvbnNvbGUuZXJyb3IpO1xuXHRcdH0pO1xuXHR9XG5cblx0Y29uc3QgY2xvc2VCdG4gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2Nsb3NlLWJ1dHRvblwiKTtcblx0aWYgKGNsb3NlQnRuKSB7XG5cdFx0Y2xvc2VCdG4uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGFzeW5jIChlKSA9PiB7XG5cdFx0XHRhd2FpdCBtZS5jbG9zZSgpO1xuXHRcdH0pO1xuXHR9XG5cblx0YXdhaXQgbWUub24oXCJ2aWV3LWNoaWxkLXZpZXctY3JlYXRlZFwiLCBhc3luYyAoZSkgPT4ge1xuXHRcdC8vIFRoZSBjb250ZW50IGNyZWF0aW9uIHJ1bGVzIGNvbnN0cnVjdCB0aGUgb3B0aW9ucyBmb3IgdGhlIHZpZXcgaW4gdGhlIGNoaWxkT3B0aW9uc1xuXHRcdC8vIFRoZSB2aWV3IGhhcyBiZWVuIGNyZWF0ZWQgYnV0IG5vdCB5ZXQgYXR0YWNoZWQgb3IgbmF2aWdhdGVkXG5cdFx0Y29uc29sZS5sb2coZSk7XG5cdFx0Y29uc3Qgdmlld09wdGlvbnMgPSBlLmNoaWxkT3B0aW9ucztcblx0XHRsZXQgb3JpZ2luYWxUYXJnZXROYW1lO1xuXHRcdGxldCBjcmVhdGUgPSB0cnVlO1xuXG5cdFx0Ly8gSWYgdGhlIHdpbmRvdy5vcGVuIGNvbnRhaW5lZCBhIHRhcmdldCBpdCBpcyB0aGUgdmlld09wdGlvbnMubmFtZSxcblx0XHQvLyB0aGUgbmFtZSBzdGFydHMgaW50ZXJuYWwtZ2VuZXJhdGVkIGlmIGEgdGFyZ2V0IHdhc24ndCBzcGVjaWZpZWRcblx0XHRpZiAoIXZpZXdPcHRpb25zLm5hbWU/LnN0YXJ0c1dpdGgoXCJpbnRlcm5hbC1nZW5lcmF0ZWRcIikpIHtcblx0XHRcdC8vIFRoaXMgaXMgYSB3aW5kb3cub3BlbiB3aXRoIGEgdGFyZ2V0LCBidXQgd2UgY2FuJ3QgdXNlIHRoZSBvcmlnaW5hbCB0YXJnZXQgbmFtZVxuXHRcdFx0Ly8gYXMgdGhlIHZpZXcgbmFtZSwgYmVjYXVzZSB0aGlzIHdvdWxkIG5vdCBhbGxvdyBpdCB0byBiZSByZS11c2VkLCBzbyB3ZVxuXHRcdFx0Ly8gc3Vic3RpdHV0ZSBhIGRlcml2ZWQgdmlldyBuYW1lIGFuZCB0aGVuIHJlbW92ZSB0aGUgb2xkIHZpZXcgbGF0ZXJcblxuXHRcdFx0Ly8gU3RvcmUgdGhlIG9yaWdpbmFsIHZpZXcgbmFtZSBzbyB0aGF0IHdlIGNhbiBkZXN0cm95IGl0IGxhdGVyXG5cdFx0XHRvcmlnaW5hbFRhcmdldE5hbWUgPSB2aWV3T3B0aW9ucy5uYW1lO1xuXG5cdFx0XHQvLyBTZXQgYSBuZXcgZGVyaXZlZCBuYW1lIGZvciB0aGUgdmlldyBiYXNlZCBvbiB0aGUgb3JpZ2luYWwgbmFtZVxuXHRcdFx0dmlld09wdGlvbnMubmFtZSA9IGAke3ZpZXdPcHRpb25zLm5hbWV9LXZpZXdgO1xuXG5cdFx0XHR0cnkge1xuXHRcdFx0XHQvLyBTZWUgaWYgd2UgY2FuIGdldCB0aGUgZGVyaXZlZCByZXVzYWJsZSB2aWV3IG5hbWVcblx0XHRcdFx0Y29uc3QgY3VycmVudFZpZXcgPSBmaW4uVmlldy53cmFwU3luYyh7IHV1aWQ6IGZpbi5tZS5pZGVudGl0eS51dWlkLCBuYW1lOiB2aWV3T3B0aW9ucy5uYW1lIH0pO1xuXG5cdFx0XHRcdC8vIElmIHdlIGhhdmUgaXQgdGhlbiBuYXZpZ2F0ZSB0byB0aGUgcmVxdWVzdGVkIHVybFxuXHRcdFx0XHRhd2FpdCBjdXJyZW50Vmlldy5uYXZpZ2F0ZSh2aWV3T3B0aW9ucy51cmwpO1xuXG5cdFx0XHRcdC8vIEFuZCBmb2N1cyBpdCwgd2hpY2ggd2lsbCBzd2l0Y2ggdG8gdGhlIHRhYiBpZiBpdHMgbm90IGFjdGl2ZVxuXHRcdFx0XHRhd2FpdCBjdXJyZW50Vmlldy5mb2N1cygpO1xuXG5cdFx0XHRcdC8vIFdlIGhhdmUgcmV1c2VkIHNvIG5vIG5lZWQgdG8gY3JlYXRlXG5cdFx0XHRcdGNyZWF0ZSA9IGZhbHNlO1xuXHRcdFx0fSBjYXRjaCB7XG5cdFx0XHRcdC8vIFNvbWV0aGluZyBmYWlsZWQsIG1vc3QgbGlrZWx5IHRoZSB2aWV3IGRvZXMgbm90IGV4aXN0XG5cdFx0XHRcdC8vIHNvIHRoZSBjcmVhdGUgZmxhZyB3aWxsIHN0aWxsIGJlIHNldFxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFRoZSBjcmVhdGUgZmxhZyBpcyBzZXQgYmVjYXVzZSB3ZSBjb3VsZG4ndCBmaW5kIHRoZSBleGlzdGluZyB2aWV3XG5cdFx0aWYgKGNyZWF0ZSkge1xuXHRcdFx0Ly8gQ3JlYXRlIHRoZSB2aWV3IHVzaW5nIHRoZSBvcmlnaW5hbCB2aWV3IG9wdGlvbnMsIHRoaXMgd2lsbCBqdXN0IGF0dGFjaCB0aGVcblx0XHRcdC8vIHZpZXcgY3JlYXRlZCBmb3IgdXMgYnkgdGhlIGNvbnRlbnQgY3JlYXRpb24gcnVsZXNcblx0XHRcdC8vIE9yIGlmIGl0IGhhZCB0aGUgbmFtZSBzd2FwcGVkIGR1ZSB0byBhIHRhcmdldCBzcGVjaWZpZWQgaW4gdGhlIG9yaWdpbmFsXG5cdFx0XHQvLyB3aW5kb3cub3BlbiBpdCB3aWxsIGNyZWF0ZSBhIG5ldyB2aWV3IHdpdGggdGhlIGRlcml2ZWQgbmFtZVxuXHRcdFx0Y29uc3QgdmlldyA9IGF3YWl0IHBsYXRmb3JtLmNyZWF0ZVZpZXcodmlld09wdGlvbnMsIGUudGFyZ2V0KTtcblxuXHRcdFx0Ly8gV2UgbXVzdCBleHBsaWNpdGx5IG5hdmlnYXRlIHRoZSB2aWV3IGNyZWF0ZWQgYnkgdGhlIGNvbnRlbnQgY3JlYXRpb24gcnVsZXNcblx0XHRcdGF3YWl0IHZpZXcubmF2aWdhdGUodmlld09wdGlvbnMudXJsKTtcblx0XHR9XG5cblx0XHQvLyBDbGVhbnVwIHRoZSB2aWV3IHRoYXQgd2FzIGNyZWF0ZWQgd2l0aCB0aGUgb3JpZ2luYWwgdGFyZ2V0IG5hbWUgaWYgaXQgaGFkIG9uZVxuXHRcdC8vIGFzIHdlIGhhdmUgc3Vic3RpdHV0ZWQgYSB2aWV3IHdpdGggYSBkZXJpdmVkIG5hbWVcblx0XHRpZiAob3JpZ2luYWxUYXJnZXROYW1lKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRjb25zdCB0YXJnZXRWaWV3ID0gZmluLlZpZXcud3JhcFN5bmMoeyB1dWlkOiBmaW4ubWUuaWRlbnRpdHkudXVpZCwgbmFtZTogb3JpZ2luYWxUYXJnZXROYW1lIH0pO1xuXHRcdFx0XHRhd2FpdCB0YXJnZXRWaWV3LmRlc3Ryb3koKTtcblx0XHRcdH0gY2F0Y2gge31cblx0XHR9XG5cdH0pO1xuXG5cdGF3YWl0IG1lLm9uKFwidmlldy1jaGlsZC13aW5kb3ctY3JlYXRlZFwiLCBhc3luYyAoZSkgPT4ge1xuXHRcdC8vIENhbGxlZCB3aGVuIGNvbnRlbnQgaXMgb3BlbmVkIGluIGEgd2luZG93XG5cdFx0Y29uc29sZS5sb2coZSk7XG5cdH0pO1xuXG5cdGF3YWl0IG1lLm9uKFwidmlldy1jaGlsZC1jb250ZW50LW9wZW5lZC1pbi1icm93c2VyXCIsIGFzeW5jIChlKSA9PiB7XG5cdFx0Ly8gQ2FsbGVkIHdoZW4gY29udGVudCBpcyBvcGVuZWQgaW4gdGhlIGJyb3dzZXJcblx0XHRjb25zb2xlLmxvZyhlKTtcblx0fSk7XG5cblx0YXdhaXQgbWUub24oXCJ2aWV3LWNoaWxkLWNvbnRlbnQtYmxvY2tlZFwiLCBhc3luYyAoZSkgPT4ge1xuXHRcdC8vIENhbGxlZCB3aGVuIGNvbnRlbnQgaXMgYmxvY2tlZFxuXHRcdGNvbnNvbGUubG9nKGUpO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBNYXhpbWl6ZSBvZiByZXN0b3JlIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0gd2luIFRoZSB3aW5kb3cgdG8gcGVyZm9ybSB0aGUgYWN0aW9uIG9uLlxuICogQHJldHVybnMgTm90aGluZy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbWF4T3JSZXN0b3JlKHdpbjogT3BlbkZpbi5XaW5kb3cpOiBQcm9taXNlPHZvaWQ+IHtcblx0aWYgKChhd2FpdCB3aW4uZ2V0U3RhdGUoKSkgPT09IFwibm9ybWFsXCIpIHtcblx0XHRyZXR1cm4gd2luLm1heGltaXplKCk7XG5cdH1cblxuXHRyZXR1cm4gd2luLnJlc3RvcmUoKTtcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-content-creation-rules/js/provider.bundle.js b/dev/john/update-logging-example/use-content-creation-rules/js/provider.bundle.js new file mode 100644 index 00000000..19f532b0 --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/js/provider.bundle.js @@ -0,0 +1,13 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/*!********************************!*\ + !*** ./client/src/provider.ts ***! + \********************************/ + +document.addEventListener("DOMContentLoaded", async () => { + await fin.Platform.init(); +}); + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIuYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN4RCxNQUFNLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDM0IsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly91c2UtY29udGVudC1jcmVhdGlvbi1ydWxlcy8uL2NsaWVudC9zcmMvcHJvdmlkZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgYXN5bmMgKCkgPT4ge1xuXHRhd2FpdCBmaW4uUGxhdGZvcm0uaW5pdCgpO1xufSk7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-content-creation-rules/manifest.fin.json b/dev/john/update-logging-example/use-content-creation-rules/manifest.fin.json new file mode 100644 index 00000000..b56679f1 --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/manifest.fin.json @@ -0,0 +1,95 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "shortcut": { + "company": "OpenFin", + "description": "Content Creation Rules", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-content-creation-rules/favicon.ico", + "name": "Content Creation Rules" + }, + "platform": { + "uuid": "use-content-creation-rules", + "name": "use-content-creation-rules", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-content-creation-rules/favicon.ico", + "autoShow": false, + "providerUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-content-creation-rules/html/platform-provider.html", + "waitForPageLoad": false, + "defaultWindowOptions": { + "waitForPageLoad": false, + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-content-creation-rules/html/default-platform-window.html", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-content-creation-rules/favicon.ico", + "contextMenu": true, + "defaultWidth": 600, + "defaultHeight": 600, + "defaultLeft": 0, + "defaultTop": 0, + "saveWindowState": false, + "backgroundThrottling": true, + "minHeight": 445, + "minWidth": 308 + }, + "defaultViewOptions": { + "contentCreation": { + "rules": [ + { + "behavior": "view", + "match": ["*://*.google.com/*"] + }, + { + "behavior": "view", + "match": ["*://*.examples.com/category/business/*"] + }, + { + "behavior": "window", + "match": ["*://*.bing.com/*"] + }, + { + "behavior": "window", + "match": ["*://*.examples.com/category/education/*"] + }, + { + "behavior": "browser", + "match": ["*://*.microsoft.com/*"] + }, + { + "behavior": "block", + "match": ["*://*.apple.com/*"] + } + ] + } + }, + "commands": [ + { + "command": "stack.nextTab", + "keys": "Ctrl+Tab" + } + ] + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "stack", + "id": "no-drop-target", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "name": "component_A1", + "processAffinity": "ps_1", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-content-creation-rules/html/app.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-content-creation-rules/styles/default-window-content.css b/dev/john/update-logging-example/use-content-creation-rules/styles/default-window-content.css new file mode 100644 index 00000000..6d00d23f --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/styles/default-window-content.css @@ -0,0 +1,141 @@ +:root { + --sidebar-width: 120px; + + --layout-locked-icon: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03IDJDNy41NTIyOCAyIDggMi40NDc3MiA4IDNWMjlDOCAyOS41NTIzIDcuNTUyMjggMzAgNyAzMEM2LjQ0NzcyIDMwIDYgMjkuNTUyMyA2IDI5VjNDNiAyLjQ0NzcyIDYuNDQ3NzIgMiA3IDJaIiBmaWxsPSIjRjRGNUY4Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjEuNSAxNEMyMC4xMTkzIDE0IDE5IDE1LjExOTMgMTkgMTYuNVYyMkgxN1YxNi41QzE3IDE0LjAxNDcgMTkuMDE0NyAxMiAyMS41IDEyQzIzLjk4NTMgMTIgMjYgMTQuMDE0NyAyNiAxNi41VjIySDI0VjE2LjVDMjQgMTUuMTE5MyAyMi44ODA3IDE0IDIxLjUgMTRaIiBmaWxsPSIjRjRGNUY4Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjUgMkMyNS41NTIzIDIgMjYgMi40NDc3MiAyNiAzVjEwLjVDMjYgMTEuMDUyMyAyNS41NTIzIDExLjUgMjUgMTEuNUMyNC40NDc3IDExLjUgMjQgMTEuMDUyMyAyNCAxMC41VjNDMjQgMi40NDc3MiAyNC40NDc3IDIgMjUgMloiIGZpbGw9IiNGNEY1RjgiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yIDdDMiA2LjQ0NzcyIDIuNDQ3NzIgNiAzIDZMMjkgNkMyOS41NTIzIDYgMzAgNi40NDc3MiAzMCA3QzMwIDcuNTUyMjggMjkuNTUyMyA4IDI5IDhMMyA4QzIuNDQ3NzIgOCAyIDcuNTUyMjggMiA3WiIgZmlsbD0iI0Y0RjVGOCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIgMjVDMiAyNC40NDc3IDIuNDQ3NzIgMjQgMyAyNEgxMUMxMS41NTIzIDI0IDEyIDI0LjQ0NzcgMTIgMjVDMTIgMjUuNTUyMyAxMS41NTIzIDI2IDExIDI2SDNDMi40NDc3MiAyNiAyIDI1LjU1MjMgMiAyNVoiIGZpbGw9IiNGNEY1RjgiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNSAyMUMxNC40NDc3IDIxIDE0IDIxLjQ0NzcgMTQgMjJWMjlDMTQgMjkuNTUyMyAxNC40NDc3IDMwIDE1IDMwSDI4QzI4LjU1MjMgMzAgMjkgMjkuNTUyMyAyOSAyOVYyMkMyOSAyMS40NDc3IDI4LjU1MjMgMjEgMjggMjFIMTVaTTIxLjUgMjdDMjIuMzI4NCAyNyAyMyAyNi4zMjg0IDIzIDI1LjVDMjMgMjQuNjcxNiAyMi4zMjg0IDI0IDIxLjUgMjRDMjAuNjcxNiAyNCAyMCAyNC42NzE2IDIwIDI1LjVDMjAgMjYuMzI4NCAyMC42NzE2IDI3IDIxLjUgMjdaIiBmaWxsPSIjRjRGNUY4Ii8+Cjwvc3ZnPgo='); + --layout-unlocked-icon: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03IDJDNy41NTIyOCAyIDggMi40NDc3MiA4IDNWMjlDOCAyOS41NTIzIDcuNTUyMjggMzAgNyAzMEM2LjQ0NzcyIDMwIDYgMjkuNTUyMyA2IDI5VjNDNiAyLjQ0NzcyIDYuNDQ3NzIgMiA3IDJaIiBmaWxsPSIjRjRGNUY4Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjUgMkMyNS41NTIzIDIgMjYgMi40NDc3MiAyNiAzVjI5QzI2IDI5LjU1MjMgMjUuNTUyMyAzMCAyNSAzMEMyNC40NDc3IDMwIDI0IDI5LjU1MjMgMjQgMjlWM0MyNCAyLjQ0NzcyIDI0LjQ0NzcgMiAyNSAyWiIgZmlsbD0iI0Y0RjVGOCIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIgN0MyIDYuNDQ3NzIgMi40NDc3MiA2IDMgNkwyOSA2QzI5LjU1MjMgNiAzMCA2LjQ0NzcyIDMwIDdDMzAgNy41NTIyOCAyOS41NTIzIDggMjkgOEwzIDhDMi40NDc3MiA4IDIgNy41NTIyOCAyIDdaIiBmaWxsPSIjRjRGNUY4Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMiAyNUMyIDI0LjQ0NzcgMi40NDc3MiAyNCAzIDI0SDI5QzI5LjU1MjMgMjQgMzAgMjQuNDQ3NyAzMCAyNUMzMCAyNS41NTIzIDI5LjU1MjMgMjYgMjkgMjZIM0MyLjQ0NzcyIDI2IDIgMjUuNTUyMyAyIDI1WiIgZmlsbD0iI0Y0RjVGOCIvPgo8L3N2Zz4K'); + --menu-icon: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNMjQgNmgtMjR2LTRoMjR2NHptMCA0aC0yNHY0aDI0di00em0wIDhoLTI0djRoMjR2LTR6Ii8+PC9zdmc+'); + --logo-icon: url('https://www.capitalgroup.com/content/capital-group/us/en/home/_jcr_content/root/responsivegrid/responsivegrid/responsivegrid/responsivegrid/responsivegrid/responsivegrid/responsivegrid/image.coreimg.100.1440.png/1627670282143/cg-af-white-trans-400x154.png'); +} + +#body-container { + display: flex; +} + +.hidden { + display: none; +} + +left-menu { + padding-left: 4px; + margin-top: 4px; + padding-right: 4px; + border-right: 1px solid var(--tab-button-hover-color); +} + +left-menu ul { + list-style: none; + padding-inline-start: 0px; + margin-block-start: 20px; +} + +left-menu button { + width: var(--sidebar-width); + border: none; + background-color: var(--main-background-color); + color: var(--body-font-color); + text-align: left; +} + +left-menu button:hover { + cursor: pointer; + background-color: var(--tab-button-hover-color); +} + +left-menu button:focus { + outline: 1px solid var(--tab-button-active-color); +} + +fieldset button { + width: var(--sidebar-width); + border: 1px solid var(--tab-button-active-color); + background-color: var(--tab-button-hover-color); + color: var(--body-font-color); + text-align: center; + padding: 3px 0px; + margin: 5px 0px; +} + +fieldset button:hover { + cursor: pointer; + background-color: var(--main-background-color); +} + +fieldset button:focus { + outline: 1px solid var(--tab-button-hover-color); +} + +fieldset input { + margin: 5px 0px; +} + +fieldset label { + font-size: 14px; +} + +.two-sided-container { + transition: 0.8s; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; + height: 100%; + width: 100%; +} + +.face { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + z-index: 1; +} + +.layout-button, +.snapshot-button { + background-color: var(--of-highlight); +} + +.layout-button:hover, +.snapshot-button:hover { + background-color: var(--of-dark-theme); +} + +#theme-button:after { + content: ''; + background-color: var(--of-default-grey-light); + padding: 5px; + display: inline-block; + margin-left: 10px; + margin-top: 10px; +} + +#menu-button { + background-image: var(--menu-icon); + background-size: 12px; +} + +#lock-button { + background-size: 16px; + background-image: var(--layout-unlocked-icon); +} + +#lock-button.layout-locked { + background-image: var(--layout-locked-icon); +} + +#logo { + position: fixed; + top: 0; + left: 0; + margin: 0; + padding: 0; +} + +.center-form { + color: #eee; + display: flex; + height: 100%; + margin: 0; + justify-content: center; + align-items: center; + font-family: Arial, Helvetica, sans-serif; +} diff --git a/dev/john/update-logging-example/use-content-creation-rules/styles/default-window-styles.css b/dev/john/update-logging-example/use-content-creation-rules/styles/default-window-styles.css new file mode 100644 index 00000000..87bfc658 --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/styles/default-window-styles.css @@ -0,0 +1,93 @@ +/* This is a copy of the default CSS that is loaded on your Platform Windows. */ +/* Use this as a reference to set your color, icon, and spacing preferences. */ + +:root { + /* Colors used for dark theme */ + --of-default-black: black; + --of-default-charcoal-dark: #111118; + --of-default-charcoal-light: #2a292f; + --of-default-grey-dark: #a5aebd; + --of-default-grey-dark-opacity: #a5aebd2e; + --of-default-grey-light: #f4f5f8; + --of-default-grey-light-opacity: #f4f5f82e; + --of-default-white: white; + --of-dark-theme: #7b7bff; + --of-light-theme: #504cff; + --of-highlight: #958eff; + --of-highlight-opacity: #958eff26; + --of-default-red: red; + --of-default-red-negative: #f55d5f; + + /* Main colors to set from the above list */ + --main-background-color: var(--of-default-charcoal-dark); + --secondary-background-color: var(--of-default-black); + --tab-background-color: var(--of-default-charcoal-light); + --tab-button-hover-color: var(--of-default-grey-dark-opacity); + --tab-button-active-color: var(--of-default-grey-light-opacity); + --tab-border-top-color: var(--of-dark-theme); + --tab-border-top-highlight-color: var(--of-light-theme); + --tab-font-color: var(--of-default-white); + --top-bar-close-button-color: var(--of-default-red); + --top-bar-close-button-active-color: var(--of-default-red-negative); + --drop-target-border-color: var(--of-highlight); + --drop-target-background-color: var(--of-highlight-opacity); + + /* Colors that default to dependent on Main Colors, but should be uniquely editable */ + --frame-background-color: var(--secondary-background-color); + --body-font-color: var(--tab-font-color); + --splitter-color: var(--secondary-background-color); + --splitter-hover-color: var(--tab-background-color); + --tabs-bar-background-color: var(--secondary-background-color); + --title-bar-background-color: var(--main-background-color); + --color-behind-views: var(--main-background-color); /* only seen if there's a problem with the view */ + --tab-background-active-color: var(--tab-background-color); + --top-bar-button-hover-color: var(--tab-background-color); + --top-bar-button-active-color: var(--tab-button-active-color); + + /* Measurements for various components */ + --title-bar-height: 30px; + --title-bar-border-bottom-height: 1px; + --header-border-bottom-height: 2px; + --corner-radius: 0px; + --splitter-width: 4px; + + --body-container-padding-top: 0px; + --body-container-padding-right: 0px; + --body-container-padding-bottom: 0px; + --body-container-padding-left: 0px; + + --body-container-width: calc( + 100% - var(--body-container-padding-left) - var(--body-container-padding-right) + ); + --body-container-height: calc( + 100% - var(--title-bar-height) - var(--title-bar-border-bottom-height) - var(--body-container-padding-top) - + var(--body-container-padding-bottom) + ); + --body-container-padding: var(--body-container-padding-top) var(--body-container-padding-right) + var(--body-container-padding-bottom) var(--body-container-padding-left); + + --layout-container-padding-top: 0px; + --layout-container-padding-right: 0px; + --layout-container-padding-bottom: 0px; + --layout-container-padding-left: 0px; + --layout-container-from-top: calc( + var(--title-bar-height) + var(--title-bar-border-bottom-height) + var(--layout-container-padding-top) + ); + + --layout-container-width: calc( + 100% - var(--layout-container-padding-left) - var(--layout-container-padding-right) + ); + --layout-container-height: calc( + 100% - var(--header-border-bottom-height) - var(--layout-container-padding-top) - + var(--layout-container-padding-bottom) + ); + --layout-container-padding: var(--layout-container-padding-top) var(--layout-container-padding-right) + var(--layout-container-padding-bottom) var(--layout-container-padding-left); + + /* Top Bar and Tab Icons */ + --close-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvWC9EYXJrIFQuIj4KPHBhdGggaWQ9IkNvbWJpbmVkIFNoYXBlIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTcuNDI2MDEgNi4xNjEwN0M3LjA3MTcgNS45MTU2MyA2LjU4MTg0IDUuOTUwNjkgNi4yNjYyNyA2LjI2NjI3QzUuOTExMjQgNi42MjEyOSA1LjkxMTI0IDcuMTk2ODkgNi4yNjYyNyA3LjU1MTkyTDE0LjcxNDQgMTZMNi4yNjYyNyAyNC40NDgxTDYuMTYxMDcgMjQuNTc0QzUuOTE1NjMgMjQuOTI4MyA1Ljk1MDY5IDI1LjQxODIgNi4yNjYyNyAyNS43MzM3QzYuNjIxMjkgMjYuMDg4OCA3LjE5Njg5IDI2LjA4ODggNy41NTE5MiAyNS43MzM3TDE2IDE3LjI4NTZMMjQuNDQ4MSAyNS43MzM3TDI0LjU3NCAyNS44Mzg5QzI0LjkyODMgMjYuMDg0NCAyNS40MTgyIDI2LjA0OTMgMjUuNzMzNyAyNS43MzM3QzI2LjA4ODggMjUuMzc4NyAyNi4wODg4IDI0LjgwMzEgMjUuNzMzNyAyNC40NDgxTDE3LjI4NTYgMTZMMjUuNzMzNyA3LjU1MTkyTDI1LjgzODkgNy40MjYwMUMyNi4wODQ0IDcuMDcxNyAyNi4wNDkzIDYuNTgxODQgMjUuNzMzNyA2LjI2NjI3QzI1LjM3ODcgNS45MTEyNCAyNC44MDMxIDUuOTExMjQgMjQuNDQ4MSA2LjI2NjI3TDE2IDE0LjcxNDRMNy41NTE5MiA2LjI2NjI3TDcuNDI2MDEgNi4xNjEwN1oiIGZpbGw9IiNGMkY0RjkiLz4KPC9nPgo8L3N2Zz4K'); + --minimize-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvTWluaW1pemUvV2luZG93L0RhcmsgVC4iPgo8cmVjdCBpZD0iUmVjdGFuZ2xlIiB4PSIzIiB5PSIyNCIgd2lkdGg9IjI2IiBoZWlnaHQ9IjMiIHJ4PSIxLjUiIGZpbGw9IiNGMkY0RjkiLz4KPC9nPgo8L3N2Zz4K'); + --expand-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvRXhwYW5kL0RhcmsgVC4iPgo8cGF0aCBpZD0iQ29tYmluZWQgU2hhcGUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTYuOTU2NSA1TDI2LjAzNDggNS4wMDAwNEwyNi4wOTE1IDUuMDAxMThMMjYuMTQxMyA1LjAwNDk4TDI2LjIwNDMgNS4wMTM1NEwyNi4yNDE0IDUuMDIwNTFMMjYuMjc1NiA1LjAyODM1TDI2LjMwMzUgNS4wMzU3NkwyNi4zNTc3IDUuMDUyODJMMjYuNDAyOCA1LjA2OTc3TDI2LjQ1NzkgNS4wOTQxOEwyNi41MDkyIDUuMTIwNzNMMjYuNTY0MyA1LjE1NDFMMjYuNjAxMyA1LjE3OTNMMjYuNjMyNiA1LjIwMjhMMjYuNjc0IDUuMjM3MThMMjYuNzEwNSA1LjI3MDkyTDI2Ljc0MTggNS4zMDI4MkwyNi43ODEgNS4zNDczM0wyNi43OTM4IDUuMzYzMjRDMjYuODEzMyA1LjM4Nzg1IDI2LjgzMTYgNS40MTM0MyAyNi44NDg2IDUuNDM5OTFDMjYuODcgNS40NzMwNCAyNi44ODkxIDUuNTA3MjIgMjYuOTA1OSA1LjU0MjIxTDI2LjkyNDMgNS41ODI4OUwyNi45NDA2IDUuNjIzOTdMMjYuOTU2MyA1LjY3MDA1QzI2Ljk2NDkgNS42OTcyNyAyNi45NzIyIDUuNzI0OTcgMjYuOTc4MyA1Ljc1MzEyTDI2Ljk4OTYgNS44MTUxN0MyNi45OTQyIDUuODQ1OTIgMjYuOTk3MyA1Ljg3NzE1IDI2Ljk5ODggNS45MDg3OEwyNyA1Ljk1NjUyVjE1LjA0MzVDMjcgMTUuNTcxOCAyNi41NzE4IDE2IDI2LjA0MzUgMTZDMjUuNTMxMiAxNiAyNS4xMTMgMTUuNTk3MyAyNS4wODgxIDE1LjA5MTJMMjUuMDg3IDE1LjA0MzVWOC4yNjU1N0wxOC40Njk4IDE0Ljg4MjlDMTguMDk2MyAxNS4yNTY0IDE3LjQ5MDcgMTUuMjU2NCAxNy4xMTcxIDE0Ljg4MjlDMTYuNzU2IDE0LjUyMTggMTYuNzQ0IDEzLjk0MzggMTcuMDgxIDEzLjU2ODNMMTcuMTE3MSAxMy41MzAyTDIzLjczNCA2LjkxMzA0SDE2Ljk1NjVDMTYuNDI4MiA2LjkxMzA0IDE2IDYuNDg0NzkgMTYgNS45NTY1MkMxNiA1LjQ0NDI2IDE2LjQwMjcgNS4wMjYwNSAxNi45MDg4IDUuMDAxMTdMMTYuOTU2NSA1WiIgZmlsbD0iI0YyRjRGOSIvPgo8cGF0aCBpZD0iQ29tYmluZWQgU2hhcGUgQ29weSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01Ljk1NjUyIDI3TDUuOTA4NTQgMjYuOTk4OEw1Ljg1ODc0IDI2Ljk5NUw1Ljc5NTcyIDI2Ljk4NjVMNS43NTg1OCAyNi45Nzk1TDUuNzI0NDMgMjYuOTcxNkw1LjY5NjUxIDI2Ljk2NDJMNS42NDIyNyAyNi45NDcyTDUuNTk3MjMgMjYuOTMwMkw1LjU0MjEzIDI2LjkwNThMNS40OTA4NSAyNi44NzkzTDUuNDM1NjkgMjYuODQ1OUw1LjM5ODcyIDI2LjgyMDdMNS4zNjc0NCAyNi43OTcyTDUuMzI2MDQgMjYuNzYyOEw1LjI4OTUyIDI2LjcyOTFMNS4yNTgyMiAyNi42OTcyTDUuMjE5IDI2LjY1MjdMNS4yMDYxNyAyNi42MzY4QzUuMTg2NjkgMjYuNjEyMiA1LjE2ODQgMjYuNTg2NiA1LjE1MTM3IDI2LjU2MDFDNS4xMjk5NyAyNi41MjcgNS4xMTA5MSAyNi40OTI4IDUuMDk0MSAyNi40NTc4TDUuMDc1NzIgMjYuNDE3MUw1LjA1OTQyIDI2LjM3Nkw1LjA0MzcgMjYuMzI5OUM1LjAzNTEzIDI2LjMwMjcgNS4wMjc3NyAyNi4yNzUgNS4wMjE2NyAyNi4yNDY5TDUuMDEwMzcgMjYuMTg0OEM1LjAwNTgyIDI2LjE1NDEgNS4wMDI3MiAyNi4xMjI4IDUuMDAxMTcgMjYuMDkxMkw1IDI2LjA0MzVWMTYuOTU2NUM1IDE2LjQyODIgNS40MjgyNSAxNiA1Ljk1NjUyIDE2QzYuNDY4NzkgMTYgNi44ODcgMTYuNDAyNyA2LjkxMTg3IDE2LjkwODhMNi45MTMwNCAxNi45NTY1VjIzLjczNDRMMTMuNTMwMiAxNy4xMTcxQzEzLjkwMzcgMTYuNzQzNiAxNC41MDkzIDE2Ljc0MzYgMTQuODgyOSAxNy4xMTcxQzE1LjI0NCAxNy40NzgyIDE1LjI1NiAxOC4wNTYyIDE0LjkxOSAxOC40MzE3TDE0Ljg4MjkgMTguNDY5OEw4LjI2NjA0IDI1LjA4N0gxNS4wNDM1QzE1LjU3MTggMjUuMDg3IDE2IDI1LjUxNTIgMTYgMjYuMDQzNUMxNiAyNi41NTU3IDE1LjU5NzMgMjYuOTc0IDE1LjA5MTIgMjYuOTk4OEwxNS4wNDM1IDI3SDUuOTU2NTJaIiBmaWxsPSIjRjJGNEY5Ii8+CjwvZz4KPC9zdmc+Cg=='); + --tab-close-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvWC9EYXJrIFQuIj4KPHBhdGggaWQ9IkNvbWJpbmVkIFNoYXBlIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTcuNDI2MDEgNi4xNjEwN0M3LjA3MTcgNS45MTU2MyA2LjU4MTg0IDUuOTUwNjkgNi4yNjYyNyA2LjI2NjI3QzUuOTExMjQgNi42MjEyOSA1LjkxMTI0IDcuMTk2ODkgNi4yNjYyNyA3LjU1MTkyTDE0LjcxNDQgMTZMNi4yNjYyNyAyNC40NDgxTDYuMTYxMDcgMjQuNTc0QzUuOTE1NjMgMjQuOTI4MyA1Ljk1MDY5IDI1LjQxODIgNi4yNjYyNyAyNS43MzM3QzYuNjIxMjkgMjYuMDg4OCA3LjE5Njg5IDI2LjA4ODggNy41NTE5MiAyNS43MzM3TDE2IDE3LjI4NTZMMjQuNDQ4MSAyNS43MzM3TDI0LjU3NCAyNS44Mzg5QzI0LjkyODMgMjYuMDg0NCAyNS40MTgyIDI2LjA0OTMgMjUuNzMzNyAyNS43MzM3QzI2LjA4ODggMjUuMzc4NyAyNi4wODg4IDI0LjgwMzEgMjUuNzMzNyAyNC40NDgxTDE3LjI4NTYgMTZMMjUuNzMzNyA3LjU1MTkyTDI1LjgzODkgNy40MjYwMUMyNi4wODQ0IDcuMDcxNyAyNi4wNDkzIDYuNTgxODQgMjUuNzMzNyA2LjI2NjI3QzI1LjM3ODcgNS45MTEyNCAyNC44MDMxIDUuOTExMjQgMjQuNDQ4MSA2LjI2NjI3TDE2IDE0LjcxNDRMNy41NTE5MiA2LjI2NjI3TDcuNDI2MDEgNi4xNjEwN1oiIGZpbGw9IiNGMkY0RjkiLz4KPC9nPgo8L3N2Zz4K'); + --logo-icon-url: url('http://localhost:5050/favicon.svg'); +} diff --git a/dev/john/update-logging-example/use-content-creation-rules/styles/light-theme.css b/dev/john/update-logging-example/use-content-creation-rules/styles/light-theme.css new file mode 100644 index 00000000..9098fa88 --- /dev/null +++ b/dev/john/update-logging-example/use-content-creation-rules/styles/light-theme.css @@ -0,0 +1,40 @@ +:root.light-theme { + /* Setting some shared colors up top for organization */ + --black: black; + --white: white; + --grey-light: #f4f5f8; + --grey: #d8d8d8; + --grey-dark: #a5aebd; + + /* Setting the colors on the main components I want to override. */ + /* These will trickle down to other elements, as shown in frame-styles-template.css */ + --main-background-color: var(--grey-light); + --secondary-background-color: var(--white); + --tab-button-hover-color: var(--grey); + --tab-button-active-color: var(--grey-dark); + --tab-font-color: var(--black); + + /* Setting colors that depend on my main component colors */ + --tab-background-color: var(--main-background-color); + --drop-target-border-color: var(--tab-border-top-highlight-color); + --top-bar-button-hover-color: var(--tab-button-hover-color); + --top-bar-button-active-color: var(--tab-button-active-color); + --splitter-hover-color: var(--tab-button-active-color); + + --close-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvWC9MaWdodCBULiI+CjxwYXRoIGlkPSJDb21iaW5lZCBTaGFwZSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjQyNjAxIDYuMTYxMDdDNy4wNzE3IDUuOTE1NjMgNi41ODE4NCA1Ljk1MDY5IDYuMjY2MjcgNi4yNjYyN0M1LjkxMTI0IDYuNjIxMjkgNS45MTEyNCA3LjE5Njg5IDYuMjY2MjcgNy41NTE5MkwxNC43MTQ0IDE2TDYuMjY2MjcgMjQuNDQ4MUw2LjE2MTA3IDI0LjU3NEM1LjkxNTYzIDI0LjkyODMgNS45NTA2OSAyNS40MTgyIDYuMjY2MjcgMjUuNzMzN0M2LjYyMTI5IDI2LjA4ODggNy4xOTY4OSAyNi4wODg4IDcuNTUxOTIgMjUuNzMzN0wxNiAxNy4yODU2TDI0LjQ0ODEgMjUuNzMzN0wyNC41NzQgMjUuODM4OUMyNC45MjgzIDI2LjA4NDQgMjUuNDE4MiAyNi4wNDkzIDI1LjczMzcgMjUuNzMzN0MyNi4wODg4IDI1LjM3ODcgMjYuMDg4OCAyNC44MDMxIDI1LjczMzcgMjQuNDQ4MUwxNy4yODU2IDE2TDI1LjczMzcgNy41NTE5MkwyNS44Mzg5IDcuNDI2MDFDMjYuMDg0NCA3LjA3MTcgMjYuMDQ5MyA2LjU4MTg0IDI1LjczMzcgNi4yNjYyN0MyNS4zNzg3IDUuOTExMjQgMjQuODAzMSA1LjkxMTI0IDI0LjQ0ODEgNi4yNjYyN0wxNiAxNC43MTQ0TDcuNTUxOTIgNi4yNjYyN0w3LjQyNjAxIDYuMTYxMDdaIiBmaWxsPSIjMkEyOTJGIi8+CjwvZz4KPC9zdmc+Cg=='); + --expand-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvRXhwYW5kL0xpZ2h0IFQuIj4KPHBhdGggaWQ9IkNvbWJpbmVkIFNoYXBlIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTE2Ljk1NjUgNUwyNi4wMzQ4IDUuMDAwMDRMMjYuMDkxNSA1LjAwMTE4TDI2LjE0MTMgNS4wMDQ5OEwyNi4yMDQzIDUuMDEzNTRMMjYuMjQxNCA1LjAyMDUxTDI2LjI3NTYgNS4wMjgzNUwyNi4zMDM1IDUuMDM1NzZMMjYuMzU3NyA1LjA1MjgyTDI2LjQwMjggNS4wNjk3N0wyNi40NTc5IDUuMDk0MThMMjYuNTA5MiA1LjEyMDczTDI2LjU2NDMgNS4xNTQxTDI2LjYwMTMgNS4xNzkzTDI2LjYzMjYgNS4yMDI4TDI2LjY3NCA1LjIzNzE4TDI2LjcxMDUgNS4yNzA5MkwyNi43NDE4IDUuMzAyODJMMjYuNzgxIDUuMzQ3MzNMMjYuNzkzOCA1LjM2MzI0QzI2LjgxMzMgNS4zODc4NSAyNi44MzE2IDUuNDEzNDMgMjYuODQ4NiA1LjQzOTkxQzI2Ljg3IDUuNDczMDQgMjYuODg5MSA1LjUwNzIyIDI2LjkwNTkgNS41NDIyMUwyNi45MjQzIDUuNTgyODlMMjYuOTQwNiA1LjYyMzk3TDI2Ljk1NjMgNS42NzAwNUMyNi45NjQ5IDUuNjk3MjcgMjYuOTcyMiA1LjcyNDk3IDI2Ljk3ODMgNS43NTMxMkwyNi45ODk2IDUuODE1MTdDMjYuOTk0MiA1Ljg0NTkyIDI2Ljk5NzMgNS44NzcxNSAyNi45OTg4IDUuOTA4NzhMMjcgNS45NTY1MlYxNS4wNDM1QzI3IDE1LjU3MTggMjYuNTcxOCAxNiAyNi4wNDM1IDE2QzI1LjUzMTIgMTYgMjUuMTEzIDE1LjU5NzMgMjUuMDg4MSAxNS4wOTEyTDI1LjA4NyAxNS4wNDM1VjguMjY1NTdMMTguNDY5OCAxNC44ODI5QzE4LjA5NjMgMTUuMjU2NCAxNy40OTA3IDE1LjI1NjQgMTcuMTE3MSAxNC44ODI5QzE2Ljc1NiAxNC41MjE4IDE2Ljc0NCAxMy45NDM4IDE3LjA4MSAxMy41NjgzTDE3LjExNzEgMTMuNTMwMkwyMy43MzQgNi45MTMwNEgxNi45NTY1QzE2LjQyODIgNi45MTMwNCAxNiA2LjQ4NDc5IDE2IDUuOTU2NTJDMTYgNS40NDQyNiAxNi40MDI3IDUuMDI2MDUgMTYuOTA4OCA1LjAwMTE3TDE2Ljk1NjUgNVoiIGZpbGw9IiMyQTI5MkYiLz4KPHBhdGggaWQ9IkNvbWJpbmVkIFNoYXBlIENvcHkiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNS45NTY1MiAyN0w1LjkwODU0IDI2Ljk5ODhMNS44NTg3NCAyNi45OTVMNS43OTU3MiAyNi45ODY1TDUuNzU4NTggMjYuOTc5NUw1LjcyNDQzIDI2Ljk3MTZMNS42OTY1MSAyNi45NjQyTDUuNjQyMjcgMjYuOTQ3Mkw1LjU5NzIzIDI2LjkzMDJMNS41NDIxMyAyNi45MDU4TDUuNDkwODUgMjYuODc5M0w1LjQzNTY5IDI2Ljg0NTlMNS4zOTg3MiAyNi44MjA3TDUuMzY3NDQgMjYuNzk3Mkw1LjMyNjA0IDI2Ljc2MjhMNS4yODk1MiAyNi43MjkxTDUuMjU4MjIgMjYuNjk3Mkw1LjIxOSAyNi42NTI3TDUuMjA2MTcgMjYuNjM2OEM1LjE4NjY5IDI2LjYxMjIgNS4xNjg0IDI2LjU4NjYgNS4xNTEzNyAyNi41NjAxQzUuMTI5OTcgMjYuNTI3IDUuMTEwOTEgMjYuNDkyOCA1LjA5NDEgMjYuNDU3OEw1LjA3NTcyIDI2LjQxNzFMNS4wNTk0MiAyNi4zNzZMNS4wNDM3IDI2LjMyOTlDNS4wMzUxMyAyNi4zMDI3IDUuMDI3NzcgMjYuMjc1IDUuMDIxNjcgMjYuMjQ2OUw1LjAxMDM3IDI2LjE4NDhDNS4wMDU4MiAyNi4xNTQxIDUuMDAyNzIgMjYuMTIyOCA1LjAwMTE3IDI2LjA5MTJMNSAyNi4wNDM1VjE2Ljk1NjVDNSAxNi40MjgyIDUuNDI4MjUgMTYgNS45NTY1MiAxNkM2LjQ2ODc5IDE2IDYuODg3IDE2LjQwMjcgNi45MTE4NyAxNi45MDg4TDYuOTEzMDQgMTYuOTU2NVYyMy43MzQ0TDEzLjUzMDIgMTcuMTE3MUMxMy45MDM3IDE2Ljc0MzYgMTQuNTA5MyAxNi43NDM2IDE0Ljg4MjkgMTcuMTE3MUMxNS4yNDQgMTcuNDc4MiAxNS4yNTYgMTguMDU2MiAxNC45MTkgMTguNDMxN0wxNC44ODI5IDE4LjQ2OThMOC4yNjYwNCAyNS4wODdIMTUuMDQzNUMxNS41NzE4IDI1LjA4NyAxNiAyNS41MTUyIDE2IDI2LjA0MzVDMTYgMjYuNTU1NyAxNS41OTczIDI2Ljk3NCAxNS4wOTEyIDI2Ljk5ODhMMTUuMDQzNSAyN0g1Ljk1NjUyWiIgZmlsbD0iIzJBMjkyRiIvPgo8L2c+Cjwvc3ZnPgo='); + --minimize-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvTWluaW1pemUvV2luZG93L0xpZ2h0IFQuIj4KPHJlY3QgaWQ9IlJlY3RhbmdsZSIgeD0iMyIgeT0iMjQiIHdpZHRoPSIyNiIgaGVpZ2h0PSIzIiByeD0iMS41IiBmaWxsPSIjMkEyOTJGIi8+CjwvZz4KPC9zdmc+Cg=='); + --tab-close-button-url: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgaWQ9IjAyIC0gSUNPTlMvWC9MaWdodCBULiI+CjxwYXRoIGlkPSJDb21iaW5lZCBTaGFwZSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03LjQyNjAxIDYuMTYxMDdDNy4wNzE3IDUuOTE1NjMgNi41ODE4NCA1Ljk1MDY5IDYuMjY2MjcgNi4yNjYyN0M1LjkxMTI0IDYuNjIxMjkgNS45MTEyNCA3LjE5Njg5IDYuMjY2MjcgNy41NTE5MkwxNC43MTQ0IDE2TDYuMjY2MjcgMjQuNDQ4MUw2LjE2MTA3IDI0LjU3NEM1LjkxNTYzIDI0LjkyODMgNS45NTA2OSAyNS40MTgyIDYuMjY2MjcgMjUuNzMzN0M2LjYyMTI5IDI2LjA4ODggNy4xOTY4OSAyNi4wODg4IDcuNTUxOTIgMjUuNzMzN0wxNiAxNy4yODU2TDI0LjQ0ODEgMjUuNzMzN0wyNC41NzQgMjUuODM4OUMyNC45MjgzIDI2LjA4NDQgMjUuNDE4MiAyNi4wNDkzIDI1LjczMzcgMjUuNzMzN0MyNi4wODg4IDI1LjM3ODcgMjYuMDg4OCAyNC44MDMxIDI1LjczMzcgMjQuNDQ4MUwxNy4yODU2IDE2TDI1LjczMzcgNy41NTE5MkwyNS44Mzg5IDcuNDI2MDFDMjYuMDg0NCA3LjA3MTcgMjYuMDQ5MyA2LjU4MTg0IDI1LjczMzcgNi4yNjYyN0MyNS4zNzg3IDUuOTExMjQgMjQuODAzMSA1LjkxMTI0IDI0LjQ0ODEgNi4yNjYyN0wxNiAxNC43MTQ0TDcuNTUxOTIgNi4yNjYyN0w3LjQyNjAxIDYuMTYxMDdaIiBmaWxsPSIjMkEyOTJGIi8+CjwvZz4KPC9zdmc+Cg=='); + + --layout-locked-icon: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03IDJDNy41NTIyOCAyIDggMi40NDc3MiA4IDNWMjlDOCAyOS41NTIzIDcuNTUyMjggMzAgNyAzMEM2LjQ0NzcyIDMwIDYgMjkuNTUyMyA2IDI5VjNDNiAyLjQ0NzcyIDYuNDQ3NzIgMiA3IDJaIiBmaWxsPSIjMkEyOTJGIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjEuNSAxNEMyMC4xMTkzIDE0IDE5IDE1LjExOTMgMTkgMTYuNVYyMkgxN1YxNi41QzE3IDE0LjAxNDcgMTkuMDE0NyAxMiAyMS41IDEyQzIzLjk4NTMgMTIgMjYgMTQuMDE0NyAyNiAxNi41VjIySDI0VjE2LjVDMjQgMTUuMTE5MyAyMi44ODA3IDE0IDIxLjUgMTRaIiBmaWxsPSIjMkEyOTJGIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMjUgMkMyNS41NTIzIDIgMjYgMi40NDc3MiAyNiAzVjEwLjVDMjYgMTEuMDUyMyAyNS41NTIzIDExLjUgMjUgMTEuNUMyNC40NDc3IDExLjUgMjQgMTEuMDUyMyAyNCAxMC41VjNDMjQgMi40NDc3MiAyNC40NDc3IDIgMjUgMloiIGZpbGw9IiMyQTI5MkYiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yIDdDMiA2LjQ0NzcyIDIuNDQ3NzIgNiAzIDZMMjkgNkMyOS41NTIzIDYgMzAgNi40NDc3MiAzMCA3QzMwIDcuNTUyMjggMjkuNTUyMyA4IDI5IDhMMyA4QzIuNDQ3NzIgOCAyIDcuNTUyMjggMiA3WiIgZmlsbD0iIzJBMjkyRiIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIgMjVDMiAyNC40NDc3IDIuNDQ3NzIgMjQgMyAyNEgxMUMxMS41NTIzIDI0IDEyIDI0LjQ0NzcgMTIgMjVDMTIgMjUuNTUyMyAxMS41NTIzIDI2IDExIDI2SDNDMi40NDc3MiAyNiAyIDI1LjU1MjMgMiAyNVoiIGZpbGw9IiMyQTI5MkYiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNSAyMUMxNC40NDc3IDIxIDE0IDIxLjQ0NzcgMTQgMjJWMjlDMTQgMjkuNTUyMyAxNC40NDc3IDMwIDE1IDMwSDI4QzI4LjU1MjMgMzAgMjkgMjkuNTUyMyAyOSAyOVYyMkMyOSAyMS40NDc3IDI4LjU1MjMgMjEgMjggMjFIMTVaTTIxLjUgMjdDMjIuMzI4NCAyNyAyMyAyNi4zMjg0IDIzIDI1LjVDMjMgMjQuNjcxNiAyMi4zMjg0IDI0IDIxLjUgMjRDMjAuNjcxNiAyNCAyMCAyNC42NzE2IDIwIDI1LjVDMjAgMjYuMzI4NCAyMC42NzE2IDI3IDIxLjUgMjdaIiBmaWxsPSIjMkEyOTJGIi8+Cjwvc3ZnPgo='); + --layout-unlocked-icon: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTcgMjlWMyIgc3Ryb2tlPSIjMkEyOTJGIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMjUgMjlMMjUgMyIgc3Ryb2tlPSIjMkEyOTJGIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8cGF0aCBkPSJNMjkgN0wzIDciIHN0cm9rZT0iIzJBMjkyRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPHBhdGggZD0iTTI5IDI1TDMgMjUiIHN0cm9rZT0iIzJBMjkyRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KPC9zdmc+Cg=='); + --menu-icon: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMjQgNmgtMjR2LTRoMjR2NHptMCA0aC0yNHY0aDI0di00em0wIDhoLTI0djRoMjR2LTR6Ii8+PC9zdmc+'); +} + +/* Icon flips to match the light theme color */ +:root.light-theme .lm_popout, +:root.light-theme .lm_maximise, +:root.light-theme .lm_close, +:root.light-theme #theme-button:after { + filter: invert(100%); +} diff --git a/dev/john/update-logging-example/use-dynamic-manifest-basic/common/images/icon-blue.png b/dev/john/update-logging-example/use-dynamic-manifest-basic/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-dynamic-manifest-basic/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-dynamic-manifest-basic/common/style/app.css b/dev/john/update-logging-example/use-dynamic-manifest-basic/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-dynamic-manifest-basic/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-dynamic-manifest-basic/favicon.ico b/dev/john/update-logging-example/use-dynamic-manifest-basic/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-dynamic-manifest-basic/favicon.ico differ diff --git a/dev/john/update-logging-example/use-dynamic-manifest-basic/html/app-dev.html b/dev/john/update-logging-example/use-dynamic-manifest-basic/html/app-dev.html new file mode 100644 index 00000000..512e9bda --- /dev/null +++ b/dev/john/update-logging-example/use-dynamic-manifest-basic/html/app-dev.html @@ -0,0 +1,29 @@ + + + + + + + Dynamic Manifest + + + + +
+
+

Dynamic Manifest

+

How to provide dynamic manifests from an endpoint.

+
+
+ OpenFin +
+
+
+

+ This is the + Development + environment +

+
+ + diff --git a/dev/john/update-logging-example/use-dynamic-manifest-basic/html/app-staging.html b/dev/john/update-logging-example/use-dynamic-manifest-basic/html/app-staging.html new file mode 100644 index 00000000..b7955118 --- /dev/null +++ b/dev/john/update-logging-example/use-dynamic-manifest-basic/html/app-staging.html @@ -0,0 +1,29 @@ + + + + + + + Dynamic Manifest + + + + +
+
+

Dynamic Manifest

+

How to provide dynamic manifests from an endpoint.

+
+
+ OpenFin +
+
+
+

+ This is the + Staging + environment +

+
+ + diff --git a/dev/john/update-logging-example/use-interop-cloud-interop/common/images/icon-blue.png b/dev/john/update-logging-example/use-interop-cloud-interop/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-interop-cloud-interop/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-interop-cloud-interop/common/style/app.css b/dev/john/update-logging-example/use-interop-cloud-interop/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-interop-cloud-interop/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-interop-cloud-interop/favicon.ico b/dev/john/update-logging-example/use-interop-cloud-interop/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-interop-cloud-interop/favicon.ico differ diff --git a/dev/john/update-logging-example/use-interop-cloud-interop/html/provider.html b/dev/john/update-logging-example/use-interop-cloud-interop/html/provider.html new file mode 100644 index 00000000..91029415 --- /dev/null +++ b/dev/john/update-logging-example/use-interop-cloud-interop/html/provider.html @@ -0,0 +1,17 @@ + + + + + + OpenFin Template + + + + + + +
+

Platform Provider

+
+ + diff --git a/dev/john/update-logging-example/use-interop-cloud-interop/html/window.html b/dev/john/update-logging-example/use-interop-cloud-interop/html/window.html new file mode 100644 index 00000000..4a3e7430 --- /dev/null +++ b/dev/john/update-logging-example/use-interop-cloud-interop/html/window.html @@ -0,0 +1,29 @@ + + + + + + + Interop + + + + + +
+ +
+

+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/dev/john/update-logging-example/use-interop-cloud-interop/js/provider.bundle.js b/dev/john/update-logging-example/use-interop-cloud-interop/js/provider.bundle.js new file mode 100644 index 00000000..e07005cd --- /dev/null +++ b/dev/john/update-logging-example/use-interop-cloud-interop/js/provider.bundle.js @@ -0,0 +1,5982 @@ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "../../../node_modules/@openfin/cloud-interop/out/index.js": +/*!*****************************************************************!*\ + !*** ../../../node_modules/@openfin/cloud-interop/out/index.js ***! + \*****************************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ cloudInteropOverride: () => (/* binding */ cloudInteropOverride) +/* harmony export */ }); +/* harmony import */ var buffer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! buffer */ "../../../node_modules/buffer/index.js"); + + +function bind(fn, thisArg) { + return function wrap() { + return fn.apply(thisArg, arguments); + }; +} + +// utils is a library of generic helper functions non-specific to axios + +const {toString} = Object.prototype; +const {getPrototypeOf} = Object; + +const kindOf = (cache => thing => { + const str = toString.call(thing); + return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase()); +})(Object.create(null)); + +const kindOfTest = (type) => { + type = type.toLowerCase(); + return (thing) => kindOf(thing) === type +}; + +const typeOfTest = type => thing => typeof thing === type; + +/** + * Determine if a value is an Array + * + * @param {Object} val The value to test + * + * @returns {boolean} True if value is an Array, otherwise false + */ +const {isArray} = Array; + +/** + * Determine if a value is undefined + * + * @param {*} val The value to test + * + * @returns {boolean} True if the value is undefined, otherwise false + */ +const isUndefined = typeOfTest('undefined'); + +/** + * Determine if a value is a Buffer + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a Buffer, otherwise false + */ +function isBuffer(val) { + return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor) + && isFunction(val.constructor.isBuffer) && val.constructor.isBuffer(val); +} + +/** + * Determine if a value is an ArrayBuffer + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is an ArrayBuffer, otherwise false + */ +const isArrayBuffer = kindOfTest('ArrayBuffer'); + + +/** + * Determine if a value is a view on an ArrayBuffer + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false + */ +function isArrayBufferView(val) { + let result; + if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { + result = ArrayBuffer.isView(val); + } else { + result = (val) && (val.buffer) && (isArrayBuffer(val.buffer)); + } + return result; +} + +/** + * Determine if a value is a String + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a String, otherwise false + */ +const isString = typeOfTest('string'); + +/** + * Determine if a value is a Function + * + * @param {*} val The value to test + * @returns {boolean} True if value is a Function, otherwise false + */ +const isFunction = typeOfTest('function'); + +/** + * Determine if a value is a Number + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a Number, otherwise false + */ +const isNumber = typeOfTest('number'); + +/** + * Determine if a value is an Object + * + * @param {*} thing The value to test + * + * @returns {boolean} True if value is an Object, otherwise false + */ +const isObject = (thing) => thing !== null && typeof thing === 'object'; + +/** + * Determine if a value is a Boolean + * + * @param {*} thing The value to test + * @returns {boolean} True if value is a Boolean, otherwise false + */ +const isBoolean = thing => thing === true || thing === false; + +/** + * Determine if a value is a plain Object + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a plain Object, otherwise false + */ +const isPlainObject = (val) => { + if (kindOf(val) !== 'object') { + return false; + } + + const prototype = getPrototypeOf(val); + return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in val) && !(Symbol.iterator in val); +}; + +/** + * Determine if a value is a Date + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a Date, otherwise false + */ +const isDate = kindOfTest('Date'); + +/** + * Determine if a value is a File + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a File, otherwise false + */ +const isFile = kindOfTest('File'); + +/** + * Determine if a value is a Blob + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a Blob, otherwise false + */ +const isBlob = kindOfTest('Blob'); + +/** + * Determine if a value is a FileList + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a File, otherwise false + */ +const isFileList = kindOfTest('FileList'); + +/** + * Determine if a value is a Stream + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a Stream, otherwise false + */ +const isStream = (val) => isObject(val) && isFunction(val.pipe); + +/** + * Determine if a value is a FormData + * + * @param {*} thing The value to test + * + * @returns {boolean} True if value is an FormData, otherwise false + */ +const isFormData = (thing) => { + let kind; + return thing && ( + (typeof FormData === 'function' && thing instanceof FormData) || ( + isFunction(thing.append) && ( + (kind = kindOf(thing)) === 'formdata' || + // detect form-data instance + (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]') + ) + ) + ) +}; + +/** + * Determine if a value is a URLSearchParams object + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a URLSearchParams object, otherwise false + */ +const isURLSearchParams = kindOfTest('URLSearchParams'); + +/** + * Trim excess whitespace off the beginning and end of a string + * + * @param {String} str The String to trim + * + * @returns {String} The String freed of excess whitespace + */ +const trim = (str) => str.trim ? + str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + +/** + * Iterate over an Array or an Object invoking a function for each item. + * + * If `obj` is an Array callback will be called passing + * the value, index, and complete array for each item. + * + * If 'obj' is an Object callback will be called passing + * the value, key, and complete object for each property. + * + * @param {Object|Array} obj The object to iterate + * @param {Function} fn The callback to invoke for each item + * + * @param {Boolean} [allOwnKeys = false] + * @returns {any} + */ +function forEach(obj, fn, {allOwnKeys = false} = {}) { + // Don't bother if no value provided + if (obj === null || typeof obj === 'undefined') { + return; + } + + let i; + let l; + + // Force an array if not already something iterable + if (typeof obj !== 'object') { + /*eslint no-param-reassign:0*/ + obj = [obj]; + } + + if (isArray(obj)) { + // Iterate over array values + for (i = 0, l = obj.length; i < l; i++) { + fn.call(null, obj[i], i, obj); + } + } else { + // Iterate over object keys + const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj); + const len = keys.length; + let key; + + for (i = 0; i < len; i++) { + key = keys[i]; + fn.call(null, obj[key], key, obj); + } + } +} + +function findKey(obj, key) { + key = key.toLowerCase(); + const keys = Object.keys(obj); + let i = keys.length; + let _key; + while (i-- > 0) { + _key = keys[i]; + if (key === _key.toLowerCase()) { + return _key; + } + } + return null; +} + +const _global = (() => { + /*eslint no-undef:0*/ + if (typeof globalThis !== "undefined") return globalThis; + return typeof self !== "undefined" ? self : (typeof window !== 'undefined' ? window : __webpack_require__.g) +})(); + +const isContextDefined = (context) => !isUndefined(context) && context !== _global; + +/** + * Accepts varargs expecting each argument to be an object, then + * immutably merges the properties of each object and returns result. + * + * When multiple objects contain the same key the later object in + * the arguments list will take precedence. + * + * Example: + * + * ```js + * var result = merge({foo: 123}, {foo: 456}); + * console.log(result.foo); // outputs 456 + * ``` + * + * @param {Object} obj1 Object to merge + * + * @returns {Object} Result of all merge properties + */ +function merge(/* obj1, obj2, obj3, ... */) { + const {caseless} = isContextDefined(this) && this || {}; + const result = {}; + const assignValue = (val, key) => { + const targetKey = caseless && findKey(result, key) || key; + if (isPlainObject(result[targetKey]) && isPlainObject(val)) { + result[targetKey] = merge(result[targetKey], val); + } else if (isPlainObject(val)) { + result[targetKey] = merge({}, val); + } else if (isArray(val)) { + result[targetKey] = val.slice(); + } else { + result[targetKey] = val; + } + }; + + for (let i = 0, l = arguments.length; i < l; i++) { + arguments[i] && forEach(arguments[i], assignValue); + } + return result; +} + +/** + * Extends object a by mutably adding to it the properties of object b. + * + * @param {Object} a The object to be extended + * @param {Object} b The object to copy properties from + * @param {Object} thisArg The object to bind function to + * + * @param {Boolean} [allOwnKeys] + * @returns {Object} The resulting value of object a + */ +const extend = (a, b, thisArg, {allOwnKeys}= {}) => { + forEach(b, (val, key) => { + if (thisArg && isFunction(val)) { + a[key] = bind(val, thisArg); + } else { + a[key] = val; + } + }, {allOwnKeys}); + return a; +}; + +/** + * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + * + * @param {string} content with BOM + * + * @returns {string} content value without BOM + */ +const stripBOM = (content) => { + if (content.charCodeAt(0) === 0xFEFF) { + content = content.slice(1); + } + return content; +}; + +/** + * Inherit the prototype methods from one constructor into another + * @param {function} constructor + * @param {function} superConstructor + * @param {object} [props] + * @param {object} [descriptors] + * + * @returns {void} + */ +const inherits = (constructor, superConstructor, props, descriptors) => { + constructor.prototype = Object.create(superConstructor.prototype, descriptors); + constructor.prototype.constructor = constructor; + Object.defineProperty(constructor, 'super', { + value: superConstructor.prototype + }); + props && Object.assign(constructor.prototype, props); +}; + +/** + * Resolve object with deep prototype chain to a flat object + * @param {Object} sourceObj source object + * @param {Object} [destObj] + * @param {Function|Boolean} [filter] + * @param {Function} [propFilter] + * + * @returns {Object} + */ +const toFlatObject = (sourceObj, destObj, filter, propFilter) => { + let props; + let i; + let prop; + const merged = {}; + + destObj = destObj || {}; + // eslint-disable-next-line no-eq-null,eqeqeq + if (sourceObj == null) return destObj; + + do { + props = Object.getOwnPropertyNames(sourceObj); + i = props.length; + while (i-- > 0) { + prop = props[i]; + if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) { + destObj[prop] = sourceObj[prop]; + merged[prop] = true; + } + } + sourceObj = filter !== false && getPrototypeOf(sourceObj); + } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype); + + return destObj; +}; + +/** + * Determines whether a string ends with the characters of a specified string + * + * @param {String} str + * @param {String} searchString + * @param {Number} [position= 0] + * + * @returns {boolean} + */ +const endsWith = (str, searchString, position) => { + str = String(str); + if (position === undefined || position > str.length) { + position = str.length; + } + position -= searchString.length; + const lastIndex = str.indexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; +}; + + +/** + * Returns new array from array like object or null if failed + * + * @param {*} [thing] + * + * @returns {?Array} + */ +const toArray = (thing) => { + if (!thing) return null; + if (isArray(thing)) return thing; + let i = thing.length; + if (!isNumber(i)) return null; + const arr = new Array(i); + while (i-- > 0) { + arr[i] = thing[i]; + } + return arr; +}; + +/** + * Checking if the Uint8Array exists and if it does, it returns a function that checks if the + * thing passed in is an instance of Uint8Array + * + * @param {TypedArray} + * + * @returns {Array} + */ +// eslint-disable-next-line func-names +const isTypedArray = (TypedArray => { + // eslint-disable-next-line func-names + return thing => { + return TypedArray && thing instanceof TypedArray; + }; +})(typeof Uint8Array !== 'undefined' && getPrototypeOf(Uint8Array)); + +/** + * For each entry in the object, call the function with the key and value. + * + * @param {Object} obj - The object to iterate over. + * @param {Function} fn - The function to call for each entry. + * + * @returns {void} + */ +const forEachEntry = (obj, fn) => { + const generator = obj && obj[Symbol.iterator]; + + const iterator = generator.call(obj); + + let result; + + while ((result = iterator.next()) && !result.done) { + const pair = result.value; + fn.call(obj, pair[0], pair[1]); + } +}; + +/** + * It takes a regular expression and a string, and returns an array of all the matches + * + * @param {string} regExp - The regular expression to match against. + * @param {string} str - The string to search. + * + * @returns {Array} + */ +const matchAll = (regExp, str) => { + let matches; + const arr = []; + + while ((matches = regExp.exec(str)) !== null) { + arr.push(matches); + } + + return arr; +}; + +/* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */ +const isHTMLForm = kindOfTest('HTMLFormElement'); + +const toCamelCase = str => { + return str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g, + function replacer(m, p1, p2) { + return p1.toUpperCase() + p2; + } + ); +}; + +/* Creating a function that will check if an object has a property. */ +const hasOwnProperty = (({hasOwnProperty}) => (obj, prop) => hasOwnProperty.call(obj, prop))(Object.prototype); + +/** + * Determine if a value is a RegExp object + * + * @param {*} val The value to test + * + * @returns {boolean} True if value is a RegExp object, otherwise false + */ +const isRegExp = kindOfTest('RegExp'); + +const reduceDescriptors = (obj, reducer) => { + const descriptors = Object.getOwnPropertyDescriptors(obj); + const reducedDescriptors = {}; + + forEach(descriptors, (descriptor, name) => { + let ret; + if ((ret = reducer(descriptor, name, obj)) !== false) { + reducedDescriptors[name] = ret || descriptor; + } + }); + + Object.defineProperties(obj, reducedDescriptors); +}; + +/** + * Makes all methods read-only + * @param {Object} obj + */ + +const freezeMethods = (obj) => { + reduceDescriptors(obj, (descriptor, name) => { + // skip restricted props in strict mode + if (isFunction(obj) && ['arguments', 'caller', 'callee'].indexOf(name) !== -1) { + return false; + } + + const value = obj[name]; + + if (!isFunction(value)) return; + + descriptor.enumerable = false; + + if ('writable' in descriptor) { + descriptor.writable = false; + return; + } + + if (!descriptor.set) { + descriptor.set = () => { + throw Error('Can not rewrite read-only method \'' + name + '\''); + }; + } + }); +}; + +const toObjectSet = (arrayOrString, delimiter) => { + const obj = {}; + + const define = (arr) => { + arr.forEach(value => { + obj[value] = true; + }); + }; + + isArray(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter)); + + return obj; +}; + +const noop = () => {}; + +const toFiniteNumber = (value, defaultValue) => { + value = +value; + return Number.isFinite(value) ? value : defaultValue; +}; + +const ALPHA = 'abcdefghijklmnopqrstuvwxyz'; + +const DIGIT = '0123456789'; + +const ALPHABET = { + DIGIT, + ALPHA, + ALPHA_DIGIT: ALPHA + ALPHA.toUpperCase() + DIGIT +}; + +const generateString = (size = 16, alphabet = ALPHABET.ALPHA_DIGIT) => { + let str = ''; + const {length} = alphabet; + while (size--) { + str += alphabet[Math.random() * length|0]; + } + + return str; +}; + +/** + * If the thing is a FormData object, return true, otherwise return false. + * + * @param {unknown} thing - The thing to check. + * + * @returns {boolean} + */ +function isSpecCompliantForm(thing) { + return !!(thing && isFunction(thing.append) && thing[Symbol.toStringTag] === 'FormData' && thing[Symbol.iterator]); +} + +const toJSONObject = (obj) => { + const stack = new Array(10); + + const visit = (source, i) => { + + if (isObject(source)) { + if (stack.indexOf(source) >= 0) { + return; + } + + if(!('toJSON' in source)) { + stack[i] = source; + const target = isArray(source) ? [] : {}; + + forEach(source, (value, key) => { + const reducedValue = visit(value, i + 1); + !isUndefined(reducedValue) && (target[key] = reducedValue); + }); + + stack[i] = undefined; + + return target; + } + } + + return source; + }; + + return visit(obj, 0); +}; + +const isAsyncFn = kindOfTest('AsyncFunction'); + +const isThenable = (thing) => + thing && (isObject(thing) || isFunction(thing)) && isFunction(thing.then) && isFunction(thing.catch); + +var utils$1 = { + isArray, + isArrayBuffer, + isBuffer, + isFormData, + isArrayBufferView, + isString, + isNumber, + isBoolean, + isObject, + isPlainObject, + isUndefined, + isDate, + isFile, + isBlob, + isRegExp, + isFunction, + isStream, + isURLSearchParams, + isTypedArray, + isFileList, + forEach, + merge, + extend, + trim, + stripBOM, + inherits, + toFlatObject, + kindOf, + kindOfTest, + endsWith, + toArray, + forEachEntry, + matchAll, + isHTMLForm, + hasOwnProperty, + hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection + reduceDescriptors, + freezeMethods, + toObjectSet, + toCamelCase, + noop, + toFiniteNumber, + findKey, + global: _global, + isContextDefined, + ALPHABET, + generateString, + isSpecCompliantForm, + toJSONObject, + isAsyncFn, + isThenable +}; + +/** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [config] The config. + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * + * @returns {Error} The created error. + */ +function AxiosError(message, code, config, request, response) { + Error.call(this); + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } else { + this.stack = (new Error()).stack; + } + + this.message = message; + this.name = 'AxiosError'; + code && (this.code = code); + config && (this.config = config); + request && (this.request = request); + response && (this.response = response); +} + +utils$1.inherits(AxiosError, Error, { + toJSON: function toJSON() { + return { + // Standard + message: this.message, + name: this.name, + // Microsoft + description: this.description, + number: this.number, + // Mozilla + fileName: this.fileName, + lineNumber: this.lineNumber, + columnNumber: this.columnNumber, + stack: this.stack, + // Axios + config: utils$1.toJSONObject(this.config), + code: this.code, + status: this.response && this.response.status ? this.response.status : null + }; + } +}); + +const prototype$1 = AxiosError.prototype; +const descriptors = {}; + +[ + 'ERR_BAD_OPTION_VALUE', + 'ERR_BAD_OPTION', + 'ECONNABORTED', + 'ETIMEDOUT', + 'ERR_NETWORK', + 'ERR_FR_TOO_MANY_REDIRECTS', + 'ERR_DEPRECATED', + 'ERR_BAD_RESPONSE', + 'ERR_BAD_REQUEST', + 'ERR_CANCELED', + 'ERR_NOT_SUPPORT', + 'ERR_INVALID_URL' +// eslint-disable-next-line func-names +].forEach(code => { + descriptors[code] = {value: code}; +}); + +Object.defineProperties(AxiosError, descriptors); +Object.defineProperty(prototype$1, 'isAxiosError', {value: true}); + +// eslint-disable-next-line func-names +AxiosError.from = (error, code, config, request, response, customProps) => { + const axiosError = Object.create(prototype$1); + + utils$1.toFlatObject(error, axiosError, function filter(obj) { + return obj !== Error.prototype; + }, prop => { + return prop !== 'isAxiosError'; + }); + + AxiosError.call(axiosError, error.message, code, config, request, response); + + axiosError.cause = error; + + axiosError.name = error.name; + + customProps && Object.assign(axiosError, customProps); + + return axiosError; +}; + +// eslint-disable-next-line strict +var httpAdapter = null; + +/** + * Determines if the given thing is a array or js object. + * + * @param {string} thing - The object or array to be visited. + * + * @returns {boolean} + */ +function isVisitable(thing) { + return utils$1.isPlainObject(thing) || utils$1.isArray(thing); +} + +/** + * It removes the brackets from the end of a string + * + * @param {string} key - The key of the parameter. + * + * @returns {string} the key without the brackets. + */ +function removeBrackets(key) { + return utils$1.endsWith(key, '[]') ? key.slice(0, -2) : key; +} + +/** + * It takes a path, a key, and a boolean, and returns a string + * + * @param {string} path - The path to the current key. + * @param {string} key - The key of the current object being iterated over. + * @param {string} dots - If true, the key will be rendered with dots instead of brackets. + * + * @returns {string} The path to the current key. + */ +function renderKey(path, key, dots) { + if (!path) return key; + return path.concat(key).map(function each(token, i) { + // eslint-disable-next-line no-param-reassign + token = removeBrackets(token); + return !dots && i ? '[' + token + ']' : token; + }).join(dots ? '.' : ''); +} + +/** + * If the array is an array and none of its elements are visitable, then it's a flat array. + * + * @param {Array} arr - The array to check + * + * @returns {boolean} + */ +function isFlatArray(arr) { + return utils$1.isArray(arr) && !arr.some(isVisitable); +} + +const predicates = utils$1.toFlatObject(utils$1, {}, null, function filter(prop) { + return /^is[A-Z]/.test(prop); +}); + +/** + * Convert a data object to FormData + * + * @param {Object} obj + * @param {?Object} [formData] + * @param {?Object} [options] + * @param {Function} [options.visitor] + * @param {Boolean} [options.metaTokens = true] + * @param {Boolean} [options.dots = false] + * @param {?Boolean} [options.indexes = false] + * + * @returns {Object} + **/ + +/** + * It converts an object into a FormData object + * + * @param {Object} obj - The object to convert to form data. + * @param {string} formData - The FormData object to append to. + * @param {Object} options + * + * @returns + */ +function toFormData(obj, formData, options) { + if (!utils$1.isObject(obj)) { + throw new TypeError('target must be an object'); + } + + // eslint-disable-next-line no-param-reassign + formData = formData || new (FormData)(); + + // eslint-disable-next-line no-param-reassign + options = utils$1.toFlatObject(options, { + metaTokens: true, + dots: false, + indexes: false + }, false, function defined(option, source) { + // eslint-disable-next-line no-eq-null,eqeqeq + return !utils$1.isUndefined(source[option]); + }); + + const metaTokens = options.metaTokens; + // eslint-disable-next-line no-use-before-define + const visitor = options.visitor || defaultVisitor; + const dots = options.dots; + const indexes = options.indexes; + const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob; + const useBlob = _Blob && utils$1.isSpecCompliantForm(formData); + + if (!utils$1.isFunction(visitor)) { + throw new TypeError('visitor must be a function'); + } + + function convertValue(value) { + if (value === null) return ''; + + if (utils$1.isDate(value)) { + return value.toISOString(); + } + + if (!useBlob && utils$1.isBlob(value)) { + throw new AxiosError('Blob is not supported. Use a Buffer instead.'); + } + + if (utils$1.isArrayBuffer(value) || utils$1.isTypedArray(value)) { + return useBlob && typeof Blob === 'function' ? new Blob([value]) : buffer__WEBPACK_IMPORTED_MODULE_0__.Buffer.from(value); + } + + return value; + } + + /** + * Default visitor. + * + * @param {*} value + * @param {String|Number} key + * @param {Array} path + * @this {FormData} + * + * @returns {boolean} return true to visit the each prop of the value recursively + */ + function defaultVisitor(value, key, path) { + let arr = value; + + if (value && !path && typeof value === 'object') { + if (utils$1.endsWith(key, '{}')) { + // eslint-disable-next-line no-param-reassign + key = metaTokens ? key : key.slice(0, -2); + // eslint-disable-next-line no-param-reassign + value = JSON.stringify(value); + } else if ( + (utils$1.isArray(value) && isFlatArray(value)) || + ((utils$1.isFileList(value) || utils$1.endsWith(key, '[]')) && (arr = utils$1.toArray(value)) + )) { + // eslint-disable-next-line no-param-reassign + key = removeBrackets(key); + + arr.forEach(function each(el, index) { + !(utils$1.isUndefined(el) || el === null) && formData.append( + // eslint-disable-next-line no-nested-ternary + indexes === true ? renderKey([key], index, dots) : (indexes === null ? key : key + '[]'), + convertValue(el) + ); + }); + return false; + } + } + + if (isVisitable(value)) { + return true; + } + + formData.append(renderKey(path, key, dots), convertValue(value)); + + return false; + } + + const stack = []; + + const exposedHelpers = Object.assign(predicates, { + defaultVisitor, + convertValue, + isVisitable + }); + + function build(value, path) { + if (utils$1.isUndefined(value)) return; + + if (stack.indexOf(value) !== -1) { + throw Error('Circular reference detected in ' + path.join('.')); + } + + stack.push(value); + + utils$1.forEach(value, function each(el, key) { + const result = !(utils$1.isUndefined(el) || el === null) && visitor.call( + formData, el, utils$1.isString(key) ? key.trim() : key, path, exposedHelpers + ); + + if (result === true) { + build(el, path ? path.concat(key) : [key]); + } + }); + + stack.pop(); + } + + if (!utils$1.isObject(obj)) { + throw new TypeError('data must be an object'); + } + + build(obj); + + return formData; +} + +/** + * It encodes a string by replacing all characters that are not in the unreserved set with + * their percent-encoded equivalents + * + * @param {string} str - The string to encode. + * + * @returns {string} The encoded string. + */ +function encode$1(str) { + const charMap = { + '!': '%21', + "'": '%27', + '(': '%28', + ')': '%29', + '~': '%7E', + '%20': '+', + '%00': '\x00' + }; + return encodeURIComponent(str).replace(/[!'()~]|%20|%00/g, function replacer(match) { + return charMap[match]; + }); +} + +/** + * It takes a params object and converts it to a FormData object + * + * @param {Object} params - The parameters to be converted to a FormData object. + * @param {Object} options - The options object passed to the Axios constructor. + * + * @returns {void} + */ +function AxiosURLSearchParams(params, options) { + this._pairs = []; + + params && toFormData(params, this, options); +} + +const prototype = AxiosURLSearchParams.prototype; + +prototype.append = function append(name, value) { + this._pairs.push([name, value]); +}; + +prototype.toString = function toString(encoder) { + const _encode = encoder ? function(value) { + return encoder.call(this, value, encode$1); + } : encode$1; + + return this._pairs.map(function each(pair) { + return _encode(pair[0]) + '=' + _encode(pair[1]); + }, '').join('&'); +}; + +/** + * It replaces all instances of the characters `:`, `$`, `,`, `+`, `[`, and `]` with their + * URI encoded counterparts + * + * @param {string} val The value to be encoded. + * + * @returns {string} The encoded value. + */ +function encode(val) { + return encodeURIComponent(val). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%20/g, '+'). + replace(/%5B/gi, '['). + replace(/%5D/gi, ']'); +} + +/** + * Build a URL by appending params to the end + * + * @param {string} url The base of the url (e.g., http://www.google.com) + * @param {object} [params] The params to be appended + * @param {?object} options + * + * @returns {string} The formatted url + */ +function buildURL(url, params, options) { + /*eslint no-param-reassign:0*/ + if (!params) { + return url; + } + + const _encode = options && options.encode || encode; + + const serializeFn = options && options.serialize; + + let serializedParams; + + if (serializeFn) { + serializedParams = serializeFn(params, options); + } else { + serializedParams = utils$1.isURLSearchParams(params) ? + params.toString() : + new AxiosURLSearchParams(params, options).toString(_encode); + } + + if (serializedParams) { + const hashmarkIndex = url.indexOf("#"); + + if (hashmarkIndex !== -1) { + url = url.slice(0, hashmarkIndex); + } + url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; + } + + return url; +} + +class InterceptorManager { + constructor() { + this.handlers = []; + } + + /** + * Add a new interceptor to the stack + * + * @param {Function} fulfilled The function to handle `then` for a `Promise` + * @param {Function} rejected The function to handle `reject` for a `Promise` + * + * @return {Number} An ID used to remove interceptor later + */ + use(fulfilled, rejected, options) { + this.handlers.push({ + fulfilled, + rejected, + synchronous: options ? options.synchronous : false, + runWhen: options ? options.runWhen : null + }); + return this.handlers.length - 1; + } + + /** + * Remove an interceptor from the stack + * + * @param {Number} id The ID that was returned by `use` + * + * @returns {Boolean} `true` if the interceptor was removed, `false` otherwise + */ + eject(id) { + if (this.handlers[id]) { + this.handlers[id] = null; + } + } + + /** + * Clear all interceptors from the stack + * + * @returns {void} + */ + clear() { + if (this.handlers) { + this.handlers = []; + } + } + + /** + * Iterate over all the registered interceptors + * + * This method is particularly useful for skipping over any + * interceptors that may have become `null` calling `eject`. + * + * @param {Function} fn The function to call for each interceptor + * + * @returns {void} + */ + forEach(fn) { + utils$1.forEach(this.handlers, function forEachHandler(h) { + if (h !== null) { + fn(h); + } + }); + } +} + +var transitionalDefaults = { + silentJSONParsing: true, + forcedJSONParsing: true, + clarifyTimeoutError: false +}; + +var URLSearchParams$1 = typeof URLSearchParams !== 'undefined' ? URLSearchParams : AxiosURLSearchParams; + +var FormData$1 = typeof FormData !== 'undefined' ? FormData : null; + +var Blob$1 = typeof Blob !== 'undefined' ? Blob : null; + +var platform$1 = { + isBrowser: true, + classes: { + URLSearchParams: URLSearchParams$1, + FormData: FormData$1, + Blob: Blob$1 + }, + protocols: ['http', 'https', 'file', 'blob', 'url', 'data'] +}; + +const hasBrowserEnv = typeof window !== 'undefined' && typeof document !== 'undefined'; + +/** + * Determine if we're running in a standard browser environment + * + * This allows axios to run in a web worker, and react-native. + * Both environments support XMLHttpRequest, but not fully standard globals. + * + * web workers: + * typeof window -> undefined + * typeof document -> undefined + * + * react-native: + * navigator.product -> 'ReactNative' + * nativescript + * navigator.product -> 'NativeScript' or 'NS' + * + * @returns {boolean} + */ +const hasStandardBrowserEnv = ( + (product) => { + return hasBrowserEnv && ['ReactNative', 'NativeScript', 'NS'].indexOf(product) < 0 + })(typeof navigator !== 'undefined' && navigator.product); + +/** + * Determine if we're running in a standard browser webWorker environment + * + * Although the `isStandardBrowserEnv` method indicates that + * `allows axios to run in a web worker`, the WebWorker will still be + * filtered out due to its judgment standard + * `typeof window !== 'undefined' && typeof document !== 'undefined'`. + * This leads to a problem when axios post `FormData` in webWorker + */ +const hasStandardBrowserWebWorkerEnv = (() => { + return ( + typeof WorkerGlobalScope !== 'undefined' && + // eslint-disable-next-line no-undef + self instanceof WorkerGlobalScope && + typeof self.importScripts === 'function' + ); +})(); + +var utils = /*#__PURE__*/Object.freeze({ + __proto__: null, + hasBrowserEnv: hasBrowserEnv, + hasStandardBrowserEnv: hasStandardBrowserEnv, + hasStandardBrowserWebWorkerEnv: hasStandardBrowserWebWorkerEnv +}); + +var platform = { + ...utils, + ...platform$1 +}; + +function toURLEncodedForm(data, options) { + return toFormData(data, new platform.classes.URLSearchParams(), Object.assign({ + visitor: function(value, key, path, helpers) { + if (platform.isNode && utils$1.isBuffer(value)) { + this.append(key, value.toString('base64')); + return false; + } + + return helpers.defaultVisitor.apply(this, arguments); + } + }, options)); +} + +/** + * It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z'] + * + * @param {string} name - The name of the property to get. + * + * @returns An array of strings. + */ +function parsePropPath(name) { + // foo[x][y][z] + // foo.x.y.z + // foo-x-y-z + // foo x y z + return utils$1.matchAll(/\w+|\[(\w*)]/g, name).map(match => { + return match[0] === '[]' ? '' : match[1] || match[0]; + }); +} + +/** + * Convert an array to an object. + * + * @param {Array} arr - The array to convert to an object. + * + * @returns An object with the same keys and values as the array. + */ +function arrayToObject(arr) { + const obj = {}; + const keys = Object.keys(arr); + let i; + const len = keys.length; + let key; + for (i = 0; i < len; i++) { + key = keys[i]; + obj[key] = arr[key]; + } + return obj; +} + +/** + * It takes a FormData object and returns a JavaScript object + * + * @param {string} formData The FormData object to convert to JSON. + * + * @returns {Object | null} The converted object. + */ +function formDataToJSON(formData) { + function buildPath(path, value, target, index) { + let name = path[index++]; + + if (name === '__proto__') return true; + + const isNumericKey = Number.isFinite(+name); + const isLast = index >= path.length; + name = !name && utils$1.isArray(target) ? target.length : name; + + if (isLast) { + if (utils$1.hasOwnProp(target, name)) { + target[name] = [target[name], value]; + } else { + target[name] = value; + } + + return !isNumericKey; + } + + if (!target[name] || !utils$1.isObject(target[name])) { + target[name] = []; + } + + const result = buildPath(path, value, target[name], index); + + if (result && utils$1.isArray(target[name])) { + target[name] = arrayToObject(target[name]); + } + + return !isNumericKey; + } + + if (utils$1.isFormData(formData) && utils$1.isFunction(formData.entries)) { + const obj = {}; + + utils$1.forEachEntry(formData, (name, value) => { + buildPath(parsePropPath(name), value, obj, 0); + }); + + return obj; + } + + return null; +} + +/** + * It takes a string, tries to parse it, and if it fails, it returns the stringified version + * of the input + * + * @param {any} rawValue - The value to be stringified. + * @param {Function} parser - A function that parses a string into a JavaScript object. + * @param {Function} encoder - A function that takes a value and returns a string. + * + * @returns {string} A stringified version of the rawValue. + */ +function stringifySafely(rawValue, parser, encoder) { + if (utils$1.isString(rawValue)) { + try { + (parser || JSON.parse)(rawValue); + return utils$1.trim(rawValue); + } catch (e) { + if (e.name !== 'SyntaxError') { + throw e; + } + } + } + + return (encoder || JSON.stringify)(rawValue); +} + +const defaults = { + + transitional: transitionalDefaults, + + adapter: ['xhr', 'http'], + + transformRequest: [function transformRequest(data, headers) { + const contentType = headers.getContentType() || ''; + const hasJSONContentType = contentType.indexOf('application/json') > -1; + const isObjectPayload = utils$1.isObject(data); + + if (isObjectPayload && utils$1.isHTMLForm(data)) { + data = new FormData(data); + } + + const isFormData = utils$1.isFormData(data); + + if (isFormData) { + return hasJSONContentType ? JSON.stringify(formDataToJSON(data)) : data; + } + + if (utils$1.isArrayBuffer(data) || + utils$1.isBuffer(data) || + utils$1.isStream(data) || + utils$1.isFile(data) || + utils$1.isBlob(data) + ) { + return data; + } + if (utils$1.isArrayBufferView(data)) { + return data.buffer; + } + if (utils$1.isURLSearchParams(data)) { + headers.setContentType('application/x-www-form-urlencoded;charset=utf-8', false); + return data.toString(); + } + + let isFileList; + + if (isObjectPayload) { + if (contentType.indexOf('application/x-www-form-urlencoded') > -1) { + return toURLEncodedForm(data, this.formSerializer).toString(); + } + + if ((isFileList = utils$1.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) { + const _FormData = this.env && this.env.FormData; + + return toFormData( + isFileList ? {'files[]': data} : data, + _FormData && new _FormData(), + this.formSerializer + ); + } + } + + if (isObjectPayload || hasJSONContentType ) { + headers.setContentType('application/json', false); + return stringifySafely(data); + } + + return data; + }], + + transformResponse: [function transformResponse(data) { + const transitional = this.transitional || defaults.transitional; + const forcedJSONParsing = transitional && transitional.forcedJSONParsing; + const JSONRequested = this.responseType === 'json'; + + if (data && utils$1.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) { + const silentJSONParsing = transitional && transitional.silentJSONParsing; + const strictJSONParsing = !silentJSONParsing && JSONRequested; + + try { + return JSON.parse(data); + } catch (e) { + if (strictJSONParsing) { + if (e.name === 'SyntaxError') { + throw AxiosError.from(e, AxiosError.ERR_BAD_RESPONSE, this, null, this.response); + } + throw e; + } + } + } + + return data; + }], + + /** + * A timeout in milliseconds to abort a request. If set to 0 (default) a + * timeout is not created. + */ + timeout: 0, + + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', + + maxContentLength: -1, + maxBodyLength: -1, + + env: { + FormData: platform.classes.FormData, + Blob: platform.classes.Blob + }, + + validateStatus: function validateStatus(status) { + return status >= 200 && status < 300; + }, + + headers: { + common: { + 'Accept': 'application/json, text/plain, */*', + 'Content-Type': undefined + } + } +}; + +utils$1.forEach(['delete', 'get', 'head', 'post', 'put', 'patch'], (method) => { + defaults.headers[method] = {}; +}); + +var defaults$1 = defaults; + +// RawAxiosHeaders whose duplicates are ignored by node +// c.f. https://nodejs.org/api/http.html#http_message_headers +const ignoreDuplicateOf = utils$1.toObjectSet([ + 'age', 'authorization', 'content-length', 'content-type', 'etag', + 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', + 'last-modified', 'location', 'max-forwards', 'proxy-authorization', + 'referer', 'retry-after', 'user-agent' +]); + +/** + * Parse headers into an object + * + * ``` + * Date: Wed, 27 Aug 2014 08:58:49 GMT + * Content-Type: application/json + * Connection: keep-alive + * Transfer-Encoding: chunked + * ``` + * + * @param {String} rawHeaders Headers needing to be parsed + * + * @returns {Object} Headers parsed into an object + */ +var parseHeaders = rawHeaders => { + const parsed = {}; + let key; + let val; + let i; + + rawHeaders && rawHeaders.split('\n').forEach(function parser(line) { + i = line.indexOf(':'); + key = line.substring(0, i).trim().toLowerCase(); + val = line.substring(i + 1).trim(); + + if (!key || (parsed[key] && ignoreDuplicateOf[key])) { + return; + } + + if (key === 'set-cookie') { + if (parsed[key]) { + parsed[key].push(val); + } else { + parsed[key] = [val]; + } + } else { + parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; + } + }); + + return parsed; +}; + +const $internals = Symbol('internals'); + +function normalizeHeader(header) { + return header && String(header).trim().toLowerCase(); +} + +function normalizeValue(value) { + if (value === false || value == null) { + return value; + } + + return utils$1.isArray(value) ? value.map(normalizeValue) : String(value); +} + +function parseTokens(str) { + const tokens = Object.create(null); + const tokensRE = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g; + let match; + + while ((match = tokensRE.exec(str))) { + tokens[match[1]] = match[2]; + } + + return tokens; +} + +const isValidHeaderName = (str) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str.trim()); + +function matchHeaderValue(context, value, header, filter, isHeaderNameFilter) { + if (utils$1.isFunction(filter)) { + return filter.call(this, value, header); + } + + if (isHeaderNameFilter) { + value = header; + } + + if (!utils$1.isString(value)) return; + + if (utils$1.isString(filter)) { + return value.indexOf(filter) !== -1; + } + + if (utils$1.isRegExp(filter)) { + return filter.test(value); + } +} + +function formatHeader(header) { + return header.trim() + .toLowerCase().replace(/([a-z\d])(\w*)/g, (w, char, str) => { + return char.toUpperCase() + str; + }); +} + +function buildAccessors(obj, header) { + const accessorName = utils$1.toCamelCase(' ' + header); + + ['get', 'set', 'has'].forEach(methodName => { + Object.defineProperty(obj, methodName + accessorName, { + value: function(arg1, arg2, arg3) { + return this[methodName].call(this, header, arg1, arg2, arg3); + }, + configurable: true + }); + }); +} + +class AxiosHeaders { + constructor(headers) { + headers && this.set(headers); + } + + set(header, valueOrRewrite, rewrite) { + const self = this; + + function setHeader(_value, _header, _rewrite) { + const lHeader = normalizeHeader(_header); + + if (!lHeader) { + throw new Error('header name must be a non-empty string'); + } + + const key = utils$1.findKey(self, lHeader); + + if(!key || self[key] === undefined || _rewrite === true || (_rewrite === undefined && self[key] !== false)) { + self[key || _header] = normalizeValue(_value); + } + } + + const setHeaders = (headers, _rewrite) => + utils$1.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite)); + + if (utils$1.isPlainObject(header) || header instanceof this.constructor) { + setHeaders(header, valueOrRewrite); + } else if(utils$1.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) { + setHeaders(parseHeaders(header), valueOrRewrite); + } else { + header != null && setHeader(valueOrRewrite, header, rewrite); + } + + return this; + } + + get(header, parser) { + header = normalizeHeader(header); + + if (header) { + const key = utils$1.findKey(this, header); + + if (key) { + const value = this[key]; + + if (!parser) { + return value; + } + + if (parser === true) { + return parseTokens(value); + } + + if (utils$1.isFunction(parser)) { + return parser.call(this, value, key); + } + + if (utils$1.isRegExp(parser)) { + return parser.exec(value); + } + + throw new TypeError('parser must be boolean|regexp|function'); + } + } + } + + has(header, matcher) { + header = normalizeHeader(header); + + if (header) { + const key = utils$1.findKey(this, header); + + return !!(key && this[key] !== undefined && (!matcher || matchHeaderValue(this, this[key], key, matcher))); + } + + return false; + } + + delete(header, matcher) { + const self = this; + let deleted = false; + + function deleteHeader(_header) { + _header = normalizeHeader(_header); + + if (_header) { + const key = utils$1.findKey(self, _header); + + if (key && (!matcher || matchHeaderValue(self, self[key], key, matcher))) { + delete self[key]; + + deleted = true; + } + } + } + + if (utils$1.isArray(header)) { + header.forEach(deleteHeader); + } else { + deleteHeader(header); + } + + return deleted; + } + + clear(matcher) { + const keys = Object.keys(this); + let i = keys.length; + let deleted = false; + + while (i--) { + const key = keys[i]; + if(!matcher || matchHeaderValue(this, this[key], key, matcher, true)) { + delete this[key]; + deleted = true; + } + } + + return deleted; + } + + normalize(format) { + const self = this; + const headers = {}; + + utils$1.forEach(this, (value, header) => { + const key = utils$1.findKey(headers, header); + + if (key) { + self[key] = normalizeValue(value); + delete self[header]; + return; + } + + const normalized = format ? formatHeader(header) : String(header).trim(); + + if (normalized !== header) { + delete self[header]; + } + + self[normalized] = normalizeValue(value); + + headers[normalized] = true; + }); + + return this; + } + + concat(...targets) { + return this.constructor.concat(this, ...targets); + } + + toJSON(asStrings) { + const obj = Object.create(null); + + utils$1.forEach(this, (value, header) => { + value != null && value !== false && (obj[header] = asStrings && utils$1.isArray(value) ? value.join(', ') : value); + }); + + return obj; + } + + [Symbol.iterator]() { + return Object.entries(this.toJSON())[Symbol.iterator](); + } + + toString() { + return Object.entries(this.toJSON()).map(([header, value]) => header + ': ' + value).join('\n'); + } + + get [Symbol.toStringTag]() { + return 'AxiosHeaders'; + } + + static from(thing) { + return thing instanceof this ? thing : new this(thing); + } + + static concat(first, ...targets) { + const computed = new this(first); + + targets.forEach((target) => computed.set(target)); + + return computed; + } + + static accessor(header) { + const internals = this[$internals] = (this[$internals] = { + accessors: {} + }); + + const accessors = internals.accessors; + const prototype = this.prototype; + + function defineAccessor(_header) { + const lHeader = normalizeHeader(_header); + + if (!accessors[lHeader]) { + buildAccessors(prototype, _header); + accessors[lHeader] = true; + } + } + + utils$1.isArray(header) ? header.forEach(defineAccessor) : defineAccessor(header); + + return this; + } +} + +AxiosHeaders.accessor(['Content-Type', 'Content-Length', 'Accept', 'Accept-Encoding', 'User-Agent', 'Authorization']); + +// reserved names hotfix +utils$1.reduceDescriptors(AxiosHeaders.prototype, ({value}, key) => { + let mapped = key[0].toUpperCase() + key.slice(1); // map `set` => `Set` + return { + get: () => value, + set(headerValue) { + this[mapped] = headerValue; + } + } +}); + +utils$1.freezeMethods(AxiosHeaders); + +var AxiosHeaders$1 = AxiosHeaders; + +/** + * Transform the data for a request or a response + * + * @param {Array|Function} fns A single function or Array of functions + * @param {?Object} response The response object + * + * @returns {*} The resulting transformed data + */ +function transformData(fns, response) { + const config = this || defaults$1; + const context = response || config; + const headers = AxiosHeaders$1.from(context.headers); + let data = context.data; + + utils$1.forEach(fns, function transform(fn) { + data = fn.call(config, data, headers.normalize(), response ? response.status : undefined); + }); + + headers.normalize(); + + return data; +} + +function isCancel(value) { + return !!(value && value.__CANCEL__); +} + +/** + * A `CanceledError` is an object that is thrown when an operation is canceled. + * + * @param {string=} message The message. + * @param {Object=} config The config. + * @param {Object=} request The request. + * + * @returns {CanceledError} The created error. + */ +function CanceledError(message, config, request) { + // eslint-disable-next-line no-eq-null,eqeqeq + AxiosError.call(this, message == null ? 'canceled' : message, AxiosError.ERR_CANCELED, config, request); + this.name = 'CanceledError'; +} + +utils$1.inherits(CanceledError, AxiosError, { + __CANCEL__: true +}); + +/** + * Resolve or reject a Promise based on response status. + * + * @param {Function} resolve A function that resolves the promise. + * @param {Function} reject A function that rejects the promise. + * @param {object} response The response. + * + * @returns {object} The response. + */ +function settle(resolve, reject, response) { + const validateStatus = response.config.validateStatus; + if (!response.status || !validateStatus || validateStatus(response.status)) { + resolve(response); + } else { + reject(new AxiosError( + 'Request failed with status code ' + response.status, + [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4], + response.config, + response.request, + response + )); + } +} + +var cookies = platform.hasStandardBrowserEnv ? + + // Standard browser envs support document.cookie + { + write(name, value, expires, path, domain, secure) { + const cookie = [name + '=' + encodeURIComponent(value)]; + + utils$1.isNumber(expires) && cookie.push('expires=' + new Date(expires).toGMTString()); + + utils$1.isString(path) && cookie.push('path=' + path); + + utils$1.isString(domain) && cookie.push('domain=' + domain); + + secure === true && cookie.push('secure'); + + document.cookie = cookie.join('; '); + }, + + read(name) { + const match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); + return (match ? decodeURIComponent(match[3]) : null); + }, + + remove(name) { + this.write(name, '', Date.now() - 86400000); + } + } + + : + + // Non-standard browser env (web workers, react-native) lack needed support. + { + write() {}, + read() { + return null; + }, + remove() {} + }; + +/** + * Determines whether the specified URL is absolute + * + * @param {string} url The URL to test + * + * @returns {boolean} True if the specified URL is absolute, otherwise false + */ +function isAbsoluteURL(url) { + // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). + // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed + // by any combination of letters, digits, plus, period, or hyphen. + return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url); +} + +/** + * Creates a new URL by combining the specified URLs + * + * @param {string} baseURL The base URL + * @param {string} relativeURL The relative URL + * + * @returns {string} The combined URL + */ +function combineURLs(baseURL, relativeURL) { + return relativeURL + ? baseURL.replace(/\/?\/$/, '') + '/' + relativeURL.replace(/^\/+/, '') + : baseURL; +} + +/** + * Creates a new URL by combining the baseURL with the requestedURL, + * only when the requestedURL is not already an absolute URL. + * If the requestURL is absolute, this function returns the requestedURL untouched. + * + * @param {string} baseURL The base URL + * @param {string} requestedURL Absolute or relative URL to combine + * + * @returns {string} The combined full path + */ +function buildFullPath(baseURL, requestedURL) { + if (baseURL && !isAbsoluteURL(requestedURL)) { + return combineURLs(baseURL, requestedURL); + } + return requestedURL; +} + +var isURLSameOrigin = platform.hasStandardBrowserEnv ? + +// Standard browser envs have full support of the APIs needed to test +// whether the request URL is of the same origin as current location. + (function standardBrowserEnv() { + const msie = /(msie|trident)/i.test(navigator.userAgent); + const urlParsingNode = document.createElement('a'); + let originURL; + + /** + * Parse a URL to discover its components + * + * @param {String} url The URL to be parsed + * @returns {Object} + */ + function resolveURL(url) { + let href = url; + + if (msie) { + // IE needs attribute set twice to normalize properties + urlParsingNode.setAttribute('href', href); + href = urlParsingNode.href; + } + + urlParsingNode.setAttribute('href', href); + + // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils + return { + href: urlParsingNode.href, + protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', + host: urlParsingNode.host, + search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', + hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', + hostname: urlParsingNode.hostname, + port: urlParsingNode.port, + pathname: (urlParsingNode.pathname.charAt(0) === '/') ? + urlParsingNode.pathname : + '/' + urlParsingNode.pathname + }; + } + + originURL = resolveURL(window.location.href); + + /** + * Determine if a URL shares the same origin as the current location + * + * @param {String} requestURL The URL to test + * @returns {boolean} True if URL shares the same origin, otherwise false + */ + return function isURLSameOrigin(requestURL) { + const parsed = (utils$1.isString(requestURL)) ? resolveURL(requestURL) : requestURL; + return (parsed.protocol === originURL.protocol && + parsed.host === originURL.host); + }; + })() : + + // Non standard browser envs (web workers, react-native) lack needed support. + (function nonStandardBrowserEnv() { + return function isURLSameOrigin() { + return true; + }; + })(); + +function parseProtocol(url) { + const match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url); + return match && match[1] || ''; +} + +/** + * Calculate data maxRate + * @param {Number} [samplesCount= 10] + * @param {Number} [min= 1000] + * @returns {Function} + */ +function speedometer(samplesCount, min) { + samplesCount = samplesCount || 10; + const bytes = new Array(samplesCount); + const timestamps = new Array(samplesCount); + let head = 0; + let tail = 0; + let firstSampleTS; + + min = min !== undefined ? min : 1000; + + return function push(chunkLength) { + const now = Date.now(); + + const startedAt = timestamps[tail]; + + if (!firstSampleTS) { + firstSampleTS = now; + } + + bytes[head] = chunkLength; + timestamps[head] = now; + + let i = tail; + let bytesCount = 0; + + while (i !== head) { + bytesCount += bytes[i++]; + i = i % samplesCount; + } + + head = (head + 1) % samplesCount; + + if (head === tail) { + tail = (tail + 1) % samplesCount; + } + + if (now - firstSampleTS < min) { + return; + } + + const passed = startedAt && now - startedAt; + + return passed ? Math.round(bytesCount * 1000 / passed) : undefined; + }; +} + +function progressEventReducer(listener, isDownloadStream) { + let bytesNotified = 0; + const _speedometer = speedometer(50, 250); + + return e => { + const loaded = e.loaded; + const total = e.lengthComputable ? e.total : undefined; + const progressBytes = loaded - bytesNotified; + const rate = _speedometer(progressBytes); + const inRange = loaded <= total; + + bytesNotified = loaded; + + const data = { + loaded, + total, + progress: total ? (loaded / total) : undefined, + bytes: progressBytes, + rate: rate ? rate : undefined, + estimated: rate && total && inRange ? (total - loaded) / rate : undefined, + event: e + }; + + data[isDownloadStream ? 'download' : 'upload'] = true; + + listener(data); + }; +} + +const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined'; + +var xhrAdapter = isXHRAdapterSupported && function (config) { + return new Promise(function dispatchXhrRequest(resolve, reject) { + let requestData = config.data; + const requestHeaders = AxiosHeaders$1.from(config.headers).normalize(); + let {responseType, withXSRFToken} = config; + let onCanceled; + function done() { + if (config.cancelToken) { + config.cancelToken.unsubscribe(onCanceled); + } + + if (config.signal) { + config.signal.removeEventListener('abort', onCanceled); + } + } + + let contentType; + + if (utils$1.isFormData(requestData)) { + if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) { + requestHeaders.setContentType(false); // Let the browser set it + } else if ((contentType = requestHeaders.getContentType()) !== false) { + // fix semicolon duplication issue for ReactNative FormData implementation + const [type, ...tokens] = contentType ? contentType.split(';').map(token => token.trim()).filter(Boolean) : []; + requestHeaders.setContentType([type || 'multipart/form-data', ...tokens].join('; ')); + } + } + + let request = new XMLHttpRequest(); + + // HTTP basic authentication + if (config.auth) { + const username = config.auth.username || ''; + const password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : ''; + requestHeaders.set('Authorization', 'Basic ' + btoa(username + ':' + password)); + } + + const fullPath = buildFullPath(config.baseURL, config.url); + + request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true); + + // Set the request timeout in MS + request.timeout = config.timeout; + + function onloadend() { + if (!request) { + return; + } + // Prepare the response + const responseHeaders = AxiosHeaders$1.from( + 'getAllResponseHeaders' in request && request.getAllResponseHeaders() + ); + const responseData = !responseType || responseType === 'text' || responseType === 'json' ? + request.responseText : request.response; + const response = { + data: responseData, + status: request.status, + statusText: request.statusText, + headers: responseHeaders, + config, + request + }; + + settle(function _resolve(value) { + resolve(value); + done(); + }, function _reject(err) { + reject(err); + done(); + }, response); + + // Clean up request + request = null; + } + + if ('onloadend' in request) { + // Use onloadend if available + request.onloadend = onloadend; + } else { + // Listen for ready state to emulate onloadend + request.onreadystatechange = function handleLoad() { + if (!request || request.readyState !== 4) { + return; + } + + // The request errored out and we didn't get a response, this will be + // handled by onerror instead + // With one exception: request that using file: protocol, most browsers + // will return status as 0 even though it's a successful request + if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { + return; + } + // readystate handler is calling before onerror or ontimeout handlers, + // so we should call onloadend on the next 'tick' + setTimeout(onloadend); + }; + } + + // Handle browser request cancellation (as opposed to a manual cancellation) + request.onabort = function handleAbort() { + if (!request) { + return; + } + + reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request)); + + // Clean up request + request = null; + }; + + // Handle low level network errors + request.onerror = function handleError() { + // Real errors are hidden from us by the browser + // onerror should only fire if it's a network error + reject(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request)); + + // Clean up request + request = null; + }; + + // Handle timeout + request.ontimeout = function handleTimeout() { + let timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded'; + const transitional = config.transitional || transitionalDefaults; + if (config.timeoutErrorMessage) { + timeoutErrorMessage = config.timeoutErrorMessage; + } + reject(new AxiosError( + timeoutErrorMessage, + transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, + config, + request)); + + // Clean up request + request = null; + }; + + // Add xsrf header + // This is only done if running in a standard browser environment. + // Specifically not if we're in a web worker, or react-native. + if(platform.hasStandardBrowserEnv) { + withXSRFToken && utils$1.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(config)); + + if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(fullPath))) { + // Add xsrf header + const xsrfValue = config.xsrfHeaderName && config.xsrfCookieName && cookies.read(config.xsrfCookieName); + + if (xsrfValue) { + requestHeaders.set(config.xsrfHeaderName, xsrfValue); + } + } + } + + // Remove Content-Type if data is undefined + requestData === undefined && requestHeaders.setContentType(null); + + // Add headers to the request + if ('setRequestHeader' in request) { + utils$1.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) { + request.setRequestHeader(key, val); + }); + } + + // Add withCredentials to request if needed + if (!utils$1.isUndefined(config.withCredentials)) { + request.withCredentials = !!config.withCredentials; + } + + // Add responseType to request if needed + if (responseType && responseType !== 'json') { + request.responseType = config.responseType; + } + + // Handle progress if needed + if (typeof config.onDownloadProgress === 'function') { + request.addEventListener('progress', progressEventReducer(config.onDownloadProgress, true)); + } + + // Not all browsers support upload events + if (typeof config.onUploadProgress === 'function' && request.upload) { + request.upload.addEventListener('progress', progressEventReducer(config.onUploadProgress)); + } + + if (config.cancelToken || config.signal) { + // Handle cancellation + // eslint-disable-next-line func-names + onCanceled = cancel => { + if (!request) { + return; + } + reject(!cancel || cancel.type ? new CanceledError(null, config, request) : cancel); + request.abort(); + request = null; + }; + + config.cancelToken && config.cancelToken.subscribe(onCanceled); + if (config.signal) { + config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled); + } + } + + const protocol = parseProtocol(fullPath); + + if (protocol && platform.protocols.indexOf(protocol) === -1) { + reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config)); + return; + } + + + // Send the request + request.send(requestData || null); + }); +}; + +const knownAdapters = { + http: httpAdapter, + xhr: xhrAdapter +}; + +utils$1.forEach(knownAdapters, (fn, value) => { + if (fn) { + try { + Object.defineProperty(fn, 'name', {value}); + } catch (e) { + // eslint-disable-next-line no-empty + } + Object.defineProperty(fn, 'adapterName', {value}); + } +}); + +const renderReason = (reason) => `- ${reason}`; + +const isResolvedHandle = (adapter) => utils$1.isFunction(adapter) || adapter === null || adapter === false; + +var adapters = { + getAdapter: (adapters) => { + adapters = utils$1.isArray(adapters) ? adapters : [adapters]; + + const {length} = adapters; + let nameOrAdapter; + let adapter; + + const rejectedReasons = {}; + + for (let i = 0; i < length; i++) { + nameOrAdapter = adapters[i]; + let id; + + adapter = nameOrAdapter; + + if (!isResolvedHandle(nameOrAdapter)) { + adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()]; + + if (adapter === undefined) { + throw new AxiosError(`Unknown adapter '${id}'`); + } + } + + if (adapter) { + break; + } + + rejectedReasons[id || '#' + i] = adapter; + } + + if (!adapter) { + + const reasons = Object.entries(rejectedReasons) + .map(([id, state]) => `adapter ${id} ` + + (state === false ? 'is not supported by the environment' : 'is not available in the build') + ); + + let s = length ? + (reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0])) : + 'as no adapter specified'; + + throw new AxiosError( + `There is no suitable adapter to dispatch the request ` + s, + 'ERR_NOT_SUPPORT' + ); + } + + return adapter; + }, + adapters: knownAdapters +}; + +/** + * Throws a `CanceledError` if cancellation has been requested. + * + * @param {Object} config The config that is to be used for the request + * + * @returns {void} + */ +function throwIfCancellationRequested(config) { + if (config.cancelToken) { + config.cancelToken.throwIfRequested(); + } + + if (config.signal && config.signal.aborted) { + throw new CanceledError(null, config); + } +} + +/** + * Dispatch a request to the server using the configured adapter. + * + * @param {object} config The config that is to be used for the request + * + * @returns {Promise} The Promise to be fulfilled + */ +function dispatchRequest(config) { + throwIfCancellationRequested(config); + + config.headers = AxiosHeaders$1.from(config.headers); + + // Transform request data + config.data = transformData.call( + config, + config.transformRequest + ); + + if (['post', 'put', 'patch'].indexOf(config.method) !== -1) { + config.headers.setContentType('application/x-www-form-urlencoded', false); + } + + const adapter = adapters.getAdapter(config.adapter || defaults$1.adapter); + + return adapter(config).then(function onAdapterResolution(response) { + throwIfCancellationRequested(config); + + // Transform response data + response.data = transformData.call( + config, + config.transformResponse, + response + ); + + response.headers = AxiosHeaders$1.from(response.headers); + + return response; + }, function onAdapterRejection(reason) { + if (!isCancel(reason)) { + throwIfCancellationRequested(config); + + // Transform response data + if (reason && reason.response) { + reason.response.data = transformData.call( + config, + config.transformResponse, + reason.response + ); + reason.response.headers = AxiosHeaders$1.from(reason.response.headers); + } + } + + return Promise.reject(reason); + }); +} + +const headersToObject = (thing) => thing instanceof AxiosHeaders$1 ? { ...thing } : thing; + +/** + * Config-specific merge-function which creates a new config-object + * by merging two configuration objects together. + * + * @param {Object} config1 + * @param {Object} config2 + * + * @returns {Object} New object resulting from merging config2 to config1 + */ +function mergeConfig(config1, config2) { + // eslint-disable-next-line no-param-reassign + config2 = config2 || {}; + const config = {}; + + function getMergedValue(target, source, caseless) { + if (utils$1.isPlainObject(target) && utils$1.isPlainObject(source)) { + return utils$1.merge.call({caseless}, target, source); + } else if (utils$1.isPlainObject(source)) { + return utils$1.merge({}, source); + } else if (utils$1.isArray(source)) { + return source.slice(); + } + return source; + } + + // eslint-disable-next-line consistent-return + function mergeDeepProperties(a, b, caseless) { + if (!utils$1.isUndefined(b)) { + return getMergedValue(a, b, caseless); + } else if (!utils$1.isUndefined(a)) { + return getMergedValue(undefined, a, caseless); + } + } + + // eslint-disable-next-line consistent-return + function valueFromConfig2(a, b) { + if (!utils$1.isUndefined(b)) { + return getMergedValue(undefined, b); + } + } + + // eslint-disable-next-line consistent-return + function defaultToConfig2(a, b) { + if (!utils$1.isUndefined(b)) { + return getMergedValue(undefined, b); + } else if (!utils$1.isUndefined(a)) { + return getMergedValue(undefined, a); + } + } + + // eslint-disable-next-line consistent-return + function mergeDirectKeys(a, b, prop) { + if (prop in config2) { + return getMergedValue(a, b); + } else if (prop in config1) { + return getMergedValue(undefined, a); + } + } + + const mergeMap = { + url: valueFromConfig2, + method: valueFromConfig2, + data: valueFromConfig2, + baseURL: defaultToConfig2, + transformRequest: defaultToConfig2, + transformResponse: defaultToConfig2, + paramsSerializer: defaultToConfig2, + timeout: defaultToConfig2, + timeoutMessage: defaultToConfig2, + withCredentials: defaultToConfig2, + withXSRFToken: defaultToConfig2, + adapter: defaultToConfig2, + responseType: defaultToConfig2, + xsrfCookieName: defaultToConfig2, + xsrfHeaderName: defaultToConfig2, + onUploadProgress: defaultToConfig2, + onDownloadProgress: defaultToConfig2, + decompress: defaultToConfig2, + maxContentLength: defaultToConfig2, + maxBodyLength: defaultToConfig2, + beforeRedirect: defaultToConfig2, + transport: defaultToConfig2, + httpAgent: defaultToConfig2, + httpsAgent: defaultToConfig2, + cancelToken: defaultToConfig2, + socketPath: defaultToConfig2, + responseEncoding: defaultToConfig2, + validateStatus: mergeDirectKeys, + headers: (a, b) => mergeDeepProperties(headersToObject(a), headersToObject(b), true) + }; + + utils$1.forEach(Object.keys(Object.assign({}, config1, config2)), function computeConfigValue(prop) { + const merge = mergeMap[prop] || mergeDeepProperties; + const configValue = merge(config1[prop], config2[prop], prop); + (utils$1.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue); + }); + + return config; +} + +const VERSION = "1.6.8"; + +const validators$1 = {}; + +// eslint-disable-next-line func-names +['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach((type, i) => { + validators$1[type] = function validator(thing) { + return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type; + }; +}); + +const deprecatedWarnings = {}; + +/** + * Transitional option validator + * + * @param {function|boolean?} validator - set to false if the transitional option has been removed + * @param {string?} version - deprecated version / removed since version + * @param {string?} message - some message with additional info + * + * @returns {function} + */ +validators$1.transitional = function transitional(validator, version, message) { + function formatMessage(opt, desc) { + return '[Axios v' + VERSION + '] Transitional option \'' + opt + '\'' + desc + (message ? '. ' + message : ''); + } + + // eslint-disable-next-line func-names + return (value, opt, opts) => { + if (validator === false) { + throw new AxiosError( + formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')), + AxiosError.ERR_DEPRECATED + ); + } + + if (version && !deprecatedWarnings[opt]) { + deprecatedWarnings[opt] = true; + // eslint-disable-next-line no-console + console.warn( + formatMessage( + opt, + ' has been deprecated since v' + version + ' and will be removed in the near future' + ) + ); + } + + return validator ? validator(value, opt, opts) : true; + }; +}; + +/** + * Assert object's properties type + * + * @param {object} options + * @param {object} schema + * @param {boolean?} allowUnknown + * + * @returns {object} + */ + +function assertOptions(options, schema, allowUnknown) { + if (typeof options !== 'object') { + throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE); + } + const keys = Object.keys(options); + let i = keys.length; + while (i-- > 0) { + const opt = keys[i]; + const validator = schema[opt]; + if (validator) { + const value = options[opt]; + const result = value === undefined || validator(value, opt, options); + if (result !== true) { + throw new AxiosError('option ' + opt + ' must be ' + result, AxiosError.ERR_BAD_OPTION_VALUE); + } + continue; + } + if (allowUnknown !== true) { + throw new AxiosError('Unknown option ' + opt, AxiosError.ERR_BAD_OPTION); + } + } +} + +var validator = { + assertOptions, + validators: validators$1 +}; + +const validators = validator.validators; + +/** + * Create a new instance of Axios + * + * @param {Object} instanceConfig The default config for the instance + * + * @return {Axios} A new instance of Axios + */ +class Axios { + constructor(instanceConfig) { + this.defaults = instanceConfig; + this.interceptors = { + request: new InterceptorManager(), + response: new InterceptorManager() + }; + } + + /** + * Dispatch a request + * + * @param {String|Object} configOrUrl The config specific for this request (merged with this.defaults) + * @param {?Object} config + * + * @returns {Promise} The Promise to be fulfilled + */ + async request(configOrUrl, config) { + try { + return await this._request(configOrUrl, config); + } catch (err) { + if (err instanceof Error) { + let dummy; + + Error.captureStackTrace ? Error.captureStackTrace(dummy = {}) : (dummy = new Error()); + + // slice off the Error: ... line + const stack = dummy.stack ? dummy.stack.replace(/^.+\n/, '') : ''; + + if (!err.stack) { + err.stack = stack; + // match without the 2 top stack lines + } else if (stack && !String(err.stack).endsWith(stack.replace(/^.+\n.+\n/, ''))) { + err.stack += '\n' + stack; + } + } + + throw err; + } + } + + _request(configOrUrl, config) { + /*eslint no-param-reassign:0*/ + // Allow for axios('example/url'[, config]) a la fetch API + if (typeof configOrUrl === 'string') { + config = config || {}; + config.url = configOrUrl; + } else { + config = configOrUrl || {}; + } + + config = mergeConfig(this.defaults, config); + + const {transitional, paramsSerializer, headers} = config; + + if (transitional !== undefined) { + validator.assertOptions(transitional, { + silentJSONParsing: validators.transitional(validators.boolean), + forcedJSONParsing: validators.transitional(validators.boolean), + clarifyTimeoutError: validators.transitional(validators.boolean) + }, false); + } + + if (paramsSerializer != null) { + if (utils$1.isFunction(paramsSerializer)) { + config.paramsSerializer = { + serialize: paramsSerializer + }; + } else { + validator.assertOptions(paramsSerializer, { + encode: validators.function, + serialize: validators.function + }, true); + } + } + + // Set config.method + config.method = (config.method || this.defaults.method || 'get').toLowerCase(); + + // Flatten headers + let contextHeaders = headers && utils$1.merge( + headers.common, + headers[config.method] + ); + + headers && utils$1.forEach( + ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], + (method) => { + delete headers[method]; + } + ); + + config.headers = AxiosHeaders$1.concat(contextHeaders, headers); + + // filter out skipped interceptors + const requestInterceptorChain = []; + let synchronousRequestInterceptors = true; + this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { + if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) { + return; + } + + synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous; + + requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); + }); + + const responseInterceptorChain = []; + this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { + responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); + }); + + let promise; + let i = 0; + let len; + + if (!synchronousRequestInterceptors) { + const chain = [dispatchRequest.bind(this), undefined]; + chain.unshift.apply(chain, requestInterceptorChain); + chain.push.apply(chain, responseInterceptorChain); + len = chain.length; + + promise = Promise.resolve(config); + + while (i < len) { + promise = promise.then(chain[i++], chain[i++]); + } + + return promise; + } + + len = requestInterceptorChain.length; + + let newConfig = config; + + i = 0; + + while (i < len) { + const onFulfilled = requestInterceptorChain[i++]; + const onRejected = requestInterceptorChain[i++]; + try { + newConfig = onFulfilled(newConfig); + } catch (error) { + onRejected.call(this, error); + break; + } + } + + try { + promise = dispatchRequest.call(this, newConfig); + } catch (error) { + return Promise.reject(error); + } + + i = 0; + len = responseInterceptorChain.length; + + while (i < len) { + promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]); + } + + return promise; + } + + getUri(config) { + config = mergeConfig(this.defaults, config); + const fullPath = buildFullPath(config.baseURL, config.url); + return buildURL(fullPath, config.params, config.paramsSerializer); + } +} + +// Provide aliases for supported request methods +utils$1.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { + /*eslint func-names:0*/ + Axios.prototype[method] = function(url, config) { + return this.request(mergeConfig(config || {}, { + method, + url, + data: (config || {}).data + })); + }; +}); + +utils$1.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { + /*eslint func-names:0*/ + + function generateHTTPMethod(isForm) { + return function httpMethod(url, data, config) { + return this.request(mergeConfig(config || {}, { + method, + headers: isForm ? { + 'Content-Type': 'multipart/form-data' + } : {}, + url, + data + })); + }; + } + + Axios.prototype[method] = generateHTTPMethod(); + + Axios.prototype[method + 'Form'] = generateHTTPMethod(true); +}); + +var Axios$1 = Axios; + +/** + * A `CancelToken` is an object that can be used to request cancellation of an operation. + * + * @param {Function} executor The executor function. + * + * @returns {CancelToken} + */ +class CancelToken { + constructor(executor) { + if (typeof executor !== 'function') { + throw new TypeError('executor must be a function.'); + } + + let resolvePromise; + + this.promise = new Promise(function promiseExecutor(resolve) { + resolvePromise = resolve; + }); + + const token = this; + + // eslint-disable-next-line func-names + this.promise.then(cancel => { + if (!token._listeners) return; + + let i = token._listeners.length; + + while (i-- > 0) { + token._listeners[i](cancel); + } + token._listeners = null; + }); + + // eslint-disable-next-line func-names + this.promise.then = onfulfilled => { + let _resolve; + // eslint-disable-next-line func-names + const promise = new Promise(resolve => { + token.subscribe(resolve); + _resolve = resolve; + }).then(onfulfilled); + + promise.cancel = function reject() { + token.unsubscribe(_resolve); + }; + + return promise; + }; + + executor(function cancel(message, config, request) { + if (token.reason) { + // Cancellation has already been requested + return; + } + + token.reason = new CanceledError(message, config, request); + resolvePromise(token.reason); + }); + } + + /** + * Throws a `CanceledError` if cancellation has been requested. + */ + throwIfRequested() { + if (this.reason) { + throw this.reason; + } + } + + /** + * Subscribe to the cancel signal + */ + + subscribe(listener) { + if (this.reason) { + listener(this.reason); + return; + } + + if (this._listeners) { + this._listeners.push(listener); + } else { + this._listeners = [listener]; + } + } + + /** + * Unsubscribe from the cancel signal + */ + + unsubscribe(listener) { + if (!this._listeners) { + return; + } + const index = this._listeners.indexOf(listener); + if (index !== -1) { + this._listeners.splice(index, 1); + } + } + + /** + * Returns an object that contains a new `CancelToken` and a function that, when called, + * cancels the `CancelToken`. + */ + static source() { + let cancel; + const token = new CancelToken(function executor(c) { + cancel = c; + }); + return { + token, + cancel + }; + } +} + +var CancelToken$1 = CancelToken; + +/** + * Syntactic sugar for invoking a function and expanding an array for arguments. + * + * Common use case would be to use `Function.prototype.apply`. + * + * ```js + * function f(x, y, z) {} + * var args = [1, 2, 3]; + * f.apply(null, args); + * ``` + * + * With `spread` this example can be re-written. + * + * ```js + * spread(function(x, y, z) {})([1, 2, 3]); + * ``` + * + * @param {Function} callback + * + * @returns {Function} + */ +function spread(callback) { + return function wrap(arr) { + return callback.apply(null, arr); + }; +} + +/** + * Determines whether the payload is an error thrown by Axios + * + * @param {*} payload The value to test + * + * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false + */ +function isAxiosError(payload) { + return utils$1.isObject(payload) && (payload.isAxiosError === true); +} + +const HttpStatusCode = { + Continue: 100, + SwitchingProtocols: 101, + Processing: 102, + EarlyHints: 103, + Ok: 200, + Created: 201, + Accepted: 202, + NonAuthoritativeInformation: 203, + NoContent: 204, + ResetContent: 205, + PartialContent: 206, + MultiStatus: 207, + AlreadyReported: 208, + ImUsed: 226, + MultipleChoices: 300, + MovedPermanently: 301, + Found: 302, + SeeOther: 303, + NotModified: 304, + UseProxy: 305, + Unused: 306, + TemporaryRedirect: 307, + PermanentRedirect: 308, + BadRequest: 400, + Unauthorized: 401, + PaymentRequired: 402, + Forbidden: 403, + NotFound: 404, + MethodNotAllowed: 405, + NotAcceptable: 406, + ProxyAuthenticationRequired: 407, + RequestTimeout: 408, + Conflict: 409, + Gone: 410, + LengthRequired: 411, + PreconditionFailed: 412, + PayloadTooLarge: 413, + UriTooLong: 414, + UnsupportedMediaType: 415, + RangeNotSatisfiable: 416, + ExpectationFailed: 417, + ImATeapot: 418, + MisdirectedRequest: 421, + UnprocessableEntity: 422, + Locked: 423, + FailedDependency: 424, + TooEarly: 425, + UpgradeRequired: 426, + PreconditionRequired: 428, + TooManyRequests: 429, + RequestHeaderFieldsTooLarge: 431, + UnavailableForLegalReasons: 451, + InternalServerError: 500, + NotImplemented: 501, + BadGateway: 502, + ServiceUnavailable: 503, + GatewayTimeout: 504, + HttpVersionNotSupported: 505, + VariantAlsoNegotiates: 506, + InsufficientStorage: 507, + LoopDetected: 508, + NotExtended: 510, + NetworkAuthenticationRequired: 511, +}; + +Object.entries(HttpStatusCode).forEach(([key, value]) => { + HttpStatusCode[value] = key; +}); + +var HttpStatusCode$1 = HttpStatusCode; + +/** + * Create an instance of Axios + * + * @param {Object} defaultConfig The default config for the instance + * + * @returns {Axios} A new instance of Axios + */ +function createInstance(defaultConfig) { + const context = new Axios$1(defaultConfig); + const instance = bind(Axios$1.prototype.request, context); + + // Copy axios.prototype to instance + utils$1.extend(instance, Axios$1.prototype, context, {allOwnKeys: true}); + + // Copy context to instance + utils$1.extend(instance, context, null, {allOwnKeys: true}); + + // Factory for creating new instances + instance.create = function create(instanceConfig) { + return createInstance(mergeConfig(defaultConfig, instanceConfig)); + }; + + return instance; +} + +// Create the default instance to be exported +const axios = createInstance(defaults$1); + +// Expose Axios class to allow class inheritance +axios.Axios = Axios$1; + +// Expose Cancel & CancelToken +axios.CanceledError = CanceledError; +axios.CancelToken = CancelToken$1; +axios.isCancel = isCancel; +axios.VERSION = VERSION; +axios.toFormData = toFormData; + +// Expose AxiosError class +axios.AxiosError = AxiosError; + +// alias for CanceledError for backward compatibility +axios.Cancel = axios.CanceledError; + +// Expose all/spread +axios.all = function all(promises) { + return Promise.all(promises); +}; + +axios.spread = spread; + +// Expose isAxiosError +axios.isAxiosError = isAxiosError; + +// Expose mergeConfig +axios.mergeConfig = mergeConfig; + +axios.AxiosHeaders = AxiosHeaders$1; + +axios.formToJSON = thing => formDataToJSON(utils$1.isHTMLForm(thing) ? new FormData(thing) : thing); + +axios.getAdapter = adapters.getAdapter; + +axios.HttpStatusCode = HttpStatusCode$1; + +axios.default = axios; + +var ds=Object.defineProperty;var zg=Object.getOwnPropertyDescriptor;var Kg=Object.getOwnPropertyNames;var Gg=Object.prototype.hasOwnProperty;var we=(t,e)=>()=>(t&&(e=t(t=0)),e);var M=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Qt=(t,e)=>{for(var r in e)ds(t,r,{get:e[r],enumerable:!0});},Qg=(t,e,r,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Kg(e))!Gg.call(t,n)&&n!==r&&ds(t,n,{get:()=>e[n],enumerable:!(i=zg(e,n))||i.enumerable});return t};var X=t=>Qg(ds({},"__esModule",{value:!0}),t);var B,_=we(()=>{B={deviceMemory:8,hardwareConcurrency:8,language:"en-US"};});var P={};Qt(P,{_debugEnd:()=>yu,_debugProcess:()=>gu,_events:()=>ku,_eventsCount:()=>xu,_exiting:()=>Yl,_fatalExceptions:()=>cu,_getActiveHandles:()=>eu,_getActiveRequests:()=>Zl,_kill:()=>ru,_linkedBinding:()=>Gl,_maxListeners:()=>Ou,_preload_modules:()=>Cu,_rawDebug:()=>zl,_startProfilerIdleNotifier:()=>bu,_stopProfilerIdleNotifier:()=>wu,_tickCallback:()=>pu,abort:()=>Eu,addListener:()=>Mu,allowedNodeEnvironmentFlags:()=>lu,arch:()=>xl,argv:()=>Ul,argv0:()=>Ru,assert:()=>uu,binding:()=>Fl,chdir:()=>Hl,config:()=>Jl,cpuUsage:()=>Fi,cwd:()=>$l,debugPort:()=>Tu,default:()=>$u,dlopen:()=>Xl,domain:()=>Ql,emit:()=>Du,emitWarning:()=>jl,env:()=>Ll,execArgv:()=>Nl,execPath:()=>Iu,exit:()=>ou,features:()=>fu,hasUncaughtExceptionCaptureCallback:()=>du,hrtime:()=>ji,kill:()=>su,listeners:()=>Wu,memoryUsage:()=>nu,moduleLoadList:()=>Kl,nextTick:()=>Pl,off:()=>Uu,on:()=>bt,once:()=>Lu,openStdin:()=>au,pid:()=>Su,platform:()=>Ml,ppid:()=>Au,prependListener:()=>ju,prependOnceListener:()=>Fu,reallyExit:()=>tu,release:()=>Vl,removeAllListeners:()=>qu,removeListener:()=>Nu,resourceUsage:()=>iu,setSourceMapsEnabled:()=>Bu,setUncaughtExceptionCaptureCallback:()=>hu,stderr:()=>mu,stdin:()=>vu,stdout:()=>_u,title:()=>kl,umask:()=>Wl,uptime:()=>Pu,version:()=>ql,versions:()=>Dl});function ys(t){throw new Error("Node.js process "+t+" is not supported by JSPM core outside of Node.js")}function Yg(){!xr||!Yt||(xr=!1,Yt.length?yt=Yt.concat(yt):Di=-1,yt.length&&Bl());}function Bl(){if(!xr){var t=setTimeout(Yg,0);xr=!0;for(var e=yt.length;e;){for(Yt=yt,yt=[];++Di1)for(var r=1;r{v();m();_();yt=[],xr=!1,Di=-1;Ol.prototype.run=function(){this.fun.apply(null,this.array);};kl="browser",xl="x64",Ml="browser",Ll={PATH:"/usr/bin",LANG:B.language+".UTF-8",PWD:"/",HOME:"/home",TMP:"/tmp"},Ul=["/usr/bin/node"],Nl=[],ql="v16.8.0",Dl={},jl=function(t,e){console.warn((e?e+": ":"")+t);},Fl=function(t){ys("binding");},Wl=function(t){return 0},$l=function(){return "/"},Hl=function(t){},Vl={name:"node",sourceUrl:"",headersUrl:"",libUrl:""};zl=ve,Kl=[];Ql={},Yl=!1,Jl={};tu=ve,ru=ve,Fi=function(){return {}},iu=Fi,nu=Fi,su=ve,ou=ve,au=ve,lu={};fu={inspector:!1,debug:!1,uv:!1,ipv6:!1,tls_alpn:!1,tls_sni:!1,tls_ocsp:!1,tls:!1,cached_builtins:!0},cu=ve,hu=ve;pu=ve,gu=ve,yu=ve,bu=ve,wu=ve,_u=void 0,mu=void 0,vu=void 0,Eu=ve,Su=2,Au=1,Iu="/bin/usr/node",Tu=9229,Ru="node",Cu=[],Bu=ve,Mt={now:typeof performance<"u"?performance.now.bind(performance):void 0,timing:typeof performance<"u"?performance.timing:void 0};Mt.now===void 0&&(ps=Date.now(),Mt.timing&&Mt.timing.navigationStart&&(ps=Mt.timing.navigationStart),Mt.now=()=>Date.now()-ps);gs=1e9;ji.bigint=function(t){var e=ji(t);return typeof BigInt>"u"?e[0]*gs+e[1]:BigInt(e[0]*gs)+BigInt(e[1])};Ou=10,ku={},xu=0;Mu=bt,Lu=bt,Uu=bt,Nu=bt,qu=bt,Du=ve,ju=bt,Fu=bt;$u={version:ql,versions:Dl,arch:xl,platform:Ml,release:Vl,_rawDebug:zl,moduleLoadList:Kl,binding:Fl,_linkedBinding:Gl,_events:ku,_eventsCount:xu,_maxListeners:Ou,on:bt,addListener:Mu,once:Lu,off:Uu,removeListener:Nu,removeAllListeners:qu,emit:Du,prependListener:ju,prependOnceListener:Fu,listeners:Wu,domain:Ql,_exiting:Yl,config:Jl,dlopen:Xl,uptime:Pu,_getActiveRequests:Zl,_getActiveHandles:eu,reallyExit:tu,_kill:ru,cpuUsage:Fi,resourceUsage:iu,memoryUsage:nu,kill:su,exit:ou,openStdin:au,allowedNodeEnvironmentFlags:lu,assert:uu,features:fu,_fatalExceptions:cu,setUncaughtExceptionCaptureCallback:hu,hasUncaughtExceptionCaptureCallback:du,emitWarning:jl,nextTick:Pl,_tickCallback:pu,_debugProcess:gu,_debugEnd:yu,_startProfilerIdleNotifier:bu,_stopProfilerIdleNotifier:wu,stdout:_u,stdin:vu,stderr:mu,abort:Eu,umask:Wl,chdir:Hl,cwd:$l,env:Ll,title:kl,argv:Ul,execArgv:Nl,pid:Su,ppid:Au,execPath:Iu,debugPort:Tu,hrtime:ji,argv0:Ru,_preload_modules:Cu,setSourceMapsEnabled:Bu};});var m=we(()=>{Hu();});var _e={};Qt(_e,{Buffer:()=>x,INSPECT_MAX_BYTES:()=>ey,default:()=>Lt,kMaxLength:()=>ty});function Jg(){if(Vu)return ui;Vu=!0,ui.byteLength=a,ui.toByteArray=c,ui.fromByteArray=g;for(var t=[],e=[],r=typeof Uint8Array<"u"?Uint8Array:Array,i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=0,o=i.length;n0)throw new Error("Invalid string. Length must be a multiple of 4");var E=y.indexOf("=");E===-1&&(E=w);var S=E===w?0:4-E%4;return [E,S]}function a(y){var w=s(y),E=w[0],S=w[1];return (E+S)*3/4-S}function u(y,w,E){return (w+E)*3/4-E}function c(y){var w,E=s(y),S=E[0],I=E[1],C=new r(u(y,S,I)),R=0,U=I>0?S-4:S,N;for(N=0;N>16&255,C[R++]=w>>8&255,C[R++]=w&255;return I===2&&(w=e[y.charCodeAt(N)]<<2|e[y.charCodeAt(N+1)]>>4,C[R++]=w&255),I===1&&(w=e[y.charCodeAt(N)]<<10|e[y.charCodeAt(N+1)]<<4|e[y.charCodeAt(N+2)]>>2,C[R++]=w>>8&255,C[R++]=w&255),C}function h(y){return t[y>>18&63]+t[y>>12&63]+t[y>>6&63]+t[y&63]}function d(y,w,E){for(var S,I=[],C=w;CU?U:R+C));return S===1?(w=y[E-1],I.push(t[w>>2]+t[w<<4&63]+"==")):S===2&&(w=(y[E-2]<<8)+y[E-1],I.push(t[w>>10]+t[w>>4&63]+t[w<<2&63]+"=")),I.join("")}return ui}function Xg(){if(zu)return Wi;zu=!0;return Wi.read=function(t,e,r,i,n){var o,s,a=n*8-i-1,u=(1<>1,h=-7,d=r?n-1:0,g=r?-1:1,y=t[e+d];for(d+=g,o=y&(1<<-h)-1,y>>=-h,h+=a;h>0;o=o*256+t[e+d],d+=g,h-=8);for(s=o&(1<<-h)-1,o>>=-h,h+=i;h>0;s=s*256+t[e+d],d+=g,h-=8);if(o===0)o=1-c;else {if(o===u)return s?NaN:(y?-1:1)*(1/0);s=s+Math.pow(2,i),o=o-c;}return (y?-1:1)*s*Math.pow(2,o-i)},Wi.write=function(t,e,r,i,n,o){var s,a,u,c=o*8-n-1,h=(1<>1,g=n===23?Math.pow(2,-24)-Math.pow(2,-77):0,y=i?0:o-1,w=i?1:-1,E=e<0||e===0&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(a=isNaN(e)?1:0,s=h):(s=Math.floor(Math.log(e)/Math.LN2),e*(u=Math.pow(2,-s))<1&&(s--,u*=2),s+d>=1?e+=g/u:e+=g*Math.pow(2,1-d),e*u>=2&&(s++,u/=2),s+d>=h?(a=0,s=h):s+d>=1?(a=(e*u-1)*Math.pow(2,n),s=s+d):(a=e*Math.pow(2,d-1)*Math.pow(2,n),s=0));n>=8;t[r+y]=a&255,y+=w,a/=256,n-=8);for(s=s<0;t[r+y]=s&255,y+=w,s/=256,c-=8);t[r+y-w]|=E*128;},Wi}function Zg(){if(Ku)return Jt;Ku=!0;let t=Jg(),e=Xg(),r=typeof Symbol=="function"&&typeof Symbol.for=="function"?Symbol.for("nodejs.util.inspect.custom"):null;Jt.Buffer=s,Jt.SlowBuffer=I,Jt.INSPECT_MAX_BYTES=50;let i=2147483647;Jt.kMaxLength=i,s.TYPED_ARRAY_SUPPORT=n(),!s.TYPED_ARRAY_SUPPORT&&typeof console<"u"&&typeof console.error=="function"&&console.error("This browser lacks typed array (Uint8Array) support which is required by `buffer` v5.x. Use `buffer` v4.x if you require old browser support.");function n(){try{let p=new Uint8Array(1),l={foo:function(){return 42}};return Object.setPrototypeOf(l,Uint8Array.prototype),Object.setPrototypeOf(p,l),p.foo()===42}catch{return !1}}Object.defineProperty(s.prototype,"parent",{enumerable:!0,get:function(){if(s.isBuffer(this))return this.buffer}}),Object.defineProperty(s.prototype,"offset",{enumerable:!0,get:function(){if(s.isBuffer(this))return this.byteOffset}});function o(p){if(p>i)throw new RangeError('The value "'+p+'" is invalid for option "size"');let l=new Uint8Array(p);return Object.setPrototypeOf(l,s.prototype),l}function s(p,l,f){if(typeof p=="number"){if(typeof l=="string")throw new TypeError('The "string" argument must be of type string. Received type number');return h(p)}return a(p,l,f)}s.poolSize=8192;function a(p,l,f){if(typeof p=="string")return d(p,l);if(ArrayBuffer.isView(p))return y(p);if(p==null)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof p);if(Ye(p,ArrayBuffer)||p&&Ye(p.buffer,ArrayBuffer)||typeof SharedArrayBuffer<"u"&&(Ye(p,SharedArrayBuffer)||p&&Ye(p.buffer,SharedArrayBuffer)))return w(p,l,f);if(typeof p=="number")throw new TypeError('The "value" argument must not be of type number. Received type number');let b=p.valueOf&&p.valueOf();if(b!=null&&b!==p)return s.from(b,l,f);let A=E(p);if(A)return A;if(typeof Symbol<"u"&&Symbol.toPrimitive!=null&&typeof p[Symbol.toPrimitive]=="function")return s.from(p[Symbol.toPrimitive]("string"),l,f);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof p)}s.from=function(p,l,f){return a(p,l,f)},Object.setPrototypeOf(s.prototype,Uint8Array.prototype),Object.setPrototypeOf(s,Uint8Array);function u(p){if(typeof p!="number")throw new TypeError('"size" argument must be of type number');if(p<0)throw new RangeError('The value "'+p+'" is invalid for option "size"')}function c(p,l,f){return u(p),p<=0?o(p):l!==void 0?typeof f=="string"?o(p).fill(l,f):o(p).fill(l):o(p)}s.alloc=function(p,l,f){return c(p,l,f)};function h(p){return u(p),o(p<0?0:S(p)|0)}s.allocUnsafe=function(p){return h(p)},s.allocUnsafeSlow=function(p){return h(p)};function d(p,l){if((typeof l!="string"||l==="")&&(l="utf8"),!s.isEncoding(l))throw new TypeError("Unknown encoding: "+l);let f=C(p,l)|0,b=o(f),A=b.write(p,l);return A!==f&&(b=b.slice(0,A)),b}function g(p){let l=p.length<0?0:S(p.length)|0,f=o(l);for(let b=0;b=i)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+i.toString(16)+" bytes");return p|0}function I(p){return +p!=p&&(p=0),s.alloc(+p)}s.isBuffer=function(l){return l!=null&&l._isBuffer===!0&&l!==s.prototype},s.compare=function(l,f){if(Ye(l,Uint8Array)&&(l=s.from(l,l.offset,l.byteLength)),Ye(f,Uint8Array)&&(f=s.from(f,f.offset,f.byteLength)),!s.isBuffer(l)||!s.isBuffer(f))throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(l===f)return 0;let b=l.length,A=f.length;for(let T=0,O=Math.min(b,A);TA.length?(s.isBuffer(O)||(O=s.from(O)),O.copy(A,T)):Uint8Array.prototype.set.call(A,O,T);else if(s.isBuffer(O))O.copy(A,T);else throw new TypeError('"list" argument must be an Array of Buffers');T+=O.length;}return A};function C(p,l){if(s.isBuffer(p))return p.length;if(ArrayBuffer.isView(p)||Ye(p,ArrayBuffer))return p.byteLength;if(typeof p!="string")throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof p);let f=p.length,b=arguments.length>2&&arguments[2]===!0;if(!b&&f===0)return 0;let A=!1;for(;;)switch(l){case"ascii":case"latin1":case"binary":return f;case"utf8":case"utf-8":return cs(p).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return f*2;case"hex":return f>>>1;case"base64":return Cl(p).length;default:if(A)return b?-1:cs(p).length;l=(""+l).toLowerCase(),A=!0;}}s.byteLength=C;function R(p,l,f){let b=!1;if((l===void 0||l<0)&&(l=0),l>this.length||((f===void 0||f>this.length)&&(f=this.length),f<=0)||(f>>>=0,l>>>=0,f<=l))return "";for(p||(p="utf8");;)switch(p){case"hex":return Ng(this,l,f);case"utf8":case"utf-8":return Cr(this,l,f);case"ascii":return us(this,l,f);case"latin1":case"binary":return Ug(this,l,f);case"base64":return pe(this,l,f);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return qg(this,l,f);default:if(b)throw new TypeError("Unknown encoding: "+p);p=(p+"").toLowerCase(),b=!0;}}s.prototype._isBuffer=!0;function U(p,l,f){let b=p[l];p[l]=p[f],p[f]=b;}s.prototype.swap16=function(){let l=this.length;if(l%2!==0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(let f=0;ff&&(l+=" ... "),""},r&&(s.prototype[r]=s.prototype.inspect),s.prototype.compare=function(l,f,b,A,T){if(Ye(l,Uint8Array)&&(l=s.from(l,l.offset,l.byteLength)),!s.isBuffer(l))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof l);if(f===void 0&&(f=0),b===void 0&&(b=l?l.length:0),A===void 0&&(A=0),T===void 0&&(T=this.length),f<0||b>l.length||A<0||T>this.length)throw new RangeError("out of range index");if(A>=T&&f>=b)return 0;if(A>=T)return -1;if(f>=b)return 1;if(f>>>=0,b>>>=0,A>>>=0,T>>>=0,this===l)return 0;let O=T-A,$=b-f,se=Math.min(O,$),te=this.slice(A,T),oe=l.slice(f,b);for(let J=0;J2147483647?f=2147483647:f<-2147483648&&(f=-2147483648),f=+f,hs(f)&&(f=A?0:p.length-1),f<0&&(f=p.length+f),f>=p.length){if(A)return -1;f=p.length-1;}else if(f<0)if(A)f=0;else return -1;if(typeof l=="string"&&(l=s.from(l,b)),s.isBuffer(l))return l.length===0?-1:W(p,l,f,b,A);if(typeof l=="number")return l=l&255,typeof Uint8Array.prototype.indexOf=="function"?A?Uint8Array.prototype.indexOf.call(p,l,f):Uint8Array.prototype.lastIndexOf.call(p,l,f):W(p,[l],f,b,A);throw new TypeError("val must be string, number or Buffer")}function W(p,l,f,b,A){let T=1,O=p.length,$=l.length;if(b!==void 0&&(b=String(b).toLowerCase(),b==="ucs2"||b==="ucs-2"||b==="utf16le"||b==="utf-16le")){if(p.length<2||l.length<2)return -1;T=2,O/=2,$/=2,f/=2;}function se(oe,J){return T===1?oe[J]:oe.readUInt16BE(J*T)}let te;if(A){let oe=-1;for(te=f;teO&&(f=O-$),te=f;te>=0;te--){let oe=!0;for(let J=0;J<$;J++)if(se(p,te+J)!==se(l,J)){oe=!1;break}if(oe)return te}return -1}s.prototype.includes=function(l,f,b){return this.indexOf(l,f,b)!==-1},s.prototype.indexOf=function(l,f,b){return N(this,l,f,b,!0)},s.prototype.lastIndexOf=function(l,f,b){return N(this,l,f,b,!1)};function K(p,l,f,b){f=Number(f)||0;let A=p.length-f;b?(b=Number(b),b>A&&(b=A)):b=A;let T=l.length;b>T/2&&(b=T/2);let O;for(O=0;O>>0,isFinite(b)?(b=b>>>0,A===void 0&&(A="utf8")):(A=b,b=void 0);else throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");let T=this.length-f;if((b===void 0||b>T)&&(b=T),l.length>0&&(b<0||f<0)||f>this.length)throw new RangeError("Attempt to write outside buffer bounds");A||(A="utf8");let O=!1;for(;;)switch(A){case"hex":return K(this,l,f,b);case"utf8":case"utf-8":return z(this,l,f,b);case"ascii":case"latin1":case"binary":return Q(this,l,f,b);case"base64":return de(this,l,f,b);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Gt(this,l,f,b);default:if(O)throw new TypeError("Unknown encoding: "+A);A=(""+A).toLowerCase(),O=!0;}},s.prototype.toJSON=function(){return {type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function pe(p,l,f){return l===0&&f===p.length?t.fromByteArray(p):t.fromByteArray(p.slice(l,f))}function Cr(p,l,f){f=Math.min(p.length,f);let b=[],A=l;for(;A239?4:T>223?3:T>191?2:1;if(A+$<=f){let se,te,oe,J;switch($){case 1:T<128&&(O=T);break;case 2:se=p[A+1],(se&192)===128&&(J=(T&31)<<6|se&63,J>127&&(O=J));break;case 3:se=p[A+1],te=p[A+2],(se&192)===128&&(te&192)===128&&(J=(T&15)<<12|(se&63)<<6|te&63,J>2047&&(J<55296||J>57343)&&(O=J));break;case 4:se=p[A+1],te=p[A+2],oe=p[A+3],(se&192)===128&&(te&192)===128&&(oe&192)===128&&(J=(T&15)<<18|(se&63)<<12|(te&63)<<6|oe&63,J>65535&&J<1114112&&(O=J));}}O===null?(O=65533,$=1):O>65535&&(O-=65536,b.push(O>>>10&1023|55296),O=56320|O&1023),b.push(O),A+=$;}return Pr(b)}let Br=4096;function Pr(p){let l=p.length;if(l<=Br)return String.fromCharCode.apply(String,p);let f="",b=0;for(;bb)&&(f=b);let A="";for(let T=l;Tb&&(l=b),f<0?(f+=b,f<0&&(f=0)):f>b&&(f=b),ff)throw new RangeError("Trying to access beyond buffer length")}s.prototype.readUintLE=s.prototype.readUIntLE=function(l,f,b){l=l>>>0,f=f>>>0,b||ge(l,f,this.length);let A=this[l],T=1,O=0;for(;++O>>0,f=f>>>0,b||ge(l,f,this.length);let A=this[l+--f],T=1;for(;f>0&&(T*=256);)A+=this[l+--f]*T;return A},s.prototype.readUint8=s.prototype.readUInt8=function(l,f){return l=l>>>0,f||ge(l,1,this.length),this[l]},s.prototype.readUint16LE=s.prototype.readUInt16LE=function(l,f){return l=l>>>0,f||ge(l,2,this.length),this[l]|this[l+1]<<8},s.prototype.readUint16BE=s.prototype.readUInt16BE=function(l,f){return l=l>>>0,f||ge(l,2,this.length),this[l]<<8|this[l+1]},s.prototype.readUint32LE=s.prototype.readUInt32LE=function(l,f){return l=l>>>0,f||ge(l,4,this.length),(this[l]|this[l+1]<<8|this[l+2]<<16)+this[l+3]*16777216},s.prototype.readUint32BE=s.prototype.readUInt32BE=function(l,f){return l=l>>>0,f||ge(l,4,this.length),this[l]*16777216+(this[l+1]<<16|this[l+2]<<8|this[l+3])},s.prototype.readBigUInt64LE=xt(function(l){l=l>>>0,kr(l,"offset");let f=this[l],b=this[l+7];(f===void 0||b===void 0)&&li(l,this.length-8);let A=f+this[++l]*2**8+this[++l]*2**16+this[++l]*2**24,T=this[++l]+this[++l]*2**8+this[++l]*2**16+b*2**24;return BigInt(A)+(BigInt(T)<>>0,kr(l,"offset");let f=this[l],b=this[l+7];(f===void 0||b===void 0)&&li(l,this.length-8);let A=f*2**24+this[++l]*2**16+this[++l]*2**8+this[++l],T=this[++l]*2**24+this[++l]*2**16+this[++l]*2**8+b;return (BigInt(A)<>>0,f=f>>>0,b||ge(l,f,this.length);let A=this[l],T=1,O=0;for(;++O=T&&(A-=Math.pow(2,8*f)),A},s.prototype.readIntBE=function(l,f,b){l=l>>>0,f=f>>>0,b||ge(l,f,this.length);let A=f,T=1,O=this[l+--A];for(;A>0&&(T*=256);)O+=this[l+--A]*T;return T*=128,O>=T&&(O-=Math.pow(2,8*f)),O},s.prototype.readInt8=function(l,f){return l=l>>>0,f||ge(l,1,this.length),this[l]&128?(255-this[l]+1)*-1:this[l]},s.prototype.readInt16LE=function(l,f){l=l>>>0,f||ge(l,2,this.length);let b=this[l]|this[l+1]<<8;return b&32768?b|4294901760:b},s.prototype.readInt16BE=function(l,f){l=l>>>0,f||ge(l,2,this.length);let b=this[l+1]|this[l]<<8;return b&32768?b|4294901760:b},s.prototype.readInt32LE=function(l,f){return l=l>>>0,f||ge(l,4,this.length),this[l]|this[l+1]<<8|this[l+2]<<16|this[l+3]<<24},s.prototype.readInt32BE=function(l,f){return l=l>>>0,f||ge(l,4,this.length),this[l]<<24|this[l+1]<<16|this[l+2]<<8|this[l+3]},s.prototype.readBigInt64LE=xt(function(l){l=l>>>0,kr(l,"offset");let f=this[l],b=this[l+7];(f===void 0||b===void 0)&&li(l,this.length-8);let A=this[l+4]+this[l+5]*2**8+this[l+6]*2**16+(b<<24);return (BigInt(A)<>>0,kr(l,"offset");let f=this[l],b=this[l+7];(f===void 0||b===void 0)&&li(l,this.length-8);let A=(f<<24)+this[++l]*2**16+this[++l]*2**8+this[++l];return (BigInt(A)<>>0,f||ge(l,4,this.length),e.read(this,l,!0,23,4)},s.prototype.readFloatBE=function(l,f){return l=l>>>0,f||ge(l,4,this.length),e.read(this,l,!1,23,4)},s.prototype.readDoubleLE=function(l,f){return l=l>>>0,f||ge(l,8,this.length),e.read(this,l,!0,52,8)},s.prototype.readDoubleBE=function(l,f){return l=l>>>0,f||ge(l,8,this.length),e.read(this,l,!1,52,8)};function Ce(p,l,f,b,A,T){if(!s.isBuffer(p))throw new TypeError('"buffer" argument must be a Buffer instance');if(l>A||lp.length)throw new RangeError("Index out of range")}s.prototype.writeUintLE=s.prototype.writeUIntLE=function(l,f,b,A){if(l=+l,f=f>>>0,b=b>>>0,!A){let $=Math.pow(2,8*b)-1;Ce(this,l,f,b,$,0);}let T=1,O=0;for(this[f]=l&255;++O>>0,b=b>>>0,!A){let $=Math.pow(2,8*b)-1;Ce(this,l,f,b,$,0);}let T=b-1,O=1;for(this[f+T]=l&255;--T>=0&&(O*=256);)this[f+T]=l/O&255;return f+b},s.prototype.writeUint8=s.prototype.writeUInt8=function(l,f,b){return l=+l,f=f>>>0,b||Ce(this,l,f,1,255,0),this[f]=l&255,f+1},s.prototype.writeUint16LE=s.prototype.writeUInt16LE=function(l,f,b){return l=+l,f=f>>>0,b||Ce(this,l,f,2,65535,0),this[f]=l&255,this[f+1]=l>>>8,f+2},s.prototype.writeUint16BE=s.prototype.writeUInt16BE=function(l,f,b){return l=+l,f=f>>>0,b||Ce(this,l,f,2,65535,0),this[f]=l>>>8,this[f+1]=l&255,f+2},s.prototype.writeUint32LE=s.prototype.writeUInt32LE=function(l,f,b){return l=+l,f=f>>>0,b||Ce(this,l,f,4,4294967295,0),this[f+3]=l>>>24,this[f+2]=l>>>16,this[f+1]=l>>>8,this[f]=l&255,f+4},s.prototype.writeUint32BE=s.prototype.writeUInt32BE=function(l,f,b){return l=+l,f=f>>>0,b||Ce(this,l,f,4,4294967295,0),this[f]=l>>>24,this[f+1]=l>>>16,this[f+2]=l>>>8,this[f+3]=l&255,f+4};function vl(p,l,f,b,A){Rl(l,b,A,p,f,7);let T=Number(l&BigInt(4294967295));p[f++]=T,T=T>>8,p[f++]=T,T=T>>8,p[f++]=T,T=T>>8,p[f++]=T;let O=Number(l>>BigInt(32)&BigInt(4294967295));return p[f++]=O,O=O>>8,p[f++]=O,O=O>>8,p[f++]=O,O=O>>8,p[f++]=O,f}function El(p,l,f,b,A){Rl(l,b,A,p,f,7);let T=Number(l&BigInt(4294967295));p[f+7]=T,T=T>>8,p[f+6]=T,T=T>>8,p[f+5]=T,T=T>>8,p[f+4]=T;let O=Number(l>>BigInt(32)&BigInt(4294967295));return p[f+3]=O,O=O>>8,p[f+2]=O,O=O>>8,p[f+1]=O,O=O>>8,p[f]=O,f+8}s.prototype.writeBigUInt64LE=xt(function(l,f=0){return vl(this,l,f,BigInt(0),BigInt("0xffffffffffffffff"))}),s.prototype.writeBigUInt64BE=xt(function(l,f=0){return El(this,l,f,BigInt(0),BigInt("0xffffffffffffffff"))}),s.prototype.writeIntLE=function(l,f,b,A){if(l=+l,f=f>>>0,!A){let se=Math.pow(2,8*b-1);Ce(this,l,f,b,se-1,-se);}let T=0,O=1,$=0;for(this[f]=l&255;++T>0)-$&255;return f+b},s.prototype.writeIntBE=function(l,f,b,A){if(l=+l,f=f>>>0,!A){let se=Math.pow(2,8*b-1);Ce(this,l,f,b,se-1,-se);}let T=b-1,O=1,$=0;for(this[f+T]=l&255;--T>=0&&(O*=256);)l<0&&$===0&&this[f+T+1]!==0&&($=1),this[f+T]=(l/O>>0)-$&255;return f+b},s.prototype.writeInt8=function(l,f,b){return l=+l,f=f>>>0,b||Ce(this,l,f,1,127,-128),l<0&&(l=255+l+1),this[f]=l&255,f+1},s.prototype.writeInt16LE=function(l,f,b){return l=+l,f=f>>>0,b||Ce(this,l,f,2,32767,-32768),this[f]=l&255,this[f+1]=l>>>8,f+2},s.prototype.writeInt16BE=function(l,f,b){return l=+l,f=f>>>0,b||Ce(this,l,f,2,32767,-32768),this[f]=l>>>8,this[f+1]=l&255,f+2},s.prototype.writeInt32LE=function(l,f,b){return l=+l,f=f>>>0,b||Ce(this,l,f,4,2147483647,-2147483648),this[f]=l&255,this[f+1]=l>>>8,this[f+2]=l>>>16,this[f+3]=l>>>24,f+4},s.prototype.writeInt32BE=function(l,f,b){return l=+l,f=f>>>0,b||Ce(this,l,f,4,2147483647,-2147483648),l<0&&(l=4294967295+l+1),this[f]=l>>>24,this[f+1]=l>>>16,this[f+2]=l>>>8,this[f+3]=l&255,f+4},s.prototype.writeBigInt64LE=xt(function(l,f=0){return vl(this,l,f,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))}),s.prototype.writeBigInt64BE=xt(function(l,f=0){return El(this,l,f,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))});function Sl(p,l,f,b,A,T){if(f+b>p.length)throw new RangeError("Index out of range");if(f<0)throw new RangeError("Index out of range")}function Al(p,l,f,b,A){return l=+l,f=f>>>0,A||Sl(p,l,f,4),e.write(p,l,f,b,23,4),f+4}s.prototype.writeFloatLE=function(l,f,b){return Al(this,l,f,!0,b)},s.prototype.writeFloatBE=function(l,f,b){return Al(this,l,f,!1,b)};function Il(p,l,f,b,A){return l=+l,f=f>>>0,A||Sl(p,l,f,8),e.write(p,l,f,b,52,8),f+8}s.prototype.writeDoubleLE=function(l,f,b){return Il(this,l,f,!0,b)},s.prototype.writeDoubleBE=function(l,f,b){return Il(this,l,f,!1,b)},s.prototype.copy=function(l,f,b,A){if(!s.isBuffer(l))throw new TypeError("argument should be a Buffer");if(b||(b=0),!A&&A!==0&&(A=this.length),f>=l.length&&(f=l.length),f||(f=0),A>0&&A=this.length)throw new RangeError("Index out of range");if(A<0)throw new RangeError("sourceEnd out of bounds");A>this.length&&(A=this.length),l.length-f>>0,b=b===void 0?this.length:b>>>0,l||(l=0);let T;if(typeof l=="number")for(T=f;T2**32?A=Tl(String(f)):typeof f=="bigint"&&(A=String(f),(f>BigInt(2)**BigInt(32)||f<-(BigInt(2)**BigInt(32)))&&(A=Tl(A)),A+="n"),b+=` It must be ${l}. Received ${A}`,b},RangeError);function Tl(p){let l="",f=p.length,b=p[0]==="-"?1:0;for(;f>=b+4;f-=3)l=`_${p.slice(f-3,f)}${l}`;return `${p.slice(0,f)}${l}`}function Dg(p,l,f){kr(l,"offset"),(p[l]===void 0||p[l+f]===void 0)&&li(l,p.length-(f+1));}function Rl(p,l,f,b,A,T){if(p>f||p3?l===0||l===BigInt(0)?$=`>= 0${O} and < 2${O} ** ${(T+1)*8}${O}`:$=`>= -(2${O} ** ${(T+1)*8-1}${O}) and < 2 ** ${(T+1)*8-1}${O}`:$=`>= ${l}${O} and <= ${f}${O}`,new Or.ERR_OUT_OF_RANGE("value",$,p)}Dg(b,A,T);}function kr(p,l){if(typeof p!="number")throw new Or.ERR_INVALID_ARG_TYPE(l,"number",p)}function li(p,l,f){throw Math.floor(p)!==p?(kr(p,f),new Or.ERR_OUT_OF_RANGE(f||"offset","an integer",p)):l<0?new Or.ERR_BUFFER_OUT_OF_BOUNDS:new Or.ERR_OUT_OF_RANGE(f||"offset",`>= ${f?1:0} and <= ${l}`,p)}let jg=/[^+/0-9A-Za-z-_]/g;function Fg(p){if(p=p.split("=")[0],p=p.trim().replace(jg,""),p.length<2)return "";for(;p.length%4!==0;)p=p+"=";return p}function cs(p,l){l=l||1/0;let f,b=p.length,A=null,T=[];for(let O=0;O55295&&f<57344){if(!A){if(f>56319){(l-=3)>-1&&T.push(239,191,189);continue}else if(O+1===b){(l-=3)>-1&&T.push(239,191,189);continue}A=f;continue}if(f<56320){(l-=3)>-1&&T.push(239,191,189),A=f;continue}f=(A-55296<<10|f-56320)+65536;}else A&&(l-=3)>-1&&T.push(239,191,189);if(A=null,f<128){if((l-=1)<0)break;T.push(f);}else if(f<2048){if((l-=2)<0)break;T.push(f>>6|192,f&63|128);}else if(f<65536){if((l-=3)<0)break;T.push(f>>12|224,f>>6&63|128,f&63|128);}else if(f<1114112){if((l-=4)<0)break;T.push(f>>18|240,f>>12&63|128,f>>6&63|128,f&63|128);}else throw new Error("Invalid code point")}return T}function Wg(p){let l=[];for(let f=0;f>8,A=f%256,T.push(A),T.push(b);return T}function Cl(p){return t.toByteArray(Fg(p))}function qi(p,l,f,b){let A;for(A=0;A=l.length||A>=p.length);++A)l[A+f]=p[A];return A}function Ye(p,l){return p instanceof l||p!=null&&p.constructor!=null&&p.constructor.name!=null&&p.constructor.name===l.name}function hs(p){return p!==p}let Hg=function(){let p="0123456789abcdef",l=new Array(256);for(let f=0;f<16;++f){let b=f*16;for(let A=0;A<16;++A)l[b+A]=p[f]+p[A];}return l}();function xt(p){return typeof BigInt>"u"?Vg:p}function Vg(){throw new Error("BigInt not supported")}return Jt}var ui,Vu,Wi,zu,Jt,Ku,Lt,x,ey,ty,ye=we(()=>{v();m();_();ui={},Vu=!1;Wi={},zu=!1;Jt={},Ku=!1;Lt=Zg();Lt.Buffer;Lt.SlowBuffer;Lt.INSPECT_MAX_BYTES;Lt.kMaxLength;x=Lt.Buffer,ey=Lt.INSPECT_MAX_BYTES,ty=Lt.kMaxLength;});var v=we(()=>{ye();});var Gu=M(ws=>{v();m();_();Object.defineProperty(ws,"__esModule",{value:!0});var bs=class{constructor(e){this.aliasToTopic={},this.max=e;}put(e,r){return r===0||r>this.max?!1:(this.aliasToTopic[r]=e,this.length=Object.keys(this.aliasToTopic).length,!0)}getTopicByAlias(e){return this.aliasToTopic[e]}clear(){this.aliasToTopic={};}};ws.default=bs;});var ce=M((PA,Qu)=>{v();m();_();Qu.exports={ArrayIsArray(t){return Array.isArray(t)},ArrayPrototypeIncludes(t,e){return t.includes(e)},ArrayPrototypeIndexOf(t,e){return t.indexOf(e)},ArrayPrototypeJoin(t,e){return t.join(e)},ArrayPrototypeMap(t,e){return t.map(e)},ArrayPrototypePop(t,e){return t.pop(e)},ArrayPrototypePush(t,e){return t.push(e)},ArrayPrototypeSlice(t,e,r){return t.slice(e,r)},Error,FunctionPrototypeCall(t,e,...r){return t.call(e,...r)},FunctionPrototypeSymbolHasInstance(t,e){return Function.prototype[Symbol.hasInstance].call(t,e)},MathFloor:Math.floor,Number,NumberIsInteger:Number.isInteger,NumberIsNaN:Number.isNaN,NumberMAX_SAFE_INTEGER:Number.MAX_SAFE_INTEGER,NumberMIN_SAFE_INTEGER:Number.MIN_SAFE_INTEGER,NumberParseInt:Number.parseInt,ObjectDefineProperties(t,e){return Object.defineProperties(t,e)},ObjectDefineProperty(t,e,r){return Object.defineProperty(t,e,r)},ObjectGetOwnPropertyDescriptor(t,e){return Object.getOwnPropertyDescriptor(t,e)},ObjectKeys(t){return Object.keys(t)},ObjectSetPrototypeOf(t,e){return Object.setPrototypeOf(t,e)},Promise,PromisePrototypeCatch(t,e){return t.catch(e)},PromisePrototypeThen(t,e,r){return t.then(e,r)},PromiseReject(t){return Promise.reject(t)},ReflectApply:Reflect.apply,RegExpPrototypeTest(t,e){return t.test(e)},SafeSet:Set,String,StringPrototypeSlice(t,e,r){return t.slice(e,r)},StringPrototypeToLowerCase(t){return t.toLowerCase()},StringPrototypeToUpperCase(t){return t.toUpperCase()},StringPrototypeTrim(t){return t.trim()},Symbol,SymbolFor:Symbol.for,SymbolAsyncIterator:Symbol.asyncIterator,SymbolHasInstance:Symbol.hasInstance,SymbolIterator:Symbol.iterator,TypedArrayPrototypeSet(t,e,r){return t.set(e,r)},Uint8Array};});var Je=M((jA,ms)=>{v();m();_();var ry=(ye(),X(_e)),iy=Object.getPrototypeOf(async function(){}).constructor,Yu=globalThis.Blob||ry.Blob,ny=typeof Yu<"u"?function(e){return e instanceof Yu}:function(e){return !1},_s=class extends Error{constructor(e){if(!Array.isArray(e))throw new TypeError(`Expected input to be an Array, got ${typeof e}`);let r="";for(let i=0;i{t=i,e=n;}),resolve:t,reject:e}},promisify(t){return new Promise((e,r)=>{t((i,...n)=>i?r(i):e(...n));})},debuglog(){return function(){}},format(t,...e){return t.replace(/%([sdifj])/g,function(...[r,i]){let n=e.shift();return i==="f"?n.toFixed(6):i==="j"?JSON.stringify(n):i==="s"&&typeof n=="object"?`${n.constructor!==Object?n.constructor.name:""} {}`.trim():n.toString()})},inspect(t){switch(typeof t){case"string":if(t.includes("'"))if(t.includes('"')){if(!t.includes("`")&&!t.includes("${"))return `\`${t}\``}else return `"${t}"`;return `'${t}'`;case"number":return isNaN(t)?"NaN":Object.is(t,-0)?String(t):t;case"bigint":return `${String(t)}n`;case"boolean":case"undefined":return String(t);case"object":return "{}"}},types:{isAsyncFunction(t){return t instanceof iy},isArrayBufferView(t){return ArrayBuffer.isView(t)}},isBlob:ny};ms.exports.promisify.custom=Symbol.for("nodejs.util.promisify.custom");});var Hi=M((YA,$i)=>{v();m();_();var{AbortController:Ju,AbortSignal:sy}=typeof self<"u"?self:typeof window<"u"?window:void 0;$i.exports=Ju;$i.exports.AbortSignal=sy;$i.exports.default=Ju;});var Se=M((oI,ef)=>{v();m();_();var{format:oy,inspect:Vi,AggregateError:ay}=Je(),ly=globalThis.AggregateError||ay,uy=Symbol("kIsNodeError"),fy=["string","function","number","object","Function","Object","boolean","bigint","symbol"],cy=/^([A-Z][a-z0-9]*)+$/,hy="__node_internal_",zi={};function Xt(t,e){if(!t)throw new zi.ERR_INTERNAL_ASSERTION(e)}function Xu(t){let e="",r=t.length,i=t[0]==="-"?1:0;for(;r>=i+4;r-=3)e=`_${t.slice(r-3,r)}${e}`;return `${t.slice(0,r)}${e}`}function dy(t,e,r){if(typeof e=="function")return Xt(e.length<=r.length,`Code: ${t}; The provided arguments length (${r.length}) does not match the required ones (${e.length}).`),e(...r);let i=(e.match(/%[dfijoOs]/g)||[]).length;return Xt(i===r.length,`Code: ${t}; The provided arguments length (${r.length}) does not match the required ones (${i}).`),r.length===0?e:oy(e,...r)}function me(t,e,r){r||(r=Error);class i extends r{constructor(...o){super(dy(t,e,o));}toString(){return `${this.name} [${t}]: ${this.message}`}}Object.defineProperties(i.prototype,{name:{value:r.name,writable:!0,enumerable:!1,configurable:!0},toString:{value(){return `${this.name} [${t}]: ${this.message}`},writable:!0,enumerable:!1,configurable:!0}}),i.prototype.code=t,i.prototype[uy]=!0,zi[t]=i;}function Zu(t){let e=hy+t.name;return Object.defineProperty(t,"name",{value:e}),t}function py(t,e){if(t&&e&&t!==e){if(Array.isArray(e.errors))return e.errors.push(t),e;let r=new ly([e,t],e.message);return r.code=e.code,r}return t||e}var vs=class extends Error{constructor(e="The operation was aborted",r=void 0){if(r!==void 0&&typeof r!="object")throw new zi.ERR_INVALID_ARG_TYPE("options","Object",r);super(e,r),this.code="ABORT_ERR",this.name="AbortError";}};me("ERR_ASSERTION","%s",Error);me("ERR_INVALID_ARG_TYPE",(t,e,r)=>{Xt(typeof t=="string","'name' must be a string"),Array.isArray(e)||(e=[e]);let i="The ";t.endsWith(" argument")?i+=`${t} `:i+=`"${t}" ${t.includes(".")?"property":"argument"} `,i+="must be ";let n=[],o=[],s=[];for(let u of e)Xt(typeof u=="string","All expected entries have to be of type string"),fy.includes(u)?n.push(u.toLowerCase()):cy.test(u)?o.push(u):(Xt(u!=="object",'The value "object" should be written as "Object"'),s.push(u));if(o.length>0){let u=n.indexOf("object");u!==-1&&(n.splice(n,u,1),o.push("Object"));}if(n.length>0){switch(n.length){case 1:i+=`of type ${n[0]}`;break;case 2:i+=`one of type ${n[0]} or ${n[1]}`;break;default:{let u=n.pop();i+=`one of type ${n.join(", ")}, or ${u}`;}}(o.length>0||s.length>0)&&(i+=" or ");}if(o.length>0){switch(o.length){case 1:i+=`an instance of ${o[0]}`;break;case 2:i+=`an instance of ${o[0]} or ${o[1]}`;break;default:{let u=o.pop();i+=`an instance of ${o.join(", ")}, or ${u}`;}}s.length>0&&(i+=" or ");}switch(s.length){case 0:break;case 1:s[0].toLowerCase()!==s[0]&&(i+="an "),i+=`${s[0]}`;break;case 2:i+=`one of ${s[0]} or ${s[1]}`;break;default:{let u=s.pop();i+=`one of ${s.join(", ")}, or ${u}`;}}if(r==null)i+=`. Received ${r}`;else if(typeof r=="function"&&r.name)i+=`. Received function ${r.name}`;else if(typeof r=="object"){var a;if((a=r.constructor)!==null&&a!==void 0&&a.name)i+=`. Received an instance of ${r.constructor.name}`;else {let u=Vi(r,{depth:-1});i+=`. Received ${u}`;}}else {let u=Vi(r,{colors:!1});u.length>25&&(u=`${u.slice(0,25)}...`),i+=`. Received type ${typeof r} (${u})`;}return i},TypeError);me("ERR_INVALID_ARG_VALUE",(t,e,r="is invalid")=>{let i=Vi(e);return i.length>128&&(i=i.slice(0,128)+"..."),`The ${t.includes(".")?"property":"argument"} '${t}' ${r}. Received ${i}`},TypeError);me("ERR_INVALID_RETURN_VALUE",(t,e,r)=>{var i;let n=r!=null&&(i=r.constructor)!==null&&i!==void 0&&i.name?`instance of ${r.constructor.name}`:`type ${typeof r}`;return `Expected ${t} to be returned from the "${e}" function but got ${n}.`},TypeError);me("ERR_MISSING_ARGS",(...t)=>{Xt(t.length>0,"At least one arg needs to be specified");let e,r=t.length;switch(t=(Array.isArray(t)?t:[t]).map(i=>`"${i}"`).join(" or "),r){case 1:e+=`The ${t[0]} argument`;break;case 2:e+=`The ${t[0]} and ${t[1]} arguments`;break;default:{let i=t.pop();e+=`The ${t.join(", ")}, and ${i} arguments`;}break}return `${e} must be specified`},TypeError);me("ERR_OUT_OF_RANGE",(t,e,r)=>{Xt(e,'Missing "range" argument');let i;return Number.isInteger(r)&&Math.abs(r)>2**32?i=Xu(String(r)):typeof r=="bigint"?(i=String(r),(r>2n**32n||r<-(2n**32n))&&(i=Xu(i)),i+="n"):i=Vi(r),`The value of "${t}" is out of range. It must be ${e}. Received ${i}`},RangeError);me("ERR_MULTIPLE_CALLBACK","Callback called multiple times",Error);me("ERR_METHOD_NOT_IMPLEMENTED","The %s method is not implemented",Error);me("ERR_STREAM_ALREADY_FINISHED","Cannot call %s after a stream was finished",Error);me("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable",Error);me("ERR_STREAM_DESTROYED","Cannot call %s after a stream was destroyed",Error);me("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError);me("ERR_STREAM_PREMATURE_CLOSE","Premature close",Error);me("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF",Error);me("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event",Error);me("ERR_STREAM_WRITE_AFTER_END","write after end",Error);me("ERR_UNKNOWN_ENCODING","Unknown encoding: %s",TypeError);ef.exports={AbortError:vs,aggregateTwoErrors:Zu(py),hideStackFrames:Zu,codes:zi};});var fi=M((yI,ff)=>{v();m();_();var{ArrayIsArray:Ss,ArrayPrototypeIncludes:sf,ArrayPrototypeJoin:of,ArrayPrototypeMap:gy,NumberIsInteger:As,NumberIsNaN:yy,NumberMAX_SAFE_INTEGER:by,NumberMIN_SAFE_INTEGER:wy,NumberParseInt:_y,ObjectPrototypeHasOwnProperty:my,RegExpPrototypeExec:af,String:vy,StringPrototypeToUpperCase:Ey,StringPrototypeTrim:Sy}=ce(),{hideStackFrames:Ue,codes:{ERR_SOCKET_BAD_PORT:Ay,ERR_INVALID_ARG_TYPE:Ae,ERR_INVALID_ARG_VALUE:Mr,ERR_OUT_OF_RANGE:Zt,ERR_UNKNOWN_SIGNAL:tf}}=Se(),{normalizeEncoding:Iy}=Je(),{isAsyncFunction:Ty,isArrayBufferView:Ry}=Je().types,rf={};function Cy(t){return t===(t|0)}function By(t){return t===t>>>0}var Py=/^[0-7]+$/,Oy="must be a 32-bit unsigned integer or an octal string";function ky(t,e,r){if(typeof t>"u"&&(t=r),typeof t=="string"){if(af(Py,t)===null)throw new Mr(e,t,Oy);t=_y(t,8);}return lf(t,e),t}var xy=Ue((t,e,r=wy,i=by)=>{if(typeof t!="number")throw new Ae(e,"number",t);if(!As(t))throw new Zt(e,"an integer",t);if(ti)throw new Zt(e,`>= ${r} && <= ${i}`,t)}),My=Ue((t,e,r=-2147483648,i=2147483647)=>{if(typeof t!="number")throw new Ae(e,"number",t);if(!As(t))throw new Zt(e,"an integer",t);if(ti)throw new Zt(e,`>= ${r} && <= ${i}`,t)}),lf=Ue((t,e,r=!1)=>{if(typeof t!="number")throw new Ae(e,"number",t);if(!As(t))throw new Zt(e,"an integer",t);let i=r?1:0,n=4294967295;if(tn)throw new Zt(e,`>= ${i} && <= ${n}`,t)});function Is(t,e){if(typeof t!="string")throw new Ae(e,"string",t)}function Ly(t,e,r=void 0,i){if(typeof t!="number")throw new Ae(e,"number",t);if(r!=null&&ti||(r!=null||i!=null)&&yy(t))throw new Zt(e,`${r!=null?`>= ${r}`:""}${r!=null&&i!=null?" && ":""}${i!=null?`<= ${i}`:""}`,t)}var Uy=Ue((t,e,r)=>{if(!sf(r,t)){let n="must be one of: "+of(gy(r,o=>typeof o=="string"?`'${o}'`:vy(o)),", ");throw new Mr(e,t,n)}});function uf(t,e){if(typeof t!="boolean")throw new Ae(e,"boolean",t)}function Es(t,e,r){return t==null||!my(t,e)?r:t[e]}var Ny=Ue((t,e,r=null)=>{let i=Es(r,"allowArray",!1),n=Es(r,"allowFunction",!1);if(!Es(r,"nullable",!1)&&t===null||!i&&Ss(t)||typeof t!="object"&&(!n||typeof t!="function"))throw new Ae(e,"Object",t)}),qy=Ue((t,e)=>{if(t!=null&&typeof t!="object"&&typeof t!="function")throw new Ae(e,"a dictionary",t)}),Ts=Ue((t,e,r=0)=>{if(!Ss(t))throw new Ae(e,"Array",t);if(t.length{if(!Ry(t))throw new Ae(e,["Buffer","TypedArray","DataView"],t)});function $y(t,e){let r=Iy(e),i=t.length;if(r==="hex"&&i%2!==0)throw new Mr("encoding",e,`is invalid for data of length ${i}`)}function Hy(t,e="Port",r=!0){if(typeof t!="number"&&typeof t!="string"||typeof t=="string"&&Sy(t).length===0||+t!==+t>>>0||t>65535||t===0&&!r)throw new Ay(e,t,r);return t|0}var Vy=Ue((t,e)=>{if(t!==void 0&&(t===null||typeof t!="object"||!("aborted"in t)))throw new Ae(e,"AbortSignal",t)}),zy=Ue((t,e)=>{if(typeof t!="function")throw new Ae(e,"Function",t)}),Ky=Ue((t,e)=>{if(typeof t!="function"||Ty(t))throw new Ae(e,"Function",t)}),Gy=Ue((t,e)=>{if(t!==void 0)throw new Ae(e,"undefined",t)});function Qy(t,e,r){if(!sf(r,t))throw new Ae(e,`('${of(r,"|")}')`,t)}var Yy=/^(?:<[^>]*>)(?:\s*;\s*[^;"\s]+(?:=(")?[^;"\s]*\1)?)*$/;function nf(t,e){if(typeof t>"u"||!af(Yy,t))throw new Mr(e,t,'must be an array or string of format "; rel=preload; as=style"')}function Jy(t){if(typeof t=="string")return nf(t,"hints"),t;if(Ss(t)){let e=t.length,r="";if(e===0)return r;for(let i=0;i; rel=preload; as=style"')}ff.exports={isInt32:Cy,isUint32:By,parseFileMode:ky,validateArray:Ts,validateStringArray:Dy,validateBooleanArray:jy,validateBoolean:uf,validateBuffer:Wy,validateDictionary:qy,validateEncoding:$y,validateFunction:zy,validateInt32:My,validateInteger:xy,validateNumber:Ly,validateObject:Ny,validateOneOf:Uy,validatePlainFunction:Ky,validatePort:Hy,validateSignalName:Fy,validateString:Is,validateUint32:lf,validateUndefined:Gy,validateUnion:Qy,validateAbortSignal:Vy,validateLinkHeaderValue:Jy};});var Ut=M((TI,pf)=>{v();m();_();var ae=pf.exports={},Xe,Ze;function Rs(){throw new Error("setTimeout has not been defined")}function Cs(){throw new Error("clearTimeout has not been defined")}(function(){try{typeof setTimeout=="function"?Xe=setTimeout:Xe=Rs;}catch{Xe=Rs;}try{typeof clearTimeout=="function"?Ze=clearTimeout:Ze=Cs;}catch{Ze=Cs;}})();function cf(t){if(Xe===setTimeout)return setTimeout(t,0);if((Xe===Rs||!Xe)&&setTimeout)return Xe=setTimeout,setTimeout(t,0);try{return Xe(t,0)}catch{try{return Xe.call(null,t,0)}catch{return Xe.call(this,t,0)}}}function Xy(t){if(Ze===clearTimeout)return clearTimeout(t);if((Ze===Cs||!Ze)&&clearTimeout)return Ze=clearTimeout,clearTimeout(t);try{return Ze(t)}catch{try{return Ze.call(null,t)}catch{return Ze.call(this,t)}}}var wt=[],Lr=!1,er,Ki=-1;function Zy(){!Lr||!er||(Lr=!1,er.length?wt=er.concat(wt):Ki=-1,wt.length&&hf());}function hf(){if(!Lr){var t=cf(Zy);Lr=!0;for(var e=wt.length;e;){for(er=wt,wt=[];++Ki1)for(var r=1;r{v();m();_();var{Symbol:Gi,SymbolAsyncIterator:gf,SymbolIterator:yf,SymbolFor:bf}=ce(),wf=Gi("kDestroyed"),_f=Gi("kIsErrored"),Bs=Gi("kIsReadable"),mf=Gi("kIsDisturbed"),eb=bf("nodejs.webstream.isClosedPromise"),tb=bf("nodejs.webstream.controllerErrorFunction");function Qi(t,e=!1){var r;return !!(t&&typeof t.pipe=="function"&&typeof t.on=="function"&&(!e||typeof t.pause=="function"&&typeof t.resume=="function")&&(!t._writableState||((r=t._readableState)===null||r===void 0?void 0:r.readable)!==!1)&&(!t._writableState||t._readableState))}function Yi(t){var e;return !!(t&&typeof t.write=="function"&&typeof t.on=="function"&&(!t._readableState||((e=t._writableState)===null||e===void 0?void 0:e.writable)!==!1))}function rb(t){return !!(t&&typeof t.pipe=="function"&&t._readableState&&typeof t.on=="function"&&typeof t.write=="function")}function et(t){return t&&(t._readableState||t._writableState||typeof t.write=="function"&&typeof t.on=="function"||typeof t.pipe=="function"&&typeof t.on=="function")}function vf(t){return !!(t&&!et(t)&&typeof t.pipeThrough=="function"&&typeof t.getReader=="function"&&typeof t.cancel=="function")}function Ef(t){return !!(t&&!et(t)&&typeof t.getWriter=="function"&&typeof t.abort=="function")}function Sf(t){return !!(t&&!et(t)&&typeof t.readable=="object"&&typeof t.writable=="object")}function ib(t){return vf(t)||Ef(t)||Sf(t)}function nb(t,e){return t==null?!1:e===!0?typeof t[gf]=="function":e===!1?typeof t[yf]=="function":typeof t[gf]=="function"||typeof t[yf]=="function"}function Ji(t){if(!et(t))return null;let e=t._writableState,r=t._readableState,i=e||r;return !!(t.destroyed||t[wf]||i!=null&&i.destroyed)}function Af(t){if(!Yi(t))return null;if(t.writableEnded===!0)return !0;let e=t._writableState;return e!=null&&e.errored?!1:typeof e?.ended!="boolean"?null:e.ended}function sb(t,e){if(!Yi(t))return null;if(t.writableFinished===!0)return !0;let r=t._writableState;return r!=null&&r.errored?!1:typeof r?.finished!="boolean"?null:!!(r.finished||e===!1&&r.ended===!0&&r.length===0)}function ob(t){if(!Qi(t))return null;if(t.readableEnded===!0)return !0;let e=t._readableState;return !e||e.errored?!1:typeof e?.ended!="boolean"?null:e.ended}function If(t,e){if(!Qi(t))return null;let r=t._readableState;return r!=null&&r.errored?!1:typeof r?.endEmitted!="boolean"?null:!!(r.endEmitted||e===!1&&r.ended===!0&&r.length===0)}function Tf(t){return t&&t[Bs]!=null?t[Bs]:typeof t?.readable!="boolean"?null:Ji(t)?!1:Qi(t)&&t.readable&&!If(t)}function Rf(t){return typeof t?.writable!="boolean"?null:Ji(t)?!1:Yi(t)&&t.writable&&!Af(t)}function ab(t,e){return et(t)?Ji(t)?!0:!(e?.readable!==!1&&Tf(t)||e?.writable!==!1&&Rf(t)):null}function lb(t){var e,r;return et(t)?t.writableErrored?t.writableErrored:(e=(r=t._writableState)===null||r===void 0?void 0:r.errored)!==null&&e!==void 0?e:null:null}function ub(t){var e,r;return et(t)?t.readableErrored?t.readableErrored:(e=(r=t._readableState)===null||r===void 0?void 0:r.errored)!==null&&e!==void 0?e:null:null}function fb(t){if(!et(t))return null;if(typeof t.closed=="boolean")return t.closed;let e=t._writableState,r=t._readableState;return typeof e?.closed=="boolean"||typeof r?.closed=="boolean"?e?.closed||r?.closed:typeof t._closed=="boolean"&&Cf(t)?t._closed:null}function Cf(t){return typeof t._closed=="boolean"&&typeof t._defaultKeepAlive=="boolean"&&typeof t._removedConnection=="boolean"&&typeof t._removedContLen=="boolean"}function Bf(t){return typeof t._sent100=="boolean"&&Cf(t)}function cb(t){var e;return typeof t._consuming=="boolean"&&typeof t._dumped=="boolean"&&((e=t.req)===null||e===void 0?void 0:e.upgradeOrConnect)===void 0}function hb(t){if(!et(t))return null;let e=t._writableState,r=t._readableState,i=e||r;return !i&&Bf(t)||!!(i&&i.autoDestroy&&i.emitClose&&i.closed===!1)}function db(t){var e;return !!(t&&((e=t[mf])!==null&&e!==void 0?e:t.readableDidRead||t.readableAborted))}function pb(t){var e,r,i,n,o,s,a,u,c,h;return !!(t&&((e=(r=(i=(n=(o=(s=t[_f])!==null&&s!==void 0?s:t.readableErrored)!==null&&o!==void 0?o:t.writableErrored)!==null&&n!==void 0?n:(a=t._readableState)===null||a===void 0?void 0:a.errorEmitted)!==null&&i!==void 0?i:(u=t._writableState)===null||u===void 0?void 0:u.errorEmitted)!==null&&r!==void 0?r:(c=t._readableState)===null||c===void 0?void 0:c.errored)!==null&&e!==void 0?e:!((h=t._writableState)===null||h===void 0)&&h.errored))}Pf.exports={kDestroyed:wf,isDisturbed:db,kIsDisturbed:mf,isErrored:pb,kIsErrored:_f,isReadable:Tf,kIsReadable:Bs,kIsClosedPromise:eb,kControllerErrorFunction:tb,isClosed:fb,isDestroyed:Ji,isDuplexNodeStream:rb,isFinished:ab,isIterable:nb,isReadableNodeStream:Qi,isReadableStream:vf,isReadableEnded:ob,isReadableFinished:If,isReadableErrored:ub,isNodeStream:et,isWebStream:ib,isWritable:Rf,isWritableNodeStream:Yi,isWritableStream:Ef,isWritableEnded:Af,isWritableFinished:sb,isWritableErrored:lb,isServerRequest:cb,isServerResponse:Bf,willEmitClose:hb,isTransformStream:Sf};});var mt=M((zI,Ms)=>{v();m();_();var Nt=Ut(),{AbortError:Df,codes:gb}=Se(),{ERR_INVALID_ARG_TYPE:yb,ERR_STREAM_PREMATURE_CLOSE:Of}=gb,{kEmptyObject:Os,once:ks}=Je(),{validateAbortSignal:bb,validateFunction:wb,validateObject:_b,validateBoolean:mb}=fi(),{Promise:vb,PromisePrototypeThen:Eb}=ce(),{isClosed:Sb,isReadable:kf,isReadableNodeStream:Ps,isReadableStream:Ab,isReadableFinished:xf,isReadableErrored:Mf,isWritable:Lf,isWritableNodeStream:Uf,isWritableStream:Ib,isWritableFinished:Nf,isWritableErrored:qf,isNodeStream:Tb,willEmitClose:Rb,kIsClosedPromise:Cb}=tt();function Bb(t){return t.setHeader&&typeof t.abort=="function"}var xs=()=>{};function jf(t,e,r){var i,n;if(arguments.length===2?(r=e,e=Os):e==null?e=Os:_b(e,"options"),wb(r,"callback"),bb(e.signal,"options.signal"),r=ks(r),Ab(t)||Ib(t))return Pb(t,e,r);if(!Tb(t))throw new yb("stream",["ReadableStream","WritableStream","Stream"],t);let o=(i=e.readable)!==null&&i!==void 0?i:Ps(t),s=(n=e.writable)!==null&&n!==void 0?n:Uf(t),a=t._writableState,u=t._readableState,c=()=>{t.writable||g();},h=Rb(t)&&Ps(t)===o&&Uf(t)===s,d=Nf(t,!1),g=()=>{d=!0,t.destroyed&&(h=!1),!(h&&(!t.readable||o))&&(!o||y)&&r.call(t);},y=xf(t,!1),w=()=>{y=!0,t.destroyed&&(h=!1),!(h&&(!t.writable||s))&&(!s||d)&&r.call(t);},E=N=>{r.call(t,N);},S=Sb(t),I=()=>{S=!0;let N=qf(t)||Mf(t);if(N&&typeof N!="boolean")return r.call(t,N);if(o&&!y&&Ps(t,!0)&&!xf(t,!1))return r.call(t,new Of);if(s&&!d&&!Nf(t,!1))return r.call(t,new Of);r.call(t);},C=()=>{S=!0;let N=qf(t)||Mf(t);if(N&&typeof N!="boolean")return r.call(t,N);r.call(t);},R=()=>{t.req.on("finish",g);};Bb(t)?(t.on("complete",g),h||t.on("abort",I),t.req?R():t.on("request",R)):s&&!a&&(t.on("end",c),t.on("close",c)),!h&&typeof t.aborted=="boolean"&&t.on("aborted",I),t.on("end",w),t.on("finish",g),e.error!==!1&&t.on("error",E),t.on("close",I),S?Nt.nextTick(I):a!=null&&a.errorEmitted||u!=null&&u.errorEmitted?h||Nt.nextTick(C):(!o&&(!h||kf(t))&&(d||Lf(t)===!1)||!s&&(!h||Lf(t))&&(y||kf(t)===!1)||u&&t.req&&t.aborted)&&Nt.nextTick(C);let U=()=>{r=xs,t.removeListener("aborted",I),t.removeListener("complete",g),t.removeListener("abort",I),t.removeListener("request",R),t.req&&t.req.removeListener("finish",g),t.removeListener("end",c),t.removeListener("close",c),t.removeListener("finish",g),t.removeListener("end",w),t.removeListener("error",E),t.removeListener("close",I);};if(e.signal&&!S){let N=()=>{let W=r;U(),W.call(t,new Df(void 0,{cause:e.signal.reason}));};if(e.signal.aborted)Nt.nextTick(N);else {let W=r;r=ks((...K)=>{e.signal.removeEventListener("abort",N),W.apply(t,K);}),e.signal.addEventListener("abort",N);}}return U}function Pb(t,e,r){let i=!1,n=xs;if(e.signal)if(n=()=>{i=!0,r.call(t,new Df(void 0,{cause:e.signal.reason}));},e.signal.aborted)Nt.nextTick(n);else {let s=r;r=ks((...a)=>{e.signal.removeEventListener("abort",n),s.apply(t,a);}),e.signal.addEventListener("abort",n);}let o=(...s)=>{i||Nt.nextTick(()=>r.apply(t,s));};return Eb(t[Cb].promise,o,o),xs}function Ob(t,e){var r;let i=!1;return e===null&&(e=Os),(r=e)!==null&&r!==void 0&&r.cleanup&&(mb(e.cleanup,"cleanup"),i=e.cleanup),new vb((n,o)=>{let s=jf(t,e,a=>{i&&s(),a?o(a):n();});})}Ms.exports=jf;Ms.exports.finished=Ob;});var tr=M((rT,Gf)=>{v();m();_();var rt=Ut(),{aggregateTwoErrors:kb,codes:{ERR_MULTIPLE_CALLBACK:xb},AbortError:Mb}=Se(),{Symbol:$f}=ce(),{kDestroyed:Lb,isDestroyed:Ub,isFinished:Nb,isServerRequest:qb}=tt(),Hf=$f("kDestroy"),Ls=$f("kConstruct");function Vf(t,e,r){t&&(t.stack,e&&!e.errored&&(e.errored=t),r&&!r.errored&&(r.errored=t));}function Db(t,e){let r=this._readableState,i=this._writableState,n=i||r;return i!=null&&i.destroyed||r!=null&&r.destroyed?(typeof e=="function"&&e(),this):(Vf(t,i,r),i&&(i.destroyed=!0),r&&(r.destroyed=!0),n.constructed?Ff(this,t,e):this.once(Hf,function(o){Ff(this,kb(o,t),e);}),this)}function Ff(t,e,r){let i=!1;function n(o){if(i)return;i=!0;let s=t._readableState,a=t._writableState;Vf(o,a,s),a&&(a.closed=!0),s&&(s.closed=!0),typeof r=="function"&&r(o),o?rt.nextTick(jb,t,o):rt.nextTick(zf,t);}try{t._destroy(e||null,n);}catch(o){n(o);}}function jb(t,e){Us(t,e),zf(t);}function zf(t){let e=t._readableState,r=t._writableState;r&&(r.closeEmitted=!0),e&&(e.closeEmitted=!0),(r!=null&&r.emitClose||e!=null&&e.emitClose)&&t.emit("close");}function Us(t,e){let r=t._readableState,i=t._writableState;i!=null&&i.errorEmitted||r!=null&&r.errorEmitted||(i&&(i.errorEmitted=!0),r&&(r.errorEmitted=!0),t.emit("error",e));}function Fb(){let t=this._readableState,e=this._writableState;t&&(t.constructed=!0,t.closed=!1,t.closeEmitted=!1,t.destroyed=!1,t.errored=null,t.errorEmitted=!1,t.reading=!1,t.ended=t.readable===!1,t.endEmitted=t.readable===!1),e&&(e.constructed=!0,e.destroyed=!1,e.closed=!1,e.closeEmitted=!1,e.errored=null,e.errorEmitted=!1,e.finalCalled=!1,e.prefinished=!1,e.ended=e.writable===!1,e.ending=e.writable===!1,e.finished=e.writable===!1);}function Ns(t,e,r){let i=t._readableState,n=t._writableState;if(n!=null&&n.destroyed||i!=null&&i.destroyed)return this;i!=null&&i.autoDestroy||n!=null&&n.autoDestroy?t.destroy(e):e&&(e.stack,n&&!n.errored&&(n.errored=e),i&&!i.errored&&(i.errored=e),r?rt.nextTick(Us,t,e):Us(t,e));}function Wb(t,e){if(typeof t._construct!="function")return;let r=t._readableState,i=t._writableState;r&&(r.constructed=!1),i&&(i.constructed=!1),t.once(Ls,e),!(t.listenerCount(Ls)>1)&&rt.nextTick($b,t);}function $b(t){let e=!1;function r(i){if(e){Ns(t,i??new xb);return}e=!0;let n=t._readableState,o=t._writableState,s=o||n;n&&(n.constructed=!0),o&&(o.constructed=!0),s.destroyed?t.emit(Hf,i):i?Ns(t,i,!0):rt.nextTick(Hb,t);}try{t._construct(i=>{rt.nextTick(r,i);});}catch(i){rt.nextTick(r,i);}}function Hb(t){t.emit(Ls);}function Wf(t){return t?.setHeader&&typeof t.abort=="function"}function Kf(t){t.emit("close");}function Vb(t,e){t.emit("error",e),rt.nextTick(Kf,t);}function zb(t,e){!t||Ub(t)||(!e&&!Nb(t)&&(e=new Mb),qb(t)?(t.socket=null,t.destroy(e)):Wf(t)?t.abort():Wf(t.req)?t.req.abort():typeof t.destroy=="function"?t.destroy(e):typeof t.close=="function"?t.close():e?rt.nextTick(Vb,t,e):rt.nextTick(Kf,t),t.destroyed||(t[Lb]=!0));}Gf.exports={construct:Wb,destroyer:zb,destroy:Db,undestroy:Fb,errorOrDestroy:Ns};});function Y(){Y.init.call(this);}function Xi(t){if(typeof t!="function")throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof t)}function nc(t){return t._maxListeners===void 0?Y.defaultMaxListeners:t._maxListeners}function Xf(t,e,r,i){var n,o,s,a;if(Xi(r),(o=t._events)===void 0?(o=t._events=Object.create(null),t._eventsCount=0):(o.newListener!==void 0&&(t.emit("newListener",e,r.listener?r.listener:r),o=t._events),s=o[e]),s===void 0)s=o[e]=r,++t._eventsCount;else if(typeof s=="function"?s=o[e]=i?[r,s]:[s,r]:i?s.unshift(r):s.push(r),(n=nc(t))>0&&s.length>n&&!s.warned){s.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(e)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=t,u.type=e,u.count=s.length,a=u,console&&console.warn&&console.warn(a);}return t}function Kb(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,arguments.length===0?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function Zf(t,e,r){var i={fired:!1,wrapFn:void 0,target:t,type:e,listener:r},n=Kb.bind(i);return n.listener=r,i.wrapFn=n,n}function ec(t,e,r){var i=t._events;if(i===void 0)return [];var n=i[e];return n===void 0?[]:typeof n=="function"?r?[n.listener||n]:[n]:r?function(o){for(var s=new Array(o.length),a=0;a{v();m();_();Ur=typeof Reflect=="object"?Reflect:null,Qf=Ur&&typeof Ur.apply=="function"?Ur.apply:function(t,e,r){return Function.prototype.apply.call(t,e,r)};ic=Ur&&typeof Ur.ownKeys=="function"?Ur.ownKeys:Object.getOwnPropertySymbols?function(t){return Object.getOwnPropertyNames(t).concat(Object.getOwnPropertySymbols(t))}:function(t){return Object.getOwnPropertyNames(t)};Yf=Number.isNaN||function(t){return t!=t};rc=Y,Y.EventEmitter=Y,Y.prototype._events=void 0,Y.prototype._eventsCount=0,Y.prototype._maxListeners=void 0;Jf=10;Object.defineProperty(Y,"defaultMaxListeners",{enumerable:!0,get:function(){return Jf},set:function(t){if(typeof t!="number"||t<0||Yf(t))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+t+".");Jf=t;}}),Y.init=function(){this._events!==void 0&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0;},Y.prototype.setMaxListeners=function(t){if(typeof t!="number"||t<0||Yf(t))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+t+".");return this._maxListeners=t,this},Y.prototype.getMaxListeners=function(){return nc(this)},Y.prototype.emit=function(t){for(var e=[],r=1;r0&&(o=e[0]),o instanceof Error)throw o;var s=new Error("Unhandled error."+(o?" ("+o.message+")":""));throw s.context=o,s}var a=n[t];if(a===void 0)return !1;if(typeof a=="function")Qf(a,this,e);else {var u=a.length,c=sc(a,u);for(r=0;r=0;o--)if(r[o]===e||r[o].listener===e){s=r[o].listener,n=o;break}if(n<0)return this;n===0?r.shift():function(a,u){for(;u+1=0;i--)this.removeListener(t,e[i]);return this},Y.prototype.listeners=function(t){return ec(this,t,!0)},Y.prototype.rawListeners=function(t){return ec(this,t,!1)},Y.listenerCount=function(t,e){return typeof t.listenerCount=="function"?t.listenerCount(e):tc.call(t,e)},Y.prototype.listenerCount=tc,Y.prototype.eventNames=function(){return this._eventsCount>0?ic(this._events):[]};Be=rc;Be.EventEmitter;Be.defaultMaxListeners;Be.init;Be.listenerCount;Be.EventEmitter;Be.defaultMaxListeners;Be.init;Be.listenerCount;});var rr={};Qt(rr,{EventEmitter:()=>Gb,default:()=>Be,defaultMaxListeners:()=>Qb,init:()=>Yb,listenerCount:()=>Jb,on:()=>Xb,once:()=>Zb});var Gb,Qb,Yb,Jb,Xb,Zb,ir=we(()=>{v();m();_();qs();qs();Be.once=function(t,e){return new Promise((r,i)=>{function n(...s){o!==void 0&&t.removeListener("error",o),r(s);}let o;e!=="error"&&(o=s=>{t.removeListener(name,n),i(s);},t.once("error",o)),t.once(e,n);})};Be.on=function(t,e){let r=[],i=[],n=null,o=!1,s={async next(){let c=r.shift();if(c)return createIterResult(c,!1);if(n){let h=Promise.reject(n);return n=null,h}return o?createIterResult(void 0,!0):new Promise((h,d)=>i.push({resolve:h,reject:d}))},async return(){t.removeListener(e,a),t.removeListener("error",u),o=!0;for(let c of i)c.resolve(createIterResult(void 0,!0));return createIterResult(void 0,!0)},throw(c){n=c,t.removeListener(e,a),t.removeListener("error",u);},[Symbol.asyncIterator](){return this}};return t.on(e,a),t.on("error",u),s;function a(...c){let h=i.shift();h?h.resolve(createIterResult(c,!1)):r.push(c);}function u(c){o=!0;let h=i.shift();h?h.reject(c):n=c,s.return();}};({EventEmitter:Gb,defaultMaxListeners:Qb,init:Yb,listenerCount:Jb,on:Xb,once:Zb}=Be);});var tn=M((xT,ac)=>{v();m();_();var{ArrayIsArray:ew,ObjectSetPrototypeOf:oc}=ce(),{EventEmitter:Zi}=(ir(),X(rr));function en(t){Zi.call(this,t);}oc(en.prototype,Zi.prototype);oc(en,Zi);en.prototype.pipe=function(t,e){let r=this;function i(h){t.writable&&t.write(h)===!1&&r.pause&&r.pause();}r.on("data",i);function n(){r.readable&&r.resume&&r.resume();}t.on("drain",n),!t._isStdio&&(!e||e.end!==!1)&&(r.on("end",s),r.on("close",a));let o=!1;function s(){o||(o=!0,t.end());}function a(){o||(o=!0,typeof t.destroy=="function"&&t.destroy());}function u(h){c(),Zi.listenerCount(this,"error")===0&&this.emit("error",h);}Ds(r,"error",u),Ds(t,"error",u);function c(){r.removeListener("data",i),t.removeListener("drain",n),r.removeListener("end",s),r.removeListener("close",a),r.removeListener("error",u),t.removeListener("error",u),r.removeListener("end",c),r.removeListener("close",c),t.removeListener("close",c);}return r.on("end",c),r.on("close",c),t.on("close",c),t.emit("pipe",r),t};function Ds(t,e,r){if(typeof t.prependListener=="function")return t.prependListener(e,r);!t._events||!t._events[e]?t.on(e,r):ew(t._events[e])?t._events[e].unshift(r):t._events[e]=[r,t._events[e]];}ac.exports={Stream:en,prependListener:Ds};});var ci=M(($T,rn)=>{v();m();_();var{AbortError:lc,codes:tw}=Se(),{isNodeStream:uc,isWebStream:rw,kControllerErrorFunction:iw}=tt(),nw=mt(),{ERR_INVALID_ARG_TYPE:fc}=tw,sw=(t,e)=>{if(typeof t!="object"||!("aborted"in t))throw new fc(e,"AbortSignal",t)};rn.exports.addAbortSignal=function(e,r){if(sw(e,"signal"),!uc(r)&&!rw(r))throw new fc("stream",["ReadableStream","WritableStream","Stream"],r);return rn.exports.addAbortSignalNoValidate(e,r)};rn.exports.addAbortSignalNoValidate=function(t,e){if(typeof t!="object"||!("aborted"in t))return e;let r=uc(e)?()=>{e.destroy(new lc(void 0,{cause:t.reason}));}:()=>{e[iw](new lc(void 0,{cause:t.reason}));};return t.aborted?r():(t.addEventListener("abort",r),nw(e,()=>t.removeEventListener("abort",r))),e};});var dc=M((e2,hc)=>{v();m();_();var{StringPrototypeSlice:cc,SymbolIterator:ow,TypedArrayPrototypeSet:nn,Uint8Array:aw}=ce(),{Buffer:js}=(ye(),X(_e)),{inspect:lw}=Je();hc.exports=class{constructor(){this.head=null,this.tail=null,this.length=0;}push(e){let r={data:e,next:null};this.length>0?this.tail.next=r:this.head=r,this.tail=r,++this.length;}unshift(e){let r={data:e,next:this.head};this.length===0&&(this.tail=r),this.head=r,++this.length;}shift(){if(this.length===0)return;let e=this.head.data;return this.length===1?this.head=this.tail=null:this.head=this.head.next,--this.length,e}clear(){this.head=this.tail=null,this.length=0;}join(e){if(this.length===0)return "";let r=this.head,i=""+r.data;for(;(r=r.next)!==null;)i+=e+r.data;return i}concat(e){if(this.length===0)return js.alloc(0);let r=js.allocUnsafe(e>>>0),i=this.head,n=0;for(;i;)nn(r,i.data,n),n+=i.data.length,i=i.next;return r}consume(e,r){let i=this.head.data;if(eo.length)r+=o,e-=o.length;else {e===o.length?(r+=o,++n,i.next?this.head=i.next:this.head=this.tail=null):(r+=cc(o,0,e),this.head=i,i.data=cc(o,e));break}++n;}while((i=i.next)!==null);return this.length-=n,r}_getBuffer(e){let r=js.allocUnsafe(e),i=e,n=this.head,o=0;do{let s=n.data;if(e>s.length)nn(r,s,i-e),e-=s.length;else {e===s.length?(nn(r,s,i-e),++o,n.next?this.head=n.next:this.head=this.tail=null):(nn(r,new aw(s.buffer,s.byteOffset,e),i-e),this.head=n,n.data=s.slice(e));break}++o;}while((n=n.next)!==null);return this.length-=o,r}[Symbol.for("nodejs.util.inspect.custom")](e,r){return lw(this,{...r,depth:0,customInspect:!1})}};});var sn=M((f2,gc)=>{v();m();_();var{MathFloor:uw,NumberIsInteger:fw}=ce(),{ERR_INVALID_ARG_VALUE:cw}=Se().codes;function hw(t,e,r){return t.highWaterMark!=null?t.highWaterMark:e?t[r]:null}function pc(t){return t?16:16*1024}function dw(t,e,r,i){let n=hw(e,i,r);if(n!=null){if(!fw(n)||n<0){let o=i?`options.${r}`:"options.highWaterMark";throw new cw(o,n)}return uw(n)}return pc(t.objectMode)}gc.exports={getHighWaterMark:dw,getDefaultHighWaterMark:pc};});function wc(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var r=t.indexOf("=");return r===-1&&(r=e),[r,r===e?0:4-r%4]}function pw(t,e,r){for(var i,n,o=[],s=e;s>18&63]+$e[n>>12&63]+$e[n>>6&63]+$e[63&n]);return o.join("")}function vt(t){if(t>2147483647)throw new RangeError('The value "'+t+'" is invalid for option "size"');var e=new Uint8Array(t);return Object.setPrototypeOf(e,k.prototype),e}function k(t,e,r){if(typeof t=="number"){if(typeof e=="string")throw new TypeError('The "string" argument must be of type string. Received type number');return Hs(t)}return Cc(t,e,r)}function Cc(t,e,r){if(typeof t=="string")return function(o,s){if(typeof s=="string"&&s!==""||(s="utf8"),!k.isEncoding(s))throw new TypeError("Unknown encoding: "+s);var a=0|Pc(o,s),u=vt(a),c=u.write(o,s);return c!==a&&(u=u.slice(0,c)),u}(t,e);if(ArrayBuffer.isView(t))return Fs(t);if(t==null)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t);if(Et(t,ArrayBuffer)||t&&Et(t.buffer,ArrayBuffer)||typeof SharedArrayBuffer<"u"&&(Et(t,SharedArrayBuffer)||t&&Et(t.buffer,SharedArrayBuffer)))return mc(t,e,r);if(typeof t=="number")throw new TypeError('The "value" argument must not be of type number. Received type number');var i=t.valueOf&&t.valueOf();if(i!=null&&i!==t)return k.from(i,e,r);var n=function(o){if(k.isBuffer(o)){var s=0|Ks(o.length),a=vt(s);return a.length===0||o.copy(a,0,0,s),a}if(o.length!==void 0)return typeof o.length!="number"||Gs(o.length)?vt(0):Fs(o);if(o.type==="Buffer"&&Array.isArray(o.data))return Fs(o.data)}(t);if(n)return n;if(typeof Symbol<"u"&&Symbol.toPrimitive!=null&&typeof t[Symbol.toPrimitive]=="function")return k.from(t[Symbol.toPrimitive]("string"),e,r);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t)}function Bc(t){if(typeof t!="number")throw new TypeError('"size" argument must be of type number');if(t<0)throw new RangeError('The value "'+t+'" is invalid for option "size"')}function Hs(t){return Bc(t),vt(t<0?0:0|Ks(t))}function Fs(t){for(var e=t.length<0?0:0|Ks(t.length),r=vt(e),i=0;i=2147483647)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+2147483647 .toString(16)+" bytes");return 0|t}function Pc(t,e){if(k.isBuffer(t))return t.length;if(ArrayBuffer.isView(t)||Et(t,ArrayBuffer))return t.byteLength;if(typeof t!="string")throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof t);var r=t.length,i=arguments.length>2&&arguments[2]===!0;if(!i&&r===0)return 0;for(var n=!1;;)switch(e){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":return Vs(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return Mc(t).length;default:if(n)return i?-1:Vs(t).length;e=(""+e).toLowerCase(),n=!0;}}function yw(t,e,r){var i=!1;if((e===void 0||e<0)&&(e=0),e>this.length||((r===void 0||r>this.length)&&(r=this.length),r<=0)||(r>>>=0)<=(e>>>=0))return "";for(t||(t="utf8");;)switch(t){case"hex":return Iw(this,e,r);case"utf8":case"utf-8":return kc(this,e,r);case"ascii":return Sw(this,e,r);case"latin1":case"binary":return Aw(this,e,r);case"base64":return Ew(this,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Tw(this,e,r);default:if(i)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),i=!0;}}function sr(t,e,r){var i=t[e];t[e]=t[r],t[r]=i;}function vc(t,e,r,i,n){if(t.length===0)return -1;if(typeof r=="string"?(i=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),Gs(r=+r)&&(r=n?0:t.length-1),r<0&&(r=t.length+r),r>=t.length){if(n)return -1;r=t.length-1;}else if(r<0){if(!n)return -1;r=0;}if(typeof e=="string"&&(e=k.from(e,i)),k.isBuffer(e))return e.length===0?-1:Ec(t,e,r,i,n);if(typeof e=="number")return e&=255,typeof Uint8Array.prototype.indexOf=="function"?n?Uint8Array.prototype.indexOf.call(t,e,r):Uint8Array.prototype.lastIndexOf.call(t,e,r):Ec(t,[e],r,i,n);throw new TypeError("val must be string, number or Buffer")}function Ec(t,e,r,i,n){var o,s=1,a=t.length,u=e.length;if(i!==void 0&&((i=String(i).toLowerCase())==="ucs2"||i==="ucs-2"||i==="utf16le"||i==="utf-16le")){if(t.length<2||e.length<2)return -1;s=2,a/=2,u/=2,r/=2;}function c(y,w){return s===1?y[w]:y.readUInt16BE(w*s)}if(n){var h=-1;for(o=r;oa&&(r=a-u),o=r;o>=0;o--){for(var d=!0,g=0;gn&&(i=n):i=n;var o=e.length;i>o/2&&(i=o/2);for(var s=0;s>8,u=s%256,c.push(u),c.push(a);return c}(e,t.length-r),t,r,i)}function Ew(t,e,r){return e===0&&r===t.length?$s.fromByteArray(t):$s.fromByteArray(t.slice(e,r))}function kc(t,e,r){r=Math.min(t.length,r);for(var i=[],n=e;n239?4:c>223?3:c>191?2:1;if(n+d<=r)switch(d){case 1:c<128&&(h=c);break;case 2:(192&(o=t[n+1]))==128&&(u=(31&c)<<6|63&o)>127&&(h=u);break;case 3:o=t[n+1],s=t[n+2],(192&o)==128&&(192&s)==128&&(u=(15&c)<<12|(63&o)<<6|63&s)>2047&&(u<55296||u>57343)&&(h=u);break;case 4:o=t[n+1],s=t[n+2],a=t[n+3],(192&o)==128&&(192&s)==128&&(192&a)==128&&(u=(15&c)<<18|(63&o)<<12|(63&s)<<6|63&a)>65535&&u<1114112&&(h=u);}h===null?(h=65533,d=1):h>65535&&(h-=65536,i.push(h>>>10&1023|55296),h=56320|1023&h),i.push(h),n+=d;}return function(g){var y=g.length;if(y<=4096)return String.fromCharCode.apply(String,g);for(var w="",E=0;Ei)&&(r=i);for(var n="",o=e;or)throw new RangeError("Trying to access beyond buffer length")}function Pe(t,e,r,i,n,o){if(!k.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>n||et.length)throw new RangeError("Index out of range")}function xc(t,e,r,i,n,o){if(r+i>t.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function Sc(t,e,r,i,n){return e=+e,r>>>=0,n||xc(t,0,r,4),Nr.write(t,e,r,i,23,4),r+4}function Ac(t,e,r,i,n){return e=+e,r>>>=0,n||xc(t,0,r,8),Nr.write(t,e,r,i,52,8),r+8}function Vs(t,e){var r;e=e||1/0;for(var i=t.length,n=null,o=[],s=0;s55295&&r<57344){if(!n){if(r>56319){(e-=3)>-1&&o.push(239,191,189);continue}if(s+1===i){(e-=3)>-1&&o.push(239,191,189);continue}n=r;continue}if(r<56320){(e-=3)>-1&&o.push(239,191,189),n=r;continue}r=65536+(n-55296<<10|r-56320);}else n&&(e-=3)>-1&&o.push(239,191,189);if(n=null,r<128){if((e-=1)<0)break;o.push(r);}else if(r<2048){if((e-=2)<0)break;o.push(r>>6|192,63&r|128);}else if(r<65536){if((e-=3)<0)break;o.push(r>>12|224,r>>6&63|128,63&r|128);}else {if(!(r<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;o.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128);}}return o}function Mc(t){return $s.toByteArray(function(e){if((e=(e=e.split("=")[0]).trim().replace(Rw,"")).length<2)return "";for(;e.length%4!=0;)e+="=";return e}(t))}function un(t,e,r,i){for(var n=0;n=e.length||n>=t.length);++n)e[n+r]=t[n];return n}function Et(t,e){return t instanceof e||t!=null&&t.constructor!=null&&t.constructor.name!=null&&t.constructor.name===e.name}function Gs(t){return t!=t}function Ic(t,e){for(var r in t)e[r]=t[r];}function or(t,e,r){return it(t,e,r)}function hi(t){var e;switch(this.encoding=function(r){var i=function(n){if(!n)return "utf8";for(var o;;)switch(n){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 n;default:if(o)return;n=(""+n).toLowerCase(),o=!0;}}(r);if(typeof i!="string"&&(zs.isEncoding===Tc||!Tc(r)))throw new Error("Unknown encoding: "+r);return i||r}(t),this.encoding){case"utf16le":this.text=Ow,this.end=kw,e=4;break;case"utf8":this.fillLast=Pw,e=4;break;case"base64":this.text=xw,this.end=Mw,e=3;break;default:return this.write=Lw,this.end=Uw,void 0}this.lastNeed=0,this.lastTotal=0,this.lastChar=zs.allocUnsafe(e);}function Ws(t){return t<=127?0:t>>5==6?2:t>>4==14?3:t>>3==30?4:t>>6==2?-1:-2}function Pw(t){var e=this.lastTotal-this.lastNeed,r=function(i,n,o){if((192&n[0])!=128)return i.lastNeed=0,"\uFFFD";if(i.lastNeed>1&&n.length>1){if((192&n[1])!=128)return i.lastNeed=1,"\uFFFD";if(i.lastNeed>2&&n.length>2&&(192&n[2])!=128)return i.lastNeed=2,"\uFFFD"}}(this,t);return r!==void 0?r:this.lastNeed<=t.length?(t.copy(this.lastChar,e,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(t.copy(this.lastChar,e,0,t.length),this.lastNeed-=t.length,void 0)}function Ow(t,e){if((t.length-e)%2==0){var r=t.toString("utf16le",e);if(r){var i=r.charCodeAt(r.length-1);if(i>=55296&&i<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=t[t.length-2],this.lastChar[1]=t[t.length-1],r.slice(0,-1)}return r}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=t[t.length-1],t.toString("utf16le",e,t.length-1)}function kw(t){var e=t&&t.length?this.write(t):"";if(this.lastNeed){var r=this.lastTotal-this.lastNeed;return e+this.lastChar.toString("utf16le",0,r)}return e}function xw(t,e){var r=(t.length-e)%3;return r===0?t.toString("base64",e):(this.lastNeed=3-r,this.lastTotal=3,r===1?this.lastChar[0]=t[t.length-1]:(this.lastChar[0]=t[t.length-2],this.lastChar[1]=t[t.length-1]),t.toString("base64",e,t.length-r))}function Mw(t){var e=t&&t.length?this.write(t):"";return this.lastNeed?e+this.lastChar.toString("base64",0,3-this.lastNeed):e}function Lw(t){return t.toString(this.encoding)}function Uw(t){return t&&t.length?this.write(t):""}var Rc,$e,ke,yc,on,nr,bc,gw,St,$s,Nr,_c,Rw,Cw,an,ln,it,Bw,ar,zs,Tc,Qs=we(()=>{v();m();_();for(Rc={byteLength:function(t){var e=wc(t),r=e[0],i=e[1];return 3*(r+i)/4-i},toByteArray:function(t){var e,r,i=wc(t),n=i[0],o=i[1],s=new yc(function(c,h,d){return 3*(h+d)/4-d}(0,n,o)),a=0,u=o>0?n-4:n;for(r=0;r>16&255,s[a++]=e>>8&255,s[a++]=255&e;return o===2&&(e=ke[t.charCodeAt(r)]<<2|ke[t.charCodeAt(r+1)]>>4,s[a++]=255&e),o===1&&(e=ke[t.charCodeAt(r)]<<10|ke[t.charCodeAt(r+1)]<<4|ke[t.charCodeAt(r+2)]>>2,s[a++]=e>>8&255,s[a++]=255&e),s},fromByteArray:function(t){for(var e,r=t.length,i=r%3,n=[],o=0,s=r-i;os?s:o+16383));return i===1?(e=t[r-1],n.push($e[e>>2]+$e[e<<4&63]+"==")):i===2&&(e=(t[r-2]<<8)+t[r-1],n.push($e[e>>10]+$e[e>>4&63]+$e[e<<2&63]+"=")),n.join("")}},$e=[],ke=[],yc=typeof Uint8Array<"u"?Uint8Array:Array,on="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",nr=0,bc=on.length;nr>1,h=-7,d=r?n-1:0,g=r?-1:1,y=t[e+d];for(d+=g,o=y&(1<<-h)-1,y>>=-h,h+=a;h>0;o=256*o+t[e+d],d+=g,h-=8);for(s=o&(1<<-h)-1,o>>=-h,h+=i;h>0;s=256*s+t[e+d],d+=g,h-=8);if(o===0)o=1-c;else {if(o===u)return s?NaN:1/0*(y?-1:1);s+=Math.pow(2,i),o-=c;}return (y?-1:1)*s*Math.pow(2,o-i)},write:function(t,e,r,i,n,o){var s,a,u,c=8*o-n-1,h=(1<>1,g=n===23?Math.pow(2,-24)-Math.pow(2,-77):0,y=i?0:o-1,w=i?1:-1,E=e<0||e===0&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(a=isNaN(e)?1:0,s=h):(s=Math.floor(Math.log(e)/Math.LN2),e*(u=Math.pow(2,-s))<1&&(s--,u*=2),(e+=s+d>=1?g/u:g*Math.pow(2,1-d))*u>=2&&(s++,u/=2),s+d>=h?(a=0,s=h):s+d>=1?(a=(e*u-1)*Math.pow(2,n),s+=d):(a=e*Math.pow(2,d-1)*Math.pow(2,n),s=0));n>=8;t[r+y]=255&a,y+=w,a/=256,n-=8);for(s=s<0;t[r+y]=255&s,y+=w,s/=256,c-=8);t[r+y-w]|=128*E;}},St={},$s=Rc,Nr=gw,_c=typeof Symbol=="function"&&typeof Symbol.for=="function"?Symbol.for("nodejs.util.inspect.custom"):null;St.Buffer=k,St.SlowBuffer=function(t){return +t!=t&&(t=0),k.alloc(+t)},St.INSPECT_MAX_BYTES=50;St.kMaxLength=2147483647,k.TYPED_ARRAY_SUPPORT=function(){try{var t=new Uint8Array(1),e={foo:function(){return 42}};return Object.setPrototypeOf(e,Uint8Array.prototype),Object.setPrototypeOf(t,e),t.foo()===42}catch{return !1}}(),k.TYPED_ARRAY_SUPPORT||typeof console>"u"||typeof console.error!="function"||console.error("This browser lacks typed array (Uint8Array) support which is required by `buffer` v5.x. Use `buffer` v4.x if you require old browser support."),Object.defineProperty(k.prototype,"parent",{enumerable:!0,get:function(){if(k.isBuffer(this))return this.buffer}}),Object.defineProperty(k.prototype,"offset",{enumerable:!0,get:function(){if(k.isBuffer(this))return this.byteOffset}}),k.poolSize=8192,k.from=function(t,e,r){return Cc(t,e,r)},Object.setPrototypeOf(k.prototype,Uint8Array.prototype),Object.setPrototypeOf(k,Uint8Array),k.alloc=function(t,e,r){return function(i,n,o){return Bc(i),i<=0?vt(i):n!==void 0?typeof o=="string"?vt(i).fill(n,o):vt(i).fill(n):vt(i)}(t,e,r)},k.allocUnsafe=function(t){return Hs(t)},k.allocUnsafeSlow=function(t){return Hs(t)},k.isBuffer=function(t){return t!=null&&t._isBuffer===!0&&t!==k.prototype},k.compare=function(t,e){if(Et(t,Uint8Array)&&(t=k.from(t,t.offset,t.byteLength)),Et(e,Uint8Array)&&(e=k.from(e,e.offset,e.byteLength)),!k.isBuffer(t)||!k.isBuffer(e))throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(t===e)return 0;for(var r=t.length,i=e.length,n=0,o=Math.min(r,i);ne&&(t+=" ... "),""},_c&&(k.prototype[_c]=k.prototype.inspect),k.prototype.compare=function(t,e,r,i,n){if(Et(t,Uint8Array)&&(t=k.from(t,t.offset,t.byteLength)),!k.isBuffer(t))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof t);if(e===void 0&&(e=0),r===void 0&&(r=t?t.length:0),i===void 0&&(i=0),n===void 0&&(n=this.length),e<0||r>t.length||i<0||n>this.length)throw new RangeError("out of range index");if(i>=n&&e>=r)return 0;if(i>=n)return -1;if(e>=r)return 1;if(this===t)return 0;for(var o=(n>>>=0)-(i>>>=0),s=(r>>>=0)-(e>>>=0),a=Math.min(o,s),u=this.slice(i,n),c=t.slice(e,r),h=0;h>>=0,isFinite(r)?(r>>>=0,i===void 0&&(i="utf8")):(i=r,r=void 0);}var n=this.length-e;if((r===void 0||r>n)&&(r=n),t.length>0&&(r<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");i||(i="utf8");for(var o=!1;;)switch(i){case"hex":return bw(this,t,e,r);case"utf8":case"utf-8":return ww(this,t,e,r);case"ascii":return Oc(this,t,e,r);case"latin1":case"binary":return _w(this,t,e,r);case"base64":return mw(this,t,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return vw(this,t,e,r);default:if(o)throw new TypeError("Unknown encoding: "+i);i=(""+i).toLowerCase(),o=!0;}},k.prototype.toJSON=function(){return {type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};k.prototype.slice=function(t,e){var r=this.length;(t=~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),(e=e===void 0?r:~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),e>>=0,e>>>=0,r||be(t,e,this.length);for(var i=this[t],n=1,o=0;++o>>=0,e>>>=0,r||be(t,e,this.length);for(var i=this[t+--e],n=1;e>0&&(n*=256);)i+=this[t+--e]*n;return i},k.prototype.readUInt8=function(t,e){return t>>>=0,e||be(t,1,this.length),this[t]},k.prototype.readUInt16LE=function(t,e){return t>>>=0,e||be(t,2,this.length),this[t]|this[t+1]<<8},k.prototype.readUInt16BE=function(t,e){return t>>>=0,e||be(t,2,this.length),this[t]<<8|this[t+1]},k.prototype.readUInt32LE=function(t,e){return t>>>=0,e||be(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},k.prototype.readUInt32BE=function(t,e){return t>>>=0,e||be(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},k.prototype.readIntLE=function(t,e,r){t>>>=0,e>>>=0,r||be(t,e,this.length);for(var i=this[t],n=1,o=0;++o=(n*=128)&&(i-=Math.pow(2,8*e)),i},k.prototype.readIntBE=function(t,e,r){t>>>=0,e>>>=0,r||be(t,e,this.length);for(var i=e,n=1,o=this[t+--i];i>0&&(n*=256);)o+=this[t+--i]*n;return o>=(n*=128)&&(o-=Math.pow(2,8*e)),o},k.prototype.readInt8=function(t,e){return t>>>=0,e||be(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},k.prototype.readInt16LE=function(t,e){t>>>=0,e||be(t,2,this.length);var r=this[t]|this[t+1]<<8;return 32768&r?4294901760|r:r},k.prototype.readInt16BE=function(t,e){t>>>=0,e||be(t,2,this.length);var r=this[t+1]|this[t]<<8;return 32768&r?4294901760|r:r},k.prototype.readInt32LE=function(t,e){return t>>>=0,e||be(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},k.prototype.readInt32BE=function(t,e){return t>>>=0,e||be(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},k.prototype.readFloatLE=function(t,e){return t>>>=0,e||be(t,4,this.length),Nr.read(this,t,!0,23,4)},k.prototype.readFloatBE=function(t,e){return t>>>=0,e||be(t,4,this.length),Nr.read(this,t,!1,23,4)},k.prototype.readDoubleLE=function(t,e){return t>>>=0,e||be(t,8,this.length),Nr.read(this,t,!0,52,8)},k.prototype.readDoubleBE=function(t,e){return t>>>=0,e||be(t,8,this.length),Nr.read(this,t,!1,52,8)},k.prototype.writeUIntLE=function(t,e,r,i){t=+t,e>>>=0,r>>>=0,i||Pe(this,t,e,r,Math.pow(2,8*r)-1,0);var n=1,o=0;for(this[e]=255&t;++o>>=0,r>>>=0,i||Pe(this,t,e,r,Math.pow(2,8*r)-1,0);var n=r-1,o=1;for(this[e+n]=255&t;--n>=0&&(o*=256);)this[e+n]=t/o&255;return e+r},k.prototype.writeUInt8=function(t,e,r){return t=+t,e>>>=0,r||Pe(this,t,e,1,255,0),this[e]=255&t,e+1},k.prototype.writeUInt16LE=function(t,e,r){return t=+t,e>>>=0,r||Pe(this,t,e,2,65535,0),this[e]=255&t,this[e+1]=t>>>8,e+2},k.prototype.writeUInt16BE=function(t,e,r){return t=+t,e>>>=0,r||Pe(this,t,e,2,65535,0),this[e]=t>>>8,this[e+1]=255&t,e+2},k.prototype.writeUInt32LE=function(t,e,r){return t=+t,e>>>=0,r||Pe(this,t,e,4,4294967295,0),this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t,e+4},k.prototype.writeUInt32BE=function(t,e,r){return t=+t,e>>>=0,r||Pe(this,t,e,4,4294967295,0),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t,e+4},k.prototype.writeIntLE=function(t,e,r,i){if(t=+t,e>>>=0,!i){var n=Math.pow(2,8*r-1);Pe(this,t,e,r,n-1,-n);}var o=0,s=1,a=0;for(this[e]=255&t;++o>0)-a&255;return e+r},k.prototype.writeIntBE=function(t,e,r,i){if(t=+t,e>>>=0,!i){var n=Math.pow(2,8*r-1);Pe(this,t,e,r,n-1,-n);}var o=r-1,s=1,a=0;for(this[e+o]=255&t;--o>=0&&(s*=256);)t<0&&a===0&&this[e+o+1]!==0&&(a=1),this[e+o]=(t/s>>0)-a&255;return e+r},k.prototype.writeInt8=function(t,e,r){return t=+t,e>>>=0,r||Pe(this,t,e,1,127,-128),t<0&&(t=255+t+1),this[e]=255&t,e+1},k.prototype.writeInt16LE=function(t,e,r){return t=+t,e>>>=0,r||Pe(this,t,e,2,32767,-32768),this[e]=255&t,this[e+1]=t>>>8,e+2},k.prototype.writeInt16BE=function(t,e,r){return t=+t,e>>>=0,r||Pe(this,t,e,2,32767,-32768),this[e]=t>>>8,this[e+1]=255&t,e+2},k.prototype.writeInt32LE=function(t,e,r){return t=+t,e>>>=0,r||Pe(this,t,e,4,2147483647,-2147483648),this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24,e+4},k.prototype.writeInt32BE=function(t,e,r){return t=+t,e>>>=0,r||Pe(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t,e+4},k.prototype.writeFloatLE=function(t,e,r){return Sc(this,t,e,!0,r)},k.prototype.writeFloatBE=function(t,e,r){return Sc(this,t,e,!1,r)},k.prototype.writeDoubleLE=function(t,e,r){return Ac(this,t,e,!0,r)},k.prototype.writeDoubleBE=function(t,e,r){return Ac(this,t,e,!1,r)},k.prototype.copy=function(t,e,r,i){if(!k.isBuffer(t))throw new TypeError("argument should be a Buffer");if(r||(r=0),i||i===0||(i=this.length),e>=t.length&&(e=t.length),e||(e=0),i>0&&i=this.length)throw new RangeError("Index out of range");if(i<0)throw new RangeError("sourceEnd out of bounds");i>this.length&&(i=this.length),t.length-e=0;--o)t[o+e]=this[o+r];else Uint8Array.prototype.set.call(t,this.subarray(r,i),e);return n},k.prototype.fill=function(t,e,r,i){if(typeof t=="string"){if(typeof e=="string"?(i=e,e=0,r=this.length):typeof r=="string"&&(i=r,r=this.length),i!==void 0&&typeof i!="string")throw new TypeError("encoding must be a string");if(typeof i=="string"&&!k.isEncoding(i))throw new TypeError("Unknown encoding: "+i);if(t.length===1){var n=t.charCodeAt(0);(i==="utf8"&&n<128||i==="latin1")&&(t=n);}}else typeof t=="number"?t&=255:typeof t=="boolean"&&(t=Number(t));if(e<0||this.length>>=0,r=r===void 0?this.length:r>>>0,t||(t=0),typeof t=="number")for(o=e;o=0?(u>0&&(n.lastNeed=u-1),u):--a=0?(u>0&&(n.lastNeed=u-2),u):--a=0?(u>0&&(u===2?u=0:n.lastNeed=u-3),u):0}(this,t,e);if(!this.lastNeed)return t.toString("utf8",e);this.lastTotal=r;var i=t.length-(r-this.lastNeed);return t.copy(this.lastChar,0,i),t.toString("utf8",e,i)},hi.prototype.fillLast=function(t){if(this.lastNeed<=t.length)return t.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);t.copy(this.lastChar,this.lastTotal-this.lastNeed,0,t.length),this.lastNeed-=t.length;};ar.StringDecoder;ar.StringDecoder;});var Lc={};Qt(Lc,{StringDecoder:()=>Nw,default:()=>ar});var Nw,Uc=we(()=>{v();m();_();Qs();Qs();Nw=ar.StringDecoder;});var Ys=M((F2,jc)=>{v();m();_();var Nc=Ut(),{PromisePrototypeThen:qw,SymbolAsyncIterator:qc,SymbolIterator:Dc}=ce(),{Buffer:Dw}=(ye(),X(_e)),{ERR_INVALID_ARG_TYPE:jw,ERR_STREAM_NULL_VALUES:Fw}=Se().codes;function Ww(t,e,r){let i;if(typeof e=="string"||e instanceof Dw)return new t({objectMode:!0,...r,read(){this.push(e),this.push(null);}});let n;if(e&&e[qc])n=!0,i=e[qc]();else if(e&&e[Dc])n=!1,i=e[Dc]();else throw new jw("iterable",["Iterable"],e);let o=new t({objectMode:!0,highWaterMark:1,...r}),s=!1;o._read=function(){s||(s=!0,u());},o._destroy=function(c,h){qw(a(c),()=>Nc.nextTick(h,c),d=>Nc.nextTick(h,d||c));};async function a(c){let h=c!=null,d=typeof i.throw=="function";if(h&&d){let{value:g,done:y}=await i.throw(c);if(await g,y)return}if(typeof i.return=="function"){let{value:g}=await i.return();await g;}}async function u(){for(;;){try{let{value:c,done:h}=n?await i.next():i.next();if(h)o.push(null);else {let d=c&&typeof c.then=="function"?await c:c;if(d===null)throw s=!1,new Fw;if(o.push(d))continue;s=!1;}}catch(c){o.destroy(c);}break}}return o}jc.exports=Ww;});var di=M((J2,Zc)=>{v();m();_();var He=Ut(),{ArrayPrototypeIndexOf:$w,NumberIsInteger:Hw,NumberIsNaN:Vw,NumberParseInt:zw,ObjectDefineProperties:$c,ObjectKeys:Kw,ObjectSetPrototypeOf:Hc,Promise:Gw,SafeSet:Qw,SymbolAsyncIterator:Yw,Symbol:Jw}=ce();Zc.exports=F;F.ReadableState=ro;var{EventEmitter:Xw}=(ir(),X(rr)),{Stream:qt,prependListener:Zw}=tn(),{Buffer:Js}=(ye(),X(_e)),{addAbortSignal:e_}=ci(),t_=mt(),H=Je().debuglog("stream",t=>{H=t;}),r_=dc(),Dr=tr(),{getHighWaterMark:i_,getDefaultHighWaterMark:n_}=sn(),{aggregateTwoErrors:Fc,codes:{ERR_INVALID_ARG_TYPE:s_,ERR_METHOD_NOT_IMPLEMENTED:o_,ERR_OUT_OF_RANGE:a_,ERR_STREAM_PUSH_AFTER_EOF:l_,ERR_STREAM_UNSHIFT_AFTER_END_EVENT:u_}}=Se(),{validateObject:f_}=fi(),lr=Jw("kPaused"),{StringDecoder:Vc}=(Uc(),X(Lc)),c_=Ys();Hc(F.prototype,qt.prototype);Hc(F,qt);var Xs=()=>{},{errorOrDestroy:qr}=Dr;function ro(t,e,r){typeof r!="boolean"&&(r=e instanceof nt()),this.objectMode=!!(t&&t.objectMode),r&&(this.objectMode=this.objectMode||!!(t&&t.readableObjectMode)),this.highWaterMark=t?i_(this,t,"readableHighWaterMark",r):n_(!1),this.buffer=new r_,this.length=0,this.pipes=[],this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.constructed=!0,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this[lr]=null,this.errorEmitted=!1,this.emitClose=!t||t.emitClose!==!1,this.autoDestroy=!t||t.autoDestroy!==!1,this.destroyed=!1,this.errored=null,this.closed=!1,this.closeEmitted=!1,this.defaultEncoding=t&&t.defaultEncoding||"utf8",this.awaitDrainWriters=null,this.multiAwaitDrain=!1,this.readingMore=!1,this.dataEmitted=!1,this.decoder=null,this.encoding=null,t&&t.encoding&&(this.decoder=new Vc(t.encoding),this.encoding=t.encoding);}function F(t){if(!(this instanceof F))return new F(t);let e=this instanceof nt();this._readableState=new ro(t,this,e),t&&(typeof t.read=="function"&&(this._read=t.read),typeof t.destroy=="function"&&(this._destroy=t.destroy),typeof t.construct=="function"&&(this._construct=t.construct),t.signal&&!e&&e_(t.signal,this)),qt.call(this,t),Dr.construct(this,()=>{this._readableState.needReadable&&fn(this,this._readableState);});}F.prototype.destroy=Dr.destroy;F.prototype._undestroy=Dr.undestroy;F.prototype._destroy=function(t,e){e(t);};F.prototype[Xw.captureRejectionSymbol]=function(t){this.destroy(t);};F.prototype.push=function(t,e){return zc(this,t,e,!1)};F.prototype.unshift=function(t,e){return zc(this,t,e,!0)};function zc(t,e,r,i){H("readableAddChunk",e);let n=t._readableState,o;if(n.objectMode||(typeof e=="string"?(r=r||n.defaultEncoding,n.encoding!==r&&(i&&n.encoding?e=Js.from(e,r).toString(n.encoding):(e=Js.from(e,r),r=""))):e instanceof Js?r="":qt._isUint8Array(e)?(e=qt._uint8ArrayToBuffer(e),r=""):e!=null&&(o=new s_("chunk",["string","Buffer","Uint8Array"],e))),o)qr(t,o);else if(e===null)n.reading=!1,p_(t,n);else if(n.objectMode||e&&e.length>0)if(i)if(n.endEmitted)qr(t,new u_);else {if(n.destroyed||n.errored)return !1;Zs(t,n,e,!0);}else if(n.ended)qr(t,new l_);else {if(n.destroyed||n.errored)return !1;n.reading=!1,n.decoder&&!r?(e=n.decoder.write(e),n.objectMode||e.length!==0?Zs(t,n,e,!1):fn(t,n)):Zs(t,n,e,!1);}else i||(n.reading=!1,fn(t,n));return !n.ended&&(n.length0?(e.multiAwaitDrain?e.awaitDrainWriters.clear():e.awaitDrainWriters=null,e.dataEmitted=!0,t.emit("data",r)):(e.length+=e.objectMode?1:r.length,i?e.buffer.unshift(r):e.buffer.push(r),e.needReadable&&cn(t)),fn(t,e);}F.prototype.isPaused=function(){let t=this._readableState;return t[lr]===!0||t.flowing===!1};F.prototype.setEncoding=function(t){let e=new Vc(t);this._readableState.decoder=e,this._readableState.encoding=this._readableState.decoder.encoding;let r=this._readableState.buffer,i="";for(let n of r)i+=e.write(n);return r.clear(),i!==""&&r.push(i),this._readableState.length=i.length,this};var h_=1073741824;function d_(t){if(t>h_)throw new a_("size","<= 1GiB",t);return t--,t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,t|=t>>>16,t++,t}function Wc(t,e){return t<=0||e.length===0&&e.ended?0:e.objectMode?1:Vw(t)?e.flowing&&e.length?e.buffer.first().length:e.length:t<=e.length?t:e.ended?e.length:0}F.prototype.read=function(t){H("read",t),t===void 0?t=NaN:Hw(t)||(t=zw(t,10));let e=this._readableState,r=t;if(t>e.highWaterMark&&(e.highWaterMark=d_(t)),t!==0&&(e.emittedReadable=!1),t===0&&e.needReadable&&((e.highWaterMark!==0?e.length>=e.highWaterMark:e.length>0)||e.ended))return H("read: emitReadable",e.length,e.ended),e.length===0&&e.ended?eo(this):cn(this),null;if(t=Wc(t,e),t===0&&e.ended)return e.length===0&&eo(this),null;let i=e.needReadable;if(H("need readable",i),(e.length===0||e.length-t0?n=Jc(t,e):n=null,n===null?(e.needReadable=e.length<=e.highWaterMark,t=0):(e.length-=t,e.multiAwaitDrain?e.awaitDrainWriters.clear():e.awaitDrainWriters=null),e.length===0&&(e.ended||(e.needReadable=!0),r!==t&&e.ended&&eo(this)),n!==null&&!e.errorEmitted&&!e.closeEmitted&&(e.dataEmitted=!0,this.emit("data",n)),n};function p_(t,e){if(H("onEofChunk"),!e.ended){if(e.decoder){let r=e.decoder.end();r&&r.length&&(e.buffer.push(r),e.length+=e.objectMode?1:r.length);}e.ended=!0,e.sync?cn(t):(e.needReadable=!1,e.emittedReadable=!0,Kc(t));}}function cn(t){let e=t._readableState;H("emitReadable",e.needReadable,e.emittedReadable),e.needReadable=!1,e.emittedReadable||(H("emitReadable",e.flowing),e.emittedReadable=!0,He.nextTick(Kc,t));}function Kc(t){let e=t._readableState;H("emitReadable_",e.destroyed,e.length,e.ended),!e.destroyed&&!e.errored&&(e.length||e.ended)&&(t.emit("readable"),e.emittedReadable=!1),e.needReadable=!e.flowing&&!e.ended&&e.length<=e.highWaterMark,Qc(t);}function fn(t,e){!e.readingMore&&e.constructed&&(e.readingMore=!0,He.nextTick(g_,t,e));}function g_(t,e){for(;!e.reading&&!e.ended&&(e.length1&&i.pipes.includes(t)&&(H("false write response, pause",i.awaitDrainWriters.size),i.awaitDrainWriters.add(t)),r.pause()),u||(u=y_(r,t),t.on("drain",u));}r.on("data",g);function g(I){H("ondata");let C=t.write(I);H("dest.write",C),C===!1&&d();}function y(I){if(H("onerror",I),S(),t.removeListener("error",y),t.listenerCount("error")===0){let C=t._writableState||t._readableState;C&&!C.errorEmitted?qr(t,I):t.emit("error",I);}}Zw(t,"error",y);function w(){t.removeListener("finish",E),S();}t.once("close",w);function E(){H("onfinish"),t.removeListener("close",w),S();}t.once("finish",E);function S(){H("unpipe"),r.unpipe(t);}return t.emit("pipe",r),t.writableNeedDrain===!0?i.flowing&&d():i.flowing||(H("pipe resume"),r.resume()),t};function y_(t,e){return function(){let i=t._readableState;i.awaitDrainWriters===e?(H("pipeOnDrain",1),i.awaitDrainWriters=null):i.multiAwaitDrain&&(H("pipeOnDrain",i.awaitDrainWriters.size),i.awaitDrainWriters.delete(e)),(!i.awaitDrainWriters||i.awaitDrainWriters.size===0)&&t.listenerCount("data")&&t.resume();}}F.prototype.unpipe=function(t){let e=this._readableState,r={hasUnpiped:!1};if(e.pipes.length===0)return this;if(!t){let n=e.pipes;e.pipes=[],this.pause();for(let o=0;o0,i.flowing!==!1&&this.resume()):t==="readable"&&!i.endEmitted&&!i.readableListening&&(i.readableListening=i.needReadable=!0,i.flowing=!1,i.emittedReadable=!1,H("on readable",i.length,i.reading),i.length?cn(this):i.reading||He.nextTick(b_,this)),r};F.prototype.addListener=F.prototype.on;F.prototype.removeListener=function(t,e){let r=qt.prototype.removeListener.call(this,t,e);return t==="readable"&&He.nextTick(Gc,this),r};F.prototype.off=F.prototype.removeListener;F.prototype.removeAllListeners=function(t){let e=qt.prototype.removeAllListeners.apply(this,arguments);return (t==="readable"||t===void 0)&&He.nextTick(Gc,this),e};function Gc(t){let e=t._readableState;e.readableListening=t.listenerCount("readable")>0,e.resumeScheduled&&e[lr]===!1?e.flowing=!0:t.listenerCount("data")>0?t.resume():e.readableListening||(e.flowing=null);}function b_(t){H("readable nexttick read 0"),t.read(0);}F.prototype.resume=function(){let t=this._readableState;return t.flowing||(H("resume"),t.flowing=!t.readableListening,w_(this,t)),t[lr]=!1,this};function w_(t,e){e.resumeScheduled||(e.resumeScheduled=!0,He.nextTick(__,t,e));}function __(t,e){H("resume",e.reading),e.reading||t.read(0),e.resumeScheduled=!1,t.emit("resume"),Qc(t),e.flowing&&!e.reading&&t.read(0);}F.prototype.pause=function(){return H("call pause flowing=%j",this._readableState.flowing),this._readableState.flowing!==!1&&(H("pause"),this._readableState.flowing=!1,this.emit("pause")),this._readableState[lr]=!0,this};function Qc(t){let e=t._readableState;for(H("flow",e.flowing);e.flowing&&t.read()!==null;);}F.prototype.wrap=function(t){let e=!1;t.on("data",i=>{!this.push(i)&&t.pause&&(e=!0,t.pause());}),t.on("end",()=>{this.push(null);}),t.on("error",i=>{qr(this,i);}),t.on("close",()=>{this.destroy();}),t.on("destroy",()=>{this.destroy();}),this._read=()=>{e&&t.resume&&(e=!1,t.resume());};let r=Kw(t);for(let i=1;i{n=s?Fc(n,s):null,r(),r=Xs;});try{for(;;){let s=t.destroyed?null:t.read();if(s!==null)yield s;else {if(n)throw n;if(n===null)return;await new Gw(i);}}}catch(s){throw n=Fc(n,s),n}finally{(n||e?.destroyOnReturn!==!1)&&(n===void 0||t._readableState.autoDestroy)?Dr.destroyer(t,null):(t.off("readable",i),o());}}$c(F.prototype,{readable:{__proto__:null,get(){let t=this._readableState;return !!t&&t.readable!==!1&&!t.destroyed&&!t.errorEmitted&&!t.endEmitted},set(t){this._readableState&&(this._readableState.readable=!!t);}},readableDidRead:{__proto__:null,enumerable:!1,get:function(){return this._readableState.dataEmitted}},readableAborted:{__proto__:null,enumerable:!1,get:function(){return !!(this._readableState.readable!==!1&&(this._readableState.destroyed||this._readableState.errored)&&!this._readableState.endEmitted)}},readableHighWaterMark:{__proto__:null,enumerable:!1,get:function(){return this._readableState.highWaterMark}},readableBuffer:{__proto__:null,enumerable:!1,get:function(){return this._readableState&&this._readableState.buffer}},readableFlowing:{__proto__:null,enumerable:!1,get:function(){return this._readableState.flowing},set:function(t){this._readableState&&(this._readableState.flowing=t);}},readableLength:{__proto__:null,enumerable:!1,get(){return this._readableState.length}},readableObjectMode:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.objectMode:!1}},readableEncoding:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.encoding:null}},errored:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.errored:null}},closed:{__proto__:null,get(){return this._readableState?this._readableState.closed:!1}},destroyed:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.destroyed:!1},set(t){this._readableState&&(this._readableState.destroyed=t);}},readableEnded:{__proto__:null,enumerable:!1,get(){return this._readableState?this._readableState.endEmitted:!1}}});$c(ro.prototype,{pipesCount:{__proto__:null,get(){return this.pipes.length}},paused:{__proto__:null,get(){return this[lr]!==!1},set(t){this[lr]=!!t;}}});F._fromList=Jc;function Jc(t,e){if(e.length===0)return null;let r;return e.objectMode?r=e.buffer.shift():!t||t>=e.length?(e.decoder?r=e.buffer.join(""):e.buffer.length===1?r=e.buffer.first():r=e.buffer.concat(e.length),e.buffer.clear()):r=e.buffer.consume(t,e.decoder),r}function eo(t){let e=t._readableState;H("endReadable",e.endEmitted),e.endEmitted||(e.ended=!0,He.nextTick(v_,e,t));}function v_(t,e){if(H("endReadableNT",t.endEmitted,t.length),!t.errored&&!t.closeEmitted&&!t.endEmitted&&t.length===0){if(t.endEmitted=!0,e.emit("end"),e.writable&&e.allowHalfOpen===!1)He.nextTick(E_,e);else if(t.autoDestroy){let r=e._writableState;(!r||r.autoDestroy&&(r.finished||r.writable===!1))&&e.destroy();}}}function E_(t){t.writable&&!t.writableEnded&&!t.destroyed&&t.end();}F.from=function(t,e){return c_(F,t,e)};var to;function Xc(){return to===void 0&&(to={}),to}F.fromWeb=function(t,e){return Xc().newStreamReadableFromReadableStream(t,e)};F.toWeb=function(t,e){return Xc().newReadableStreamFromStreamReadable(t,e)};F.wrap=function(t,e){var r,i;return new F({objectMode:(r=(i=t.readableObjectMode)!==null&&i!==void 0?i:t.objectMode)!==null&&r!==void 0?r:!0,...e,destroy(n,o){Dr.destroyer(t,n),o(n);}}).wrap(t)};});var uo=M((aR,ch)=>{v();m();_();var ur=Ut(),{ArrayPrototypeSlice:rh,Error:S_,FunctionPrototypeSymbolHasInstance:ih,ObjectDefineProperty:nh,ObjectDefineProperties:A_,ObjectSetPrototypeOf:sh,StringPrototypeToLowerCase:I_,Symbol:T_,SymbolHasInstance:R_}=ce();ch.exports=ie;ie.WritableState=yi;var{EventEmitter:C_}=(ir(),X(rr)),pi=tn().Stream,{Buffer:hn}=(ye(),X(_e)),gn=tr(),{addAbortSignal:B_}=ci(),{getHighWaterMark:P_,getDefaultHighWaterMark:O_}=sn(),{ERR_INVALID_ARG_TYPE:k_,ERR_METHOD_NOT_IMPLEMENTED:x_,ERR_MULTIPLE_CALLBACK:oh,ERR_STREAM_CANNOT_PIPE:M_,ERR_STREAM_DESTROYED:gi,ERR_STREAM_ALREADY_FINISHED:L_,ERR_STREAM_NULL_VALUES:U_,ERR_STREAM_WRITE_AFTER_END:N_,ERR_UNKNOWN_ENCODING:ah}=Se().codes,{errorOrDestroy:jr}=gn;sh(ie.prototype,pi.prototype);sh(ie,pi);function so(){}var Fr=T_("kOnFinished");function yi(t,e,r){typeof r!="boolean"&&(r=e instanceof nt()),this.objectMode=!!(t&&t.objectMode),r&&(this.objectMode=this.objectMode||!!(t&&t.writableObjectMode)),this.highWaterMark=t?P_(this,t,"writableHighWaterMark",r):O_(!1),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;let i=!!(t&&t.decodeStrings===!1);this.decodeStrings=!i,this.defaultEncoding=t&&t.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=D_.bind(void 0,e),this.writecb=null,this.writelen=0,this.afterWriteTickInfo=null,pn(this),this.pendingcb=0,this.constructed=!0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=!t||t.emitClose!==!1,this.autoDestroy=!t||t.autoDestroy!==!1,this.errored=null,this.closed=!1,this.closeEmitted=!1,this[Fr]=[];}function pn(t){t.buffered=[],t.bufferedIndex=0,t.allBuffers=!0,t.allNoop=!0;}yi.prototype.getBuffer=function(){return rh(this.buffered,this.bufferedIndex)};nh(yi.prototype,"bufferedRequestCount",{__proto__:null,get(){return this.buffered.length-this.bufferedIndex}});function ie(t){let e=this instanceof nt();if(!e&&!ih(ie,this))return new ie(t);this._writableState=new yi(t,this,e),t&&(typeof t.write=="function"&&(this._write=t.write),typeof t.writev=="function"&&(this._writev=t.writev),typeof t.destroy=="function"&&(this._destroy=t.destroy),typeof t.final=="function"&&(this._final=t.final),typeof t.construct=="function"&&(this._construct=t.construct),t.signal&&B_(t.signal,this)),pi.call(this,t),gn.construct(this,()=>{let r=this._writableState;r.writing||ao(this,r),lo(this,r);});}nh(ie,R_,{__proto__:null,value:function(t){return ih(this,t)?!0:this!==ie?!1:t&&t._writableState instanceof yi}});ie.prototype.pipe=function(){jr(this,new M_);};function lh(t,e,r,i){let n=t._writableState;if(typeof r=="function")i=r,r=n.defaultEncoding;else {if(!r)r=n.defaultEncoding;else if(r!=="buffer"&&!hn.isEncoding(r))throw new ah(r);typeof i!="function"&&(i=so);}if(e===null)throw new U_;if(!n.objectMode)if(typeof e=="string")n.decodeStrings!==!1&&(e=hn.from(e,r),r="buffer");else if(e instanceof hn)r="buffer";else if(pi._isUint8Array(e))e=pi._uint8ArrayToBuffer(e),r="buffer";else throw new k_("chunk",["string","Buffer","Uint8Array"],e);let o;return n.ending?o=new N_:n.destroyed&&(o=new gi("write")),o?(ur.nextTick(i,o),jr(t,o,!0),o):(n.pendingcb++,q_(t,n,e,r,i))}ie.prototype.write=function(t,e,r){return lh(this,t,e,r)===!0};ie.prototype.cork=function(){this._writableState.corked++;};ie.prototype.uncork=function(){let t=this._writableState;t.corked&&(t.corked--,t.writing||ao(this,t));};ie.prototype.setDefaultEncoding=function(e){if(typeof e=="string"&&(e=I_(e)),!hn.isEncoding(e))throw new ah(e);return this._writableState.defaultEncoding=e,this};function q_(t,e,r,i,n){let o=e.objectMode?1:r.length;e.length+=o;let s=e.lengthr.bufferedIndex&&ao(t,r),i?r.afterWriteTickInfo!==null&&r.afterWriteTickInfo.cb===n?r.afterWriteTickInfo.count++:(r.afterWriteTickInfo={count:1,cb:n,stream:t,state:r},ur.nextTick(j_,r.afterWriteTickInfo)):uh(t,r,1,n));}function j_({stream:t,state:e,count:r,cb:i}){return e.afterWriteTickInfo=null,uh(t,e,r,i)}function uh(t,e,r,i){for(!e.ending&&!t.destroyed&&e.length===0&&e.needDrain&&(e.needDrain=!1,t.emit("drain"));r-- >0;)e.pendingcb--,i();e.destroyed&&oo(e),lo(t,e);}function oo(t){if(t.writing)return;for(let n=t.bufferedIndex;n1&&t._writev){e.pendingcb-=o-1;let a=e.allNoop?so:c=>{for(let h=s;h256?(r.splice(0,s),e.bufferedIndex=0):e.bufferedIndex=s;}e.bufferProcessing=!1;}ie.prototype._write=function(t,e,r){if(this._writev)this._writev([{chunk:t,encoding:e}],r);else throw new x_("_write()")};ie.prototype._writev=null;ie.prototype.end=function(t,e,r){let i=this._writableState;typeof t=="function"?(r=t,t=null,e=null):typeof e=="function"&&(r=e,e=null);let n;if(t!=null){let o=lh(this,t,e);o instanceof S_&&(n=o);}return i.corked&&(i.corked=1,this.uncork()),n||(!i.errored&&!i.ending?(i.ending=!0,lo(this,i,!0),i.ended=!0):i.finished?n=new L_("end"):i.destroyed&&(n=new gi("end"))),typeof r=="function"&&(n||i.finished?ur.nextTick(r,n):i[Fr].push(r)),this};function dn(t){return t.ending&&!t.destroyed&&t.constructed&&t.length===0&&!t.errored&&t.buffered.length===0&&!t.finished&&!t.writing&&!t.errorEmitted&&!t.closeEmitted}function F_(t,e){let r=!1;function i(n){if(r){jr(t,n??oh());return}if(r=!0,e.pendingcb--,n){let o=e[Fr].splice(0);for(let s=0;s{dn(n)?no(i,n):n.pendingcb--;},t,e)):dn(e)&&(e.pendingcb++,no(t,e))));}function no(t,e){e.pendingcb--,e.finished=!0;let r=e[Fr].splice(0);for(let i=0;i{v();m();_();var fo=Ut(),H_=(ye(),X(_e)),{isReadable:V_,isWritable:z_,isIterable:hh,isNodeStream:K_,isReadableNodeStream:dh,isWritableNodeStream:ph,isDuplexNodeStream:G_}=tt(),gh=mt(),{AbortError:vh,codes:{ERR_INVALID_ARG_TYPE:Q_,ERR_INVALID_RETURN_VALUE:yh}}=Se(),{destroyer:Wr}=tr(),Y_=nt(),J_=di(),{createDeferredPromise:bh}=Je(),wh=Ys(),_h=globalThis.Blob||H_.Blob,X_=typeof _h<"u"?function(e){return e instanceof _h}:function(e){return !1},Z_=globalThis.AbortController||Hi().AbortController,{FunctionPrototypeCall:mh}=ce(),fr=class extends Y_{constructor(e){super(e),e?.readable===!1&&(this._readableState.readable=!1,this._readableState.ended=!0,this._readableState.endEmitted=!0),e?.writable===!1&&(this._writableState.writable=!1,this._writableState.ending=!0,this._writableState.ended=!0,this._writableState.finished=!0);}};Eh.exports=function t(e,r){if(G_(e))return e;if(dh(e))return yn({readable:e});if(ph(e))return yn({writable:e});if(K_(e))return yn({writable:!1,readable:!1});if(typeof e=="function"){let{value:n,write:o,final:s,destroy:a}=e0(e);if(hh(n))return wh(fr,n,{objectMode:!0,write:o,final:s,destroy:a});let u=n?.then;if(typeof u=="function"){let c,h=mh(u,n,d=>{if(d!=null)throw new yh("nully","body",d)},d=>{Wr(c,d);});return c=new fr({objectMode:!0,readable:!1,write:o,final(d){s(async()=>{try{await h,fo.nextTick(d,null);}catch(g){fo.nextTick(d,g);}});},destroy:a})}throw new yh("Iterable, AsyncIterable or AsyncFunction",r,n)}if(X_(e))return t(e.arrayBuffer());if(hh(e))return wh(fr,e,{objectMode:!0,writable:!1});if(typeof e?.writable=="object"||typeof e?.readable=="object"){let n=e!=null&&e.readable?dh(e?.readable)?e?.readable:t(e.readable):void 0,o=e!=null&&e.writable?ph(e?.writable)?e?.writable:t(e.writable):void 0;return yn({readable:n,writable:o})}let i=e?.then;if(typeof i=="function"){let n;return mh(i,e,o=>{o!=null&&n.push(o),n.push(null);},o=>{Wr(n,o);}),n=new fr({objectMode:!0,writable:!1,read(){}})}throw new Q_(r,["Blob","ReadableStream","WritableStream","Stream","Iterable","AsyncIterable","Function","{ readable, writable } pair","Promise"],e)};function e0(t){let{promise:e,resolve:r}=bh(),i=new Z_,n=i.signal;return {value:t(async function*(){for(;;){let s=e;e=null;let{chunk:a,done:u,cb:c}=await s;if(fo.nextTick(c),u)return;if(n.aborted)throw new vh(void 0,{cause:n.reason});(({promise:e,resolve:r}=bh())),yield a;}}(),{signal:n}),write(s,a,u){let c=r;r=null,c({chunk:s,done:!1,cb:u});},final(s){let a=r;r=null,a({done:!0,cb:s});},destroy(s,a){i.abort(),a(s);}}}function yn(t){let e=t.readable&&typeof t.readable.read!="function"?J_.wrap(t.readable):t.readable,r=t.writable,i=!!V_(e),n=!!z_(r),o,s,a,u,c;function h(d){let g=u;u=null,g?g(d):d&&c.destroy(d);}return c=new fr({readableObjectMode:!!(e!=null&&e.readableObjectMode),writableObjectMode:!!(r!=null&&r.writableObjectMode),readable:i,writable:n}),n&&(gh(r,d=>{n=!1,d&&Wr(e,d),h(d);}),c._write=function(d,g,y){r.write(d,g)?y():o=y;},c._final=function(d){r.end(),s=d;},r.on("drain",function(){if(o){let d=o;o=null,d();}}),r.on("finish",function(){if(s){let d=s;s=null,d();}})),i&&(gh(e,d=>{i=!1,d&&Wr(e,d),h(d);}),e.on("readable",function(){if(a){let d=a;a=null,d();}}),e.on("end",function(){c.push(null);}),c._read=function(){for(;;){let d=e.read();if(d===null){a=c._read;return}if(!c.push(d))return}}),c._destroy=function(d,g){!d&&u!==null&&(d=new vh),a=null,o=null,s=null,u===null?g(d):(u=g,Wr(r,d),Wr(e,d));},c}});var nt=M((RR,Th)=>{v();m();_();var{ObjectDefineProperties:t0,ObjectGetOwnPropertyDescriptor:At,ObjectKeys:r0,ObjectSetPrototypeOf:Ah}=ce();Th.exports=Ve;var po=di(),Ne=uo();Ah(Ve.prototype,po.prototype);Ah(Ve,po);{let t=r0(Ne.prototype);for(let e=0;e{v();m();_();var{ObjectSetPrototypeOf:Rh,Symbol:i0}=ce();Ch.exports=It;var{ERR_METHOD_NOT_IMPLEMENTED:n0}=Se().codes,yo=nt(),{getHighWaterMark:s0}=sn();Rh(It.prototype,yo.prototype);Rh(It,yo);var bi=i0("kCallback");function It(t){if(!(this instanceof It))return new It(t);let e=t?s0(this,t,"readableHighWaterMark",!0):null;e===0&&(t={...t,highWaterMark:null,readableHighWaterMark:e,writableHighWaterMark:t.writableHighWaterMark||0}),yo.call(this,t),this._readableState.sync=!1,this[bi]=null,t&&(typeof t.transform=="function"&&(this._transform=t.transform),typeof t.flush=="function"&&(this._flush=t.flush)),this.on("prefinish",o0);}function go(t){typeof this._flush=="function"&&!this.destroyed?this._flush((e,r)=>{if(e){t?t(e):this.destroy(e);return}r!=null&&this.push(r),this.push(null),t&&t();}):(this.push(null),t&&t());}function o0(){this._final!==go&&go.call(this);}It.prototype._final=go;It.prototype._transform=function(t,e,r){throw new n0("_transform()")};It.prototype._write=function(t,e,r){let i=this._readableState,n=this._writableState,o=i.length;this._transform(t,e,(s,a)=>{if(s){r(s);return}a!=null&&this.push(a),n.ended||o===i.length||i.length{v();m();_();var{ObjectSetPrototypeOf:Bh}=ce();Ph.exports=$r;var wo=bo();Bh($r.prototype,wo.prototype);Bh($r,wo);function $r(t){if(!(this instanceof $r))return new $r(t);wo.call(this,t);}$r.prototype._transform=function(t,e,r){r(null,t);};});var mn=M((iC,Lh)=>{v();m();_();var wi=Ut(),{ArrayIsArray:a0,Promise:l0,SymbolAsyncIterator:u0}=ce(),_n=mt(),{once:f0}=Je(),c0=tr(),Oh=nt(),{aggregateTwoErrors:h0,codes:{ERR_INVALID_ARG_TYPE:Ro,ERR_INVALID_RETURN_VALUE:mo,ERR_MISSING_ARGS:d0,ERR_STREAM_DESTROYED:p0,ERR_STREAM_PREMATURE_CLOSE:g0},AbortError:y0}=Se(),{validateFunction:b0,validateAbortSignal:w0}=fi(),{isIterable:cr,isReadable:vo,isReadableNodeStream:wn,isNodeStream:kh,isTransformStream:Hr,isWebStream:_0,isReadableStream:Eo,isReadableEnded:m0}=tt(),v0=globalThis.AbortController||Hi().AbortController,So,Ao;function xh(t,e,r){let i=!1;t.on("close",()=>{i=!0;});let n=_n(t,{readable:e,writable:r},o=>{i=!o;});return {destroy:o=>{i||(i=!0,c0.destroyer(t,o||new p0("pipe")));},cleanup:n}}function E0(t){return b0(t[t.length-1],"streams[stream.length - 1]"),t.pop()}function Io(t){if(cr(t))return t;if(wn(t))return S0(t);throw new Ro("val",["Readable","Iterable","AsyncIterable"],t)}async function*S0(t){Ao||(Ao=di()),yield*Ao.prototype[u0].call(t);}async function bn(t,e,r,{end:i}){let n,o=null,s=c=>{if(c&&(n=c),o){let h=o;o=null,h();}},a=()=>new l0((c,h)=>{n?h(n):o=()=>{n?h(n):c();};});e.on("drain",s);let u=_n(e,{readable:!1},s);try{e.writableNeedDrain&&await a();for await(let c of t)e.write(c)||await a();i&&e.end(),await a(),r();}catch(c){r(n!==c?h0(n,c):c);}finally{u(),e.off("drain",s);}}async function To(t,e,r,{end:i}){Hr(e)&&(e=e.writable);let n=e.getWriter();try{for await(let o of t)await n.ready,n.write(o).catch(()=>{});await n.ready,i&&await n.close(),r();}catch(o){try{await n.abort(o),r(o);}catch(s){r(s);}}}function A0(...t){return Mh(t,f0(E0(t)))}function Mh(t,e,r){if(t.length===1&&a0(t[0])&&(t=t[0]),t.length<2)throw new d0("streams");let i=new v0,n=i.signal,o=r?.signal,s=[];w0(o,"options.signal");function a(){y(new y0);}o?.addEventListener("abort",a);let u,c,h=[],d=0;function g(C){y(C,--d===0);}function y(C,R){if(C&&(!u||u.code==="ERR_STREAM_PREMATURE_CLOSE")&&(u=C),!(!u&&!R)){for(;h.length;)h.shift()(u);o?.removeEventListener("abort",a),i.abort(),R&&(u||s.forEach(U=>U()),wi.nextTick(e,u,c));}}let w;for(let C=0;C0,W=U||r?.end!==!1,K=C===t.length-1;if(kh(R)){let z=function(Q){Q&&Q.name!=="AbortError"&&Q.code!=="ERR_STREAM_PREMATURE_CLOSE"&&g(Q);};if(W){let{destroy:Q,cleanup:de}=xh(R,U,N);h.push(Q),vo(R)&&K&&s.push(de);}R.on("error",z),vo(R)&&K&&s.push(()=>{R.removeListener("error",z);});}if(C===0)if(typeof R=="function"){if(w=R({signal:n}),!cr(w))throw new mo("Iterable, AsyncIterable or Stream","source",w)}else cr(R)||wn(R)||Hr(R)?w=R:w=Oh.from(R);else if(typeof R=="function"){if(Hr(w)){var E;w=Io((E=w)===null||E===void 0?void 0:E.readable);}else w=Io(w);if(w=R(w,{signal:n}),U){if(!cr(w,!0))throw new mo("AsyncIterable",`transform[${C-1}]`,w)}else {var S;So||(So=_o());let z=new So({objectMode:!0}),Q=(S=w)===null||S===void 0?void 0:S.then;if(typeof Q=="function")d++,Q.call(w,pe=>{c=pe,pe!=null&&z.write(pe),W&&z.end(),wi.nextTick(g);},pe=>{z.destroy(pe),wi.nextTick(g,pe);});else if(cr(w,!0))d++,bn(w,z,g,{end:W});else if(Eo(w)||Hr(w)){let pe=w.readable||w;d++,bn(pe,z,g,{end:W});}else throw new mo("AsyncIterable or Promise","destination",w);w=z;let{destroy:de,cleanup:Gt}=xh(w,!1,!0);h.push(de),K&&s.push(Gt);}}else if(kh(R)){if(wn(w)){d+=2;let z=I0(w,R,g,{end:W});vo(R)&&K&&s.push(z);}else if(Hr(w)||Eo(w)){let z=w.readable||w;d++,bn(z,R,g,{end:W});}else if(cr(w))d++,bn(w,R,g,{end:W});else throw new Ro("val",["Readable","Iterable","AsyncIterable","ReadableStream","TransformStream"],w);w=R;}else if(_0(R)){if(wn(w))d++,To(Io(w),R,g,{end:W});else if(Eo(w)||cr(w))d++,To(w,R,g,{end:W});else if(Hr(w))d++,To(w.readable,R,g,{end:W});else throw new Ro("val",["Readable","Iterable","AsyncIterable","ReadableStream","TransformStream"],w);w=R;}else w=Oh.from(R);}return (n!=null&&n.aborted||o!=null&&o.aborted)&&wi.nextTick(a),w}function I0(t,e,r,{end:i}){let n=!1;if(e.on("close",()=>{n||r(new g0);}),t.pipe(e,{end:!1}),i){let s=function(){n=!0,e.end();};m0(t)?wi.nextTick(s):t.once("end",s);}else r();return _n(t,{readable:!0,writable:!1},s=>{let a=t._readableState;s&&s.code==="ERR_STREAM_PREMATURE_CLOSE"&&a&&a.ended&&!a.errored&&!a.errorEmitted?t.once("end",r).once("error",r):r(s);}),_n(e,{readable:!1,writable:!0},r)}Lh.exports={pipelineImpl:Mh,pipeline:A0};});var Bo=M((dC,Fh)=>{v();m();_();var{pipeline:T0}=mn(),vn=nt(),{destroyer:R0}=tr(),{isNodeStream:En,isReadable:Uh,isWritable:Nh,isWebStream:Co,isTransformStream:hr,isWritableStream:qh,isReadableStream:Dh}=tt(),{AbortError:C0,codes:{ERR_INVALID_ARG_VALUE:jh,ERR_MISSING_ARGS:B0}}=Se(),P0=mt();Fh.exports=function(...e){if(e.length===0)throw new B0("streams");if(e.length===1)return vn.from(e[0]);let r=[...e];if(typeof e[0]=="function"&&(e[0]=vn.from(e[0])),typeof e[e.length-1]=="function"){let y=e.length-1;e[y]=vn.from(e[y]);}for(let y=0;y0&&!(Nh(e[y])||qh(e[y])||hr(e[y])))throw new jh(`streams[${y}]`,r[y],"must be writable")}let i,n,o,s,a;function u(y){let w=s;s=null,w?w(y):y?a.destroy(y):!g&&!d&&a.destroy();}let c=e[0],h=T0(e,u),d=!!(Nh(c)||qh(c)||hr(c)),g=!!(Uh(h)||Dh(h)||hr(h));if(a=new vn({writableObjectMode:!!(c!=null&&c.writableObjectMode),readableObjectMode:!!(h!=null&&h.writableObjectMode),writable:d,readable:g}),d){if(En(c))a._write=function(w,E,S){c.write(w,E)?S():i=S;},a._final=function(w){c.end(),n=w;},c.on("drain",function(){if(i){let w=i;i=null,w();}});else if(Co(c)){let E=(hr(c)?c.writable:c).getWriter();a._write=async function(S,I,C){try{await E.ready,E.write(S).catch(()=>{}),C();}catch(R){C(R);}},a._final=async function(S){try{await E.ready,E.close().catch(()=>{}),n=S;}catch(I){S(I);}};}let y=hr(h)?h.readable:h;P0(y,()=>{if(n){let w=n;n=null,w();}});}if(g){if(En(h))h.on("readable",function(){if(o){let y=o;o=null,y();}}),h.on("end",function(){a.push(null);}),a._read=function(){for(;;){let y=h.read();if(y===null){o=a._read;return}if(!a.push(y))return}};else if(Co(h)){let w=(hr(h)?h.readable:h).getReader();a._read=async function(){for(;;)try{let{value:E,done:S}=await w.read();if(!a.push(E))return;if(S){a.push(null);return}}catch{return}};}}return a._destroy=function(y,w){!y&&s!==null&&(y=new C0),o=null,i=null,n=null,s===null?w(y):(s=w,En(h)&&R0(h,y));},a};});var Qh=M((SC,ko)=>{v();m();_();var Vh=globalThis.AbortController||Hi().AbortController,{codes:{ERR_INVALID_ARG_VALUE:O0,ERR_INVALID_ARG_TYPE:_i,ERR_MISSING_ARGS:k0,ERR_OUT_OF_RANGE:x0},AbortError:st}=Se(),{validateAbortSignal:dr,validateInteger:M0,validateObject:pr}=fi(),L0=ce().Symbol("kWeak"),{finished:U0}=mt(),N0=Bo(),{addAbortSignalNoValidate:q0}=ci(),{isWritable:D0,isNodeStream:j0}=tt(),{ArrayPrototypePush:F0,MathFloor:W0,Number:$0,NumberIsNaN:H0,Promise:Wh,PromiseReject:$h,PromisePrototypeThen:V0,Symbol:zh}=ce(),Sn=zh("kEmpty"),Hh=zh("kEof");function z0(t,e){if(e!=null&&pr(e,"options"),e?.signal!=null&&dr(e.signal,"options.signal"),j0(t)&&!D0(t))throw new O0("stream",t,"must be writable");let r=N0(this,t);return e!=null&&e.signal&&q0(e.signal,r),r}function An(t,e){if(typeof t!="function")throw new _i("fn",["Function","AsyncFunction"],t);e!=null&&pr(e,"options"),e?.signal!=null&&dr(e.signal,"options.signal");let r=1;return e?.concurrency!=null&&(r=W0(e.concurrency)),M0(r,"concurrency",1),async function*(){var n,o;let s=new Vh,a=this,u=[],c=s.signal,h={signal:c},d=()=>s.abort();e!=null&&(n=e.signal)!==null&&n!==void 0&&n.aborted&&d(),e==null||(o=e.signal)===null||o===void 0||o.addEventListener("abort",d);let g,y,w=!1;function E(){w=!0;}async function S(){try{for await(let R of a){var I;if(w)return;if(c.aborted)throw new st;try{R=t(R,h);}catch(U){R=$h(U);}R!==Sn&&(typeof((I=R)===null||I===void 0?void 0:I.catch)=="function"&&R.catch(E),u.push(R),g&&(g(),g=null),!w&&u.length&&u.length>=r&&await new Wh(U=>{y=U;}));}u.push(Hh);}catch(R){let U=$h(R);V0(U,void 0,E),u.push(U);}finally{var C;w=!0,g&&(g(),g=null),e==null||(C=e.signal)===null||C===void 0||C.removeEventListener("abort",d);}}S();try{for(;;){for(;u.length>0;){let I=await u[0];if(I===Hh)return;if(c.aborted)throw new st;I!==Sn&&(yield I),u.shift(),y&&(y(),y=null);}await new Wh(I=>{g=I;});}}finally{s.abort(),w=!0,y&&(y(),y=null);}}.call(this)}function K0(t=void 0){return t!=null&&pr(t,"options"),t?.signal!=null&&dr(t.signal,"options.signal"),async function*(){let r=0;for await(let n of this){var i;if(t!=null&&(i=t.signal)!==null&&i!==void 0&&i.aborted)throw new st({cause:t.signal.reason});yield [r++,n];}}.call(this)}async function Kh(t,e=void 0){for await(let r of Oo.call(this,t,e))return !0;return !1}async function G0(t,e=void 0){if(typeof t!="function")throw new _i("fn",["Function","AsyncFunction"],t);return !await Kh.call(this,async(...r)=>!await t(...r),e)}async function Q0(t,e){for await(let r of Oo.call(this,t,e))return r}async function Y0(t,e){if(typeof t!="function")throw new _i("fn",["Function","AsyncFunction"],t);async function r(i,n){return await t(i,n),Sn}for await(let i of An.call(this,r,e));}function Oo(t,e){if(typeof t!="function")throw new _i("fn",["Function","AsyncFunction"],t);async function r(i,n){return await t(i,n)?i:Sn}return An.call(this,r,e)}var Po=class extends k0{constructor(){super("reduce"),this.message="Reduce of an empty stream requires an initial value";}};async function J0(t,e,r){var i;if(typeof t!="function")throw new _i("reducer",["Function","AsyncFunction"],t);r!=null&&pr(r,"options"),r?.signal!=null&&dr(r.signal,"options.signal");let n=arguments.length>1;if(r!=null&&(i=r.signal)!==null&&i!==void 0&&i.aborted){let c=new st(void 0,{cause:r.signal.reason});throw this.once("error",()=>{}),await U0(this.destroy(c)),c}let o=new Vh,s=o.signal;if(r!=null&&r.signal){let c={once:!0,[L0]:this};r.signal.addEventListener("abort",()=>o.abort(),c);}let a=!1;try{for await(let c of this){var u;if(a=!0,r!=null&&(u=r.signal)!==null&&u!==void 0&&u.aborted)throw new st;n?e=await t(e,c,{signal:s}):(e=c,n=!0);}if(!a&&!n)throw new Po}finally{o.abort();}return e}async function X0(t){t!=null&&pr(t,"options"),t?.signal!=null&&dr(t.signal,"options.signal");let e=[];for await(let i of this){var r;if(t!=null&&(r=t.signal)!==null&&r!==void 0&&r.aborted)throw new st(void 0,{cause:t.signal.reason});F0(e,i);}return e}function Z0(t,e){let r=An.call(this,t,e);return async function*(){for await(let n of r)yield*n;}.call(this)}function Gh(t){if(t=$0(t),H0(t))return 0;if(t<0)throw new x0("number",">= 0",t);return t}function em(t,e=void 0){return e!=null&&pr(e,"options"),e?.signal!=null&&dr(e.signal,"options.signal"),t=Gh(t),async function*(){var i;if(e!=null&&(i=e.signal)!==null&&i!==void 0&&i.aborted)throw new st;for await(let o of this){var n;if(e!=null&&(n=e.signal)!==null&&n!==void 0&&n.aborted)throw new st;t--<=0&&(yield o);}}.call(this)}function tm(t,e=void 0){return e!=null&&pr(e,"options"),e?.signal!=null&&dr(e.signal,"options.signal"),t=Gh(t),async function*(){var i;if(e!=null&&(i=e.signal)!==null&&i!==void 0&&i.aborted)throw new st;for await(let o of this){var n;if(e!=null&&(n=e.signal)!==null&&n!==void 0&&n.aborted)throw new st;if(t-- >0)yield o;else return}}.call(this)}ko.exports.streamReturningOperators={asIndexedPairs:K0,drop:em,filter:Oo,flatMap:Z0,map:An,take:tm,compose:z0};ko.exports.promiseReturningOperators={every:G0,forEach:Y0,reduce:J0,toArray:X0,some:Kh,find:Q0};});var xo=M((xC,Yh)=>{v();m();_();var{ArrayPrototypePop:rm,Promise:im}=ce(),{isIterable:nm,isNodeStream:sm,isWebStream:om}=tt(),{pipelineImpl:am}=mn(),{finished:lm}=mt();Mo();function um(...t){return new im((e,r)=>{let i,n,o=t[t.length-1];if(o&&typeof o=="object"&&!sm(o)&&!nm(o)&&!om(o)){let s=rm(t);i=s.signal,n=s.end;}am(t,(s,a)=>{s?r(s):e(a);},{signal:i,end:n});})}Yh.exports={finished:lm,pipeline:um};});var Mo=M(($C,sd)=>{v();m();_();var{Buffer:fm}=(ye(),X(_e)),{ObjectDefineProperty:Tt,ObjectKeys:Zh,ReflectApply:ed}=ce(),{promisify:{custom:td}}=Je(),{streamReturningOperators:Jh,promiseReturningOperators:Xh}=Qh(),{codes:{ERR_ILLEGAL_CONSTRUCTOR:rd}}=Se(),cm=Bo(),{pipeline:id}=mn(),{destroyer:hm}=tr(),nd=mt(),Lo=xo(),Uo=tt(),le=sd.exports=tn().Stream;le.isDisturbed=Uo.isDisturbed;le.isErrored=Uo.isErrored;le.isReadable=Uo.isReadable;le.Readable=di();for(let t of Zh(Jh)){let r=function(...i){if(new.target)throw rd();return le.Readable.from(ed(e,this,i))};let e=Jh[t];Tt(r,"name",{__proto__:null,value:e.name}),Tt(r,"length",{__proto__:null,value:e.length}),Tt(le.Readable.prototype,t,{__proto__:null,value:r,enumerable:!1,configurable:!0,writable:!0});}for(let t of Zh(Xh)){let r=function(...n){if(new.target)throw rd();return ed(e,this,n)};let e=Xh[t];Tt(r,"name",{__proto__:null,value:e.name}),Tt(r,"length",{__proto__:null,value:e.length}),Tt(le.Readable.prototype,t,{__proto__:null,value:r,enumerable:!1,configurable:!0,writable:!0});}le.Writable=uo();le.Duplex=nt();le.Transform=bo();le.PassThrough=_o();le.pipeline=id;var{addAbortSignal:dm}=ci();le.addAbortSignal=dm;le.finished=nd;le.destroy=hm;le.compose=cm;Tt(le,"promises",{__proto__:null,configurable:!0,enumerable:!0,get(){return Lo}});Tt(id,td,{__proto__:null,enumerable:!0,get(){return Lo.pipeline}});Tt(nd,td,{__proto__:null,enumerable:!0,get(){return Lo.finished}});le.Stream=le;le._isUint8Array=function(e){return e instanceof Uint8Array};le._uint8ArrayToBuffer=function(e){return fm.from(e.buffer,e.byteOffset,e.byteLength)};});var Dt=M((ZC,ue)=>{v();m();_();var he=Mo(),pm=xo(),gm=he.Readable.destroy;ue.exports=he.Readable;ue.exports._uint8ArrayToBuffer=he._uint8ArrayToBuffer;ue.exports._isUint8Array=he._isUint8Array;ue.exports.isDisturbed=he.isDisturbed;ue.exports.isErrored=he.isErrored;ue.exports.isReadable=he.isReadable;ue.exports.Readable=he.Readable;ue.exports.Writable=he.Writable;ue.exports.Duplex=he.Duplex;ue.exports.Transform=he.Transform;ue.exports.PassThrough=he.PassThrough;ue.exports.addAbortSignal=he.addAbortSignal;ue.exports.finished=he.finished;ue.exports.destroy=he.destroy;ue.exports.destroy=gm;ue.exports.pipeline=he.pipeline;ue.exports.compose=he.compose;Object.defineProperty(he,"promises",{configurable:!0,enumerable:!0,get(){return pm}});ue.exports.Stream=he.Stream;ue.exports.default=ue.exports;});var od=M((uB,qo)=>{v();m();_();typeof Object.create=="function"?qo.exports=function(e,r){r&&(e.super_=r,e.prototype=Object.create(r.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}));}:qo.exports=function(e,r){if(r){e.super_=r;var i=function(){};i.prototype=r.prototype,e.prototype=new i,e.prototype.constructor=e;}};});var ud=M((_B,ld)=>{v();m();_();var{Buffer:ze}=(ye(),X(_e)),ad=Symbol.for("BufferList");function ee(t){if(!(this instanceof ee))return new ee(t);ee._init.call(this,t);}ee._init=function(e){Object.defineProperty(this,ad,{value:!0}),this._bufs=[],this.length=0,e&&this.append(e);};ee.prototype._new=function(e){return new ee(e)};ee.prototype._offset=function(e){if(e===0)return [0,0];let r=0;for(let i=0;ithis.length||e<0)return;let r=this._offset(e);return this._bufs[r[0]][r[1]]};ee.prototype.slice=function(e,r){return typeof e=="number"&&e<0&&(e+=this.length),typeof r=="number"&&r<0&&(r+=this.length),this.copy(null,0,e,r)};ee.prototype.copy=function(e,r,i,n){if((typeof i!="number"||i<0)&&(i=0),(typeof n!="number"||n>this.length)&&(n=this.length),i>=this.length||n<=0)return e||ze.alloc(0);let o=!!e,s=this._offset(i),a=n-i,u=a,c=o&&r||0,h=s[1];if(i===0&&n===this.length){if(!o)return this._bufs.length===1?this._bufs[0]:ze.concat(this._bufs,this.length);for(let d=0;dg)this._bufs[d].copy(e,c,h),c+=g;else {this._bufs[d].copy(e,c,h,h+u),c+=g;break}u-=g,h&&(h=0);}return e.length>c?e.slice(0,c):e};ee.prototype.shallowSlice=function(e,r){if(e=e||0,r=typeof r!="number"?this.length:r,e<0&&(e+=this.length),r<0&&(r+=this.length),e===r)return this._new();let i=this._offset(e),n=this._offset(r),o=this._bufs.slice(i[0],n[0]+1);return n[1]===0?o.pop():o[o.length-1]=o[o.length-1].slice(0,n[1]),i[1]!==0&&(o[0]=o[0].slice(i[1])),this._new(o)};ee.prototype.toString=function(e,r,i){return this.slice(r,i).toString(e)};ee.prototype.consume=function(e){if(e=Math.trunc(e),Number.isNaN(e)||e<=0)return this;for(;this._bufs.length;)if(e>=this._bufs[0].length)e-=this._bufs[0].length,this.length-=this._bufs[0].length,this._bufs.shift();else {this._bufs[0]=this._bufs[0].slice(e),this.length-=e;break}return this};ee.prototype.duplicate=function(){let e=this._new();for(let r=0;rthis.length?this.length:e;let i=this._offset(e),n=i[0],o=i[1];for(;n=t.length){let u=s.indexOf(t,o);if(u!==-1)return this._reverseOffset([n,u]);o=s.length-t.length+1;}else {let u=this._reverseOffset([n,o]);if(this._match(u,t))return u;o++;}o=0;}return -1};ee.prototype._match=function(t,e){if(this.length-t{v();m();_();var Do=Dt().Duplex,ym=od(),mi=ud();function Ee(t){if(!(this instanceof Ee))return new Ee(t);if(typeof t=="function"){this._callback=t;let e=function(i){this._callback&&(this._callback(i),this._callback=null);}.bind(this);this.on("pipe",function(i){i.on("error",e);}),this.on("unpipe",function(i){i.removeListener("error",e);}),t=null;}mi._init.call(this,t),Do.call(this);}ym(Ee,Do);Object.assign(Ee.prototype,mi.prototype);Ee.prototype._new=function(e){return new Ee(e)};Ee.prototype._write=function(e,r,i){this._appendBuffer(e),typeof i=="function"&&i();};Ee.prototype._read=function(e){if(!this.length)return this.push(null);e=Math.min(e,this.length),this.push(this.slice(0,e)),this.consume(e);};Ee.prototype.end=function(e){Do.prototype.end.call(this,e),this._callback&&(this._callback(null,this.slice()),this._callback=null);};Ee.prototype._destroy=function(e,r){this._bufs.length=0,this.length=0,r(e);};Ee.prototype._isBufferList=function(e){return e instanceof Ee||e instanceof mi||Ee.isBufferList(e)};Ee.isBufferList=mi.isBufferList;In.exports=Ee;In.exports.BufferListStream=Ee;In.exports.BufferList=mi;});var hd=M((DB,cd)=>{v();m();_();var jo=class{constructor(){this.cmd=null,this.retain=!1,this.qos=0,this.dup=!1,this.length=-1,this.topic=null,this.payload=null;}};cd.exports=jo;});var Fo=M((QB,dd)=>{v();m();_();var L=dd.exports,{Buffer:Oe}=(ye(),X(_e));L.types={0:"reserved",1:"connect",2:"connack",3:"publish",4:"puback",5:"pubrec",6:"pubrel",7:"pubcomp",8:"subscribe",9:"suback",10:"unsubscribe",11:"unsuback",12:"pingreq",13:"pingresp",14:"disconnect",15:"auth"};L.requiredHeaderFlags={1:0,2:0,4:0,5:0,6:2,7:0,8:2,9:0,10:2,11:0,12:0,13:0,14:0,15:0};L.requiredHeaderFlagsErrors={};for(let t in L.requiredHeaderFlags){let e=L.requiredHeaderFlags[t];L.requiredHeaderFlagsErrors[t]="Invalid header flag bits, must be 0x"+e.toString(16)+" for "+L.types[t]+" packet";}L.codes={};for(let t in L.types){let e=L.types[t];L.codes[e]=t;}L.CMD_SHIFT=4;L.CMD_MASK=240;L.DUP_MASK=8;L.QOS_MASK=3;L.QOS_SHIFT=1;L.RETAIN_MASK=1;L.VARBYTEINT_MASK=127;L.VARBYTEINT_FIN_MASK=128;L.VARBYTEINT_MAX=268435455;L.SESSIONPRESENT_MASK=1;L.SESSIONPRESENT_HEADER=Oe.from([L.SESSIONPRESENT_MASK]);L.CONNACK_HEADER=Oe.from([L.codes.connack<[0,1].map(r=>[0,1].map(i=>{let n=Oe.alloc(1);return n.writeUInt8(L.codes[t]<Oe.from([t]));L.EMPTY={pingreq:Oe.from([L.codes.pingreq<<4,0]),pingresp:Oe.from([L.codes.pingresp<<4,0]),disconnect:Oe.from([L.codes.disconnect<<4,0])};L.MQTT5_PUBACK_PUBREC_CODES={0:"Success",16:"No matching subscribers",128:"Unspecified error",131:"Implementation specific error",135:"Not authorized",144:"Topic Name invalid",145:"Packet identifier in use",151:"Quota exceeded",153:"Payload format invalid"};L.MQTT5_PUBREL_PUBCOMP_CODES={0:"Success",146:"Packet Identifier not found"};L.MQTT5_SUBACK_CODES={0:"Granted QoS 0",1:"Granted QoS 1",2:"Granted QoS 2",128:"Unspecified error",131:"Implementation specific error",135:"Not authorized",143:"Topic Filter invalid",145:"Packet Identifier in use",151:"Quota exceeded",158:"Shared Subscriptions not supported",161:"Subscription Identifiers not supported",162:"Wildcard Subscriptions not supported"};L.MQTT5_UNSUBACK_CODES={0:"Success",17:"No subscription existed",128:"Unspecified error",131:"Implementation specific error",135:"Not authorized",143:"Topic Filter invalid",145:"Packet Identifier in use"};L.MQTT5_DISCONNECT_CODES={0:"Normal disconnection",4:"Disconnect with Will Message",128:"Unspecified error",129:"Malformed Packet",130:"Protocol Error",131:"Implementation specific error",135:"Not authorized",137:"Server busy",139:"Server shutting down",141:"Keep Alive timeout",142:"Session taken over",143:"Topic Filter invalid",144:"Topic Name invalid",147:"Receive Maximum exceeded",148:"Topic Alias invalid",149:"Packet too large",150:"Message rate too high",151:"Quota exceeded",152:"Administrative action",153:"Payload format invalid",154:"Retain not supported",155:"QoS not supported",156:"Use another server",157:"Server moved",158:"Shared Subscriptions not supported",159:"Connection rate exceeded",160:"Maximum connect time",161:"Subscription Identifiers not supported",162:"Wildcard Subscriptions not supported"};L.MQTT5_AUTH_CODES={0:"Success",24:"Continue authentication",25:"Re-authenticate"};});var gd=M((sP,pd)=>{v();m();_();var Vr=1e3,zr=Vr*60,Kr=zr*60,gr=Kr*24,bm=gr*7,wm=gr*365.25;pd.exports=function(t,e){e=e||{};var r=typeof t;if(r==="string"&&t.length>0)return _m(t);if(r==="number"&&isFinite(t))return e.long?vm(t):mm(t);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(t))};function _m(t){if(t=String(t),!(t.length>100)){var e=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(t);if(e){var r=parseFloat(e[1]),i=(e[2]||"ms").toLowerCase();switch(i){case"years":case"year":case"yrs":case"yr":case"y":return r*wm;case"weeks":case"week":case"w":return r*bm;case"days":case"day":case"d":return r*gr;case"hours":case"hour":case"hrs":case"hr":case"h":return r*Kr;case"minutes":case"minute":case"mins":case"min":case"m":return r*zr;case"seconds":case"second":case"secs":case"sec":case"s":return r*Vr;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return r;default:return}}}}function mm(t){var e=Math.abs(t);return e>=gr?Math.round(t/gr)+"d":e>=Kr?Math.round(t/Kr)+"h":e>=zr?Math.round(t/zr)+"m":e>=Vr?Math.round(t/Vr)+"s":t+"ms"}function vm(t){var e=Math.abs(t);return e>=gr?Tn(t,e,gr,"day"):e>=Kr?Tn(t,e,Kr,"hour"):e>=zr?Tn(t,e,zr,"minute"):e>=Vr?Tn(t,e,Vr,"second"):t+" ms"}function Tn(t,e,r,i){var n=e>=r*1.5;return Math.round(t/r)+" "+i+(n?"s":"")}});var bd=M((gP,yd)=>{v();m();_();function Em(t){r.debug=r,r.default=r,r.coerce=u,r.disable=o,r.enable=n,r.enabled=s,r.humanize=gd(),r.destroy=c,Object.keys(t).forEach(h=>{r[h]=t[h];}),r.names=[],r.skips=[],r.formatters={};function e(h){let d=0;for(let g=0;g{if(W==="%%")return "%";U++;let z=r.formatters[K];if(typeof z=="function"){let Q=S[U];W=z.call(I,Q),S.splice(U,1),U--;}return W}),r.formatArgs.call(I,S),(I.log||r.log).apply(I,S);}return E.namespace=h,E.useColors=r.useColors(),E.color=r.selectColor(h),E.extend=i,E.destroy=r.destroy,Object.defineProperty(E,"enabled",{enumerable:!0,configurable:!1,get:()=>g!==null?g:(y!==r.namespaces&&(y=r.namespaces,w=r.enabled(h)),w),set:S=>{g=S;}}),typeof r.init=="function"&&r.init(E),E}function i(h,d){let g=r(this.namespace+(typeof d>"u"?":":d)+h);return g.log=this.log,g}function n(h){r.save(h),r.namespaces=h,r.names=[],r.skips=[];let d,g=(typeof h=="string"?h:"").split(/[\s,]+/),y=g.length;for(d=0;d"-"+d)].join(",");return r.enable(""),h}function s(h){if(h[h.length-1]==="*")return !0;let d,g;for(d=0,g=r.skips.length;d{v();m();_();xe.formatArgs=Am;xe.save=Im;xe.load=Tm;xe.useColors=Sm;xe.storage=Rm();xe.destroy=(()=>{let t=!1;return ()=>{t||(t=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."));}})();xe.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function Sm(){return typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs)?!0:typeof B<"u"&&B.userAgent&&B.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)?!1:typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof B<"u"&&B.userAgent&&B.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||typeof B<"u"&&B.userAgent&&B.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}function Am(t){if(t[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+t[0]+(this.useColors?"%c ":" ")+"+"+Rn.exports.humanize(this.diff),!this.useColors)return;let e="color: "+this.color;t.splice(1,0,e,"color: inherit");let r=0,i=0;t[0].replace(/%[a-zA-Z%]/g,n=>{n!=="%%"&&(r++,n==="%c"&&(i=r));}),t.splice(i,0,e);}xe.log=console.debug||console.log||(()=>{});function Im(t){try{t?xe.storage.setItem("debug",t):xe.storage.removeItem("debug");}catch{}}function Tm(){let t;try{t=xe.storage.getItem("debug");}catch{}return !t&&typeof P<"u"&&"env"in P&&(t=P.env.DEBUG),t}function Rm(){try{return localStorage}catch{}}Rn.exports=bd()(xe);var{formatters:Cm}=Rn.exports;Cm.j=function(t){try{return JSON.stringify(t)}catch(e){return "[UnexpectedJSONParseError]: "+e.message}};});var md=M((MP,_d)=>{v();m();_();var Bm=fd(),{EventEmitter:Pm}=(ir(),X(rr)),wd=hd(),V=Fo(),D=ot()("mqtt-packet:parser"),Wo=class t extends Pm{constructor(){super(),this.parser=this.constructor.parser;}static parser(e){return this instanceof t?(this.settings=e||{},this._states=["_parseHeader","_parseLength","_parsePayload","_newPacket"],this._resetState(),this):new t().parser(e)}_resetState(){D("_resetState: resetting packet, error, _list, and _stateCounter"),this.packet=new wd,this.error=null,this._list=Bm(),this._stateCounter=0;}parse(e){for(this.error&&this._resetState(),this._list.append(e),D("parse: current state: %s",this._states[this._stateCounter]);(this.packet.length!==-1||this._list.length>0)&&this[this._states[this._stateCounter]]()&&!this.error;)this._stateCounter++,D("parse: state complete. _stateCounter is now: %d",this._stateCounter),D("parse: packet.length: %d, buffer list length: %d",this.packet.length,this._list.length),this._stateCounter>=this._states.length&&(this._stateCounter=0);return D("parse: exited while loop. packet: %d, buffer list length: %d",this.packet.length,this._list.length),this._list.length}_parseHeader(){let e=this._list.readUInt8(0),r=e>>V.CMD_SHIFT;this.packet.cmd=V.types[r];let i=e&15,n=V.requiredHeaderFlags[r];return n!=null&&i!==n?this._emitError(new Error(V.requiredHeaderFlagsErrors[r])):(this.packet.retain=(e&V.RETAIN_MASK)!==0,this.packet.qos=e>>V.QOS_SHIFT&V.QOS_MASK,this.packet.qos>2?this._emitError(new Error("Packet must not have both QoS bits set to 1")):(this.packet.dup=(e&V.DUP_MASK)!==0,D("_parseHeader: packet: %o",this.packet),this._list.consume(1),!0))}_parseLength(){let e=this._parseVarByteNum(!0);return e&&(this.packet.length=e.value,this._list.consume(e.bytes)),D("_parseLength %d",e.value),!!e}_parsePayload(){D("_parsePayload: payload %O",this._list);let e=!1;if(this.packet.length===0||this._list.length>=this.packet.length){switch(this._pos=0,this.packet.cmd){case"connect":this._parseConnect();break;case"connack":this._parseConnack();break;case"publish":this._parsePublish();break;case"puback":case"pubrec":case"pubrel":case"pubcomp":this._parseConfirmation();break;case"subscribe":this._parseSubscribe();break;case"suback":this._parseSuback();break;case"unsubscribe":this._parseUnsubscribe();break;case"unsuback":this._parseUnsuback();break;case"pingreq":case"pingresp":break;case"disconnect":this._parseDisconnect();break;case"auth":this._parseAuth();break;default:this._emitError(new Error("Not supported"));}e=!0;}return D("_parsePayload complete result: %s",e),e}_parseConnect(){D("_parseConnect");let e,r,i,n,o={},s=this.packet,a=this._parseString();if(a===null)return this._emitError(new Error("Cannot parse protocolId"));if(a!=="MQTT"&&a!=="MQIsdp")return this._emitError(new Error("Invalid protocolId"));if(s.protocolId=a,this._pos>=this._list.length)return this._emitError(new Error("Packet too short"));if(s.protocolVersion=this._list.readUInt8(this._pos),s.protocolVersion>=128&&(s.bridgeMode=!0,s.protocolVersion=s.protocolVersion-128),s.protocolVersion!==3&&s.protocolVersion!==4&&s.protocolVersion!==5)return this._emitError(new Error("Invalid protocol version"));if(this._pos++,this._pos>=this._list.length)return this._emitError(new Error("Packet too short"));if(this._list.readUInt8(this._pos)&1)return this._emitError(new Error("Connect flag bit 0 must be 0, but got 1"));o.username=this._list.readUInt8(this._pos)&V.USERNAME_MASK,o.password=this._list.readUInt8(this._pos)&V.PASSWORD_MASK,o.will=this._list.readUInt8(this._pos)&V.WILL_FLAG_MASK;let u=!!(this._list.readUInt8(this._pos)&V.WILL_RETAIN_MASK),c=(this._list.readUInt8(this._pos)&V.WILL_QOS_MASK)>>V.WILL_QOS_SHIFT;if(o.will)s.will={},s.will.retain=u,s.will.qos=c;else {if(u)return this._emitError(new Error("Will Retain Flag must be set to zero when Will Flag is set to 0"));if(c)return this._emitError(new Error("Will QoS must be set to zero when Will Flag is set to 0"))}if(s.clean=(this._list.readUInt8(this._pos)&V.CLEAN_SESSION_MASK)!==0,this._pos++,s.keepalive=this._parseNum(),s.keepalive===-1)return this._emitError(new Error("Packet too short"));if(s.protocolVersion===5){let d=this._parseProperties();Object.getOwnPropertyNames(d).length&&(s.properties=d);}let h=this._parseString();if(h===null)return this._emitError(new Error("Packet too short"));if(s.clientId=h,D("_parseConnect: packet.clientId: %s",s.clientId),o.will){if(s.protocolVersion===5){let d=this._parseProperties();Object.getOwnPropertyNames(d).length&&(s.will.properties=d);}if(e=this._parseString(),e===null)return this._emitError(new Error("Cannot parse will topic"));if(s.will.topic=e,D("_parseConnect: packet.will.topic: %s",s.will.topic),r=this._parseBuffer(),r===null)return this._emitError(new Error("Cannot parse will payload"));s.will.payload=r,D("_parseConnect: packet.will.paylaod: %s",s.will.payload);}if(o.username){if(n=this._parseString(),n===null)return this._emitError(new Error("Cannot parse username"));s.username=n,D("_parseConnect: packet.username: %s",s.username);}if(o.password){if(i=this._parseBuffer(),i===null)return this._emitError(new Error("Cannot parse password"));s.password=i;}return this.settings=s,D("_parseConnect: complete"),s}_parseConnack(){D("_parseConnack");let e=this.packet;if(this._list.length<1)return null;let r=this._list.readUInt8(this._pos++);if(r>1)return this._emitError(new Error("Invalid connack flags, bits 7-1 must be set to 0"));if(e.sessionPresent=!!(r&V.SESSIONPRESENT_MASK),this.settings.protocolVersion===5)this._list.length>=2?e.reasonCode=this._list.readUInt8(this._pos++):e.reasonCode=0;else {if(this._list.length<2)return null;e.returnCode=this._list.readUInt8(this._pos++);}if(e.returnCode===-1||e.reasonCode===-1)return this._emitError(new Error("Cannot parse return code"));if(this.settings.protocolVersion===5){let i=this._parseProperties();Object.getOwnPropertyNames(i).length&&(e.properties=i);}D("_parseConnack: complete");}_parsePublish(){D("_parsePublish");let e=this.packet;if(e.topic=this._parseString(),e.topic===null)return this._emitError(new Error("Cannot parse topic"));if(!(e.qos>0&&!this._parseMessageId())){if(this.settings.protocolVersion===5){let r=this._parseProperties();Object.getOwnPropertyNames(r).length&&(e.properties=r);}e.payload=this._list.slice(this._pos,e.length),D("_parsePublish: payload from buffer list: %o",e.payload);}}_parseSubscribe(){D("_parseSubscribe");let e=this.packet,r,i,n,o,s,a,u;if(e.subscriptions=[],!!this._parseMessageId()){if(this.settings.protocolVersion===5){let c=this._parseProperties();Object.getOwnPropertyNames(c).length&&(e.properties=c);}if(e.length<=0)return this._emitError(new Error("Malformed subscribe, no payload specified"));for(;this._pos=e.length)return this._emitError(new Error("Malformed Subscribe Payload"));if(i=this._parseByte(),this.settings.protocolVersion===5){if(i&192)return this._emitError(new Error("Invalid subscribe topic flag bits, bits 7-6 must be 0"))}else if(i&252)return this._emitError(new Error("Invalid subscribe topic flag bits, bits 7-2 must be 0"));if(n=i&V.SUBSCRIBE_OPTIONS_QOS_MASK,n>2)return this._emitError(new Error("Invalid subscribe QoS, must be <= 2"));if(a=(i>>V.SUBSCRIBE_OPTIONS_NL_SHIFT&V.SUBSCRIBE_OPTIONS_NL_MASK)!==0,s=(i>>V.SUBSCRIBE_OPTIONS_RAP_SHIFT&V.SUBSCRIBE_OPTIONS_RAP_MASK)!==0,o=i>>V.SUBSCRIBE_OPTIONS_RH_SHIFT&V.SUBSCRIBE_OPTIONS_RH_MASK,o>2)return this._emitError(new Error("Invalid retain handling, must be <= 2"));u={topic:r,qos:n},this.settings.protocolVersion===5?(u.nl=a,u.rap=s,u.rh=o):this.settings.bridgeMode&&(u.rh=0,u.rap=!0,u.nl=!0),D("_parseSubscribe: push subscription `%s` to subscription",u),e.subscriptions.push(u);}}}_parseSuback(){D("_parseSuback");let e=this.packet;if(this.packet.granted=[],!!this._parseMessageId()){if(this.settings.protocolVersion===5){let r=this._parseProperties();Object.getOwnPropertyNames(r).length&&(e.properties=r);}if(e.length<=0)return this._emitError(new Error("Malformed suback, no payload specified"));for(;this._pos2&&r!==128)return this._emitError(new Error("Invalid suback QoS, must be 0, 1, 2 or 128"));this.packet.granted.push(r);}}}_parseUnsubscribe(){D("_parseUnsubscribe");let e=this.packet;if(e.unsubscriptions=[],!!this._parseMessageId()){if(this.settings.protocolVersion===5){let r=this._parseProperties();Object.getOwnPropertyNames(r).length&&(e.properties=r);}if(e.length<=0)return this._emitError(new Error("Malformed unsubscribe, no payload specified"));for(;this._pos2){switch(e.reasonCode=this._parseByte(),this.packet.cmd){case"puback":case"pubrec":if(!V.MQTT5_PUBACK_PUBREC_CODES[e.reasonCode])return this._emitError(new Error("Invalid "+this.packet.cmd+" reason code"));break;case"pubrel":case"pubcomp":if(!V.MQTT5_PUBREL_PUBCOMP_CODES[e.reasonCode])return this._emitError(new Error("Invalid "+this.packet.cmd+" reason code"));break}D("_parseConfirmation: packet.reasonCode `%d`",e.reasonCode);}else e.reasonCode=0;if(e.length>3){let r=this._parseProperties();Object.getOwnPropertyNames(r).length&&(e.properties=r);}}return !0}_parseDisconnect(){let e=this.packet;if(D("_parseDisconnect"),this.settings.protocolVersion===5){this._list.length>0?(e.reasonCode=this._parseByte(),V.MQTT5_DISCONNECT_CODES[e.reasonCode]||this._emitError(new Error("Invalid disconnect reason code"))):e.reasonCode=0;let r=this._parseProperties();Object.getOwnPropertyNames(r).length&&(e.properties=r);}return D("_parseDisconnect result: true"),!0}_parseAuth(){D("_parseAuth");let e=this.packet;if(this.settings.protocolVersion!==5)return this._emitError(new Error("Not supported auth packet for this version MQTT"));if(e.reasonCode=this._parseByte(),!V.MQTT5_AUTH_CODES[e.reasonCode])return this._emitError(new Error("Invalid auth reason code"));let r=this._parseProperties();return Object.getOwnPropertyNames(r).length&&(e.properties=r),D("_parseAuth: result: true"),!0}_parseMessageId(){let e=this.packet;return e.messageId=this._parseNum(),e.messageId===null?(this._emitError(new Error("Cannot parse messageId")),!1):(D("_parseMessageId: packet.messageId %d",e.messageId),!0)}_parseString(e){let r=this._parseNum(),i=r+this._pos;if(r===-1||i>this._list.length||i>this.packet.length)return null;let n=this._list.toString("utf8",this._pos,i);return this._pos+=r,D("_parseString: result: %s",n),n}_parseStringPair(){return D("_parseStringPair"),{name:this._parseString(),value:this._parseString()}}_parseBuffer(){let e=this._parseNum(),r=e+this._pos;if(e===-1||r>this._list.length||r>this.packet.length)return null;let i=this._list.slice(this._pos,r);return this._pos+=e,D("_parseBuffer: result: %o",i),i}_parseNum(){if(this._list.length-this._pos<2)return -1;let e=this._list.readUInt16BE(this._pos);return this._pos+=2,D("_parseNum: result: %s",e),e}_parse4ByteNum(){if(this._list.length-this._pos<4)return -1;let e=this._list.readUInt32BE(this._pos);return this._pos+=4,D("_parse4ByteNum: result: %s",e),e}_parseVarByteNum(e){D("_parseVarByteNum");let r=4,i=0,n=1,o=0,s=!1,a,u=this._pos?this._pos:0;for(;i=i&&this._emitError(new Error("Invalid variable byte integer")),u&&(this._pos+=i),s?e?s={bytes:i,value:o}:s=o:s=!1,D("_parseVarByteNum: result: %o",s),s}_parseByte(){let e;return this._pos{v();m();_();var{Buffer:vi}=(ye(),X(_e)),Om=65536,vd={},km=vi.isBuffer(vi.from([1,2]).subarray(0,1));function Ed(t){let e=vi.allocUnsafe(2);return e.writeUInt8(t>>8,0),e.writeUInt8(t&255,0+1),e}function xm(){for(let t=0;t0&&(r=r|128),n.writeUInt8(r,i++);while(t>0&&i<4);return t>0&&(i=0),km?n.subarray(0,i):n.slice(0,i)}function Lm(t){let e=vi.allocUnsafe(4);return e.writeUInt32BE(t,0),e}Sd.exports={cache:vd,generateCache:xm,generateNumber:Ed,genBufVariableByteInt:Mm,generate4ByteBuffer:Lm};});var Id=M((eO,$o)=>{v();m();_();typeof P>"u"||!P.version||P.version.indexOf("v0.")===0||P.version.indexOf("v1.")===0&&P.version.indexOf("v1.8.")!==0?$o.exports={nextTick:Um}:$o.exports=P;function Um(t,e,r,i){if(typeof t!="function")throw new TypeError('"callback" argument must be a function');var n=arguments.length,o,s;switch(n){case 0:case 1:return P.nextTick(t);case 2:return P.nextTick(function(){t.call(null,e);});case 3:return P.nextTick(function(){t.call(null,e,r);});case 4:return P.nextTick(function(){t.call(null,e,r,i);});default:for(o=new Array(n-1),s=0;s{v();m();_();var j=Fo(),{Buffer:q}=(ye(),X(_e)),Nm=q.allocUnsafe(0),qm=q.from([0]),Ei=Ad(),Dm=Id().nextTick,qe=ot()("mqtt-packet:writeToStream"),Cn=Ei.cache,jm=Ei.generateNumber,Fm=Ei.generateCache,Ho=Ei.genBufVariableByteInt,Wm=Ei.generate4ByteBuffer,Ie=Vo,Bn=!0;function Od(t,e,r){switch(qe("generate called"),e.cork&&(e.cork(),Dm($m,e)),Bn&&(Bn=!1,Fm()),qe("generate: packet.cmd: %s",t.cmd),t.cmd){case"connect":return Hm(t,e);case"connack":return Vm(t,e,r);case"publish":return zm(t,e,r);case"puback":case"pubrec":case"pubrel":case"pubcomp":return Km(t,e,r);case"subscribe":return Gm(t,e,r);case"suback":return Qm(t,e,r);case"unsubscribe":return Ym(t,e,r);case"unsuback":return Jm(t,e,r);case"pingreq":case"pingresp":return Xm(t,e);case"disconnect":return Zm(t,e,r);case"auth":return e1(t,e,r);default:return e.destroy(new Error("Unknown command")),!1}}Object.defineProperty(Od,"cacheNumbers",{get(){return Ie===Vo},set(t){t?((!Cn||Object.keys(Cn).length===0)&&(Bn=!0),Ie=Vo):(Bn=!1,Ie=t1);}});function $m(t){t.uncork();}function Hm(t,e,r){let i=t||{},n=i.protocolId||"MQTT",o=i.protocolVersion||4,s=i.will,a=i.clean,u=i.keepalive||0,c=i.clientId||"",h=i.username,d=i.password,g=i.properties;a===void 0&&(a=!0);let y=0;if(!n||typeof n!="string"&&!q.isBuffer(n))return e.destroy(new Error("Invalid protocolId")),!1;if(y+=n.length+2,o!==3&&o!==4&&o!==5)return e.destroy(new Error("Invalid protocol version")),!1;if(y+=1,(typeof c=="string"||q.isBuffer(c))&&(c||o>=4)&&(c||a))y+=q.byteLength(c)+2;else {if(o<4)return e.destroy(new Error("clientId must be supplied before 3.1.1")),!1;if(a*1===0)return e.destroy(new Error("clientId must be given if cleanSession set to 0")),!1}if(typeof u!="number"||u<0||u>65535||u%1!==0)return e.destroy(new Error("Invalid keepalive")),!1;y+=2,y+=1;let w,E;if(o===5){if(w=Ft(e,g),!w)return !1;y+=w.length;}if(s){if(typeof s!="object")return e.destroy(new Error("Invalid will")),!1;if(!s.topic||typeof s.topic!="string")return e.destroy(new Error("Invalid will topic")),!1;if(y+=q.byteLength(s.topic)+2,y+=2,s.payload)if(s.payload.length>=0)typeof s.payload=="string"?y+=q.byteLength(s.payload):y+=s.payload.length;else return e.destroy(new Error("Invalid will payload")),!1;if(E={},o===5){if(E=Ft(e,s.properties),!E)return !1;y+=E.length;}}let S=!1;if(h!=null)if(Pd(h))S=!0,y+=q.byteLength(h)+2;else return e.destroy(new Error("Invalid username")),!1;if(d!=null){if(!S)return e.destroy(new Error("Username is required to use password")),!1;if(Pd(d))y+=kd(d)+2;else return e.destroy(new Error("Invalid password")),!1}e.write(j.CONNECT_HEADER),De(e,y),Gr(e,n),i.bridgeMode&&(o+=128),e.write(o===131?j.VERSION131:o===132?j.VERSION132:o===4?j.VERSION4:o===5?j.VERSION5:j.VERSION3);let I=0;return I|=h!=null?j.USERNAME_MASK:0,I|=d!=null?j.PASSWORD_MASK:0,I|=s&&s.retain?j.WILL_RETAIN_MASK:0,I|=s&&s.qos?s.qos<0&&Ie(e,c),g?.write(),qe("publish: payload: %o",u),e.write(u)}function Km(t,e,r){let i=r?r.protocolVersion:4,n=t||{},o=n.cmd||"puback",s=n.messageId,a=n.dup&&o==="pubrel"?j.DUP_MASK:0,u=0,c=n.reasonCode,h=n.properties,d=i===5?3:2;if(o==="pubrel"&&(u=1),typeof s!="number")return e.destroy(new Error("Invalid messageId")),!1;let g=null;if(i===5&&typeof h=="object"){if(g=Si(e,h,r,d),!g)return !1;d+=g.length;}return e.write(j.ACKS[o][u][a][0]),d===3&&(d+=c!==0?1:-1),De(e,d),Ie(e,s),i===5&&d!==2&&e.write(q.from([c])),g!==null?g.write():d===4&&e.write(q.from([0])),!0}function Gm(t,e,r){qe("subscribe: packet: ");let i=r?r.protocolVersion:4,n=t||{},o=n.dup?j.DUP_MASK:0,s=n.messageId,a=n.subscriptions,u=n.properties,c=0;if(typeof s!="number")return e.destroy(new Error("Invalid messageId")),!1;c+=2;let h=null;if(i===5){if(h=Ft(e,u),!h)return !1;c+=h.length;}if(typeof a=="object"&&a.length)for(let g=0;g2)return e.destroy(new Error("Invalid subscriptions - invalid Retain Handling")),!1}c+=q.byteLength(y)+2+1;}else return e.destroy(new Error("Invalid subscriptions")),!1;qe("subscribe: writing to stream: %o",j.SUBSCRIBE_HEADER),e.write(j.SUBSCRIBE_HEADER[1][o?1:0][0]),De(e,c),Ie(e,s),h!==null&&h.write();let d=!0;for(let g of a){let y=g.topic,w=g.qos,E=+g.nl,S=+g.rap,I=g.rh,C;yr(e,y),C=j.SUBSCRIBE_OPTIONS_QOS[w],i===5&&(C|=E?j.SUBSCRIBE_OPTIONS_NL:0,C|=S?j.SUBSCRIBE_OPTIONS_RAP:0,C|=I?j.SUBSCRIBE_OPTIONS_RH[I]:0),d=e.write(q.from([C]));}return d}function Qm(t,e,r){let i=r?r.protocolVersion:4,n=t||{},o=n.messageId,s=n.granted,a=n.properties,u=0;if(typeof o!="number")return e.destroy(new Error("Invalid messageId")),!1;if(u+=2,typeof s=="object"&&s.length)for(let h=0;hj.VARBYTEINT_MAX)return t.destroy(new Error(`Invalid variable byte integer: ${e}`)),!1;let r=Td[e];return r||(r=Ho(e),e<16384&&(Td[e]=r)),qe("writeVarByteInt: writing to stream: %o",r),t.write(r)}function yr(t,e){let r=q.byteLength(e);return Ie(t,r),qe("writeString: %s",e),t.write(e,"utf8")}function Rd(t,e,r){yr(t,e),yr(t,r);}function Vo(t,e){return qe("writeNumberCached: number: %d",e),qe("writeNumberCached: %o",Cn[e]),t.write(Cn[e])}function t1(t,e){let r=jm(e);return qe("writeNumberGenerated: %o",r),t.write(r)}function r1(t,e){let r=Wm(e);return qe("write4ByteNumber: %o",r),t.write(r)}function Gr(t,e){typeof e=="string"?yr(t,e):e?(Ie(t,e.length),t.write(e)):Ie(t,0);}function Ft(t,e){if(typeof e!="object"||e.length!=null)return {length:1,write(){Bd(t,{},0);}};let r=0;function i(o,s){let a=j.propertiesTypes[o],u=0;switch(a){case"byte":{if(typeof s!="boolean")return t.destroy(new Error(`Invalid ${o}: ${s}`)),!1;u+=1+1;break}case"int8":{if(typeof s!="number"||s<0||s>255)return t.destroy(new Error(`Invalid ${o}: ${s}`)),!1;u+=1+1;break}case"binary":{if(s&&s===null)return t.destroy(new Error(`Invalid ${o}: ${s}`)),!1;u+=1+q.byteLength(s)+2;break}case"int16":{if(typeof s!="number"||s<0||s>65535)return t.destroy(new Error(`Invalid ${o}: ${s}`)),!1;u+=1+2;break}case"int32":{if(typeof s!="number"||s<0||s>4294967295)return t.destroy(new Error(`Invalid ${o}: ${s}`)),!1;u+=1+4;break}case"var":{if(typeof s!="number"||s<0||s>268435455)return t.destroy(new Error(`Invalid ${o}: ${s}`)),!1;u+=1+q.byteLength(Ho(s));break}case"string":{if(typeof s!="string")return t.destroy(new Error(`Invalid ${o}: ${s}`)),!1;u+=1+2+q.byteLength(s.toString());break}case"pair":{if(typeof s!="object")return t.destroy(new Error(`Invalid ${o}: ${s}`)),!1;u+=Object.getOwnPropertyNames(s).reduce((c,h)=>{let d=s[h];return Array.isArray(d)?c+=d.reduce((g,y)=>(g+=1+2+q.byteLength(h.toString())+2+q.byteLength(y.toString()),g),0):c+=1+2+q.byteLength(h.toString())+2+q.byteLength(s[h].toString()),c},0);break}default:return t.destroy(new Error(`Invalid property ${o}: ${s}`)),!1}return u}if(e)for(let o in e){let s=0,a=0,u=e[o];if(Array.isArray(u))for(let c=0;co;){let a=n.shift();if(a&&e[a])delete e[a],s=Ft(t,e);else return !1}return s}function Cd(t,e,r){switch(j.propertiesTypes[e]){case"byte":{t.write(q.from([j.properties[e]])),t.write(q.from([+r]));break}case"int8":{t.write(q.from([j.properties[e]])),t.write(q.from([r]));break}case"binary":{t.write(q.from([j.properties[e]])),Gr(t,r);break}case"int16":{t.write(q.from([j.properties[e]])),Ie(t,r);break}case"int32":{t.write(q.from([j.properties[e]])),r1(t,r);break}case"var":{t.write(q.from([j.properties[e]])),De(t,r);break}case"string":{t.write(q.from([j.properties[e]])),yr(t,r);break}case"pair":{Object.getOwnPropertyNames(r).forEach(n=>{let o=r[n];Array.isArray(o)?o.forEach(s=>{t.write(q.from([j.properties[e]])),Rd(t,n.toString(),s.toString());}):(t.write(q.from([j.properties[e]])),Rd(t,n.toString(),o.toString()));});break}default:return t.destroy(new Error(`Invalid property ${e} value: ${r}`)),!1}}function Bd(t,e,r){De(t,r);for(let i in e)if(Object.prototype.hasOwnProperty.call(e,i)&&e[i]!==null){let n=e[i];if(Array.isArray(n))for(let o=0;o{v();m();_();var i1=zo(),{EventEmitter:n1}=(ir(),X(rr)),{Buffer:Md}=(ye(),X(_e));function s1(t,e){let r=new Ko;return i1(t,r,e),r.concat()}var Ko=class extends n1{constructor(){super(),this._array=new Array(20),this._i=0;}write(e){return this._array[this._i++]=e,!0}concat(){let e=0,r=new Array(this._array.length),i=this._array,n=0,o;for(o=0;o{v();m();_();Pn.parser=md().parser;Pn.generate=Ud();Pn.writeToStream=zo();});var Yo=M(Qo=>{v();m();_();Object.defineProperty(Qo,"__esModule",{value:!0});var Go=class{constructor(){this.nextId=Math.max(1,Math.floor(Math.random()*65535));}allocate(){let e=this.nextId++;return this.nextId===65536&&(this.nextId=1),e}getLastAllocated(){return this.nextId===1?65535:this.nextId-1}register(e){return !0}deallocate(e){}clear(){}};Qo.default=Go;});var Dd=M((YO,qd)=>{v();m();_();qd.exports=o1;function Qr(t){return t instanceof x?x.from(t):new t.constructor(t.buffer.slice(),t.byteOffset,t.length)}function o1(t){if(t=t||{},t.circles)return a1(t);return t.proto?i:r;function e(n,o){for(var s=Object.keys(n),a=new Array(s.length),u=0;u{v();m();_();jd.exports=Dd()();});var $d=M(Yr=>{v();m();_();Object.defineProperty(Yr,"__esModule",{value:!0});Yr.validateTopics=Yr.validateTopic=void 0;function Wd(t){let e=t.split("/");for(let r=0;r{v();m();_();Object.defineProperty(Xo,"__esModule",{value:!0});var u1=Dt(),f1={objectMode:!0},c1={clean:!0},Jo=class{constructor(e){this.options=e||{},this.options=Object.assign(Object.assign({},c1),e),this._inflights=new Map;}put(e,r){return this._inflights.set(e.messageId,e),r&&r(),this}createStream(){let e=new u1.Readable(f1),r=[],i=!1,n=0;return this._inflights.forEach((o,s)=>{r.push(o);}),e._read=()=>{!i&&n{if(!i)return i=!0,setTimeout(()=>{e.emit("close");},0),e},e}del(e,r){let i=this._inflights.get(e.messageId);return i?(this._inflights.delete(e.messageId),r(null,i)):r&&r(new Error("missing packet")),this}get(e,r){let i=this._inflights.get(e.messageId);return i?r(null,i):r&&r(new Error("missing packet")),this}close(e){this.options.clean&&(this._inflights=null),e&&e();}};Xo.default=Jo;});var Vd=M(ea=>{v();m();_();Object.defineProperty(ea,"__esModule",{value:!0});var Hd=[0,16,128,131,135,144,145,151,153],h1=(t,e,r)=>{t.log("handlePublish: packet %o",e),r=typeof r<"u"?r:t.noop;let i=e.topic.toString(),n=e.payload,{qos:o}=e,{messageId:s}=e,{options:a}=t;if(t.options.protocolVersion===5){let u;if(e.properties&&(u=e.properties.topicAlias),typeof u<"u")if(i.length===0)if(u>0&&u<=65535){let c=t.topicAliasRecv.getTopicByAlias(u);if(c)i=c,t.log("handlePublish :: topic complemented by alias. topic: %s - alias: %d",i,u);else {t.log("handlePublish :: unregistered topic alias. alias: %d",u),t.emit("error",new Error("Received unregistered Topic Alias"));return}}else {t.log("handlePublish :: topic alias out of range. alias: %d",u),t.emit("error",new Error("Received Topic Alias is out of range"));return}else if(t.topicAliasRecv.put(i,u))t.log("handlePublish :: registered topic: %s - alias: %d",i,u);else {t.log("handlePublish :: topic alias out of range. alias: %d",u),t.emit("error",new Error("Received Topic Alias is out of range"));return}}switch(t.log("handlePublish: qos %d",o),o){case 2:{a.customHandleAcks(i,n,e,(u,c)=>{if(typeof u=="number"&&(c=u,u=null),u)return t.emit("error",u);if(Hd.indexOf(c)===-1)return t.emit("error",new Error("Wrong reason code for pubrec"));c?t._sendPacket({cmd:"pubrec",messageId:s,reasonCode:c},r):t.incomingStore.put(e,()=>{t._sendPacket({cmd:"pubrec",messageId:s},r);});});break}case 1:{a.customHandleAcks(i,n,e,(u,c)=>{if(typeof u=="number"&&(c=u,u=null),u)return t.emit("error",u);if(Hd.indexOf(c)===-1)return t.emit("error",new Error("Wrong reason code for puback"));c||t.emit("message",i,n,e),t.handleMessage(e,h=>{if(h)return r&&r(h);t._sendPacket({cmd:"puback",messageId:s,reasonCode:c},r);});});break}case 0:t.emit("message",i,n,e),t.handleMessage(e,r);break;default:t.log("handlePublish: unknown QoS. Doing nothing.");break}};ea.default=h1;});var Jr=M(Wt=>{v();m();_();Object.defineProperty(Wt,"__esModule",{value:!0});Wt.nextTick=Wt.applyMixin=Wt.ErrorWithReasonCode=void 0;var ta=class t extends Error{constructor(e,r){super(e),this.code=r,Object.setPrototypeOf(this,t.prototype),Object.getPrototypeOf(this).name="ErrorWithReasonCode";}};Wt.ErrorWithReasonCode=ta;function d1(t,e,r=!1){var i;let n=[e];for(;;){let o=n[0],s=Object.getPrototypeOf(o);if(s?.prototype)n.unshift(s);else break}for(let o of n)for(let s of Object.getOwnPropertyNames(o.prototype))(r||s!=="constructor")&&Object.defineProperty(t.prototype,s,(i=Object.getOwnPropertyDescriptor(o.prototype,s))!==null&&i!==void 0?i:Object.create(null));}Wt.applyMixin=d1;Wt.nextTick=typeof(P===null||P===void 0?void 0:P.nextTick)=="function"?P.nextTick:t=>{setTimeout(t,0);};});var Ai=M(br=>{v();m();_();Object.defineProperty(br,"__esModule",{value:!0});br.ReasonCodes=void 0;br.ReasonCodes={0:"",1:"Unacceptable protocol version",2:"Identifier rejected",3:"Server unavailable",4:"Bad username or password",5:"Not authorized",16:"No matching subscribers",17:"No subscription existed",128:"Unspecified error",129:"Malformed Packet",130:"Protocol Error",131:"Implementation specific error",132:"Unsupported Protocol Version",133:"Client Identifier not valid",134:"Bad User Name or Password",135:"Not authorized",136:"Server unavailable",137:"Server busy",138:"Banned",139:"Server shutting down",140:"Bad authentication method",141:"Keep Alive timeout",142:"Session taken over",143:"Topic Filter invalid",144:"Topic Name invalid",145:"Packet identifier in use",146:"Packet Identifier not found",147:"Receive Maximum exceeded",148:"Topic Alias invalid",149:"Packet too large",150:"Message rate too high",151:"Quota exceeded",152:"Administrative action",153:"Payload format invalid",154:"Retain not supported",155:"QoS not supported",156:"Use another server",157:"Server moved",158:"Shared Subscriptions not supported",159:"Connection rate exceeded",160:"Maximum connect time",161:"Subscription Identifiers not supported",162:"Wildcard Subscriptions not supported"};var p1=(t,e)=>{let{messageId:r}=e,i=e.cmd,n=null,o=t.outgoing[r]?t.outgoing[r].cb:null,s;if(!o){t.log("_handleAck :: Server sent an ack in error. Ignoring.");return}switch(t.log("_handleAck :: packet type",i),i){case"pubcomp":case"puback":{let a=e.reasonCode;a&&a>0&&a!==16?(s=new Error(`Publish error: ${br.ReasonCodes[a]}`),s.code=a,t._removeOutgoingAndStoreMessage(r,()=>{o(s,e);})):t._removeOutgoingAndStoreMessage(r,o);break}case"pubrec":{n={cmd:"pubrel",qos:2,messageId:r};let a=e.reasonCode;a&&a>0&&a!==16?(s=new Error(`Publish error: ${br.ReasonCodes[a]}`),s.code=a,t._removeOutgoingAndStoreMessage(r,()=>{o(s,e);})):t._sendPacket(n);break}case"suback":{delete t.outgoing[r],t.messageIdProvider.deallocate(r);let a=e.granted;for(let u=0;u{delete t._resubscribeTopics[h];});}delete t.messageIdToTopic[r],t._invokeStoreProcessingQueue(),o(null,e);break}case"unsuback":{delete t.outgoing[r],t.messageIdProvider.deallocate(r),t._invokeStoreProcessingQueue(),o(null);break}default:t.emit("error",new Error("unrecognized packet type"));}t.disconnecting&&Object.keys(t.outgoing).length===0&&t.emit("outgoingEmpty");};br.default=p1;});var Kd=M(ra=>{v();m();_();Object.defineProperty(ra,"__esModule",{value:!0});var zd=Jr(),g1=Ai(),y1=(t,e)=>{let{options:r}=t,i=r.protocolVersion,n=i===5?e.reasonCode:e.returnCode;if(i!==5){let o=new zd.ErrorWithReasonCode(`Protocol error: Auth packets are only supported in MQTT 5. Your version:${i}`,n);t.emit("error",o);return}t.handleAuth(e,(o,s)=>{if(o){t.emit("error",o);return}if(n===24)t.reconnecting=!1,t._sendPacket(s);else {let a=new zd.ErrorWithReasonCode(`Connection refused: ${g1.ReasonCodes[n]}`,n);t.emit("error",a);}});};ra.default=y1;});var Xd=M(kn=>{v();m();_();Object.defineProperty(kn,"__esModule",{value:!0});kn.LRUCache=void 0;var Ii=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date,Qd=new Set,ia=typeof P=="object"&&P?P:{},Yd=(t,e,r,i)=>{typeof ia.emitWarning=="function"?ia.emitWarning(t,e,r,i):console.error(`[${r}] ${e}: ${t}`);},On=globalThis.AbortController,Gd=globalThis.AbortSignal;if(typeof On>"u"){Gd=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(i,n){this._onabort.push(n);}},On=class{constructor(){e();}signal=new Gd;abort(i){if(!this.signal.aborted){this.signal.reason=i,this.signal.aborted=!0;for(let n of this.signal._onabort)n(i);this.signal.onabort?.(i);}}};let t=ia.env?.LRU_CACHE_IGNORE_AC_WARNING!=="1",e=()=>{t&&(t=!1,Yd("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",e));};}var b1=t=>!Qd.has(t),$t=t=>t&&t===Math.floor(t)&&t>0&&isFinite(t),Jd=t=>$t(t)?t<=Math.pow(2,8)?Uint8Array:t<=Math.pow(2,16)?Uint16Array:t<=Math.pow(2,32)?Uint32Array:t<=Number.MAX_SAFE_INTEGER?Xr:null:null,Xr=class extends Array{constructor(e){super(e),this.fill(0);}},na=class t{heap;length;static#l=!1;static create(e){let r=Jd(e);if(!r)return [];t.#l=!0;let i=new t(e,r);return t.#l=!1,i}constructor(e,r){if(!t.#l)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new r(e),this.length=0;}push(e){this.heap[this.length++]=e;}pop(){return this.heap[--this.length]}},sa=class t{#l;#c;#p;#g;#B;ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#i;#y;#n;#r;#e;#u;#h;#a;#s;#b;#o;#E;#S;#w;#_;#I;#f;static unsafeExposeInternals(e){return {starts:e.#S,ttls:e.#w,sizes:e.#E,keyMap:e.#n,keyList:e.#r,valList:e.#e,next:e.#u,prev:e.#h,get head(){return e.#a},get tail(){return e.#s},free:e.#b,isBackgroundFetch:r=>e.#t(r),backgroundFetch:(r,i,n,o)=>e.#k(r,i,n,o),moveToTail:r=>e.#C(r),indexes:r=>e.#m(r),rindexes:r=>e.#v(r),isStale:r=>e.#d(r)}}get max(){return this.#l}get maxSize(){return this.#c}get calculatedSize(){return this.#y}get size(){return this.#i}get fetchMethod(){return this.#B}get dispose(){return this.#p}get disposeAfter(){return this.#g}constructor(e){let{max:r=0,ttl:i,ttlResolution:n=1,ttlAutopurge:o,updateAgeOnGet:s,updateAgeOnHas:a,allowStale:u,dispose:c,disposeAfter:h,noDisposeOnSet:d,noUpdateTTL:g,maxSize:y=0,maxEntrySize:w=0,sizeCalculation:E,fetchMethod:S,noDeleteOnFetchRejection:I,noDeleteOnStaleGet:C,allowStaleOnFetchRejection:R,allowStaleOnFetchAbort:U,ignoreFetchAbort:N}=e;if(r!==0&&!$t(r))throw new TypeError("max option must be a nonnegative integer");let W=r?Jd(r):Array;if(!W)throw new Error("invalid max value: "+r);if(this.#l=r,this.#c=y,this.maxEntrySize=w||this.#c,this.sizeCalculation=E,this.sizeCalculation){if(!this.#c&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(S!==void 0&&typeof S!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#B=S,this.#I=!!S,this.#n=new Map,this.#r=new Array(r).fill(void 0),this.#e=new Array(r).fill(void 0),this.#u=new W(r),this.#h=new W(r),this.#a=0,this.#s=0,this.#b=na.create(r),this.#i=0,this.#y=0,typeof c=="function"&&(this.#p=c),typeof h=="function"?(this.#g=h,this.#o=[]):(this.#g=void 0,this.#o=void 0),this.#_=!!this.#p,this.#f=!!this.#g,this.noDisposeOnSet=!!d,this.noUpdateTTL=!!g,this.noDeleteOnFetchRejection=!!I,this.allowStaleOnFetchRejection=!!R,this.allowStaleOnFetchAbort=!!U,this.ignoreFetchAbort=!!N,this.maxEntrySize!==0){if(this.#c!==0&&!$t(this.#c))throw new TypeError("maxSize must be a positive integer if specified");if(!$t(this.maxEntrySize))throw new TypeError("maxEntrySize must be a positive integer if specified");this.#q();}if(this.allowStale=!!u,this.noDeleteOnStaleGet=!!C,this.updateAgeOnGet=!!s,this.updateAgeOnHas=!!a,this.ttlResolution=$t(n)||n===0?n:1,this.ttlAutopurge=!!o,this.ttl=i||0,this.ttl){if(!$t(this.ttl))throw new TypeError("ttl must be a positive integer if specified");this.#x();}if(this.#l===0&&this.ttl===0&&this.#c===0)throw new TypeError("At least one of max, maxSize, or ttl is required");if(!this.ttlAutopurge&&!this.#l&&!this.#c){let K="LRU_CACHE_UNBOUNDED";b1(K)&&(Qd.add(K),Yd("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.","UnboundedCacheWarning",K,t));}}getRemainingTTL(e){return this.#n.has(e)?1/0:0}#x(){let e=new Xr(this.#l),r=new Xr(this.#l);this.#w=e,this.#S=r,this.#M=(o,s,a=Ii.now())=>{if(r[o]=s!==0?a:0,e[o]=s,s!==0&&this.ttlAutopurge){let u=setTimeout(()=>{this.#d(o)&&this.delete(this.#r[o]);},s+1);u.unref&&u.unref();}},this.#T=o=>{r[o]=e[o]!==0?Ii.now():0;},this.#A=(o,s)=>{if(e[s]){let a=e[s],u=r[s];o.ttl=a,o.start=u,o.now=i||n();let c=o.now-u;o.remainingTTL=a-c;}};let i=0,n=()=>{let o=Ii.now();if(this.ttlResolution>0){i=o;let s=setTimeout(()=>i=0,this.ttlResolution);s.unref&&s.unref();}return o};this.getRemainingTTL=o=>{let s=this.#n.get(o);if(s===void 0)return 0;let a=e[s],u=r[s];if(a===0||u===0)return 1/0;let c=(i||n())-u;return a-c},this.#d=o=>e[o]!==0&&r[o]!==0&&(i||n())-r[o]>e[o];}#T=()=>{};#A=()=>{};#M=()=>{};#d=()=>!1;#q(){let e=new Xr(this.#l);this.#y=0,this.#E=e,this.#R=r=>{this.#y-=e[r],e[r]=0;},this.#L=(r,i,n,o)=>{if(this.#t(i))return 0;if(!$t(n))if(o){if(typeof o!="function")throw new TypeError("sizeCalculation must be a function");if(n=o(i,r),!$t(n))throw new TypeError("sizeCalculation return invalid (expect positive integer)")}else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");return n},this.#P=(r,i,n)=>{if(e[r]=i,this.#c){let o=this.#c-e[r];for(;this.#y>o;)this.#O(!0);}this.#y+=e[r],n&&(n.entrySize=i,n.totalCalculatedSize=this.#y);};}#R=e=>{};#P=(e,r,i)=>{};#L=(e,r,i,n)=>{if(i||n)throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");return 0};*#m({allowStale:e=this.allowStale}={}){if(this.#i)for(let r=this.#s;!(!this.#U(r)||((e||!this.#d(r))&&(yield r),r===this.#a));)r=this.#h[r];}*#v({allowStale:e=this.allowStale}={}){if(this.#i)for(let r=this.#a;!(!this.#U(r)||((e||!this.#d(r))&&(yield r),r===this.#s));)r=this.#u[r];}#U(e){return e!==void 0&&this.#n.get(this.#r[e])===e}*entries(){for(let e of this.#m())this.#e[e]!==void 0&&this.#r[e]!==void 0&&!this.#t(this.#e[e])&&(yield [this.#r[e],this.#e[e]]);}*rentries(){for(let e of this.#v())this.#e[e]!==void 0&&this.#r[e]!==void 0&&!this.#t(this.#e[e])&&(yield [this.#r[e],this.#e[e]]);}*keys(){for(let e of this.#m()){let r=this.#r[e];r!==void 0&&!this.#t(this.#e[e])&&(yield r);}}*rkeys(){for(let e of this.#v()){let r=this.#r[e];r!==void 0&&!this.#t(this.#e[e])&&(yield r);}}*values(){for(let e of this.#m())this.#e[e]!==void 0&&!this.#t(this.#e[e])&&(yield this.#e[e]);}*rvalues(){for(let e of this.#v())this.#e[e]!==void 0&&!this.#t(this.#e[e])&&(yield this.#e[e]);}[Symbol.iterator](){return this.entries()}find(e,r={}){for(let i of this.#m()){let n=this.#e[i],o=this.#t(n)?n.__staleWhileFetching:n;if(o!==void 0&&e(o,this.#r[i],this))return this.get(this.#r[i],r)}}forEach(e,r=this){for(let i of this.#m()){let n=this.#e[i],o=this.#t(n)?n.__staleWhileFetching:n;o!==void 0&&e.call(r,o,this.#r[i],this);}}rforEach(e,r=this){for(let i of this.#v()){let n=this.#e[i],o=this.#t(n)?n.__staleWhileFetching:n;o!==void 0&&e.call(r,o,this.#r[i],this);}}purgeStale(){let e=!1;for(let r of this.#v({allowStale:!0}))this.#d(r)&&(this.delete(this.#r[r]),e=!0);return e}dump(){let e=[];for(let r of this.#m({allowStale:!0})){let i=this.#r[r],n=this.#e[r],o=this.#t(n)?n.__staleWhileFetching:n;if(o===void 0||i===void 0)continue;let s={value:o};if(this.#w&&this.#S){s.ttl=this.#w[r];let a=Ii.now()-this.#S[r];s.start=Math.floor(Date.now()-a);}this.#E&&(s.size=this.#E[r]),e.unshift([i,s]);}return e}load(e){this.clear();for(let[r,i]of e){if(i.start){let n=Date.now()-i.start;i.start=Ii.now()-n;}this.set(r,i.value,i);}}set(e,r,i={}){if(r===void 0)return this.delete(e),this;let{ttl:n=this.ttl,start:o,noDisposeOnSet:s=this.noDisposeOnSet,sizeCalculation:a=this.sizeCalculation,status:u}=i,{noUpdateTTL:c=this.noUpdateTTL}=i,h=this.#L(e,r,i.size||0,a);if(this.maxEntrySize&&h>this.maxEntrySize)return u&&(u.set="miss",u.maxEntrySizeExceeded=!0),this.delete(e),this;let d=this.#i===0?void 0:this.#n.get(e);if(d===void 0)d=this.#i===0?this.#s:this.#b.length!==0?this.#b.pop():this.#i===this.#l?this.#O(!1):this.#i,this.#r[d]=e,this.#e[d]=r,this.#n.set(e,d),this.#u[this.#s]=d,this.#h[d]=this.#s,this.#s=d,this.#i++,this.#P(d,h,u),u&&(u.set="add"),c=!1;else {this.#C(d);let g=this.#e[d];if(r!==g){if(this.#I&&this.#t(g)){g.__abortController.abort(new Error("replaced"));let{__staleWhileFetching:y}=g;y!==void 0&&!s&&(this.#_&&this.#p?.(y,e,"set"),this.#f&&this.#o?.push([y,e,"set"]));}else s||(this.#_&&this.#p?.(g,e,"set"),this.#f&&this.#o?.push([g,e,"set"]));if(this.#R(d),this.#P(d,h,u),this.#e[d]=r,u){u.set="replace";let y=g&&this.#t(g)?g.__staleWhileFetching:g;y!==void 0&&(u.oldValue=y);}}else u&&(u.set="update");}if(n!==0&&!this.#w&&this.#x(),this.#w&&(c||this.#M(d,n,o),u&&this.#A(u,d)),!s&&this.#f&&this.#o){let g=this.#o,y;for(;y=g?.shift();)this.#g?.(...y);}return this}pop(){try{for(;this.#i;){let e=this.#e[this.#a];if(this.#O(!0),this.#t(e)){if(e.__staleWhileFetching)return e.__staleWhileFetching}else if(e!==void 0)return e}}finally{if(this.#f&&this.#o){let e=this.#o,r;for(;r=e?.shift();)this.#g?.(...r);}}}#O(e){let r=this.#a,i=this.#r[r],n=this.#e[r];return this.#I&&this.#t(n)?n.__abortController.abort(new Error("evicted")):(this.#_||this.#f)&&(this.#_&&this.#p?.(n,i,"evict"),this.#f&&this.#o?.push([n,i,"evict"])),this.#R(r),e&&(this.#r[r]=void 0,this.#e[r]=void 0,this.#b.push(r)),this.#i===1?(this.#a=this.#s=0,this.#b.length=0):this.#a=this.#u[r],this.#n.delete(i),this.#i--,r}has(e,r={}){let{updateAgeOnHas:i=this.updateAgeOnHas,status:n}=r,o=this.#n.get(e);if(o!==void 0){let s=this.#e[o];if(this.#t(s)&&s.__staleWhileFetching===void 0)return !1;if(this.#d(o))n&&(n.has="stale",this.#A(n,o));else return i&&this.#T(o),n&&(n.has="hit",this.#A(n,o)),!0}else n&&(n.has="miss");return !1}peek(e,r={}){let{allowStale:i=this.allowStale}=r,n=this.#n.get(e);if(n!==void 0&&(i||!this.#d(n))){let o=this.#e[n];return this.#t(o)?o.__staleWhileFetching:o}}#k(e,r,i,n){let o=r===void 0?void 0:this.#e[r];if(this.#t(o))return o;let s=new On,{signal:a}=i;a?.addEventListener("abort",()=>s.abort(a.reason),{signal:s.signal});let u={signal:s.signal,options:i,context:n},c=(E,S=!1)=>{let{aborted:I}=s.signal,C=i.ignoreFetchAbort&&E!==void 0;if(i.status&&(I&&!S?(i.status.fetchAborted=!0,i.status.fetchError=s.signal.reason,C&&(i.status.fetchAbortIgnored=!0)):i.status.fetchResolved=!0),I&&!C&&!S)return d(s.signal.reason);let R=y;return this.#e[r]===y&&(E===void 0?R.__staleWhileFetching?this.#e[r]=R.__staleWhileFetching:this.delete(e):(i.status&&(i.status.fetchUpdated=!0),this.set(e,E,u.options))),E},h=E=>(i.status&&(i.status.fetchRejected=!0,i.status.fetchError=E),d(E)),d=E=>{let{aborted:S}=s.signal,I=S&&i.allowStaleOnFetchAbort,C=I||i.allowStaleOnFetchRejection,R=C||i.noDeleteOnFetchRejection,U=y;if(this.#e[r]===y&&(!R||U.__staleWhileFetching===void 0?this.delete(e):I||(this.#e[r]=U.__staleWhileFetching)),C)return i.status&&U.__staleWhileFetching!==void 0&&(i.status.returnedStale=!0),U.__staleWhileFetching;if(U.__returned===U)throw E},g=(E,S)=>{let I=this.#B?.(e,o,u);I&&I instanceof Promise&&I.then(C=>E(C===void 0?void 0:C),S),s.signal.addEventListener("abort",()=>{(!i.ignoreFetchAbort||i.allowStaleOnFetchAbort)&&(E(void 0),i.allowStaleOnFetchAbort&&(E=C=>c(C,!0)));});};i.status&&(i.status.fetchDispatched=!0);let y=new Promise(g).then(c,h),w=Object.assign(y,{__abortController:s,__staleWhileFetching:o,__returned:void 0});return r===void 0?(this.set(e,w,{...u.options,status:void 0}),r=this.#n.get(e)):this.#e[r]=w,w}#t(e){if(!this.#I)return !1;let r=e;return !!r&&r instanceof Promise&&r.hasOwnProperty("__staleWhileFetching")&&r.__abortController instanceof On}async fetch(e,r={}){let{allowStale:i=this.allowStale,updateAgeOnGet:n=this.updateAgeOnGet,noDeleteOnStaleGet:o=this.noDeleteOnStaleGet,ttl:s=this.ttl,noDisposeOnSet:a=this.noDisposeOnSet,size:u=0,sizeCalculation:c=this.sizeCalculation,noUpdateTTL:h=this.noUpdateTTL,noDeleteOnFetchRejection:d=this.noDeleteOnFetchRejection,allowStaleOnFetchRejection:g=this.allowStaleOnFetchRejection,ignoreFetchAbort:y=this.ignoreFetchAbort,allowStaleOnFetchAbort:w=this.allowStaleOnFetchAbort,context:E,forceRefresh:S=!1,status:I,signal:C}=r;if(!this.#I)return I&&(I.fetch="get"),this.get(e,{allowStale:i,updateAgeOnGet:n,noDeleteOnStaleGet:o,status:I});let R={allowStale:i,updateAgeOnGet:n,noDeleteOnStaleGet:o,ttl:s,noDisposeOnSet:a,size:u,sizeCalculation:c,noUpdateTTL:h,noDeleteOnFetchRejection:d,allowStaleOnFetchRejection:g,allowStaleOnFetchAbort:w,ignoreFetchAbort:y,status:I,signal:C},U=this.#n.get(e);if(U===void 0){I&&(I.fetch="miss");let N=this.#k(e,U,R,E);return N.__returned=N}else {let N=this.#e[U];if(this.#t(N)){let de=i&&N.__staleWhileFetching!==void 0;return I&&(I.fetch="inflight",de&&(I.returnedStale=!0)),de?N.__staleWhileFetching:N.__returned=N}let W=this.#d(U);if(!S&&!W)return I&&(I.fetch="hit"),this.#C(U),n&&this.#T(U),I&&this.#A(I,U),N;let K=this.#k(e,U,R,E),Q=K.__staleWhileFetching!==void 0&&i;return I&&(I.fetch=W?"stale":"refresh",Q&&W&&(I.returnedStale=!0)),Q?K.__staleWhileFetching:K.__returned=K}}get(e,r={}){let{allowStale:i=this.allowStale,updateAgeOnGet:n=this.updateAgeOnGet,noDeleteOnStaleGet:o=this.noDeleteOnStaleGet,status:s}=r,a=this.#n.get(e);if(a!==void 0){let u=this.#e[a],c=this.#t(u);return s&&this.#A(s,a),this.#d(a)?(s&&(s.get="stale"),c?(s&&i&&u.__staleWhileFetching!==void 0&&(s.returnedStale=!0),i?u.__staleWhileFetching:void 0):(o||this.delete(e),s&&i&&(s.returnedStale=!0),i?u:void 0)):(s&&(s.get="hit"),c?u.__staleWhileFetching:(this.#C(a),n&&this.#T(a),u))}else s&&(s.get="miss");}#N(e,r){this.#h[r]=e,this.#u[e]=r;}#C(e){e!==this.#s&&(e===this.#a?this.#a=this.#u[e]:this.#N(this.#h[e],this.#u[e]),this.#N(this.#s,e),this.#s=e);}delete(e){let r=!1;if(this.#i!==0){let i=this.#n.get(e);if(i!==void 0)if(r=!0,this.#i===1)this.clear();else {this.#R(i);let n=this.#e[i];this.#t(n)?n.__abortController.abort(new Error("deleted")):(this.#_||this.#f)&&(this.#_&&this.#p?.(n,e,"delete"),this.#f&&this.#o?.push([n,e,"delete"])),this.#n.delete(e),this.#r[i]=void 0,this.#e[i]=void 0,i===this.#s?this.#s=this.#h[i]:i===this.#a?this.#a=this.#u[i]:(this.#u[this.#h[i]]=this.#u[i],this.#h[this.#u[i]]=this.#h[i]),this.#i--,this.#b.push(i);}}if(this.#f&&this.#o?.length){let i=this.#o,n;for(;n=i?.shift();)this.#g?.(...n);}return r}clear(){for(let e of this.#v({allowStale:!0})){let r=this.#e[e];if(this.#t(r))r.__abortController.abort(new Error("deleted"));else {let i=this.#r[e];this.#_&&this.#p?.(r,i,"delete"),this.#f&&this.#o?.push([r,i,"delete"]);}}if(this.#n.clear(),this.#e.fill(void 0),this.#r.fill(void 0),this.#w&&this.#S&&(this.#w.fill(0),this.#S.fill(0)),this.#E&&this.#E.fill(0),this.#a=0,this.#s=0,this.#b.length=0,this.#y=0,this.#i=0,this.#f&&this.#o){let e=this.#o,r;for(;r=e?.shift();)this.#g?.(...r);}}};kn.LRUCache=sa;});var at=M(Ht=>{v();m();_();Object.defineProperty(Ht,"t",{value:!0});Ht.ContainerIterator=Ht.Container=Ht.Base=void 0;var oa=class{constructor(e=0){this.iteratorType=e;}equals(e){return this.o===e.o}};Ht.ContainerIterator=oa;var xn=class{constructor(){this.i=0;}get length(){return this.i}size(){return this.i}empty(){return this.i===0}};Ht.Base=xn;var aa=class extends xn{};Ht.Container=aa;});var Zd=M(Mn=>{v();m();_();Object.defineProperty(Mn,"t",{value:!0});Mn.default=void 0;var w1=at(),la=class extends w1.Base{constructor(e=[]){super(),this.S=[];let r=this;e.forEach(function(i){r.push(i);});}clear(){this.i=0,this.S=[];}push(e){return this.S.push(e),this.i+=1,this.i}pop(){if(this.i!==0)return this.i-=1,this.S.pop()}top(){return this.S[this.i-1]}},_1=la;Mn.default=_1;});var ep=M(Ln=>{v();m();_();Object.defineProperty(Ln,"t",{value:!0});Ln.default=void 0;var m1=at(),ua=class extends m1.Base{constructor(e=[]){super(),this.j=0,this.q=[];let r=this;e.forEach(function(i){r.push(i);});}clear(){this.q=[],this.i=this.j=0;}push(e){let r=this.q.length;if(this.j/r>.5&&this.j+this.i>=r&&r>4096){let i=this.i;for(let n=0;n{v();m();_();Object.defineProperty(Un,"t",{value:!0});Un.default=void 0;var E1=at(),fa=class extends E1.Base{constructor(e=[],r=function(n,o){return n>o?-1:n>1;for(let o=this.i-1>>1;o>=0;--o)this.k(o,n);}m(e){let r=this.C[e];for(;e>0;){let i=e-1>>1,n=this.C[i];if(this.v(n,r)<=0)break;this.C[e]=n,e=i;}this.C[e]=r;}k(e,r){let i=this.C[e];for(;e0&&(n=o,s=this.C[o]),this.v(s,i)>=0)break;this.C[e]=s,e=n;}this.C[e]=i;}clear(){this.i=0,this.C.length=0;}push(e){this.C.push(e),this.m(this.i),this.i+=1;}pop(){if(this.i===0)return;let e=this.C[0],r=this.C.pop();return this.i-=1,this.i&&(this.C[0]=r,this.k(0,this.i>>1)),e}top(){return this.C[0]}find(e){return this.C.indexOf(e)>=0}remove(e){let r=this.C.indexOf(e);return r<0?!1:(r===0?this.pop():r===this.i-1?(this.C.pop(),this.i-=1):(this.C.splice(r,1,this.C.pop()),this.i-=1,this.m(r),this.k(r,this.i>>1)),!0)}updateItem(e){let r=this.C.indexOf(e);return r<0?!1:(this.m(r),this.k(r,this.i>>1),!0)}toArray(){return [...this.C]}},S1=fa;Un.default=S1;});var qn=M(Nn=>{v();m();_();Object.defineProperty(Nn,"t",{value:!0});Nn.default=void 0;var A1=at(),ca=class extends A1.Container{},I1=ca;Nn.default=I1;});var lt=M(ha=>{v();m();_();Object.defineProperty(ha,"t",{value:!0});ha.throwIteratorAccessError=T1;function T1(){throw new RangeError("Iterator access denied!")}});var pa=M(jn=>{v();m();_();Object.defineProperty(jn,"t",{value:!0});jn.RandomIterator=void 0;var R1=at(),Dn=lt(),da=class extends R1.ContainerIterator{constructor(e,r){super(r),this.o=e,this.iteratorType===0?(this.pre=function(){return this.o===0&&(0, Dn.throwIteratorAccessError)(),this.o-=1,this},this.next=function(){return this.o===this.container.size()&&(0, Dn.throwIteratorAccessError)(),this.o+=1,this}):(this.pre=function(){return this.o===this.container.size()-1&&(0, Dn.throwIteratorAccessError)(),this.o+=1,this},this.next=function(){return this.o===-1&&(0, Dn.throwIteratorAccessError)(),this.o-=1,this});}get pointer(){return this.container.getElementByPos(this.o)}set pointer(e){this.container.setElementByPos(this.o,e);}};jn.RandomIterator=da;});var rp=M(Fn=>{v();m();_();Object.defineProperty(Fn,"t",{value:!0});Fn.default=void 0;var C1=P1(qn()),B1=pa();function P1(t){return t&&t.t?t:{default:t}}var wr=class t extends B1.RandomIterator{constructor(e,r,i){super(e,i),this.container=r;}copy(){return new t(this.o,this.container,this.iteratorType)}},ga=class extends C1.default{constructor(e=[],r=!0){if(super(),Array.isArray(e))this.J=r?[...e]:e,this.i=e.length;else {this.J=[];let i=this;e.forEach(function(n){i.pushBack(n);});}}clear(){this.i=0,this.J.length=0;}begin(){return new wr(0,this)}end(){return new wr(this.i,this)}rBegin(){return new wr(this.i-1,this,1)}rEnd(){return new wr(-1,this,1)}front(){return this.J[0]}back(){return this.J[this.i-1]}getElementByPos(e){if(e<0||e>this.i-1)throw new RangeError;return this.J[e]}eraseElementByPos(e){if(e<0||e>this.i-1)throw new RangeError;return this.J.splice(e,1),this.i-=1,this.i}eraseElementByValue(e){let r=0;for(let i=0;ithis.i-1)throw new RangeError;this.J[e]=r;}insert(e,r,i=1){if(e<0||e>this.i)throw new RangeError;return this.J.splice(e,0,...new Array(i).fill(r)),this.i+=i,this.i}find(e){for(let r=0;r{v();m();_();Object.defineProperty(Wn,"t",{value:!0});Wn.default=void 0;var k1=M1(qn()),x1=at(),_r=lt();function M1(t){return t&&t.t?t:{default:t}}var mr=class t extends x1.ContainerIterator{constructor(e,r,i,n){super(n),this.o=e,this.h=r,this.container=i,this.iteratorType===0?(this.pre=function(){return this.o.L===this.h&&(0, _r.throwIteratorAccessError)(),this.o=this.o.L,this},this.next=function(){return this.o===this.h&&(0, _r.throwIteratorAccessError)(),this.o=this.o.B,this}):(this.pre=function(){return this.o.B===this.h&&(0, _r.throwIteratorAccessError)(),this.o=this.o.B,this},this.next=function(){return this.o===this.h&&(0, _r.throwIteratorAccessError)(),this.o=this.o.L,this});}get pointer(){return this.o===this.h&&(0, _r.throwIteratorAccessError)(),this.o.l}set pointer(e){this.o===this.h&&(0, _r.throwIteratorAccessError)(),this.o.l=e;}copy(){return new t(this.o,this.h,this.container,this.iteratorType)}},ya=class extends k1.default{constructor(e=[]){super(),this.h={},this.p=this._=this.h.L=this.h.B=this.h;let r=this;e.forEach(function(i){r.pushBack(i);});}V(e){let{L:r,B:i}=e;r.B=i,i.L=r,e===this.p&&(this.p=i),e===this._&&(this._=r),this.i-=1;}G(e,r){let i=r.B,n={l:e,L:r,B:i};r.B=n,i.L=n,r===this.h&&(this.p=n),i===this.h&&(this._=n),this.i+=1;}clear(){this.i=0,this.p=this._=this.h.L=this.h.B=this.h;}begin(){return new mr(this.p,this.h,this)}end(){return new mr(this.h,this.h,this)}rBegin(){return new mr(this._,this.h,this,1)}rEnd(){return new mr(this.h,this.h,this,1)}front(){return this.p.l}back(){return this._.l}getElementByPos(e){if(e<0||e>this.i-1)throw new RangeError;let r=this.p;for(;e--;)r=r.B;return r.l}eraseElementByPos(e){if(e<0||e>this.i-1)throw new RangeError;let r=this.p;for(;e--;)r=r.B;return this.V(r),this.i}eraseElementByValue(e){let r=this.p;for(;r!==this.h;)r.l===e&&this.V(r),r=r.B;return this.i}eraseElementByIterator(e){let r=e.o;return r===this.h&&(0, _r.throwIteratorAccessError)(),e=e.next(),this.V(r),e}pushBack(e){return this.G(e,this._),this.i}popBack(){if(this.i===0)return;let e=this._.l;return this.V(this._),e}pushFront(e){return this.G(e,this.h),this.i}popFront(){if(this.i===0)return;let e=this.p.l;return this.V(this.p),e}setElementByPos(e,r){if(e<0||e>this.i-1)throw new RangeError;let i=this.p;for(;e--;)i=i.B;i.l=r;}insert(e,r,i=1){if(e<0||e>this.i)throw new RangeError;if(i<=0)return this.i;if(e===0)for(;i--;)this.pushFront(r);else if(e===this.i)for(;i--;)this.pushBack(r);else {let n=this.p;for(let s=1;s{v();m();_();Object.defineProperty($n,"t",{value:!0});$n.default=void 0;var U1=q1(qn()),N1=pa();function q1(t){return t&&t.t?t:{default:t}}var vr=class t extends N1.RandomIterator{constructor(e,r,i){super(e,i),this.container=r;}copy(){return new t(this.o,this.container,this.iteratorType)}},ba=class extends U1.default{constructor(e=[],r=4096){super(),this.j=0,this.D=0,this.R=0,this.N=0,this.P=0,this.A=[];let i=(()=>{if(typeof e.length=="number")return e.length;if(typeof e.size=="number")return e.size;if(typeof e.size=="function")return e.size();throw new TypeError("Cannot get the length or size of the container")})();this.F=r,this.P=Math.max(Math.ceil(i/this.F),1);for(let s=0;s>1)-(n>>1),this.D=this.N=this.F-i%this.F>>1;let o=this;e.forEach(function(s){o.pushBack(s);});}T(){let e=[],r=Math.max(this.P>>1,1);for(let i=0;i>1;}begin(){return new vr(0,this)}end(){return new vr(this.i,this)}rBegin(){return new vr(this.i-1,this,1)}rEnd(){return new vr(-1,this,1)}front(){if(this.i!==0)return this.A[this.j][this.D]}back(){if(this.i!==0)return this.A[this.R][this.N]}pushBack(e){return this.i&&(this.N0?this.N-=1:this.R>0?(this.R-=1,this.N=this.F-1):(this.R=this.P-1,this.N=this.F-1)),this.i-=1,e}pushFront(e){return this.i&&(this.D>0?this.D-=1:this.j>0?(this.j-=1,this.D=this.F-1):(this.j=this.P-1,this.D=this.F-1),this.j===this.R&&this.D===this.N&&this.T()),this.i+=1,this.A[this.j][this.D]=e,this.i}popFront(){if(this.i===0)return;let e=this.A[this.j][this.D];return this.i!==1&&(this.Dthis.i-1)throw new RangeError;let{curNodeBucketIndex:r,curNodePointerIndex:i}=this.O(e);return this.A[r][i]}setElementByPos(e,r){if(e<0||e>this.i-1)throw new RangeError;let{curNodeBucketIndex:i,curNodePointerIndex:n}=this.O(e);this.A[i][n]=r;}insert(e,r,i=1){if(e<0||e>this.i)throw new RangeError;if(e===0)for(;i--;)this.pushFront(r);else if(e===this.i)for(;i--;)this.pushBack(r);else {let n=[];for(let o=e;othis.i-1)throw new RangeError;if(e===0)this.popFront();else if(e===this.i-1)this.popBack();else {let r=[];for(let n=e+1;ne;)this.popBack();return this.i}sort(e){let r=[];for(let i=0;i{v();m();_();Object.defineProperty(Zr,"t",{value:!0});Zr.TreeNodeEnableIndex=Zr.TreeNode=void 0;var Hn=class{constructor(e,r){this.ee=1,this.u=void 0,this.l=void 0,this.U=void 0,this.W=void 0,this.tt=void 0,this.u=e,this.l=r;}L(){let e=this;if(e.ee===1&&e.tt.tt===e)e=e.W;else if(e.U)for(e=e.U;e.W;)e=e.W;else {let r=e.tt;for(;r.U===e;)e=r,r=e.tt;e=r;}return e}B(){let e=this;if(e.W){for(e=e.W;e.U;)e=e.U;return e}else {let r=e.tt;for(;r.W===e;)e=r,r=e.tt;return e.W!==r?r:e}}te(){let e=this.tt,r=this.W,i=r.U;return e.tt===this?e.tt=r:e.U===this?e.U=r:e.W=r,r.tt=e,r.U=this,this.tt=r,this.W=i,i&&(i.tt=this),r}se(){let e=this.tt,r=this.U,i=r.W;return e.tt===this?e.tt=r:e.U===this?e.U=r:e.W=r,r.tt=e,r.W=this,this.tt=r,this.U=i,i&&(i.tt=this),r}};Zr.TreeNode=Hn;var wa=class extends Hn{constructor(){super(...arguments),this.rt=1;}te(){let e=super.te();return this.ie(),e.ie(),e}se(){let e=super.se();return this.ie(),e.ie(),e}ie(){this.rt=1,this.U&&(this.rt+=this.U.rt),this.W&&(this.rt+=this.W.rt);}};Zr.TreeNodeEnableIndex=wa;});var ma=M(Vn=>{v();m();_();Object.defineProperty(Vn,"t",{value:!0});Vn.default=void 0;var op=sp(),j1=at(),ap=lt(),_a=class extends j1.Container{constructor(e=function(i,n){return in?1:0},r=!1){super(),this.Y=void 0,this.v=e,r?(this.re=op.TreeNodeEnableIndex,this.M=function(i,n,o){let s=this.ne(i,n,o);if(s){let a=s.tt;for(;a!==this.h;)a.rt+=1,a=a.tt;let u=this.he(s);if(u){let{parentNode:c,grandParent:h,curNode:d}=u;c.ie(),h.ie(),d.ie();}}return this.i},this.V=function(i){let n=this.fe(i);for(;n!==this.h;)n.rt-=1,n=n.tt;}):(this.re=op.TreeNode,this.M=function(i,n,o){let s=this.ne(i,n,o);return s&&this.he(s),this.i},this.V=this.fe),this.h=new this.re;}X(e,r){let i=this.h;for(;e;){let n=this.v(e.u,r);if(n<0)e=e.W;else if(n>0)i=e,e=e.U;else return e}return i}Z(e,r){let i=this.h;for(;e;)this.v(e.u,r)<=0?e=e.W:(i=e,e=e.U);return i}$(e,r){let i=this.h;for(;e;){let n=this.v(e.u,r);if(n<0)i=e,e=e.W;else if(n>0)e=e.U;else return e}return i}rr(e,r){let i=this.h;for(;e;)this.v(e.u,r)<0?(i=e,e=e.W):e=e.U;return i}ue(e){for(;;){let r=e.tt;if(r===this.h)return;if(e.ee===1){e.ee=0;return}if(e===r.U){let i=r.W;if(i.ee===1)i.ee=0,r.ee=1,r===this.Y?this.Y=r.te():r.te();else if(i.W&&i.W.ee===1){i.ee=r.ee,r.ee=0,i.W.ee=0,r===this.Y?this.Y=r.te():r.te();return}else i.U&&i.U.ee===1?(i.ee=1,i.U.ee=0,i.se()):(i.ee=1,e=r);}else {let i=r.U;if(i.ee===1)i.ee=0,r.ee=1,r===this.Y?this.Y=r.se():r.se();else if(i.U&&i.U.ee===1){i.ee=r.ee,r.ee=0,i.U.ee=0,r===this.Y?this.Y=r.se():r.se();return}else i.W&&i.W.ee===1?(i.ee=1,i.W.ee=0,i.te()):(i.ee=1,e=r);}}}fe(e){if(this.i===1)return this.clear(),this.h;let r=e;for(;r.U||r.W;){if(r.W)for(r=r.W;r.U;)r=r.U;else r=r.U;[e.u,r.u]=[r.u,e.u],[e.l,r.l]=[r.l,e.l],e=r;}this.h.U===r?this.h.U=r.tt:this.h.W===r&&(this.h.W=r.tt),this.ue(r);let i=r.tt;return r===i.U?i.U=void 0:i.W=void 0,this.i-=1,this.Y.ee=0,i}oe(e,r){return e===void 0?!1:this.oe(e.U,r)||r(e)?!0:this.oe(e.W,r)}he(e){for(;;){let r=e.tt;if(r.ee===0)return;let i=r.tt;if(r===i.U){let n=i.W;if(n&&n.ee===1){if(n.ee=r.ee=0,i===this.Y)return;i.ee=1,e=i;continue}else if(e===r.W){if(e.ee=0,e.U&&(e.U.tt=r),e.W&&(e.W.tt=i),r.W=e.U,i.U=e.W,e.U=r,e.W=i,i===this.Y)this.Y=e,this.h.tt=e;else {let o=i.tt;o.U===i?o.U=e:o.W=e;}return e.tt=i.tt,r.tt=e,i.tt=e,i.ee=1,{parentNode:r,grandParent:i,curNode:e}}else r.ee=0,i===this.Y?this.Y=i.se():i.se(),i.ee=1;}else {let n=i.U;if(n&&n.ee===1){if(n.ee=r.ee=0,i===this.Y)return;i.ee=1,e=i;continue}else if(e===r.U){if(e.ee=0,e.U&&(e.U.tt=i),e.W&&(e.W.tt=r),i.W=e.U,r.U=e.W,e.U=i,e.W=r,i===this.Y)this.Y=e,this.h.tt=e;else {let o=i.tt;o.U===i?o.U=e:o.W=e;}return e.tt=i.tt,r.tt=e,i.tt=e,i.ee=1,{parentNode:r,grandParent:i,curNode:e}}else r.ee=0,i===this.Y?this.Y=i.te():i.te(),i.ee=1;}return}}ne(e,r,i){if(this.Y===void 0){this.i+=1,this.Y=new this.re(e,r),this.Y.ee=0,this.Y.tt=this.h,this.h.tt=this.Y,this.h.U=this.Y,this.h.W=this.Y;return}let n,o=this.h.U,s=this.v(o.u,e);if(s===0){o.l=r;return}else if(s>0)o.U=new this.re(e,r),o.U.tt=o,n=o.U,this.h.U=n;else {let a=this.h.W,u=this.v(a.u,e);if(u===0){a.l=r;return}else if(u<0)a.W=new this.re(e,r),a.W.tt=a,n=a.W,this.h.W=n;else {if(i!==void 0){let c=i.o;if(c!==this.h){let h=this.v(c.u,e);if(h===0){c.l=r;return}else if(h>0){let d=c.L(),g=this.v(d.u,e);if(g===0){d.l=r;return}else g<0&&(n=new this.re(e,r),d.W===void 0?(d.W=n,n.tt=d):(c.U=n,n.tt=c));}}}if(n===void 0)for(n=this.Y;;){let c=this.v(n.u,e);if(c>0){if(n.U===void 0){n.U=new this.re(e,r),n.U.tt=n,n=n.U;break}n=n.U;}else if(c<0){if(n.W===void 0){n.W=new this.re(e,r),n.W.tt=n,n=n.W;break}n=n.W;}else {n.l=r;return}}}}return this.i+=1,n}I(e,r){for(;e;){let i=this.v(e.u,r);if(i<0)e=e.W;else if(i>0)e=e.U;else return e}return e||this.h}clear(){this.i=0,this.Y=void 0,this.h.tt=void 0,this.h.U=this.h.W=void 0;}updateKeyByIterator(e,r){let i=e.o;if(i===this.h&&(0, ap.throwIteratorAccessError)(),this.i===1)return i.u=r,!0;if(i===this.h.U)return this.v(i.B().u,r)>0?(i.u=r,!0):!1;if(i===this.h.W)return this.v(i.L().u,r)<0?(i.u=r,!0):!1;let n=i.L().u;if(this.v(n,r)>=0)return !1;let o=i.B().u;return this.v(o,r)<=0?!1:(i.u=r,!0)}eraseElementByPos(e){if(e<0||e>this.i-1)throw new RangeError;let r=0,i=this;return this.oe(this.Y,function(n){return e===r?(i.V(n),!0):(r+=1,!1)}),this.i}eraseElementByKey(e){if(this.i===0)return !1;let r=this.I(this.Y,e);return r===this.h?!1:(this.V(r),!0)}eraseElementByIterator(e){let r=e.o;r===this.h&&(0, ap.throwIteratorAccessError)();let i=r.W===void 0;return e.iteratorType===0?i&&e.next():(!i||r.U===void 0)&&e.next(),this.V(r),e}forEach(e){let r=0;for(let i of this)e(i,r++,this);}getElementByPos(e){if(e<0||e>this.i-1)throw new RangeError;let r,i=0;for(let n of this){if(i===e){r=n;break}i+=1;}return r}getHeight(){if(this.i===0)return 0;let e=function(r){return r?Math.max(e(r.U),e(r.W))+1:0};return e(this.Y)}},F1=_a;Vn.default=F1;});var Ea=M(Kn=>{v();m();_();Object.defineProperty(Kn,"t",{value:!0});Kn.default=void 0;var W1=at(),zn=lt(),va=class extends W1.ContainerIterator{constructor(e,r,i){super(i),this.o=e,this.h=r,this.iteratorType===0?(this.pre=function(){return this.o===this.h.U&&(0, zn.throwIteratorAccessError)(),this.o=this.o.L(),this},this.next=function(){return this.o===this.h&&(0, zn.throwIteratorAccessError)(),this.o=this.o.B(),this}):(this.pre=function(){return this.o===this.h.W&&(0, zn.throwIteratorAccessError)(),this.o=this.o.B(),this},this.next=function(){return this.o===this.h&&(0, zn.throwIteratorAccessError)(),this.o=this.o.L(),this});}get index(){let e=this.o,r=this.h.tt;if(e===this.h)return r?r.rt-1:0;let i=0;for(e.U&&(i+=e.U.rt);e!==r;){let n=e.tt;e===n.W&&(i+=1,n.U&&(i+=n.U.rt)),e=n;}return i}},$1=va;Kn.default=$1;});var up=M(Gn=>{v();m();_();Object.defineProperty(Gn,"t",{value:!0});Gn.default=void 0;var H1=lp(ma()),V1=lp(Ea()),z1=lt();function lp(t){return t&&t.t?t:{default:t}}var Ke=class t extends V1.default{constructor(e,r,i,n){super(e,r,n),this.container=i;}get pointer(){return this.o===this.h&&(0, z1.throwIteratorAccessError)(),this.o.u}copy(){return new t(this.o,this.h,this.container,this.iteratorType)}},Sa=class extends H1.default{constructor(e=[],r,i){super(r,i);let n=this;e.forEach(function(o){n.insert(o);});}*K(e){e!==void 0&&(yield*this.K(e.U),yield e.u,yield*this.K(e.W));}begin(){return new Ke(this.h.U||this.h,this.h,this)}end(){return new Ke(this.h,this.h,this)}rBegin(){return new Ke(this.h.W||this.h,this.h,this,1)}rEnd(){return new Ke(this.h,this.h,this,1)}front(){return this.h.U?this.h.U.u:void 0}back(){return this.h.W?this.h.W.u:void 0}insert(e,r){return this.M(e,void 0,r)}find(e){let r=this.I(this.Y,e);return new Ke(r,this.h,this)}lowerBound(e){let r=this.X(this.Y,e);return new Ke(r,this.h,this)}upperBound(e){let r=this.Z(this.Y,e);return new Ke(r,this.h,this)}reverseLowerBound(e){let r=this.$(this.Y,e);return new Ke(r,this.h,this)}reverseUpperBound(e){let r=this.rr(this.Y,e);return new Ke(r,this.h,this)}union(e){let r=this;return e.forEach(function(i){r.insert(i);}),this.i}[Symbol.iterator](){return this.K(this.Y)}},K1=Sa;Gn.default=K1;});var cp=M(Qn=>{v();m();_();Object.defineProperty(Qn,"t",{value:!0});Qn.default=void 0;var G1=fp(ma()),Q1=fp(Ea()),Y1=lt();function fp(t){return t&&t.t?t:{default:t}}var Ge=class t extends Q1.default{constructor(e,r,i,n){super(e,r,n),this.container=i;}get pointer(){this.o===this.h&&(0, Y1.throwIteratorAccessError)();let e=this;return new Proxy([],{get(r,i){if(i==="0")return e.o.u;if(i==="1")return e.o.l},set(r,i,n){if(i!=="1")throw new TypeError("props must be 1");return e.o.l=n,!0}})}copy(){return new t(this.o,this.h,this.container,this.iteratorType)}},Aa=class extends G1.default{constructor(e=[],r,i){super(r,i);let n=this;e.forEach(function(o){n.setElement(o[0],o[1]);});}*K(e){e!==void 0&&(yield*this.K(e.U),yield [e.u,e.l],yield*this.K(e.W));}begin(){return new Ge(this.h.U||this.h,this.h,this)}end(){return new Ge(this.h,this.h,this)}rBegin(){return new Ge(this.h.W||this.h,this.h,this,1)}rEnd(){return new Ge(this.h,this.h,this,1)}front(){if(this.i===0)return;let e=this.h.U;return [e.u,e.l]}back(){if(this.i===0)return;let e=this.h.W;return [e.u,e.l]}lowerBound(e){let r=this.X(this.Y,e);return new Ge(r,this.h,this)}upperBound(e){let r=this.Z(this.Y,e);return new Ge(r,this.h,this)}reverseLowerBound(e){let r=this.$(this.Y,e);return new Ge(r,this.h,this)}reverseUpperBound(e){let r=this.rr(this.Y,e);return new Ge(r,this.h,this)}setElement(e,r,i){return this.M(e,r,i)}find(e){let r=this.I(this.Y,e);return new Ge(r,this.h,this)}getElementByKey(e){return this.I(this.Y,e).l}union(e){let r=this;return e.forEach(function(i){r.setElement(i[0],i[1]);}),this.i}[Symbol.iterator](){return this.K(this.Y)}},J1=Aa;Qn.default=J1;});var Ta=M(Ia=>{v();m();_();Object.defineProperty(Ia,"t",{value:!0});Ia.default=X1;function X1(t){let e=typeof t;return e==="object"&&t!==null||e==="function"}});var Pa=M(ei=>{v();m();_();Object.defineProperty(ei,"t",{value:!0});ei.HashContainerIterator=ei.HashContainer=void 0;var hp=at(),Ra=Z1(Ta()),Ti=lt();function Z1(t){return t&&t.t?t:{default:t}}var Ca=class extends hp.ContainerIterator{constructor(e,r,i){super(i),this.o=e,this.h=r,this.iteratorType===0?(this.pre=function(){return this.o.L===this.h&&(0, Ti.throwIteratorAccessError)(),this.o=this.o.L,this},this.next=function(){return this.o===this.h&&(0, Ti.throwIteratorAccessError)(),this.o=this.o.B,this}):(this.pre=function(){return this.o.B===this.h&&(0, Ti.throwIteratorAccessError)(),this.o=this.o.B,this},this.next=function(){return this.o===this.h&&(0, Ti.throwIteratorAccessError)(),this.o=this.o.L,this});}};ei.HashContainerIterator=Ca;var Ba=class extends hp.Container{constructor(){super(),this.H=[],this.g={},this.HASH_TAG=Symbol("@@HASH_TAG"),Object.setPrototypeOf(this.g,null),this.h={},this.h.L=this.h.B=this.p=this._=this.h;}V(e){let{L:r,B:i}=e;r.B=i,i.L=r,e===this.p&&(this.p=i),e===this._&&(this._=r),this.i-=1;}M(e,r,i){i===void 0&&(i=(0, Ra.default)(e));let n;if(i){let o=e[this.HASH_TAG];if(o!==void 0)return this.H[o].l=r,this.i;Object.defineProperty(e,this.HASH_TAG,{value:this.H.length,configurable:!0}),n={u:e,l:r,L:this._,B:this.h},this.H.push(n);}else {let o=this.g[e];if(o)return o.l=r,this.i;n={u:e,l:r,L:this._,B:this.h},this.g[e]=n;}return this.i===0?(this.p=n,this.h.B=n):this._.B=n,this._=n,this.h.L=n,++this.i}I(e,r){if(r===void 0&&(r=(0, Ra.default)(e)),r){let i=e[this.HASH_TAG];return i===void 0?this.h:this.H[i]}else return this.g[e]||this.h}clear(){let e=this.HASH_TAG;this.H.forEach(function(r){delete r.u[e];}),this.H=[],this.g={},Object.setPrototypeOf(this.g,null),this.i=0,this.p=this._=this.h.L=this.h.B=this.h;}eraseElementByKey(e,r){let i;if(r===void 0&&(r=(0, Ra.default)(e)),r){let n=e[this.HASH_TAG];if(n===void 0)return !1;delete e[this.HASH_TAG],i=this.H[n],delete this.H[n];}else {if(i=this.g[e],i===void 0)return !1;delete this.g[e];}return this.V(i),!0}eraseElementByIterator(e){let r=e.o;return r===this.h&&(0, Ti.throwIteratorAccessError)(),this.V(r),e.next()}eraseElementByPos(e){if(e<0||e>this.i-1)throw new RangeError;let r=this.p;for(;e--;)r=r.B;return this.V(r),this.i}};ei.HashContainer=Ba;});var pp=M(Yn=>{v();m();_();Object.defineProperty(Yn,"t",{value:!0});Yn.default=void 0;var dp=Pa(),ev=lt(),Er=class t extends dp.HashContainerIterator{constructor(e,r,i,n){super(e,r,n),this.container=i;}get pointer(){return this.o===this.h&&(0, ev.throwIteratorAccessError)(),this.o.u}copy(){return new t(this.o,this.h,this.container,this.iteratorType)}},Oa=class extends dp.HashContainer{constructor(e=[]){super();let r=this;e.forEach(function(i){r.insert(i);});}begin(){return new Er(this.p,this.h,this)}end(){return new Er(this.h,this.h,this)}rBegin(){return new Er(this._,this.h,this,1)}rEnd(){return new Er(this.h,this.h,this,1)}front(){return this.p.u}back(){return this._.u}insert(e,r){return this.M(e,void 0,r)}getElementByPos(e){if(e<0||e>this.i-1)throw new RangeError;let r=this.p;for(;e--;)r=r.B;return r.u}find(e,r){let i=this.I(e,r);return new Er(i,this.h,this)}forEach(e){let r=0,i=this.p;for(;i!==this.h;)e(i.u,r++,this),i=i.B;}[Symbol.iterator](){return function*(){let e=this.p;for(;e!==this.h;)yield e.u,e=e.B;}.bind(this)()}},tv=Oa;Yn.default=tv;});var yp=M(Jn=>{v();m();_();Object.defineProperty(Jn,"t",{value:!0});Jn.default=void 0;var gp=Pa(),rv=nv(Ta()),iv=lt();function nv(t){return t&&t.t?t:{default:t}}var Sr=class t extends gp.HashContainerIterator{constructor(e,r,i,n){super(e,r,n),this.container=i;}get pointer(){this.o===this.h&&(0, iv.throwIteratorAccessError)();let e=this;return new Proxy([],{get(r,i){if(i==="0")return e.o.u;if(i==="1")return e.o.l},set(r,i,n){if(i!=="1")throw new TypeError("props must be 1");return e.o.l=n,!0}})}copy(){return new t(this.o,this.h,this.container,this.iteratorType)}},ka=class extends gp.HashContainer{constructor(e=[]){super();let r=this;e.forEach(function(i){r.setElement(i[0],i[1]);});}begin(){return new Sr(this.p,this.h,this)}end(){return new Sr(this.h,this.h,this)}rBegin(){return new Sr(this._,this.h,this,1)}rEnd(){return new Sr(this.h,this.h,this,1)}front(){if(this.i!==0)return [this.p.u,this.p.l]}back(){if(this.i!==0)return [this._.u,this._.l]}setElement(e,r,i){return this.M(e,r,i)}getElementByKey(e,r){if(r===void 0&&(r=(0, rv.default)(e)),r){let n=e[this.HASH_TAG];return n!==void 0?this.H[n].l:void 0}let i=this.g[e];return i?i.l:void 0}getElementByPos(e){if(e<0||e>this.i-1)throw new RangeError;let r=this.p;for(;e--;)r=r.B;return [r.u,r.l]}find(e,r){let i=this.I(e,r);return new Sr(i,this.h,this)}forEach(e){let r=0,i=this.p;for(;i!==this.h;)e([i.u,i.l],r++,this),i=i.B;}[Symbol.iterator](){return function*(){let e=this.p;for(;e!==this.h;)yield [e.u,e.l],e=e.B;}.bind(this)()}},sv=ka;Jn.default=sv;});var bp=M(je=>{v();m();_();Object.defineProperty(je,"t",{value:!0});Object.defineProperty(je,"Deque",{enumerable:!0,get:function(){return cv.default}});Object.defineProperty(je,"HashMap",{enumerable:!0,get:function(){return gv.default}});Object.defineProperty(je,"HashSet",{enumerable:!0,get:function(){return pv.default}});Object.defineProperty(je,"LinkList",{enumerable:!0,get:function(){return fv.default}});Object.defineProperty(je,"OrderedMap",{enumerable:!0,get:function(){return dv.default}});Object.defineProperty(je,"OrderedSet",{enumerable:!0,get:function(){return hv.default}});Object.defineProperty(je,"PriorityQueue",{enumerable:!0,get:function(){return lv.default}});Object.defineProperty(je,"Queue",{enumerable:!0,get:function(){return av.default}});Object.defineProperty(je,"Stack",{enumerable:!0,get:function(){return ov.default}});Object.defineProperty(je,"Vector",{enumerable:!0,get:function(){return uv.default}});var ov=ut(Zd()),av=ut(ep()),lv=ut(tp()),uv=ut(rp()),fv=ut(ip()),cv=ut(np()),hv=ut(up()),dv=ut(cp()),pv=ut(pp()),gv=ut(yp());function ut(t){return t&&t.t?t:{default:t}}});var _p=M((mN,wp)=>{v();m();_();var yv=bp().OrderedSet,ft=ot()("number-allocator:trace"),bv=ot()("number-allocator:error");function Te(t,e){this.low=t,this.high=e;}Te.prototype.equals=function(t){return this.low===t.low&&this.high===t.high};Te.prototype.compare=function(t){return this.lowr.compare(i)),ft("Create"),this.clear();}ct.prototype.firstVacant=function(){return this.ss.size()===0?null:this.ss.front().low};ct.prototype.alloc=function(){if(this.ss.size()===0)return ft("alloc():empty"),null;let t=this.ss.begin(),e=t.pointer.low,r=t.pointer.high,i=e;return i+1<=r?this.ss.updateKeyByIterator(t,new Te(e+1,r)):this.ss.eraseElementByPos(0),ft("alloc():"+i),i};ct.prototype.use=function(t){let e=new Te(t,t),r=this.ss.lowerBound(e);if(!r.equals(this.ss.end())){let i=r.pointer.low,n=r.pointer.high;return r.pointer.equals(e)?(this.ss.eraseElementByIterator(r),ft("use():"+t),!0):i>t?!1:i===t?(this.ss.updateKeyByIterator(r,new Te(i+1,n)),ft("use():"+t),!0):n===t?(this.ss.updateKeyByIterator(r,new Te(i,n-1)),ft("use():"+t),!0):(this.ss.updateKeyByIterator(r,new Te(t+1,n)),this.ss.insert(new Te(i,t-1)),ft("use():"+t),!0)}return ft("use():failed"),!1};ct.prototype.free=function(t){if(tthis.max){bv("free():"+t+" is out of range");return}let e=new Te(t,t),r=this.ss.upperBound(e);if(r.equals(this.ss.end())){if(r.equals(this.ss.begin())){this.ss.insert(e);return}r.pre();let i=r.pointer.high;r.pointer.high+1===t?this.ss.updateKeyByIterator(r,new Te(i,t)):this.ss.insert(e);}else if(r.equals(this.ss.begin()))if(t+1===r.pointer.low){let i=r.pointer.high;this.ss.updateKeyByIterator(r,new Te(t,i));}else this.ss.insert(e);else {let i=r.pointer.low,n=r.pointer.high;r.pre();let o=r.pointer.low;r.pointer.high+1===t?t+1===i?(this.ss.eraseElementByIterator(r),this.ss.updateKeyByIterator(r,new Te(o,n))):this.ss.updateKeyByIterator(r,new Te(o,t)):t+1===i?(this.ss.eraseElementByIterator(r.next()),this.ss.insert(new Te(t,n))):this.ss.insert(e);}ft("free():"+t);};ct.prototype.clear=function(){ft("clear()"),this.ss.clear(),this.ss.insert(new Te(this.min,this.max));};ct.prototype.intervalCount=function(){return this.ss.size()};ct.prototype.dump=function(){console.log("length:"+this.ss.size());for(let t of this.ss)console.log(t);};wp.exports=ct;});var xa=M((PN,mp)=>{v();m();_();var wv=_p();mp.exports.NumberAllocator=wv;});var vp=M(La=>{v();m();_();Object.defineProperty(La,"__esModule",{value:!0});var _v=Xd(),mv=xa(),Ma=class{constructor(e){e>0&&(this.aliasToTopic=new _v.LRUCache({max:e}),this.topicToAlias={},this.numberAllocator=new mv.NumberAllocator(1,e),this.max=e,this.length=0);}put(e,r){if(r===0||r>this.max)return !1;let i=this.aliasToTopic.get(r);return i&&delete this.topicToAlias[i],this.aliasToTopic.set(r,e),this.topicToAlias[e]=r,this.numberAllocator.use(r),this.length=this.aliasToTopic.size,!0}getTopicByAlias(e){return this.aliasToTopic.get(e)}getAliasByTopic(e){let r=this.topicToAlias[e];return typeof r<"u"&&this.aliasToTopic.get(r),r}clear(){this.aliasToTopic.clear(),this.topicToAlias={},this.numberAllocator.clear(),this.length=0;}getLruAlias(){let e=this.numberAllocator.firstVacant();return e||[...this.aliasToTopic.keys()][this.aliasToTopic.size-1]}};La.default=Ma;});var Ep=M(Ri=>{v();m();_();var vv=Ri&&Ri.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Ri,"__esModule",{value:!0});var Ev=Ai(),Sv=vv(vp()),Av=Jr(),Iv=(t,e)=>{t.log("_handleConnack");let{options:r}=t,n=r.protocolVersion===5?e.reasonCode:e.returnCode;if(clearTimeout(t.connackTimer),delete t.topicAliasSend,e.properties){if(e.properties.topicAliasMaximum){if(e.properties.topicAliasMaximum>65535){t.emit("error",new Error("topicAliasMaximum from broker is out of range"));return}e.properties.topicAliasMaximum>0&&(t.topicAliasSend=new Sv.default(e.properties.topicAliasMaximum));}e.properties.serverKeepAlive&&r.keepalive&&(r.keepalive=e.properties.serverKeepAlive,t._shiftPingInterval()),e.properties.maximumPacketSize&&(r.properties||(r.properties={}),r.properties.maximumPacketSize=e.properties.maximumPacketSize);}if(n===0)t.reconnecting=!1,t._onConnect(e);else if(n>0){let o=new Av.ErrorWithReasonCode(`Connection refused: ${Ev.ReasonCodes[n]}`,n);t.emit("error",o);}};Ri.default=Iv;});var Sp=M(Ua=>{v();m();_();Object.defineProperty(Ua,"__esModule",{value:!0});var Tv=(t,e,r)=>{t.log("handling pubrel packet");let i=typeof r<"u"?r:t.noop,{messageId:n}=e,o={cmd:"pubcomp",messageId:n};t.incomingStore.get(e,(s,a)=>{s?t._sendPacket(o,i):(t.emit("message",a.topic,a.payload,a),t.handleMessage(a,u=>{if(u)return i(u);t.incomingStore.del(a,t.noop),t._sendPacket(o,i);}));});};Ua.default=Tv;});var Ap=M(Ci=>{v();m();_();var Bi=Ci&&Ci.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Ci,"__esModule",{value:!0});var Rv=Bi(Vd()),Cv=Bi(Kd()),Bv=Bi(Ep()),Pv=Bi(Ai()),Ov=Bi(Sp()),kv=(t,e,r)=>{let{options:i}=t;if(i.protocolVersion===5&&i.properties&&i.properties.maximumPacketSize&&i.properties.maximumPacketSize{v();m();_();var xv=ti&&ti.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(ti,"__esModule",{value:!0});ti.TypedEventEmitter=void 0;var Mv=xv((ir(),X(rr))),Lv=Jr(),Xn=class{};ti.TypedEventEmitter=Xn;(0, Lv.applyMixin)(Xn,Mv.default);});var Pi=M(Ar=>{v();m();_();Object.defineProperty(Ar,"__esModule",{value:!0});Ar.isReactNativeBrowser=Ar.isWebWorker=void 0;var Uv=()=>typeof window<"u"&&typeof window.document<"u",Tp=()=>{var t,e;return !!(typeof self=="object"&&(!((e=(t=self?.constructor)===null||t===void 0?void 0:t.name)===null||e===void 0)&&e.includes("WorkerGlobalScope")))},Rp=()=>typeof B<"u"&&B.product==="ReactNative",Nv=Uv()||Tp()||Rp();Ar.isWebWorker=Tp();Ar.isReactNativeBrowser=Rp();Ar.default=Nv;});var Bp=M((Zn,Cp)=>{v();m();_();(function(t,e){typeof Zn=="object"&&typeof Cp<"u"?e(Zn):typeof define=="function"&&__webpack_require__.amdO?define(["exports"],e):(t=typeof globalThis<"u"?globalThis:t||self,e(t.fastUniqueNumbers={}));})(Zn,function(t){var e=function(g){return function(y){var w=g(y);return y.add(w),w}},r=function(g){return function(y,w){return g.set(y,w),w}},i=Number.MAX_SAFE_INTEGER===void 0?9007199254740991:Number.MAX_SAFE_INTEGER,n=536870912,o=n*2,s=function(g,y){return function(w){var E=y.get(w),S=E===void 0?w.size:Ei)throw new Error("Congratulations, you created a collection of unique numbers which uses all available integers!");for(;w.has(S);)S=Math.floor(Math.random()*i);return g(w,S)}},a=new WeakMap,u=r(a),c=s(u,a),h=e(c);t.addUniqueNumber=h,t.generateUniqueNumber=c;});});var Op=M((es,Pp)=>{v();m();_();(function(t,e){typeof es=="object"&&typeof Pp<"u"?e(es,Bp()):typeof define=="function"&&__webpack_require__.amdO?define(["exports","fast-unique-numbers"],e):(t=typeof globalThis<"u"?globalThis:t||self,e(t.workerTimersBroker={},t.fastUniqueNumbers));})(es,function(t,e){var r=function(s){return s.method!==void 0&&s.method==="call"},i=function(s){return s.error===null&&typeof s.id=="number"},n=function(s){var a=new Map([[0,function(){}]]),u=new Map([[0,function(){}]]),c=new Map,h=new Worker(s);h.addEventListener("message",function(E){var S=E.data;if(r(S)){var I=S.params,C=I.timerId,R=I.timerType;if(R==="interval"){var U=a.get(C);if(typeof U=="number"){var N=c.get(U);if(N===void 0||N.timerId!==C||N.timerType!==R)throw new Error("The timer is in an undefined state.")}else if(typeof U<"u")U();else throw new Error("The timer is in an undefined state.")}else if(R==="timeout"){var W=u.get(C);if(typeof W=="number"){var K=c.get(W);if(K===void 0||K.timerId!==C||K.timerType!==R)throw new Error("The timer is in an undefined state.")}else if(typeof W<"u")W(),u.delete(C);else throw new Error("The timer is in an undefined state.")}}else if(i(S)){var z=S.id,Q=c.get(z);if(Q===void 0)throw new Error("The timer is in an undefined state.");var de=Q.timerId,Gt=Q.timerType;c.delete(z),Gt==="interval"?a.delete(de):u.delete(de);}else {var pe=S.error.message;throw new Error(pe)}});var d=function(S){var I=e.generateUniqueNumber(c);c.set(I,{timerId:S,timerType:"interval"}),a.set(S,I),h.postMessage({id:I,method:"clear",params:{timerId:S,timerType:"interval"}});},g=function(S){var I=e.generateUniqueNumber(c);c.set(I,{timerId:S,timerType:"timeout"}),u.set(S,I),h.postMessage({id:I,method:"clear",params:{timerId:S,timerType:"timeout"}});},y=function(S){var I=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,C=e.generateUniqueNumber(a);return a.set(C,function(){S(),typeof a.get(C)=="function"&&h.postMessage({id:null,method:"set",params:{delay:I,now:performance.now(),timerId:C,timerType:"interval"}});}),h.postMessage({id:null,method:"set",params:{delay:I,now:performance.now(),timerId:C,timerType:"interval"}}),C},w=function(S){var I=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,C=e.generateUniqueNumber(u);return u.set(C,S),h.postMessage({id:null,method:"set",params:{delay:I,now:performance.now(),timerId:C,timerType:"timeout"}}),C};return {clearInterval:d,clearTimeout:g,setInterval:y,setTimeout:w}};t.load=n;});});var xp=M((ts,kp)=>{v();m();_();(function(t,e){typeof ts=="object"&&typeof kp<"u"?e(ts,Op()):typeof define=="function"&&__webpack_require__.amdO?define(["exports","worker-timers-broker"],e):(t=typeof globalThis<"u"?globalThis:t||self,e(t.workerTimers={},t.workerTimersBroker));})(ts,function(t,e){var r=function(h,d){var g=null;return function(){if(g!==null)return g;var y=new Blob([d],{type:"application/javascript; charset=utf-8"}),w=URL.createObjectURL(y);return g=h(w),setTimeout(function(){return URL.revokeObjectURL(w)}),g}},i=`(()=>{var e={472:(e,t,r)=>{var o,i;void 0===(i="function"==typeof(o=function(){"use strict";var e=new Map,t=new Map,r=function(t){var r=e.get(t);if(void 0===r)throw new Error('There is no interval scheduled with the given id "'.concat(t,'".'));clearTimeout(r),e.delete(t)},o=function(e){var r=t.get(e);if(void 0===r)throw new Error('There is no timeout scheduled with the given id "'.concat(e,'".'));clearTimeout(r),t.delete(e)},i=function(e,t){var r,o=performance.now();return{expected:o+(r=e-Math.max(0,o-t)),remainingDelay:r}},n=function e(t,r,o,i){var n=performance.now();n>o?postMessage({id:null,method:"call",params:{timerId:r,timerType:i}}):t.set(r,setTimeout(e,o-n,t,r,o,i))},a=function(t,r,o){var a=i(t,o),s=a.expected,d=a.remainingDelay;e.set(r,setTimeout(n,d,e,r,s,"interval"))},s=function(e,r,o){var a=i(e,o),s=a.expected,d=a.remainingDelay;t.set(r,setTimeout(n,d,t,r,s,"timeout"))};addEventListener("message",(function(e){var t=e.data;try{if("clear"===t.method){var i=t.id,n=t.params,d=n.timerId,c=n.timerType;if("interval"===c)r(d),postMessage({error:null,id:i});else{if("timeout"!==c)throw new Error('The given type "'.concat(c,'" is not supported'));o(d),postMessage({error:null,id:i})}}else{if("set"!==t.method)throw new Error('The given method "'.concat(t.method,'" is not supported'));var u=t.params,l=u.delay,p=u.now,m=u.timerId,v=u.timerType;if("interval"===v)a(l,m,p);else{if("timeout"!==v)throw new Error('The given type "'.concat(v,'" is not supported'));s(l,m,p)}}}catch(e){postMessage({error:{message:e.message},id:t.id,result:null})}}))})?o.call(t,r,t,e):o)||(e.exports=i)}},t={};function r(o){var i=t[o];if(void 0!==i)return i.exports;var n=t[o]={exports:{}};return e[o](n,n.exports,r),n.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";r(472)})()})();`,n=r(e.load,i),o=function(h){return n().clearInterval(h)},s=function(h){return n().clearTimeout(h)},a=function(){var h;return (h=n()).setInterval.apply(h,arguments)},u=function(){var h;return (h=n()).setTimeout.apply(h,arguments)};t.clearInterval=o,t.clearTimeout=s,t.setInterval=a,t.setTimeout=u;});});var Np=M(Rt=>{v();m();_();var qv=Rt&&Rt.__createBinding||(Object.create?function(t,e,r,i){i===void 0&&(i=r);var n=Object.getOwnPropertyDescriptor(e,r);(!n||("get"in n?!e.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,i,n);}:function(t,e,r,i){i===void 0&&(i=r),t[i]=e[r];}),Dv=Rt&&Rt.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e});}:function(t,e){t.default=e;}),jv=Rt&&Rt.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.prototype.hasOwnProperty.call(t,r)&&qv(e,t,r);return Dv(e,t),e};Object.defineProperty(Rt,"__esModule",{value:!0});var Na=jv(Pi()),Mp=xp(),Lp={set:Mp.setTimeout,clear:Mp.clearTimeout},Up={set:(t,e)=>setTimeout(t,e),clear:t=>clearTimeout(t)},Fv=t=>{switch(t){case"native":return Up;case"worker":return Lp;case"auto":default:return Na.default&&!Na.isWebWorker&&!Na.isReactNativeBrowser?Lp:Up}};Rt.default=Fv;});var Da=M(Oi=>{v();m();_();var Wv=Oi&&Oi.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Oi,"__esModule",{value:!0});var $v=Wv(Np()),qa=class{constructor(e,r,i){this.keepalive=e*1e3,this.checkPing=r,this.timer=(0, $v.default)(i),this.reschedule();}clear(){this.timerId&&(this.timer.clear(this.timerId),this.timerId=null);}reschedule(){this.clear(),this.timerId=this.timer.set(()=>{this.checkPing(),this.timerId&&this.reschedule();},this.keepalive);}};Oi.default=qa;});var ns=M(Qe=>{v();m();_();var Hv=Qe&&Qe.__createBinding||(Object.create?function(t,e,r,i){i===void 0&&(i=r);var n=Object.getOwnPropertyDescriptor(e,r);(!n||("get"in n?!e.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,i,n);}:function(t,e,r,i){i===void 0&&(i=r),t[i]=e[r];}),Vv=Qe&&Qe.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e});}:function(t,e){t.default=e;}),Wp=Qe&&Qe.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.prototype.hasOwnProperty.call(t,r)&&Hv(e,t,r);return Vv(e,t),e},Vt=Qe&&Qe.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Qe,"__esModule",{value:!0});var zv=Vt(Gu()),ja=Vt(Nd()),Kv=Vt(Yo()),Gv=Dt(),qp=Vt(Fd()),Dp=Wp($d()),Qv=Vt(ot()),rs=Vt(Zo()),Yv=Vt(Ap()),Wa=Jr(),Jv=Ip(),Xv=Vt(Da()),jp=Wp(Pi()),Fa=globalThis.setImmediate||((...t)=>{let e=t.shift();(0, Wa.nextTick)(()=>{e(...t);});}),Fp={keepalive:60,reschedulePings:!0,protocolId:"MQTT",protocolVersion:4,reconnectPeriod:1e3,connectTimeout:30*1e3,clean:!0,resubscribe:!0,writeCache:!0,timerVariant:"auto"},is=class t extends Jv.TypedEventEmitter{static defaultId(){return `mqttjs_${Math.random().toString(16).substr(2,8)}`}constructor(e,r){super(),this.options=r||{};for(let i in Fp)typeof this.options[i]>"u"?this.options[i]=Fp[i]:this.options[i]=r[i];this.log=this.options.log||(0, Qv.default)("mqttjs:client"),this.noop=this._noop.bind(this),this.log("MqttClient :: version:",t.VERSION),jp.isWebWorker?this.log("MqttClient :: environment","webworker"):this.log("MqttClient :: environment",jp.default?"browser":"node"),this.log("MqttClient :: options.protocol",r.protocol),this.log("MqttClient :: options.protocolVersion",r.protocolVersion),this.log("MqttClient :: options.username",r.username),this.log("MqttClient :: options.keepalive",r.keepalive),this.log("MqttClient :: options.reconnectPeriod",r.reconnectPeriod),this.log("MqttClient :: options.rejectUnauthorized",r.rejectUnauthorized),this.log("MqttClient :: options.properties.topicAliasMaximum",r.properties?r.properties.topicAliasMaximum:void 0),this.options.clientId=typeof r.clientId=="string"?r.clientId:t.defaultId(),this.log("MqttClient :: clientId",this.options.clientId),this.options.customHandleAcks=r.protocolVersion===5&&r.customHandleAcks?r.customHandleAcks:(...i)=>{i[3](null,0);},this.options.writeCache||(ja.default.writeToStream.cacheNumbers=!1),this.streamBuilder=e,this.messageIdProvider=typeof this.options.messageIdProvider>"u"?new Kv.default:this.options.messageIdProvider,this.outgoingStore=r.outgoingStore||new rs.default,this.incomingStore=r.incomingStore||new rs.default,this.queueQoSZero=r.queueQoSZero===void 0?!0:r.queueQoSZero,this._resubscribeTopics={},this.messageIdToTopic={},this.pingTimer=null,this.connected=!1,this.disconnecting=!1,this.reconnecting=!1,this.queue=[],this.connackTimer=null,this.reconnectTimer=null,this._storeProcessing=!1,this._packetIdsDuringStoreProcessing={},this._storeProcessingQueue=[],this.outgoing={},this._firstConnection=!0,r.properties&&r.properties.topicAliasMaximum>0&&(r.properties.topicAliasMaximum>65535?this.log("MqttClient :: options.properties.topicAliasMaximum is out of range"):this.topicAliasRecv=new zv.default(r.properties.topicAliasMaximum)),this.on("connect",()=>{let{queue:i}=this,n=()=>{let o=i.shift();this.log("deliver :: entry %o",o);let s=null;if(!o){this._resubscribe();return}s=o.packet,this.log("deliver :: call _sendPacket for %o",s);let a=!0;s.messageId&&s.messageId!==0&&(this.messageIdProvider.register(s.messageId)||(a=!1)),a?this._sendPacket(s,u=>{o.cb&&o.cb(u),n();}):(this.log("messageId: %d has already used. The message is skipped and removed.",s.messageId),n());};this.log("connect :: sending queued packets"),n();}),this.on("close",()=>{this.log("close :: connected set to `false`"),this.connected=!1,this.log("close :: clearing connackTimer"),clearTimeout(this.connackTimer),this.log("close :: clearing ping timer"),this.pingTimer&&(this.pingTimer.clear(),this.pingTimer=null),this.topicAliasRecv&&this.topicAliasRecv.clear(),this.log("close :: calling _setupReconnect"),this._setupReconnect();}),this.options.manualConnect||(this.log("MqttClient :: setting up stream"),this.connect());}handleAuth(e,r){r();}handleMessage(e,r){r();}_nextId(){return this.messageIdProvider.allocate()}getLastMessageId(){return this.messageIdProvider.getLastAllocated()}connect(){var e;let r=new Gv.Writable,i=ja.default.parser(this.options),n=null,o=[];this.log("connect :: calling method to clear reconnect"),this._clearReconnect(),this.log("connect :: using streamBuilder provided to client to create stream"),this.stream=this.streamBuilder(this),i.on("packet",h=>{this.log("parser :: on packet push to packets array."),o.push(h);});let s=()=>{this.log("work :: getting next packet in queue");let h=o.shift();if(h)this.log("work :: packet pulled from queue"),(0, Yv.default)(this,h,a);else {this.log("work :: no packets in queue");let d=n;n=null,this.log("work :: done flag is %s",!!d),d&&d();}},a=()=>{if(o.length)(0, Wa.nextTick)(s);else {let h=n;n=null,h();}};r._write=(h,d,g)=>{n=g,this.log("writable stream :: parsing buffer"),i.parse(h),s();};let u=h=>{this.log("streamErrorHandler :: error",h.message),h.code?(this.log("streamErrorHandler :: emitting error"),this.emit("error",h)):this.noop(h);};this.log("connect :: pipe stream to writable stream"),this.stream.pipe(r),this.stream.on("error",u),this.stream.on("close",()=>{this.log("(%s)stream :: on close",this.options.clientId),this._flushVolatile(),this.log("stream: emit close to MqttClient"),this.emit("close");}),this.log("connect: sending packet `connect`");let c={cmd:"connect",protocolId:this.options.protocolId,protocolVersion:this.options.protocolVersion,clean:this.options.clean,clientId:this.options.clientId,keepalive:this.options.keepalive,username:this.options.username,password:this.options.password,properties:this.options.properties};if(this.options.will&&(c.will=Object.assign(Object.assign({},this.options.will),{payload:(e=this.options.will)===null||e===void 0?void 0:e.payload})),this.topicAliasRecv&&(c.properties||(c.properties={}),this.topicAliasRecv&&(c.properties.topicAliasMaximum=this.topicAliasRecv.max)),this._writePacket(c),i.on("error",this.emit.bind(this,"error")),this.options.properties){if(!this.options.properties.authenticationMethod&&this.options.properties.authenticationData)return this.end(()=>this.emit("error",new Error("Packet has no Authentication Method"))),this;if(this.options.properties.authenticationMethod&&this.options.authPacket&&typeof this.options.authPacket=="object"){let h=Object.assign({cmd:"auth",reasonCode:0},this.options.authPacket);this._writePacket(h);}}return this.stream.setMaxListeners(1e3),clearTimeout(this.connackTimer),this.connackTimer=setTimeout(()=>{this.log("!!connectTimeout hit!! Calling _cleanUp with force `true`"),this.emit("error",new Error("connack timeout")),this._cleanUp(!0);},this.options.connectTimeout),this}publish(e,r,i,n){this.log("publish :: message `%s` to topic `%s`",r,e);let{options:o}=this;typeof i=="function"&&(n=i,i=null),i=i||{},i=Object.assign(Object.assign({},{qos:0,retain:!1,dup:!1}),i);let{qos:a,retain:u,dup:c,properties:h,cbStorePut:d}=i;if(this._checkDisconnecting(n))return this;let g=()=>{let y=0;if((a===1||a===2)&&(y=this._nextId(),y===null))return this.log("No messageId left"),!1;let w={cmd:"publish",topic:e,payload:r,qos:a,retain:u,messageId:y,dup:c};switch(o.protocolVersion===5&&(w.properties=h),this.log("publish :: qos",a),a){case 1:case 2:this.outgoing[w.messageId]={volatile:!1,cb:n||this.noop},this.log("MqttClient:publish: packet cmd: %s",w.cmd),this._sendPacket(w,void 0,d);break;default:this.log("MqttClient:publish: packet cmd: %s",w.cmd),this._sendPacket(w,n,d);break}return !0};return (this._storeProcessing||this._storeProcessingQueue.length>0||!g())&&this._storeProcessingQueue.push({invoke:g,cbStorePut:i.cbStorePut,callback:n}),this}publishAsync(e,r,i){return new Promise((n,o)=>{this.publish(e,r,i,(s,a)=>{s?o(s):n(a);});})}subscribe(e,r,i){let n=this.options.protocolVersion;typeof r=="function"&&(i=r),i=i||this.noop;let o=!1,s=[];typeof e=="string"?(e=[e],s=e):Array.isArray(e)?s=e:typeof e=="object"&&(o=e.resubscribe,delete e.resubscribe,s=Object.keys(e));let a=Dp.validateTopics(s);if(a!==null)return Fa(i,new Error(`Invalid topic ${a}`)),this;if(this._checkDisconnecting(i))return this.log("subscribe: discconecting true"),this;let u={qos:0};n===5&&(u.nl=!1,u.rap=!1,u.rh=0),r=Object.assign(Object.assign({},u),r);let c=r.properties,h=[],d=(y,w)=>{if(w=w||r,!Object.prototype.hasOwnProperty.call(this._resubscribeTopics,y)||this._resubscribeTopics[y].qos{this.log("subscribe: array topic %s",y),d(y);}):Object.keys(e).forEach(y=>{this.log("subscribe: object topic %s, %o",y,e[y]),d(y,e[y]);}),!h.length)return i(null,[]),this;let g=()=>{let y=this._nextId();if(y===null)return this.log("No messageId left"),!1;let w={cmd:"subscribe",subscriptions:h,messageId:y};if(c&&(w.properties=c),this.options.resubscribe){this.log("subscribe :: resubscribe true");let E=[];h.forEach(S=>{if(this.options.reconnectPeriod>0){let I={qos:S.qos};n===5&&(I.nl=S.nl||!1,I.rap=S.rap||!1,I.rh=S.rh||0,I.properties=S.properties),this._resubscribeTopics[S.topic]=I,E.push(S.topic);}}),this.messageIdToTopic[w.messageId]=E;}return this.outgoing[w.messageId]={volatile:!0,cb(E,S){if(!E){let{granted:I}=S;for(let C=0;C0||!g())&&this._storeProcessingQueue.push({invoke:g,callback:i}),this}subscribeAsync(e,r){return new Promise((i,n)=>{this.subscribe(e,r,(o,s)=>{o?n(o):i(s);});})}unsubscribe(e,r,i){typeof e=="string"&&(e=[e]),typeof r=="function"&&(i=r),i=i||this.noop;let n=Dp.validateTopics(e);if(n!==null)return Fa(i,new Error(`Invalid topic ${n}`)),this;if(this._checkDisconnecting(i))return this;let o=()=>{let s=this._nextId();if(s===null)return this.log("No messageId left"),!1;let a={cmd:"unsubscribe",messageId:s,unsubscriptions:[]};return typeof e=="string"?a.unsubscriptions=[e]:Array.isArray(e)&&(a.unsubscriptions=e),this.options.resubscribe&&a.unsubscriptions.forEach(u=>{delete this._resubscribeTopics[u];}),typeof r=="object"&&r.properties&&(a.properties=r.properties),this.outgoing[a.messageId]={volatile:!0,cb:i},this.log("unsubscribe: call _sendPacket"),this._sendPacket(a),!0};return (this._storeProcessing||this._storeProcessingQueue.length>0||!o())&&this._storeProcessingQueue.push({invoke:o,callback:i}),this}unsubscribeAsync(e,r){return new Promise((i,n)=>{this.unsubscribe(e,r,(o,s)=>{o?n(o):i(s);});})}end(e,r,i){this.log("end :: (%s)",this.options.clientId),(e==null||typeof e!="boolean")&&(i=i||r,r=e,e=!1),typeof r!="object"&&(i=i||r,r=null),this.log("end :: cb? %s",!!i),(!i||typeof i!="function")&&(i=this.noop);let n=()=>{this.log("end :: closeStores: closing incoming and outgoing stores"),this.disconnected=!0,this.incomingStore.close(s=>{this.outgoingStore.close(a=>{if(this.log("end :: closeStores: emitting end"),this.emit("end"),i){let u=s||a;this.log("end :: closeStores: invoking callback with args"),i(u);}});}),this._deferredReconnect&&this._deferredReconnect();},o=()=>{this.log("end :: (%s) :: finish :: calling _cleanUp with force %s",this.options.clientId,e),this._cleanUp(e,()=>{this.log("end :: finish :: calling process.nextTick on closeStores"),(0, Wa.nextTick)(n);},r);};return this.disconnecting?(i(),this):(this._clearReconnect(),this.disconnecting=!0,!e&&Object.keys(this.outgoing).length>0?(this.log("end :: (%s) :: calling finish in 10ms once outgoing is empty",this.options.clientId),this.once("outgoingEmpty",setTimeout.bind(null,o,10))):(this.log("end :: (%s) :: immediately calling finish",this.options.clientId),o()),this)}endAsync(e,r){return new Promise((i,n)=>{this.end(e,r,o=>{o?n(o):i();});})}removeOutgoingMessage(e){if(this.outgoing[e]){let{cb:r}=this.outgoing[e];this._removeOutgoingAndStoreMessage(e,()=>{r(new Error("Message removed"));});}return this}reconnect(e){this.log("client reconnect");let r=()=>{e?(this.options.incomingStore=e.incomingStore,this.options.outgoingStore=e.outgoingStore):(this.options.incomingStore=null,this.options.outgoingStore=null),this.incomingStore=this.options.incomingStore||new rs.default,this.outgoingStore=this.options.outgoingStore||new rs.default,this.disconnecting=!1,this.disconnected=!1,this._deferredReconnect=null,this._reconnect();};return this.disconnecting&&!this.disconnected?this._deferredReconnect=r:r(),this}_flushVolatile(){this.outgoing&&(this.log("_flushVolatile :: deleting volatile messages from the queue and setting their callbacks as error function"),Object.keys(this.outgoing).forEach(e=>{this.outgoing[e].volatile&&typeof this.outgoing[e].cb=="function"&&(this.outgoing[e].cb(new Error("Connection closed")),delete this.outgoing[e]);}));}_flush(){this.outgoing&&(this.log("_flush: queue exists? %b",!!this.outgoing),Object.keys(this.outgoing).forEach(e=>{typeof this.outgoing[e].cb=="function"&&(this.outgoing[e].cb(new Error("Connection closed")),delete this.outgoing[e]);}));}_removeTopicAliasAndRecoverTopicName(e){let r;e.properties&&(r=e.properties.topicAlias);let i=e.topic.toString();if(this.log("_removeTopicAliasAndRecoverTopicName :: alias %d, topic %o",r,i),i.length===0){if(typeof r>"u")return new Error("Unregistered Topic Alias");if(i=this.topicAliasSend.getTopicByAlias(r),typeof i>"u")return new Error("Unregistered Topic Alias");e.topic=i;}r&&delete e.properties.topicAlias;}_checkDisconnecting(e){return this.disconnecting&&(e&&e!==this.noop?e(new Error("client disconnecting")):this.emit("error",new Error("client disconnecting"))),this.disconnecting}_reconnect(){this.log("_reconnect: emitting reconnect to client"),this.emit("reconnect"),this.connected?(this.end(()=>{this.connect();}),this.log("client already connected. disconnecting first.")):(this.log("_reconnect: calling connect"),this.connect());}_setupReconnect(){!this.disconnecting&&!this.reconnectTimer&&this.options.reconnectPeriod>0?(this.reconnecting||(this.log("_setupReconnect :: emit `offline` state"),this.emit("offline"),this.log("_setupReconnect :: set `reconnecting` to `true`"),this.reconnecting=!0),this.log("_setupReconnect :: setting reconnectTimer for %d ms",this.options.reconnectPeriod),this.reconnectTimer=setInterval(()=>{this.log("reconnectTimer :: reconnect triggered!"),this._reconnect();},this.options.reconnectPeriod)):this.log("_setupReconnect :: doing nothing...");}_clearReconnect(){this.log("_clearReconnect : clearing reconnect timer"),this.reconnectTimer&&(clearInterval(this.reconnectTimer),this.reconnectTimer=null);}_cleanUp(e,r,i={}){if(r&&(this.log("_cleanUp :: done callback provided for on stream close"),this.stream.on("close",r)),this.log("_cleanUp :: forced? %s",e),e)this.options.reconnectPeriod===0&&this.options.clean&&this._flush(),this.log("_cleanUp :: (%s) :: destroying stream",this.options.clientId),this.stream.destroy();else {let n=Object.assign({cmd:"disconnect"},i);this.log("_cleanUp :: (%s) :: call _sendPacket with disconnect packet",this.options.clientId),this._sendPacket(n,()=>{this.log("_cleanUp :: (%s) :: destroying stream",this.options.clientId),Fa(()=>{this.stream.end(()=>{this.log("_cleanUp :: (%s) :: stream destroyed",this.options.clientId);});});});}!this.disconnecting&&!this.reconnecting&&(this.log("_cleanUp :: client not disconnecting/reconnecting. Clearing and resetting reconnect."),this._clearReconnect(),this._setupReconnect()),this.pingTimer&&(this.log("_cleanUp :: clearing pingTimer"),this.pingTimer.clear(),this.pingTimer=null),r&&!this.connected&&(this.log("_cleanUp :: (%s) :: removing stream `done` callback `close` listener",this.options.clientId),this.stream.removeListener("close",r),r());}_storeAndSend(e,r,i){this.log("storeAndSend :: store packet with cmd %s to outgoingStore",e.cmd);let n=e,o;if(n.cmd==="publish"&&(n=(0, qp.default)(e),o=this._removeTopicAliasAndRecoverTopicName(n),o))return r&&r(o);this.outgoingStore.put(n,s=>{if(s)return r&&r(s);i(),this._writePacket(e,r);});}_applyTopicAlias(e){if(this.options.protocolVersion===5&&e.cmd==="publish"){let r;e.properties&&(r=e.properties.topicAlias);let i=e.topic.toString();if(this.topicAliasSend)if(r){if(i.length!==0&&(this.log("applyTopicAlias :: register topic: %s - alias: %d",i,r),!this.topicAliasSend.put(i,r)))return this.log("applyTopicAlias :: error out of range. topic: %s - alias: %d",i,r),new Error("Sending Topic Alias out of range")}else i.length!==0&&(this.options.autoAssignTopicAlias?(r=this.topicAliasSend.getAliasByTopic(i),r?(e.topic="",e.properties=Object.assign(Object.assign({},e.properties),{topicAlias:r}),this.log("applyTopicAlias :: auto assign(use) topic: %s - alias: %d",i,r)):(r=this.topicAliasSend.getLruAlias(),this.topicAliasSend.put(i,r),e.properties=Object.assign(Object.assign({},e.properties),{topicAlias:r}),this.log("applyTopicAlias :: auto assign topic: %s - alias: %d",i,r))):this.options.autoUseTopicAlias&&(r=this.topicAliasSend.getAliasByTopic(i),r&&(e.topic="",e.properties=Object.assign(Object.assign({},e.properties),{topicAlias:r}),this.log("applyTopicAlias :: auto use topic: %s - alias: %d",i,r))));else if(r)return this.log("applyTopicAlias :: error out of range. topic: %s - alias: %d",i,r),new Error("Sending Topic Alias out of range")}}_noop(e){this.log("noop ::",e);}_writePacket(e,r){this.log("_writePacket :: packet: %O",e),this.log("_writePacket :: emitting `packetsend`"),this.emit("packetsend",e),this._shiftPingInterval(),this.log("_writePacket :: writing to stream");let i=ja.default.writeToStream(e,this.stream,this.options);this.log("_writePacket :: writeToStream result %s",i),!i&&r&&r!==this.noop?(this.log("_writePacket :: handle events on `drain` once through callback."),this.stream.once("drain",r)):r&&(this.log("_writePacket :: invoking cb"),r());}_sendPacket(e,r,i,n){this.log("_sendPacket :: (%s) :: start",this.options.clientId),i=i||this.noop,r=r||this.noop;let o=this._applyTopicAlias(e);if(o){r(o);return}if(!this.connected){if(e.cmd==="auth"){this._writePacket(e,r);return}this.log("_sendPacket :: client not connected. Storing packet offline."),this._storePacket(e,r,i);return}if(n){this._writePacket(e,r);return}switch(e.cmd){case"publish":break;case"pubrel":this._storeAndSend(e,r,i);return;default:this._writePacket(e,r);return}switch(e.qos){case 2:case 1:this._storeAndSend(e,r,i);break;case 0:default:this._writePacket(e,r);break}this.log("_sendPacket :: (%s) :: end",this.options.clientId);}_storePacket(e,r,i){this.log("_storePacket :: packet: %o",e),this.log("_storePacket :: cb? %s",!!r),i=i||this.noop;let n=e;if(n.cmd==="publish"){n=(0, qp.default)(e);let s=this._removeTopicAliasAndRecoverTopicName(n);if(s)return r&&r(s)}let o=n.qos||0;o===0&&this.queueQoSZero||n.cmd!=="publish"?this.queue.push({packet:n,cb:r}):o>0?(r=this.outgoing[n.messageId]?this.outgoing[n.messageId].cb:null,this.outgoingStore.put(n,s=>{if(s)return r&&r(s);i();})):r&&r(new Error("No connection to broker"));}_setupPingTimer(){this.log("_setupPingTimer :: keepalive %d (seconds)",this.options.keepalive),!this.pingTimer&&this.options.keepalive&&(this.pingResp=!0,this.pingTimer=new Xv.default(this.options.keepalive,()=>{this._checkPing();},this.options.timerVariant));}_shiftPingInterval(){this.pingTimer&&this.options.keepalive&&this.options.reschedulePings&&this.pingTimer.reschedule();}_checkPing(){this.log("_checkPing :: checking ping..."),this.pingResp?(this.log("_checkPing :: ping response received. Clearing flag and sending `pingreq`"),this.pingResp=!1,this._sendPacket({cmd:"pingreq"})):(this.emit("error",new Error("Keepalive timeout")),this.log("_checkPing :: calling _cleanUp with force true"),this._cleanUp(!0));}_resubscribe(){this.log("_resubscribe");let e=Object.keys(this._resubscribeTopics);if(!this._firstConnection&&(this.options.clean||this.options.protocolVersion>=4&&!this.connackPacket.sessionPresent)&&e.length>0)if(this.options.resubscribe)if(this.options.protocolVersion===5){this.log("_resubscribe: protocolVersion 5");for(let r=0;r{let i=this.outgoingStore.createStream(),n=()=>{i.destroy(),i=null,this._flushStoreProcessingQueue(),o();},o=()=>{this._storeProcessing=!1,this._packetIdsDuringStoreProcessing={};};this.once("close",n),i.on("error",a=>{o(),this._flushStoreProcessingQueue(),this.removeListener("close",n),this.emit("error",a);});let s=()=>{if(!i)return;let a=i.read(1),u;if(!a){i.once("readable",s);return}if(this._storeProcessing=!0,this._packetIdsDuringStoreProcessing[a.messageId]){s();return}!this.disconnecting&&!this.reconnectTimer?(u=this.outgoing[a.messageId]?this.outgoing[a.messageId].cb:null,this.outgoing[a.messageId]={volatile:!1,cb(c,h){u&&u(c,h),s();}},this._packetIdsDuringStoreProcessing[a.messageId]=!0,this.messageIdProvider.register(a.messageId)?this._sendPacket(a,void 0,void 0,!0):this.log("messageId: %d has already used.",a.messageId)):i.destroy&&i.destroy();};i.on("end",()=>{let a=!0;for(let u in this._packetIdsDuringStoreProcessing)if(!this._packetIdsDuringStoreProcessing[u]){a=!1;break}this.removeListener("close",n),a?(o(),this._invokeAllStoreProcessingQueue(),this.emit("connect",e)):r();}),s();};r();}_invokeStoreProcessingQueue(){if(!this._storeProcessing&&this._storeProcessingQueue.length>0){let e=this._storeProcessingQueue[0];if(e&&e.invoke())return this._storeProcessingQueue.shift(),!0}return !1}_invokeAllStoreProcessingQueue(){for(;this._invokeStoreProcessingQueue(););}_flushStoreProcessingQueue(){for(let e of this._storeProcessingQueue)e.cbStorePut&&e.cbStorePut(new Error("Connection closed")),e.callback&&e.callback(new Error("Connection closed"));this._storeProcessingQueue.splice(0);}_removeOutgoingAndStoreMessage(e,r){delete this.outgoing[e],this.outgoingStore.del({messageId:e},(i,n)=>{r(i,n),this.messageIdProvider.deallocate(e),this._invokeStoreProcessingQueue();});}};is.VERSION="5.5.2";Qe.default=is;});var $p=M(Ha=>{v();m();_();Object.defineProperty(Ha,"__esModule",{value:!0});var Zv=xa(),$a=class{constructor(){this.numberAllocator=new Zv.NumberAllocator(1,65535);}allocate(){return this.lastId=this.numberAllocator.alloc(),this.lastId}getLastAllocated(){return this.lastId}register(e){return this.numberAllocator.use(e)}deallocate(e){this.numberAllocator.free(e);}clear(){this.numberAllocator.clear();}};Ha.default=$a;});function Ir(t){throw new RangeError(iE[t])}function Hp(t,e){let r=t.split("@"),i="";r.length>1&&(i=r[0]+"@",t=r[1]);let n=function(o,s){let a=[],u=o.length;for(;u--;)a[u]=s(o[u]);return a}((t=t.replace(rE,".")).split("."),e).join(".");return i+n}function Gp(t){let e=[],r=0,i=t.length;for(;r=55296&&n<=56319&&r{v();m();_();eE=/^xn--/,tE=/[^\0-\x7E]/,rE=/[\x2E\u3002\uFF0E\uFF61]/g,iE={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},ht=Math.floor,Va=String.fromCharCode;Vp=function(t,e){return t+22+75*(t<26)-((e!=0)<<5)},Qp=function(t,e,r){let i=0;for(t=r?ht(t/700):t>>1,t+=ht(t/e);t>455;i+=36)t=ht(t/35);return ht(i+36*t/(t+38))},zp=function(t){let e=[],r=t.length,i=0,n=128,o=72,s=t.lastIndexOf("-");s<0&&(s=0);for(let u=0;u=128&&Ir("not-basic"),e.push(t.charCodeAt(u));for(let u=s>0?s+1:0;u=r&&Ir("invalid-input");let y=(a=t.charCodeAt(u++))-48<10?a-22:a-65<26?a-65:a-97<26?a-97:36;(y>=36||y>ht((2147483647-i)/d))&&Ir("overflow"),i+=y*d;let w=g<=o?1:g>=o+26?26:g-o;if(yht(2147483647/E)&&Ir("overflow"),d*=E;}let h=e.length+1;o=Qp(i-c,h,c==0),ht(i/h)>2147483647-n&&Ir("overflow"),n+=ht(i/h),i%=h,e.splice(i++,0,n);}var a;return String.fromCodePoint(...e)},Kp=function(t){let e=[],r=(t=Gp(t)).length,i=128,n=0,o=72;for(let u of t)u<128&&e.push(Va(u));let s=e.length,a=s;for(s&&e.push("-");a=i&&hht((2147483647-n)/c)&&Ir("overflow"),n+=(u-i)*c,i=u;for(let h of t)if(h2147483647&&Ir("overflow"),h==i){let d=n;for(let g=36;;g+=36){let y=g<=o?1:g>=o+26?26:g-o;if(dString.fromCodePoint(...t)},decode:zp,encode:Kp,toASCII:function(t){return Hp(t,function(e){return tE.test(e)?"xn--"+Kp(e):e})},toUnicode:function(t){return Hp(t,function(e){return eE.test(e)?zp(e.slice(4).toLowerCase()):e})}};zt.decode;zt.encode;zt.toASCII;zt.toUnicode;zt.ucs2;zt.version;});function nE(t,e){return Object.prototype.hasOwnProperty.call(t,e)}var sE,ki,oE,dt,Jp=we(()=>{v();m();_();sE=function(t,e,r,i){e=e||"&",r=r||"=";var n={};if(typeof t!="string"||t.length===0)return n;var o=/\+/g;t=t.split(e);var s=1e3;i&&typeof i.maxKeys=="number"&&(s=i.maxKeys);var a=t.length;s>0&&a>s&&(a=s);for(var u=0;u=0?(c=y.substr(0,w),h=y.substr(w+1)):(c=y,h=""),d=decodeURIComponent(c),g=decodeURIComponent(h),nE(n,d)?Array.isArray(n[d])?n[d].push(g):n[d]=[n[d],g]:n[d]=g;}return n},ki=function(t){switch(typeof t){case"string":return t;case"boolean":return t?"true":"false";case"number":return isFinite(t)?t:"";default:return ""}},oE=function(t,e,r,i){return e=e||"&",r=r||"=",t===null&&(t=void 0),typeof t=="object"?Object.keys(t).map(function(n){var o=encodeURIComponent(ki(n))+r;return Array.isArray(t[n])?t[n].map(function(s){return o+encodeURIComponent(ki(s))}).join(e):o+encodeURIComponent(ki(t[n]))}).join(e):i?encodeURIComponent(ki(i))+r+encodeURIComponent(ki(t)):""},dt={};dt.decode=dt.parse=sE,dt.encode=dt.stringify=oE;dt.decode;dt.encode;dt.parse;dt.stringify;});function za(){throw new Error("setTimeout has not been defined")}function Ka(){throw new Error("clearTimeout has not been defined")}function eg(t){if(Bt===setTimeout)return setTimeout(t,0);if((Bt===za||!Bt)&&setTimeout)return Bt=setTimeout,setTimeout(t,0);try{return Bt(t,0)}catch{try{return Bt.call(null,t,0)}catch{return Bt.call(this||ii,t,0)}}}function aE(){ri&&Tr&&(ri=!1,Tr.length?Ot=Tr.concat(Ot):ss=-1,Ot.length&&tg());}function tg(){if(!ri){var t=eg(aE);ri=!0;for(var e=Ot.length;e;){for(Tr=Ot,Ot=[];++ss{v();m();_();ii=typeof globalThis<"u"?globalThis:typeof self<"u"?self:__webpack_require__.g,fe=Zp={};(function(){try{Bt=typeof setTimeout=="function"?setTimeout:za;}catch{Bt=za;}try{Pt=typeof clearTimeout=="function"?clearTimeout:Ka;}catch{Pt=Ka;}})();Ot=[],ri=!1,ss=-1;fe.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r1)for(var I=1;I{v();m();_();Ga={},ig=!1,ni=typeof globalThis<"u"?globalThis:typeof self<"u"?self:__webpack_require__.g;re=lE();re.platform="browser";re.addListener;re.argv;re.binding;re.browser;re.chdir;re.cwd;re.emit;re.env;re.listeners;re.nextTick;re.off;re.on;re.once;re.prependListener;re.prependOnceListener;re.removeAllListeners;re.removeListener;re.title;re.umask;re.version;re.versions;});function uE(){if(ng)return Ya;ng=!0;var t=re;function e(o){if(typeof o!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(o))}function r(o,s){for(var a="",u=0,c=-1,h=0,d,g=0;g<=o.length;++g){if(g2){var y=a.lastIndexOf("/");if(y!==a.length-1){y===-1?(a="",u=0):(a=a.slice(0,y),u=a.length-1-a.lastIndexOf("/")),c=g,h=0;continue}}else if(a.length===2||a.length===1){a="",u=0,c=g,h=0;continue}}s&&(a.length>0?a+="/..":a="..",u=2);}else a.length>0?a+="/"+o.slice(c+1,g):a=o.slice(c+1,g),u=g-c-1;c=g,h=0;}else d===46&&h!==-1?++h:h=-1;}return a}function i(o,s){var a=s.dir||s.root,u=s.base||(s.name||"")+(s.ext||"");return a?a===s.root?a+u:a+o+u:u}var n={resolve:function(){for(var s="",a=!1,u,c=arguments.length-1;c>=-1&&!a;c--){var h;c>=0?h=arguments[c]:(u===void 0&&(u=t.cwd()),h=u),e(h),h.length!==0&&(s=h+"/"+s,a=h.charCodeAt(0)===47);}return s=r(s,!a),a?s.length>0?"/"+s:"/":s.length>0?s:"."},normalize:function(s){if(e(s),s.length===0)return ".";var a=s.charCodeAt(0)===47,u=s.charCodeAt(s.length-1)===47;return s=r(s,!a),s.length===0&&!a&&(s="."),s.length>0&&u&&(s+="/"),a?"/"+s:s},isAbsolute:function(s){return e(s),s.length>0&&s.charCodeAt(0)===47},join:function(){if(arguments.length===0)return ".";for(var s,a=0;a0&&(s===void 0?s=u:s+="/"+u);}return s===void 0?".":n.normalize(s)},relative:function(s,a){if(e(s),e(a),s===a||(s=n.resolve(s),a=n.resolve(a),s===a))return "";for(var u=1;uw){if(a.charCodeAt(d+S)===47)return a.slice(d+S+1);if(S===0)return a.slice(d+S)}else h>w&&(s.charCodeAt(u+S)===47?E=S:S===0&&(E=0));break}var I=s.charCodeAt(u+S),C=a.charCodeAt(d+S);if(I!==C)break;I===47&&(E=S);}var R="";for(S=u+E+1;S<=c;++S)(S===c||s.charCodeAt(S)===47)&&(R.length===0?R+="..":R+="/..");return R.length>0?R+a.slice(d+E):(d+=E,a.charCodeAt(d)===47&&++d,a.slice(d))},_makeLong:function(s){return s},dirname:function(s){if(e(s),s.length===0)return ".";for(var a=s.charCodeAt(0),u=a===47,c=-1,h=!0,d=s.length-1;d>=1;--d)if(a=s.charCodeAt(d),a===47){if(!h){c=d;break}}else h=!1;return c===-1?u?"/":".":u&&c===1?"//":s.slice(0,c)},basename:function(s,a){if(a!==void 0&&typeof a!="string")throw new TypeError('"ext" argument must be a string');e(s);var u=0,c=-1,h=!0,d;if(a!==void 0&&a.length>0&&a.length<=s.length){if(a.length===s.length&&a===s)return "";var g=a.length-1,y=-1;for(d=s.length-1;d>=0;--d){var w=s.charCodeAt(d);if(w===47){if(!h){u=d+1;break}}else y===-1&&(h=!1,y=d+1),g>=0&&(w===a.charCodeAt(g)?--g===-1&&(c=d):(g=-1,c=y));}return u===c?c=y:c===-1&&(c=s.length),s.slice(u,c)}else {for(d=s.length-1;d>=0;--d)if(s.charCodeAt(d)===47){if(!h){u=d+1;break}}else c===-1&&(h=!1,c=d+1);return c===-1?"":s.slice(u,c)}},extname:function(s){e(s);for(var a=-1,u=0,c=-1,h=!0,d=0,g=s.length-1;g>=0;--g){var y=s.charCodeAt(g);if(y===47){if(!h){u=g+1;break}continue}c===-1&&(h=!1,c=g+1),y===46?a===-1?a=g:d!==1&&(d=1):a!==-1&&(d=-1);}return a===-1||c===-1||d===0||d===1&&a===c-1&&a===u+1?"":s.slice(a,c)},format:function(s){if(s===null||typeof s!="object")throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof s);return i("/",s)},parse:function(s){e(s);var a={root:"",dir:"",base:"",ext:"",name:""};if(s.length===0)return a;var u=s.charCodeAt(0),c=u===47,h;c?(a.root="/",h=1):h=0;for(var d=-1,g=0,y=-1,w=!0,E=s.length-1,S=0;E>=h;--E){if(u=s.charCodeAt(E),u===47){if(!w){g=E+1;break}continue}y===-1&&(w=!1,y=E+1),u===46?d===-1?d=E:S!==1&&(S=1):d!==-1&&(S=-1);}return d===-1||y===-1||S===0||S===1&&d===y-1&&d===g+1?y!==-1&&(g===0&&c?a.base=a.name=s.slice(1,y):a.base=a.name=s.slice(g,y)):(g===0&&c?(a.name=s.slice(1,d),a.base=s.slice(1,y)):(a.name=s.slice(g,d),a.base=s.slice(g,y)),a.ext=s.slice(d,y)),g>0?a.dir=s.slice(0,g-1):c&&(a.dir="/"),a},sep:"/",delimiter:":",win32:null,posix:null};return n.posix=n,Ya=n,Ya}var Ya,ng,Ja,sg=we(()=>{v();m();_();Qa();Ya={},ng=!1;Ja=uE();});var dg={};Qt(dg,{URL:()=>DE,Url:()=>ME,default:()=>Z,fileURLToPath:()=>cg,format:()=>LE,parse:()=>qE,pathToFileURL:()=>hg,resolve:()=>UE,resolveObject:()=>NE});function Fe(){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;}function xi(t,e,r){if(t&&pt.isObject(t)&&t instanceof Fe)return t;var i=new Fe;return i.parse(t,e,r),i}function bE(){if(ug)return el;ug=!0;var t=ne;function e(o){if(typeof o!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(o))}function r(o,s){for(var a="",u=0,c=-1,h=0,d,g=0;g<=o.length;++g){if(g2){var y=a.lastIndexOf("/");if(y!==a.length-1){y===-1?(a="",u=0):(a=a.slice(0,y),u=a.length-1-a.lastIndexOf("/")),c=g,h=0;continue}}else if(a.length===2||a.length===1){a="",u=0,c=g,h=0;continue}}s&&(a.length>0?a+="/..":a="..",u=2);}else a.length>0?a+="/"+o.slice(c+1,g):a=o.slice(c+1,g),u=g-c-1;c=g,h=0;}else d===46&&h!==-1?++h:h=-1;}return a}function i(o,s){var a=s.dir||s.root,u=s.base||(s.name||"")+(s.ext||"");return a?a===s.root?a+u:a+o+u:u}var n={resolve:function(){for(var s="",a=!1,u,c=arguments.length-1;c>=-1&&!a;c--){var h;c>=0?h=arguments[c]:(u===void 0&&(u=t.cwd()),h=u),e(h),h.length!==0&&(s=h+"/"+s,a=h.charCodeAt(0)===47);}return s=r(s,!a),a?s.length>0?"/"+s:"/":s.length>0?s:"."},normalize:function(s){if(e(s),s.length===0)return ".";var a=s.charCodeAt(0)===47,u=s.charCodeAt(s.length-1)===47;return s=r(s,!a),s.length===0&&!a&&(s="."),s.length>0&&u&&(s+="/"),a?"/"+s:s},isAbsolute:function(s){return e(s),s.length>0&&s.charCodeAt(0)===47},join:function(){if(arguments.length===0)return ".";for(var s,a=0;a0&&(s===void 0?s=u:s+="/"+u);}return s===void 0?".":n.normalize(s)},relative:function(s,a){if(e(s),e(a),s===a||(s=n.resolve(s),a=n.resolve(a),s===a))return "";for(var u=1;uw){if(a.charCodeAt(d+S)===47)return a.slice(d+S+1);if(S===0)return a.slice(d+S)}else h>w&&(s.charCodeAt(u+S)===47?E=S:S===0&&(E=0));break}var I=s.charCodeAt(u+S),C=a.charCodeAt(d+S);if(I!==C)break;I===47&&(E=S);}var R="";for(S=u+E+1;S<=c;++S)(S===c||s.charCodeAt(S)===47)&&(R.length===0?R+="..":R+="/..");return R.length>0?R+a.slice(d+E):(d+=E,a.charCodeAt(d)===47&&++d,a.slice(d))},_makeLong:function(s){return s},dirname:function(s){if(e(s),s.length===0)return ".";for(var a=s.charCodeAt(0),u=a===47,c=-1,h=!0,d=s.length-1;d>=1;--d)if(a=s.charCodeAt(d),a===47){if(!h){c=d;break}}else h=!1;return c===-1?u?"/":".":u&&c===1?"//":s.slice(0,c)},basename:function(s,a){if(a!==void 0&&typeof a!="string")throw new TypeError('"ext" argument must be a string');e(s);var u=0,c=-1,h=!0,d;if(a!==void 0&&a.length>0&&a.length<=s.length){if(a.length===s.length&&a===s)return "";var g=a.length-1,y=-1;for(d=s.length-1;d>=0;--d){var w=s.charCodeAt(d);if(w===47){if(!h){u=d+1;break}}else y===-1&&(h=!1,y=d+1),g>=0&&(w===a.charCodeAt(g)?--g===-1&&(c=d):(g=-1,c=y));}return u===c?c=y:c===-1&&(c=s.length),s.slice(u,c)}else {for(d=s.length-1;d>=0;--d)if(s.charCodeAt(d)===47){if(!h){u=d+1;break}}else c===-1&&(h=!1,c=d+1);return c===-1?"":s.slice(u,c)}},extname:function(s){e(s);for(var a=-1,u=0,c=-1,h=!0,d=0,g=s.length-1;g>=0;--g){var y=s.charCodeAt(g);if(y===47){if(!h){u=g+1;break}continue}c===-1&&(h=!1,c=g+1),y===46?a===-1?a=g:d!==1&&(d=1):a!==-1&&(d=-1);}return a===-1||c===-1||d===0||d===1&&a===c-1&&a===u+1?"":s.slice(a,c)},format:function(s){if(s===null||typeof s!="object")throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof s);return i("/",s)},parse:function(s){e(s);var a={root:"",dir:"",base:"",ext:"",name:""};if(s.length===0)return a;var u=s.charCodeAt(0),c=u===47,h;c?(a.root="/",h=1):h=0;for(var d=-1,g=0,y=-1,w=!0,E=s.length-1,S=0;E>=h;--E){if(u=s.charCodeAt(E),u===47){if(!w){g=E+1;break}continue}y===-1&&(w=!1,y=E+1),u===46?d===-1?d=E:S!==1&&(S=1):d!==-1&&(S=-1);}return d===-1||y===-1||S===0||S===1&&d===y-1&&d===g+1?y!==-1&&(g===0&&c?a.base=a.name=s.slice(1,y):a.base=a.name=s.slice(g,y)):(g===0&&c?(a.name=s.slice(1,d),a.base=s.slice(1,y)):(a.name=s.slice(g,d),a.base=s.slice(g,y)),a.ext=s.slice(d,y)),g>0?a.dir=s.slice(0,g-1):c&&(a.dir="/"),a},sep:"/",delimiter:":",win32:null,posix:null};return n.posix=n,el=n,el}function BE(t){if(typeof t=="string")t=new URL(t);else if(!(t instanceof URL))throw new Deno.errors.InvalidData("invalid argument path , must be a string or URL");if(t.protocol!=="file:")throw new Deno.errors.InvalidData("invalid url scheme");return rl?PE(t):OE(t)}function PE(t){let e=t.hostname,r=t.pathname;for(let i=0;iEE||n!==":")throw new Deno.errors.InvalidData("file url path must be absolute");return r.slice(1)}}function OE(t){if(t.hostname!=="")throw new Deno.errors.InvalidData("invalid file url hostname");let e=t.pathname;for(let r=0;r$E||n!==":")throw new Deno.errors.InvalidData("file url path must be absolute");return r.slice(1)}}function JE(t){if(t.hostname!=="")throw new Deno.errors.InvalidData("invalid file url hostname");let e=t.pathname;for(let r=0;r{v();m();_();Yp();Jp();rg();sg();Qa();Z={},fE=zt,pt={isString:function(t){return typeof t=="string"},isObject:function(t){return typeof t=="object"&&t!==null},isNull:function(t){return t===null},isNullOrUndefined:function(t){return t==null}};Z.parse=xi,Z.resolve=function(t,e){return xi(t,!1,!0).resolve(e)},Z.resolveObject=function(t,e){return t?xi(t,!1,!0).resolveObject(e):e},Z.format=function(t){return pt.isString(t)&&(t=xi(t)),t instanceof Fe?t.format():Fe.prototype.format.call(t)},Z.Url=Fe;cE=/^([a-z0-9.+-]+:)/i,hE=/:[0-9]*$/,dE=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,pE=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r",` +`," "]),tl=["'"].concat(pE),og=["%","/","?",";","#"].concat(tl),ag=["/","?","#"],lg=/^[+a-z0-9A-Z_-]{0,63}$/,gE=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,yE={javascript:!0,"javascript:":!0},Xa={javascript:!0,"javascript:":!0},si={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},Za=dt;Fe.prototype.parse=function(t,e,r){if(!pt.isString(t))throw new TypeError("Parameter 'url' must be a string, not "+typeof t);var i=t.indexOf("?"),n=i!==-1&&i127?U+="x":U+=R[N];if(!U.match(lg)){var K=I.slice(0,w),z=I.slice(w+1),Q=R.match(gE);Q&&(K.push(Q[1]),z.unshift(Q[2])),z.length&&(s="/"+z.join(".")+s),this.hostname=K.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),S||(this.hostname=fE.toASCII(this.hostname));var de=this.port?":"+this.port:"",Gt=this.hostname||"";this.host=Gt+de,this.href+=this.host,S&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),s[0]!=="/"&&(s="/"+s));}if(!yE[c])for(w=0,C=tl.length;w0)&&r.host.split("@"))&&(r.auth=Q.shift(),r.host=r.hostname=Q.shift())),r.search=t.search,r.query=t.query,pt.isNull(r.pathname)&&pt.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.href=r.format(),r;if(!R.length)return r.pathname=null,r.search?r.path="/"+r.search:r.path=null,r.href=r.format(),r;for(var N=R.slice(-1)[0],W=(r.host||t.host||R.length>1)&&(N==="."||N==="..")||N==="",K=0,z=R.length;z>=0;z--)(N=R[z])==="."?R.splice(z,1):N===".."?(R.splice(z,1),K++):K&&(R.splice(z,1),K--);if(!I&&!C)for(;K--;K)R.unshift("..");!I||R[0]===""||R[0]&&R[0].charAt(0)==="/"||R.unshift(""),W&&R.join("/").substr(-1)!=="/"&&R.push("");var Q,de=R[0]===""||R[0]&&R[0].charAt(0)==="/";return U&&(r.hostname=r.host=de?"":R.length?R.shift():"",(Q=!!(r.host&&r.host.indexOf("@")>0)&&r.host.split("@"))&&(r.auth=Q.shift(),r.host=r.hostname=Q.shift())),(I=I||r.host&&R.length)&&!de&&R.unshift(""),R.length?r.pathname=R.join("/"):(r.pathname=null,r.path=null),pt.isNull(r.pathname)&&pt.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.auth=t.auth||r.auth,r.slashes=r.slashes||t.slashes,r.href=r.format(),r},Fe.prototype.parseHost=function(){var t=this.host,e=hE.exec(t);e&&((e=e[0])!==":"&&(this.port=e.substr(1)),t=t.substr(0,t.length-e.length)),t&&(this.hostname=t);};Z.Url;Z.format;Z.resolve;Z.resolveObject;el={},ug=!1;fg=bE(),wE=typeof Deno<"u"?Deno.build.os==="windows"?"win32":Deno.build.os:void 0;Z.URL=typeof URL<"u"?URL:null;Z.pathToFileURL=kE;Z.fileURLToPath=BE;Z.Url;Z.format;Z.resolve;Z.resolveObject;Z.URL;_E=92,mE=47,vE=97,EE=122,rl=wE==="win32",SE=/\//g,AE=/%/g,IE=/\\/g,TE=/\n/g,RE=/\r/g,CE=/\t/g;xE=typeof Deno<"u"?Deno.build.os==="windows"?"win32":Deno.build.os:void 0;Z.URL=typeof URL<"u"?URL:null;Z.pathToFileURL=hg;Z.fileURLToPath=cg;ME=Z.Url,LE=Z.format,UE=Z.resolve,NE=Z.resolveObject,qE=Z.parse,DE=Z.URL,jE=92,FE=47,WE=97,$E=122,il=xE==="win32",HE=/\//g,VE=/%/g,zE=/\\/g,KE=/\n/g,GE=/\r/g,QE=/\t/g;});var nl={};Qt(nl,{Server:()=>Me,Socket:()=>Me,Stream:()=>Me,_createServerHandle:()=>Me,_normalizeArgs:()=>Me,_setSimultaneousAccepts:()=>Me,connect:()=>Me,createConnection:()=>Me,createServer:()=>Me,default:()=>XE,isIP:()=>Me,isIPv4:()=>Me,isIPv6:()=>Me});function Me(){throw new Error("Node.js net module is not supported by JSPM core outside of Node.js")}var XE,sl=we(()=>{v();m();_();XE={_createServerHandle:Me,_normalizeArgs:Me,_setSimultaneousAccepts:Me,connect:Me,createConnection:Me,createServer:Me,isIP:Me,isIPv4:Me,isIPv6:Me,Server:Me,Socket:Me,Stream:Me};});var ol=M(Mi=>{v();m();_();var gg=Mi&&Mi.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Mi,"__esModule",{value:!0});var ZE=gg((sl(),X(nl))),eS=gg(ot()),tS=(0, eS.default)("mqttjs:tcp"),rS=(t,e)=>{e.port=e.port||1883,e.hostname=e.hostname||e.host||"localhost";let{port:r}=e,i=e.hostname;return tS("port %d and host %s",r,i),ZE.default.createConnection(r,i)};Mi.default=rS;});var yg={};Qt(yg,{default:()=>iS});var iS,bg=we(()=>{v();m();_();iS={};});var ll=M(Li=>{v();m();_();var al=Li&&Li.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Li,"__esModule",{value:!0});var nS=al((bg(),X(yg))),sS=al((sl(),X(nl))),oS=al(ot()),aS=(0, oS.default)("mqttjs:tls"),lS=(t,e)=>{e.port=e.port||8883,e.host=e.hostname||e.host||"localhost",sS.default.isIP(e.host)===0&&(e.servername=e.host),e.rejectUnauthorized=e.rejectUnauthorized!==!1,delete e.path,aS("port %d host %s rejectUnauthorized %b",e.port,e.host,e.rejectUnauthorized);let r=nS.default.connect(e);r.on("secureConnect",()=>{e.rejectUnauthorized&&!r.authorized?r.emit("error",new Error("TLS not authorized")):r.removeListener("error",i);});function i(n){e.rejectUnauthorized&&t.emit("error",n),r.end();}return r.on("error",i),r};Li.default=lS;});var os=M(oi=>{v();m();_();Object.defineProperty(oi,"__esModule",{value:!0});oi.BufferedDuplex=oi.writev=void 0;var uS=Dt(),wg=(ye(),X(_e));function _g(t,e){let r=new Array(t.length);for(let i=0;i{this.push(n);});}_read(e){this.proxy.read(e);}_write(e,r,i){this.isSocketOpen?this.writeToProxy(e,r,i):this.writeQueue.push({chunk:e,encoding:r,cb:i});}_final(e){this.writeQueue=[],this.proxy.end(e);}_destroy(e,r){this.writeQueue=[],this.proxy.destroy(),r(e);}socketReady(){this.emit("connect"),this.isSocketOpen=!0,this.processWriteQueue();}writeToProxy(e,r,i){this.proxy.write(e,r)===!1?this.proxy.once("drain",i):i();}processWriteQueue(){for(;this.writeQueue.length>0;){let{chunk:e,encoding:r,cb:i}=this.writeQueue.shift();this.writeToProxy(e,r,i);}}};oi.BufferedDuplex=ul;});var hl=M(cl=>{v();m();_();Object.defineProperty(cl,"__esModule",{value:!0});var mg=(ye(),X(_e)),fS=Dt(),cS=os(),gt,fl,Le;function hS(){let t=new fS.Transform;return t._write=(e,r,i)=>{gt.send({data:e.buffer,success(){i();},fail(n){i(new Error(n));}});},t._flush=e=>{gt.close({success(){e();}});},t}function dS(t){t.hostname||(t.hostname="localhost"),t.path||(t.path="/"),t.wsOptions||(t.wsOptions={});}function pS(t,e){let r=t.protocol==="wxs"?"wss":"ws",i=`${r}://${t.hostname}${t.path}`;return t.port&&t.port!==80&&t.port!==443&&(i=`${r}://${t.hostname}:${t.port}${t.path}`),typeof t.transformWsUrl=="function"&&(i=t.transformWsUrl(i,t,e)),i}function gS(){gt.onOpen(()=>{Le.socketReady();}),gt.onMessage(t=>{let{data:e}=t;e instanceof ArrayBuffer?e=mg.Buffer.from(e):e=mg.Buffer.from(e,"utf8"),fl.push(e);}),gt.onClose(()=>{Le.emit("close"),Le.end(),Le.destroy();}),gt.onError(t=>{let e=new Error(t.errMsg);Le.destroy(e);});}var yS=(t,e)=>{if(e.hostname=e.hostname||e.host,!e.hostname)throw new Error("Could not determine host. Specify host manually.");let r=e.protocolId==="MQIsdp"&&e.protocolVersion===3?"mqttv3.1":"mqtt";dS(e);let i=pS(e,t);gt=wx.connectSocket({url:i,protocols:[r]}),fl=hS(),Le=new cS.BufferedDuplex(e,fl,gt),Le._destroy=(o,s)=>{gt.close({success(){s&&s(o);}});};let n=Le.destroy;return Le.destroy=(o,s)=>(Le.destroy=n,setTimeout(()=>{gt.close({fail(){Le._destroy(o,s);}});},0),Le),gS(),Le};cl.default=yS;});var gl=M(pl=>{v();m();_();Object.defineProperty(pl,"__esModule",{value:!0});var dl=(ye(),X(_e)),bS=Dt(),wS=os(),kt,as,ai,vg=!1;function _S(){let t=new bS.Transform;return t._write=(e,r,i)=>{kt.sendSocketMessage({data:e.buffer,success(){i();},fail(){i(new Error);}});},t._flush=e=>{kt.closeSocket({success(){e();}});},t}function mS(t){t.hostname||(t.hostname="localhost"),t.path||(t.path="/"),t.wsOptions||(t.wsOptions={});}function vS(t,e){let r=t.protocol==="alis"?"wss":"ws",i=`${r}://${t.hostname}${t.path}`;return t.port&&t.port!==80&&t.port!==443&&(i=`${r}://${t.hostname}:${t.port}${t.path}`),typeof t.transformWsUrl=="function"&&(i=t.transformWsUrl(i,t,e)),i}function ES(){vg||(vg=!0,kt.onSocketOpen(()=>{ai.socketReady();}),kt.onSocketMessage(t=>{if(typeof t.data=="string"){let e=dl.Buffer.from(t.data,"base64");as.push(e);}else {let e=new FileReader;e.addEventListener("load",()=>{let r=e.result;r instanceof ArrayBuffer?r=dl.Buffer.from(r):r=dl.Buffer.from(r,"utf8"),as.push(r);}),e.readAsArrayBuffer(t.data);}}),kt.onSocketClose(()=>{ai.end(),ai.destroy();}),kt.onSocketError(t=>{ai.destroy(t);}));}var SS=(t,e)=>{if(e.hostname=e.hostname||e.host,!e.hostname)throw new Error("Could not determine host. Specify host manually.");let r=e.protocolId==="MQIsdp"&&e.protocolVersion===3?"mqttv3.1":"mqtt";mS(e);let i=vS(e,t);return kt=e.my,kt.connectSocket({url:i,protocols:r}),as=_S(),ai=new wS.BufferedDuplex(e,as,kt),ES(),ai};pl.default=SS;});var Sg=M((PD,Eg)=>{v();m();_();Eg.exports=function(){throw new Error("ws does not work in the browser. Browser clients must use the native WebSocket object")};});var _l=M(Ui=>{v();m();_();var wl=Ui&&Ui.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Ui,"__esModule",{value:!0});var yl=(ye(),X(_e)),Ag=wl(Sg()),AS=wl(ot()),IS=Dt(),Ig=wl(Pi()),bl=os(),Kt=(0, AS.default)("mqttjs:ws"),TS=["rejectUnauthorized","ca","cert","key","pfx","passphrase"];function Tg(t,e){let r=`${t.protocol}://${t.hostname}:${t.port}${t.path}`;return typeof t.transformWsUrl=="function"&&(r=t.transformWsUrl(r,t,e)),r}function Rg(t){let e=t;return t.hostname||(e.hostname="localhost"),t.port||(t.protocol==="wss"?e.port=443:e.port=80),t.path||(e.path="/"),t.wsOptions||(e.wsOptions={}),!Ig.default&&t.protocol==="wss"&&TS.forEach(r=>{Object.prototype.hasOwnProperty.call(t,r)&&!Object.prototype.hasOwnProperty.call(t.wsOptions,r)&&(e.wsOptions[r]=t[r]);}),e}function RS(t){let e=Rg(t);if(e.hostname||(e.hostname=e.host),!e.hostname){if(typeof document>"u")throw new Error("Could not determine host. Specify host manually.");let r=new URL(document.URL);e.hostname=r.hostname,e.port||(e.port=Number(r.port));}return e.objectMode===void 0&&(e.objectMode=!(e.binary===!0||e.binary===void 0)),e}function CS(t,e,r){Kt("createWebSocket"),Kt(`protocol: ${r.protocolId} ${r.protocolVersion}`);let i=r.protocolId==="MQIsdp"&&r.protocolVersion===3?"mqttv3.1":"mqtt";Kt(`creating new Websocket for url: ${e} and protocol: ${i}`);let n;return r.createWebsocket?n=r.createWebsocket(e,[i],r):n=new Ag.default(e,[i],r.wsOptions),n}function BS(t,e){let r=e.protocolId==="MQIsdp"&&e.protocolVersion===3?"mqttv3.1":"mqtt",i=Tg(e,t),n;return e.createWebsocket?n=e.createWebsocket(i,[r],e):n=new WebSocket(i,[r]),n.binaryType="arraybuffer",n}var PS=(t,e)=>{Kt("streamBuilder");let r=Rg(e),i=Tg(r,t),n=CS(t,i,r),o=Ag.default.createWebSocketStream(n,r.wsOptions);return o.url=i,n.on("close",()=>{o.destroy();}),o},OS=(t,e)=>{Kt("browserStreamBuilder");let r,n=RS(e).browserBufferSize||1024*512,o=e.browserBufferTimeout||1e3,s=!e.objectMode,a=BS(t,e),u=h(e,E,S);e.objectMode||(u._writev=bl.writev.bind(u)),u.on("close",()=>{a.close();});let c=typeof a.addEventListener<"u";a.readyState===a.OPEN?(r=u,r.socket=a):(r=new bl.BufferedDuplex(e,u,a),c?a.addEventListener("open",d):a.onopen=d),c?(a.addEventListener("close",g),a.addEventListener("error",y),a.addEventListener("message",w)):(a.onclose=g,a.onerror=y,a.onmessage=w);function h(I,C,R){let U=new IS.Transform({objectMode:I.objectMode});return U._write=C,U._flush=R,U}function d(){Kt("WebSocket onOpen"),r instanceof bl.BufferedDuplex&&r.socketReady();}function g(I){Kt("WebSocket onClose",I),r.end(),r.destroy();}function y(I){Kt("WebSocket onError",I);let C=new Error("WebSocket error");C.event=I,r.destroy(C);}function w(I){let{data:C}=I;C instanceof ArrayBuffer?C=yl.Buffer.from(C):C=yl.Buffer.from(C,"utf8"),u.push(C);}function E(I,C,R){if(a.bufferedAmount>n){setTimeout(E,o,I,C,R);return}s&&typeof I=="string"&&(I=yl.Buffer.from(I,"utf8"));try{a.send(I);}catch(U){return R(U)}R();}function S(I){a.close(),I();}return r};Ui.default=Ig.default?OS:PS;});var Pg=M(Rr=>{v();m();_();var ls=Rr&&Rr.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Rr,"__esModule",{value:!0});Rr.connectAsync=void 0;var kS=ls(ot()),xS=ls((pg(),X(dg))),MS=ls(ns()),LS=ls(Pi()),Cg=(0, kS.default)("mqttjs"),Re={};LS.default?(Re.wx=hl().default,Re.wxs=hl().default,Re.ali=gl().default,Re.alis=gl().default):(Re.mqtt=ol().default,Re.tcp=ol().default,Re.ssl=ll().default,Re.tls=Re.ssl,Re.mqtts=ll().default);Re.ws=_l().default;Re.wss=_l().default;function US(t){let e;t.auth&&(e=t.auth.match(/^(.+):(.+)$/),e?(t.username=e[1],t.password=e[2]):t.username=t.auth);}function Bg(t,e){if(Cg("connecting to an MQTT broker..."),typeof t=="object"&&!e&&(e=t,t=""),e=e||{},t&&typeof t=="string"){let n=xS.default.parse(t,!0);if(n.port!=null&&(n.port=Number(n.port)),e=Object.assign(Object.assign({},n),e),e.protocol===null)throw new Error("Missing protocol");e.protocol=e.protocol.replace(/:$/,"");}if(US(e),e.query&&typeof e.query.clientId=="string"&&(e.clientId=e.query.clientId),e.cert&&e.key)if(e.protocol){if(["mqtts","wss","wxs","alis"].indexOf(e.protocol)===-1)switch(e.protocol){case"mqtt":e.protocol="mqtts";break;case"ws":e.protocol="wss";break;case"wx":e.protocol="wxs";break;case"ali":e.protocol="alis";break;default:throw new Error(`Unknown protocol for secure connection: "${e.protocol}"!`)}}else throw new Error("Missing secure protocol key");if(!Re[e.protocol]){let n=["mqtts","wss"].indexOf(e.protocol)!==-1;e.protocol=["mqtt","mqtts","ws","wss","wx","wxs","ali","alis"].filter((o,s)=>n&&s%2===0?!1:typeof Re[o]=="function")[0];}if(e.clean===!1&&!e.clientId)throw new Error("Missing clientId for unclean clients");e.protocol&&(e.defaultProtocol=e.protocol);function r(n){return e.servers&&((!n._reconnectCount||n._reconnectCount===e.servers.length)&&(n._reconnectCount=0),e.host=e.servers[n._reconnectCount].host,e.port=e.servers[n._reconnectCount].port,e.protocol=e.servers[n._reconnectCount].protocol?e.servers[n._reconnectCount].protocol:e.defaultProtocol,e.hostname=e.host,n._reconnectCount++),Cg("calling streambuilder for",e.protocol),Re[e.protocol](n,e)}let i=new MS.default(r,e);return i.on("error",()=>{}),i}function NS(t,e,r=!0){return new Promise((i,n)=>{let o=Bg(t,e),s={connect:u=>{a(),i(o);},end:()=>{a(),i(o);},error:u=>{a(),o.end(),n(u);}};r===!1&&(s.close=()=>{s.error(new Error("Couldn't connect to server"));});function a(){Object.keys(s).forEach(u=>{o.off(u,s[u]);});}Object.keys(s).forEach(u=>{o.on(u,s[u]);});})}Rr.connectAsync=NS;Rr.default=Bg;});var ml=M(G=>{v();m();_();var Og=G&&G.__createBinding||(Object.create?function(t,e,r,i){i===void 0&&(i=r);var n=Object.getOwnPropertyDescriptor(e,r);(!n||("get"in n?!e.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,i,n);}:function(t,e,r,i){i===void 0&&(i=r),t[i]=e[r];}),qS=G&&G.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e});}:function(t,e){t.default=e;}),DS=G&&G.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.prototype.hasOwnProperty.call(t,r)&&Og(e,t,r);return qS(e,t),e},kg=G&&G.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&Og(e,t,r);},Ni=G&&G.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(G,"__esModule",{value:!0});G.ReasonCodes=G.PingTimer=G.UniqueMessageIdProvider=G.DefaultMessageIdProvider=G.Store=G.MqttClient=G.connectAsync=G.connect=G.Client=void 0;var xg=Ni(ns());G.MqttClient=xg.default;var jS=Ni(Yo());G.DefaultMessageIdProvider=jS.default;var FS=Ni($p());G.UniqueMessageIdProvider=FS.default;var WS=Ni(Zo());G.Store=WS.default;var Mg=DS(Pg());G.connect=Mg.default;Object.defineProperty(G,"connectAsync",{enumerable:!0,get:function(){return Mg.connectAsync}});var $S=Ni(Da());G.PingTimer=$S.default;G.Client=xg.default;kg(ns(),G);kg(Jr(),G);var HS=Ai();Object.defineProperty(G,"ReasonCodes",{enumerable:!0,get:function(){return HS.ReasonCodes}});});var QS=M(We=>{v();m();_();var Lg=We&&We.__createBinding||(Object.create?function(t,e,r,i){i===void 0&&(i=r);var n=Object.getOwnPropertyDescriptor(e,r);(!n||("get"in n?!e.__esModule:n.writable||n.configurable))&&(n={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,i,n);}:function(t,e,r,i){i===void 0&&(i=r),t[i]=e[r];}),VS=We&&We.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e});}:function(t,e){t.default=e;}),zS=We&&We.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.prototype.hasOwnProperty.call(t,r)&&Lg(e,t,r);return VS(e,t),e},KS=We&&We.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&Lg(e,t,r);};Object.defineProperty(We,"__esModule",{value:!0});var GS=zS(ml());We.default=GS;KS(ml(),We);});var mqtt = QS(); +/*! Bundled license information: + +@jspm/core/nodelibs/browser/buffer.js: + (*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh *) +*/ + +class CloudInteropAPI { + connectParams; + _sessionDetails; + _mqttClient; + reconnectRetryLimit = 30; + reconnectRetries = 0; + contextListener; + constructor(connectParams) { + this.connectParams = connectParams; + } + get sessionDetails() { + return this._sessionDetails; + } + get mqttClient() { + return this._mqttClient; + } + async connect(params) { + const { userId, password, sourceId, platformId } = params; + let connectResponse; + try { + connectResponse = await axios.post(`${this.connectParams.url}/sessions`, { + userId, + sourceId, + platformId + }); + if (connectResponse.status !== 200) { + throw new Error(`Failed to connect to Cloud Interop url: ${this.connectParams.url}`); + } + const { sessionRootTopic } = connectResponse.data; + const lastWillPayload = { + userId, + sourceId, + platformId, + sessionId: connectResponse.data.sessionId + }; + const clientOptions = { + clientId: connectResponse.data.sessionId, + clean: true, + protocolVersion: 5, + will: { + topic: 'interop/lastwill', + payload: buffer__WEBPACK_IMPORTED_MODULE_0__.Buffer.from(JSON.stringify(lastWillPayload)), + qos: 0, + retain: false + }, + username: userId, + password + }; + this._mqttClient = await mqtt.connectAsync(connectResponse.data.mqttUrl, clientOptions); + this._sessionDetails = connectResponse.data; + console.log(`Cloud Interop successfully connected to ${this.connectParams.url}`); + this._mqttClient.on('error', (error) => { + console.error(`Cloud Interop Error: ${error}`); + }); + this._mqttClient.stream.on('error', (error) => { + console.error(`Cloud Interop Connection Error: ${error}`); + }); + this._mqttClient.on('reconnect', () => { + console.warn(`Cloud Interop attempting reconnection...`); + // Default reconnectPeriod = 30 seconds + // Attempt reconnection 30 times before ending session + this.reconnectRetries += 1; + if (this.reconnectRetries === this.reconnectRetryLimit) { + console.warn(`Cloud Interop reached max reconnection attempts...`); + this.disconnect(); + } + }); + // Does not fire on initial connection, only successful reconnection attempts + this._mqttClient.on('connect', () => { + console.log(`Cloud Interop successfully reconnected`); + this.reconnectRetries = 0; + }); + this._mqttClient.on('message', (topic, message) => { + this.handleCommand(topic, message, this._sessionDetails); + }); + // Subscribe to all context groups + this._mqttClient.subscribe(`${sessionRootTopic}/context-groups/#`); + // Listen out for global commands + this._mqttClient.subscribe(`${sessionRootTopic}/commands`); + } + catch (error) { + console.warn(`Failed to connect to Cloud Interop at ${this.connectParams.url}`, error); + } + } + async disconnect() { + if (!this._sessionDetails) { + return; + } + try { + const disconnectResponse = await axios.delete(`${this.connectParams.url}/sessions/${this._sessionDetails.sessionId}`); + if (disconnectResponse.status !== 200) { + console.warn(`Cloud Interop disconnection failed`, disconnectResponse); + } + } + catch (error) { + console.warn(`Cloud Interop error during disconnection`, error); + } + finally { + this._mqttClient?.removeAllListeners(); + this._mqttClient?.end(true); + this._sessionDetails = undefined; + this._mqttClient = undefined; + this.reconnectRetries = 0; + } + } + async setContext(contextGroup, context) { + if (!this._sessionDetails) { + return; + } + const { userId, sourceId } = this.connectParams; + const payload = { + userId, + sourceId, + context + }; + await axios.post(`${this.connectParams.url}/context-groups/${this._sessionDetails.sessionId}/${contextGroup}`, payload); + } + addContextListener(callback) { + this.contextListener = callback; + } + startIntentDiscovery(intentName, context) { + throw new Error('Method not implemented.'); + } + endIntentDiscovery(discoveryId) { + throw new Error('Method not implemented.'); + } + sendIntentDetail(discoveryId, intentDetail) { + throw new Error('Method not implemented.'); + } + raiseIntent(targetSession, intentInstanceId, context) { + throw new Error('Method not implemented.'); + } + addIntentDetailListener(callback) { + throw new Error('Method not implemented.'); + } + handleCommand(topic, message, sessionDetails) { + if (message.length === 0 || !sessionDetails) { + // Ignore clean up messages + return; + } + const messageEnvelope = JSON.parse(message.toString()); + if (topic.startsWith(`${sessionDetails.sessionRootTopic}/context-groups/`)) { + if (messageEnvelope.source.sessionId === sessionDetails.sessionId) { + return; + } + if (this.contextListener) { + const { channelName: contextGroup, payload: context, source } = messageEnvelope; + this.contextListener(contextGroup, context, source); + } + } + } +} + +async function cloudInteropOverride(config) { + const client = new CloudInteropAPI(config); + try { + await client.connect(config); + } + catch (err) { + console.warn(err); + return (Base) => { + return class NoOpOverride extends Base { + constructor() { + super(); + } + }; + }; + } + return (Base) => { + return class CloudInteropOverride extends Base { + constructor() { + super(); + client.addContextListener((contextGroup, context, source) => { + if (this.getContextGroups() + .map(({ id }) => id) + .includes(contextGroup) && + client.sessionDetails?.sessionId !== source.sessionId) { + super.setContextForGroup({ context: context }, contextGroup); + } + }); + } + async setContextForGroup({ context }, contextGroupId) { + client.setContext(contextGroupId, context); + super.setContextForGroup({ context }, contextGroupId); + } + async cloudReconnect() { + await client.connect(config); + } + get cloudConnectionState() { + if (client.mqttClient?.connected) { + return 'connected'; + } + if (client.mqttClient?.reconnecting) { + return 'reconnecting'; + } + return 'disconnected'; + } + }; + }; +} + + + + +/***/ }), + +/***/ "../../../node_modules/base64-js/index.js": +/*!************************************************!*\ + !*** ../../../node_modules/base64-js/index.js ***! + \************************************************/ +/***/ ((__unused_webpack_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 + + var i + for (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('') +} + + +/***/ }), + +/***/ "../../../node_modules/buffer/index.js": +/*!*********************************************!*\ + !*** ../../../node_modules/buffer/index.js ***! + \*********************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + + + +const base64 = __webpack_require__(/*! base64-js */ "../../../node_modules/base64-js/index.js") +const ieee754 = __webpack_require__(/*! ieee754 */ "../../../node_modules/ieee754/index.js") +const customInspectSymbol = + (typeof Symbol === 'function' && typeof Symbol['for'] === 'function') // eslint-disable-line dot-notation + ? Symbol['for']('nodejs.util.inspect.custom') // eslint-disable-line dot-notation + : null + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +const K_MAX_LENGTH = 0x7fffffff +exports.kMaxLength = K_MAX_LENGTH + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an 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+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() + +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && + typeof console.error === 'function') { + console.error( + 'This browser lacks typed array (Uint8Array) support which is required by ' + + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' + ) +} + +function typedArraySupport () { + // Can typed array instances can be augmented? + try { + const arr = new Uint8Array(1) + const proto = { foo: function () { return 42 } } + Object.setPrototypeOf(proto, Uint8Array.prototype) + Object.setPrototypeOf(arr, proto) + return arr.foo() === 42 + } catch (e) { + return false + } +} + +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.buffer + } +}) + +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.byteOffset + } +}) + +function createBuffer (length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"') + } + // Return an augmented `Uint8Array` instance + const buf = new Uint8Array(length) + Object.setPrototypeOf(buf, Buffer.prototype) + return buf +} + +/** + * 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) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError( + 'The "string" argument must be of type string. Received type number' + ) + } + return allocUnsafe(arg) + } + return from(arg, encodingOrOffset, length) +} + +Buffer.poolSize = 8192 // not used by this implementation + +function from (value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + + if (ArrayBuffer.isView(value)) { + return fromArrayView(value) + } + + if (value == null) { + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) + } + + if (isInstance(value, ArrayBuffer) || + (value && isInstance(value.buffer, ArrayBuffer))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof SharedArrayBuffer !== 'undefined' && + (isInstance(value, SharedArrayBuffer) || + (value && isInstance(value.buffer, SharedArrayBuffer)))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof value === 'number') { + throw new TypeError( + 'The "value" argument must not be of type number. Received type number' + ) + } + + const valueOf = value.valueOf && value.valueOf() + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length) + } + + const b = fromObject(value) + if (b) return b + + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && + typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length) + } + + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof 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(value, encodingOrOffset, length) +} + +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Object.setPrototypeOf(Buffer.prototype, Uint8Array.prototype) +Object.setPrototypeOf(Buffer, Uint8Array) + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number') + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } +} + +function alloc (size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpreted as a start offset. + return typeof encoding === 'string' + ? createBuffer(size).fill(fill, encoding) + : createBuffer(size).fill(fill) + } + return createBuffer(size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding) +} + +function allocUnsafe (size) { + assertSize(size) + return createBuffer(size < 0 ? 0 : checked(size) | 0) +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size) +} + +function fromString (string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + + const length = byteLength(string, encoding) | 0 + let buf = createBuffer(length) + + const actual = buf.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') + buf = buf.slice(0, actual) + } + + return buf +} + +function fromArrayLike (array) { + const length = array.length < 0 ? 0 : checked(array.length) | 0 + const buf = createBuffer(length) + for (let i = 0; i < length; i += 1) { + buf[i] = array[i] & 255 + } + return buf +} + +function fromArrayView (arrayView) { + if (isInstance(arrayView, Uint8Array)) { + const copy = new Uint8Array(arrayView) + return fromArrayBuffer(copy.buffer, copy.byteOffset, copy.byteLength) + } + return fromArrayLike(arrayView) +} + +function fromArrayBuffer (array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds') + } + + let buf + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array) + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset) + } else { + buf = new Uint8Array(array, byteOffset, length) + } + + // Return an augmented `Uint8Array` instance + Object.setPrototypeOf(buf, Buffer.prototype) + + return buf +} + +function fromObject (obj) { + if (Buffer.isBuffer(obj)) { + const len = checked(obj.length) | 0 + const buf = createBuffer(len) + + if (buf.length === 0) { + return buf + } + + obj.copy(buf, 0, 0, len) + return buf + } + + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0) + } + return fromArrayLike(obj) + } + + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data) + } +} + +function checked (length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + K_MAX_LENGTH.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 === true && + b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false +} + +Buffer.compare = function compare (a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError( + 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' + ) + } + + if (a === b) return 0 + + let x = a.length + let y = b.length + + for (let 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 (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + let i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + const buffer = Buffer.allocUnsafe(length) + let pos = 0 + for (i = 0; i < list.length; ++i) { + let buf = list[i] + if (isInstance(buf, Uint8Array)) { + if (pos + buf.length > buffer.length) { + if (!Buffer.isBuffer(buf)) buf = Buffer.from(buf) + buf.copy(buffer, pos) + } else { + Uint8Array.prototype.set.call( + buffer, + buf, + pos + ) + } + } else if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } else { + buf.copy(buffer, pos) + } + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + throw new TypeError( + 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + + 'Received type ' + typeof string + ) + } + + const len = string.length + const mustMatch = (arguments.length > 2 && arguments[2] === true) + if (!mustMatch && len === 0) return 0 + + // Use a for loop to avoid recursion + let loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + 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 mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 + } + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + let 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 coercion 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 + } + } +} + +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + const i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + const len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (let i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + const len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (let i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + const len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (let 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 () { + const length = this.length + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.toLocaleString = Buffer.prototype.toString + +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 () { + let str = '' + const max = exports.INSPECT_MAX_BYTES + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() + if (this.length > max) str += ' ... ' + return '' +} +if (customInspectSymbol) { + Buffer.prototype[customInspectSymbol] = Buffer.prototype.inspect +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength) + } + if (!Buffer.isBuffer(target)) { + throw new TypeError( + 'The "target" argument must be one of type Buffer or Uint8Array. ' + + 'Received type ' + (typeof target) + ) + } + + 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 + + let x = thisEnd - thisStart + let y = end - start + const len = Math.min(x, y) + + const thisCopy = this.slice(thisStart, thisEnd) + const targetCopy = target.slice(start, end) + + for (let 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 (numberIsNaN(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 (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) { + let indexSize = 1 + let arrLength = arr.length + let 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) + } + } + + let i + if (dir) { + let 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--) { + let found = true + for (let 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 + const remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + const strLen = string.length + + if (length > strLen / 2) { + length = strLen / 2 + } + let i + for (i = 0; i < length; ++i) { + const parsed = parseInt(string.substr(i * 2, 2), 16) + if (numberIsNaN(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 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 + } + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + const 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' + + let 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': + case 'latin1': + case 'binary': + return asciiWrite(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) + const res = [] + + let i = start + while (i < end) { + const firstByte = buf[i] + let codePoint = null + let bytesPerSequence = (firstByte > 0xEF) + ? 4 + : (firstByte > 0xDF) + ? 3 + : (firstByte > 0xBF) + ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + let 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 +const MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + const 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". + let res = '' + let i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + let ret = '' + end = Math.min(buf.length, end) + + for (let i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + let ret = '' + end = Math.min(buf.length, end) + + for (let i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + const len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + let out = '' + for (let i = start; i < end; ++i) { + out += hexSliceLookupTable[buf[i]] + } + return out +} + +function utf16leSlice (buf, start, end) { + const bytes = buf.slice(start, end) + let res = '' + // If bytes.length is odd, the last 8 bits must be ignored (same as node.js) + for (let i = 0; i < bytes.length - 1; i += 2) { + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + const 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 + + const newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + Object.setPrototypeOf(newBuf, Buffer.prototype) + + 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 = +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + let val = this[offset] + let mul = 1 + let i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUintBE = +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + let val = this[offset + --byteLength] + let mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUint8 = +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUint16LE = +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUint16BE = +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUint32LE = +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + offset = offset >>> 0 + 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 = +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readBigUInt64LE = defineBigIntMethod(function readBigUInt64LE (offset) { + offset = offset >>> 0 + validateNumber(offset, 'offset') + const first = this[offset] + const last = this[offset + 7] + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8) + } + + const lo = first + + this[++offset] * 2 ** 8 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 24 + + const hi = this[++offset] + + this[++offset] * 2 ** 8 + + this[++offset] * 2 ** 16 + + last * 2 ** 24 + + return BigInt(lo) + (BigInt(hi) << BigInt(32)) +}) + +Buffer.prototype.readBigUInt64BE = defineBigIntMethod(function readBigUInt64BE (offset) { + offset = offset >>> 0 + validateNumber(offset, 'offset') + const first = this[offset] + const last = this[offset + 7] + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8) + } + + const hi = first * 2 ** 24 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + + this[++offset] + + const lo = this[++offset] * 2 ** 24 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + + last + + return (BigInt(hi) << BigInt(32)) + BigInt(lo) +}) + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + let val = this[offset] + let mul = 1 + let 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) + + let i = byteLength + let mul = 1 + let 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) { + offset = offset >>> 0 + 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) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + const val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + const val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + offset = offset >>> 0 + 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) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readBigInt64LE = defineBigIntMethod(function readBigInt64LE (offset) { + offset = offset >>> 0 + validateNumber(offset, 'offset') + const first = this[offset] + const last = this[offset + 7] + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8) + } + + const val = this[offset + 4] + + this[offset + 5] * 2 ** 8 + + this[offset + 6] * 2 ** 16 + + (last << 24) // Overflow + + return (BigInt(val) << BigInt(32)) + + BigInt(first + + this[++offset] * 2 ** 8 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 24) +}) + +Buffer.prototype.readBigInt64BE = defineBigIntMethod(function readBigInt64BE (offset) { + offset = offset >>> 0 + validateNumber(offset, 'offset') + const first = this[offset] + const last = this[offset + 7] + if (first === undefined || last === undefined) { + boundsError(offset, this.length - 8) + } + + const val = (first << 24) + // Overflow + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + + this[++offset] + + return (BigInt(val) << BigInt(32)) + + BigInt(this[++offset] * 2 ** 24 + + this[++offset] * 2 ** 16 + + this[++offset] * 2 ** 8 + + last) +}) + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + offset = offset >>> 0 + 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 = +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + const maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + let mul = 1 + let i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUintBE = +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + const maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + let i = byteLength - 1 + let mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUint8 = +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeUint16LE = +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeUint16BE = +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeUint32LE = +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeUint32BE = +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +function wrtBigUInt64LE (buf, value, offset, min, max) { + checkIntBI(value, min, max, buf, offset, 7) + + let lo = Number(value & BigInt(0xffffffff)) + buf[offset++] = lo + lo = lo >> 8 + buf[offset++] = lo + lo = lo >> 8 + buf[offset++] = lo + lo = lo >> 8 + buf[offset++] = lo + let hi = Number(value >> BigInt(32) & BigInt(0xffffffff)) + buf[offset++] = hi + hi = hi >> 8 + buf[offset++] = hi + hi = hi >> 8 + buf[offset++] = hi + hi = hi >> 8 + buf[offset++] = hi + return offset +} + +function wrtBigUInt64BE (buf, value, offset, min, max) { + checkIntBI(value, min, max, buf, offset, 7) + + let lo = Number(value & BigInt(0xffffffff)) + buf[offset + 7] = lo + lo = lo >> 8 + buf[offset + 6] = lo + lo = lo >> 8 + buf[offset + 5] = lo + lo = lo >> 8 + buf[offset + 4] = lo + let hi = Number(value >> BigInt(32) & BigInt(0xffffffff)) + buf[offset + 3] = hi + hi = hi >> 8 + buf[offset + 2] = hi + hi = hi >> 8 + buf[offset + 1] = hi + hi = hi >> 8 + buf[offset] = hi + return offset + 8 +} + +Buffer.prototype.writeBigUInt64LE = defineBigIntMethod(function writeBigUInt64LE (value, offset = 0) { + return wrtBigUInt64LE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff')) +}) + +Buffer.prototype.writeBigUInt64BE = defineBigIntMethod(function writeBigUInt64BE (value, offset = 0) { + return wrtBigUInt64BE(this, value, offset, BigInt(0), BigInt('0xffffffffffffffff')) +}) + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + const limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + let i = 0 + let mul = 1 + let 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) { + const limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + let i = byteLength - 1 + let mul = 1 + let 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 (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) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + 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) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + 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) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + 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 + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeBigInt64LE = defineBigIntMethod(function writeBigInt64LE (value, offset = 0) { + return wrtBigUInt64LE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff')) +}) + +Buffer.prototype.writeBigInt64BE = defineBigIntMethod(function writeBigInt64BE (value, offset = 0) { + return wrtBigUInt64BE(this, value, offset, -BigInt('0x8000000000000000'), BigInt('0x7fffffffffffffff')) +}) + +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) { + value = +value + offset = offset >>> 0 + 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) { + value = +value + offset = offset >>> 0 + 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 (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') + 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('Index out of range') + 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 + } + + const len = end - start + + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end) + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, end), + 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 (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) + } + if (val.length === 1) { + const code = val.charCodeAt(0) + if ((encoding === 'utf8' && code < 128) || + encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code + } + } + } else if (typeof val === 'number') { + val = val & 255 + } else if (typeof val === 'boolean') { + val = Number(val) + } + + // 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 + + let i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + const bytes = Buffer.isBuffer(val) + ? val + : Buffer.from(val, encoding) + const len = bytes.length + if (len === 0) { + throw new TypeError('The value "' + val + + '" is invalid for argument "value"') + } + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// CUSTOM ERRORS +// ============= + +// Simplified versions from Node, changed for Buffer-only usage +const errors = {} +function E (sym, getMessage, Base) { + errors[sym] = class NodeError extends Base { + constructor () { + super() + + Object.defineProperty(this, 'message', { + value: getMessage.apply(this, arguments), + writable: true, + configurable: true + }) + + // Add the error code to the name to include it in the stack trace. + this.name = `${this.name} [${sym}]` + // Access the stack to generate the error message including the error code + // from the name. + this.stack // eslint-disable-line no-unused-expressions + // Reset the name to the actual name. + delete this.name + } + + get code () { + return sym + } + + set code (value) { + Object.defineProperty(this, 'code', { + configurable: true, + enumerable: true, + value, + writable: true + }) + } + + toString () { + return `${this.name} [${sym}]: ${this.message}` + } + } +} + +E('ERR_BUFFER_OUT_OF_BOUNDS', + function (name) { + if (name) { + return `${name} is outside of buffer bounds` + } + + return 'Attempt to access memory outside buffer bounds' + }, RangeError) +E('ERR_INVALID_ARG_TYPE', + function (name, actual) { + return `The "${name}" argument must be of type number. Received type ${typeof actual}` + }, TypeError) +E('ERR_OUT_OF_RANGE', + function (str, range, input) { + let msg = `The value of "${str}" is out of range.` + let received = input + if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) { + received = addNumericalSeparator(String(input)) + } else if (typeof input === 'bigint') { + received = String(input) + if (input > BigInt(2) ** BigInt(32) || input < -(BigInt(2) ** BigInt(32))) { + received = addNumericalSeparator(received) + } + received += 'n' + } + msg += ` It must be ${range}. Received ${received}` + return msg + }, RangeError) + +function addNumericalSeparator (val) { + let res = '' + let i = val.length + const start = val[0] === '-' ? 1 : 0 + for (; i >= start + 4; i -= 3) { + res = `_${val.slice(i - 3, i)}${res}` + } + return `${val.slice(0, i)}${res}` +} + +// CHECK FUNCTIONS +// =============== + +function checkBounds (buf, offset, byteLength) { + validateNumber(offset, 'offset') + if (buf[offset] === undefined || buf[offset + byteLength] === undefined) { + boundsError(offset, buf.length - (byteLength + 1)) + } +} + +function checkIntBI (value, min, max, buf, offset, byteLength) { + if (value > max || value < min) { + const n = typeof min === 'bigint' ? 'n' : '' + let range + if (byteLength > 3) { + if (min === 0 || min === BigInt(0)) { + range = `>= 0${n} and < 2${n} ** ${(byteLength + 1) * 8}${n}` + } else { + range = `>= -(2${n} ** ${(byteLength + 1) * 8 - 1}${n}) and < 2 ** ` + + `${(byteLength + 1) * 8 - 1}${n}` + } + } else { + range = `>= ${min}${n} and <= ${max}${n}` + } + throw new errors.ERR_OUT_OF_RANGE('value', range, value) + } + checkBounds(buf, offset, byteLength) +} + +function validateNumber (value, name) { + if (typeof value !== 'number') { + throw new errors.ERR_INVALID_ARG_TYPE(name, 'number', value) + } +} + +function boundsError (value, length, type) { + if (Math.floor(value) !== value) { + validateNumber(value, type) + throw new errors.ERR_OUT_OF_RANGE(type || 'offset', 'an integer', value) + } + + if (length < 0) { + throw new errors.ERR_BUFFER_OUT_OF_BOUNDS() + } + + throw new errors.ERR_OUT_OF_RANGE(type || 'offset', + `>= ${type ? 1 : 0} and <= ${length}`, + value) +} + +// HELPER FUNCTIONS +// ================ + +const INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0] + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().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 utf8ToBytes (string, units) { + units = units || Infinity + let codePoint + const length = string.length + let leadSurrogate = null + const bytes = [] + + for (let 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) { + const byteArray = [] + for (let 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) { + let c, hi, lo + const byteArray = [] + for (let 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) { + let i + for (i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 +function isInstance (obj, type) { + return obj instanceof type || + (obj != null && obj.constructor != null && obj.constructor.name != null && + obj.constructor.name === type.name) +} +function numberIsNaN (obj) { + // For IE11 support + return obj !== obj // eslint-disable-line no-self-compare +} + +// Create lookup table for `toString('hex')` +// See: https://github.com/feross/buffer/issues/219 +const hexSliceLookupTable = (function () { + const alphabet = '0123456789abcdef' + const table = new Array(256) + for (let i = 0; i < 16; ++i) { + const i16 = i * 16 + for (let j = 0; j < 16; ++j) { + table[i16 + j] = alphabet[i] + alphabet[j] + } + } + return table +})() + +// Return not function with Error if BigInt not supported +function defineBigIntMethod (fn) { + return typeof BigInt === 'undefined' ? BufferBigIntNotDefined : fn +} + +function BufferBigIntNotDefined () { + throw new Error('BigInt not supported') +} + + +/***/ }), + +/***/ "../../../node_modules/ieee754/index.js": +/*!**********************************************!*\ + !*** ../../../node_modules/ieee754/index.js ***! + \**********************************************/ +/***/ ((__unused_webpack_module, exports) => { + +/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ +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 +} + + +/***/ }), + +/***/ "./client/src/settings.ts": +/*!********************************!*\ + !*** ./client/src/settings.ts ***! + \********************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ getManifestCustomSettings: () => (/* binding */ getManifestCustomSettings) +/* harmony export */ }); +/** + * Load the customSettings section from the application manifest. + * @returns The custom settings from the manifest. + */ +async function getManifestCustomSettings() { + const app = await fin.Application.getCurrent(); + const manifest = await app.getManifest(); + return manifest.customSettings; +} + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/amd options */ +/******/ (() => { +/******/ __webpack_require__.amdO = {}; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be in strict mode. +(() => { +"use strict"; +/*!********************************!*\ + !*** ./client/src/provider.ts ***! + \********************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _openfin_cloud_interop__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @openfin/cloud-interop */ "../../../node_modules/@openfin/cloud-interop/out/index.js"); +/* harmony import */ var _settings__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./settings */ "./client/src/settings.ts"); + + +window.addEventListener("DOMContentLoaded", async () => { + const customSettings = await (0,_settings__WEBPACK_IMPORTED_MODULE_1__.getManifestCustomSettings)(); + const interopOverrides = []; + if (customSettings?.cloudInteropProvider?.enabled) { + const initializedCloudInteropOverride = (await (0,_openfin_cloud_interop__WEBPACK_IMPORTED_MODULE_0__.cloudInteropOverride)(customSettings?.cloudInteropProvider?.connectParams)); + interopOverrides.push(initializedCloudInteropOverride); + } + fin.Platform.init({ interopOverride: interopOverrides }).catch((error) => console.error(error)); +}); + +})(); + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25COztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUyxRQUFRO0FBQ2pCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLFdB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QUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwyQkFBMkIsbUJBQW1CO0FBQzlDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLEtBQUs7QUFDTCxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtB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QTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EseUNBQXlDLE1BQU07QUFDL0MsTUFBTTtBQUNOO0FBQ0E7QUFDQSw4Q0FBOEMsTUFBTTtBQUNwRDtBQUNBLENBQUM7O0FBRUQsc0NBQXNDLE9BQU87O0FBRTdDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTs7QUFFQTs7QUFFQSxvQkFBb0IsWUFBWTtBQUNoQztBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxtREFBbUQsR0FBRztBQUN0RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EseUNBQXlDLElBQUk7QUFDN0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNB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QUFPOztBQUVQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0EsV0FBVyxVQUFVO0FBQ3JCO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZDtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixZQUFZO0FBQzlCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSx3Q0FBd0MsU0FBUztBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsaUJBQWlCO0FBQ2pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxpQkFBaUI7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixTQUFTO0FBQzNCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsU0FBUztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsU0FBUztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQsRUFBRTtBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsa0JBQWtCLFNBQVM7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQztBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QixlQUFlO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBLHlCQUF5QixRQUFRO0FBQ2pDO0FBQ0Esc0JBQXNCLGVBQWU7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsc0JBQXNCLFNBQVM7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixTQUFTO0FBQy9CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLHNCQUFzQixTQUFTO0FBQy9CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLHNCQUFzQjtBQUN4QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVB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QyxrQkFBa0IsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN0RCxNQUFNLGNBQWMsR0FBRyxNQUFNLG9FQUF5QixFQUFFLENBQUM7SUFDekQsTUFBTSxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7SUFFNUIsSUFBSSxjQUFjLEVBQUUsb0JBQW9CLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDbkQsTUFBTSwrQkFBK0IsR0FBRyxDQUFDLE1BQU0sNEVBQW9CLENBQ2xFLGNBQWMsRUFBRSxvQkFBb0IsRUFBRSxhQUFhLENBQ25ELENBQWtFLENBQUM7UUFDcEUsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUNELEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsZUFBZSxFQUFFLGdCQUFnQixFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUNqRyxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL2NvbnRhaW5lci1zdGFydGVyLXVzZS1pbnRlcm9wLS1jbG91ZC1pbnRlcm9wLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9Ab3BlbmZpbi9jbG91ZC1pbnRlcm9wL291dC9pbmRleC5qcyIsIndlYnBhY2s6Ly9jb250YWluZXItc3RhcnRlci11c2UtaW50ZXJvcC0tY2xvdWQtaW50ZXJvcC8uLi8uLi8uLi9ub2RlX21vZHVsZXMvYmFzZTY0LWpzL2luZGV4LmpzIiwid2VicGFjazovL2NvbnRhaW5lci1zdGFydGVyLXVzZS1pbnRlcm9wLS1jbG91ZC1pbnRlcm9wLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9idWZmZXIvaW5kZXguanMiLCJ3ZWJwYWNrOi8vY29udGFpbmVyLXN0YXJ0ZXItdXNlLWludGVyb3AtLWNsb3VkLWludGVyb3AvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCJ3ZWJwYWNrOi8vY29udGFpbmVyLXN0YXJ0ZXItdXNlLWludGVyb3AtLWNsb3VkLWludGVyb3AvLi9jbGllbnQvc3JjL3NldHRpbmdzLnRzIiwid2VicGFjazovL2NvbnRhaW5lci1zdGFydGVyLXVzZS1pbnRlcm9wLS1jbG91ZC1pbnRlcm9wL3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL2NvbnRhaW5lci1zdGFydGVyLXVzZS1pbnRlcm9wLS1jbG91ZC1pbnRlcm9wL3dlYnBhY2svcnVudGltZS9hbWQgb3B0aW9ucyIsIndlYnBhY2s6Ly9jb250YWluZXItc3RhcnRlci11c2UtaW50ZXJvcC0tY2xvdWQtaW50ZXJvcC93ZWJwYWNrL3J1bnRpbWUvZGVmaW5lIHByb3BlcnR5IGdldHRlcnMiLCJ3ZWJwYWNrOi8vY29udGFpbmVyLXN0YXJ0ZXItdXNlLWludGVyb3AtLWNsb3VkLWludGVyb3Avd2VicGFjay9ydW50aW1lL2dsb2JhbCIsIndlYnBhY2s6Ly9jb250YWluZXItc3RhcnRlci11c2UtaW50ZXJvcC0tY2xvdWQtaW50ZXJvcC93ZWJwYWNrL3J1bnRpbWUvaGFzT3duUHJvcGVydHkgc2hvcnRoYW5kIiwid2VicGFjazovL2NvbnRhaW5lci1zdGFydGVyLXVzZS1pbnRlcm9wLS1jbG91ZC1pbnRlcm9wL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vY29udGFpbmVyLXN0YXJ0ZXItdXNlLWludGVyb3AtLWNsb3VkLWludGVyb3AvLi9jbGllbnQvc3JjL3Byb3ZpZGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEJ1ZmZlciB9IGZyb20gJ2J1ZmZlcic7XG5cbmZ1bmN0aW9uIGJpbmQoZm4sIHRoaXNBcmcpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHdyYXAoKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXNBcmcsIGFyZ3VtZW50cyk7XG4gIH07XG59XG5cbi8vIHV0aWxzIGlzIGEgbGlicmFyeSBvZiBnZW5lcmljIGhlbHBlciBmdW5jdGlvbnMgbm9uLXNwZWNpZmljIHRvIGF4aW9zXG5cbmNvbnN0IHt0b1N0cmluZ30gPSBPYmplY3QucHJvdG90eXBlO1xuY29uc3Qge2dldFByb3RvdHlwZU9mfSA9IE9iamVjdDtcblxuY29uc3Qga2luZE9mID0gKGNhY2hlID0+IHRoaW5nID0+IHtcbiAgICBjb25zdCBzdHIgPSB0b1N0cmluZy5jYWxsKHRoaW5nKTtcbiAgICByZXR1cm4gY2FjaGVbc3RyXSB8fCAoY2FjaGVbc3RyXSA9IHN0ci5zbGljZSg4LCAtMSkudG9Mb3dlckNhc2UoKSk7XG59KShPYmplY3QuY3JlYXRlKG51bGwpKTtcblxuY29uc3Qga2luZE9mVGVzdCA9ICh0eXBlKSA9PiB7XG4gIHR5cGUgPSB0eXBlLnRvTG93ZXJDYXNlKCk7XG4gIHJldHVybiAodGhpbmcpID0+IGtpbmRPZih0aGluZykgPT09IHR5cGVcbn07XG5cbmNvbnN0IHR5cGVPZlRlc3QgPSB0eXBlID0+IHRoaW5nID0+IHR5cGVvZiB0aGluZyA9PT0gdHlwZTtcblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhbiBBcnJheVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhbiBBcnJheSwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmNvbnN0IHtpc0FycmF5fSA9IEFycmF5O1xuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIHVuZGVmaW5lZFxuICpcbiAqIEBwYXJhbSB7Kn0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIHVuZGVmaW5lZCwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmNvbnN0IGlzVW5kZWZpbmVkID0gdHlwZU9mVGVzdCgndW5kZWZpbmVkJyk7XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBCdWZmZXJcbiAqXG4gKiBAcGFyYW0geyp9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGEgQnVmZmVyLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNCdWZmZXIodmFsKSB7XG4gIHJldHVybiB2YWwgIT09IG51bGwgJiYgIWlzVW5kZWZpbmVkKHZhbCkgJiYgdmFsLmNvbnN0cnVjdG9yICE9PSBudWxsICYmICFpc1VuZGVmaW5lZCh2YWwuY29uc3RydWN0b3IpXG4gICAgJiYgaXNGdW5jdGlvbih2YWwuY29uc3RydWN0b3IuaXNCdWZmZXIpICYmIHZhbC5jb25zdHJ1Y3Rvci5pc0J1ZmZlcih2YWwpO1xufVxuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGFuIEFycmF5QnVmZmVyXG4gKlxuICogQHBhcmFtIHsqfSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhbiBBcnJheUJ1ZmZlciwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmNvbnN0IGlzQXJyYXlCdWZmZXIgPSBraW5kT2ZUZXN0KCdBcnJheUJ1ZmZlcicpO1xuXG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSB2aWV3IG9uIGFuIEFycmF5QnVmZmVyXG4gKlxuICogQHBhcmFtIHsqfSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIHZpZXcgb24gYW4gQXJyYXlCdWZmZXIsIG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0FycmF5QnVmZmVyVmlldyh2YWwpIHtcbiAgbGV0IHJlc3VsdDtcbiAgaWYgKCh0eXBlb2YgQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnKSAmJiAoQXJyYXlCdWZmZXIuaXNWaWV3KSkge1xuICAgIHJlc3VsdCA9IEFycmF5QnVmZmVyLmlzVmlldyh2YWwpO1xuICB9IGVsc2Uge1xuICAgIHJlc3VsdCA9ICh2YWwpICYmICh2YWwuYnVmZmVyKSAmJiAoaXNBcnJheUJ1ZmZlcih2YWwuYnVmZmVyKSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIFN0cmluZ1xuICpcbiAqIEBwYXJhbSB7Kn0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBTdHJpbmcsIG90aGVyd2lzZSBmYWxzZVxuICovXG5jb25zdCBpc1N0cmluZyA9IHR5cGVPZlRlc3QoJ3N0cmluZycpO1xuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGEgRnVuY3Rpb25cbiAqXG4gKiBAcGFyYW0geyp9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBGdW5jdGlvbiwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmNvbnN0IGlzRnVuY3Rpb24gPSB0eXBlT2ZUZXN0KCdmdW5jdGlvbicpO1xuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGEgTnVtYmVyXG4gKlxuICogQHBhcmFtIHsqfSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIE51bWJlciwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmNvbnN0IGlzTnVtYmVyID0gdHlwZU9mVGVzdCgnbnVtYmVyJyk7XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYW4gT2JqZWN0XG4gKlxuICogQHBhcmFtIHsqfSB0aGluZyBUaGUgdmFsdWUgdG8gdGVzdFxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGFuIE9iamVjdCwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmNvbnN0IGlzT2JqZWN0ID0gKHRoaW5nKSA9PiB0aGluZyAhPT0gbnVsbCAmJiB0eXBlb2YgdGhpbmcgPT09ICdvYmplY3QnO1xuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGEgQm9vbGVhblxuICpcbiAqIEBwYXJhbSB7Kn0gdGhpbmcgVGhlIHZhbHVlIHRvIHRlc3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGEgQm9vbGVhbiwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmNvbnN0IGlzQm9vbGVhbiA9IHRoaW5nID0+IHRoaW5nID09PSB0cnVlIHx8IHRoaW5nID09PSBmYWxzZTtcblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIHBsYWluIE9iamVjdFxuICpcbiAqIEBwYXJhbSB7Kn0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBwbGFpbiBPYmplY3QsIG90aGVyd2lzZSBmYWxzZVxuICovXG5jb25zdCBpc1BsYWluT2JqZWN0ID0gKHZhbCkgPT4ge1xuICBpZiAoa2luZE9mKHZhbCkgIT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgcHJvdG90eXBlID0gZ2V0UHJvdG90eXBlT2YodmFsKTtcbiAgcmV0dXJuIChwcm90b3R5cGUgPT09IG51bGwgfHwgcHJvdG90eXBlID09PSBPYmplY3QucHJvdG90eXBlIHx8IE9iamVjdC5nZXRQcm90b3R5cGVPZihwcm90b3R5cGUpID09PSBudWxsKSAmJiAhKFN5bWJvbC50b1N0cmluZ1RhZyBpbiB2YWwpICYmICEoU3ltYm9sLml0ZXJhdG9yIGluIHZhbCk7XG59O1xuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGEgRGF0ZVxuICpcbiAqIEBwYXJhbSB7Kn0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBEYXRlLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuY29uc3QgaXNEYXRlID0ga2luZE9mVGVzdCgnRGF0ZScpO1xuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGEgRmlsZVxuICpcbiAqIEBwYXJhbSB7Kn0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBGaWxlLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuY29uc3QgaXNGaWxlID0ga2luZE9mVGVzdCgnRmlsZScpO1xuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGEgQmxvYlxuICpcbiAqIEBwYXJhbSB7Kn0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBCbG9iLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuY29uc3QgaXNCbG9iID0ga2luZE9mVGVzdCgnQmxvYicpO1xuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGEgRmlsZUxpc3RcbiAqXG4gKiBAcGFyYW0geyp9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGEgRmlsZSwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmNvbnN0IGlzRmlsZUxpc3QgPSBraW5kT2ZUZXN0KCdGaWxlTGlzdCcpO1xuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGEgU3RyZWFtXG4gKlxuICogQHBhcmFtIHsqfSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIFN0cmVhbSwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmNvbnN0IGlzU3RyZWFtID0gKHZhbCkgPT4gaXNPYmplY3QodmFsKSAmJiBpc0Z1bmN0aW9uKHZhbC5waXBlKTtcblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIEZvcm1EYXRhXG4gKlxuICogQHBhcmFtIHsqfSB0aGluZyBUaGUgdmFsdWUgdG8gdGVzdFxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGFuIEZvcm1EYXRhLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuY29uc3QgaXNGb3JtRGF0YSA9ICh0aGluZykgPT4ge1xuICBsZXQga2luZDtcbiAgcmV0dXJuIHRoaW5nICYmIChcbiAgICAodHlwZW9mIEZvcm1EYXRhID09PSAnZnVuY3Rpb24nICYmIHRoaW5nIGluc3RhbmNlb2YgRm9ybURhdGEpIHx8IChcbiAgICAgIGlzRnVuY3Rpb24odGhpbmcuYXBwZW5kKSAmJiAoXG4gICAgICAgIChraW5kID0ga2luZE9mKHRoaW5nKSkgPT09ICdmb3JtZGF0YScgfHxcbiAgICAgICAgLy8gZGV0ZWN0IGZvcm0tZGF0YSBpbnN0YW5jZVxuICAgICAgICAoa2luZCA9PT0gJ29iamVjdCcgJiYgaXNGdW5jdGlvbih0aGluZy50b1N0cmluZykgJiYgdGhpbmcudG9TdHJpbmcoKSA9PT0gJ1tvYmplY3QgRm9ybURhdGFdJylcbiAgICAgIClcbiAgICApXG4gIClcbn07XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBVUkxTZWFyY2hQYXJhbXMgb2JqZWN0XG4gKlxuICogQHBhcmFtIHsqfSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIFVSTFNlYXJjaFBhcmFtcyBvYmplY3QsIG90aGVyd2lzZSBmYWxzZVxuICovXG5jb25zdCBpc1VSTFNlYXJjaFBhcmFtcyA9IGtpbmRPZlRlc3QoJ1VSTFNlYXJjaFBhcmFtcycpO1xuXG4vKipcbiAqIFRyaW0gZXhjZXNzIHdoaXRlc3BhY2Ugb2ZmIHRoZSBiZWdpbm5pbmcgYW5kIGVuZCBvZiBhIHN0cmluZ1xuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIFN0cmluZyB0byB0cmltXG4gKlxuICogQHJldHVybnMge1N0cmluZ30gVGhlIFN0cmluZyBmcmVlZCBvZiBleGNlc3Mgd2hpdGVzcGFjZVxuICovXG5jb25zdCB0cmltID0gKHN0cikgPT4gc3RyLnRyaW0gP1xuICBzdHIudHJpbSgpIDogc3RyLnJlcGxhY2UoL15bXFxzXFx1RkVGRlxceEEwXSt8W1xcc1xcdUZFRkZcXHhBMF0rJC9nLCAnJyk7XG5cbi8qKlxuICogSXRlcmF0ZSBvdmVyIGFuIEFycmF5IG9yIGFuIE9iamVjdCBpbnZva2luZyBhIGZ1bmN0aW9uIGZvciBlYWNoIGl0ZW0uXG4gKlxuICogSWYgYG9iamAgaXMgYW4gQXJyYXkgY2FsbGJhY2sgd2lsbCBiZSBjYWxsZWQgcGFzc2luZ1xuICogdGhlIHZhbHVlLCBpbmRleCwgYW5kIGNvbXBsZXRlIGFycmF5IGZvciBlYWNoIGl0ZW0uXG4gKlxuICogSWYgJ29iaicgaXMgYW4gT2JqZWN0IGNhbGxiYWNrIHdpbGwgYmUgY2FsbGVkIHBhc3NpbmdcbiAqIHRoZSB2YWx1ZSwga2V5LCBhbmQgY29tcGxldGUgb2JqZWN0IGZvciBlYWNoIHByb3BlcnR5LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fEFycmF5fSBvYmogVGhlIG9iamVjdCB0byBpdGVyYXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgY2FsbGJhY2sgdG8gaW52b2tlIGZvciBlYWNoIGl0ZW1cbiAqXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFthbGxPd25LZXlzID0gZmFsc2VdXG4gKiBAcmV0dXJucyB7YW55fVxuICovXG5mdW5jdGlvbiBmb3JFYWNoKG9iaiwgZm4sIHthbGxPd25LZXlzID0gZmFsc2V9ID0ge30pIHtcbiAgLy8gRG9uJ3QgYm90aGVyIGlmIG5vIHZhbHVlIHByb3ZpZGVkXG4gIGlmIChvYmogPT09IG51bGwgfHwgdHlwZW9mIG9iaiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBsZXQgaTtcbiAgbGV0IGw7XG5cbiAgLy8gRm9yY2UgYW4gYXJyYXkgaWYgbm90IGFscmVhZHkgc29tZXRoaW5nIGl0ZXJhYmxlXG4gIGlmICh0eXBlb2Ygb2JqICE9PSAnb2JqZWN0Jykge1xuICAgIC8qZXNsaW50IG5vLXBhcmFtLXJlYXNzaWduOjAqL1xuICAgIG9iaiA9IFtvYmpdO1xuICB9XG5cbiAgaWYgKGlzQXJyYXkob2JqKSkge1xuICAgIC8vIEl0ZXJhdGUgb3ZlciBhcnJheSB2YWx1ZXNcbiAgICBmb3IgKGkgPSAwLCBsID0gb2JqLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgZm4uY2FsbChudWxsLCBvYmpbaV0sIGksIG9iaik7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIEl0ZXJhdGUgb3ZlciBvYmplY3Qga2V5c1xuICAgIGNvbnN0IGtleXMgPSBhbGxPd25LZXlzID8gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMob2JqKSA6IE9iamVjdC5rZXlzKG9iaik7XG4gICAgY29uc3QgbGVuID0ga2V5cy5sZW5ndGg7XG4gICAgbGV0IGtleTtcblxuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgIGZuLmNhbGwobnVsbCwgb2JqW2tleV0sIGtleSwgb2JqKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZmluZEtleShvYmosIGtleSkge1xuICBrZXkgPSBrZXkudG9Mb3dlckNhc2UoKTtcbiAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKG9iaik7XG4gIGxldCBpID0ga2V5cy5sZW5ndGg7XG4gIGxldCBfa2V5O1xuICB3aGlsZSAoaS0tID4gMCkge1xuICAgIF9rZXkgPSBrZXlzW2ldO1xuICAgIGlmIChrZXkgPT09IF9rZXkudG9Mb3dlckNhc2UoKSkge1xuICAgICAgcmV0dXJuIF9rZXk7XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5jb25zdCBfZ2xvYmFsID0gKCgpID0+IHtcbiAgLyplc2xpbnQgbm8tdW5kZWY6MCovXG4gIGlmICh0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gXCJ1bmRlZmluZWRcIikgcmV0dXJuIGdsb2JhbFRoaXM7XG4gIHJldHVybiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiBnbG9iYWwpXG59KSgpO1xuXG5jb25zdCBpc0NvbnRleHREZWZpbmVkID0gKGNvbnRleHQpID0+ICFpc1VuZGVmaW5lZChjb250ZXh0KSAmJiBjb250ZXh0ICE9PSBfZ2xvYmFsO1xuXG4vKipcbiAqIEFjY2VwdHMgdmFyYXJncyBleHBlY3RpbmcgZWFjaCBhcmd1bWVudCB0byBiZSBhbiBvYmplY3QsIHRoZW5cbiAqIGltbXV0YWJseSBtZXJnZXMgdGhlIHByb3BlcnRpZXMgb2YgZWFjaCBvYmplY3QgYW5kIHJldHVybnMgcmVzdWx0LlxuICpcbiAqIFdoZW4gbXVsdGlwbGUgb2JqZWN0cyBjb250YWluIHRoZSBzYW1lIGtleSB0aGUgbGF0ZXIgb2JqZWN0IGluXG4gKiB0aGUgYXJndW1lbnRzIGxpc3Qgd2lsbCB0YWtlIHByZWNlZGVuY2UuXG4gKlxuICogRXhhbXBsZTpcbiAqXG4gKiBgYGBqc1xuICogdmFyIHJlc3VsdCA9IG1lcmdlKHtmb286IDEyM30sIHtmb286IDQ1Nn0pO1xuICogY29uc29sZS5sb2cocmVzdWx0LmZvbyk7IC8vIG91dHB1dHMgNDU2XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqMSBPYmplY3QgdG8gbWVyZ2VcbiAqXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXN1bHQgb2YgYWxsIG1lcmdlIHByb3BlcnRpZXNcbiAqL1xuZnVuY3Rpb24gbWVyZ2UoLyogb2JqMSwgb2JqMiwgb2JqMywgLi4uICovKSB7XG4gIGNvbnN0IHtjYXNlbGVzc30gPSBpc0NvbnRleHREZWZpbmVkKHRoaXMpICYmIHRoaXMgfHwge307XG4gIGNvbnN0IHJlc3VsdCA9IHt9O1xuICBjb25zdCBhc3NpZ25WYWx1ZSA9ICh2YWwsIGtleSkgPT4ge1xuICAgIGNvbnN0IHRhcmdldEtleSA9IGNhc2VsZXNzICYmIGZpbmRLZXkocmVzdWx0LCBrZXkpIHx8IGtleTtcbiAgICBpZiAoaXNQbGFpbk9iamVjdChyZXN1bHRbdGFyZ2V0S2V5XSkgJiYgaXNQbGFpbk9iamVjdCh2YWwpKSB7XG4gICAgICByZXN1bHRbdGFyZ2V0S2V5XSA9IG1lcmdlKHJlc3VsdFt0YXJnZXRLZXldLCB2YWwpO1xuICAgIH0gZWxzZSBpZiAoaXNQbGFpbk9iamVjdCh2YWwpKSB7XG4gICAgICByZXN1bHRbdGFyZ2V0S2V5XSA9IG1lcmdlKHt9LCB2YWwpO1xuICAgIH0gZWxzZSBpZiAoaXNBcnJheSh2YWwpKSB7XG4gICAgICByZXN1bHRbdGFyZ2V0S2V5XSA9IHZhbC5zbGljZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHRbdGFyZ2V0S2V5XSA9IHZhbDtcbiAgICB9XG4gIH07XG5cbiAgZm9yIChsZXQgaSA9IDAsIGwgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgYXJndW1lbnRzW2ldICYmIGZvckVhY2goYXJndW1lbnRzW2ldLCBhc3NpZ25WYWx1ZSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBFeHRlbmRzIG9iamVjdCBhIGJ5IG11dGFibHkgYWRkaW5nIHRvIGl0IHRoZSBwcm9wZXJ0aWVzIG9mIG9iamVjdCBiLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBhIFRoZSBvYmplY3QgdG8gYmUgZXh0ZW5kZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSBiIFRoZSBvYmplY3QgdG8gY29weSBwcm9wZXJ0aWVzIGZyb21cbiAqIEBwYXJhbSB7T2JqZWN0fSB0aGlzQXJnIFRoZSBvYmplY3QgdG8gYmluZCBmdW5jdGlvbiB0b1xuICpcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW2FsbE93bktleXNdXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgcmVzdWx0aW5nIHZhbHVlIG9mIG9iamVjdCBhXG4gKi9cbmNvbnN0IGV4dGVuZCA9IChhLCBiLCB0aGlzQXJnLCB7YWxsT3duS2V5c309IHt9KSA9PiB7XG4gIGZvckVhY2goYiwgKHZhbCwga2V5KSA9PiB7XG4gICAgaWYgKHRoaXNBcmcgJiYgaXNGdW5jdGlvbih2YWwpKSB7XG4gICAgICBhW2tleV0gPSBiaW5kKHZhbCwgdGhpc0FyZyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFba2V5XSA9IHZhbDtcbiAgICB9XG4gIH0sIHthbGxPd25LZXlzfSk7XG4gIHJldHVybiBhO1xufTtcblxuLyoqXG4gKiBSZW1vdmUgYnl0ZSBvcmRlciBtYXJrZXIuIFRoaXMgY2F0Y2hlcyBFRiBCQiBCRiAodGhlIFVURi04IEJPTSlcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gY29udGVudCB3aXRoIEJPTVxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IGNvbnRlbnQgdmFsdWUgd2l0aG91dCBCT01cbiAqL1xuY29uc3Qgc3RyaXBCT00gPSAoY29udGVudCkgPT4ge1xuICBpZiAoY29udGVudC5jaGFyQ29kZUF0KDApID09PSAweEZFRkYpIHtcbiAgICBjb250ZW50ID0gY29udGVudC5zbGljZSgxKTtcbiAgfVxuICByZXR1cm4gY29udGVudDtcbn07XG5cbi8qKlxuICogSW5oZXJpdCB0aGUgcHJvdG90eXBlIG1ldGhvZHMgZnJvbSBvbmUgY29uc3RydWN0b3IgaW50byBhbm90aGVyXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtmdW5jdGlvbn0gc3VwZXJDb25zdHJ1Y3RvclxuICogQHBhcmFtIHtvYmplY3R9IFtwcm9wc11cbiAqIEBwYXJhbSB7b2JqZWN0fSBbZGVzY3JpcHRvcnNdXG4gKlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmNvbnN0IGluaGVyaXRzID0gKGNvbnN0cnVjdG9yLCBzdXBlckNvbnN0cnVjdG9yLCBwcm9wcywgZGVzY3JpcHRvcnMpID0+IHtcbiAgY29uc3RydWN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNvbnN0cnVjdG9yLnByb3RvdHlwZSwgZGVzY3JpcHRvcnMpO1xuICBjb25zdHJ1Y3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjb25zdHJ1Y3RvcjtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvbnN0cnVjdG9yLCAnc3VwZXInLCB7XG4gICAgdmFsdWU6IHN1cGVyQ29uc3RydWN0b3IucHJvdG90eXBlXG4gIH0pO1xuICBwcm9wcyAmJiBPYmplY3QuYXNzaWduKGNvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvcHMpO1xufTtcblxuLyoqXG4gKiBSZXNvbHZlIG9iamVjdCB3aXRoIGRlZXAgcHJvdG90eXBlIGNoYWluIHRvIGEgZmxhdCBvYmplY3RcbiAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2VPYmogc291cmNlIG9iamVjdFxuICogQHBhcmFtIHtPYmplY3R9IFtkZXN0T2JqXVxuICogQHBhcmFtIHtGdW5jdGlvbnxCb29sZWFufSBbZmlsdGVyXVxuICogQHBhcmFtIHtGdW5jdGlvbn0gW3Byb3BGaWx0ZXJdXG4gKlxuICogQHJldHVybnMge09iamVjdH1cbiAqL1xuY29uc3QgdG9GbGF0T2JqZWN0ID0gKHNvdXJjZU9iaiwgZGVzdE9iaiwgZmlsdGVyLCBwcm9wRmlsdGVyKSA9PiB7XG4gIGxldCBwcm9wcztcbiAgbGV0IGk7XG4gIGxldCBwcm9wO1xuICBjb25zdCBtZXJnZWQgPSB7fTtcblxuICBkZXN0T2JqID0gZGVzdE9iaiB8fCB7fTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWVxLW51bGwsZXFlcWVxXG4gIGlmIChzb3VyY2VPYmogPT0gbnVsbCkgcmV0dXJuIGRlc3RPYmo7XG5cbiAgZG8ge1xuICAgIHByb3BzID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoc291cmNlT2JqKTtcbiAgICBpID0gcHJvcHMubGVuZ3RoO1xuICAgIHdoaWxlIChpLS0gPiAwKSB7XG4gICAgICBwcm9wID0gcHJvcHNbaV07XG4gICAgICBpZiAoKCFwcm9wRmlsdGVyIHx8IHByb3BGaWx0ZXIocHJvcCwgc291cmNlT2JqLCBkZXN0T2JqKSkgJiYgIW1lcmdlZFtwcm9wXSkge1xuICAgICAgICBkZXN0T2JqW3Byb3BdID0gc291cmNlT2JqW3Byb3BdO1xuICAgICAgICBtZXJnZWRbcHJvcF0gPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICBzb3VyY2VPYmogPSBmaWx0ZXIgIT09IGZhbHNlICYmIGdldFByb3RvdHlwZU9mKHNvdXJjZU9iaik7XG4gIH0gd2hpbGUgKHNvdXJjZU9iaiAmJiAoIWZpbHRlciB8fCBmaWx0ZXIoc291cmNlT2JqLCBkZXN0T2JqKSkgJiYgc291cmNlT2JqICE9PSBPYmplY3QucHJvdG90eXBlKTtcblxuICByZXR1cm4gZGVzdE9iajtcbn07XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB3aGV0aGVyIGEgc3RyaW5nIGVuZHMgd2l0aCB0aGUgY2hhcmFjdGVycyBvZiBhIHNwZWNpZmllZCBzdHJpbmdcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyXG4gKiBAcGFyYW0ge1N0cmluZ30gc2VhcmNoU3RyaW5nXG4gKiBAcGFyYW0ge051bWJlcn0gW3Bvc2l0aW9uPSAwXVxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5jb25zdCBlbmRzV2l0aCA9IChzdHIsIHNlYXJjaFN0cmluZywgcG9zaXRpb24pID0+IHtcbiAgc3RyID0gU3RyaW5nKHN0cik7XG4gIGlmIChwb3NpdGlvbiA9PT0gdW5kZWZpbmVkIHx8IHBvc2l0aW9uID4gc3RyLmxlbmd0aCkge1xuICAgIHBvc2l0aW9uID0gc3RyLmxlbmd0aDtcbiAgfVxuICBwb3NpdGlvbiAtPSBzZWFyY2hTdHJpbmcubGVuZ3RoO1xuICBjb25zdCBsYXN0SW5kZXggPSBzdHIuaW5kZXhPZihzZWFyY2hTdHJpbmcsIHBvc2l0aW9uKTtcbiAgcmV0dXJuIGxhc3RJbmRleCAhPT0gLTEgJiYgbGFzdEluZGV4ID09PSBwb3NpdGlvbjtcbn07XG5cblxuLyoqXG4gKiBSZXR1cm5zIG5ldyBhcnJheSBmcm9tIGFycmF5IGxpa2Ugb2JqZWN0IG9yIG51bGwgaWYgZmFpbGVkXG4gKlxuICogQHBhcmFtIHsqfSBbdGhpbmddXG4gKlxuICogQHJldHVybnMgez9BcnJheX1cbiAqL1xuY29uc3QgdG9BcnJheSA9ICh0aGluZykgPT4ge1xuICBpZiAoIXRoaW5nKSByZXR1cm4gbnVsbDtcbiAgaWYgKGlzQXJyYXkodGhpbmcpKSByZXR1cm4gdGhpbmc7XG4gIGxldCBpID0gdGhpbmcubGVuZ3RoO1xuICBpZiAoIWlzTnVtYmVyKGkpKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgYXJyID0gbmV3IEFycmF5KGkpO1xuICB3aGlsZSAoaS0tID4gMCkge1xuICAgIGFycltpXSA9IHRoaW5nW2ldO1xuICB9XG4gIHJldHVybiBhcnI7XG59O1xuXG4vKipcbiAqIENoZWNraW5nIGlmIHRoZSBVaW50OEFycmF5IGV4aXN0cyBhbmQgaWYgaXQgZG9lcywgaXQgcmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgY2hlY2tzIGlmIHRoZVxuICogdGhpbmcgcGFzc2VkIGluIGlzIGFuIGluc3RhbmNlIG9mIFVpbnQ4QXJyYXlcbiAqXG4gKiBAcGFyYW0ge1R5cGVkQXJyYXl9XG4gKlxuICogQHJldHVybnMge0FycmF5fVxuICovXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZnVuYy1uYW1lc1xuY29uc3QgaXNUeXBlZEFycmF5ID0gKFR5cGVkQXJyYXkgPT4ge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZnVuYy1uYW1lc1xuICByZXR1cm4gdGhpbmcgPT4ge1xuICAgIHJldHVybiBUeXBlZEFycmF5ICYmIHRoaW5nIGluc3RhbmNlb2YgVHlwZWRBcnJheTtcbiAgfTtcbn0pKHR5cGVvZiBVaW50OEFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiBnZXRQcm90b3R5cGVPZihVaW50OEFycmF5KSk7XG5cbi8qKlxuICogRm9yIGVhY2ggZW50cnkgaW4gdGhlIG9iamVjdCwgY2FsbCB0aGUgZnVuY3Rpb24gd2l0aCB0aGUga2V5IGFuZCB2YWx1ZS5cbiAqXG4gKiBAcGFyYW0ge09iamVjdDxhbnksIGFueT59IG9iaiAtIFRoZSBvYmplY3QgdG8gaXRlcmF0ZSBvdmVyLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gLSBUaGUgZnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCBlbnRyeS5cbiAqXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuY29uc3QgZm9yRWFjaEVudHJ5ID0gKG9iaiwgZm4pID0+IHtcbiAgY29uc3QgZ2VuZXJhdG9yID0gb2JqICYmIG9ialtTeW1ib2wuaXRlcmF0b3JdO1xuXG4gIGNvbnN0IGl0ZXJhdG9yID0gZ2VuZXJhdG9yLmNhbGwob2JqKTtcblxuICBsZXQgcmVzdWx0O1xuXG4gIHdoaWxlICgocmVzdWx0ID0gaXRlcmF0b3IubmV4dCgpKSAmJiAhcmVzdWx0LmRvbmUpIHtcbiAgICBjb25zdCBwYWlyID0gcmVzdWx0LnZhbHVlO1xuICAgIGZuLmNhbGwob2JqLCBwYWlyWzBdLCBwYWlyWzFdKTtcbiAgfVxufTtcblxuLyoqXG4gKiBJdCB0YWtlcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhbmQgYSBzdHJpbmcsIGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIGFsbCB0aGUgbWF0Y2hlc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSByZWdFeHAgLSBUaGUgcmVndWxhciBleHByZXNzaW9uIHRvIG1hdGNoIGFnYWluc3QuXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gVGhlIHN0cmluZyB0byBzZWFyY2guXG4gKlxuICogQHJldHVybnMge0FycmF5PGJvb2xlYW4+fVxuICovXG5jb25zdCBtYXRjaEFsbCA9IChyZWdFeHAsIHN0cikgPT4ge1xuICBsZXQgbWF0Y2hlcztcbiAgY29uc3QgYXJyID0gW107XG5cbiAgd2hpbGUgKChtYXRjaGVzID0gcmVnRXhwLmV4ZWMoc3RyKSkgIT09IG51bGwpIHtcbiAgICBhcnIucHVzaChtYXRjaGVzKTtcbiAgfVxuXG4gIHJldHVybiBhcnI7XG59O1xuXG4vKiBDaGVja2luZyBpZiB0aGUga2luZE9mVGVzdCBmdW5jdGlvbiByZXR1cm5zIHRydWUgd2hlbiBwYXNzZWQgYW4gSFRNTEZvcm1FbGVtZW50LiAqL1xuY29uc3QgaXNIVE1MRm9ybSA9IGtpbmRPZlRlc3QoJ0hUTUxGb3JtRWxlbWVudCcpO1xuXG5jb25zdCB0b0NhbWVsQ2FzZSA9IHN0ciA9PiB7XG4gIHJldHVybiBzdHIudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9bLV9cXHNdKFthLXpcXGRdKShcXHcqKS9nLFxuICAgIGZ1bmN0aW9uIHJlcGxhY2VyKG0sIHAxLCBwMikge1xuICAgICAgcmV0dXJuIHAxLnRvVXBwZXJDYXNlKCkgKyBwMjtcbiAgICB9XG4gICk7XG59O1xuXG4vKiBDcmVhdGluZyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBjaGVjayBpZiBhbiBvYmplY3QgaGFzIGEgcHJvcGVydHkuICovXG5jb25zdCBoYXNPd25Qcm9wZXJ0eSA9ICgoe2hhc093blByb3BlcnR5fSkgPT4gKG9iaiwgcHJvcCkgPT4gaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKShPYmplY3QucHJvdG90eXBlKTtcblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIFJlZ0V4cCBvYmplY3RcbiAqXG4gKiBAcGFyYW0geyp9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGEgUmVnRXhwIG9iamVjdCwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmNvbnN0IGlzUmVnRXhwID0ga2luZE9mVGVzdCgnUmVnRXhwJyk7XG5cbmNvbnN0IHJlZHVjZURlc2NyaXB0b3JzID0gKG9iaiwgcmVkdWNlcikgPT4ge1xuICBjb25zdCBkZXNjcmlwdG9ycyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKG9iaik7XG4gIGNvbnN0IHJlZHVjZWREZXNjcmlwdG9ycyA9IHt9O1xuXG4gIGZvckVhY2goZGVzY3JpcHRvcnMsIChkZXNjcmlwdG9yLCBuYW1lKSA9PiB7XG4gICAgbGV0IHJldDtcbiAgICBpZiAoKHJldCA9IHJlZHVjZXIoZGVzY3JpcHRvciwgbmFtZSwgb2JqKSkgIT09IGZhbHNlKSB7XG4gICAgICByZWR1Y2VkRGVzY3JpcHRvcnNbbmFtZV0gPSByZXQgfHwgZGVzY3JpcHRvcjtcbiAgICB9XG4gIH0pO1xuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKG9iaiwgcmVkdWNlZERlc2NyaXB0b3JzKTtcbn07XG5cbi8qKlxuICogTWFrZXMgYWxsIG1ldGhvZHMgcmVhZC1vbmx5XG4gKiBAcGFyYW0ge09iamVjdH0gb2JqXG4gKi9cblxuY29uc3QgZnJlZXplTWV0aG9kcyA9IChvYmopID0+IHtcbiAgcmVkdWNlRGVzY3JpcHRvcnMob2JqLCAoZGVzY3JpcHRvciwgbmFtZSkgPT4ge1xuICAgIC8vIHNraXAgcmVzdHJpY3RlZCBwcm9wcyBpbiBzdHJpY3QgbW9kZVxuICAgIGlmIChpc0Z1bmN0aW9uKG9iaikgJiYgWydhcmd1bWVudHMnLCAnY2FsbGVyJywgJ2NhbGxlZSddLmluZGV4T2YobmFtZSkgIT09IC0xKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgdmFsdWUgPSBvYmpbbmFtZV07XG5cbiAgICBpZiAoIWlzRnVuY3Rpb24odmFsdWUpKSByZXR1cm47XG5cbiAgICBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBmYWxzZTtcblxuICAgIGlmICgnd3JpdGFibGUnIGluIGRlc2NyaXB0b3IpIHtcbiAgICAgIGRlc2NyaXB0b3Iud3JpdGFibGUgPSBmYWxzZTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIWRlc2NyaXB0b3Iuc2V0KSB7XG4gICAgICBkZXNjcmlwdG9yLnNldCA9ICgpID0+IHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ0NhbiBub3QgcmV3cml0ZSByZWFkLW9ubHkgbWV0aG9kIFxcJycgKyBuYW1lICsgJ1xcJycpO1xuICAgICAgfTtcbiAgICB9XG4gIH0pO1xufTtcblxuY29uc3QgdG9PYmplY3RTZXQgPSAoYXJyYXlPclN0cmluZywgZGVsaW1pdGVyKSA9PiB7XG4gIGNvbnN0IG9iaiA9IHt9O1xuXG4gIGNvbnN0IGRlZmluZSA9IChhcnIpID0+IHtcbiAgICBhcnIuZm9yRWFjaCh2YWx1ZSA9PiB7XG4gICAgICBvYmpbdmFsdWVdID0gdHJ1ZTtcbiAgICB9KTtcbiAgfTtcblxuICBpc0FycmF5KGFycmF5T3JTdHJpbmcpID8gZGVmaW5lKGFycmF5T3JTdHJpbmcpIDogZGVmaW5lKFN0cmluZyhhcnJheU9yU3RyaW5nKS5zcGxpdChkZWxpbWl0ZXIpKTtcblxuICByZXR1cm4gb2JqO1xufTtcblxuY29uc3Qgbm9vcCA9ICgpID0+IHt9O1xuXG5jb25zdCB0b0Zpbml0ZU51bWJlciA9ICh2YWx1ZSwgZGVmYXVsdFZhbHVlKSA9PiB7XG4gIHZhbHVlID0gK3ZhbHVlO1xuICByZXR1cm4gTnVtYmVyLmlzRmluaXRlKHZhbHVlKSA/IHZhbHVlIDogZGVmYXVsdFZhbHVlO1xufTtcblxuY29uc3QgQUxQSEEgPSAnYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXonO1xuXG5jb25zdCBESUdJVCA9ICcwMTIzNDU2Nzg5JztcblxuY29uc3QgQUxQSEFCRVQgPSB7XG4gIERJR0lULFxuICBBTFBIQSxcbiAgQUxQSEFfRElHSVQ6IEFMUEhBICsgQUxQSEEudG9VcHBlckNhc2UoKSArIERJR0lUXG59O1xuXG5jb25zdCBnZW5lcmF0ZVN0cmluZyA9IChzaXplID0gMTYsIGFscGhhYmV0ID0gQUxQSEFCRVQuQUxQSEFfRElHSVQpID0+IHtcbiAgbGV0IHN0ciA9ICcnO1xuICBjb25zdCB7bGVuZ3RofSA9IGFscGhhYmV0O1xuICB3aGlsZSAoc2l6ZS0tKSB7XG4gICAgc3RyICs9IGFscGhhYmV0W01hdGgucmFuZG9tKCkgKiBsZW5ndGh8MF07XG4gIH1cblxuICByZXR1cm4gc3RyO1xufTtcblxuLyoqXG4gKiBJZiB0aGUgdGhpbmcgaXMgYSBGb3JtRGF0YSBvYmplY3QsIHJldHVybiB0cnVlLCBvdGhlcndpc2UgcmV0dXJuIGZhbHNlLlxuICpcbiAqIEBwYXJhbSB7dW5rbm93bn0gdGhpbmcgLSBUaGUgdGhpbmcgdG8gY2hlY2suXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzU3BlY0NvbXBsaWFudEZvcm0odGhpbmcpIHtcbiAgcmV0dXJuICEhKHRoaW5nICYmIGlzRnVuY3Rpb24odGhpbmcuYXBwZW5kKSAmJiB0aGluZ1tTeW1ib2wudG9TdHJpbmdUYWddID09PSAnRm9ybURhdGEnICYmIHRoaW5nW1N5bWJvbC5pdGVyYXRvcl0pO1xufVxuXG5jb25zdCB0b0pTT05PYmplY3QgPSAob2JqKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IEFycmF5KDEwKTtcblxuICBjb25zdCB2aXNpdCA9IChzb3VyY2UsIGkpID0+IHtcblxuICAgIGlmIChpc09iamVjdChzb3VyY2UpKSB7XG4gICAgICBpZiAoc3RhY2suaW5kZXhPZihzb3VyY2UpID49IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZighKCd0b0pTT04nIGluIHNvdXJjZSkpIHtcbiAgICAgICAgc3RhY2tbaV0gPSBzb3VyY2U7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGlzQXJyYXkoc291cmNlKSA/IFtdIDoge307XG5cbiAgICAgICAgZm9yRWFjaChzb3VyY2UsICh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgICAgY29uc3QgcmVkdWNlZFZhbHVlID0gdmlzaXQodmFsdWUsIGkgKyAxKTtcbiAgICAgICAgICAhaXNVbmRlZmluZWQocmVkdWNlZFZhbHVlKSAmJiAodGFyZ2V0W2tleV0gPSByZWR1Y2VkVmFsdWUpO1xuICAgICAgICB9KTtcblxuICAgICAgICBzdGFja1tpXSA9IHVuZGVmaW5lZDtcblxuICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzb3VyY2U7XG4gIH07XG5cbiAgcmV0dXJuIHZpc2l0KG9iaiwgMCk7XG59O1xuXG5jb25zdCBpc0FzeW5jRm4gPSBraW5kT2ZUZXN0KCdBc3luY0Z1bmN0aW9uJyk7XG5cbmNvbnN0IGlzVGhlbmFibGUgPSAodGhpbmcpID0+XG4gIHRoaW5nICYmIChpc09iamVjdCh0aGluZykgfHwgaXNGdW5jdGlvbih0aGluZykpICYmIGlzRnVuY3Rpb24odGhpbmcudGhlbikgJiYgaXNGdW5jdGlvbih0aGluZy5jYXRjaCk7XG5cbnZhciB1dGlscyQxID0ge1xuICBpc0FycmF5LFxuICBpc0FycmF5QnVmZmVyLFxuICBpc0J1ZmZlcixcbiAgaXNGb3JtRGF0YSxcbiAgaXNBcnJheUJ1ZmZlclZpZXcsXG4gIGlzU3RyaW5nLFxuICBpc051bWJlcixcbiAgaXNCb29sZWFuLFxuICBpc09iamVjdCxcbiAgaXNQbGFpbk9iamVjdCxcbiAgaXNVbmRlZmluZWQsXG4gIGlzRGF0ZSxcbiAgaXNGaWxlLFxuICBpc0Jsb2IsXG4gIGlzUmVnRXhwLFxuICBpc0Z1bmN0aW9uLFxuICBpc1N0cmVhbSxcbiAgaXNVUkxTZWFyY2hQYXJhbXMsXG4gIGlzVHlwZWRBcnJheSxcbiAgaXNGaWxlTGlzdCxcbiAgZm9yRWFjaCxcbiAgbWVyZ2UsXG4gIGV4dGVuZCxcbiAgdHJpbSxcbiAgc3RyaXBCT00sXG4gIGluaGVyaXRzLFxuICB0b0ZsYXRPYmplY3QsXG4gIGtpbmRPZixcbiAga2luZE9mVGVzdCxcbiAgZW5kc1dpdGgsXG4gIHRvQXJyYXksXG4gIGZvckVhY2hFbnRyeSxcbiAgbWF0Y2hBbGwsXG4gIGlzSFRNTEZvcm0sXG4gIGhhc093blByb3BlcnR5LFxuICBoYXNPd25Qcm9wOiBoYXNPd25Qcm9wZXJ0eSwgLy8gYW4gYWxpYXMgdG8gYXZvaWQgRVNMaW50IG5vLXByb3RvdHlwZS1idWlsdGlucyBkZXRlY3Rpb25cbiAgcmVkdWNlRGVzY3JpcHRvcnMsXG4gIGZyZWV6ZU1ldGhvZHMsXG4gIHRvT2JqZWN0U2V0LFxuICB0b0NhbWVsQ2FzZSxcbiAgbm9vcCxcbiAgdG9GaW5pdGVOdW1iZXIsXG4gIGZpbmRLZXksXG4gIGdsb2JhbDogX2dsb2JhbCxcbiAgaXNDb250ZXh0RGVmaW5lZCxcbiAgQUxQSEFCRVQsXG4gIGdlbmVyYXRlU3RyaW5nLFxuICBpc1NwZWNDb21wbGlhbnRGb3JtLFxuICB0b0pTT05PYmplY3QsXG4gIGlzQXN5bmNGbixcbiAgaXNUaGVuYWJsZVxufTtcblxuLyoqXG4gKiBDcmVhdGUgYW4gRXJyb3Igd2l0aCB0aGUgc3BlY2lmaWVkIG1lc3NhZ2UsIGNvbmZpZywgZXJyb3IgY29kZSwgcmVxdWVzdCBhbmQgcmVzcG9uc2UuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgVGhlIGVycm9yIG1lc3NhZ2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gW2NvZGVdIFRoZSBlcnJvciBjb2RlIChmb3IgZXhhbXBsZSwgJ0VDT05OQUJPUlRFRCcpLlxuICogQHBhcmFtIHtPYmplY3R9IFtjb25maWddIFRoZSBjb25maWcuXG4gKiBAcGFyYW0ge09iamVjdH0gW3JlcXVlc3RdIFRoZSByZXF1ZXN0LlxuICogQHBhcmFtIHtPYmplY3R9IFtyZXNwb25zZV0gVGhlIHJlc3BvbnNlLlxuICpcbiAqIEByZXR1cm5zIHtFcnJvcn0gVGhlIGNyZWF0ZWQgZXJyb3IuXG4gKi9cbmZ1bmN0aW9uIEF4aW9zRXJyb3IobWVzc2FnZSwgY29kZSwgY29uZmlnLCByZXF1ZXN0LCByZXNwb25zZSkge1xuICBFcnJvci5jYWxsKHRoaXMpO1xuXG4gIGlmIChFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSkge1xuICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMuc3RhY2sgPSAobmV3IEVycm9yKCkpLnN0YWNrO1xuICB9XG5cbiAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgdGhpcy5uYW1lID0gJ0F4aW9zRXJyb3InO1xuICBjb2RlICYmICh0aGlzLmNvZGUgPSBjb2RlKTtcbiAgY29uZmlnICYmICh0aGlzLmNvbmZpZyA9IGNvbmZpZyk7XG4gIHJlcXVlc3QgJiYgKHRoaXMucmVxdWVzdCA9IHJlcXVlc3QpO1xuICByZXNwb25zZSAmJiAodGhpcy5yZXNwb25zZSA9IHJlc3BvbnNlKTtcbn1cblxudXRpbHMkMS5pbmhlcml0cyhBeGlvc0Vycm9yLCBFcnJvciwge1xuICB0b0pTT046IGZ1bmN0aW9uIHRvSlNPTigpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLy8gU3RhbmRhcmRcbiAgICAgIG1lc3NhZ2U6IHRoaXMubWVzc2FnZSxcbiAgICAgIG5hbWU6IHRoaXMubmFtZSxcbiAgICAgIC8vIE1pY3Jvc29mdFxuICAgICAgZGVzY3JpcHRpb246IHRoaXMuZGVzY3JpcHRpb24sXG4gICAgICBudW1iZXI6IHRoaXMubnVtYmVyLFxuICAgICAgLy8gTW96aWxsYVxuICAgICAgZmlsZU5hbWU6IHRoaXMuZmlsZU5hbWUsXG4gICAgICBsaW5lTnVtYmVyOiB0aGlzLmxpbmVOdW1iZXIsXG4gICAgICBjb2x1bW5OdW1iZXI6IHRoaXMuY29sdW1uTnVtYmVyLFxuICAgICAgc3RhY2s6IHRoaXMuc3RhY2ssXG4gICAgICAvLyBBeGlvc1xuICAgICAgY29uZmlnOiB1dGlscyQxLnRvSlNPTk9iamVjdCh0aGlzLmNvbmZpZyksXG4gICAgICBjb2RlOiB0aGlzLmNvZGUsXG4gICAgICBzdGF0dXM6IHRoaXMucmVzcG9uc2UgJiYgdGhpcy5yZXNwb25zZS5zdGF0dXMgPyB0aGlzLnJlc3BvbnNlLnN0YXR1cyA6IG51bGxcbiAgICB9O1xuICB9XG59KTtcblxuY29uc3QgcHJvdG90eXBlJDEgPSBBeGlvc0Vycm9yLnByb3RvdHlwZTtcbmNvbnN0IGRlc2NyaXB0b3JzID0ge307XG5cbltcbiAgJ0VSUl9CQURfT1BUSU9OX1ZBTFVFJyxcbiAgJ0VSUl9CQURfT1BUSU9OJyxcbiAgJ0VDT05OQUJPUlRFRCcsXG4gICdFVElNRURPVVQnLFxuICAnRVJSX05FVFdPUksnLFxuICAnRVJSX0ZSX1RPT19NQU5ZX1JFRElSRUNUUycsXG4gICdFUlJfREVQUkVDQVRFRCcsXG4gICdFUlJfQkFEX1JFU1BPTlNFJyxcbiAgJ0VSUl9CQURfUkVRVUVTVCcsXG4gICdFUlJfQ0FOQ0VMRUQnLFxuICAnRVJSX05PVF9TVVBQT1JUJyxcbiAgJ0VSUl9JTlZBTElEX1VSTCdcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBmdW5jLW5hbWVzXG5dLmZvckVhY2goY29kZSA9PiB7XG4gIGRlc2NyaXB0b3JzW2NvZGVdID0ge3ZhbHVlOiBjb2RlfTtcbn0pO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydGllcyhBeGlvc0Vycm9yLCBkZXNjcmlwdG9ycyk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkocHJvdG90eXBlJDEsICdpc0F4aW9zRXJyb3InLCB7dmFsdWU6IHRydWV9KTtcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGZ1bmMtbmFtZXNcbkF4aW9zRXJyb3IuZnJvbSA9IChlcnJvciwgY29kZSwgY29uZmlnLCByZXF1ZXN0LCByZXNwb25zZSwgY3VzdG9tUHJvcHMpID0+IHtcbiAgY29uc3QgYXhpb3NFcnJvciA9IE9iamVjdC5jcmVhdGUocHJvdG90eXBlJDEpO1xuXG4gIHV0aWxzJDEudG9GbGF0T2JqZWN0KGVycm9yLCBheGlvc0Vycm9yLCBmdW5jdGlvbiBmaWx0ZXIob2JqKSB7XG4gICAgcmV0dXJuIG9iaiAhPT0gRXJyb3IucHJvdG90eXBlO1xuICB9LCBwcm9wID0+IHtcbiAgICByZXR1cm4gcHJvcCAhPT0gJ2lzQXhpb3NFcnJvcic7XG4gIH0pO1xuXG4gIEF4aW9zRXJyb3IuY2FsbChheGlvc0Vycm9yLCBlcnJvci5tZXNzYWdlLCBjb2RlLCBjb25maWcsIHJlcXVlc3QsIHJlc3BvbnNlKTtcblxuICBheGlvc0Vycm9yLmNhdXNlID0gZXJyb3I7XG5cbiAgYXhpb3NFcnJvci5uYW1lID0gZXJyb3IubmFtZTtcblxuICBjdXN0b21Qcm9wcyAmJiBPYmplY3QuYXNzaWduKGF4aW9zRXJyb3IsIGN1c3RvbVByb3BzKTtcblxuICByZXR1cm4gYXhpb3NFcnJvcjtcbn07XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBzdHJpY3RcbnZhciBodHRwQWRhcHRlciA9IG51bGw7XG5cbi8qKlxuICogRGV0ZXJtaW5lcyBpZiB0aGUgZ2l2ZW4gdGhpbmcgaXMgYSBhcnJheSBvciBqcyBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRoaW5nIC0gVGhlIG9iamVjdCBvciBhcnJheSB0byBiZSB2aXNpdGVkLlxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5mdW5jdGlvbiBpc1Zpc2l0YWJsZSh0aGluZykge1xuICByZXR1cm4gdXRpbHMkMS5pc1BsYWluT2JqZWN0KHRoaW5nKSB8fCB1dGlscyQxLmlzQXJyYXkodGhpbmcpO1xufVxuXG4vKipcbiAqIEl0IHJlbW92ZXMgdGhlIGJyYWNrZXRzIGZyb20gdGhlIGVuZCBvZiBhIHN0cmluZ1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUga2V5IG9mIHRoZSBwYXJhbWV0ZXIuXG4gKlxuICogQHJldHVybnMge3N0cmluZ30gdGhlIGtleSB3aXRob3V0IHRoZSBicmFja2V0cy5cbiAqL1xuZnVuY3Rpb24gcmVtb3ZlQnJhY2tldHMoa2V5KSB7XG4gIHJldHVybiB1dGlscyQxLmVuZHNXaXRoKGtleSwgJ1tdJykgPyBrZXkuc2xpY2UoMCwgLTIpIDoga2V5O1xufVxuXG4vKipcbiAqIEl0IHRha2VzIGEgcGF0aCwgYSBrZXksIGFuZCBhIGJvb2xlYW4sIGFuZCByZXR1cm5zIGEgc3RyaW5nXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggLSBUaGUgcGF0aCB0byB0aGUgY3VycmVudCBrZXkuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGtleSBvZiB0aGUgY3VycmVudCBvYmplY3QgYmVpbmcgaXRlcmF0ZWQgb3Zlci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkb3RzIC0gSWYgdHJ1ZSwgdGhlIGtleSB3aWxsIGJlIHJlbmRlcmVkIHdpdGggZG90cyBpbnN0ZWFkIG9mIGJyYWNrZXRzLlxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBwYXRoIHRvIHRoZSBjdXJyZW50IGtleS5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyS2V5KHBhdGgsIGtleSwgZG90cykge1xuICBpZiAoIXBhdGgpIHJldHVybiBrZXk7XG4gIHJldHVybiBwYXRoLmNvbmNhdChrZXkpLm1hcChmdW5jdGlvbiBlYWNoKHRva2VuLCBpKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgdG9rZW4gPSByZW1vdmVCcmFja2V0cyh0b2tlbik7XG4gICAgcmV0dXJuICFkb3RzICYmIGkgPyAnWycgKyB0b2tlbiArICddJyA6IHRva2VuO1xuICB9KS5qb2luKGRvdHMgPyAnLicgOiAnJyk7XG59XG5cbi8qKlxuICogSWYgdGhlIGFycmF5IGlzIGFuIGFycmF5IGFuZCBub25lIG9mIGl0cyBlbGVtZW50cyBhcmUgdmlzaXRhYmxlLCB0aGVuIGl0J3MgYSBmbGF0IGFycmF5LlxuICpcbiAqIEBwYXJhbSB7QXJyYXk8YW55Pn0gYXJyIC0gVGhlIGFycmF5IHRvIGNoZWNrXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzRmxhdEFycmF5KGFycikge1xuICByZXR1cm4gdXRpbHMkMS5pc0FycmF5KGFycikgJiYgIWFyci5zb21lKGlzVmlzaXRhYmxlKTtcbn1cblxuY29uc3QgcHJlZGljYXRlcyA9IHV0aWxzJDEudG9GbGF0T2JqZWN0KHV0aWxzJDEsIHt9LCBudWxsLCBmdW5jdGlvbiBmaWx0ZXIocHJvcCkge1xuICByZXR1cm4gL15pc1tBLVpdLy50ZXN0KHByb3ApO1xufSk7XG5cbi8qKlxuICogQ29udmVydCBhIGRhdGEgb2JqZWN0IHRvIEZvcm1EYXRhXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9ialxuICogQHBhcmFtIHs/T2JqZWN0fSBbZm9ybURhdGFdXG4gKiBAcGFyYW0gez9PYmplY3R9IFtvcHRpb25zXVxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMudmlzaXRvcl1cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMubWV0YVRva2VucyA9IHRydWVdXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmRvdHMgPSBmYWxzZV1cbiAqIEBwYXJhbSB7P0Jvb2xlYW59IFtvcHRpb25zLmluZGV4ZXMgPSBmYWxzZV1cbiAqXG4gKiBAcmV0dXJucyB7T2JqZWN0fVxuICoqL1xuXG4vKipcbiAqIEl0IGNvbnZlcnRzIGFuIG9iamVjdCBpbnRvIGEgRm9ybURhdGEgb2JqZWN0XG4gKlxuICogQHBhcmFtIHtPYmplY3Q8YW55LCBhbnk+fSBvYmogLSBUaGUgb2JqZWN0IHRvIGNvbnZlcnQgdG8gZm9ybSBkYXRhLlxuICogQHBhcmFtIHtzdHJpbmd9IGZvcm1EYXRhIC0gVGhlIEZvcm1EYXRhIG9iamVjdCB0byBhcHBlbmQgdG8uXG4gKiBAcGFyYW0ge09iamVjdDxzdHJpbmcsIGFueT59IG9wdGlvbnNcbiAqXG4gKiBAcmV0dXJuc1xuICovXG5mdW5jdGlvbiB0b0Zvcm1EYXRhKG9iaiwgZm9ybURhdGEsIG9wdGlvbnMpIHtcbiAgaWYgKCF1dGlscyQxLmlzT2JqZWN0KG9iaikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0YXJnZXQgbXVzdCBiZSBhbiBvYmplY3QnKTtcbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wYXJhbS1yZWFzc2lnblxuICBmb3JtRGF0YSA9IGZvcm1EYXRhIHx8IG5ldyAoRm9ybURhdGEpKCk7XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG4gIG9wdGlvbnMgPSB1dGlscyQxLnRvRmxhdE9iamVjdChvcHRpb25zLCB7XG4gICAgbWV0YVRva2VuczogdHJ1ZSxcbiAgICBkb3RzOiBmYWxzZSxcbiAgICBpbmRleGVzOiBmYWxzZVxuICB9LCBmYWxzZSwgZnVuY3Rpb24gZGVmaW5lZChvcHRpb24sIHNvdXJjZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1lcS1udWxsLGVxZXFlcVxuICAgIHJldHVybiAhdXRpbHMkMS5pc1VuZGVmaW5lZChzb3VyY2Vbb3B0aW9uXSk7XG4gIH0pO1xuXG4gIGNvbnN0IG1ldGFUb2tlbnMgPSBvcHRpb25zLm1ldGFUb2tlbnM7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11c2UtYmVmb3JlLWRlZmluZVxuICBjb25zdCB2aXNpdG9yID0gb3B0aW9ucy52aXNpdG9yIHx8IGRlZmF1bHRWaXNpdG9yO1xuICBjb25zdCBkb3RzID0gb3B0aW9ucy5kb3RzO1xuICBjb25zdCBpbmRleGVzID0gb3B0aW9ucy5pbmRleGVzO1xuICBjb25zdCBfQmxvYiA9IG9wdGlvbnMuQmxvYiB8fCB0eXBlb2YgQmxvYiAhPT0gJ3VuZGVmaW5lZCcgJiYgQmxvYjtcbiAgY29uc3QgdXNlQmxvYiA9IF9CbG9iICYmIHV0aWxzJDEuaXNTcGVjQ29tcGxpYW50Rm9ybShmb3JtRGF0YSk7XG5cbiAgaWYgKCF1dGlscyQxLmlzRnVuY3Rpb24odmlzaXRvcikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2aXNpdG9yIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICB9XG5cbiAgZnVuY3Rpb24gY29udmVydFZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSBudWxsKSByZXR1cm4gJyc7XG5cbiAgICBpZiAodXRpbHMkMS5pc0RhdGUodmFsdWUpKSB7XG4gICAgICByZXR1cm4gdmFsdWUudG9JU09TdHJpbmcoKTtcbiAgICB9XG5cbiAgICBpZiAoIXVzZUJsb2IgJiYgdXRpbHMkMS5pc0Jsb2IodmFsdWUpKSB7XG4gICAgICB0aHJvdyBuZXcgQXhpb3NFcnJvcignQmxvYiBpcyBub3Qgc3VwcG9ydGVkLiBVc2UgYSBCdWZmZXIgaW5zdGVhZC4nKTtcbiAgICB9XG5cbiAgICBpZiAodXRpbHMkMS5pc0FycmF5QnVmZmVyKHZhbHVlKSB8fCB1dGlscyQxLmlzVHlwZWRBcnJheSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB1c2VCbG9iICYmIHR5cGVvZiBCbG9iID09PSAnZnVuY3Rpb24nID8gbmV3IEJsb2IoW3ZhbHVlXSkgOiBCdWZmZXIuZnJvbSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIERlZmF1bHQgdmlzaXRvci5cbiAgICpcbiAgICogQHBhcmFtIHsqfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ3xOdW1iZXJ9IGtleVxuICAgKiBAcGFyYW0ge0FycmF5PFN0cmluZ3xOdW1iZXI+fSBwYXRoXG4gICAqIEB0aGlzIHtGb3JtRGF0YX1cbiAgICpcbiAgICogQHJldHVybnMge2Jvb2xlYW59IHJldHVybiB0cnVlIHRvIHZpc2l0IHRoZSBlYWNoIHByb3Agb2YgdGhlIHZhbHVlIHJlY3Vyc2l2ZWx5XG4gICAqL1xuICBmdW5jdGlvbiBkZWZhdWx0VmlzaXRvcih2YWx1ZSwga2V5LCBwYXRoKSB7XG4gICAgbGV0IGFyciA9IHZhbHVlO1xuXG4gICAgaWYgKHZhbHVlICYmICFwYXRoICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmICh1dGlscyQxLmVuZHNXaXRoKGtleSwgJ3t9JykpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgICAgIGtleSA9IG1ldGFUb2tlbnMgPyBrZXkgOiBrZXkuc2xpY2UoMCwgLTIpO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcGFyYW0tcmVhc3NpZ25cbiAgICAgICAgdmFsdWUgPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAodXRpbHMkMS5pc0FycmF5KHZhbHVlKSAmJiBpc0ZsYXRBcnJheSh2YWx1ZSkpIHx8XG4gICAgICAgICgodXRpbHMkMS5pc0ZpbGVMaXN0KHZhbHVlKSB8fCB1dGlscyQxLmVuZHNXaXRoKGtleSwgJ1tdJykpICYmIChhcnIgPSB1dGlscyQxLnRvQXJyYXkodmFsdWUpKVxuICAgICAgICApKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wYXJhbS1yZWFzc2lnblxuICAgICAgICBrZXkgPSByZW1vdmVCcmFja2V0cyhrZXkpO1xuXG4gICAgICAgIGFyci5mb3JFYWNoKGZ1bmN0aW9uIGVhY2goZWwsIGluZGV4KSB7XG4gICAgICAgICAgISh1dGlscyQxLmlzVW5kZWZpbmVkKGVsKSB8fCBlbCA9PT0gbnVsbCkgJiYgZm9ybURhdGEuYXBwZW5kKFxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5lc3RlZC10ZXJuYXJ5XG4gICAgICAgICAgICBpbmRleGVzID09PSB0cnVlID8gcmVuZGVyS2V5KFtrZXldLCBpbmRleCwgZG90cykgOiAoaW5kZXhlcyA9PT0gbnVsbCA/IGtleSA6IGtleSArICdbXScpLFxuICAgICAgICAgICAgY29udmVydFZhbHVlKGVsKVxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGlzVmlzaXRhYmxlKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgZm9ybURhdGEuYXBwZW5kKHJlbmRlcktleShwYXRoLCBrZXksIGRvdHMpLCBjb252ZXJ0VmFsdWUodmFsdWUpKTtcblxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IHN0YWNrID0gW107XG5cbiAgY29uc3QgZXhwb3NlZEhlbHBlcnMgPSBPYmplY3QuYXNzaWduKHByZWRpY2F0ZXMsIHtcbiAgICBkZWZhdWx0VmlzaXRvcixcbiAgICBjb252ZXJ0VmFsdWUsXG4gICAgaXNWaXNpdGFibGVcbiAgfSk7XG5cbiAgZnVuY3Rpb24gYnVpbGQodmFsdWUsIHBhdGgpIHtcbiAgICBpZiAodXRpbHMkMS5pc1VuZGVmaW5lZCh2YWx1ZSkpIHJldHVybjtcblxuICAgIGlmIChzdGFjay5pbmRleE9mKHZhbHVlKSAhPT0gLTEpIHtcbiAgICAgIHRocm93IEVycm9yKCdDaXJjdWxhciByZWZlcmVuY2UgZGV0ZWN0ZWQgaW4gJyArIHBhdGguam9pbignLicpKTtcbiAgICB9XG5cbiAgICBzdGFjay5wdXNoKHZhbHVlKTtcblxuICAgIHV0aWxzJDEuZm9yRWFjaCh2YWx1ZSwgZnVuY3Rpb24gZWFjaChlbCwga2V5KSB7XG4gICAgICBjb25zdCByZXN1bHQgPSAhKHV0aWxzJDEuaXNVbmRlZmluZWQoZWwpIHx8IGVsID09PSBudWxsKSAmJiB2aXNpdG9yLmNhbGwoXG4gICAgICAgIGZvcm1EYXRhLCBlbCwgdXRpbHMkMS5pc1N0cmluZyhrZXkpID8ga2V5LnRyaW0oKSA6IGtleSwgcGF0aCwgZXhwb3NlZEhlbHBlcnNcbiAgICAgICk7XG5cbiAgICAgIGlmIChyZXN1bHQgPT09IHRydWUpIHtcbiAgICAgICAgYnVpbGQoZWwsIHBhdGggPyBwYXRoLmNvbmNhdChrZXkpIDogW2tleV0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgc3RhY2sucG9wKCk7XG4gIH1cblxuICBpZiAoIXV0aWxzJDEuaXNPYmplY3Qob2JqKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RhdGEgbXVzdCBiZSBhbiBvYmplY3QnKTtcbiAgfVxuXG4gIGJ1aWxkKG9iaik7XG5cbiAgcmV0dXJuIGZvcm1EYXRhO1xufVxuXG4vKipcbiAqIEl0IGVuY29kZXMgYSBzdHJpbmcgYnkgcmVwbGFjaW5nIGFsbCBjaGFyYWN0ZXJzIHRoYXQgYXJlIG5vdCBpbiB0aGUgdW5yZXNlcnZlZCBzZXQgd2l0aFxuICogdGhlaXIgcGVyY2VudC1lbmNvZGVkIGVxdWl2YWxlbnRzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFRoZSBzdHJpbmcgdG8gZW5jb2RlLlxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBlbmNvZGVkIHN0cmluZy5cbiAqL1xuZnVuY3Rpb24gZW5jb2RlJDEoc3RyKSB7XG4gIGNvbnN0IGNoYXJNYXAgPSB7XG4gICAgJyEnOiAnJTIxJyxcbiAgICBcIidcIjogJyUyNycsXG4gICAgJygnOiAnJTI4JyxcbiAgICAnKSc6ICclMjknLFxuICAgICd+JzogJyU3RScsXG4gICAgJyUyMCc6ICcrJyxcbiAgICAnJTAwJzogJ1xceDAwJ1xuICB9O1xuICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KHN0cikucmVwbGFjZSgvWyEnKCl+XXwlMjB8JTAwL2csIGZ1bmN0aW9uIHJlcGxhY2VyKG1hdGNoKSB7XG4gICAgcmV0dXJuIGNoYXJNYXBbbWF0Y2hdO1xuICB9KTtcbn1cblxuLyoqXG4gKiBJdCB0YWtlcyBhIHBhcmFtcyBvYmplY3QgYW5kIGNvbnZlcnRzIGl0IHRvIGEgRm9ybURhdGEgb2JqZWN0XG4gKlxuICogQHBhcmFtIHtPYmplY3Q8c3RyaW5nLCBhbnk+fSBwYXJhbXMgLSBUaGUgcGFyYW1ldGVycyB0byBiZSBjb252ZXJ0ZWQgdG8gYSBGb3JtRGF0YSBvYmplY3QuXG4gKiBAcGFyYW0ge09iamVjdDxzdHJpbmcsIGFueT59IG9wdGlvbnMgLSBUaGUgb3B0aW9ucyBvYmplY3QgcGFzc2VkIHRvIHRoZSBBeGlvcyBjb25zdHJ1Y3Rvci5cbiAqXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gQXhpb3NVUkxTZWFyY2hQYXJhbXMocGFyYW1zLCBvcHRpb25zKSB7XG4gIHRoaXMuX3BhaXJzID0gW107XG5cbiAgcGFyYW1zICYmIHRvRm9ybURhdGEocGFyYW1zLCB0aGlzLCBvcHRpb25zKTtcbn1cblxuY29uc3QgcHJvdG90eXBlID0gQXhpb3NVUkxTZWFyY2hQYXJhbXMucHJvdG90eXBlO1xuXG5wcm90b3R5cGUuYXBwZW5kID0gZnVuY3Rpb24gYXBwZW5kKG5hbWUsIHZhbHVlKSB7XG4gIHRoaXMuX3BhaXJzLnB1c2goW25hbWUsIHZhbHVlXSk7XG59O1xuXG5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZyhlbmNvZGVyKSB7XG4gIGNvbnN0IF9lbmNvZGUgPSBlbmNvZGVyID8gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gZW5jb2Rlci5jYWxsKHRoaXMsIHZhbHVlLCBlbmNvZGUkMSk7XG4gIH0gOiBlbmNvZGUkMTtcblxuICByZXR1cm4gdGhpcy5fcGFpcnMubWFwKGZ1bmN0aW9uIGVhY2gocGFpcikge1xuICAgIHJldHVybiBfZW5jb2RlKHBhaXJbMF0pICsgJz0nICsgX2VuY29kZShwYWlyWzFdKTtcbiAgfSwgJycpLmpvaW4oJyYnKTtcbn07XG5cbi8qKlxuICogSXQgcmVwbGFjZXMgYWxsIGluc3RhbmNlcyBvZiB0aGUgY2hhcmFjdGVycyBgOmAsIGAkYCwgYCxgLCBgK2AsIGBbYCwgYW5kIGBdYCB3aXRoIHRoZWlyXG4gKiBVUkkgZW5jb2RlZCBjb3VudGVycGFydHNcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsIFRoZSB2YWx1ZSB0byBiZSBlbmNvZGVkLlxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBlbmNvZGVkIHZhbHVlLlxuICovXG5mdW5jdGlvbiBlbmNvZGUodmFsKSB7XG4gIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQodmFsKS5cbiAgICByZXBsYWNlKC8lM0EvZ2ksICc6JykuXG4gICAgcmVwbGFjZSgvJTI0L2csICckJykuXG4gICAgcmVwbGFjZSgvJTJDL2dpLCAnLCcpLlxuICAgIHJlcGxhY2UoLyUyMC9nLCAnKycpLlxuICAgIHJlcGxhY2UoLyU1Qi9naSwgJ1snKS5cbiAgICByZXBsYWNlKC8lNUQvZ2ksICddJyk7XG59XG5cbi8qKlxuICogQnVpbGQgYSBVUkwgYnkgYXBwZW5kaW5nIHBhcmFtcyB0byB0aGUgZW5kXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHVybCBUaGUgYmFzZSBvZiB0aGUgdXJsIChlLmcuLCBodHRwOi8vd3d3Lmdvb2dsZS5jb20pXG4gKiBAcGFyYW0ge29iamVjdH0gW3BhcmFtc10gVGhlIHBhcmFtcyB0byBiZSBhcHBlbmRlZFxuICogQHBhcmFtIHs/b2JqZWN0fSBvcHRpb25zXG4gKlxuICogQHJldHVybnMge3N0cmluZ30gVGhlIGZvcm1hdHRlZCB1cmxcbiAqL1xuZnVuY3Rpb24gYnVpbGRVUkwodXJsLCBwYXJhbXMsIG9wdGlvbnMpIHtcbiAgLyplc2xpbnQgbm8tcGFyYW0tcmVhc3NpZ246MCovXG4gIGlmICghcGFyYW1zKSB7XG4gICAgcmV0dXJuIHVybDtcbiAgfVxuICBcbiAgY29uc3QgX2VuY29kZSA9IG9wdGlvbnMgJiYgb3B0aW9ucy5lbmNvZGUgfHwgZW5jb2RlO1xuXG4gIGNvbnN0IHNlcmlhbGl6ZUZuID0gb3B0aW9ucyAmJiBvcHRpb25zLnNlcmlhbGl6ZTtcblxuICBsZXQgc2VyaWFsaXplZFBhcmFtcztcblxuICBpZiAoc2VyaWFsaXplRm4pIHtcbiAgICBzZXJpYWxpemVkUGFyYW1zID0gc2VyaWFsaXplRm4ocGFyYW1zLCBvcHRpb25zKTtcbiAgfSBlbHNlIHtcbiAgICBzZXJpYWxpemVkUGFyYW1zID0gdXRpbHMkMS5pc1VSTFNlYXJjaFBhcmFtcyhwYXJhbXMpID9cbiAgICAgIHBhcmFtcy50b1N0cmluZygpIDpcbiAgICAgIG5ldyBBeGlvc1VSTFNlYXJjaFBhcmFtcyhwYXJhbXMsIG9wdGlvbnMpLnRvU3RyaW5nKF9lbmNvZGUpO1xuICB9XG5cbiAgaWYgKHNlcmlhbGl6ZWRQYXJhbXMpIHtcbiAgICBjb25zdCBoYXNobWFya0luZGV4ID0gdXJsLmluZGV4T2YoXCIjXCIpO1xuXG4gICAgaWYgKGhhc2htYXJrSW5kZXggIT09IC0xKSB7XG4gICAgICB1cmwgPSB1cmwuc2xpY2UoMCwgaGFzaG1hcmtJbmRleCk7XG4gICAgfVxuICAgIHVybCArPSAodXJsLmluZGV4T2YoJz8nKSA9PT0gLTEgPyAnPycgOiAnJicpICsgc2VyaWFsaXplZFBhcmFtcztcbiAgfVxuXG4gIHJldHVybiB1cmw7XG59XG5cbmNsYXNzIEludGVyY2VwdG9yTWFuYWdlciB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuaGFuZGxlcnMgPSBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBuZXcgaW50ZXJjZXB0b3IgdG8gdGhlIHN0YWNrXG4gICAqXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bGZpbGxlZCBUaGUgZnVuY3Rpb24gdG8gaGFuZGxlIGB0aGVuYCBmb3IgYSBgUHJvbWlzZWBcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gcmVqZWN0ZWQgVGhlIGZ1bmN0aW9uIHRvIGhhbmRsZSBgcmVqZWN0YCBmb3IgYSBgUHJvbWlzZWBcbiAgICpcbiAgICogQHJldHVybiB7TnVtYmVyfSBBbiBJRCB1c2VkIHRvIHJlbW92ZSBpbnRlcmNlcHRvciBsYXRlclxuICAgKi9cbiAgdXNlKGZ1bGZpbGxlZCwgcmVqZWN0ZWQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLmhhbmRsZXJzLnB1c2goe1xuICAgICAgZnVsZmlsbGVkLFxuICAgICAgcmVqZWN0ZWQsXG4gICAgICBzeW5jaHJvbm91czogb3B0aW9ucyA/IG9wdGlvbnMuc3luY2hyb25vdXMgOiBmYWxzZSxcbiAgICAgIHJ1bldoZW46IG9wdGlvbnMgPyBvcHRpb25zLnJ1bldoZW4gOiBudWxsXG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMuaGFuZGxlcnMubGVuZ3RoIC0gMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYW4gaW50ZXJjZXB0b3IgZnJvbSB0aGUgc3RhY2tcbiAgICpcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGlkIFRoZSBJRCB0aGF0IHdhcyByZXR1cm5lZCBieSBgdXNlYFxuICAgKlxuICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gYHRydWVgIGlmIHRoZSBpbnRlcmNlcHRvciB3YXMgcmVtb3ZlZCwgYGZhbHNlYCBvdGhlcndpc2VcbiAgICovXG4gIGVqZWN0KGlkKSB7XG4gICAgaWYgKHRoaXMuaGFuZGxlcnNbaWRdKSB7XG4gICAgICB0aGlzLmhhbmRsZXJzW2lkXSA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENsZWFyIGFsbCBpbnRlcmNlcHRvcnMgZnJvbSB0aGUgc3RhY2tcbiAgICpcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBjbGVhcigpIHtcbiAgICBpZiAodGhpcy5oYW5kbGVycykge1xuICAgICAgdGhpcy5oYW5kbGVycyA9IFtdO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJdGVyYXRlIG92ZXIgYWxsIHRoZSByZWdpc3RlcmVkIGludGVyY2VwdG9yc1xuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciBza2lwcGluZyBvdmVyIGFueVxuICAgKiBpbnRlcmNlcHRvcnMgdGhhdCBtYXkgaGF2ZSBiZWNvbWUgYG51bGxgIGNhbGxpbmcgYGVqZWN0YC5cbiAgICpcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIGNhbGwgZm9yIGVhY2ggaW50ZXJjZXB0b3JcbiAgICpcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBmb3JFYWNoKGZuKSB7XG4gICAgdXRpbHMkMS5mb3JFYWNoKHRoaXMuaGFuZGxlcnMsIGZ1bmN0aW9uIGZvckVhY2hIYW5kbGVyKGgpIHtcbiAgICAgIGlmIChoICE9PSBudWxsKSB7XG4gICAgICAgIGZuKGgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG5cbnZhciB0cmFuc2l0aW9uYWxEZWZhdWx0cyA9IHtcbiAgc2lsZW50SlNPTlBhcnNpbmc6IHRydWUsXG4gIGZvcmNlZEpTT05QYXJzaW5nOiB0cnVlLFxuICBjbGFyaWZ5VGltZW91dEVycm9yOiBmYWxzZVxufTtcblxudmFyIFVSTFNlYXJjaFBhcmFtcyQxID0gdHlwZW9mIFVSTFNlYXJjaFBhcmFtcyAhPT0gJ3VuZGVmaW5lZCcgPyBVUkxTZWFyY2hQYXJhbXMgOiBBeGlvc1VSTFNlYXJjaFBhcmFtcztcblxudmFyIEZvcm1EYXRhJDEgPSB0eXBlb2YgRm9ybURhdGEgIT09ICd1bmRlZmluZWQnID8gRm9ybURhdGEgOiBudWxsO1xuXG52YXIgQmxvYiQxID0gdHlwZW9mIEJsb2IgIT09ICd1bmRlZmluZWQnID8gQmxvYiA6IG51bGw7XG5cbnZhciBwbGF0Zm9ybSQxID0ge1xuICBpc0Jyb3dzZXI6IHRydWUsXG4gIGNsYXNzZXM6IHtcbiAgICBVUkxTZWFyY2hQYXJhbXM6IFVSTFNlYXJjaFBhcmFtcyQxLFxuICAgIEZvcm1EYXRhOiBGb3JtRGF0YSQxLFxuICAgIEJsb2I6IEJsb2IkMVxuICB9LFxuICBwcm90b2NvbHM6IFsnaHR0cCcsICdodHRwcycsICdmaWxlJywgJ2Jsb2InLCAndXJsJywgJ2RhdGEnXVxufTtcblxuY29uc3QgaGFzQnJvd3NlckVudiA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCc7XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIHdlJ3JlIHJ1bm5pbmcgaW4gYSBzdGFuZGFyZCBicm93c2VyIGVudmlyb25tZW50XG4gKlxuICogVGhpcyBhbGxvd3MgYXhpb3MgdG8gcnVuIGluIGEgd2ViIHdvcmtlciwgYW5kIHJlYWN0LW5hdGl2ZS5cbiAqIEJvdGggZW52aXJvbm1lbnRzIHN1cHBvcnQgWE1MSHR0cFJlcXVlc3QsIGJ1dCBub3QgZnVsbHkgc3RhbmRhcmQgZ2xvYmFscy5cbiAqXG4gKiB3ZWIgd29ya2VyczpcbiAqICB0eXBlb2Ygd2luZG93IC0+IHVuZGVmaW5lZFxuICogIHR5cGVvZiBkb2N1bWVudCAtPiB1bmRlZmluZWRcbiAqXG4gKiByZWFjdC1uYXRpdmU6XG4gKiAgbmF2aWdhdG9yLnByb2R1Y3QgLT4gJ1JlYWN0TmF0aXZlJ1xuICogbmF0aXZlc2NyaXB0XG4gKiAgbmF2aWdhdG9yLnByb2R1Y3QgLT4gJ05hdGl2ZVNjcmlwdCcgb3IgJ05TJ1xuICpcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5jb25zdCBoYXNTdGFuZGFyZEJyb3dzZXJFbnYgPSAoXG4gIChwcm9kdWN0KSA9PiB7XG4gICAgcmV0dXJuIGhhc0Jyb3dzZXJFbnYgJiYgWydSZWFjdE5hdGl2ZScsICdOYXRpdmVTY3JpcHQnLCAnTlMnXS5pbmRleE9mKHByb2R1Y3QpIDwgMFxuICB9KSh0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJiBuYXZpZ2F0b3IucHJvZHVjdCk7XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIHdlJ3JlIHJ1bm5pbmcgaW4gYSBzdGFuZGFyZCBicm93c2VyIHdlYldvcmtlciBlbnZpcm9ubWVudFxuICpcbiAqIEFsdGhvdWdoIHRoZSBgaXNTdGFuZGFyZEJyb3dzZXJFbnZgIG1ldGhvZCBpbmRpY2F0ZXMgdGhhdFxuICogYGFsbG93cyBheGlvcyB0byBydW4gaW4gYSB3ZWIgd29ya2VyYCwgdGhlIFdlYldvcmtlciB3aWxsIHN0aWxsIGJlXG4gKiBmaWx0ZXJlZCBvdXQgZHVlIHRvIGl0cyBqdWRnbWVudCBzdGFuZGFyZFxuICogYHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCdgLlxuICogVGhpcyBsZWFkcyB0byBhIHByb2JsZW0gd2hlbiBheGlvcyBwb3N0IGBGb3JtRGF0YWAgaW4gd2ViV29ya2VyXG4gKi9cbmNvbnN0IGhhc1N0YW5kYXJkQnJvd3NlcldlYldvcmtlckVudiA9ICgoKSA9PiB7XG4gIHJldHVybiAoXG4gICAgdHlwZW9mIFdvcmtlckdsb2JhbFNjb3BlICE9PSAndW5kZWZpbmVkJyAmJlxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlZlxuICAgIHNlbGYgaW5zdGFuY2VvZiBXb3JrZXJHbG9iYWxTY29wZSAmJlxuICAgIHR5cGVvZiBzZWxmLmltcG9ydFNjcmlwdHMgPT09ICdmdW5jdGlvbidcbiAgKTtcbn0pKCk7XG5cbnZhciB1dGlscyA9IC8qI19fUFVSRV9fKi9PYmplY3QuZnJlZXplKHtcbiAgX19wcm90b19fOiBudWxsLFxuICBoYXNCcm93c2VyRW52OiBoYXNCcm93c2VyRW52LFxuICBoYXNTdGFuZGFyZEJyb3dzZXJFbnY6IGhhc1N0YW5kYXJkQnJvd3NlckVudixcbiAgaGFzU3RhbmRhcmRCcm93c2VyV2ViV29ya2VyRW52OiBoYXNTdGFuZGFyZEJyb3dzZXJXZWJXb3JrZXJFbnZcbn0pO1xuXG52YXIgcGxhdGZvcm0gPSB7XG4gIC4uLnV0aWxzLFxuICAuLi5wbGF0Zm9ybSQxXG59O1xuXG5mdW5jdGlvbiB0b1VSTEVuY29kZWRGb3JtKGRhdGEsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIHRvRm9ybURhdGEoZGF0YSwgbmV3IHBsYXRmb3JtLmNsYXNzZXMuVVJMU2VhcmNoUGFyYW1zKCksIE9iamVjdC5hc3NpZ24oe1xuICAgIHZpc2l0b3I6IGZ1bmN0aW9uKHZhbHVlLCBrZXksIHBhdGgsIGhlbHBlcnMpIHtcbiAgICAgIGlmIChwbGF0Zm9ybS5pc05vZGUgJiYgdXRpbHMkMS5pc0J1ZmZlcih2YWx1ZSkpIHtcbiAgICAgICAgdGhpcy5hcHBlbmQoa2V5LCB2YWx1ZS50b1N0cmluZygnYmFzZTY0JykpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBoZWxwZXJzLmRlZmF1bHRWaXNpdG9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9LCBvcHRpb25zKSk7XG59XG5cbi8qKlxuICogSXQgdGFrZXMgYSBzdHJpbmcgbGlrZSBgZm9vW3hdW3ldW3pdYCBhbmQgcmV0dXJucyBhbiBhcnJheSBsaWtlIGBbJ2ZvbycsICd4JywgJ3knLCAneiddXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICpcbiAqIEByZXR1cm5zIEFuIGFycmF5IG9mIHN0cmluZ3MuXG4gKi9cbmZ1bmN0aW9uIHBhcnNlUHJvcFBhdGgobmFtZSkge1xuICAvLyBmb29beF1beV1bel1cbiAgLy8gZm9vLngueS56XG4gIC8vIGZvby14LXktelxuICAvLyBmb28geCB5IHpcbiAgcmV0dXJuIHV0aWxzJDEubWF0Y2hBbGwoL1xcdyt8XFxbKFxcdyopXS9nLCBuYW1lKS5tYXAobWF0Y2ggPT4ge1xuICAgIHJldHVybiBtYXRjaFswXSA9PT0gJ1tdJyA/ICcnIDogbWF0Y2hbMV0gfHwgbWF0Y2hbMF07XG4gIH0pO1xufVxuXG4vKipcbiAqIENvbnZlcnQgYW4gYXJyYXkgdG8gYW4gb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7QXJyYXk8YW55Pn0gYXJyIC0gVGhlIGFycmF5IHRvIGNvbnZlcnQgdG8gYW4gb2JqZWN0LlxuICpcbiAqIEByZXR1cm5zIEFuIG9iamVjdCB3aXRoIHRoZSBzYW1lIGtleXMgYW5kIHZhbHVlcyBhcyB0aGUgYXJyYXkuXG4gKi9cbmZ1bmN0aW9uIGFycmF5VG9PYmplY3QoYXJyKSB7XG4gIGNvbnN0IG9iaiA9IHt9O1xuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoYXJyKTtcbiAgbGV0IGk7XG4gIGNvbnN0IGxlbiA9IGtleXMubGVuZ3RoO1xuICBsZXQga2V5O1xuICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICBrZXkgPSBrZXlzW2ldO1xuICAgIG9ialtrZXldID0gYXJyW2tleV07XG4gIH1cbiAgcmV0dXJuIG9iajtcbn1cblxuLyoqXG4gKiBJdCB0YWtlcyBhIEZvcm1EYXRhIG9iamVjdCBhbmQgcmV0dXJucyBhIEphdmFTY3JpcHQgb2JqZWN0XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGZvcm1EYXRhIFRoZSBGb3JtRGF0YSBvYmplY3QgdG8gY29udmVydCB0byBKU09OLlxuICpcbiAqIEByZXR1cm5zIHtPYmplY3Q8c3RyaW5nLCBhbnk+IHwgbnVsbH0gVGhlIGNvbnZlcnRlZCBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIGZvcm1EYXRhVG9KU09OKGZvcm1EYXRhKSB7XG4gIGZ1bmN0aW9uIGJ1aWxkUGF0aChwYXRoLCB2YWx1ZSwgdGFyZ2V0LCBpbmRleCkge1xuICAgIGxldCBuYW1lID0gcGF0aFtpbmRleCsrXTtcblxuICAgIGlmIChuYW1lID09PSAnX19wcm90b19fJykgcmV0dXJuIHRydWU7XG5cbiAgICBjb25zdCBpc051bWVyaWNLZXkgPSBOdW1iZXIuaXNGaW5pdGUoK25hbWUpO1xuICAgIGNvbnN0IGlzTGFzdCA9IGluZGV4ID49IHBhdGgubGVuZ3RoO1xuICAgIG5hbWUgPSAhbmFtZSAmJiB1dGlscyQxLmlzQXJyYXkodGFyZ2V0KSA/IHRhcmdldC5sZW5ndGggOiBuYW1lO1xuXG4gICAgaWYgKGlzTGFzdCkge1xuICAgICAgaWYgKHV0aWxzJDEuaGFzT3duUHJvcCh0YXJnZXQsIG5hbWUpKSB7XG4gICAgICAgIHRhcmdldFtuYW1lXSA9IFt0YXJnZXRbbmFtZV0sIHZhbHVlXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRhcmdldFtuYW1lXSA9IHZhbHVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gIWlzTnVtZXJpY0tleTtcbiAgICB9XG5cbiAgICBpZiAoIXRhcmdldFtuYW1lXSB8fCAhdXRpbHMkMS5pc09iamVjdCh0YXJnZXRbbmFtZV0pKSB7XG4gICAgICB0YXJnZXRbbmFtZV0gPSBbXTtcbiAgICB9XG5cbiAgICBjb25zdCByZXN1bHQgPSBidWlsZFBhdGgocGF0aCwgdmFsdWUsIHRhcmdldFtuYW1lXSwgaW5kZXgpO1xuXG4gICAgaWYgKHJlc3VsdCAmJiB1dGlscyQxLmlzQXJyYXkodGFyZ2V0W25hbWVdKSkge1xuICAgICAgdGFyZ2V0W25hbWVdID0gYXJyYXlUb09iamVjdCh0YXJnZXRbbmFtZV0pO1xuICAgIH1cblxuICAgIHJldHVybiAhaXNOdW1lcmljS2V5O1xuICB9XG5cbiAgaWYgKHV0aWxzJDEuaXNGb3JtRGF0YShmb3JtRGF0YSkgJiYgdXRpbHMkMS5pc0Z1bmN0aW9uKGZvcm1EYXRhLmVudHJpZXMpKSB7XG4gICAgY29uc3Qgb2JqID0ge307XG5cbiAgICB1dGlscyQxLmZvckVhY2hFbnRyeShmb3JtRGF0YSwgKG5hbWUsIHZhbHVlKSA9PiB7XG4gICAgICBidWlsZFBhdGgocGFyc2VQcm9wUGF0aChuYW1lKSwgdmFsdWUsIG9iaiwgMCk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gb2JqO1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogSXQgdGFrZXMgYSBzdHJpbmcsIHRyaWVzIHRvIHBhcnNlIGl0LCBhbmQgaWYgaXQgZmFpbHMsIGl0IHJldHVybnMgdGhlIHN0cmluZ2lmaWVkIHZlcnNpb25cbiAqIG9mIHRoZSBpbnB1dFxuICpcbiAqIEBwYXJhbSB7YW55fSByYXdWYWx1ZSAtIFRoZSB2YWx1ZSB0byBiZSBzdHJpbmdpZmllZC5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IHBhcnNlciAtIEEgZnVuY3Rpb24gdGhhdCBwYXJzZXMgYSBzdHJpbmcgaW50byBhIEphdmFTY3JpcHQgb2JqZWN0LlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZW5jb2RlciAtIEEgZnVuY3Rpb24gdGhhdCB0YWtlcyBhIHZhbHVlIGFuZCByZXR1cm5zIGEgc3RyaW5nLlxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IEEgc3RyaW5naWZpZWQgdmVyc2lvbiBvZiB0aGUgcmF3VmFsdWUuXG4gKi9cbmZ1bmN0aW9uIHN0cmluZ2lmeVNhZmVseShyYXdWYWx1ZSwgcGFyc2VyLCBlbmNvZGVyKSB7XG4gIGlmICh1dGlscyQxLmlzU3RyaW5nKHJhd1ZhbHVlKSkge1xuICAgIHRyeSB7XG4gICAgICAocGFyc2VyIHx8IEpTT04ucGFyc2UpKHJhd1ZhbHVlKTtcbiAgICAgIHJldHVybiB1dGlscyQxLnRyaW0ocmF3VmFsdWUpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLm5hbWUgIT09ICdTeW50YXhFcnJvcicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gKGVuY29kZXIgfHwgSlNPTi5zdHJpbmdpZnkpKHJhd1ZhbHVlKTtcbn1cblxuY29uc3QgZGVmYXVsdHMgPSB7XG5cbiAgdHJhbnNpdGlvbmFsOiB0cmFuc2l0aW9uYWxEZWZhdWx0cyxcblxuICBhZGFwdGVyOiBbJ3hocicsICdodHRwJ10sXG5cbiAgdHJhbnNmb3JtUmVxdWVzdDogW2Z1bmN0aW9uIHRyYW5zZm9ybVJlcXVlc3QoZGF0YSwgaGVhZGVycykge1xuICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gaGVhZGVycy5nZXRDb250ZW50VHlwZSgpIHx8ICcnO1xuICAgIGNvbnN0IGhhc0pTT05Db250ZW50VHlwZSA9IGNvbnRlbnRUeXBlLmluZGV4T2YoJ2FwcGxpY2F0aW9uL2pzb24nKSA+IC0xO1xuICAgIGNvbnN0IGlzT2JqZWN0UGF5bG9hZCA9IHV0aWxzJDEuaXNPYmplY3QoZGF0YSk7XG5cbiAgICBpZiAoaXNPYmplY3RQYXlsb2FkICYmIHV0aWxzJDEuaXNIVE1MRm9ybShkYXRhKSkge1xuICAgICAgZGF0YSA9IG5ldyBGb3JtRGF0YShkYXRhKTtcbiAgICB9XG5cbiAgICBjb25zdCBpc0Zvcm1EYXRhID0gdXRpbHMkMS5pc0Zvcm1EYXRhKGRhdGEpO1xuXG4gICAgaWYgKGlzRm9ybURhdGEpIHtcbiAgICAgIHJldHVybiBoYXNKU09OQ29udGVudFR5cGUgPyBKU09OLnN0cmluZ2lmeShmb3JtRGF0YVRvSlNPTihkYXRhKSkgOiBkYXRhO1xuICAgIH1cblxuICAgIGlmICh1dGlscyQxLmlzQXJyYXlCdWZmZXIoZGF0YSkgfHxcbiAgICAgIHV0aWxzJDEuaXNCdWZmZXIoZGF0YSkgfHxcbiAgICAgIHV0aWxzJDEuaXNTdHJlYW0oZGF0YSkgfHxcbiAgICAgIHV0aWxzJDEuaXNGaWxlKGRhdGEpIHx8XG4gICAgICB1dGlscyQxLmlzQmxvYihkYXRhKVxuICAgICkge1xuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICAgIGlmICh1dGlscyQxLmlzQXJyYXlCdWZmZXJWaWV3KGRhdGEpKSB7XG4gICAgICByZXR1cm4gZGF0YS5idWZmZXI7XG4gICAgfVxuICAgIGlmICh1dGlscyQxLmlzVVJMU2VhcmNoUGFyYW1zKGRhdGEpKSB7XG4gICAgICBoZWFkZXJzLnNldENvbnRlbnRUeXBlKCdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7Y2hhcnNldD11dGYtOCcsIGZhbHNlKTtcbiAgICAgIHJldHVybiBkYXRhLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgbGV0IGlzRmlsZUxpc3Q7XG5cbiAgICBpZiAoaXNPYmplY3RQYXlsb2FkKSB7XG4gICAgICBpZiAoY29udGVudFR5cGUuaW5kZXhPZignYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJykgPiAtMSkge1xuICAgICAgICByZXR1cm4gdG9VUkxFbmNvZGVkRm9ybShkYXRhLCB0aGlzLmZvcm1TZXJpYWxpemVyKS50b1N0cmluZygpO1xuICAgICAgfVxuXG4gICAgICBpZiAoKGlzRmlsZUxpc3QgPSB1dGlscyQxLmlzRmlsZUxpc3QoZGF0YSkpIHx8IGNvbnRlbnRUeXBlLmluZGV4T2YoJ211bHRpcGFydC9mb3JtLWRhdGEnKSA+IC0xKSB7XG4gICAgICAgIGNvbnN0IF9Gb3JtRGF0YSA9IHRoaXMuZW52ICYmIHRoaXMuZW52LkZvcm1EYXRhO1xuXG4gICAgICAgIHJldHVybiB0b0Zvcm1EYXRhKFxuICAgICAgICAgIGlzRmlsZUxpc3QgPyB7J2ZpbGVzW10nOiBkYXRhfSA6IGRhdGEsXG4gICAgICAgICAgX0Zvcm1EYXRhICYmIG5ldyBfRm9ybURhdGEoKSxcbiAgICAgICAgICB0aGlzLmZvcm1TZXJpYWxpemVyXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGlzT2JqZWN0UGF5bG9hZCB8fCBoYXNKU09OQ29udGVudFR5cGUgKSB7XG4gICAgICBoZWFkZXJzLnNldENvbnRlbnRUeXBlKCdhcHBsaWNhdGlvbi9qc29uJywgZmFsc2UpO1xuICAgICAgcmV0dXJuIHN0cmluZ2lmeVNhZmVseShkYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YTtcbiAgfV0sXG5cbiAgdHJhbnNmb3JtUmVzcG9uc2U6IFtmdW5jdGlvbiB0cmFuc2Zvcm1SZXNwb25zZShkYXRhKSB7XG4gICAgY29uc3QgdHJhbnNpdGlvbmFsID0gdGhpcy50cmFuc2l0aW9uYWwgfHwgZGVmYXVsdHMudHJhbnNpdGlvbmFsO1xuICAgIGNvbnN0IGZvcmNlZEpTT05QYXJzaW5nID0gdHJhbnNpdGlvbmFsICYmIHRyYW5zaXRpb25hbC5mb3JjZWRKU09OUGFyc2luZztcbiAgICBjb25zdCBKU09OUmVxdWVzdGVkID0gdGhpcy5yZXNwb25zZVR5cGUgPT09ICdqc29uJztcblxuICAgIGlmIChkYXRhICYmIHV0aWxzJDEuaXNTdHJpbmcoZGF0YSkgJiYgKChmb3JjZWRKU09OUGFyc2luZyAmJiAhdGhpcy5yZXNwb25zZVR5cGUpIHx8IEpTT05SZXF1ZXN0ZWQpKSB7XG4gICAgICBjb25zdCBzaWxlbnRKU09OUGFyc2luZyA9IHRyYW5zaXRpb25hbCAmJiB0cmFuc2l0aW9uYWwuc2lsZW50SlNPTlBhcnNpbmc7XG4gICAgICBjb25zdCBzdHJpY3RKU09OUGFyc2luZyA9ICFzaWxlbnRKU09OUGFyc2luZyAmJiBKU09OUmVxdWVzdGVkO1xuXG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKHN0cmljdEpTT05QYXJzaW5nKSB7XG4gICAgICAgICAgaWYgKGUubmFtZSA9PT0gJ1N5bnRheEVycm9yJykge1xuICAgICAgICAgICAgdGhyb3cgQXhpb3NFcnJvci5mcm9tKGUsIEF4aW9zRXJyb3IuRVJSX0JBRF9SRVNQT05TRSwgdGhpcywgbnVsbCwgdGhpcy5yZXNwb25zZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YTtcbiAgfV0sXG5cbiAgLyoqXG4gICAqIEEgdGltZW91dCBpbiBtaWxsaXNlY29uZHMgdG8gYWJvcnQgYSByZXF1ZXN0LiBJZiBzZXQgdG8gMCAoZGVmYXVsdCkgYVxuICAgKiB0aW1lb3V0IGlzIG5vdCBjcmVhdGVkLlxuICAgKi9cbiAgdGltZW91dDogMCxcblxuICB4c3JmQ29va2llTmFtZTogJ1hTUkYtVE9LRU4nLFxuICB4c3JmSGVhZGVyTmFtZTogJ1gtWFNSRi1UT0tFTicsXG5cbiAgbWF4Q29udGVudExlbmd0aDogLTEsXG4gIG1heEJvZHlMZW5ndGg6IC0xLFxuXG4gIGVudjoge1xuICAgIEZvcm1EYXRhOiBwbGF0Zm9ybS5jbGFzc2VzLkZvcm1EYXRhLFxuICAgIEJsb2I6IHBsYXRmb3JtLmNsYXNzZXMuQmxvYlxuICB9LFxuXG4gIHZhbGlkYXRlU3RhdHVzOiBmdW5jdGlvbiB2YWxpZGF0ZVN0YXR1cyhzdGF0dXMpIHtcbiAgICByZXR1cm4gc3RhdHVzID49IDIwMCAmJiBzdGF0dXMgPCAzMDA7XG4gIH0sXG5cbiAgaGVhZGVyczoge1xuICAgIGNvbW1vbjoge1xuICAgICAgJ0FjY2VwdCc6ICdhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L3BsYWluLCAqLyonLFxuICAgICAgJ0NvbnRlbnQtVHlwZSc6IHVuZGVmaW5lZFxuICAgIH1cbiAgfVxufTtcblxudXRpbHMkMS5mb3JFYWNoKFsnZGVsZXRlJywgJ2dldCcsICdoZWFkJywgJ3Bvc3QnLCAncHV0JywgJ3BhdGNoJ10sIChtZXRob2QpID0+IHtcbiAgZGVmYXVsdHMuaGVhZGVyc1ttZXRob2RdID0ge307XG59KTtcblxudmFyIGRlZmF1bHRzJDEgPSBkZWZhdWx0cztcblxuLy8gUmF3QXhpb3NIZWFkZXJzIHdob3NlIGR1cGxpY2F0ZXMgYXJlIGlnbm9yZWQgYnkgbm9kZVxuLy8gYy5mLiBodHRwczovL25vZGVqcy5vcmcvYXBpL2h0dHAuaHRtbCNodHRwX21lc3NhZ2VfaGVhZGVyc1xuY29uc3QgaWdub3JlRHVwbGljYXRlT2YgPSB1dGlscyQxLnRvT2JqZWN0U2V0KFtcbiAgJ2FnZScsICdhdXRob3JpemF0aW9uJywgJ2NvbnRlbnQtbGVuZ3RoJywgJ2NvbnRlbnQtdHlwZScsICdldGFnJyxcbiAgJ2V4cGlyZXMnLCAnZnJvbScsICdob3N0JywgJ2lmLW1vZGlmaWVkLXNpbmNlJywgJ2lmLXVubW9kaWZpZWQtc2luY2UnLFxuICAnbGFzdC1tb2RpZmllZCcsICdsb2NhdGlvbicsICdtYXgtZm9yd2FyZHMnLCAncHJveHktYXV0aG9yaXphdGlvbicsXG4gICdyZWZlcmVyJywgJ3JldHJ5LWFmdGVyJywgJ3VzZXItYWdlbnQnXG5dKTtcblxuLyoqXG4gKiBQYXJzZSBoZWFkZXJzIGludG8gYW4gb2JqZWN0XG4gKlxuICogYGBgXG4gKiBEYXRlOiBXZWQsIDI3IEF1ZyAyMDE0IDA4OjU4OjQ5IEdNVFxuICogQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uXG4gKiBDb25uZWN0aW9uOiBrZWVwLWFsaXZlXG4gKiBUcmFuc2Zlci1FbmNvZGluZzogY2h1bmtlZFxuICogYGBgXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHJhd0hlYWRlcnMgSGVhZGVycyBuZWVkaW5nIHRvIGJlIHBhcnNlZFxuICpcbiAqIEByZXR1cm5zIHtPYmplY3R9IEhlYWRlcnMgcGFyc2VkIGludG8gYW4gb2JqZWN0XG4gKi9cbnZhciBwYXJzZUhlYWRlcnMgPSByYXdIZWFkZXJzID0+IHtcbiAgY29uc3QgcGFyc2VkID0ge307XG4gIGxldCBrZXk7XG4gIGxldCB2YWw7XG4gIGxldCBpO1xuXG4gIHJhd0hlYWRlcnMgJiYgcmF3SGVhZGVycy5zcGxpdCgnXFxuJykuZm9yRWFjaChmdW5jdGlvbiBwYXJzZXIobGluZSkge1xuICAgIGkgPSBsaW5lLmluZGV4T2YoJzonKTtcbiAgICBrZXkgPSBsaW5lLnN1YnN0cmluZygwLCBpKS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICB2YWwgPSBsaW5lLnN1YnN0cmluZyhpICsgMSkudHJpbSgpO1xuXG4gICAgaWYgKCFrZXkgfHwgKHBhcnNlZFtrZXldICYmIGlnbm9yZUR1cGxpY2F0ZU9mW2tleV0pKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGtleSA9PT0gJ3NldC1jb29raWUnKSB7XG4gICAgICBpZiAocGFyc2VkW2tleV0pIHtcbiAgICAgICAgcGFyc2VkW2tleV0ucHVzaCh2YWwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFyc2VkW2tleV0gPSBbdmFsXTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcGFyc2VkW2tleV0gPSBwYXJzZWRba2V5XSA/IHBhcnNlZFtrZXldICsgJywgJyArIHZhbCA6IHZhbDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBwYXJzZWQ7XG59O1xuXG5jb25zdCAkaW50ZXJuYWxzID0gU3ltYm9sKCdpbnRlcm5hbHMnKTtcblxuZnVuY3Rpb24gbm9ybWFsaXplSGVhZGVyKGhlYWRlcikge1xuICByZXR1cm4gaGVhZGVyICYmIFN0cmluZyhoZWFkZXIpLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBub3JtYWxpemVWYWx1ZSh2YWx1ZSkge1xuICBpZiAodmFsdWUgPT09IGZhbHNlIHx8IHZhbHVlID09IG51bGwpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICByZXR1cm4gdXRpbHMkMS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlLm1hcChub3JtYWxpemVWYWx1ZSkgOiBTdHJpbmcodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBwYXJzZVRva2VucyhzdHIpIHtcbiAgY29uc3QgdG9rZW5zID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgY29uc3QgdG9rZW5zUkUgPSAvKFteXFxzLDs9XSspXFxzKig/Oj1cXHMqKFteLDtdKykpPy9nO1xuICBsZXQgbWF0Y2g7XG5cbiAgd2hpbGUgKChtYXRjaCA9IHRva2Vuc1JFLmV4ZWMoc3RyKSkpIHtcbiAgICB0b2tlbnNbbWF0Y2hbMV1dID0gbWF0Y2hbMl07XG4gIH1cblxuICByZXR1cm4gdG9rZW5zO1xufVxuXG5jb25zdCBpc1ZhbGlkSGVhZGVyTmFtZSA9IChzdHIpID0+IC9eWy1fYS16QS1aMC05XmB8fiwhIyQlJicqKy5dKyQvLnRlc3Qoc3RyLnRyaW0oKSk7XG5cbmZ1bmN0aW9uIG1hdGNoSGVhZGVyVmFsdWUoY29udGV4dCwgdmFsdWUsIGhlYWRlciwgZmlsdGVyLCBpc0hlYWRlck5hbWVGaWx0ZXIpIHtcbiAgaWYgKHV0aWxzJDEuaXNGdW5jdGlvbihmaWx0ZXIpKSB7XG4gICAgcmV0dXJuIGZpbHRlci5jYWxsKHRoaXMsIHZhbHVlLCBoZWFkZXIpO1xuICB9XG5cbiAgaWYgKGlzSGVhZGVyTmFtZUZpbHRlcikge1xuICAgIHZhbHVlID0gaGVhZGVyO1xuICB9XG5cbiAgaWYgKCF1dGlscyQxLmlzU3RyaW5nKHZhbHVlKSkgcmV0dXJuO1xuXG4gIGlmICh1dGlscyQxLmlzU3RyaW5nKGZpbHRlcikpIHtcbiAgICByZXR1cm4gdmFsdWUuaW5kZXhPZihmaWx0ZXIpICE9PSAtMTtcbiAgfVxuXG4gIGlmICh1dGlscyQxLmlzUmVnRXhwKGZpbHRlcikpIHtcbiAgICByZXR1cm4gZmlsdGVyLnRlc3QodmFsdWUpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZvcm1hdEhlYWRlcihoZWFkZXIpIHtcbiAgcmV0dXJuIGhlYWRlci50cmltKClcbiAgICAudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC8oW2EtelxcZF0pKFxcdyopL2csICh3LCBjaGFyLCBzdHIpID0+IHtcbiAgICAgIHJldHVybiBjaGFyLnRvVXBwZXJDYXNlKCkgKyBzdHI7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkQWNjZXNzb3JzKG9iaiwgaGVhZGVyKSB7XG4gIGNvbnN0IGFjY2Vzc29yTmFtZSA9IHV0aWxzJDEudG9DYW1lbENhc2UoJyAnICsgaGVhZGVyKTtcblxuICBbJ2dldCcsICdzZXQnLCAnaGFzJ10uZm9yRWFjaChtZXRob2ROYW1lID0+IHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBtZXRob2ROYW1lICsgYWNjZXNzb3JOYW1lLCB7XG4gICAgICB2YWx1ZTogZnVuY3Rpb24oYXJnMSwgYXJnMiwgYXJnMykge1xuICAgICAgICByZXR1cm4gdGhpc1ttZXRob2ROYW1lXS5jYWxsKHRoaXMsIGhlYWRlciwgYXJnMSwgYXJnMiwgYXJnMyk7XG4gICAgICB9LFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSk7XG4gIH0pO1xufVxuXG5jbGFzcyBBeGlvc0hlYWRlcnMge1xuICBjb25zdHJ1Y3RvcihoZWFkZXJzKSB7XG4gICAgaGVhZGVycyAmJiB0aGlzLnNldChoZWFkZXJzKTtcbiAgfVxuXG4gIHNldChoZWFkZXIsIHZhbHVlT3JSZXdyaXRlLCByZXdyaXRlKSB7XG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG5cbiAgICBmdW5jdGlvbiBzZXRIZWFkZXIoX3ZhbHVlLCBfaGVhZGVyLCBfcmV3cml0ZSkge1xuICAgICAgY29uc3QgbEhlYWRlciA9IG5vcm1hbGl6ZUhlYWRlcihfaGVhZGVyKTtcblxuICAgICAgaWYgKCFsSGVhZGVyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaGVhZGVyIG5hbWUgbXVzdCBiZSBhIG5vbi1lbXB0eSBzdHJpbmcnKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qga2V5ID0gdXRpbHMkMS5maW5kS2V5KHNlbGYsIGxIZWFkZXIpO1xuXG4gICAgICBpZigha2V5IHx8IHNlbGZba2V5XSA9PT0gdW5kZWZpbmVkIHx8IF9yZXdyaXRlID09PSB0cnVlIHx8IChfcmV3cml0ZSA9PT0gdW5kZWZpbmVkICYmIHNlbGZba2V5XSAhPT0gZmFsc2UpKSB7XG4gICAgICAgIHNlbGZba2V5IHx8IF9oZWFkZXJdID0gbm9ybWFsaXplVmFsdWUoX3ZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBzZXRIZWFkZXJzID0gKGhlYWRlcnMsIF9yZXdyaXRlKSA9PlxuICAgICAgdXRpbHMkMS5mb3JFYWNoKGhlYWRlcnMsIChfdmFsdWUsIF9oZWFkZXIpID0+IHNldEhlYWRlcihfdmFsdWUsIF9oZWFkZXIsIF9yZXdyaXRlKSk7XG5cbiAgICBpZiAodXRpbHMkMS5pc1BsYWluT2JqZWN0KGhlYWRlcikgfHwgaGVhZGVyIGluc3RhbmNlb2YgdGhpcy5jb25zdHJ1Y3Rvcikge1xuICAgICAgc2V0SGVhZGVycyhoZWFkZXIsIHZhbHVlT3JSZXdyaXRlKTtcbiAgICB9IGVsc2UgaWYodXRpbHMkMS5pc1N0cmluZyhoZWFkZXIpICYmIChoZWFkZXIgPSBoZWFkZXIudHJpbSgpKSAmJiAhaXNWYWxpZEhlYWRlck5hbWUoaGVhZGVyKSkge1xuICAgICAgc2V0SGVhZGVycyhwYXJzZUhlYWRlcnMoaGVhZGVyKSwgdmFsdWVPclJld3JpdGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBoZWFkZXIgIT0gbnVsbCAmJiBzZXRIZWFkZXIodmFsdWVPclJld3JpdGUsIGhlYWRlciwgcmV3cml0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBnZXQoaGVhZGVyLCBwYXJzZXIpIHtcbiAgICBoZWFkZXIgPSBub3JtYWxpemVIZWFkZXIoaGVhZGVyKTtcblxuICAgIGlmIChoZWFkZXIpIHtcbiAgICAgIGNvbnN0IGtleSA9IHV0aWxzJDEuZmluZEtleSh0aGlzLCBoZWFkZXIpO1xuXG4gICAgICBpZiAoa2V5KSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gdGhpc1trZXldO1xuXG4gICAgICAgIGlmICghcGFyc2VyKSB7XG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcnNlciA9PT0gdHJ1ZSkge1xuICAgICAgICAgIHJldHVybiBwYXJzZVRva2Vucyh2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodXRpbHMkMS5pc0Z1bmN0aW9uKHBhcnNlcikpIHtcbiAgICAgICAgICByZXR1cm4gcGFyc2VyLmNhbGwodGhpcywgdmFsdWUsIGtleSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodXRpbHMkMS5pc1JlZ0V4cChwYXJzZXIpKSB7XG4gICAgICAgICAgcmV0dXJuIHBhcnNlci5leGVjKHZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3BhcnNlciBtdXN0IGJlIGJvb2xlYW58cmVnZXhwfGZ1bmN0aW9uJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaGFzKGhlYWRlciwgbWF0Y2hlcikge1xuICAgIGhlYWRlciA9IG5vcm1hbGl6ZUhlYWRlcihoZWFkZXIpO1xuXG4gICAgaWYgKGhlYWRlcikge1xuICAgICAgY29uc3Qga2V5ID0gdXRpbHMkMS5maW5kS2V5KHRoaXMsIGhlYWRlcik7XG5cbiAgICAgIHJldHVybiAhIShrZXkgJiYgdGhpc1trZXldICE9PSB1bmRlZmluZWQgJiYgKCFtYXRjaGVyIHx8IG1hdGNoSGVhZGVyVmFsdWUodGhpcywgdGhpc1trZXldLCBrZXksIG1hdGNoZXIpKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZGVsZXRlKGhlYWRlciwgbWF0Y2hlcikge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIGxldCBkZWxldGVkID0gZmFsc2U7XG5cbiAgICBmdW5jdGlvbiBkZWxldGVIZWFkZXIoX2hlYWRlcikge1xuICAgICAgX2hlYWRlciA9IG5vcm1hbGl6ZUhlYWRlcihfaGVhZGVyKTtcblxuICAgICAgaWYgKF9oZWFkZXIpIHtcbiAgICAgICAgY29uc3Qga2V5ID0gdXRpbHMkMS5maW5kS2V5KHNlbGYsIF9oZWFkZXIpO1xuXG4gICAgICAgIGlmIChrZXkgJiYgKCFtYXRjaGVyIHx8IG1hdGNoSGVhZGVyVmFsdWUoc2VsZiwgc2VsZltrZXldLCBrZXksIG1hdGNoZXIpKSkge1xuICAgICAgICAgIGRlbGV0ZSBzZWxmW2tleV07XG5cbiAgICAgICAgICBkZWxldGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh1dGlscyQxLmlzQXJyYXkoaGVhZGVyKSkge1xuICAgICAgaGVhZGVyLmZvckVhY2goZGVsZXRlSGVhZGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVsZXRlSGVhZGVyKGhlYWRlcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlbGV0ZWQ7XG4gIH1cblxuICBjbGVhcihtYXRjaGVyKSB7XG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHRoaXMpO1xuICAgIGxldCBpID0ga2V5cy5sZW5ndGg7XG4gICAgbGV0IGRlbGV0ZWQgPSBmYWxzZTtcblxuICAgIHdoaWxlIChpLS0pIHtcbiAgICAgIGNvbnN0IGtleSA9IGtleXNbaV07XG4gICAgICBpZighbWF0Y2hlciB8fCBtYXRjaEhlYWRlclZhbHVlKHRoaXMsIHRoaXNba2V5XSwga2V5LCBtYXRjaGVyLCB0cnVlKSkge1xuICAgICAgICBkZWxldGUgdGhpc1trZXldO1xuICAgICAgICBkZWxldGVkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZGVsZXRlZDtcbiAgfVxuXG4gIG5vcm1hbGl6ZShmb3JtYXQpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBjb25zdCBoZWFkZXJzID0ge307XG5cbiAgICB1dGlscyQxLmZvckVhY2godGhpcywgKHZhbHVlLCBoZWFkZXIpID0+IHtcbiAgICAgIGNvbnN0IGtleSA9IHV0aWxzJDEuZmluZEtleShoZWFkZXJzLCBoZWFkZXIpO1xuXG4gICAgICBpZiAoa2V5KSB7XG4gICAgICAgIHNlbGZba2V5XSA9IG5vcm1hbGl6ZVZhbHVlKHZhbHVlKTtcbiAgICAgICAgZGVsZXRlIHNlbGZbaGVhZGVyXTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBub3JtYWxpemVkID0gZm9ybWF0ID8gZm9ybWF0SGVhZGVyKGhlYWRlcikgOiBTdHJpbmcoaGVhZGVyKS50cmltKCk7XG5cbiAgICAgIGlmIChub3JtYWxpemVkICE9PSBoZWFkZXIpIHtcbiAgICAgICAgZGVsZXRlIHNlbGZbaGVhZGVyXTtcbiAgICAgIH1cblxuICAgICAgc2VsZltub3JtYWxpemVkXSA9IG5vcm1hbGl6ZVZhbHVlKHZhbHVlKTtcblxuICAgICAgaGVhZGVyc1tub3JtYWxpemVkXSA9IHRydWU7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGNvbmNhdCguLi50YXJnZXRzKSB7XG4gICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuY29uY2F0KHRoaXMsIC4uLnRhcmdldHMpO1xuICB9XG5cbiAgdG9KU09OKGFzU3RyaW5ncykge1xuICAgIGNvbnN0IG9iaiA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5cbiAgICB1dGlscyQxLmZvckVhY2godGhpcywgKHZhbHVlLCBoZWFkZXIpID0+IHtcbiAgICAgIHZhbHVlICE9IG51bGwgJiYgdmFsdWUgIT09IGZhbHNlICYmIChvYmpbaGVhZGVyXSA9IGFzU3RyaW5ncyAmJiB1dGlscyQxLmlzQXJyYXkodmFsdWUpID8gdmFsdWUuam9pbignLCAnKSA6IHZhbHVlKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gT2JqZWN0LmVudHJpZXModGhpcy50b0pTT04oKSlbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKHRoaXMudG9KU09OKCkpLm1hcCgoW2hlYWRlciwgdmFsdWVdKSA9PiBoZWFkZXIgKyAnOiAnICsgdmFsdWUpLmpvaW4oJ1xcbicpO1xuICB9XG5cbiAgZ2V0IFtTeW1ib2wudG9TdHJpbmdUYWddKCkge1xuICAgIHJldHVybiAnQXhpb3NIZWFkZXJzJztcbiAgfVxuXG4gIHN0YXRpYyBmcm9tKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nIGluc3RhbmNlb2YgdGhpcyA/IHRoaW5nIDogbmV3IHRoaXModGhpbmcpO1xuICB9XG5cbiAgc3RhdGljIGNvbmNhdChmaXJzdCwgLi4udGFyZ2V0cykge1xuICAgIGNvbnN0IGNvbXB1dGVkID0gbmV3IHRoaXMoZmlyc3QpO1xuXG4gICAgdGFyZ2V0cy5mb3JFYWNoKCh0YXJnZXQpID0+IGNvbXB1dGVkLnNldCh0YXJnZXQpKTtcblxuICAgIHJldHVybiBjb21wdXRlZDtcbiAgfVxuXG4gIHN0YXRpYyBhY2Nlc3NvcihoZWFkZXIpIHtcbiAgICBjb25zdCBpbnRlcm5hbHMgPSB0aGlzWyRpbnRlcm5hbHNdID0gKHRoaXNbJGludGVybmFsc10gPSB7XG4gICAgICBhY2Nlc3NvcnM6IHt9XG4gICAgfSk7XG5cbiAgICBjb25zdCBhY2Nlc3NvcnMgPSBpbnRlcm5hbHMuYWNjZXNzb3JzO1xuICAgIGNvbnN0IHByb3RvdHlwZSA9IHRoaXMucHJvdG90eXBlO1xuXG4gICAgZnVuY3Rpb24gZGVmaW5lQWNjZXNzb3IoX2hlYWRlcikge1xuICAgICAgY29uc3QgbEhlYWRlciA9IG5vcm1hbGl6ZUhlYWRlcihfaGVhZGVyKTtcblxuICAgICAgaWYgKCFhY2Nlc3NvcnNbbEhlYWRlcl0pIHtcbiAgICAgICAgYnVpbGRBY2Nlc3NvcnMocHJvdG90eXBlLCBfaGVhZGVyKTtcbiAgICAgICAgYWNjZXNzb3JzW2xIZWFkZXJdID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB1dGlscyQxLmlzQXJyYXkoaGVhZGVyKSA/IGhlYWRlci5mb3JFYWNoKGRlZmluZUFjY2Vzc29yKSA6IGRlZmluZUFjY2Vzc29yKGhlYWRlcik7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxufVxuXG5BeGlvc0hlYWRlcnMuYWNjZXNzb3IoWydDb250ZW50LVR5cGUnLCAnQ29udGVudC1MZW5ndGgnLCAnQWNjZXB0JywgJ0FjY2VwdC1FbmNvZGluZycsICdVc2VyLUFnZW50JywgJ0F1dGhvcml6YXRpb24nXSk7XG5cbi8vIHJlc2VydmVkIG5hbWVzIGhvdGZpeFxudXRpbHMkMS5yZWR1Y2VEZXNjcmlwdG9ycyhBeGlvc0hlYWRlcnMucHJvdG90eXBlLCAoe3ZhbHVlfSwga2V5KSA9PiB7XG4gIGxldCBtYXBwZWQgPSBrZXlbMF0udG9VcHBlckNhc2UoKSArIGtleS5zbGljZSgxKTsgLy8gbWFwIGBzZXRgID0+IGBTZXRgXG4gIHJldHVybiB7XG4gICAgZ2V0OiAoKSA9PiB2YWx1ZSxcbiAgICBzZXQoaGVhZGVyVmFsdWUpIHtcbiAgICAgIHRoaXNbbWFwcGVkXSA9IGhlYWRlclZhbHVlO1xuICAgIH1cbiAgfVxufSk7XG5cbnV0aWxzJDEuZnJlZXplTWV0aG9kcyhBeGlvc0hlYWRlcnMpO1xuXG52YXIgQXhpb3NIZWFkZXJzJDEgPSBBeGlvc0hlYWRlcnM7XG5cbi8qKlxuICogVHJhbnNmb3JtIHRoZSBkYXRhIGZvciBhIHJlcXVlc3Qgb3IgYSByZXNwb25zZVxuICpcbiAqIEBwYXJhbSB7QXJyYXl8RnVuY3Rpb259IGZucyBBIHNpbmdsZSBmdW5jdGlvbiBvciBBcnJheSBvZiBmdW5jdGlvbnNcbiAqIEBwYXJhbSB7P09iamVjdH0gcmVzcG9uc2UgVGhlIHJlc3BvbnNlIG9iamVjdFxuICpcbiAqIEByZXR1cm5zIHsqfSBUaGUgcmVzdWx0aW5nIHRyYW5zZm9ybWVkIGRhdGFcbiAqL1xuZnVuY3Rpb24gdHJhbnNmb3JtRGF0YShmbnMsIHJlc3BvbnNlKSB7XG4gIGNvbnN0IGNvbmZpZyA9IHRoaXMgfHwgZGVmYXVsdHMkMTtcbiAgY29uc3QgY29udGV4dCA9IHJlc3BvbnNlIHx8IGNvbmZpZztcbiAgY29uc3QgaGVhZGVycyA9IEF4aW9zSGVhZGVycyQxLmZyb20oY29udGV4dC5oZWFkZXJzKTtcbiAgbGV0IGRhdGEgPSBjb250ZXh0LmRhdGE7XG5cbiAgdXRpbHMkMS5mb3JFYWNoKGZucywgZnVuY3Rpb24gdHJhbnNmb3JtKGZuKSB7XG4gICAgZGF0YSA9IGZuLmNhbGwoY29uZmlnLCBkYXRhLCBoZWFkZXJzLm5vcm1hbGl6ZSgpLCByZXNwb25zZSA/IHJlc3BvbnNlLnN0YXR1cyA6IHVuZGVmaW5lZCk7XG4gIH0pO1xuXG4gIGhlYWRlcnMubm9ybWFsaXplKCk7XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbmZ1bmN0aW9uIGlzQ2FuY2VsKHZhbHVlKSB7XG4gIHJldHVybiAhISh2YWx1ZSAmJiB2YWx1ZS5fX0NBTkNFTF9fKTtcbn1cblxuLyoqXG4gKiBBIGBDYW5jZWxlZEVycm9yYCBpcyBhbiBvYmplY3QgdGhhdCBpcyB0aHJvd24gd2hlbiBhbiBvcGVyYXRpb24gaXMgY2FuY2VsZWQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmc9fSBtZXNzYWdlIFRoZSBtZXNzYWdlLlxuICogQHBhcmFtIHtPYmplY3Q9fSBjb25maWcgVGhlIGNvbmZpZy5cbiAqIEBwYXJhbSB7T2JqZWN0PX0gcmVxdWVzdCBUaGUgcmVxdWVzdC5cbiAqXG4gKiBAcmV0dXJucyB7Q2FuY2VsZWRFcnJvcn0gVGhlIGNyZWF0ZWQgZXJyb3IuXG4gKi9cbmZ1bmN0aW9uIENhbmNlbGVkRXJyb3IobWVzc2FnZSwgY29uZmlnLCByZXF1ZXN0KSB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1lcS1udWxsLGVxZXFlcVxuICBBeGlvc0Vycm9yLmNhbGwodGhpcywgbWVzc2FnZSA9PSBudWxsID8gJ2NhbmNlbGVkJyA6IG1lc3NhZ2UsIEF4aW9zRXJyb3IuRVJSX0NBTkNFTEVELCBjb25maWcsIHJlcXVlc3QpO1xuICB0aGlzLm5hbWUgPSAnQ2FuY2VsZWRFcnJvcic7XG59XG5cbnV0aWxzJDEuaW5oZXJpdHMoQ2FuY2VsZWRFcnJvciwgQXhpb3NFcnJvciwge1xuICBfX0NBTkNFTF9fOiB0cnVlXG59KTtcblxuLyoqXG4gKiBSZXNvbHZlIG9yIHJlamVjdCBhIFByb21pc2UgYmFzZWQgb24gcmVzcG9uc2Ugc3RhdHVzLlxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IHJlc29sdmUgQSBmdW5jdGlvbiB0aGF0IHJlc29sdmVzIHRoZSBwcm9taXNlLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gcmVqZWN0IEEgZnVuY3Rpb24gdGhhdCByZWplY3RzIHRoZSBwcm9taXNlLlxuICogQHBhcmFtIHtvYmplY3R9IHJlc3BvbnNlIFRoZSByZXNwb25zZS5cbiAqXG4gKiBAcmV0dXJucyB7b2JqZWN0fSBUaGUgcmVzcG9uc2UuXG4gKi9cbmZ1bmN0aW9uIHNldHRsZShyZXNvbHZlLCByZWplY3QsIHJlc3BvbnNlKSB7XG4gIGNvbnN0IHZhbGlkYXRlU3RhdHVzID0gcmVzcG9uc2UuY29uZmlnLnZhbGlkYXRlU3RhdHVzO1xuICBpZiAoIXJlc3BvbnNlLnN0YXR1cyB8fCAhdmFsaWRhdGVTdGF0dXMgfHwgdmFsaWRhdGVTdGF0dXMocmVzcG9uc2Uuc3RhdHVzKSkge1xuICAgIHJlc29sdmUocmVzcG9uc2UpO1xuICB9IGVsc2Uge1xuICAgIHJlamVjdChuZXcgQXhpb3NFcnJvcihcbiAgICAgICdSZXF1ZXN0IGZhaWxlZCB3aXRoIHN0YXR1cyBjb2RlICcgKyByZXNwb25zZS5zdGF0dXMsXG4gICAgICBbQXhpb3NFcnJvci5FUlJfQkFEX1JFUVVFU1QsIEF4aW9zRXJyb3IuRVJSX0JBRF9SRVNQT05TRV1bTWF0aC5mbG9vcihyZXNwb25zZS5zdGF0dXMgLyAxMDApIC0gNF0sXG4gICAgICByZXNwb25zZS5jb25maWcsXG4gICAgICByZXNwb25zZS5yZXF1ZXN0LFxuICAgICAgcmVzcG9uc2VcbiAgICApKTtcbiAgfVxufVxuXG52YXIgY29va2llcyA9IHBsYXRmb3JtLmhhc1N0YW5kYXJkQnJvd3NlckVudiA/XG5cbiAgLy8gU3RhbmRhcmQgYnJvd3NlciBlbnZzIHN1cHBvcnQgZG9jdW1lbnQuY29va2llXG4gIHtcbiAgICB3cml0ZShuYW1lLCB2YWx1ZSwgZXhwaXJlcywgcGF0aCwgZG9tYWluLCBzZWN1cmUpIHtcbiAgICAgIGNvbnN0IGNvb2tpZSA9IFtuYW1lICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKV07XG5cbiAgICAgIHV0aWxzJDEuaXNOdW1iZXIoZXhwaXJlcykgJiYgY29va2llLnB1c2goJ2V4cGlyZXM9JyArIG5ldyBEYXRlKGV4cGlyZXMpLnRvR01UU3RyaW5nKCkpO1xuXG4gICAgICB1dGlscyQxLmlzU3RyaW5nKHBhdGgpICYmIGNvb2tpZS5wdXNoKCdwYXRoPScgKyBwYXRoKTtcblxuICAgICAgdXRpbHMkMS5pc1N0cmluZyhkb21haW4pICYmIGNvb2tpZS5wdXNoKCdkb21haW49JyArIGRvbWFpbik7XG5cbiAgICAgIHNlY3VyZSA9PT0gdHJ1ZSAmJiBjb29raWUucHVzaCgnc2VjdXJlJyk7XG5cbiAgICAgIGRvY3VtZW50LmNvb2tpZSA9IGNvb2tpZS5qb2luKCc7ICcpO1xuICAgIH0sXG5cbiAgICByZWFkKG5hbWUpIHtcbiAgICAgIGNvbnN0IG1hdGNoID0gZG9jdW1lbnQuY29va2llLm1hdGNoKG5ldyBSZWdFeHAoJyhefDtcXFxccyopKCcgKyBuYW1lICsgJyk9KFteO10qKScpKTtcbiAgICAgIHJldHVybiAobWF0Y2ggPyBkZWNvZGVVUklDb21wb25lbnQobWF0Y2hbM10pIDogbnVsbCk7XG4gICAgfSxcblxuICAgIHJlbW92ZShuYW1lKSB7XG4gICAgICB0aGlzLndyaXRlKG5hbWUsICcnLCBEYXRlLm5vdygpIC0gODY0MDAwMDApO1xuICAgIH1cbiAgfVxuXG4gIDpcblxuICAvLyBOb24tc3RhbmRhcmQgYnJvd3NlciBlbnYgKHdlYiB3b3JrZXJzLCByZWFjdC1uYXRpdmUpIGxhY2sgbmVlZGVkIHN1cHBvcnQuXG4gIHtcbiAgICB3cml0ZSgpIHt9LFxuICAgIHJlYWQoKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9LFxuICAgIHJlbW92ZSgpIHt9XG4gIH07XG5cbi8qKlxuICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBzcGVjaWZpZWQgVVJMIGlzIGFic29sdXRlXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHVybCBUaGUgVVJMIHRvIHRlc3RcbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgc3BlY2lmaWVkIFVSTCBpcyBhYnNvbHV0ZSwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzQWJzb2x1dGVVUkwodXJsKSB7XG4gIC8vIEEgVVJMIGlzIGNvbnNpZGVyZWQgYWJzb2x1dGUgaWYgaXQgYmVnaW5zIHdpdGggXCI8c2NoZW1lPjovL1wiIG9yIFwiLy9cIiAocHJvdG9jb2wtcmVsYXRpdmUgVVJMKS5cbiAgLy8gUkZDIDM5ODYgZGVmaW5lcyBzY2hlbWUgbmFtZSBhcyBhIHNlcXVlbmNlIG9mIGNoYXJhY3RlcnMgYmVnaW5uaW5nIHdpdGggYSBsZXR0ZXIgYW5kIGZvbGxvd2VkXG4gIC8vIGJ5IGFueSBjb21iaW5hdGlvbiBvZiBsZXR0ZXJzLCBkaWdpdHMsIHBsdXMsIHBlcmlvZCwgb3IgaHlwaGVuLlxuICByZXR1cm4gL14oW2Etel1bYS16XFxkK1xcLS5dKjopP1xcL1xcLy9pLnRlc3QodXJsKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IFVSTCBieSBjb21iaW5pbmcgdGhlIHNwZWNpZmllZCBVUkxzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2VVUkwgVGhlIGJhc2UgVVJMXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVsYXRpdmVVUkwgVGhlIHJlbGF0aXZlIFVSTFxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjb21iaW5lZCBVUkxcbiAqL1xuZnVuY3Rpb24gY29tYmluZVVSTHMoYmFzZVVSTCwgcmVsYXRpdmVVUkwpIHtcbiAgcmV0dXJuIHJlbGF0aXZlVVJMXG4gICAgPyBiYXNlVVJMLnJlcGxhY2UoL1xcLz9cXC8kLywgJycpICsgJy8nICsgcmVsYXRpdmVVUkwucmVwbGFjZSgvXlxcLysvLCAnJylcbiAgICA6IGJhc2VVUkw7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBVUkwgYnkgY29tYmluaW5nIHRoZSBiYXNlVVJMIHdpdGggdGhlIHJlcXVlc3RlZFVSTCxcbiAqIG9ubHkgd2hlbiB0aGUgcmVxdWVzdGVkVVJMIGlzIG5vdCBhbHJlYWR5IGFuIGFic29sdXRlIFVSTC5cbiAqIElmIHRoZSByZXF1ZXN0VVJMIGlzIGFic29sdXRlLCB0aGlzIGZ1bmN0aW9uIHJldHVybnMgdGhlIHJlcXVlc3RlZFVSTCB1bnRvdWNoZWQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJhc2VVUkwgVGhlIGJhc2UgVVJMXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVxdWVzdGVkVVJMIEFic29sdXRlIG9yIHJlbGF0aXZlIFVSTCB0byBjb21iaW5lXG4gKlxuICogQHJldHVybnMge3N0cmluZ30gVGhlIGNvbWJpbmVkIGZ1bGwgcGF0aFxuICovXG5mdW5jdGlvbiBidWlsZEZ1bGxQYXRoKGJhc2VVUkwsIHJlcXVlc3RlZFVSTCkge1xuICBpZiAoYmFzZVVSTCAmJiAhaXNBYnNvbHV0ZVVSTChyZXF1ZXN0ZWRVUkwpKSB7XG4gICAgcmV0dXJuIGNvbWJpbmVVUkxzKGJhc2VVUkwsIHJlcXVlc3RlZFVSTCk7XG4gIH1cbiAgcmV0dXJuIHJlcXVlc3RlZFVSTDtcbn1cblxudmFyIGlzVVJMU2FtZU9yaWdpbiA9IHBsYXRmb3JtLmhhc1N0YW5kYXJkQnJvd3NlckVudiA/XG5cbi8vIFN0YW5kYXJkIGJyb3dzZXIgZW52cyBoYXZlIGZ1bGwgc3VwcG9ydCBvZiB0aGUgQVBJcyBuZWVkZWQgdG8gdGVzdFxuLy8gd2hldGhlciB0aGUgcmVxdWVzdCBVUkwgaXMgb2YgdGhlIHNhbWUgb3JpZ2luIGFzIGN1cnJlbnQgbG9jYXRpb24uXG4gIChmdW5jdGlvbiBzdGFuZGFyZEJyb3dzZXJFbnYoKSB7XG4gICAgY29uc3QgbXNpZSA9IC8obXNpZXx0cmlkZW50KS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgY29uc3QgdXJsUGFyc2luZ05vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgbGV0IG9yaWdpblVSTDtcblxuICAgIC8qKlxuICAgICogUGFyc2UgYSBVUkwgdG8gZGlzY292ZXIgaXRzIGNvbXBvbmVudHNcbiAgICAqXG4gICAgKiBAcGFyYW0ge1N0cmluZ30gdXJsIFRoZSBVUkwgdG8gYmUgcGFyc2VkXG4gICAgKiBAcmV0dXJucyB7T2JqZWN0fVxuICAgICovXG4gICAgZnVuY3Rpb24gcmVzb2x2ZVVSTCh1cmwpIHtcbiAgICAgIGxldCBocmVmID0gdXJsO1xuXG4gICAgICBpZiAobXNpZSkge1xuICAgICAgICAvLyBJRSBuZWVkcyBhdHRyaWJ1dGUgc2V0IHR3aWNlIHRvIG5vcm1hbGl6ZSBwcm9wZXJ0aWVzXG4gICAgICAgIHVybFBhcnNpbmdOb2RlLnNldEF0dHJpYnV0ZSgnaHJlZicsIGhyZWYpO1xuICAgICAgICBocmVmID0gdXJsUGFyc2luZ05vZGUuaHJlZjtcbiAgICAgIH1cblxuICAgICAgdXJsUGFyc2luZ05vZGUuc2V0QXR0cmlidXRlKCdocmVmJywgaHJlZik7XG5cbiAgICAgIC8vIHVybFBhcnNpbmdOb2RlIHByb3ZpZGVzIHRoZSBVcmxVdGlscyBpbnRlcmZhY2UgLSBodHRwOi8vdXJsLnNwZWMud2hhdHdnLm9yZy8jdXJsdXRpbHNcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhyZWY6IHVybFBhcnNpbmdOb2RlLmhyZWYsXG4gICAgICAgIHByb3RvY29sOiB1cmxQYXJzaW5nTm9kZS5wcm90b2NvbCA/IHVybFBhcnNpbmdOb2RlLnByb3RvY29sLnJlcGxhY2UoLzokLywgJycpIDogJycsXG4gICAgICAgIGhvc3Q6IHVybFBhcnNpbmdOb2RlLmhvc3QsXG4gICAgICAgIHNlYXJjaDogdXJsUGFyc2luZ05vZGUuc2VhcmNoID8gdXJsUGFyc2luZ05vZGUuc2VhcmNoLnJlcGxhY2UoL15cXD8vLCAnJykgOiAnJyxcbiAgICAgICAgaGFzaDogdXJsUGFyc2luZ05vZGUuaGFzaCA/IHVybFBhcnNpbmdOb2RlLmhhc2gucmVwbGFjZSgvXiMvLCAnJykgOiAnJyxcbiAgICAgICAgaG9zdG5hbWU6IHVybFBhcnNpbmdOb2RlLmhvc3RuYW1lLFxuICAgICAgICBwb3J0OiB1cmxQYXJzaW5nTm9kZS5wb3J0LFxuICAgICAgICBwYXRobmFtZTogKHVybFBhcnNpbmdOb2RlLnBhdGhuYW1lLmNoYXJBdCgwKSA9PT0gJy8nKSA/XG4gICAgICAgICAgdXJsUGFyc2luZ05vZGUucGF0aG5hbWUgOlxuICAgICAgICAgICcvJyArIHVybFBhcnNpbmdOb2RlLnBhdGhuYW1lXG4gICAgICB9O1xuICAgIH1cblxuICAgIG9yaWdpblVSTCA9IHJlc29sdmVVUkwod2luZG93LmxvY2F0aW9uLmhyZWYpO1xuXG4gICAgLyoqXG4gICAgKiBEZXRlcm1pbmUgaWYgYSBVUkwgc2hhcmVzIHRoZSBzYW1lIG9yaWdpbiBhcyB0aGUgY3VycmVudCBsb2NhdGlvblxuICAgICpcbiAgICAqIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VVJMIFRoZSBVUkwgdG8gdGVzdFxuICAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgVVJMIHNoYXJlcyB0aGUgc2FtZSBvcmlnaW4sIG90aGVyd2lzZSBmYWxzZVxuICAgICovXG4gICAgcmV0dXJuIGZ1bmN0aW9uIGlzVVJMU2FtZU9yaWdpbihyZXF1ZXN0VVJMKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSAodXRpbHMkMS5pc1N0cmluZyhyZXF1ZXN0VVJMKSkgPyByZXNvbHZlVVJMKHJlcXVlc3RVUkwpIDogcmVxdWVzdFVSTDtcbiAgICAgIHJldHVybiAocGFyc2VkLnByb3RvY29sID09PSBvcmlnaW5VUkwucHJvdG9jb2wgJiZcbiAgICAgICAgICBwYXJzZWQuaG9zdCA9PT0gb3JpZ2luVVJMLmhvc3QpO1xuICAgIH07XG4gIH0pKCkgOlxuXG4gIC8vIE5vbiBzdGFuZGFyZCBicm93c2VyIGVudnMgKHdlYiB3b3JrZXJzLCByZWFjdC1uYXRpdmUpIGxhY2sgbmVlZGVkIHN1cHBvcnQuXG4gIChmdW5jdGlvbiBub25TdGFuZGFyZEJyb3dzZXJFbnYoKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIGlzVVJMU2FtZU9yaWdpbigpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH07XG4gIH0pKCk7XG5cbmZ1bmN0aW9uIHBhcnNlUHJvdG9jb2wodXJsKSB7XG4gIGNvbnN0IG1hdGNoID0gL14oWy0rXFx3XXsxLDI1fSkoOj9cXC9cXC98OikvLmV4ZWModXJsKTtcbiAgcmV0dXJuIG1hdGNoICYmIG1hdGNoWzFdIHx8ICcnO1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZSBkYXRhIG1heFJhdGVcbiAqIEBwYXJhbSB7TnVtYmVyfSBbc2FtcGxlc0NvdW50PSAxMF1cbiAqIEBwYXJhbSB7TnVtYmVyfSBbbWluPSAxMDAwXVxuICogQHJldHVybnMge0Z1bmN0aW9ufVxuICovXG5mdW5jdGlvbiBzcGVlZG9tZXRlcihzYW1wbGVzQ291bnQsIG1pbikge1xuICBzYW1wbGVzQ291bnQgPSBzYW1wbGVzQ291bnQgfHwgMTA7XG4gIGNvbnN0IGJ5dGVzID0gbmV3IEFycmF5KHNhbXBsZXNDb3VudCk7XG4gIGNvbnN0IHRpbWVzdGFtcHMgPSBuZXcgQXJyYXkoc2FtcGxlc0NvdW50KTtcbiAgbGV0IGhlYWQgPSAwO1xuICBsZXQgdGFpbCA9IDA7XG4gIGxldCBmaXJzdFNhbXBsZVRTO1xuXG4gIG1pbiA9IG1pbiAhPT0gdW5kZWZpbmVkID8gbWluIDogMTAwMDtcblxuICByZXR1cm4gZnVuY3Rpb24gcHVzaChjaHVua0xlbmd0aCkge1xuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG5cbiAgICBjb25zdCBzdGFydGVkQXQgPSB0aW1lc3RhbXBzW3RhaWxdO1xuXG4gICAgaWYgKCFmaXJzdFNhbXBsZVRTKSB7XG4gICAgICBmaXJzdFNhbXBsZVRTID0gbm93O1xuICAgIH1cblxuICAgIGJ5dGVzW2hlYWRdID0gY2h1bmtMZW5ndGg7XG4gICAgdGltZXN0YW1wc1toZWFkXSA9IG5vdztcblxuICAgIGxldCBpID0gdGFpbDtcbiAgICBsZXQgYnl0ZXNDb3VudCA9IDA7XG5cbiAgICB3aGlsZSAoaSAhPT0gaGVhZCkge1xuICAgICAgYnl0ZXNDb3VudCArPSBieXRlc1tpKytdO1xuICAgICAgaSA9IGkgJSBzYW1wbGVzQ291bnQ7XG4gICAgfVxuXG4gICAgaGVhZCA9IChoZWFkICsgMSkgJSBzYW1wbGVzQ291bnQ7XG5cbiAgICBpZiAoaGVhZCA9PT0gdGFpbCkge1xuICAgICAgdGFpbCA9ICh0YWlsICsgMSkgJSBzYW1wbGVzQ291bnQ7XG4gICAgfVxuXG4gICAgaWYgKG5vdyAtIGZpcnN0U2FtcGxlVFMgPCBtaW4pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwYXNzZWQgPSBzdGFydGVkQXQgJiYgbm93IC0gc3RhcnRlZEF0O1xuXG4gICAgcmV0dXJuIHBhc3NlZCA/IE1hdGgucm91bmQoYnl0ZXNDb3VudCAqIDEwMDAgLyBwYXNzZWQpIDogdW5kZWZpbmVkO1xuICB9O1xufVxuXG5mdW5jdGlvbiBwcm9ncmVzc0V2ZW50UmVkdWNlcihsaXN0ZW5lciwgaXNEb3dubG9hZFN0cmVhbSkge1xuICBsZXQgYnl0ZXNOb3RpZmllZCA9IDA7XG4gIGNvbnN0IF9zcGVlZG9tZXRlciA9IHNwZWVkb21ldGVyKDUwLCAyNTApO1xuXG4gIHJldHVybiBlID0+IHtcbiAgICBjb25zdCBsb2FkZWQgPSBlLmxvYWRlZDtcbiAgICBjb25zdCB0b3RhbCA9IGUubGVuZ3RoQ29tcHV0YWJsZSA/IGUudG90YWwgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgcHJvZ3Jlc3NCeXRlcyA9IGxvYWRlZCAtIGJ5dGVzTm90aWZpZWQ7XG4gICAgY29uc3QgcmF0ZSA9IF9zcGVlZG9tZXRlcihwcm9ncmVzc0J5dGVzKTtcbiAgICBjb25zdCBpblJhbmdlID0gbG9hZGVkIDw9IHRvdGFsO1xuXG4gICAgYnl0ZXNOb3RpZmllZCA9IGxvYWRlZDtcblxuICAgIGNvbnN0IGRhdGEgPSB7XG4gICAgICBsb2FkZWQsXG4gICAgICB0b3RhbCxcbiAgICAgIHByb2dyZXNzOiB0b3RhbCA/IChsb2FkZWQgLyB0b3RhbCkgOiB1bmRlZmluZWQsXG4gICAgICBieXRlczogcHJvZ3Jlc3NCeXRlcyxcbiAgICAgIHJhdGU6IHJhdGUgPyByYXRlIDogdW5kZWZpbmVkLFxuICAgICAgZXN0aW1hdGVkOiByYXRlICYmIHRvdGFsICYmIGluUmFuZ2UgPyAodG90YWwgLSBsb2FkZWQpIC8gcmF0ZSA6IHVuZGVmaW5lZCxcbiAgICAgIGV2ZW50OiBlXG4gICAgfTtcblxuICAgIGRhdGFbaXNEb3dubG9hZFN0cmVhbSA/ICdkb3dubG9hZCcgOiAndXBsb2FkJ10gPSB0cnVlO1xuXG4gICAgbGlzdGVuZXIoZGF0YSk7XG4gIH07XG59XG5cbmNvbnN0IGlzWEhSQWRhcHRlclN1cHBvcnRlZCA9IHR5cGVvZiBYTUxIdHRwUmVxdWVzdCAhPT0gJ3VuZGVmaW5lZCc7XG5cbnZhciB4aHJBZGFwdGVyID0gaXNYSFJBZGFwdGVyU3VwcG9ydGVkICYmIGZ1bmN0aW9uIChjb25maWcpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIGRpc3BhdGNoWGhyUmVxdWVzdChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBsZXQgcmVxdWVzdERhdGEgPSBjb25maWcuZGF0YTtcbiAgICBjb25zdCByZXF1ZXN0SGVhZGVycyA9IEF4aW9zSGVhZGVycyQxLmZyb20oY29uZmlnLmhlYWRlcnMpLm5vcm1hbGl6ZSgpO1xuICAgIGxldCB7cmVzcG9uc2VUeXBlLCB3aXRoWFNSRlRva2VufSA9IGNvbmZpZztcbiAgICBsZXQgb25DYW5jZWxlZDtcbiAgICBmdW5jdGlvbiBkb25lKCkge1xuICAgICAgaWYgKGNvbmZpZy5jYW5jZWxUb2tlbikge1xuICAgICAgICBjb25maWcuY2FuY2VsVG9rZW4udW5zdWJzY3JpYmUob25DYW5jZWxlZCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb25maWcuc2lnbmFsKSB7XG4gICAgICAgIGNvbmZpZy5zaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBvbkNhbmNlbGVkKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgY29udGVudFR5cGU7XG5cbiAgICBpZiAodXRpbHMkMS5pc0Zvcm1EYXRhKHJlcXVlc3REYXRhKSkge1xuICAgICAgaWYgKHBsYXRmb3JtLmhhc1N0YW5kYXJkQnJvd3NlckVudiB8fCBwbGF0Zm9ybS5oYXNTdGFuZGFyZEJyb3dzZXJXZWJXb3JrZXJFbnYpIHtcbiAgICAgICAgcmVxdWVzdEhlYWRlcnMuc2V0Q29udGVudFR5cGUoZmFsc2UpOyAvLyBMZXQgdGhlIGJyb3dzZXIgc2V0IGl0XG4gICAgICB9IGVsc2UgaWYgKChjb250ZW50VHlwZSA9IHJlcXVlc3RIZWFkZXJzLmdldENvbnRlbnRUeXBlKCkpICE9PSBmYWxzZSkge1xuICAgICAgICAvLyBmaXggc2VtaWNvbG9uIGR1cGxpY2F0aW9uIGlzc3VlIGZvciBSZWFjdE5hdGl2ZSBGb3JtRGF0YSBpbXBsZW1lbnRhdGlvblxuICAgICAgICBjb25zdCBbdHlwZSwgLi4udG9rZW5zXSA9IGNvbnRlbnRUeXBlID8gY29udGVudFR5cGUuc3BsaXQoJzsnKS5tYXAodG9rZW4gPT4gdG9rZW4udHJpbSgpKS5maWx0ZXIoQm9vbGVhbikgOiBbXTtcbiAgICAgICAgcmVxdWVzdEhlYWRlcnMuc2V0Q29udGVudFR5cGUoW3R5cGUgfHwgJ211bHRpcGFydC9mb3JtLWRhdGEnLCAuLi50b2tlbnNdLmpvaW4oJzsgJykpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCByZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG5cbiAgICAvLyBIVFRQIGJhc2ljIGF1dGhlbnRpY2F0aW9uXG4gICAgaWYgKGNvbmZpZy5hdXRoKSB7XG4gICAgICBjb25zdCB1c2VybmFtZSA9IGNvbmZpZy5hdXRoLnVzZXJuYW1lIHx8ICcnO1xuICAgICAgY29uc3QgcGFzc3dvcmQgPSBjb25maWcuYXV0aC5wYXNzd29yZCA/IHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChjb25maWcuYXV0aC5wYXNzd29yZCkpIDogJyc7XG4gICAgICByZXF1ZXN0SGVhZGVycy5zZXQoJ0F1dGhvcml6YXRpb24nLCAnQmFzaWMgJyArIGJ0b2EodXNlcm5hbWUgKyAnOicgKyBwYXNzd29yZCkpO1xuICAgIH1cblxuICAgIGNvbnN0IGZ1bGxQYXRoID0gYnVpbGRGdWxsUGF0aChjb25maWcuYmFzZVVSTCwgY29uZmlnLnVybCk7XG5cbiAgICByZXF1ZXN0Lm9wZW4oY29uZmlnLm1ldGhvZC50b1VwcGVyQ2FzZSgpLCBidWlsZFVSTChmdWxsUGF0aCwgY29uZmlnLnBhcmFtcywgY29uZmlnLnBhcmFtc1NlcmlhbGl6ZXIpLCB0cnVlKTtcblxuICAgIC8vIFNldCB0aGUgcmVxdWVzdCB0aW1lb3V0IGluIE1TXG4gICAgcmVxdWVzdC50aW1lb3V0ID0gY29uZmlnLnRpbWVvdXQ7XG5cbiAgICBmdW5jdGlvbiBvbmxvYWRlbmQoKSB7XG4gICAgICBpZiAoIXJlcXVlc3QpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gUHJlcGFyZSB0aGUgcmVzcG9uc2VcbiAgICAgIGNvbnN0IHJlc3BvbnNlSGVhZGVycyA9IEF4aW9zSGVhZGVycyQxLmZyb20oXG4gICAgICAgICdnZXRBbGxSZXNwb25zZUhlYWRlcnMnIGluIHJlcXVlc3QgJiYgcmVxdWVzdC5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKVxuICAgICAgKTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlRGF0YSA9ICFyZXNwb25zZVR5cGUgfHwgcmVzcG9uc2VUeXBlID09PSAndGV4dCcgfHwgcmVzcG9uc2VUeXBlID09PSAnanNvbicgP1xuICAgICAgICByZXF1ZXN0LnJlc3BvbnNlVGV4dCA6IHJlcXVlc3QucmVzcG9uc2U7XG4gICAgICBjb25zdCByZXNwb25zZSA9IHtcbiAgICAgICAgZGF0YTogcmVzcG9uc2VEYXRhLFxuICAgICAgICBzdGF0dXM6IHJlcXVlc3Quc3RhdHVzLFxuICAgICAgICBzdGF0dXNUZXh0OiByZXF1ZXN0LnN0YXR1c1RleHQsXG4gICAgICAgIGhlYWRlcnM6IHJlc3BvbnNlSGVhZGVycyxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICByZXF1ZXN0XG4gICAgICB9O1xuXG4gICAgICBzZXR0bGUoZnVuY3Rpb24gX3Jlc29sdmUodmFsdWUpIHtcbiAgICAgICAgcmVzb2x2ZSh2YWx1ZSk7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH0sIGZ1bmN0aW9uIF9yZWplY3QoZXJyKSB7XG4gICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9LCByZXNwb25zZSk7XG5cbiAgICAgIC8vIENsZWFuIHVwIHJlcXVlc3RcbiAgICAgIHJlcXVlc3QgPSBudWxsO1xuICAgIH1cblxuICAgIGlmICgnb25sb2FkZW5kJyBpbiByZXF1ZXN0KSB7XG4gICAgICAvLyBVc2Ugb25sb2FkZW5kIGlmIGF2YWlsYWJsZVxuICAgICAgcmVxdWVzdC5vbmxvYWRlbmQgPSBvbmxvYWRlbmQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIExpc3RlbiBmb3IgcmVhZHkgc3RhdGUgdG8gZW11bGF0ZSBvbmxvYWRlbmRcbiAgICAgIHJlcXVlc3Qub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24gaGFuZGxlTG9hZCgpIHtcbiAgICAgICAgaWYgKCFyZXF1ZXN0IHx8IHJlcXVlc3QucmVhZHlTdGF0ZSAhPT0gNCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoZSByZXF1ZXN0IGVycm9yZWQgb3V0IGFuZCB3ZSBkaWRuJ3QgZ2V0IGEgcmVzcG9uc2UsIHRoaXMgd2lsbCBiZVxuICAgICAgICAvLyBoYW5kbGVkIGJ5IG9uZXJyb3IgaW5zdGVhZFxuICAgICAgICAvLyBXaXRoIG9uZSBleGNlcHRpb246IHJlcXVlc3QgdGhhdCB1c2luZyBmaWxlOiBwcm90b2NvbCwgbW9zdCBicm93c2Vyc1xuICAgICAgICAvLyB3aWxsIHJldHVybiBzdGF0dXMgYXMgMCBldmVuIHRob3VnaCBpdCdzIGEgc3VjY2Vzc2Z1bCByZXF1ZXN0XG4gICAgICAgIGlmIChyZXF1ZXN0LnN0YXR1cyA9PT0gMCAmJiAhKHJlcXVlc3QucmVzcG9uc2VVUkwgJiYgcmVxdWVzdC5yZXNwb25zZVVSTC5pbmRleE9mKCdmaWxlOicpID09PSAwKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyByZWFkeXN0YXRlIGhhbmRsZXIgaXMgY2FsbGluZyBiZWZvcmUgb25lcnJvciBvciBvbnRpbWVvdXQgaGFuZGxlcnMsXG4gICAgICAgIC8vIHNvIHdlIHNob3VsZCBjYWxsIG9ubG9hZGVuZCBvbiB0aGUgbmV4dCAndGljaydcbiAgICAgICAgc2V0VGltZW91dChvbmxvYWRlbmQpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgYnJvd3NlciByZXF1ZXN0IGNhbmNlbGxhdGlvbiAoYXMgb3Bwb3NlZCB0byBhIG1hbnVhbCBjYW5jZWxsYXRpb24pXG4gICAgcmVxdWVzdC5vbmFib3J0ID0gZnVuY3Rpb24gaGFuZGxlQWJvcnQoKSB7XG4gICAgICBpZiAoIXJlcXVlc3QpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICByZWplY3QobmV3IEF4aW9zRXJyb3IoJ1JlcXVlc3QgYWJvcnRlZCcsIEF4aW9zRXJyb3IuRUNPTk5BQk9SVEVELCBjb25maWcsIHJlcXVlc3QpKTtcblxuICAgICAgLy8gQ2xlYW4gdXAgcmVxdWVzdFxuICAgICAgcmVxdWVzdCA9IG51bGw7XG4gICAgfTtcblxuICAgIC8vIEhhbmRsZSBsb3cgbGV2ZWwgbmV0d29yayBlcnJvcnNcbiAgICByZXF1ZXN0Lm9uZXJyb3IgPSBmdW5jdGlvbiBoYW5kbGVFcnJvcigpIHtcbiAgICAgIC8vIFJlYWwgZXJyb3JzIGFyZSBoaWRkZW4gZnJvbSB1cyBieSB0aGUgYnJvd3NlclxuICAgICAgLy8gb25lcnJvciBzaG91bGQgb25seSBmaXJlIGlmIGl0J3MgYSBuZXR3b3JrIGVycm9yXG4gICAgICByZWplY3QobmV3IEF4aW9zRXJyb3IoJ05ldHdvcmsgRXJyb3InLCBBeGlvc0Vycm9yLkVSUl9ORVRXT1JLLCBjb25maWcsIHJlcXVlc3QpKTtcblxuICAgICAgLy8gQ2xlYW4gdXAgcmVxdWVzdFxuICAgICAgcmVxdWVzdCA9IG51bGw7XG4gICAgfTtcblxuICAgIC8vIEhhbmRsZSB0aW1lb3V0XG4gICAgcmVxdWVzdC5vbnRpbWVvdXQgPSBmdW5jdGlvbiBoYW5kbGVUaW1lb3V0KCkge1xuICAgICAgbGV0IHRpbWVvdXRFcnJvck1lc3NhZ2UgPSBjb25maWcudGltZW91dCA/ICd0aW1lb3V0IG9mICcgKyBjb25maWcudGltZW91dCArICdtcyBleGNlZWRlZCcgOiAndGltZW91dCBleGNlZWRlZCc7XG4gICAgICBjb25zdCB0cmFuc2l0aW9uYWwgPSBjb25maWcudHJhbnNpdGlvbmFsIHx8IHRyYW5zaXRpb25hbERlZmF1bHRzO1xuICAgICAgaWYgKGNvbmZpZy50aW1lb3V0RXJyb3JNZXNzYWdlKSB7XG4gICAgICAgIHRpbWVvdXRFcnJvck1lc3NhZ2UgPSBjb25maWcudGltZW91dEVycm9yTWVzc2FnZTtcbiAgICAgIH1cbiAgICAgIHJlamVjdChuZXcgQXhpb3NFcnJvcihcbiAgICAgICAgdGltZW91dEVycm9yTWVzc2FnZSxcbiAgICAgICAgdHJhbnNpdGlvbmFsLmNsYXJpZnlUaW1lb3V0RXJyb3IgPyBBeGlvc0Vycm9yLkVUSU1FRE9VVCA6IEF4aW9zRXJyb3IuRUNPTk5BQk9SVEVELFxuICAgICAgICBjb25maWcsXG4gICAgICAgIHJlcXVlc3QpKTtcblxuICAgICAgLy8gQ2xlYW4gdXAgcmVxdWVzdFxuICAgICAgcmVxdWVzdCA9IG51bGw7XG4gICAgfTtcblxuICAgIC8vIEFkZCB4c3JmIGhlYWRlclxuICAgIC8vIFRoaXMgaXMgb25seSBkb25lIGlmIHJ1bm5pbmcgaW4gYSBzdGFuZGFyZCBicm93c2VyIGVudmlyb25tZW50LlxuICAgIC8vIFNwZWNpZmljYWxseSBub3QgaWYgd2UncmUgaW4gYSB3ZWIgd29ya2VyLCBvciByZWFjdC1uYXRpdmUuXG4gICAgaWYocGxhdGZvcm0uaGFzU3RhbmRhcmRCcm93c2VyRW52KSB7XG4gICAgICB3aXRoWFNSRlRva2VuICYmIHV0aWxzJDEuaXNGdW5jdGlvbih3aXRoWFNSRlRva2VuKSAmJiAod2l0aFhTUkZUb2tlbiA9IHdpdGhYU1JGVG9rZW4oY29uZmlnKSk7XG5cbiAgICAgIGlmICh3aXRoWFNSRlRva2VuIHx8ICh3aXRoWFNSRlRva2VuICE9PSBmYWxzZSAmJiBpc1VSTFNhbWVPcmlnaW4oZnVsbFBhdGgpKSkge1xuICAgICAgICAvLyBBZGQgeHNyZiBoZWFkZXJcbiAgICAgICAgY29uc3QgeHNyZlZhbHVlID0gY29uZmlnLnhzcmZIZWFkZXJOYW1lICYmIGNvbmZpZy54c3JmQ29va2llTmFtZSAmJiBjb29raWVzLnJlYWQoY29uZmlnLnhzcmZDb29raWVOYW1lKTtcblxuICAgICAgICBpZiAoeHNyZlZhbHVlKSB7XG4gICAgICAgICAgcmVxdWVzdEhlYWRlcnMuc2V0KGNvbmZpZy54c3JmSGVhZGVyTmFtZSwgeHNyZlZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlbW92ZSBDb250ZW50LVR5cGUgaWYgZGF0YSBpcyB1bmRlZmluZWRcbiAgICByZXF1ZXN0RGF0YSA9PT0gdW5kZWZpbmVkICYmIHJlcXVlc3RIZWFkZXJzLnNldENvbnRlbnRUeXBlKG51bGwpO1xuXG4gICAgLy8gQWRkIGhlYWRlcnMgdG8gdGhlIHJlcXVlc3RcbiAgICBpZiAoJ3NldFJlcXVlc3RIZWFkZXInIGluIHJlcXVlc3QpIHtcbiAgICAgIHV0aWxzJDEuZm9yRWFjaChyZXF1ZXN0SGVhZGVycy50b0pTT04oKSwgZnVuY3Rpb24gc2V0UmVxdWVzdEhlYWRlcih2YWwsIGtleSkge1xuICAgICAgICByZXF1ZXN0LnNldFJlcXVlc3RIZWFkZXIoa2V5LCB2YWwpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQWRkIHdpdGhDcmVkZW50aWFscyB0byByZXF1ZXN0IGlmIG5lZWRlZFxuICAgIGlmICghdXRpbHMkMS5pc1VuZGVmaW5lZChjb25maWcud2l0aENyZWRlbnRpYWxzKSkge1xuICAgICAgcmVxdWVzdC53aXRoQ3JlZGVudGlhbHMgPSAhIWNvbmZpZy53aXRoQ3JlZGVudGlhbHM7XG4gICAgfVxuXG4gICAgLy8gQWRkIHJlc3BvbnNlVHlwZSB0byByZXF1ZXN0IGlmIG5lZWRlZFxuICAgIGlmIChyZXNwb25zZVR5cGUgJiYgcmVzcG9uc2VUeXBlICE9PSAnanNvbicpIHtcbiAgICAgIHJlcXVlc3QucmVzcG9uc2VUeXBlID0gY29uZmlnLnJlc3BvbnNlVHlwZTtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgcHJvZ3Jlc3MgaWYgbmVlZGVkXG4gICAgaWYgKHR5cGVvZiBjb25maWcub25Eb3dubG9hZFByb2dyZXNzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXF1ZXN0LmFkZEV2ZW50TGlzdGVuZXIoJ3Byb2dyZXNzJywgcHJvZ3Jlc3NFdmVudFJlZHVjZXIoY29uZmlnLm9uRG93bmxvYWRQcm9ncmVzcywgdHJ1ZSkpO1xuICAgIH1cblxuICAgIC8vIE5vdCBhbGwgYnJvd3NlcnMgc3VwcG9ydCB1cGxvYWQgZXZlbnRzXG4gICAgaWYgKHR5cGVvZiBjb25maWcub25VcGxvYWRQcm9ncmVzcyA9PT0gJ2Z1bmN0aW9uJyAmJiByZXF1ZXN0LnVwbG9hZCkge1xuICAgICAgcmVxdWVzdC51cGxvYWQuYWRkRXZlbnRMaXN0ZW5lcigncHJvZ3Jlc3MnLCBwcm9ncmVzc0V2ZW50UmVkdWNlcihjb25maWcub25VcGxvYWRQcm9ncmVzcykpO1xuICAgIH1cblxuICAgIGlmIChjb25maWcuY2FuY2VsVG9rZW4gfHwgY29uZmlnLnNpZ25hbCkge1xuICAgICAgLy8gSGFuZGxlIGNhbmNlbGxhdGlvblxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGZ1bmMtbmFtZXNcbiAgICAgIG9uQ2FuY2VsZWQgPSBjYW5jZWwgPT4ge1xuICAgICAgICBpZiAoIXJlcXVlc3QpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgcmVqZWN0KCFjYW5jZWwgfHwgY2FuY2VsLnR5cGUgPyBuZXcgQ2FuY2VsZWRFcnJvcihudWxsLCBjb25maWcsIHJlcXVlc3QpIDogY2FuY2VsKTtcbiAgICAgICAgcmVxdWVzdC5hYm9ydCgpO1xuICAgICAgICByZXF1ZXN0ID0gbnVsbDtcbiAgICAgIH07XG5cbiAgICAgIGNvbmZpZy5jYW5jZWxUb2tlbiAmJiBjb25maWcuY2FuY2VsVG9rZW4uc3Vic2NyaWJlKG9uQ2FuY2VsZWQpO1xuICAgICAgaWYgKGNvbmZpZy5zaWduYWwpIHtcbiAgICAgICAgY29uZmlnLnNpZ25hbC5hYm9ydGVkID8gb25DYW5jZWxlZCgpIDogY29uZmlnLnNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsIG9uQ2FuY2VsZWQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHByb3RvY29sID0gcGFyc2VQcm90b2NvbChmdWxsUGF0aCk7XG5cbiAgICBpZiAocHJvdG9jb2wgJiYgcGxhdGZvcm0ucHJvdG9jb2xzLmluZGV4T2YocHJvdG9jb2wpID09PSAtMSkge1xuICAgICAgcmVqZWN0KG5ldyBBeGlvc0Vycm9yKCdVbnN1cHBvcnRlZCBwcm90b2NvbCAnICsgcHJvdG9jb2wgKyAnOicsIEF4aW9zRXJyb3IuRVJSX0JBRF9SRVFVRVNULCBjb25maWcpKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cblxuICAgIC8vIFNlbmQgdGhlIHJlcXVlc3RcbiAgICByZXF1ZXN0LnNlbmQocmVxdWVzdERhdGEgfHwgbnVsbCk7XG4gIH0pO1xufTtcblxuY29uc3Qga25vd25BZGFwdGVycyA9IHtcbiAgaHR0cDogaHR0cEFkYXB0ZXIsXG4gIHhocjogeGhyQWRhcHRlclxufTtcblxudXRpbHMkMS5mb3JFYWNoKGtub3duQWRhcHRlcnMsIChmbiwgdmFsdWUpID0+IHtcbiAgaWYgKGZuKSB7XG4gICAgdHJ5IHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmbiwgJ25hbWUnLCB7dmFsdWV9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZW1wdHlcbiAgICB9XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGZuLCAnYWRhcHRlck5hbWUnLCB7dmFsdWV9KTtcbiAgfVxufSk7XG5cbmNvbnN0IHJlbmRlclJlYXNvbiA9IChyZWFzb24pID0+IGAtICR7cmVhc29ufWA7XG5cbmNvbnN0IGlzUmVzb2x2ZWRIYW5kbGUgPSAoYWRhcHRlcikgPT4gdXRpbHMkMS5pc0Z1bmN0aW9uKGFkYXB0ZXIpIHx8IGFkYXB0ZXIgPT09IG51bGwgfHwgYWRhcHRlciA9PT0gZmFsc2U7XG5cbnZhciBhZGFwdGVycyA9IHtcbiAgZ2V0QWRhcHRlcjogKGFkYXB0ZXJzKSA9PiB7XG4gICAgYWRhcHRlcnMgPSB1dGlscyQxLmlzQXJyYXkoYWRhcHRlcnMpID8gYWRhcHRlcnMgOiBbYWRhcHRlcnNdO1xuXG4gICAgY29uc3Qge2xlbmd0aH0gPSBhZGFwdGVycztcbiAgICBsZXQgbmFtZU9yQWRhcHRlcjtcbiAgICBsZXQgYWRhcHRlcjtcblxuICAgIGNvbnN0IHJlamVjdGVkUmVhc29ucyA9IHt9O1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgbmFtZU9yQWRhcHRlciA9IGFkYXB0ZXJzW2ldO1xuICAgICAgbGV0IGlkO1xuXG4gICAgICBhZGFwdGVyID0gbmFtZU9yQWRhcHRlcjtcblxuICAgICAgaWYgKCFpc1Jlc29sdmVkSGFuZGxlKG5hbWVPckFkYXB0ZXIpKSB7XG4gICAgICAgIGFkYXB0ZXIgPSBrbm93bkFkYXB0ZXJzWyhpZCA9IFN0cmluZyhuYW1lT3JBZGFwdGVyKSkudG9Mb3dlckNhc2UoKV07XG5cbiAgICAgICAgaWYgKGFkYXB0ZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBBeGlvc0Vycm9yKGBVbmtub3duIGFkYXB0ZXIgJyR7aWR9J2ApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChhZGFwdGVyKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICByZWplY3RlZFJlYXNvbnNbaWQgfHwgJyMnICsgaV0gPSBhZGFwdGVyO1xuICAgIH1cblxuICAgIGlmICghYWRhcHRlcikge1xuXG4gICAgICBjb25zdCByZWFzb25zID0gT2JqZWN0LmVudHJpZXMocmVqZWN0ZWRSZWFzb25zKVxuICAgICAgICAubWFwKChbaWQsIHN0YXRlXSkgPT4gYGFkYXB0ZXIgJHtpZH0gYCArXG4gICAgICAgICAgKHN0YXRlID09PSBmYWxzZSA/ICdpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoZSBlbnZpcm9ubWVudCcgOiAnaXMgbm90IGF2YWlsYWJsZSBpbiB0aGUgYnVpbGQnKVxuICAgICAgICApO1xuXG4gICAgICBsZXQgcyA9IGxlbmd0aCA/XG4gICAgICAgIChyZWFzb25zLmxlbmd0aCA+IDEgPyAnc2luY2UgOlxcbicgKyByZWFzb25zLm1hcChyZW5kZXJSZWFzb24pLmpvaW4oJ1xcbicpIDogJyAnICsgcmVuZGVyUmVhc29uKHJlYXNvbnNbMF0pKSA6XG4gICAgICAgICdhcyBubyBhZGFwdGVyIHNwZWNpZmllZCc7XG5cbiAgICAgIHRocm93IG5ldyBBeGlvc0Vycm9yKFxuICAgICAgICBgVGhlcmUgaXMgbm8gc3VpdGFibGUgYWRhcHRlciB0byBkaXNwYXRjaCB0aGUgcmVxdWVzdCBgICsgcyxcbiAgICAgICAgJ0VSUl9OT1RfU1VQUE9SVCdcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFkYXB0ZXI7XG4gIH0sXG4gIGFkYXB0ZXJzOiBrbm93bkFkYXB0ZXJzXG59O1xuXG4vKipcbiAqIFRocm93cyBhIGBDYW5jZWxlZEVycm9yYCBpZiBjYW5jZWxsYXRpb24gaGFzIGJlZW4gcmVxdWVzdGVkLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgVGhlIGNvbmZpZyB0aGF0IGlzIHRvIGJlIHVzZWQgZm9yIHRoZSByZXF1ZXN0XG4gKlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHRocm93SWZDYW5jZWxsYXRpb25SZXF1ZXN0ZWQoY29uZmlnKSB7XG4gIGlmIChjb25maWcuY2FuY2VsVG9rZW4pIHtcbiAgICBjb25maWcuY2FuY2VsVG9rZW4udGhyb3dJZlJlcXVlc3RlZCgpO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5zaWduYWwgJiYgY29uZmlnLnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgdGhyb3cgbmV3IENhbmNlbGVkRXJyb3IobnVsbCwgY29uZmlnKTtcbiAgfVxufVxuXG4vKipcbiAqIERpc3BhdGNoIGEgcmVxdWVzdCB0byB0aGUgc2VydmVyIHVzaW5nIHRoZSBjb25maWd1cmVkIGFkYXB0ZXIuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IGNvbmZpZyBUaGUgY29uZmlnIHRoYXQgaXMgdG8gYmUgdXNlZCBmb3IgdGhlIHJlcXVlc3RcbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZX0gVGhlIFByb21pc2UgdG8gYmUgZnVsZmlsbGVkXG4gKi9cbmZ1bmN0aW9uIGRpc3BhdGNoUmVxdWVzdChjb25maWcpIHtcbiAgdGhyb3dJZkNhbmNlbGxhdGlvblJlcXVlc3RlZChjb25maWcpO1xuXG4gIGNvbmZpZy5oZWFkZXJzID0gQXhpb3NIZWFkZXJzJDEuZnJvbShjb25maWcuaGVhZGVycyk7XG5cbiAgLy8gVHJhbnNmb3JtIHJlcXVlc3QgZGF0YVxuICBjb25maWcuZGF0YSA9IHRyYW5zZm9ybURhdGEuY2FsbChcbiAgICBjb25maWcsXG4gICAgY29uZmlnLnRyYW5zZm9ybVJlcXVlc3RcbiAgKTtcblxuICBpZiAoWydwb3N0JywgJ3B1dCcsICdwYXRjaCddLmluZGV4T2YoY29uZmlnLm1ldGhvZCkgIT09IC0xKSB7XG4gICAgY29uZmlnLmhlYWRlcnMuc2V0Q29udGVudFR5cGUoJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcsIGZhbHNlKTtcbiAgfVxuXG4gIGNvbnN0IGFkYXB0ZXIgPSBhZGFwdGVycy5nZXRBZGFwdGVyKGNvbmZpZy5hZGFwdGVyIHx8IGRlZmF1bHRzJDEuYWRhcHRlcik7XG5cbiAgcmV0dXJuIGFkYXB0ZXIoY29uZmlnKS50aGVuKGZ1bmN0aW9uIG9uQWRhcHRlclJlc29sdXRpb24ocmVzcG9uc2UpIHtcbiAgICB0aHJvd0lmQ2FuY2VsbGF0aW9uUmVxdWVzdGVkKGNvbmZpZyk7XG5cbiAgICAvLyBUcmFuc2Zvcm0gcmVzcG9uc2UgZGF0YVxuICAgIHJlc3BvbnNlLmRhdGEgPSB0cmFuc2Zvcm1EYXRhLmNhbGwoXG4gICAgICBjb25maWcsXG4gICAgICBjb25maWcudHJhbnNmb3JtUmVzcG9uc2UsXG4gICAgICByZXNwb25zZVxuICAgICk7XG5cbiAgICByZXNwb25zZS5oZWFkZXJzID0gQXhpb3NIZWFkZXJzJDEuZnJvbShyZXNwb25zZS5oZWFkZXJzKTtcblxuICAgIHJldHVybiByZXNwb25zZTtcbiAgfSwgZnVuY3Rpb24gb25BZGFwdGVyUmVqZWN0aW9uKHJlYXNvbikge1xuICAgIGlmICghaXNDYW5jZWwocmVhc29uKSkge1xuICAgICAgdGhyb3dJZkNhbmNlbGxhdGlvblJlcXVlc3RlZChjb25maWcpO1xuXG4gICAgICAvLyBUcmFuc2Zvcm0gcmVzcG9uc2UgZGF0YVxuICAgICAgaWYgKHJlYXNvbiAmJiByZWFzb24ucmVzcG9uc2UpIHtcbiAgICAgICAgcmVhc29uLnJlc3BvbnNlLmRhdGEgPSB0cmFuc2Zvcm1EYXRhLmNhbGwoXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICAgIGNvbmZpZy50cmFuc2Zvcm1SZXNwb25zZSxcbiAgICAgICAgICByZWFzb24ucmVzcG9uc2VcbiAgICAgICAgKTtcbiAgICAgICAgcmVhc29uLnJlc3BvbnNlLmhlYWRlcnMgPSBBeGlvc0hlYWRlcnMkMS5mcm9tKHJlYXNvbi5yZXNwb25zZS5oZWFkZXJzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QocmVhc29uKTtcbiAgfSk7XG59XG5cbmNvbnN0IGhlYWRlcnNUb09iamVjdCA9ICh0aGluZykgPT4gdGhpbmcgaW5zdGFuY2VvZiBBeGlvc0hlYWRlcnMkMSA/IHsgLi4udGhpbmcgfSA6IHRoaW5nO1xuXG4vKipcbiAqIENvbmZpZy1zcGVjaWZpYyBtZXJnZS1mdW5jdGlvbiB3aGljaCBjcmVhdGVzIGEgbmV3IGNvbmZpZy1vYmplY3RcbiAqIGJ5IG1lcmdpbmcgdHdvIGNvbmZpZ3VyYXRpb24gb2JqZWN0cyB0b2dldGhlci5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY29uZmlnMVxuICogQHBhcmFtIHtPYmplY3R9IGNvbmZpZzJcbiAqXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBOZXcgb2JqZWN0IHJlc3VsdGluZyBmcm9tIG1lcmdpbmcgY29uZmlnMiB0byBjb25maWcxXG4gKi9cbmZ1bmN0aW9uIG1lcmdlQ29uZmlnKGNvbmZpZzEsIGNvbmZpZzIpIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG4gIGNvbmZpZzIgPSBjb25maWcyIHx8IHt9O1xuICBjb25zdCBjb25maWcgPSB7fTtcblxuICBmdW5jdGlvbiBnZXRNZXJnZWRWYWx1ZSh0YXJnZXQsIHNvdXJjZSwgY2FzZWxlc3MpIHtcbiAgICBpZiAodXRpbHMkMS5pc1BsYWluT2JqZWN0KHRhcmdldCkgJiYgdXRpbHMkMS5pc1BsYWluT2JqZWN0KHNvdXJjZSkpIHtcbiAgICAgIHJldHVybiB1dGlscyQxLm1lcmdlLmNhbGwoe2Nhc2VsZXNzfSwgdGFyZ2V0LCBzb3VyY2UpO1xuICAgIH0gZWxzZSBpZiAodXRpbHMkMS5pc1BsYWluT2JqZWN0KHNvdXJjZSkpIHtcbiAgICAgIHJldHVybiB1dGlscyQxLm1lcmdlKHt9LCBzb3VyY2UpO1xuICAgIH0gZWxzZSBpZiAodXRpbHMkMS5pc0FycmF5KHNvdXJjZSkpIHtcbiAgICAgIHJldHVybiBzb3VyY2Uuc2xpY2UoKTtcbiAgICB9XG4gICAgcmV0dXJuIHNvdXJjZTtcbiAgfVxuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjb25zaXN0ZW50LXJldHVyblxuICBmdW5jdGlvbiBtZXJnZURlZXBQcm9wZXJ0aWVzKGEsIGIsIGNhc2VsZXNzKSB7XG4gICAgaWYgKCF1dGlscyQxLmlzVW5kZWZpbmVkKGIpKSB7XG4gICAgICByZXR1cm4gZ2V0TWVyZ2VkVmFsdWUoYSwgYiwgY2FzZWxlc3MpO1xuICAgIH0gZWxzZSBpZiAoIXV0aWxzJDEuaXNVbmRlZmluZWQoYSkpIHtcbiAgICAgIHJldHVybiBnZXRNZXJnZWRWYWx1ZSh1bmRlZmluZWQsIGEsIGNhc2VsZXNzKTtcbiAgICB9XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29uc2lzdGVudC1yZXR1cm5cbiAgZnVuY3Rpb24gdmFsdWVGcm9tQ29uZmlnMihhLCBiKSB7XG4gICAgaWYgKCF1dGlscyQxLmlzVW5kZWZpbmVkKGIpKSB7XG4gICAgICByZXR1cm4gZ2V0TWVyZ2VkVmFsdWUodW5kZWZpbmVkLCBiKTtcbiAgICB9XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29uc2lzdGVudC1yZXR1cm5cbiAgZnVuY3Rpb24gZGVmYXVsdFRvQ29uZmlnMihhLCBiKSB7XG4gICAgaWYgKCF1dGlscyQxLmlzVW5kZWZpbmVkKGIpKSB7XG4gICAgICByZXR1cm4gZ2V0TWVyZ2VkVmFsdWUodW5kZWZpbmVkLCBiKTtcbiAgICB9IGVsc2UgaWYgKCF1dGlscyQxLmlzVW5kZWZpbmVkKGEpKSB7XG4gICAgICByZXR1cm4gZ2V0TWVyZ2VkVmFsdWUodW5kZWZpbmVkLCBhKTtcbiAgICB9XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29uc2lzdGVudC1yZXR1cm5cbiAgZnVuY3Rpb24gbWVyZ2VEaXJlY3RLZXlzKGEsIGIsIHByb3ApIHtcbiAgICBpZiAocHJvcCBpbiBjb25maWcyKSB7XG4gICAgICByZXR1cm4gZ2V0TWVyZ2VkVmFsdWUoYSwgYik7XG4gICAgfSBlbHNlIGlmIChwcm9wIGluIGNvbmZpZzEpIHtcbiAgICAgIHJldHVybiBnZXRNZXJnZWRWYWx1ZSh1bmRlZmluZWQsIGEpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG1lcmdlTWFwID0ge1xuICAgIHVybDogdmFsdWVGcm9tQ29uZmlnMixcbiAgICBtZXRob2Q6IHZhbHVlRnJvbUNvbmZpZzIsXG4gICAgZGF0YTogdmFsdWVGcm9tQ29uZmlnMixcbiAgICBiYXNlVVJMOiBkZWZhdWx0VG9Db25maWcyLFxuICAgIHRyYW5zZm9ybVJlcXVlc3Q6IGRlZmF1bHRUb0NvbmZpZzIsXG4gICAgdHJhbnNmb3JtUmVzcG9uc2U6IGRlZmF1bHRUb0NvbmZpZzIsXG4gICAgcGFyYW1zU2VyaWFsaXplcjogZGVmYXVsdFRvQ29uZmlnMixcbiAgICB0aW1lb3V0OiBkZWZhdWx0VG9Db25maWcyLFxuICAgIHRpbWVvdXRNZXNzYWdlOiBkZWZhdWx0VG9Db25maWcyLFxuICAgIHdpdGhDcmVkZW50aWFsczogZGVmYXVsdFRvQ29uZmlnMixcbiAgICB3aXRoWFNSRlRva2VuOiBkZWZhdWx0VG9Db25maWcyLFxuICAgIGFkYXB0ZXI6IGRlZmF1bHRUb0NvbmZpZzIsXG4gICAgcmVzcG9uc2VUeXBlOiBkZWZhdWx0VG9Db25maWcyLFxuICAgIHhzcmZDb29raWVOYW1lOiBkZWZhdWx0VG9Db25maWcyLFxuICAgIHhzcmZIZWFkZXJOYW1lOiBkZWZhdWx0VG9Db25maWcyLFxuICAgIG9uVXBsb2FkUHJvZ3Jlc3M6IGRlZmF1bHRUb0NvbmZpZzIsXG4gICAgb25Eb3dubG9hZFByb2dyZXNzOiBkZWZhdWx0VG9Db25maWcyLFxuICAgIGRlY29tcHJlc3M6IGRlZmF1bHRUb0NvbmZpZzIsXG4gICAgbWF4Q29udGVudExlbmd0aDogZGVmYXVsdFRvQ29uZmlnMixcbiAgICBtYXhCb2R5TGVuZ3RoOiBkZWZhdWx0VG9Db25maWcyLFxuICAgIGJlZm9yZVJlZGlyZWN0OiBkZWZhdWx0VG9Db25maWcyLFxuICAgIHRyYW5zcG9ydDogZGVmYXVsdFRvQ29uZmlnMixcbiAgICBodHRwQWdlbnQ6IGRlZmF1bHRUb0NvbmZpZzIsXG4gICAgaHR0cHNBZ2VudDogZGVmYXVsdFRvQ29uZmlnMixcbiAgICBjYW5jZWxUb2tlbjogZGVmYXVsdFRvQ29uZmlnMixcbiAgICBzb2NrZXRQYXRoOiBkZWZhdWx0VG9Db25maWcyLFxuICAgIHJlc3BvbnNlRW5jb2Rpbmc6IGRlZmF1bHRUb0NvbmZpZzIsXG4gICAgdmFsaWRhdGVTdGF0dXM6IG1lcmdlRGlyZWN0S2V5cyxcbiAgICBoZWFkZXJzOiAoYSwgYikgPT4gbWVyZ2VEZWVwUHJvcGVydGllcyhoZWFkZXJzVG9PYmplY3QoYSksIGhlYWRlcnNUb09iamVjdChiKSwgdHJ1ZSlcbiAgfTtcblxuICB1dGlscyQxLmZvckVhY2goT2JqZWN0LmtleXMoT2JqZWN0LmFzc2lnbih7fSwgY29uZmlnMSwgY29uZmlnMikpLCBmdW5jdGlvbiBjb21wdXRlQ29uZmlnVmFsdWUocHJvcCkge1xuICAgIGNvbnN0IG1lcmdlID0gbWVyZ2VNYXBbcHJvcF0gfHwgbWVyZ2VEZWVwUHJvcGVydGllcztcbiAgICBjb25zdCBjb25maWdWYWx1ZSA9IG1lcmdlKGNvbmZpZzFbcHJvcF0sIGNvbmZpZzJbcHJvcF0sIHByb3ApO1xuICAgICh1dGlscyQxLmlzVW5kZWZpbmVkKGNvbmZpZ1ZhbHVlKSAmJiBtZXJnZSAhPT0gbWVyZ2VEaXJlY3RLZXlzKSB8fCAoY29uZmlnW3Byb3BdID0gY29uZmlnVmFsdWUpO1xuICB9KTtcblxuICByZXR1cm4gY29uZmlnO1xufVxuXG5jb25zdCBWRVJTSU9OID0gXCIxLjYuOFwiO1xuXG5jb25zdCB2YWxpZGF0b3JzJDEgPSB7fTtcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGZ1bmMtbmFtZXNcblsnb2JqZWN0JywgJ2Jvb2xlYW4nLCAnbnVtYmVyJywgJ2Z1bmN0aW9uJywgJ3N0cmluZycsICdzeW1ib2wnXS5mb3JFYWNoKCh0eXBlLCBpKSA9PiB7XG4gIHZhbGlkYXRvcnMkMVt0eXBlXSA9IGZ1bmN0aW9uIHZhbGlkYXRvcih0aGluZykge1xuICAgIHJldHVybiB0eXBlb2YgdGhpbmcgPT09IHR5cGUgfHwgJ2EnICsgKGkgPCAxID8gJ24gJyA6ICcgJykgKyB0eXBlO1xuICB9O1xufSk7XG5cbmNvbnN0IGRlcHJlY2F0ZWRXYXJuaW5ncyA9IHt9O1xuXG4vKipcbiAqIFRyYW5zaXRpb25hbCBvcHRpb24gdmFsaWRhdG9yXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbnxib29sZWFuP30gdmFsaWRhdG9yIC0gc2V0IHRvIGZhbHNlIGlmIHRoZSB0cmFuc2l0aW9uYWwgb3B0aW9uIGhhcyBiZWVuIHJlbW92ZWRcbiAqIEBwYXJhbSB7c3RyaW5nP30gdmVyc2lvbiAtIGRlcHJlY2F0ZWQgdmVyc2lvbiAvIHJlbW92ZWQgc2luY2UgdmVyc2lvblxuICogQHBhcmFtIHtzdHJpbmc/fSBtZXNzYWdlIC0gc29tZSBtZXNzYWdlIHdpdGggYWRkaXRpb25hbCBpbmZvXG4gKlxuICogQHJldHVybnMge2Z1bmN0aW9ufVxuICovXG52YWxpZGF0b3JzJDEudHJhbnNpdGlvbmFsID0gZnVuY3Rpb24gdHJhbnNpdGlvbmFsKHZhbGlkYXRvciwgdmVyc2lvbiwgbWVzc2FnZSkge1xuICBmdW5jdGlvbiBmb3JtYXRNZXNzYWdlKG9wdCwgZGVzYykge1xuICAgIHJldHVybiAnW0F4aW9zIHYnICsgVkVSU0lPTiArICddIFRyYW5zaXRpb25hbCBvcHRpb24gXFwnJyArIG9wdCArICdcXCcnICsgZGVzYyArIChtZXNzYWdlID8gJy4gJyArIG1lc3NhZ2UgOiAnJyk7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZnVuYy1uYW1lc1xuICByZXR1cm4gKHZhbHVlLCBvcHQsIG9wdHMpID0+IHtcbiAgICBpZiAodmFsaWRhdG9yID09PSBmYWxzZSkge1xuICAgICAgdGhyb3cgbmV3IEF4aW9zRXJyb3IoXG4gICAgICAgIGZvcm1hdE1lc3NhZ2Uob3B0LCAnIGhhcyBiZWVuIHJlbW92ZWQnICsgKHZlcnNpb24gPyAnIGluICcgKyB2ZXJzaW9uIDogJycpKSxcbiAgICAgICAgQXhpb3NFcnJvci5FUlJfREVQUkVDQVRFRFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodmVyc2lvbiAmJiAhZGVwcmVjYXRlZFdhcm5pbmdzW29wdF0pIHtcbiAgICAgIGRlcHJlY2F0ZWRXYXJuaW5nc1tvcHRdID0gdHJ1ZTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGZvcm1hdE1lc3NhZ2UoXG4gICAgICAgICAgb3B0LFxuICAgICAgICAgICcgaGFzIGJlZW4gZGVwcmVjYXRlZCBzaW5jZSB2JyArIHZlcnNpb24gKyAnIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gdGhlIG5lYXIgZnV0dXJlJ1xuICAgICAgICApXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB2YWxpZGF0b3IgPyB2YWxpZGF0b3IodmFsdWUsIG9wdCwgb3B0cykgOiB0cnVlO1xuICB9O1xufTtcblxuLyoqXG4gKiBBc3NlcnQgb2JqZWN0J3MgcHJvcGVydGllcyB0eXBlXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAqIEBwYXJhbSB7b2JqZWN0fSBzY2hlbWFcbiAqIEBwYXJhbSB7Ym9vbGVhbj99IGFsbG93VW5rbm93blxuICpcbiAqIEByZXR1cm5zIHtvYmplY3R9XG4gKi9cblxuZnVuY3Rpb24gYXNzZXJ0T3B0aW9ucyhvcHRpb25zLCBzY2hlbWEsIGFsbG93VW5rbm93bikge1xuICBpZiAodHlwZW9mIG9wdGlvbnMgIT09ICdvYmplY3QnKSB7XG4gICAgdGhyb3cgbmV3IEF4aW9zRXJyb3IoJ29wdGlvbnMgbXVzdCBiZSBhbiBvYmplY3QnLCBBeGlvc0Vycm9yLkVSUl9CQURfT1BUSU9OX1ZBTFVFKTtcbiAgfVxuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMob3B0aW9ucyk7XG4gIGxldCBpID0ga2V5cy5sZW5ndGg7XG4gIHdoaWxlIChpLS0gPiAwKSB7XG4gICAgY29uc3Qgb3B0ID0ga2V5c1tpXTtcbiAgICBjb25zdCB2YWxpZGF0b3IgPSBzY2hlbWFbb3B0XTtcbiAgICBpZiAodmFsaWRhdG9yKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IG9wdGlvbnNbb3B0XTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsaWRhdG9yKHZhbHVlLCBvcHQsIG9wdGlvbnMpO1xuICAgICAgaWYgKHJlc3VsdCAhPT0gdHJ1ZSkge1xuICAgICAgICB0aHJvdyBuZXcgQXhpb3NFcnJvcignb3B0aW9uICcgKyBvcHQgKyAnIG11c3QgYmUgJyArIHJlc3VsdCwgQXhpb3NFcnJvci5FUlJfQkFEX09QVElPTl9WQUxVRSk7XG4gICAgICB9XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKGFsbG93VW5rbm93biAhPT0gdHJ1ZSkge1xuICAgICAgdGhyb3cgbmV3IEF4aW9zRXJyb3IoJ1Vua25vd24gb3B0aW9uICcgKyBvcHQsIEF4aW9zRXJyb3IuRVJSX0JBRF9PUFRJT04pO1xuICAgIH1cbiAgfVxufVxuXG52YXIgdmFsaWRhdG9yID0ge1xuICBhc3NlcnRPcHRpb25zLFxuICB2YWxpZGF0b3JzOiB2YWxpZGF0b3JzJDFcbn07XG5cbmNvbnN0IHZhbGlkYXRvcnMgPSB2YWxpZGF0b3IudmFsaWRhdG9ycztcblxuLyoqXG4gKiBDcmVhdGUgYSBuZXcgaW5zdGFuY2Ugb2YgQXhpb3NcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gaW5zdGFuY2VDb25maWcgVGhlIGRlZmF1bHQgY29uZmlnIGZvciB0aGUgaW5zdGFuY2VcbiAqXG4gKiBAcmV0dXJuIHtBeGlvc30gQSBuZXcgaW5zdGFuY2Ugb2YgQXhpb3NcbiAqL1xuY2xhc3MgQXhpb3Mge1xuICBjb25zdHJ1Y3RvcihpbnN0YW5jZUNvbmZpZykge1xuICAgIHRoaXMuZGVmYXVsdHMgPSBpbnN0YW5jZUNvbmZpZztcbiAgICB0aGlzLmludGVyY2VwdG9ycyA9IHtcbiAgICAgIHJlcXVlc3Q6IG5ldyBJbnRlcmNlcHRvck1hbmFnZXIoKSxcbiAgICAgIHJlc3BvbnNlOiBuZXcgSW50ZXJjZXB0b3JNYW5hZ2VyKClcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIERpc3BhdGNoIGEgcmVxdWVzdFxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R9IGNvbmZpZ09yVXJsIFRoZSBjb25maWcgc3BlY2lmaWMgZm9yIHRoaXMgcmVxdWVzdCAobWVyZ2VkIHdpdGggdGhpcy5kZWZhdWx0cylcbiAgICogQHBhcmFtIHs/T2JqZWN0fSBjb25maWdcbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2V9IFRoZSBQcm9taXNlIHRvIGJlIGZ1bGZpbGxlZFxuICAgKi9cbiAgYXN5bmMgcmVxdWVzdChjb25maWdPclVybCwgY29uZmlnKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLl9yZXF1ZXN0KGNvbmZpZ09yVXJsLCBjb25maWcpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIGxldCBkdW1teTtcblxuICAgICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSA/IEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKGR1bW15ID0ge30pIDogKGR1bW15ID0gbmV3IEVycm9yKCkpO1xuXG4gICAgICAgIC8vIHNsaWNlIG9mZiB0aGUgRXJyb3I6IC4uLiBsaW5lXG4gICAgICAgIGNvbnN0IHN0YWNrID0gZHVtbXkuc3RhY2sgPyBkdW1teS5zdGFjay5yZXBsYWNlKC9eLitcXG4vLCAnJykgOiAnJztcblxuICAgICAgICBpZiAoIWVyci5zdGFjaykge1xuICAgICAgICAgIGVyci5zdGFjayA9IHN0YWNrO1xuICAgICAgICAgIC8vIG1hdGNoIHdpdGhvdXQgdGhlIDIgdG9wIHN0YWNrIGxpbmVzXG4gICAgICAgIH0gZWxzZSBpZiAoc3RhY2sgJiYgIVN0cmluZyhlcnIuc3RhY2spLmVuZHNXaXRoKHN0YWNrLnJlcGxhY2UoL14uK1xcbi4rXFxuLywgJycpKSkge1xuICAgICAgICAgIGVyci5zdGFjayArPSAnXFxuJyArIHN0YWNrO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gIH1cblxuICBfcmVxdWVzdChjb25maWdPclVybCwgY29uZmlnKSB7XG4gICAgLyplc2xpbnQgbm8tcGFyYW0tcmVhc3NpZ246MCovXG4gICAgLy8gQWxsb3cgZm9yIGF4aW9zKCdleGFtcGxlL3VybCdbLCBjb25maWddKSBhIGxhIGZldGNoIEFQSVxuICAgIGlmICh0eXBlb2YgY29uZmlnT3JVcmwgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb25maWcgPSBjb25maWcgfHwge307XG4gICAgICBjb25maWcudXJsID0gY29uZmlnT3JVcmw7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbmZpZyA9IGNvbmZpZ09yVXJsIHx8IHt9O1xuICAgIH1cblxuICAgIGNvbmZpZyA9IG1lcmdlQ29uZmlnKHRoaXMuZGVmYXVsdHMsIGNvbmZpZyk7XG5cbiAgICBjb25zdCB7dHJhbnNpdGlvbmFsLCBwYXJhbXNTZXJpYWxpemVyLCBoZWFkZXJzfSA9IGNvbmZpZztcblxuICAgIGlmICh0cmFuc2l0aW9uYWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdmFsaWRhdG9yLmFzc2VydE9wdGlvbnModHJhbnNpdGlvbmFsLCB7XG4gICAgICAgIHNpbGVudEpTT05QYXJzaW5nOiB2YWxpZGF0b3JzLnRyYW5zaXRpb25hbCh2YWxpZGF0b3JzLmJvb2xlYW4pLFxuICAgICAgICBmb3JjZWRKU09OUGFyc2luZzogdmFsaWRhdG9ycy50cmFuc2l0aW9uYWwodmFsaWRhdG9ycy5ib29sZWFuKSxcbiAgICAgICAgY2xhcmlmeVRpbWVvdXRFcnJvcjogdmFsaWRhdG9ycy50cmFuc2l0aW9uYWwodmFsaWRhdG9ycy5ib29sZWFuKVxuICAgICAgfSwgZmFsc2UpO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXNTZXJpYWxpemVyICE9IG51bGwpIHtcbiAgICAgIGlmICh1dGlscyQxLmlzRnVuY3Rpb24ocGFyYW1zU2VyaWFsaXplcikpIHtcbiAgICAgICAgY29uZmlnLnBhcmFtc1NlcmlhbGl6ZXIgPSB7XG4gICAgICAgICAgc2VyaWFsaXplOiBwYXJhbXNTZXJpYWxpemVyXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YWxpZGF0b3IuYXNzZXJ0T3B0aW9ucyhwYXJhbXNTZXJpYWxpemVyLCB7XG4gICAgICAgICAgZW5jb2RlOiB2YWxpZGF0b3JzLmZ1bmN0aW9uLFxuICAgICAgICAgIHNlcmlhbGl6ZTogdmFsaWRhdG9ycy5mdW5jdGlvblxuICAgICAgICB9LCB0cnVlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTZXQgY29uZmlnLm1ldGhvZFxuICAgIGNvbmZpZy5tZXRob2QgPSAoY29uZmlnLm1ldGhvZCB8fCB0aGlzLmRlZmF1bHRzLm1ldGhvZCB8fCAnZ2V0JykudG9Mb3dlckNhc2UoKTtcblxuICAgIC8vIEZsYXR0ZW4gaGVhZGVyc1xuICAgIGxldCBjb250ZXh0SGVhZGVycyA9IGhlYWRlcnMgJiYgdXRpbHMkMS5tZXJnZShcbiAgICAgIGhlYWRlcnMuY29tbW9uLFxuICAgICAgaGVhZGVyc1tjb25maWcubWV0aG9kXVxuICAgICk7XG5cbiAgICBoZWFkZXJzICYmIHV0aWxzJDEuZm9yRWFjaChcbiAgICAgIFsnZGVsZXRlJywgJ2dldCcsICdoZWFkJywgJ3Bvc3QnLCAncHV0JywgJ3BhdGNoJywgJ2NvbW1vbiddLFxuICAgICAgKG1ldGhvZCkgPT4ge1xuICAgICAgICBkZWxldGUgaGVhZGVyc1ttZXRob2RdO1xuICAgICAgfVxuICAgICk7XG5cbiAgICBjb25maWcuaGVhZGVycyA9IEF4aW9zSGVhZGVycyQxLmNvbmNhdChjb250ZXh0SGVhZGVycywgaGVhZGVycyk7XG5cbiAgICAvLyBmaWx0ZXIgb3V0IHNraXBwZWQgaW50ZXJjZXB0b3JzXG4gICAgY29uc3QgcmVxdWVzdEludGVyY2VwdG9yQ2hhaW4gPSBbXTtcbiAgICBsZXQgc3luY2hyb25vdXNSZXF1ZXN0SW50ZXJjZXB0b3JzID0gdHJ1ZTtcbiAgICB0aGlzLmludGVyY2VwdG9ycy5yZXF1ZXN0LmZvckVhY2goZnVuY3Rpb24gdW5zaGlmdFJlcXVlc3RJbnRlcmNlcHRvcnMoaW50ZXJjZXB0b3IpIHtcbiAgICAgIGlmICh0eXBlb2YgaW50ZXJjZXB0b3IucnVuV2hlbiA9PT0gJ2Z1bmN0aW9uJyAmJiBpbnRlcmNlcHRvci5ydW5XaGVuKGNvbmZpZykgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgc3luY2hyb25vdXNSZXF1ZXN0SW50ZXJjZXB0b3JzID0gc3luY2hyb25vdXNSZXF1ZXN0SW50ZXJjZXB0b3JzICYmIGludGVyY2VwdG9yLnN5bmNocm9ub3VzO1xuXG4gICAgICByZXF1ZXN0SW50ZXJjZXB0b3JDaGFpbi51bnNoaWZ0KGludGVyY2VwdG9yLmZ1bGZpbGxlZCwgaW50ZXJjZXB0b3IucmVqZWN0ZWQpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzcG9uc2VJbnRlcmNlcHRvckNoYWluID0gW107XG4gICAgdGhpcy5pbnRlcmNlcHRvcnMucmVzcG9uc2UuZm9yRWFjaChmdW5jdGlvbiBwdXNoUmVzcG9uc2VJbnRlcmNlcHRvcnMoaW50ZXJjZXB0b3IpIHtcbiAgICAgIHJlc3BvbnNlSW50ZXJjZXB0b3JDaGFpbi5wdXNoKGludGVyY2VwdG9yLmZ1bGZpbGxlZCwgaW50ZXJjZXB0b3IucmVqZWN0ZWQpO1xuICAgIH0pO1xuXG4gICAgbGV0IHByb21pc2U7XG4gICAgbGV0IGkgPSAwO1xuICAgIGxldCBsZW47XG5cbiAgICBpZiAoIXN5bmNocm9ub3VzUmVxdWVzdEludGVyY2VwdG9ycykge1xuICAgICAgY29uc3QgY2hhaW4gPSBbZGlzcGF0Y2hSZXF1ZXN0LmJpbmQodGhpcyksIHVuZGVmaW5lZF07XG4gICAgICBjaGFpbi51bnNoaWZ0LmFwcGx5KGNoYWluLCByZXF1ZXN0SW50ZXJjZXB0b3JDaGFpbik7XG4gICAgICBjaGFpbi5wdXNoLmFwcGx5KGNoYWluLCByZXNwb25zZUludGVyY2VwdG9yQ2hhaW4pO1xuICAgICAgbGVuID0gY2hhaW4ubGVuZ3RoO1xuXG4gICAgICBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKGNvbmZpZyk7XG5cbiAgICAgIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgICAgIHByb21pc2UgPSBwcm9taXNlLnRoZW4oY2hhaW5baSsrXSwgY2hhaW5baSsrXSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIGxlbiA9IHJlcXVlc3RJbnRlcmNlcHRvckNoYWluLmxlbmd0aDtcblxuICAgIGxldCBuZXdDb25maWcgPSBjb25maWc7XG5cbiAgICBpID0gMDtcblxuICAgIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgICBjb25zdCBvbkZ1bGZpbGxlZCA9IHJlcXVlc3RJbnRlcmNlcHRvckNoYWluW2krK107XG4gICAgICBjb25zdCBvblJlamVjdGVkID0gcmVxdWVzdEludGVyY2VwdG9yQ2hhaW5baSsrXTtcbiAgICAgIHRyeSB7XG4gICAgICAgIG5ld0NvbmZpZyA9IG9uRnVsZmlsbGVkKG5ld0NvbmZpZyk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBvblJlamVjdGVkLmNhbGwodGhpcywgZXJyb3IpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgcHJvbWlzZSA9IGRpc3BhdGNoUmVxdWVzdC5jYWxsKHRoaXMsIG5ld0NvbmZpZyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7XG4gICAgfVxuXG4gICAgaSA9IDA7XG4gICAgbGVuID0gcmVzcG9uc2VJbnRlcmNlcHRvckNoYWluLmxlbmd0aDtcblxuICAgIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgICBwcm9taXNlID0gcHJvbWlzZS50aGVuKHJlc3BvbnNlSW50ZXJjZXB0b3JDaGFpbltpKytdLCByZXNwb25zZUludGVyY2VwdG9yQ2hhaW5baSsrXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb21pc2U7XG4gIH1cblxuICBnZXRVcmkoY29uZmlnKSB7XG4gICAgY29uZmlnID0gbWVyZ2VDb25maWcodGhpcy5kZWZhdWx0cywgY29uZmlnKTtcbiAgICBjb25zdCBmdWxsUGF0aCA9IGJ1aWxkRnVsbFBhdGgoY29uZmlnLmJhc2VVUkwsIGNvbmZpZy51cmwpO1xuICAgIHJldHVybiBidWlsZFVSTChmdWxsUGF0aCwgY29uZmlnLnBhcmFtcywgY29uZmlnLnBhcmFtc1NlcmlhbGl6ZXIpO1xuICB9XG59XG5cbi8vIFByb3ZpZGUgYWxpYXNlcyBmb3Igc3VwcG9ydGVkIHJlcXVlc3QgbWV0aG9kc1xudXRpbHMkMS5mb3JFYWNoKFsnZGVsZXRlJywgJ2dldCcsICdoZWFkJywgJ29wdGlvbnMnXSwgZnVuY3Rpb24gZm9yRWFjaE1ldGhvZE5vRGF0YShtZXRob2QpIHtcbiAgLyplc2xpbnQgZnVuYy1uYW1lczowKi9cbiAgQXhpb3MucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbih1cmwsIGNvbmZpZykge1xuICAgIHJldHVybiB0aGlzLnJlcXVlc3QobWVyZ2VDb25maWcoY29uZmlnIHx8IHt9LCB7XG4gICAgICBtZXRob2QsXG4gICAgICB1cmwsXG4gICAgICBkYXRhOiAoY29uZmlnIHx8IHt9KS5kYXRhXG4gICAgfSkpO1xuICB9O1xufSk7XG5cbnV0aWxzJDEuZm9yRWFjaChbJ3Bvc3QnLCAncHV0JywgJ3BhdGNoJ10sIGZ1bmN0aW9uIGZvckVhY2hNZXRob2RXaXRoRGF0YShtZXRob2QpIHtcbiAgLyplc2xpbnQgZnVuYy1uYW1lczowKi9cblxuICBmdW5jdGlvbiBnZW5lcmF0ZUhUVFBNZXRob2QoaXNGb3JtKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIGh0dHBNZXRob2QodXJsLCBkYXRhLCBjb25maWcpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlcXVlc3QobWVyZ2VDb25maWcoY29uZmlnIHx8IHt9LCB7XG4gICAgICAgIG1ldGhvZCxcbiAgICAgICAgaGVhZGVyczogaXNGb3JtID8ge1xuICAgICAgICAgICdDb250ZW50LVR5cGUnOiAnbXVsdGlwYXJ0L2Zvcm0tZGF0YSdcbiAgICAgICAgfSA6IHt9LFxuICAgICAgICB1cmwsXG4gICAgICAgIGRhdGFcbiAgICAgIH0pKTtcbiAgICB9O1xuICB9XG5cbiAgQXhpb3MucHJvdG90eXBlW21ldGhvZF0gPSBnZW5lcmF0ZUhUVFBNZXRob2QoKTtcblxuICBBeGlvcy5wcm90b3R5cGVbbWV0aG9kICsgJ0Zvcm0nXSA9IGdlbmVyYXRlSFRUUE1ldGhvZCh0cnVlKTtcbn0pO1xuXG52YXIgQXhpb3MkMSA9IEF4aW9zO1xuXG4vKipcbiAqIEEgYENhbmNlbFRva2VuYCBpcyBhbiBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB0byByZXF1ZXN0IGNhbmNlbGxhdGlvbiBvZiBhbiBvcGVyYXRpb24uXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZXhlY3V0b3IgVGhlIGV4ZWN1dG9yIGZ1bmN0aW9uLlxuICpcbiAqIEByZXR1cm5zIHtDYW5jZWxUb2tlbn1cbiAqL1xuY2xhc3MgQ2FuY2VsVG9rZW4ge1xuICBjb25zdHJ1Y3RvcihleGVjdXRvcikge1xuICAgIGlmICh0eXBlb2YgZXhlY3V0b3IgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2V4ZWN1dG9yIG11c3QgYmUgYSBmdW5jdGlvbi4nKTtcbiAgICB9XG5cbiAgICBsZXQgcmVzb2x2ZVByb21pc2U7XG5cbiAgICB0aGlzLnByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbiBwcm9taXNlRXhlY3V0b3IocmVzb2x2ZSkge1xuICAgICAgcmVzb2x2ZVByb21pc2UgPSByZXNvbHZlO1xuICAgIH0pO1xuXG4gICAgY29uc3QgdG9rZW4gPSB0aGlzO1xuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGZ1bmMtbmFtZXNcbiAgICB0aGlzLnByb21pc2UudGhlbihjYW5jZWwgPT4ge1xuICAgICAgaWYgKCF0b2tlbi5fbGlzdGVuZXJzKSByZXR1cm47XG5cbiAgICAgIGxldCBpID0gdG9rZW4uX2xpc3RlbmVycy5sZW5ndGg7XG5cbiAgICAgIHdoaWxlIChpLS0gPiAwKSB7XG4gICAgICAgIHRva2VuLl9saXN0ZW5lcnNbaV0oY2FuY2VsKTtcbiAgICAgIH1cbiAgICAgIHRva2VuLl9saXN0ZW5lcnMgPSBudWxsO1xuICAgIH0pO1xuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGZ1bmMtbmFtZXNcbiAgICB0aGlzLnByb21pc2UudGhlbiA9IG9uZnVsZmlsbGVkID0+IHtcbiAgICAgIGxldCBfcmVzb2x2ZTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBmdW5jLW5hbWVzXG4gICAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgIHRva2VuLnN1YnNjcmliZShyZXNvbHZlKTtcbiAgICAgICAgX3Jlc29sdmUgPSByZXNvbHZlO1xuICAgICAgfSkudGhlbihvbmZ1bGZpbGxlZCk7XG5cbiAgICAgIHByb21pc2UuY2FuY2VsID0gZnVuY3Rpb24gcmVqZWN0KCkge1xuICAgICAgICB0b2tlbi51bnN1YnNjcmliZShfcmVzb2x2ZSk7XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9O1xuXG4gICAgZXhlY3V0b3IoZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UsIGNvbmZpZywgcmVxdWVzdCkge1xuICAgICAgaWYgKHRva2VuLnJlYXNvbikge1xuICAgICAgICAvLyBDYW5jZWxsYXRpb24gaGFzIGFscmVhZHkgYmVlbiByZXF1ZXN0ZWRcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0b2tlbi5yZWFzb24gPSBuZXcgQ2FuY2VsZWRFcnJvcihtZXNzYWdlLCBjb25maWcsIHJlcXVlc3QpO1xuICAgICAgcmVzb2x2ZVByb21pc2UodG9rZW4ucmVhc29uKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaHJvd3MgYSBgQ2FuY2VsZWRFcnJvcmAgaWYgY2FuY2VsbGF0aW9uIGhhcyBiZWVuIHJlcXVlc3RlZC5cbiAgICovXG4gIHRocm93SWZSZXF1ZXN0ZWQoKSB7XG4gICAgaWYgKHRoaXMucmVhc29uKSB7XG4gICAgICB0aHJvdyB0aGlzLnJlYXNvbjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3Vic2NyaWJlIHRvIHRoZSBjYW5jZWwgc2lnbmFsXG4gICAqL1xuXG4gIHN1YnNjcmliZShsaXN0ZW5lcikge1xuICAgIGlmICh0aGlzLnJlYXNvbikge1xuICAgICAgbGlzdGVuZXIodGhpcy5yZWFzb24pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9saXN0ZW5lcnMpIHtcbiAgICAgIHRoaXMuX2xpc3RlbmVycy5wdXNoKGxpc3RlbmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fbGlzdGVuZXJzID0gW2xpc3RlbmVyXTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVW5zdWJzY3JpYmUgZnJvbSB0aGUgY2FuY2VsIHNpZ25hbFxuICAgKi9cblxuICB1bnN1YnNjcmliZShsaXN0ZW5lcikge1xuICAgIGlmICghdGhpcy5fbGlzdGVuZXJzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5fbGlzdGVuZXJzLmluZGV4T2YobGlzdGVuZXIpO1xuICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgIHRoaXMuX2xpc3RlbmVycy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIG9iamVjdCB0aGF0IGNvbnRhaW5zIGEgbmV3IGBDYW5jZWxUb2tlbmAgYW5kIGEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsXG4gICAqIGNhbmNlbHMgdGhlIGBDYW5jZWxUb2tlbmAuXG4gICAqL1xuICBzdGF0aWMgc291cmNlKCkge1xuICAgIGxldCBjYW5jZWw7XG4gICAgY29uc3QgdG9rZW4gPSBuZXcgQ2FuY2VsVG9rZW4oZnVuY3Rpb24gZXhlY3V0b3IoYykge1xuICAgICAgY2FuY2VsID0gYztcbiAgICB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgdG9rZW4sXG4gICAgICBjYW5jZWxcbiAgICB9O1xuICB9XG59XG5cbnZhciBDYW5jZWxUb2tlbiQxID0gQ2FuY2VsVG9rZW47XG5cbi8qKlxuICogU3ludGFjdGljIHN1Z2FyIGZvciBpbnZva2luZyBhIGZ1bmN0aW9uIGFuZCBleHBhbmRpbmcgYW4gYXJyYXkgZm9yIGFyZ3VtZW50cy5cbiAqXG4gKiBDb21tb24gdXNlIGNhc2Ugd291bGQgYmUgdG8gdXNlIGBGdW5jdGlvbi5wcm90b3R5cGUuYXBwbHlgLlxuICpcbiAqICBgYGBqc1xuICogIGZ1bmN0aW9uIGYoeCwgeSwgeikge31cbiAqICB2YXIgYXJncyA9IFsxLCAyLCAzXTtcbiAqICBmLmFwcGx5KG51bGwsIGFyZ3MpO1xuICogIGBgYFxuICpcbiAqIFdpdGggYHNwcmVhZGAgdGhpcyBleGFtcGxlIGNhbiBiZSByZS13cml0dGVuLlxuICpcbiAqICBgYGBqc1xuICogIHNwcmVhZChmdW5jdGlvbih4LCB5LCB6KSB7fSkoWzEsIDIsIDNdKTtcbiAqICBgYGBcbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICpcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn1cbiAqL1xuZnVuY3Rpb24gc3ByZWFkKGNhbGxiYWNrKSB7XG4gIHJldHVybiBmdW5jdGlvbiB3cmFwKGFycikge1xuICAgIHJldHVybiBjYWxsYmFjay5hcHBseShudWxsLCBhcnIpO1xuICB9O1xufVxuXG4vKipcbiAqIERldGVybWluZXMgd2hldGhlciB0aGUgcGF5bG9hZCBpcyBhbiBlcnJvciB0aHJvd24gYnkgQXhpb3NcbiAqXG4gKiBAcGFyYW0geyp9IHBheWxvYWQgVGhlIHZhbHVlIHRvIHRlc3RcbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgcGF5bG9hZCBpcyBhbiBlcnJvciB0aHJvd24gYnkgQXhpb3MsIG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0F4aW9zRXJyb3IocGF5bG9hZCkge1xuICByZXR1cm4gdXRpbHMkMS5pc09iamVjdChwYXlsb2FkKSAmJiAocGF5bG9hZC5pc0F4aW9zRXJyb3IgPT09IHRydWUpO1xufVxuXG5jb25zdCBIdHRwU3RhdHVzQ29kZSA9IHtcbiAgQ29udGludWU6IDEwMCxcbiAgU3dpdGNoaW5nUHJvdG9jb2xzOiAxMDEsXG4gIFByb2Nlc3Npbmc6IDEwMixcbiAgRWFybHlIaW50czogMTAzLFxuICBPazogMjAwLFxuICBDcmVhdGVkOiAyMDEsXG4gIEFjY2VwdGVkOiAyMDIsXG4gIE5vbkF1dGhvcml0YXRpdmVJbmZvcm1hdGlvbjogMjAzLFxuICBOb0NvbnRlbnQ6IDIwNCxcbiAgUmVzZXRDb250ZW50OiAyMDUsXG4gIFBhcnRpYWxDb250ZW50OiAyMDYsXG4gIE11bHRpU3RhdHVzOiAyMDcsXG4gIEFscmVhZHlSZXBvcnRlZDogMjA4LFxuICBJbVVzZWQ6IDIyNixcbiAgTXVsdGlwbGVDaG9pY2VzOiAzMDAsXG4gIE1vdmVkUGVybWFuZW50bHk6IDMwMSxcbiAgRm91bmQ6IDMwMixcbiAgU2VlT3RoZXI6IDMwMyxcbiAgTm90TW9kaWZpZWQ6IDMwNCxcbiAgVXNlUHJveHk6IDMwNSxcbiAgVW51c2VkOiAzMDYsXG4gIFRlbXBvcmFyeVJlZGlyZWN0OiAzMDcsXG4gIFBlcm1hbmVudFJlZGlyZWN0OiAzMDgsXG4gIEJhZFJlcXVlc3Q6IDQwMCxcbiAgVW5hdXRob3JpemVkOiA0MDEsXG4gIFBheW1lbnRSZXF1aXJlZDogNDAyLFxuICBGb3JiaWRkZW46IDQwMyxcbiAgTm90Rm91bmQ6IDQwNCxcbiAgTWV0aG9kTm90QWxsb3dlZDogNDA1LFxuICBOb3RBY2NlcHRhYmxlOiA0MDYsXG4gIFByb3h5QXV0aGVudGljYXRpb25SZXF1aXJlZDogNDA3LFxuICBSZXF1ZXN0VGltZW91dDogNDA4LFxuICBDb25mbGljdDogNDA5LFxuICBHb25lOiA0MTAsXG4gIExlbmd0aFJlcXVpcmVkOiA0MTEsXG4gIFByZWNvbmRpdGlvbkZhaWxlZDogNDEyLFxuICBQYXlsb2FkVG9vTGFyZ2U6IDQxMyxcbiAgVXJpVG9vTG9uZzogNDE0LFxuICBVbnN1cHBvcnRlZE1lZGlhVHlwZTogNDE1LFxuICBSYW5nZU5vdFNhdGlzZmlhYmxlOiA0MTYsXG4gIEV4cGVjdGF0aW9uRmFpbGVkOiA0MTcsXG4gIEltQVRlYXBvdDogNDE4LFxuICBNaXNkaXJlY3RlZFJlcXVlc3Q6IDQyMSxcbiAgVW5wcm9jZXNzYWJsZUVudGl0eTogNDIyLFxuICBMb2NrZWQ6IDQyMyxcbiAgRmFpbGVkRGVwZW5kZW5jeTogNDI0LFxuICBUb29FYXJseTogNDI1LFxuICBVcGdyYWRlUmVxdWlyZWQ6IDQyNixcbiAgUHJlY29uZGl0aW9uUmVxdWlyZWQ6IDQyOCxcbiAgVG9vTWFueVJlcXVlc3RzOiA0MjksXG4gIFJlcXVlc3RIZWFkZXJGaWVsZHNUb29MYXJnZTogNDMxLFxuICBVbmF2YWlsYWJsZUZvckxlZ2FsUmVhc29uczogNDUxLFxuICBJbnRlcm5hbFNlcnZlckVycm9yOiA1MDAsXG4gIE5vdEltcGxlbWVudGVkOiA1MDEsXG4gIEJhZEdhdGV3YXk6IDUwMixcbiAgU2VydmljZVVuYXZhaWxhYmxlOiA1MDMsXG4gIEdhdGV3YXlUaW1lb3V0OiA1MDQsXG4gIEh0dHBWZXJzaW9uTm90U3VwcG9ydGVkOiA1MDUsXG4gIFZhcmlhbnRBbHNvTmVnb3RpYXRlczogNTA2LFxuICBJbnN1ZmZpY2llbnRTdG9yYWdlOiA1MDcsXG4gIExvb3BEZXRlY3RlZDogNTA4LFxuICBOb3RFeHRlbmRlZDogNTEwLFxuICBOZXR3b3JrQXV0aGVudGljYXRpb25SZXF1aXJlZDogNTExLFxufTtcblxuT2JqZWN0LmVudHJpZXMoSHR0cFN0YXR1c0NvZGUpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICBIdHRwU3RhdHVzQ29kZVt2YWx1ZV0gPSBrZXk7XG59KTtcblxudmFyIEh0dHBTdGF0dXNDb2RlJDEgPSBIdHRwU3RhdHVzQ29kZTtcblxuLyoqXG4gKiBDcmVhdGUgYW4gaW5zdGFuY2Ugb2YgQXhpb3NcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gZGVmYXVsdENvbmZpZyBUaGUgZGVmYXVsdCBjb25maWcgZm9yIHRoZSBpbnN0YW5jZVxuICpcbiAqIEByZXR1cm5zIHtBeGlvc30gQSBuZXcgaW5zdGFuY2Ugb2YgQXhpb3NcbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW5zdGFuY2UoZGVmYXVsdENvbmZpZykge1xuICBjb25zdCBjb250ZXh0ID0gbmV3IEF4aW9zJDEoZGVmYXVsdENvbmZpZyk7XG4gIGNvbnN0IGluc3RhbmNlID0gYmluZChBeGlvcyQxLnByb3RvdHlwZS5yZXF1ZXN0LCBjb250ZXh0KTtcblxuICAvLyBDb3B5IGF4aW9zLnByb3RvdHlwZSB0byBpbnN0YW5jZVxuICB1dGlscyQxLmV4dGVuZChpbnN0YW5jZSwgQXhpb3MkMS5wcm90b3R5cGUsIGNvbnRleHQsIHthbGxPd25LZXlzOiB0cnVlfSk7XG5cbiAgLy8gQ29weSBjb250ZXh0IHRvIGluc3RhbmNlXG4gIHV0aWxzJDEuZXh0ZW5kKGluc3RhbmNlLCBjb250ZXh0LCBudWxsLCB7YWxsT3duS2V5czogdHJ1ZX0pO1xuXG4gIC8vIEZhY3RvcnkgZm9yIGNyZWF0aW5nIG5ldyBpbnN0YW5jZXNcbiAgaW5zdGFuY2UuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKGluc3RhbmNlQ29uZmlnKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUluc3RhbmNlKG1lcmdlQ29uZmlnKGRlZmF1bHRDb25maWcsIGluc3RhbmNlQ29uZmlnKSk7XG4gIH07XG5cbiAgcmV0dXJuIGluc3RhbmNlO1xufVxuXG4vLyBDcmVhdGUgdGhlIGRlZmF1bHQgaW5zdGFuY2UgdG8gYmUgZXhwb3J0ZWRcbmNvbnN0IGF4aW9zID0gY3JlYXRlSW5zdGFuY2UoZGVmYXVsdHMkMSk7XG5cbi8vIEV4cG9zZSBBeGlvcyBjbGFzcyB0byBhbGxvdyBjbGFzcyBpbmhlcml0YW5jZVxuYXhpb3MuQXhpb3MgPSBBeGlvcyQxO1xuXG4vLyBFeHBvc2UgQ2FuY2VsICYgQ2FuY2VsVG9rZW5cbmF4aW9zLkNhbmNlbGVkRXJyb3IgPSBDYW5jZWxlZEVycm9yO1xuYXhpb3MuQ2FuY2VsVG9rZW4gPSBDYW5jZWxUb2tlbiQxO1xuYXhpb3MuaXNDYW5jZWwgPSBpc0NhbmNlbDtcbmF4aW9zLlZFUlNJT04gPSBWRVJTSU9OO1xuYXhpb3MudG9Gb3JtRGF0YSA9IHRvRm9ybURhdGE7XG5cbi8vIEV4cG9zZSBBeGlvc0Vycm9yIGNsYXNzXG5heGlvcy5BeGlvc0Vycm9yID0gQXhpb3NFcnJvcjtcblxuLy8gYWxpYXMgZm9yIENhbmNlbGVkRXJyb3IgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbmF4aW9zLkNhbmNlbCA9IGF4aW9zLkNhbmNlbGVkRXJyb3I7XG5cbi8vIEV4cG9zZSBhbGwvc3ByZWFkXG5heGlvcy5hbGwgPSBmdW5jdGlvbiBhbGwocHJvbWlzZXMpIHtcbiAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbn07XG5cbmF4aW9zLnNwcmVhZCA9IHNwcmVhZDtcblxuLy8gRXhwb3NlIGlzQXhpb3NFcnJvclxuYXhpb3MuaXNBeGlvc0Vycm9yID0gaXNBeGlvc0Vycm9yO1xuXG4vLyBFeHBvc2UgbWVyZ2VDb25maWdcbmF4aW9zLm1lcmdlQ29uZmlnID0gbWVyZ2VDb25maWc7XG5cbmF4aW9zLkF4aW9zSGVhZGVycyA9IEF4aW9zSGVhZGVycyQxO1xuXG5heGlvcy5mb3JtVG9KU09OID0gdGhpbmcgPT4gZm9ybURhdGFUb0pTT04odXRpbHMkMS5pc0hUTUxGb3JtKHRoaW5nKSA/IG5ldyBGb3JtRGF0YSh0aGluZykgOiB0aGluZyk7XG5cbmF4aW9zLmdldEFkYXB0ZXIgPSBhZGFwdGVycy5nZXRBZGFwdGVyO1xuXG5heGlvcy5IdHRwU3RhdHVzQ29kZSA9IEh0dHBTdGF0dXNDb2RlJDE7XG5cbmF4aW9zLmRlZmF1bHQgPSBheGlvcztcblxudmFyIGRzPU9iamVjdC5kZWZpbmVQcm9wZXJ0eTt2YXIgemc9T2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjt2YXIgS2c9T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXM7dmFyIEdnPU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7dmFyIHdlPSh0LGUpPT4oKT0+KHQmJihlPXQodD0wKSksZSk7dmFyIE09KHQsZSk9PigpPT4oZXx8dCgoZT17ZXhwb3J0czp7fX0pLmV4cG9ydHMsZSksZS5leHBvcnRzKSxRdD0odCxlKT0+e2Zvcih2YXIgciBpbiBlKWRzKHQscix7Z2V0OmVbcl0sZW51bWVyYWJsZTohMH0pO30sUWc9KHQsZSxyLGkpPT57aWYoZSYmdHlwZW9mIGU9PVwib2JqZWN0XCJ8fHR5cGVvZiBlPT1cImZ1bmN0aW9uXCIpZm9yKGxldCBuIG9mIEtnKGUpKSFHZy5jYWxsKHQsbikmJm4hPT1yJiZkcyh0LG4se2dldDooKT0+ZVtuXSxlbnVtZXJhYmxlOiEoaT16ZyhlLG4pKXx8aS5lbnVtZXJhYmxlfSk7cmV0dXJuIHR9O3ZhciBYPXQ9PlFnKGRzKHt9LFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pLHQpO3ZhciBCLF89d2UoKCk9PntCPXtkZXZpY2VNZW1vcnk6OCxoYXJkd2FyZUNvbmN1cnJlbmN5OjgsbGFuZ3VhZ2U6XCJlbi1VU1wifTt9KTt2YXIgUD17fTtRdChQLHtfZGVidWdFbmQ6KCk9Pnl1LF9kZWJ1Z1Byb2Nlc3M6KCk9Pmd1LF9ldmVudHM6KCk9Pmt1LF9ldmVudHNDb3VudDooKT0+eHUsX2V4aXRpbmc6KCk9PllsLF9mYXRhbEV4Y2VwdGlvbnM6KCk9PmN1LF9nZXRBY3RpdmVIYW5kbGVzOigpPT5ldSxfZ2V0QWN0aXZlUmVxdWVzdHM6KCk9PlpsLF9raWxsOigpPT5ydSxfbGlua2VkQmluZGluZzooKT0+R2wsX21heExpc3RlbmVyczooKT0+T3UsX3ByZWxvYWRfbW9kdWxlczooKT0+Q3UsX3Jhd0RlYnVnOigpPT56bCxfc3RhcnRQcm9maWxlcklkbGVOb3RpZmllcjooKT0+YnUsX3N0b3BQcm9maWxlcklkbGVOb3RpZmllcjooKT0+d3UsX3RpY2tDYWxsYmFjazooKT0+cHUsYWJvcnQ6KCk9PkV1LGFkZExpc3RlbmVyOigpPT5NdSxhbGxvd2VkTm9kZUVudmlyb25tZW50RmxhZ3M6KCk9Pmx1LGFyY2g6KCk9PnhsLGFyZ3Y6KCk9PlVsLGFyZ3YwOigpPT5SdSxhc3NlcnQ6KCk9PnV1LGJpbmRpbmc6KCk9PkZsLGNoZGlyOigpPT5IbCxjb25maWc6KCk9PkpsLGNwdVVzYWdlOigpPT5GaSxjd2Q6KCk9PiRsLGRlYnVnUG9ydDooKT0+VHUsZGVmYXVsdDooKT0+JHUsZGxvcGVuOigpPT5YbCxkb21haW46KCk9PlFsLGVtaXQ6KCk9PkR1LGVtaXRXYXJuaW5nOigpPT5qbCxlbnY6KCk9PkxsLGV4ZWNBcmd2OigpPT5ObCxleGVjUGF0aDooKT0+SXUsZXhpdDooKT0+b3UsZmVhdHVyZXM6KCk9PmZ1LGhhc1VuY2F1Z2h0RXhjZXB0aW9uQ2FwdHVyZUNhbGxiYWNrOigpPT5kdSxocnRpbWU6KCk9PmppLGtpbGw6KCk9PnN1LGxpc3RlbmVyczooKT0+V3UsbWVtb3J5VXNhZ2U6KCk9Pm51LG1vZHVsZUxvYWRMaXN0OigpPT5LbCxuZXh0VGljazooKT0+UGwsb2ZmOigpPT5VdSxvbjooKT0+YnQsb25jZTooKT0+THUsb3BlblN0ZGluOigpPT5hdSxwaWQ6KCk9PlN1LHBsYXRmb3JtOigpPT5NbCxwcGlkOigpPT5BdSxwcmVwZW5kTGlzdGVuZXI6KCk9Pmp1LHByZXBlbmRPbmNlTGlzdGVuZXI6KCk9PkZ1LHJlYWxseUV4aXQ6KCk9PnR1LHJlbGVhc2U6KCk9PlZsLHJlbW92ZUFsbExpc3RlbmVyczooKT0+cXUscmVtb3ZlTGlzdGVuZXI6KCk9Pk51LHJlc291cmNlVXNhZ2U6KCk9Pml1LHNldFNvdXJjZU1hcHNFbmFibGVkOigpPT5CdSxzZXRVbmNhdWdodEV4Y2VwdGlvbkNhcHR1cmVDYWxsYmFjazooKT0+aHUsc3RkZXJyOigpPT5tdSxzdGRpbjooKT0+dnUsc3Rkb3V0OigpPT5fdSx0aXRsZTooKT0+a2wsdW1hc2s6KCk9PldsLHVwdGltZTooKT0+UHUsdmVyc2lvbjooKT0+cWwsdmVyc2lvbnM6KCk9PkRsfSk7ZnVuY3Rpb24geXModCl7dGhyb3cgbmV3IEVycm9yKFwiTm9kZS5qcyBwcm9jZXNzIFwiK3QrXCIgaXMgbm90IHN1cHBvcnRlZCBieSBKU1BNIGNvcmUgb3V0c2lkZSBvZiBOb2RlLmpzXCIpfWZ1bmN0aW9uIFlnKCl7IXhyfHwhWXR8fCh4cj0hMSxZdC5sZW5ndGg/eXQ9WXQuY29uY2F0KHl0KTpEaT0tMSx5dC5sZW5ndGgmJkJsKCkpO31mdW5jdGlvbiBCbCgpe2lmKCF4cil7dmFyIHQ9c2V0VGltZW91dChZZywwKTt4cj0hMDtmb3IodmFyIGU9eXQubGVuZ3RoO2U7KXtmb3IoWXQ9eXQseXQ9W107KytEaTxlOylZdCYmWXRbRGldLnJ1bigpO0RpPS0xLGU9eXQubGVuZ3RoO31ZdD1udWxsLHhyPSExLGNsZWFyVGltZW91dCh0KTt9fWZ1bmN0aW9uIFBsKHQpe3ZhciBlPW5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoLTEpO2lmKGFyZ3VtZW50cy5sZW5ndGg+MSlmb3IodmFyIHI9MTtyPGFyZ3VtZW50cy5sZW5ndGg7cisrKWVbci0xXT1hcmd1bWVudHNbcl07eXQucHVzaChuZXcgT2wodCxlKSkseXQubGVuZ3RoPT09MSYmIXhyJiZzZXRUaW1lb3V0KEJsLDApO31mdW5jdGlvbiBPbCh0LGUpe3RoaXMuZnVuPXQsdGhpcy5hcnJheT1lO31mdW5jdGlvbiB2ZSgpe31mdW5jdGlvbiBHbCh0KXt5cyhcIl9saW5rZWRCaW5kaW5nXCIpO31mdW5jdGlvbiBYbCh0KXt5cyhcImRsb3BlblwiKTt9ZnVuY3Rpb24gWmwoKXtyZXR1cm4gW119ZnVuY3Rpb24gZXUoKXtyZXR1cm4gW119ZnVuY3Rpb24gdXUodCxlKXtpZighdCl0aHJvdyBuZXcgRXJyb3IoZXx8XCJhc3NlcnRpb24gZXJyb3JcIil9ZnVuY3Rpb24gZHUoKXtyZXR1cm4gITF9ZnVuY3Rpb24gUHUoKXtyZXR1cm4gTXQubm93KCkvMWUzfWZ1bmN0aW9uIGppKHQpe3ZhciBlPU1hdGguZmxvb3IoKERhdGUubm93KCktTXQubm93KCkpKi4wMDEpLHI9TXQubm93KCkqLjAwMSxpPU1hdGguZmxvb3IocikrZSxuPU1hdGguZmxvb3IociUxKjFlOSk7cmV0dXJuIHQmJihpPWktdFswXSxuPW4tdFsxXSxuPDAmJihpLS0sbis9Z3MpKSxbaSxuXX1mdW5jdGlvbiBidCgpe3JldHVybiAkdX1mdW5jdGlvbiBXdSh0KXtyZXR1cm4gW119dmFyIHl0LHhyLFl0LERpLGtsLHhsLE1sLExsLFVsLE5sLHFsLERsLGpsLEZsLFdsLCRsLEhsLFZsLHpsLEtsLFFsLFlsLEpsLHR1LHJ1LEZpLGl1LG51LHN1LG91LGF1LGx1LGZ1LGN1LGh1LHB1LGd1LHl1LGJ1LHd1LF91LG11LHZ1LEV1LFN1LEF1LEl1LFR1LFJ1LEN1LEJ1LE10LHBzLGdzLE91LGt1LHh1LE11LEx1LFV1LE51LHF1LER1LGp1LEZ1LCR1LEh1PXdlKCgpPT57digpO20oKTtfKCk7eXQ9W10seHI9ITEsRGk9LTE7T2wucHJvdG90eXBlLnJ1bj1mdW5jdGlvbigpe3RoaXMuZnVuLmFwcGx5KG51bGwsdGhpcy5hcnJheSk7fTtrbD1cImJyb3dzZXJcIix4bD1cIng2NFwiLE1sPVwiYnJvd3NlclwiLExsPXtQQVRIOlwiL3Vzci9iaW5cIixMQU5HOkIubGFuZ3VhZ2UrXCIuVVRGLThcIixQV0Q6XCIvXCIsSE9NRTpcIi9ob21lXCIsVE1QOlwiL3RtcFwifSxVbD1bXCIvdXNyL2Jpbi9ub2RlXCJdLE5sPVtdLHFsPVwidjE2LjguMFwiLERsPXt9LGpsPWZ1bmN0aW9uKHQsZSl7Y29uc29sZS53YXJuKChlP2UrXCI6IFwiOlwiXCIpK3QpO30sRmw9ZnVuY3Rpb24odCl7eXMoXCJiaW5kaW5nXCIpO30sV2w9ZnVuY3Rpb24odCl7cmV0dXJuIDB9LCRsPWZ1bmN0aW9uKCl7cmV0dXJuIFwiL1wifSxIbD1mdW5jdGlvbih0KXt9LFZsPXtuYW1lOlwibm9kZVwiLHNvdXJjZVVybDpcIlwiLGhlYWRlcnNVcmw6XCJcIixsaWJVcmw6XCJcIn07emw9dmUsS2w9W107UWw9e30sWWw9ITEsSmw9e307dHU9dmUscnU9dmUsRmk9ZnVuY3Rpb24oKXtyZXR1cm4ge319LGl1PUZpLG51PUZpLHN1PXZlLG91PXZlLGF1PXZlLGx1PXt9O2Z1PXtpbnNwZWN0b3I6ITEsZGVidWc6ITEsdXY6ITEsaXB2NjohMSx0bHNfYWxwbjohMSx0bHNfc25pOiExLHRsc19vY3NwOiExLHRsczohMSxjYWNoZWRfYnVpbHRpbnM6ITB9LGN1PXZlLGh1PXZlO3B1PXZlLGd1PXZlLHl1PXZlLGJ1PXZlLHd1PXZlLF91PXZvaWQgMCxtdT12b2lkIDAsdnU9dm9pZCAwLEV1PXZlLFN1PTIsQXU9MSxJdT1cIi9iaW4vdXNyL25vZGVcIixUdT05MjI5LFJ1PVwibm9kZVwiLEN1PVtdLEJ1PXZlLE10PXtub3c6dHlwZW9mIHBlcmZvcm1hbmNlPFwidVwiP3BlcmZvcm1hbmNlLm5vdy5iaW5kKHBlcmZvcm1hbmNlKTp2b2lkIDAsdGltaW5nOnR5cGVvZiBwZXJmb3JtYW5jZTxcInVcIj9wZXJmb3JtYW5jZS50aW1pbmc6dm9pZCAwfTtNdC5ub3c9PT12b2lkIDAmJihwcz1EYXRlLm5vdygpLE10LnRpbWluZyYmTXQudGltaW5nLm5hdmlnYXRpb25TdGFydCYmKHBzPU10LnRpbWluZy5uYXZpZ2F0aW9uU3RhcnQpLE10Lm5vdz0oKT0+RGF0ZS5ub3coKS1wcyk7Z3M9MWU5O2ppLmJpZ2ludD1mdW5jdGlvbih0KXt2YXIgZT1qaSh0KTtyZXR1cm4gdHlwZW9mIEJpZ0ludD5cInVcIj9lWzBdKmdzK2VbMV06QmlnSW50KGVbMF0qZ3MpK0JpZ0ludChlWzFdKX07T3U9MTAsa3U9e30seHU9MDtNdT1idCxMdT1idCxVdT1idCxOdT1idCxxdT1idCxEdT12ZSxqdT1idCxGdT1idDskdT17dmVyc2lvbjpxbCx2ZXJzaW9uczpEbCxhcmNoOnhsLHBsYXRmb3JtOk1sLHJlbGVhc2U6VmwsX3Jhd0RlYnVnOnpsLG1vZHVsZUxvYWRMaXN0OktsLGJpbmRpbmc6RmwsX2xpbmtlZEJpbmRpbmc6R2wsX2V2ZW50czprdSxfZXZlbnRzQ291bnQ6eHUsX21heExpc3RlbmVyczpPdSxvbjpidCxhZGRMaXN0ZW5lcjpNdSxvbmNlOkx1LG9mZjpVdSxyZW1vdmVMaXN0ZW5lcjpOdSxyZW1vdmVBbGxMaXN0ZW5lcnM6cXUsZW1pdDpEdSxwcmVwZW5kTGlzdGVuZXI6anUscHJlcGVuZE9uY2VMaXN0ZW5lcjpGdSxsaXN0ZW5lcnM6V3UsZG9tYWluOlFsLF9leGl0aW5nOllsLGNvbmZpZzpKbCxkbG9wZW46WGwsdXB0aW1lOlB1LF9nZXRBY3RpdmVSZXF1ZXN0czpabCxfZ2V0QWN0aXZlSGFuZGxlczpldSxyZWFsbHlFeGl0OnR1LF9raWxsOnJ1LGNwdVVzYWdlOkZpLHJlc291cmNlVXNhZ2U6aXUsbWVtb3J5VXNhZ2U6bnUsa2lsbDpzdSxleGl0Om91LG9wZW5TdGRpbjphdSxhbGxvd2VkTm9kZUVudmlyb25tZW50RmxhZ3M6bHUsYXNzZXJ0OnV1LGZlYXR1cmVzOmZ1LF9mYXRhbEV4Y2VwdGlvbnM6Y3Usc2V0VW5jYXVnaHRFeGNlcHRpb25DYXB0dXJlQ2FsbGJhY2s6aHUsaGFzVW5jYXVnaHRFeGNlcHRpb25DYXB0dXJlQ2FsbGJhY2s6ZHUsZW1pdFdhcm5pbmc6amwsbmV4dFRpY2s6UGwsX3RpY2tDYWxsYmFjazpwdSxfZGVidWdQcm9jZXNzOmd1LF9kZWJ1Z0VuZDp5dSxfc3RhcnRQcm9maWxlcklkbGVOb3RpZmllcjpidSxfc3RvcFByb2ZpbGVySWRsZU5vdGlmaWVyOnd1LHN0ZG91dDpfdSxzdGRpbjp2dSxzdGRlcnI6bXUsYWJvcnQ6RXUsdW1hc2s6V2wsY2hkaXI6SGwsY3dkOiRsLGVudjpMbCx0aXRsZTprbCxhcmd2OlVsLGV4ZWNBcmd2Ok5sLHBpZDpTdSxwcGlkOkF1LGV4ZWNQYXRoOkl1LGRlYnVnUG9ydDpUdSxocnRpbWU6amksYXJndjA6UnUsX3ByZWxvYWRfbW9kdWxlczpDdSxzZXRTb3VyY2VNYXBzRW5hYmxlZDpCdX07fSk7dmFyIG09d2UoKCk9PntIdSgpO30pO3ZhciBfZT17fTtRdChfZSx7QnVmZmVyOigpPT54LElOU1BFQ1RfTUFYX0JZVEVTOigpPT5leSxkZWZhdWx0OigpPT5MdCxrTWF4TGVuZ3RoOigpPT50eX0pO2Z1bmN0aW9uIEpnKCl7aWYoVnUpcmV0dXJuIHVpO1Z1PSEwLHVpLmJ5dGVMZW5ndGg9YSx1aS50b0J5dGVBcnJheT1jLHVpLmZyb21CeXRlQXJyYXk9Zztmb3IodmFyIHQ9W10sZT1bXSxyPXR5cGVvZiBVaW50OEFycmF5PFwidVwiP1VpbnQ4QXJyYXk6QXJyYXksaT1cIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky9cIixuPTAsbz1pLmxlbmd0aDtuPG87KytuKXRbbl09aVtuXSxlW2kuY2hhckNvZGVBdChuKV09bjtlW1wiLVwiLmNoYXJDb2RlQXQoMCldPTYyLGVbXCJfXCIuY2hhckNvZGVBdCgwKV09NjM7ZnVuY3Rpb24gcyh5KXt2YXIgdz15Lmxlbmd0aDtpZih3JTQ+MCl0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHN0cmluZy4gTGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0XCIpO3ZhciBFPXkuaW5kZXhPZihcIj1cIik7RT09PS0xJiYoRT13KTt2YXIgUz1FPT09dz8wOjQtRSU0O3JldHVybiBbRSxTXX1mdW5jdGlvbiBhKHkpe3ZhciB3PXMoeSksRT13WzBdLFM9d1sxXTtyZXR1cm4gKEUrUykqMy80LVN9ZnVuY3Rpb24gdSh5LHcsRSl7cmV0dXJuICh3K0UpKjMvNC1FfWZ1bmN0aW9uIGMoeSl7dmFyIHcsRT1zKHkpLFM9RVswXSxJPUVbMV0sQz1uZXcgcih1KHksUyxJKSksUj0wLFU9ST4wP1MtNDpTLE47Zm9yKE49MDtOPFU7Tis9NCl3PWVbeS5jaGFyQ29kZUF0KE4pXTw8MTh8ZVt5LmNoYXJDb2RlQXQoTisxKV08PDEyfGVbeS5jaGFyQ29kZUF0KE4rMildPDw2fGVbeS5jaGFyQ29kZUF0KE4rMyldLENbUisrXT13Pj4xNiYyNTUsQ1tSKytdPXc+PjgmMjU1LENbUisrXT13JjI1NTtyZXR1cm4gST09PTImJih3PWVbeS5jaGFyQ29kZUF0KE4pXTw8MnxlW3kuY2hhckNvZGVBdChOKzEpXT4+NCxDW1IrK109dyYyNTUpLEk9PT0xJiYodz1lW3kuY2hhckNvZGVBdChOKV08PDEwfGVbeS5jaGFyQ29kZUF0KE4rMSldPDw0fGVbeS5jaGFyQ29kZUF0KE4rMildPj4yLENbUisrXT13Pj44JjI1NSxDW1IrK109dyYyNTUpLEN9ZnVuY3Rpb24gaCh5KXtyZXR1cm4gdFt5Pj4xOCY2M10rdFt5Pj4xMiY2M10rdFt5Pj42JjYzXSt0W3kmNjNdfWZ1bmN0aW9uIGQoeSx3LEUpe2Zvcih2YXIgUyxJPVtdLEM9dztDPEU7Qys9MylTPSh5W0NdPDwxNiYxNjcxMTY4MCkrKHlbQysxXTw8OCY2NTI4MCkrKHlbQysyXSYyNTUpLEkucHVzaChoKFMpKTtyZXR1cm4gSS5qb2luKFwiXCIpfWZ1bmN0aW9uIGcoeSl7Zm9yKHZhciB3LEU9eS5sZW5ndGgsUz1FJTMsST1bXSxDPTE2MzgzLFI9MCxVPUUtUztSPFU7Uis9QylJLnB1c2goZCh5LFIsUitDPlU/VTpSK0MpKTtyZXR1cm4gUz09PTE/KHc9eVtFLTFdLEkucHVzaCh0W3c+PjJdK3Rbdzw8NCY2M10rXCI9PVwiKSk6Uz09PTImJih3PSh5W0UtMl08PDgpK3lbRS0xXSxJLnB1c2godFt3Pj4xMF0rdFt3Pj40JjYzXSt0W3c8PDImNjNdK1wiPVwiKSksSS5qb2luKFwiXCIpfXJldHVybiB1aX1mdW5jdGlvbiBYZygpe2lmKHp1KXJldHVybiBXaTt6dT0hMDtyZXR1cm4gV2kucmVhZD1mdW5jdGlvbih0LGUscixpLG4pe3ZhciBvLHMsYT1uKjgtaS0xLHU9KDE8PGEpLTEsYz11Pj4xLGg9LTcsZD1yP24tMTowLGc9cj8tMToxLHk9dFtlK2RdO2ZvcihkKz1nLG89eSYoMTw8LWgpLTEseT4+PS1oLGgrPWE7aD4wO289byoyNTYrdFtlK2RdLGQrPWcsaC09OCk7Zm9yKHM9byYoMTw8LWgpLTEsbz4+PS1oLGgrPWk7aD4wO3M9cyoyNTYrdFtlK2RdLGQrPWcsaC09OCk7aWYobz09PTApbz0xLWM7ZWxzZSB7aWYobz09PXUpcmV0dXJuIHM/TmFOOih5Py0xOjEpKigxLzApO3M9cytNYXRoLnBvdygyLGkpLG89by1jO31yZXR1cm4gKHk/LTE6MSkqcypNYXRoLnBvdygyLG8taSl9LFdpLndyaXRlPWZ1bmN0aW9uKHQsZSxyLGksbixvKXt2YXIgcyxhLHUsYz1vKjgtbi0xLGg9KDE8PGMpLTEsZD1oPj4xLGc9bj09PTIzP01hdGgucG93KDIsLTI0KS1NYXRoLnBvdygyLC03Nyk6MCx5PWk/MDpvLTEsdz1pPzE6LTEsRT1lPDB8fGU9PT0wJiYxL2U8MD8xOjA7Zm9yKGU9TWF0aC5hYnMoZSksaXNOYU4oZSl8fGU9PT0xLzA/KGE9aXNOYU4oZSk/MTowLHM9aCk6KHM9TWF0aC5mbG9vcihNYXRoLmxvZyhlKS9NYXRoLkxOMiksZSoodT1NYXRoLnBvdygyLC1zKSk8MSYmKHMtLSx1Kj0yKSxzK2Q+PTE/ZSs9Zy91OmUrPWcqTWF0aC5wb3coMiwxLWQpLGUqdT49MiYmKHMrKyx1Lz0yKSxzK2Q+PWg/KGE9MCxzPWgpOnMrZD49MT8oYT0oZSp1LTEpKk1hdGgucG93KDIsbikscz1zK2QpOihhPWUqTWF0aC5wb3coMixkLTEpKk1hdGgucG93KDIsbikscz0wKSk7bj49ODt0W3IreV09YSYyNTUseSs9dyxhLz0yNTYsbi09OCk7Zm9yKHM9czw8bnxhLGMrPW47Yz4wO3Rbcit5XT1zJjI1NSx5Kz13LHMvPTI1NixjLT04KTt0W3IreS13XXw9RSoxMjg7fSxXaX1mdW5jdGlvbiBaZygpe2lmKEt1KXJldHVybiBKdDtLdT0hMDtsZXQgdD1KZygpLGU9WGcoKSxyPXR5cGVvZiBTeW1ib2w9PVwiZnVuY3Rpb25cIiYmdHlwZW9mIFN5bWJvbC5mb3I9PVwiZnVuY3Rpb25cIj9TeW1ib2wuZm9yKFwibm9kZWpzLnV0aWwuaW5zcGVjdC5jdXN0b21cIik6bnVsbDtKdC5CdWZmZXI9cyxKdC5TbG93QnVmZmVyPUksSnQuSU5TUEVDVF9NQVhfQllURVM9NTA7bGV0IGk9MjE0NzQ4MzY0NztKdC5rTWF4TGVuZ3RoPWkscy5UWVBFRF9BUlJBWV9TVVBQT1JUPW4oKSwhcy5UWVBFRF9BUlJBWV9TVVBQT1JUJiZ0eXBlb2YgY29uc29sZTxcInVcIiYmdHlwZW9mIGNvbnNvbGUuZXJyb3I9PVwiZnVuY3Rpb25cIiYmY29uc29sZS5lcnJvcihcIlRoaXMgYnJvd3NlciBsYWNrcyB0eXBlZCBhcnJheSAoVWludDhBcnJheSkgc3VwcG9ydCB3aGljaCBpcyByZXF1aXJlZCBieSBgYnVmZmVyYCB2NS54LiBVc2UgYGJ1ZmZlcmAgdjQueCBpZiB5b3UgcmVxdWlyZSBvbGQgYnJvd3NlciBzdXBwb3J0LlwiKTtmdW5jdGlvbiBuKCl7dHJ5e2xldCBwPW5ldyBVaW50OEFycmF5KDEpLGw9e2ZvbzpmdW5jdGlvbigpe3JldHVybiA0Mn19O3JldHVybiBPYmplY3Quc2V0UHJvdG90eXBlT2YobCxVaW50OEFycmF5LnByb3RvdHlwZSksT2JqZWN0LnNldFByb3RvdHlwZU9mKHAsbCkscC5mb28oKT09PTQyfWNhdGNoe3JldHVybiAhMX19T2JqZWN0LmRlZmluZVByb3BlcnR5KHMucHJvdG90eXBlLFwicGFyZW50XCIse2VudW1lcmFibGU6ITAsZ2V0OmZ1bmN0aW9uKCl7aWYocy5pc0J1ZmZlcih0aGlzKSlyZXR1cm4gdGhpcy5idWZmZXJ9fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KHMucHJvdG90eXBlLFwib2Zmc2V0XCIse2VudW1lcmFibGU6ITAsZ2V0OmZ1bmN0aW9uKCl7aWYocy5pc0J1ZmZlcih0aGlzKSlyZXR1cm4gdGhpcy5ieXRlT2Zmc2V0fX0pO2Z1bmN0aW9uIG8ocCl7aWYocD5pKXRocm93IG5ldyBSYW5nZUVycm9yKCdUaGUgdmFsdWUgXCInK3ArJ1wiIGlzIGludmFsaWQgZm9yIG9wdGlvbiBcInNpemVcIicpO2xldCBsPW5ldyBVaW50OEFycmF5KHApO3JldHVybiBPYmplY3Quc2V0UHJvdG90eXBlT2YobCxzLnByb3RvdHlwZSksbH1mdW5jdGlvbiBzKHAsbCxmKXtpZih0eXBlb2YgcD09XCJudW1iZXJcIil7aWYodHlwZW9mIGw9PVwic3RyaW5nXCIpdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIFwic3RyaW5nXCIgYXJndW1lbnQgbXVzdCBiZSBvZiB0eXBlIHN0cmluZy4gUmVjZWl2ZWQgdHlwZSBudW1iZXInKTtyZXR1cm4gaChwKX1yZXR1cm4gYShwLGwsZil9cy5wb29sU2l6ZT04MTkyO2Z1bmN0aW9uIGEocCxsLGYpe2lmKHR5cGVvZiBwPT1cInN0cmluZ1wiKXJldHVybiBkKHAsbCk7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHApKXJldHVybiB5KHApO2lmKHA9PW51bGwpdGhyb3cgbmV3IFR5cGVFcnJvcihcIlRoZSBmaXJzdCBhcmd1bWVudCBtdXN0IGJlIG9uZSBvZiB0eXBlIHN0cmluZywgQnVmZmVyLCBBcnJheUJ1ZmZlciwgQXJyYXksIG9yIEFycmF5LWxpa2UgT2JqZWN0LiBSZWNlaXZlZCB0eXBlIFwiK3R5cGVvZiBwKTtpZihZZShwLEFycmF5QnVmZmVyKXx8cCYmWWUocC5idWZmZXIsQXJyYXlCdWZmZXIpfHx0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXI8XCJ1XCImJihZZShwLFNoYXJlZEFycmF5QnVmZmVyKXx8cCYmWWUocC5idWZmZXIsU2hhcmVkQXJyYXlCdWZmZXIpKSlyZXR1cm4gdyhwLGwsZik7aWYodHlwZW9mIHA9PVwibnVtYmVyXCIpdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIFwidmFsdWVcIiBhcmd1bWVudCBtdXN0IG5vdCBiZSBvZiB0eXBlIG51bWJlci4gUmVjZWl2ZWQgdHlwZSBudW1iZXInKTtsZXQgYj1wLnZhbHVlT2YmJnAudmFsdWVPZigpO2lmKGIhPW51bGwmJmIhPT1wKXJldHVybiBzLmZyb20oYixsLGYpO2xldCBBPUUocCk7aWYoQSlyZXR1cm4gQTtpZih0eXBlb2YgU3ltYm9sPFwidVwiJiZTeW1ib2wudG9QcmltaXRpdmUhPW51bGwmJnR5cGVvZiBwW1N5bWJvbC50b1ByaW1pdGl2ZV09PVwiZnVuY3Rpb25cIilyZXR1cm4gcy5mcm9tKHBbU3ltYm9sLnRvUHJpbWl0aXZlXShcInN0cmluZ1wiKSxsLGYpO3Rocm93IG5ldyBUeXBlRXJyb3IoXCJUaGUgZmlyc3QgYXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdHlwZSBzdHJpbmcsIEJ1ZmZlciwgQXJyYXlCdWZmZXIsIEFycmF5LCBvciBBcnJheS1saWtlIE9iamVjdC4gUmVjZWl2ZWQgdHlwZSBcIit0eXBlb2YgcCl9cy5mcm9tPWZ1bmN0aW9uKHAsbCxmKXtyZXR1cm4gYShwLGwsZil9LE9iamVjdC5zZXRQcm90b3R5cGVPZihzLnByb3RvdHlwZSxVaW50OEFycmF5LnByb3RvdHlwZSksT2JqZWN0LnNldFByb3RvdHlwZU9mKHMsVWludDhBcnJheSk7ZnVuY3Rpb24gdShwKXtpZih0eXBlb2YgcCE9XCJudW1iZXJcIil0aHJvdyBuZXcgVHlwZUVycm9yKCdcInNpemVcIiBhcmd1bWVudCBtdXN0IGJlIG9mIHR5cGUgbnVtYmVyJyk7aWYocDwwKXRocm93IG5ldyBSYW5nZUVycm9yKCdUaGUgdmFsdWUgXCInK3ArJ1wiIGlzIGludmFsaWQgZm9yIG9wdGlvbiBcInNpemVcIicpfWZ1bmN0aW9uIGMocCxsLGYpe3JldHVybiB1KHApLHA8PTA/byhwKTpsIT09dm9pZCAwP3R5cGVvZiBmPT1cInN0cmluZ1wiP28ocCkuZmlsbChsLGYpOm8ocCkuZmlsbChsKTpvKHApfXMuYWxsb2M9ZnVuY3Rpb24ocCxsLGYpe3JldHVybiBjKHAsbCxmKX07ZnVuY3Rpb24gaChwKXtyZXR1cm4gdShwKSxvKHA8MD8wOlMocCl8MCl9cy5hbGxvY1Vuc2FmZT1mdW5jdGlvbihwKXtyZXR1cm4gaChwKX0scy5hbGxvY1Vuc2FmZVNsb3c9ZnVuY3Rpb24ocCl7cmV0dXJuIGgocCl9O2Z1bmN0aW9uIGQocCxsKXtpZigodHlwZW9mIGwhPVwic3RyaW5nXCJ8fGw9PT1cIlwiKSYmKGw9XCJ1dGY4XCIpLCFzLmlzRW5jb2RpbmcobCkpdGhyb3cgbmV3IFR5cGVFcnJvcihcIlVua25vd24gZW5jb2Rpbmc6IFwiK2wpO2xldCBmPUMocCxsKXwwLGI9byhmKSxBPWIud3JpdGUocCxsKTtyZXR1cm4gQSE9PWYmJihiPWIuc2xpY2UoMCxBKSksYn1mdW5jdGlvbiBnKHApe2xldCBsPXAubGVuZ3RoPDA/MDpTKHAubGVuZ3RoKXwwLGY9byhsKTtmb3IobGV0IGI9MDtiPGw7Yis9MSlmW2JdPXBbYl0mMjU1O3JldHVybiBmfWZ1bmN0aW9uIHkocCl7aWYoWWUocCxVaW50OEFycmF5KSl7bGV0IGw9bmV3IFVpbnQ4QXJyYXkocCk7cmV0dXJuIHcobC5idWZmZXIsbC5ieXRlT2Zmc2V0LGwuYnl0ZUxlbmd0aCl9cmV0dXJuIGcocCl9ZnVuY3Rpb24gdyhwLGwsZil7aWYobDwwfHxwLmJ5dGVMZW5ndGg8bCl0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJvZmZzZXRcIiBpcyBvdXRzaWRlIG9mIGJ1ZmZlciBib3VuZHMnKTtpZihwLmJ5dGVMZW5ndGg8bCsoZnx8MCkpdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1wibGVuZ3RoXCIgaXMgb3V0c2lkZSBvZiBidWZmZXIgYm91bmRzJyk7bGV0IGI7cmV0dXJuIGw9PT12b2lkIDAmJmY9PT12b2lkIDA/Yj1uZXcgVWludDhBcnJheShwKTpmPT09dm9pZCAwP2I9bmV3IFVpbnQ4QXJyYXkocCxsKTpiPW5ldyBVaW50OEFycmF5KHAsbCxmKSxPYmplY3Quc2V0UHJvdG90eXBlT2YoYixzLnByb3RvdHlwZSksYn1mdW5jdGlvbiBFKHApe2lmKHMuaXNCdWZmZXIocCkpe2xldCBsPVMocC5sZW5ndGgpfDAsZj1vKGwpO3JldHVybiBmLmxlbmd0aD09PTB8fHAuY29weShmLDAsMCxsKSxmfWlmKHAubGVuZ3RoIT09dm9pZCAwKXJldHVybiB0eXBlb2YgcC5sZW5ndGghPVwibnVtYmVyXCJ8fGhzKHAubGVuZ3RoKT9vKDApOmcocCk7aWYocC50eXBlPT09XCJCdWZmZXJcIiYmQXJyYXkuaXNBcnJheShwLmRhdGEpKXJldHVybiBnKHAuZGF0YSl9ZnVuY3Rpb24gUyhwKXtpZihwPj1pKXRocm93IG5ldyBSYW5nZUVycm9yKFwiQXR0ZW1wdCB0byBhbGxvY2F0ZSBCdWZmZXIgbGFyZ2VyIHRoYW4gbWF4aW11bSBzaXplOiAweFwiK2kudG9TdHJpbmcoMTYpK1wiIGJ5dGVzXCIpO3JldHVybiBwfDB9ZnVuY3Rpb24gSShwKXtyZXR1cm4gK3AhPXAmJihwPTApLHMuYWxsb2MoK3ApfXMuaXNCdWZmZXI9ZnVuY3Rpb24obCl7cmV0dXJuIGwhPW51bGwmJmwuX2lzQnVmZmVyPT09ITAmJmwhPT1zLnByb3RvdHlwZX0scy5jb21wYXJlPWZ1bmN0aW9uKGwsZil7aWYoWWUobCxVaW50OEFycmF5KSYmKGw9cy5mcm9tKGwsbC5vZmZzZXQsbC5ieXRlTGVuZ3RoKSksWWUoZixVaW50OEFycmF5KSYmKGY9cy5mcm9tKGYsZi5vZmZzZXQsZi5ieXRlTGVuZ3RoKSksIXMuaXNCdWZmZXIobCl8fCFzLmlzQnVmZmVyKGYpKXRocm93IG5ldyBUeXBlRXJyb3IoJ1RoZSBcImJ1ZjFcIiwgXCJidWYyXCIgYXJndW1lbnRzIG11c3QgYmUgb25lIG9mIHR5cGUgQnVmZmVyIG9yIFVpbnQ4QXJyYXknKTtpZihsPT09ZilyZXR1cm4gMDtsZXQgYj1sLmxlbmd0aCxBPWYubGVuZ3RoO2ZvcihsZXQgVD0wLE89TWF0aC5taW4oYixBKTtUPE87KytUKWlmKGxbVF0hPT1mW1RdKXtiPWxbVF0sQT1mW1RdO2JyZWFrfXJldHVybiBiPEE/LTE6QTxiPzE6MH0scy5pc0VuY29kaW5nPWZ1bmN0aW9uKGwpe3N3aXRjaChTdHJpbmcobCkudG9Mb3dlckNhc2UoKSl7Y2FzZVwiaGV4XCI6Y2FzZVwidXRmOFwiOmNhc2VcInV0Zi04XCI6Y2FzZVwiYXNjaWlcIjpjYXNlXCJsYXRpbjFcIjpjYXNlXCJiaW5hcnlcIjpjYXNlXCJiYXNlNjRcIjpjYXNlXCJ1Y3MyXCI6Y2FzZVwidWNzLTJcIjpjYXNlXCJ1dGYxNmxlXCI6Y2FzZVwidXRmLTE2bGVcIjpyZXR1cm4gITA7ZGVmYXVsdDpyZXR1cm4gITF9fSxzLmNvbmNhdD1mdW5jdGlvbihsLGYpe2lmKCFBcnJheS5pc0FycmF5KGwpKXRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdFwiIGFyZ3VtZW50IG11c3QgYmUgYW4gQXJyYXkgb2YgQnVmZmVycycpO2lmKGwubGVuZ3RoPT09MClyZXR1cm4gcy5hbGxvYygwKTtsZXQgYjtpZihmPT09dm9pZCAwKWZvcihmPTAsYj0wO2I8bC5sZW5ndGg7KytiKWYrPWxbYl0ubGVuZ3RoO2xldCBBPXMuYWxsb2NVbnNhZmUoZiksVD0wO2ZvcihiPTA7YjxsLmxlbmd0aDsrK2Ipe2xldCBPPWxbYl07aWYoWWUoTyxVaW50OEFycmF5KSlUK08ubGVuZ3RoPkEubGVuZ3RoPyhzLmlzQnVmZmVyKE8pfHwoTz1zLmZyb20oTykpLE8uY29weShBLFQpKTpVaW50OEFycmF5LnByb3RvdHlwZS5zZXQuY2FsbChBLE8sVCk7ZWxzZSBpZihzLmlzQnVmZmVyKE8pKU8uY29weShBLFQpO2Vsc2UgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0XCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJyk7VCs9Ty5sZW5ndGg7fXJldHVybiBBfTtmdW5jdGlvbiBDKHAsbCl7aWYocy5pc0J1ZmZlcihwKSlyZXR1cm4gcC5sZW5ndGg7aWYoQXJyYXlCdWZmZXIuaXNWaWV3KHApfHxZZShwLEFycmF5QnVmZmVyKSlyZXR1cm4gcC5ieXRlTGVuZ3RoO2lmKHR5cGVvZiBwIT1cInN0cmluZ1wiKXRocm93IG5ldyBUeXBlRXJyb3IoJ1RoZSBcInN0cmluZ1wiIGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgc3RyaW5nLCBCdWZmZXIsIG9yIEFycmF5QnVmZmVyLiBSZWNlaXZlZCB0eXBlICcrdHlwZW9mIHApO2xldCBmPXAubGVuZ3RoLGI9YXJndW1lbnRzLmxlbmd0aD4yJiZhcmd1bWVudHNbMl09PT0hMDtpZighYiYmZj09PTApcmV0dXJuIDA7bGV0IEE9ITE7Zm9yKDs7KXN3aXRjaChsKXtjYXNlXCJhc2NpaVwiOmNhc2VcImxhdGluMVwiOmNhc2VcImJpbmFyeVwiOnJldHVybiBmO2Nhc2VcInV0ZjhcIjpjYXNlXCJ1dGYtOFwiOnJldHVybiBjcyhwKS5sZW5ndGg7Y2FzZVwidWNzMlwiOmNhc2VcInVjcy0yXCI6Y2FzZVwidXRmMTZsZVwiOmNhc2VcInV0Zi0xNmxlXCI6cmV0dXJuIGYqMjtjYXNlXCJoZXhcIjpyZXR1cm4gZj4+PjE7Y2FzZVwiYmFzZTY0XCI6cmV0dXJuIENsKHApLmxlbmd0aDtkZWZhdWx0OmlmKEEpcmV0dXJuIGI/LTE6Y3MocCkubGVuZ3RoO2w9KFwiXCIrbCkudG9Mb3dlckNhc2UoKSxBPSEwO319cy5ieXRlTGVuZ3RoPUM7ZnVuY3Rpb24gUihwLGwsZil7bGV0IGI9ITE7aWYoKGw9PT12b2lkIDB8fGw8MCkmJihsPTApLGw+dGhpcy5sZW5ndGh8fCgoZj09PXZvaWQgMHx8Zj50aGlzLmxlbmd0aCkmJihmPXRoaXMubGVuZ3RoKSxmPD0wKXx8KGY+Pj49MCxsPj4+PTAsZjw9bCkpcmV0dXJuIFwiXCI7Zm9yKHB8fChwPVwidXRmOFwiKTs7KXN3aXRjaChwKXtjYXNlXCJoZXhcIjpyZXR1cm4gTmcodGhpcyxsLGYpO2Nhc2VcInV0ZjhcIjpjYXNlXCJ1dGYtOFwiOnJldHVybiBDcih0aGlzLGwsZik7Y2FzZVwiYXNjaWlcIjpyZXR1cm4gdXModGhpcyxsLGYpO2Nhc2VcImxhdGluMVwiOmNhc2VcImJpbmFyeVwiOnJldHVybiBVZyh0aGlzLGwsZik7Y2FzZVwiYmFzZTY0XCI6cmV0dXJuIHBlKHRoaXMsbCxmKTtjYXNlXCJ1Y3MyXCI6Y2FzZVwidWNzLTJcIjpjYXNlXCJ1dGYxNmxlXCI6Y2FzZVwidXRmLTE2bGVcIjpyZXR1cm4gcWcodGhpcyxsLGYpO2RlZmF1bHQ6aWYoYil0aHJvdyBuZXcgVHlwZUVycm9yKFwiVW5rbm93biBlbmNvZGluZzogXCIrcCk7cD0ocCtcIlwiKS50b0xvd2VyQ2FzZSgpLGI9ITA7fX1zLnByb3RvdHlwZS5faXNCdWZmZXI9ITA7ZnVuY3Rpb24gVShwLGwsZil7bGV0IGI9cFtsXTtwW2xdPXBbZl0scFtmXT1iO31zLnByb3RvdHlwZS5zd2FwMTY9ZnVuY3Rpb24oKXtsZXQgbD10aGlzLmxlbmd0aDtpZihsJTIhPT0wKXRocm93IG5ldyBSYW5nZUVycm9yKFwiQnVmZmVyIHNpemUgbXVzdCBiZSBhIG11bHRpcGxlIG9mIDE2LWJpdHNcIik7Zm9yKGxldCBmPTA7ZjxsO2YrPTIpVSh0aGlzLGYsZisxKTtyZXR1cm4gdGhpc30scy5wcm90b3R5cGUuc3dhcDMyPWZ1bmN0aW9uKCl7bGV0IGw9dGhpcy5sZW5ndGg7aWYobCU0IT09MCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIkJ1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAzMi1iaXRzXCIpO2ZvcihsZXQgZj0wO2Y8bDtmKz00KVUodGhpcyxmLGYrMyksVSh0aGlzLGYrMSxmKzIpO3JldHVybiB0aGlzfSxzLnByb3RvdHlwZS5zd2FwNjQ9ZnVuY3Rpb24oKXtsZXQgbD10aGlzLmxlbmd0aDtpZihsJTghPT0wKXRocm93IG5ldyBSYW5nZUVycm9yKFwiQnVmZmVyIHNpemUgbXVzdCBiZSBhIG11bHRpcGxlIG9mIDY0LWJpdHNcIik7Zm9yKGxldCBmPTA7ZjxsO2YrPTgpVSh0aGlzLGYsZis3KSxVKHRoaXMsZisxLGYrNiksVSh0aGlzLGYrMixmKzUpLFUodGhpcyxmKzMsZis0KTtyZXR1cm4gdGhpc30scy5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtsZXQgbD10aGlzLmxlbmd0aDtyZXR1cm4gbD09PTA/XCJcIjphcmd1bWVudHMubGVuZ3RoPT09MD9Dcih0aGlzLDAsbCk6Ui5hcHBseSh0aGlzLGFyZ3VtZW50cyl9LHMucHJvdG90eXBlLnRvTG9jYWxlU3RyaW5nPXMucHJvdG90eXBlLnRvU3RyaW5nLHMucHJvdG90eXBlLmVxdWFscz1mdW5jdGlvbihsKXtpZighcy5pc0J1ZmZlcihsKSl0aHJvdyBuZXcgVHlwZUVycm9yKFwiQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlclwiKTtyZXR1cm4gdGhpcz09PWw/ITA6cy5jb21wYXJlKHRoaXMsbCk9PT0wfSxzLnByb3RvdHlwZS5pbnNwZWN0PWZ1bmN0aW9uKCl7bGV0IGw9XCJcIixmPUp0LklOU1BFQ1RfTUFYX0JZVEVTO3JldHVybiBsPXRoaXMudG9TdHJpbmcoXCJoZXhcIiwwLGYpLnJlcGxhY2UoLyguezJ9KS9nLFwiJDEgXCIpLnRyaW0oKSx0aGlzLmxlbmd0aD5mJiYobCs9XCIgLi4uIFwiKSxcIjxCdWZmZXIgXCIrbCtcIj5cIn0sciYmKHMucHJvdG90eXBlW3JdPXMucHJvdG90eXBlLmluc3BlY3QpLHMucHJvdG90eXBlLmNvbXBhcmU9ZnVuY3Rpb24obCxmLGIsQSxUKXtpZihZZShsLFVpbnQ4QXJyYXkpJiYobD1zLmZyb20obCxsLm9mZnNldCxsLmJ5dGVMZW5ndGgpKSwhcy5pc0J1ZmZlcihsKSl0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgXCJ0YXJnZXRcIiBhcmd1bWVudCBtdXN0IGJlIG9uZSBvZiB0eXBlIEJ1ZmZlciBvciBVaW50OEFycmF5LiBSZWNlaXZlZCB0eXBlICcrdHlwZW9mIGwpO2lmKGY9PT12b2lkIDAmJihmPTApLGI9PT12b2lkIDAmJihiPWw/bC5sZW5ndGg6MCksQT09PXZvaWQgMCYmKEE9MCksVD09PXZvaWQgMCYmKFQ9dGhpcy5sZW5ndGgpLGY8MHx8Yj5sLmxlbmd0aHx8QTwwfHxUPnRoaXMubGVuZ3RoKXRocm93IG5ldyBSYW5nZUVycm9yKFwib3V0IG9mIHJhbmdlIGluZGV4XCIpO2lmKEE+PVQmJmY+PWIpcmV0dXJuIDA7aWYoQT49VClyZXR1cm4gLTE7aWYoZj49YilyZXR1cm4gMTtpZihmPj4+PTAsYj4+Pj0wLEE+Pj49MCxUPj4+PTAsdGhpcz09PWwpcmV0dXJuIDA7bGV0IE89VC1BLCQ9Yi1mLHNlPU1hdGgubWluKE8sJCksdGU9dGhpcy5zbGljZShBLFQpLG9lPWwuc2xpY2UoZixiKTtmb3IobGV0IEo9MDtKPHNlOysrSilpZih0ZVtKXSE9PW9lW0pdKXtPPXRlW0pdLCQ9b2VbSl07YnJlYWt9cmV0dXJuIE88JD8tMTokPE8/MTowfTtmdW5jdGlvbiBOKHAsbCxmLGIsQSl7aWYocC5sZW5ndGg9PT0wKXJldHVybiAtMTtpZih0eXBlb2YgZj09XCJzdHJpbmdcIj8oYj1mLGY9MCk6Zj4yMTQ3NDgzNjQ3P2Y9MjE0NzQ4MzY0NzpmPC0yMTQ3NDgzNjQ4JiYoZj0tMjE0NzQ4MzY0OCksZj0rZixocyhmKSYmKGY9QT8wOnAubGVuZ3RoLTEpLGY8MCYmKGY9cC5sZW5ndGgrZiksZj49cC5sZW5ndGgpe2lmKEEpcmV0dXJuIC0xO2Y9cC5sZW5ndGgtMTt9ZWxzZSBpZihmPDApaWYoQSlmPTA7ZWxzZSByZXR1cm4gLTE7aWYodHlwZW9mIGw9PVwic3RyaW5nXCImJihsPXMuZnJvbShsLGIpKSxzLmlzQnVmZmVyKGwpKXJldHVybiBsLmxlbmd0aD09PTA/LTE6VyhwLGwsZixiLEEpO2lmKHR5cGVvZiBsPT1cIm51bWJlclwiKXJldHVybiBsPWwmMjU1LHR5cGVvZiBVaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mPT1cImZ1bmN0aW9uXCI/QT9VaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwocCxsLGYpOlVpbnQ4QXJyYXkucHJvdG90eXBlLmxhc3RJbmRleE9mLmNhbGwocCxsLGYpOlcocCxbbF0sZixiLEEpO3Rocm93IG5ldyBUeXBlRXJyb3IoXCJ2YWwgbXVzdCBiZSBzdHJpbmcsIG51bWJlciBvciBCdWZmZXJcIil9ZnVuY3Rpb24gVyhwLGwsZixiLEEpe2xldCBUPTEsTz1wLmxlbmd0aCwkPWwubGVuZ3RoO2lmKGIhPT12b2lkIDAmJihiPVN0cmluZyhiKS50b0xvd2VyQ2FzZSgpLGI9PT1cInVjczJcInx8Yj09PVwidWNzLTJcInx8Yj09PVwidXRmMTZsZVwifHxiPT09XCJ1dGYtMTZsZVwiKSl7aWYocC5sZW5ndGg8Mnx8bC5sZW5ndGg8MilyZXR1cm4gLTE7VD0yLE8vPTIsJC89MixmLz0yO31mdW5jdGlvbiBzZShvZSxKKXtyZXR1cm4gVD09PTE/b2VbSl06b2UucmVhZFVJbnQxNkJFKEoqVCl9bGV0IHRlO2lmKEEpe2xldCBvZT0tMTtmb3IodGU9Zjt0ZTxPO3RlKyspaWYoc2UocCx0ZSk9PT1zZShsLG9lPT09LTE/MDp0ZS1vZSkpe2lmKG9lPT09LTEmJihvZT10ZSksdGUtb2UrMT09PSQpcmV0dXJuIG9lKlR9ZWxzZSBvZSE9PS0xJiYodGUtPXRlLW9lKSxvZT0tMTt9ZWxzZSBmb3IoZiskPk8mJihmPU8tJCksdGU9Zjt0ZT49MDt0ZS0tKXtsZXQgb2U9ITA7Zm9yKGxldCBKPTA7SjwkO0orKylpZihzZShwLHRlK0opIT09c2UobCxKKSl7b2U9ITE7YnJlYWt9aWYob2UpcmV0dXJuIHRlfXJldHVybiAtMX1zLnByb3RvdHlwZS5pbmNsdWRlcz1mdW5jdGlvbihsLGYsYil7cmV0dXJuIHRoaXMuaW5kZXhPZihsLGYsYikhPT0tMX0scy5wcm90b3R5cGUuaW5kZXhPZj1mdW5jdGlvbihsLGYsYil7cmV0dXJuIE4odGhpcyxsLGYsYiwhMCl9LHMucHJvdG90eXBlLmxhc3RJbmRleE9mPWZ1bmN0aW9uKGwsZixiKXtyZXR1cm4gTih0aGlzLGwsZixiLCExKX07ZnVuY3Rpb24gSyhwLGwsZixiKXtmPU51bWJlcihmKXx8MDtsZXQgQT1wLmxlbmd0aC1mO2I/KGI9TnVtYmVyKGIpLGI+QSYmKGI9QSkpOmI9QTtsZXQgVD1sLmxlbmd0aDtiPlQvMiYmKGI9VC8yKTtsZXQgTztmb3IoTz0wO088YjsrK08pe2xldCAkPXBhcnNlSW50KGwuc3Vic3RyKE8qMiwyKSwxNik7aWYoaHMoJCkpcmV0dXJuIE87cFtmK09dPSQ7fXJldHVybiBPfWZ1bmN0aW9uIHoocCxsLGYsYil7cmV0dXJuIHFpKGNzKGwscC5sZW5ndGgtZikscCxmLGIpfWZ1bmN0aW9uIFEocCxsLGYsYil7cmV0dXJuIHFpKFdnKGwpLHAsZixiKX1mdW5jdGlvbiBkZShwLGwsZixiKXtyZXR1cm4gcWkoQ2wobCkscCxmLGIpfWZ1bmN0aW9uIEd0KHAsbCxmLGIpe3JldHVybiBxaSgkZyhsLHAubGVuZ3RoLWYpLHAsZixiKX1zLnByb3RvdHlwZS53cml0ZT1mdW5jdGlvbihsLGYsYixBKXtpZihmPT09dm9pZCAwKUE9XCJ1dGY4XCIsYj10aGlzLmxlbmd0aCxmPTA7ZWxzZSBpZihiPT09dm9pZCAwJiZ0eXBlb2YgZj09XCJzdHJpbmdcIilBPWYsYj10aGlzLmxlbmd0aCxmPTA7ZWxzZSBpZihpc0Zpbml0ZShmKSlmPWY+Pj4wLGlzRmluaXRlKGIpPyhiPWI+Pj4wLEE9PT12b2lkIDAmJihBPVwidXRmOFwiKSk6KEE9YixiPXZvaWQgMCk7ZWxzZSB0aHJvdyBuZXcgRXJyb3IoXCJCdWZmZXIud3JpdGUoc3RyaW5nLCBlbmNvZGluZywgb2Zmc2V0WywgbGVuZ3RoXSkgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZFwiKTtsZXQgVD10aGlzLmxlbmd0aC1mO2lmKChiPT09dm9pZCAwfHxiPlQpJiYoYj1UKSxsLmxlbmd0aD4wJiYoYjwwfHxmPDApfHxmPnRoaXMubGVuZ3RoKXRocm93IG5ldyBSYW5nZUVycm9yKFwiQXR0ZW1wdCB0byB3cml0ZSBvdXRzaWRlIGJ1ZmZlciBib3VuZHNcIik7QXx8KEE9XCJ1dGY4XCIpO2xldCBPPSExO2Zvcig7Oylzd2l0Y2goQSl7Y2FzZVwiaGV4XCI6cmV0dXJuIEsodGhpcyxsLGYsYik7Y2FzZVwidXRmOFwiOmNhc2VcInV0Zi04XCI6cmV0dXJuIHoodGhpcyxsLGYsYik7Y2FzZVwiYXNjaWlcIjpjYXNlXCJsYXRpbjFcIjpjYXNlXCJiaW5hcnlcIjpyZXR1cm4gUSh0aGlzLGwsZixiKTtjYXNlXCJiYXNlNjRcIjpyZXR1cm4gZGUodGhpcyxsLGYsYik7Y2FzZVwidWNzMlwiOmNhc2VcInVjcy0yXCI6Y2FzZVwidXRmMTZsZVwiOmNhc2VcInV0Zi0xNmxlXCI6cmV0dXJuIEd0KHRoaXMsbCxmLGIpO2RlZmF1bHQ6aWYoTyl0aHJvdyBuZXcgVHlwZUVycm9yKFwiVW5rbm93biBlbmNvZGluZzogXCIrQSk7QT0oXCJcIitBKS50b0xvd2VyQ2FzZSgpLE89ITA7fX0scy5wcm90b3R5cGUudG9KU09OPWZ1bmN0aW9uKCl7cmV0dXJuIHt0eXBlOlwiQnVmZmVyXCIsZGF0YTpBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLl9hcnJ8fHRoaXMsMCl9fTtmdW5jdGlvbiBwZShwLGwsZil7cmV0dXJuIGw9PT0wJiZmPT09cC5sZW5ndGg/dC5mcm9tQnl0ZUFycmF5KHApOnQuZnJvbUJ5dGVBcnJheShwLnNsaWNlKGwsZikpfWZ1bmN0aW9uIENyKHAsbCxmKXtmPU1hdGgubWluKHAubGVuZ3RoLGYpO2xldCBiPVtdLEE9bDtmb3IoO0E8Zjspe2xldCBUPXBbQV0sTz1udWxsLCQ9VD4yMzk/NDpUPjIyMz8zOlQ+MTkxPzI6MTtpZihBKyQ8PWYpe2xldCBzZSx0ZSxvZSxKO3N3aXRjaCgkKXtjYXNlIDE6VDwxMjgmJihPPVQpO2JyZWFrO2Nhc2UgMjpzZT1wW0ErMV0sKHNlJjE5Mik9PT0xMjgmJihKPShUJjMxKTw8NnxzZSY2MyxKPjEyNyYmKE89SikpO2JyZWFrO2Nhc2UgMzpzZT1wW0ErMV0sdGU9cFtBKzJdLChzZSYxOTIpPT09MTI4JiYodGUmMTkyKT09PTEyOCYmKEo9KFQmMTUpPDwxMnwoc2UmNjMpPDw2fHRlJjYzLEo+MjA0NyYmKEo8NTUyOTZ8fEo+NTczNDMpJiYoTz1KKSk7YnJlYWs7Y2FzZSA0OnNlPXBbQSsxXSx0ZT1wW0ErMl0sb2U9cFtBKzNdLChzZSYxOTIpPT09MTI4JiYodGUmMTkyKT09PTEyOCYmKG9lJjE5Mik9PT0xMjgmJihKPShUJjE1KTw8MTh8KHNlJjYzKTw8MTJ8KHRlJjYzKTw8NnxvZSY2MyxKPjY1NTM1JiZKPDExMTQxMTImJihPPUopKTt9fU89PT1udWxsPyhPPTY1NTMzLCQ9MSk6Tz42NTUzNSYmKE8tPTY1NTM2LGIucHVzaChPPj4+MTAmMTAyM3w1NTI5NiksTz01NjMyMHxPJjEwMjMpLGIucHVzaChPKSxBKz0kO31yZXR1cm4gUHIoYil9bGV0IEJyPTQwOTY7ZnVuY3Rpb24gUHIocCl7bGV0IGw9cC5sZW5ndGg7aWYobDw9QnIpcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLHApO2xldCBmPVwiXCIsYj0wO2Zvcig7YjxsOylmKz1TdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZyxwLnNsaWNlKGIsYis9QnIpKTtyZXR1cm4gZn1mdW5jdGlvbiB1cyhwLGwsZil7bGV0IGI9XCJcIjtmPU1hdGgubWluKHAubGVuZ3RoLGYpO2ZvcihsZXQgQT1sO0E8ZjsrK0EpYis9U3RyaW5nLmZyb21DaGFyQ29kZShwW0FdJjEyNyk7cmV0dXJuIGJ9ZnVuY3Rpb24gVWcocCxsLGYpe2xldCBiPVwiXCI7Zj1NYXRoLm1pbihwLmxlbmd0aCxmKTtmb3IobGV0IEE9bDtBPGY7KytBKWIrPVN0cmluZy5mcm9tQ2hhckNvZGUocFtBXSk7cmV0dXJuIGJ9ZnVuY3Rpb24gTmcocCxsLGYpe2xldCBiPXAubGVuZ3RoOyghbHx8bDwwKSYmKGw9MCksKCFmfHxmPDB8fGY+YikmJihmPWIpO2xldCBBPVwiXCI7Zm9yKGxldCBUPWw7VDxmOysrVClBKz1IZ1twW1RdXTtyZXR1cm4gQX1mdW5jdGlvbiBxZyhwLGwsZil7bGV0IGI9cC5zbGljZShsLGYpLEE9XCJcIjtmb3IobGV0IFQ9MDtUPGIubGVuZ3RoLTE7VCs9MilBKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGJbVF0rYltUKzFdKjI1Nik7cmV0dXJuIEF9cy5wcm90b3R5cGUuc2xpY2U9ZnVuY3Rpb24obCxmKXtsZXQgYj10aGlzLmxlbmd0aDtsPX5+bCxmPWY9PT12b2lkIDA/Yjp+fmYsbDwwPyhsKz1iLGw8MCYmKGw9MCkpOmw+YiYmKGw9YiksZjwwPyhmKz1iLGY8MCYmKGY9MCkpOmY+YiYmKGY9YiksZjxsJiYoZj1sKTtsZXQgQT10aGlzLnN1YmFycmF5KGwsZik7cmV0dXJuIE9iamVjdC5zZXRQcm90b3R5cGVPZihBLHMucHJvdG90eXBlKSxBfTtmdW5jdGlvbiBnZShwLGwsZil7aWYocCUxIT09MHx8cDwwKXRocm93IG5ldyBSYW5nZUVycm9yKFwib2Zmc2V0IGlzIG5vdCB1aW50XCIpO2lmKHArbD5mKXRocm93IG5ldyBSYW5nZUVycm9yKFwiVHJ5aW5nIHRvIGFjY2VzcyBiZXlvbmQgYnVmZmVyIGxlbmd0aFwiKX1zLnByb3RvdHlwZS5yZWFkVWludExFPXMucHJvdG90eXBlLnJlYWRVSW50TEU9ZnVuY3Rpb24obCxmLGIpe2w9bD4+PjAsZj1mPj4+MCxifHxnZShsLGYsdGhpcy5sZW5ndGgpO2xldCBBPXRoaXNbbF0sVD0xLE89MDtmb3IoOysrTzxmJiYoVCo9MjU2KTspQSs9dGhpc1tsK09dKlQ7cmV0dXJuIEF9LHMucHJvdG90eXBlLnJlYWRVaW50QkU9cy5wcm90b3R5cGUucmVhZFVJbnRCRT1mdW5jdGlvbihsLGYsYil7bD1sPj4+MCxmPWY+Pj4wLGJ8fGdlKGwsZix0aGlzLmxlbmd0aCk7bGV0IEE9dGhpc1tsKy0tZl0sVD0xO2Zvcig7Zj4wJiYoVCo9MjU2KTspQSs9dGhpc1tsKy0tZl0qVDtyZXR1cm4gQX0scy5wcm90b3R5cGUucmVhZFVpbnQ4PXMucHJvdG90eXBlLnJlYWRVSW50OD1mdW5jdGlvbihsLGYpe3JldHVybiBsPWw+Pj4wLGZ8fGdlKGwsMSx0aGlzLmxlbmd0aCksdGhpc1tsXX0scy5wcm90b3R5cGUucmVhZFVpbnQxNkxFPXMucHJvdG90eXBlLnJlYWRVSW50MTZMRT1mdW5jdGlvbihsLGYpe3JldHVybiBsPWw+Pj4wLGZ8fGdlKGwsMix0aGlzLmxlbmd0aCksdGhpc1tsXXx0aGlzW2wrMV08PDh9LHMucHJvdG90eXBlLnJlYWRVaW50MTZCRT1zLnByb3RvdHlwZS5yZWFkVUludDE2QkU9ZnVuY3Rpb24obCxmKXtyZXR1cm4gbD1sPj4+MCxmfHxnZShsLDIsdGhpcy5sZW5ndGgpLHRoaXNbbF08PDh8dGhpc1tsKzFdfSxzLnByb3RvdHlwZS5yZWFkVWludDMyTEU9cy5wcm90b3R5cGUucmVhZFVJbnQzMkxFPWZ1bmN0aW9uKGwsZil7cmV0dXJuIGw9bD4+PjAsZnx8Z2UobCw0LHRoaXMubGVuZ3RoKSwodGhpc1tsXXx0aGlzW2wrMV08PDh8dGhpc1tsKzJdPDwxNikrdGhpc1tsKzNdKjE2Nzc3MjE2fSxzLnByb3RvdHlwZS5yZWFkVWludDMyQkU9cy5wcm90b3R5cGUucmVhZFVJbnQzMkJFPWZ1bmN0aW9uKGwsZil7cmV0dXJuIGw9bD4+PjAsZnx8Z2UobCw0LHRoaXMubGVuZ3RoKSx0aGlzW2xdKjE2Nzc3MjE2Kyh0aGlzW2wrMV08PDE2fHRoaXNbbCsyXTw8OHx0aGlzW2wrM10pfSxzLnByb3RvdHlwZS5yZWFkQmlnVUludDY0TEU9eHQoZnVuY3Rpb24obCl7bD1sPj4+MCxrcihsLFwib2Zmc2V0XCIpO2xldCBmPXRoaXNbbF0sYj10aGlzW2wrN107KGY9PT12b2lkIDB8fGI9PT12b2lkIDApJiZsaShsLHRoaXMubGVuZ3RoLTgpO2xldCBBPWYrdGhpc1srK2xdKjIqKjgrdGhpc1srK2xdKjIqKjE2K3RoaXNbKytsXSoyKioyNCxUPXRoaXNbKytsXSt0aGlzWysrbF0qMioqOCt0aGlzWysrbF0qMioqMTYrYioyKioyNDtyZXR1cm4gQmlnSW50KEEpKyhCaWdJbnQoVCk8PEJpZ0ludCgzMikpfSkscy5wcm90b3R5cGUucmVhZEJpZ1VJbnQ2NEJFPXh0KGZ1bmN0aW9uKGwpe2w9bD4+PjAsa3IobCxcIm9mZnNldFwiKTtsZXQgZj10aGlzW2xdLGI9dGhpc1tsKzddOyhmPT09dm9pZCAwfHxiPT09dm9pZCAwKSYmbGkobCx0aGlzLmxlbmd0aC04KTtsZXQgQT1mKjIqKjI0K3RoaXNbKytsXSoyKioxNit0aGlzWysrbF0qMioqOCt0aGlzWysrbF0sVD10aGlzWysrbF0qMioqMjQrdGhpc1srK2xdKjIqKjE2K3RoaXNbKytsXSoyKio4K2I7cmV0dXJuIChCaWdJbnQoQSk8PEJpZ0ludCgzMikpK0JpZ0ludChUKX0pLHMucHJvdG90eXBlLnJlYWRJbnRMRT1mdW5jdGlvbihsLGYsYil7bD1sPj4+MCxmPWY+Pj4wLGJ8fGdlKGwsZix0aGlzLmxlbmd0aCk7bGV0IEE9dGhpc1tsXSxUPTEsTz0wO2Zvcig7KytPPGYmJihUKj0yNTYpOylBKz10aGlzW2wrT10qVDtyZXR1cm4gVCo9MTI4LEE+PVQmJihBLT1NYXRoLnBvdygyLDgqZikpLEF9LHMucHJvdG90eXBlLnJlYWRJbnRCRT1mdW5jdGlvbihsLGYsYil7bD1sPj4+MCxmPWY+Pj4wLGJ8fGdlKGwsZix0aGlzLmxlbmd0aCk7bGV0IEE9ZixUPTEsTz10aGlzW2wrLS1BXTtmb3IoO0E+MCYmKFQqPTI1Nik7KU8rPXRoaXNbbCstLUFdKlQ7cmV0dXJuIFQqPTEyOCxPPj1UJiYoTy09TWF0aC5wb3coMiw4KmYpKSxPfSxzLnByb3RvdHlwZS5yZWFkSW50OD1mdW5jdGlvbihsLGYpe3JldHVybiBsPWw+Pj4wLGZ8fGdlKGwsMSx0aGlzLmxlbmd0aCksdGhpc1tsXSYxMjg/KDI1NS10aGlzW2xdKzEpKi0xOnRoaXNbbF19LHMucHJvdG90eXBlLnJlYWRJbnQxNkxFPWZ1bmN0aW9uKGwsZil7bD1sPj4+MCxmfHxnZShsLDIsdGhpcy5sZW5ndGgpO2xldCBiPXRoaXNbbF18dGhpc1tsKzFdPDw4O3JldHVybiBiJjMyNzY4P2J8NDI5NDkwMTc2MDpifSxzLnByb3RvdHlwZS5yZWFkSW50MTZCRT1mdW5jdGlvbihsLGYpe2w9bD4+PjAsZnx8Z2UobCwyLHRoaXMubGVuZ3RoKTtsZXQgYj10aGlzW2wrMV18dGhpc1tsXTw8ODtyZXR1cm4gYiYzMjc2OD9ifDQyOTQ5MDE3NjA6Yn0scy5wcm90b3R5cGUucmVhZEludDMyTEU9ZnVuY3Rpb24obCxmKXtyZXR1cm4gbD1sPj4+MCxmfHxnZShsLDQsdGhpcy5sZW5ndGgpLHRoaXNbbF18dGhpc1tsKzFdPDw4fHRoaXNbbCsyXTw8MTZ8dGhpc1tsKzNdPDwyNH0scy5wcm90b3R5cGUucmVhZEludDMyQkU9ZnVuY3Rpb24obCxmKXtyZXR1cm4gbD1sPj4+MCxmfHxnZShsLDQsdGhpcy5sZW5ndGgpLHRoaXNbbF08PDI0fHRoaXNbbCsxXTw8MTZ8dGhpc1tsKzJdPDw4fHRoaXNbbCszXX0scy5wcm90b3R5cGUucmVhZEJpZ0ludDY0TEU9eHQoZnVuY3Rpb24obCl7bD1sPj4+MCxrcihsLFwib2Zmc2V0XCIpO2xldCBmPXRoaXNbbF0sYj10aGlzW2wrN107KGY9PT12b2lkIDB8fGI9PT12b2lkIDApJiZsaShsLHRoaXMubGVuZ3RoLTgpO2xldCBBPXRoaXNbbCs0XSt0aGlzW2wrNV0qMioqOCt0aGlzW2wrNl0qMioqMTYrKGI8PDI0KTtyZXR1cm4gKEJpZ0ludChBKTw8QmlnSW50KDMyKSkrQmlnSW50KGYrdGhpc1srK2xdKjIqKjgrdGhpc1srK2xdKjIqKjE2K3RoaXNbKytsXSoyKioyNCl9KSxzLnByb3RvdHlwZS5yZWFkQmlnSW50NjRCRT14dChmdW5jdGlvbihsKXtsPWw+Pj4wLGtyKGwsXCJvZmZzZXRcIik7bGV0IGY9dGhpc1tsXSxiPXRoaXNbbCs3XTsoZj09PXZvaWQgMHx8Yj09PXZvaWQgMCkmJmxpKGwsdGhpcy5sZW5ndGgtOCk7bGV0IEE9KGY8PDI0KSt0aGlzWysrbF0qMioqMTYrdGhpc1srK2xdKjIqKjgrdGhpc1srK2xdO3JldHVybiAoQmlnSW50KEEpPDxCaWdJbnQoMzIpKStCaWdJbnQodGhpc1srK2xdKjIqKjI0K3RoaXNbKytsXSoyKioxNit0aGlzWysrbF0qMioqOCtiKX0pLHMucHJvdG90eXBlLnJlYWRGbG9hdExFPWZ1bmN0aW9uKGwsZil7cmV0dXJuIGw9bD4+PjAsZnx8Z2UobCw0LHRoaXMubGVuZ3RoKSxlLnJlYWQodGhpcyxsLCEwLDIzLDQpfSxzLnByb3RvdHlwZS5yZWFkRmxvYXRCRT1mdW5jdGlvbihsLGYpe3JldHVybiBsPWw+Pj4wLGZ8fGdlKGwsNCx0aGlzLmxlbmd0aCksZS5yZWFkKHRoaXMsbCwhMSwyMyw0KX0scy5wcm90b3R5cGUucmVhZERvdWJsZUxFPWZ1bmN0aW9uKGwsZil7cmV0dXJuIGw9bD4+PjAsZnx8Z2UobCw4LHRoaXMubGVuZ3RoKSxlLnJlYWQodGhpcyxsLCEwLDUyLDgpfSxzLnByb3RvdHlwZS5yZWFkRG91YmxlQkU9ZnVuY3Rpb24obCxmKXtyZXR1cm4gbD1sPj4+MCxmfHxnZShsLDgsdGhpcy5sZW5ndGgpLGUucmVhZCh0aGlzLGwsITEsNTIsOCl9O2Z1bmN0aW9uIENlKHAsbCxmLGIsQSxUKXtpZighcy5pc0J1ZmZlcihwKSl0aHJvdyBuZXcgVHlwZUVycm9yKCdcImJ1ZmZlclwiIGFyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXIgaW5zdGFuY2UnKTtpZihsPkF8fGw8VCl0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJ2YWx1ZVwiIGFyZ3VtZW50IGlzIG91dCBvZiBib3VuZHMnKTtpZihmK2I+cC5sZW5ndGgpdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJJbmRleCBvdXQgb2YgcmFuZ2VcIil9cy5wcm90b3R5cGUud3JpdGVVaW50TEU9cy5wcm90b3R5cGUud3JpdGVVSW50TEU9ZnVuY3Rpb24obCxmLGIsQSl7aWYobD0rbCxmPWY+Pj4wLGI9Yj4+PjAsIUEpe2xldCAkPU1hdGgucG93KDIsOCpiKS0xO0NlKHRoaXMsbCxmLGIsJCwwKTt9bGV0IFQ9MSxPPTA7Zm9yKHRoaXNbZl09bCYyNTU7KytPPGImJihUKj0yNTYpOyl0aGlzW2YrT109bC9UJjI1NTtyZXR1cm4gZitifSxzLnByb3RvdHlwZS53cml0ZVVpbnRCRT1zLnByb3RvdHlwZS53cml0ZVVJbnRCRT1mdW5jdGlvbihsLGYsYixBKXtpZihsPStsLGY9Zj4+PjAsYj1iPj4+MCwhQSl7bGV0ICQ9TWF0aC5wb3coMiw4KmIpLTE7Q2UodGhpcyxsLGYsYiwkLDApO31sZXQgVD1iLTEsTz0xO2Zvcih0aGlzW2YrVF09bCYyNTU7LS1UPj0wJiYoTyo9MjU2KTspdGhpc1tmK1RdPWwvTyYyNTU7cmV0dXJuIGYrYn0scy5wcm90b3R5cGUud3JpdGVVaW50OD1zLnByb3RvdHlwZS53cml0ZVVJbnQ4PWZ1bmN0aW9uKGwsZixiKXtyZXR1cm4gbD0rbCxmPWY+Pj4wLGJ8fENlKHRoaXMsbCxmLDEsMjU1LDApLHRoaXNbZl09bCYyNTUsZisxfSxzLnByb3RvdHlwZS53cml0ZVVpbnQxNkxFPXMucHJvdG90eXBlLndyaXRlVUludDE2TEU9ZnVuY3Rpb24obCxmLGIpe3JldHVybiBsPStsLGY9Zj4+PjAsYnx8Q2UodGhpcyxsLGYsMiw2NTUzNSwwKSx0aGlzW2ZdPWwmMjU1LHRoaXNbZisxXT1sPj4+OCxmKzJ9LHMucHJvdG90eXBlLndyaXRlVWludDE2QkU9cy5wcm90b3R5cGUud3JpdGVVSW50MTZCRT1mdW5jdGlvbihsLGYsYil7cmV0dXJuIGw9K2wsZj1mPj4+MCxifHxDZSh0aGlzLGwsZiwyLDY1NTM1LDApLHRoaXNbZl09bD4+PjgsdGhpc1tmKzFdPWwmMjU1LGYrMn0scy5wcm90b3R5cGUud3JpdGVVaW50MzJMRT1zLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFPWZ1bmN0aW9uKGwsZixiKXtyZXR1cm4gbD0rbCxmPWY+Pj4wLGJ8fENlKHRoaXMsbCxmLDQsNDI5NDk2NzI5NSwwKSx0aGlzW2YrM109bD4+PjI0LHRoaXNbZisyXT1sPj4+MTYsdGhpc1tmKzFdPWw+Pj44LHRoaXNbZl09bCYyNTUsZis0fSxzLnByb3RvdHlwZS53cml0ZVVpbnQzMkJFPXMucHJvdG90eXBlLndyaXRlVUludDMyQkU9ZnVuY3Rpb24obCxmLGIpe3JldHVybiBsPStsLGY9Zj4+PjAsYnx8Q2UodGhpcyxsLGYsNCw0Mjk0OTY3Mjk1LDApLHRoaXNbZl09bD4+PjI0LHRoaXNbZisxXT1sPj4+MTYsdGhpc1tmKzJdPWw+Pj44LHRoaXNbZiszXT1sJjI1NSxmKzR9O2Z1bmN0aW9uIHZsKHAsbCxmLGIsQSl7UmwobCxiLEEscCxmLDcpO2xldCBUPU51bWJlcihsJkJpZ0ludCg0Mjk0OTY3Mjk1KSk7cFtmKytdPVQsVD1UPj44LHBbZisrXT1ULFQ9VD4+OCxwW2YrK109VCxUPVQ+PjgscFtmKytdPVQ7bGV0IE89TnVtYmVyKGw+PkJpZ0ludCgzMikmQmlnSW50KDQyOTQ5NjcyOTUpKTtyZXR1cm4gcFtmKytdPU8sTz1PPj44LHBbZisrXT1PLE89Tz4+OCxwW2YrK109TyxPPU8+PjgscFtmKytdPU8sZn1mdW5jdGlvbiBFbChwLGwsZixiLEEpe1JsKGwsYixBLHAsZiw3KTtsZXQgVD1OdW1iZXIobCZCaWdJbnQoNDI5NDk2NzI5NSkpO3BbZis3XT1ULFQ9VD4+OCxwW2YrNl09VCxUPVQ+PjgscFtmKzVdPVQsVD1UPj44LHBbZis0XT1UO2xldCBPPU51bWJlcihsPj5CaWdJbnQoMzIpJkJpZ0ludCg0Mjk0OTY3Mjk1KSk7cmV0dXJuIHBbZiszXT1PLE89Tz4+OCxwW2YrMl09TyxPPU8+PjgscFtmKzFdPU8sTz1PPj44LHBbZl09TyxmKzh9cy5wcm90b3R5cGUud3JpdGVCaWdVSW50NjRMRT14dChmdW5jdGlvbihsLGY9MCl7cmV0dXJuIHZsKHRoaXMsbCxmLEJpZ0ludCgwKSxCaWdJbnQoXCIweGZmZmZmZmZmZmZmZmZmZmZcIikpfSkscy5wcm90b3R5cGUud3JpdGVCaWdVSW50NjRCRT14dChmdW5jdGlvbihsLGY9MCl7cmV0dXJuIEVsKHRoaXMsbCxmLEJpZ0ludCgwKSxCaWdJbnQoXCIweGZmZmZmZmZmZmZmZmZmZmZcIikpfSkscy5wcm90b3R5cGUud3JpdGVJbnRMRT1mdW5jdGlvbihsLGYsYixBKXtpZihsPStsLGY9Zj4+PjAsIUEpe2xldCBzZT1NYXRoLnBvdygyLDgqYi0xKTtDZSh0aGlzLGwsZixiLHNlLTEsLXNlKTt9bGV0IFQ9MCxPPTEsJD0wO2Zvcih0aGlzW2ZdPWwmMjU1OysrVDxiJiYoTyo9MjU2KTspbDwwJiYkPT09MCYmdGhpc1tmK1QtMV0hPT0wJiYoJD0xKSx0aGlzW2YrVF09KGwvTz4+MCktJCYyNTU7cmV0dXJuIGYrYn0scy5wcm90b3R5cGUud3JpdGVJbnRCRT1mdW5jdGlvbihsLGYsYixBKXtpZihsPStsLGY9Zj4+PjAsIUEpe2xldCBzZT1NYXRoLnBvdygyLDgqYi0xKTtDZSh0aGlzLGwsZixiLHNlLTEsLXNlKTt9bGV0IFQ9Yi0xLE89MSwkPTA7Zm9yKHRoaXNbZitUXT1sJjI1NTstLVQ+PTAmJihPKj0yNTYpOylsPDAmJiQ9PT0wJiZ0aGlzW2YrVCsxXSE9PTAmJigkPTEpLHRoaXNbZitUXT0obC9PPj4wKS0kJjI1NTtyZXR1cm4gZitifSxzLnByb3RvdHlwZS53cml0ZUludDg9ZnVuY3Rpb24obCxmLGIpe3JldHVybiBsPStsLGY9Zj4+PjAsYnx8Q2UodGhpcyxsLGYsMSwxMjcsLTEyOCksbDwwJiYobD0yNTUrbCsxKSx0aGlzW2ZdPWwmMjU1LGYrMX0scy5wcm90b3R5cGUud3JpdGVJbnQxNkxFPWZ1bmN0aW9uKGwsZixiKXtyZXR1cm4gbD0rbCxmPWY+Pj4wLGJ8fENlKHRoaXMsbCxmLDIsMzI3NjcsLTMyNzY4KSx0aGlzW2ZdPWwmMjU1LHRoaXNbZisxXT1sPj4+OCxmKzJ9LHMucHJvdG90eXBlLndyaXRlSW50MTZCRT1mdW5jdGlvbihsLGYsYil7cmV0dXJuIGw9K2wsZj1mPj4+MCxifHxDZSh0aGlzLGwsZiwyLDMyNzY3LC0zMjc2OCksdGhpc1tmXT1sPj4+OCx0aGlzW2YrMV09bCYyNTUsZisyfSxzLnByb3RvdHlwZS53cml0ZUludDMyTEU9ZnVuY3Rpb24obCxmLGIpe3JldHVybiBsPStsLGY9Zj4+PjAsYnx8Q2UodGhpcyxsLGYsNCwyMTQ3NDgzNjQ3LC0yMTQ3NDgzNjQ4KSx0aGlzW2ZdPWwmMjU1LHRoaXNbZisxXT1sPj4+OCx0aGlzW2YrMl09bD4+PjE2LHRoaXNbZiszXT1sPj4+MjQsZis0fSxzLnByb3RvdHlwZS53cml0ZUludDMyQkU9ZnVuY3Rpb24obCxmLGIpe3JldHVybiBsPStsLGY9Zj4+PjAsYnx8Q2UodGhpcyxsLGYsNCwyMTQ3NDgzNjQ3LC0yMTQ3NDgzNjQ4KSxsPDAmJihsPTQyOTQ5NjcyOTUrbCsxKSx0aGlzW2ZdPWw+Pj4yNCx0aGlzW2YrMV09bD4+PjE2LHRoaXNbZisyXT1sPj4+OCx0aGlzW2YrM109bCYyNTUsZis0fSxzLnByb3RvdHlwZS53cml0ZUJpZ0ludDY0TEU9eHQoZnVuY3Rpb24obCxmPTApe3JldHVybiB2bCh0aGlzLGwsZiwtQmlnSW50KFwiMHg4MDAwMDAwMDAwMDAwMDAwXCIpLEJpZ0ludChcIjB4N2ZmZmZmZmZmZmZmZmZmZlwiKSl9KSxzLnByb3RvdHlwZS53cml0ZUJpZ0ludDY0QkU9eHQoZnVuY3Rpb24obCxmPTApe3JldHVybiBFbCh0aGlzLGwsZiwtQmlnSW50KFwiMHg4MDAwMDAwMDAwMDAwMDAwXCIpLEJpZ0ludChcIjB4N2ZmZmZmZmZmZmZmZmZmZlwiKSl9KTtmdW5jdGlvbiBTbChwLGwsZixiLEEsVCl7aWYoZitiPnAubGVuZ3RoKXRocm93IG5ldyBSYW5nZUVycm9yKFwiSW5kZXggb3V0IG9mIHJhbmdlXCIpO2lmKGY8MCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIkluZGV4IG91dCBvZiByYW5nZVwiKX1mdW5jdGlvbiBBbChwLGwsZixiLEEpe3JldHVybiBsPStsLGY9Zj4+PjAsQXx8U2wocCxsLGYsNCksZS53cml0ZShwLGwsZixiLDIzLDQpLGYrNH1zLnByb3RvdHlwZS53cml0ZUZsb2F0TEU9ZnVuY3Rpb24obCxmLGIpe3JldHVybiBBbCh0aGlzLGwsZiwhMCxiKX0scy5wcm90b3R5cGUud3JpdGVGbG9hdEJFPWZ1bmN0aW9uKGwsZixiKXtyZXR1cm4gQWwodGhpcyxsLGYsITEsYil9O2Z1bmN0aW9uIElsKHAsbCxmLGIsQSl7cmV0dXJuIGw9K2wsZj1mPj4+MCxBfHxTbChwLGwsZiw4KSxlLndyaXRlKHAsbCxmLGIsNTIsOCksZis4fXMucHJvdG90eXBlLndyaXRlRG91YmxlTEU9ZnVuY3Rpb24obCxmLGIpe3JldHVybiBJbCh0aGlzLGwsZiwhMCxiKX0scy5wcm90b3R5cGUud3JpdGVEb3VibGVCRT1mdW5jdGlvbihsLGYsYil7cmV0dXJuIElsKHRoaXMsbCxmLCExLGIpfSxzLnByb3RvdHlwZS5jb3B5PWZ1bmN0aW9uKGwsZixiLEEpe2lmKCFzLmlzQnVmZmVyKGwpKXRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBzaG91bGQgYmUgYSBCdWZmZXJcIik7aWYoYnx8KGI9MCksIUEmJkEhPT0wJiYoQT10aGlzLmxlbmd0aCksZj49bC5sZW5ndGgmJihmPWwubGVuZ3RoKSxmfHwoZj0wKSxBPjAmJkE8YiYmKEE9YiksQT09PWJ8fGwubGVuZ3RoPT09MHx8dGhpcy5sZW5ndGg9PT0wKXJldHVybiAwO2lmKGY8MCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcInRhcmdldFN0YXJ0IG91dCBvZiBib3VuZHNcIik7aWYoYjwwfHxiPj10aGlzLmxlbmd0aCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIkluZGV4IG91dCBvZiByYW5nZVwiKTtpZihBPDApdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJzb3VyY2VFbmQgb3V0IG9mIGJvdW5kc1wiKTtBPnRoaXMubGVuZ3RoJiYoQT10aGlzLmxlbmd0aCksbC5sZW5ndGgtZjxBLWImJihBPWwubGVuZ3RoLWYrYik7bGV0IFQ9QS1iO3JldHVybiB0aGlzPT09bCYmdHlwZW9mIFVpbnQ4QXJyYXkucHJvdG90eXBlLmNvcHlXaXRoaW49PVwiZnVuY3Rpb25cIj90aGlzLmNvcHlXaXRoaW4oZixiLEEpOlVpbnQ4QXJyYXkucHJvdG90eXBlLnNldC5jYWxsKGwsdGhpcy5zdWJhcnJheShiLEEpLGYpLFR9LHMucHJvdG90eXBlLmZpbGw9ZnVuY3Rpb24obCxmLGIsQSl7aWYodHlwZW9mIGw9PVwic3RyaW5nXCIpe2lmKHR5cGVvZiBmPT1cInN0cmluZ1wiPyhBPWYsZj0wLGI9dGhpcy5sZW5ndGgpOnR5cGVvZiBiPT1cInN0cmluZ1wiJiYoQT1iLGI9dGhpcy5sZW5ndGgpLEEhPT12b2lkIDAmJnR5cGVvZiBBIT1cInN0cmluZ1wiKXRocm93IG5ldyBUeXBlRXJyb3IoXCJlbmNvZGluZyBtdXN0IGJlIGEgc3RyaW5nXCIpO2lmKHR5cGVvZiBBPT1cInN0cmluZ1wiJiYhcy5pc0VuY29kaW5nKEEpKXRocm93IG5ldyBUeXBlRXJyb3IoXCJVbmtub3duIGVuY29kaW5nOiBcIitBKTtpZihsLmxlbmd0aD09PTEpe2xldCBPPWwuY2hhckNvZGVBdCgwKTsoQT09PVwidXRmOFwiJiZPPDEyOHx8QT09PVwibGF0aW4xXCIpJiYobD1PKTt9fWVsc2UgdHlwZW9mIGw9PVwibnVtYmVyXCI/bD1sJjI1NTp0eXBlb2YgbD09XCJib29sZWFuXCImJihsPU51bWJlcihsKSk7aWYoZjwwfHx0aGlzLmxlbmd0aDxmfHx0aGlzLmxlbmd0aDxiKXRocm93IG5ldyBSYW5nZUVycm9yKFwiT3V0IG9mIHJhbmdlIGluZGV4XCIpO2lmKGI8PWYpcmV0dXJuIHRoaXM7Zj1mPj4+MCxiPWI9PT12b2lkIDA/dGhpcy5sZW5ndGg6Yj4+PjAsbHx8KGw9MCk7bGV0IFQ7aWYodHlwZW9mIGw9PVwibnVtYmVyXCIpZm9yKFQ9ZjtUPGI7KytUKXRoaXNbVF09bDtlbHNlIHtsZXQgTz1zLmlzQnVmZmVyKGwpP2w6cy5mcm9tKGwsQSksJD1PLmxlbmd0aDtpZigkPT09MCl0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgdmFsdWUgXCInK2wrJ1wiIGlzIGludmFsaWQgZm9yIGFyZ3VtZW50IFwidmFsdWVcIicpO2ZvcihUPTA7VDxiLWY7KytUKXRoaXNbVCtmXT1PW1QlJF07fXJldHVybiB0aGlzfTtsZXQgT3I9e307ZnVuY3Rpb24gZnMocCxsLGYpe09yW3BdPWNsYXNzIGV4dGVuZHMgZntjb25zdHJ1Y3Rvcigpe3N1cGVyKCksT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsXCJtZXNzYWdlXCIse3ZhbHVlOmwuYXBwbHkodGhpcyxhcmd1bWVudHMpLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH0pLHRoaXMubmFtZT1gJHt0aGlzLm5hbWV9IFske3B9XWAsdGhpcy5zdGFjayxkZWxldGUgdGhpcy5uYW1lO31nZXQgY29kZSgpe3JldHVybiBwfXNldCBjb2RlKEEpe09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLFwiY29kZVwiLHtjb25maWd1cmFibGU6ITAsZW51bWVyYWJsZTohMCx2YWx1ZTpBLHdyaXRhYmxlOiEwfSk7fXRvU3RyaW5nKCl7cmV0dXJuIGAke3RoaXMubmFtZX0gWyR7cH1dOiAke3RoaXMubWVzc2FnZX1gfX07fWZzKFwiRVJSX0JVRkZFUl9PVVRfT0ZfQk9VTkRTXCIsZnVuY3Rpb24ocCl7cmV0dXJuIHA/YCR7cH0gaXMgb3V0c2lkZSBvZiBidWZmZXIgYm91bmRzYDpcIkF0dGVtcHQgdG8gYWNjZXNzIG1lbW9yeSBvdXRzaWRlIGJ1ZmZlciBib3VuZHNcIn0sUmFuZ2VFcnJvciksZnMoXCJFUlJfSU5WQUxJRF9BUkdfVFlQRVwiLGZ1bmN0aW9uKHAsbCl7cmV0dXJuIGBUaGUgXCIke3B9XCIgYXJndW1lbnQgbXVzdCBiZSBvZiB0eXBlIG51bWJlci4gUmVjZWl2ZWQgdHlwZSAke3R5cGVvZiBsfWB9LFR5cGVFcnJvciksZnMoXCJFUlJfT1VUX09GX1JBTkdFXCIsZnVuY3Rpb24ocCxsLGYpe2xldCBiPWBUaGUgdmFsdWUgb2YgXCIke3B9XCIgaXMgb3V0IG9mIHJhbmdlLmAsQT1mO3JldHVybiBOdW1iZXIuaXNJbnRlZ2VyKGYpJiZNYXRoLmFicyhmKT4yKiozMj9BPVRsKFN0cmluZyhmKSk6dHlwZW9mIGY9PVwiYmlnaW50XCImJihBPVN0cmluZyhmKSwoZj5CaWdJbnQoMikqKkJpZ0ludCgzMil8fGY8LShCaWdJbnQoMikqKkJpZ0ludCgzMikpKSYmKEE9VGwoQSkpLEErPVwiblwiKSxiKz1gIEl0IG11c3QgYmUgJHtsfS4gUmVjZWl2ZWQgJHtBfWAsYn0sUmFuZ2VFcnJvcik7ZnVuY3Rpb24gVGwocCl7bGV0IGw9XCJcIixmPXAubGVuZ3RoLGI9cFswXT09PVwiLVwiPzE6MDtmb3IoO2Y+PWIrNDtmLT0zKWw9YF8ke3Auc2xpY2UoZi0zLGYpfSR7bH1gO3JldHVybiBgJHtwLnNsaWNlKDAsZil9JHtsfWB9ZnVuY3Rpb24gRGcocCxsLGYpe2tyKGwsXCJvZmZzZXRcIiksKHBbbF09PT12b2lkIDB8fHBbbCtmXT09PXZvaWQgMCkmJmxpKGwscC5sZW5ndGgtKGYrMSkpO31mdW5jdGlvbiBSbChwLGwsZixiLEEsVCl7aWYocD5mfHxwPGwpe2xldCBPPXR5cGVvZiBsPT1cImJpZ2ludFwiP1wiblwiOlwiXCIsJDt0aHJvdyBUPjM/bD09PTB8fGw9PT1CaWdJbnQoMCk/JD1gPj0gMCR7T30gYW5kIDwgMiR7T30gKiogJHsoVCsxKSo4fSR7T31gOiQ9YD49IC0oMiR7T30gKiogJHsoVCsxKSo4LTF9JHtPfSkgYW5kIDwgMiAqKiAkeyhUKzEpKjgtMX0ke099YDokPWA+PSAke2x9JHtPfSBhbmQgPD0gJHtmfSR7T31gLG5ldyBPci5FUlJfT1VUX09GX1JBTkdFKFwidmFsdWVcIiwkLHApfURnKGIsQSxUKTt9ZnVuY3Rpb24ga3IocCxsKXtpZih0eXBlb2YgcCE9XCJudW1iZXJcIil0aHJvdyBuZXcgT3IuRVJSX0lOVkFMSURfQVJHX1RZUEUobCxcIm51bWJlclwiLHApfWZ1bmN0aW9uIGxpKHAsbCxmKXt0aHJvdyBNYXRoLmZsb29yKHApIT09cD8oa3IocCxmKSxuZXcgT3IuRVJSX09VVF9PRl9SQU5HRShmfHxcIm9mZnNldFwiLFwiYW4gaW50ZWdlclwiLHApKTpsPDA/bmV3IE9yLkVSUl9CVUZGRVJfT1VUX09GX0JPVU5EUzpuZXcgT3IuRVJSX09VVF9PRl9SQU5HRShmfHxcIm9mZnNldFwiLGA+PSAke2Y/MTowfSBhbmQgPD0gJHtsfWAscCl9bGV0IGpnPS9bXisvMC05QS1aYS16LV9dL2c7ZnVuY3Rpb24gRmcocCl7aWYocD1wLnNwbGl0KFwiPVwiKVswXSxwPXAudHJpbSgpLnJlcGxhY2UoamcsXCJcIikscC5sZW5ndGg8MilyZXR1cm4gXCJcIjtmb3IoO3AubGVuZ3RoJTQhPT0wOylwPXArXCI9XCI7cmV0dXJuIHB9ZnVuY3Rpb24gY3MocCxsKXtsPWx8fDEvMDtsZXQgZixiPXAubGVuZ3RoLEE9bnVsbCxUPVtdO2ZvcihsZXQgTz0wO088YjsrK08pe2lmKGY9cC5jaGFyQ29kZUF0KE8pLGY+NTUyOTUmJmY8NTczNDQpe2lmKCFBKXtpZihmPjU2MzE5KXsobC09Myk+LTEmJlQucHVzaCgyMzksMTkxLDE4OSk7Y29udGludWV9ZWxzZSBpZihPKzE9PT1iKXsobC09Myk+LTEmJlQucHVzaCgyMzksMTkxLDE4OSk7Y29udGludWV9QT1mO2NvbnRpbnVlfWlmKGY8NTYzMjApeyhsLT0zKT4tMSYmVC5wdXNoKDIzOSwxOTEsMTg5KSxBPWY7Y29udGludWV9Zj0oQS01NTI5Njw8MTB8Zi01NjMyMCkrNjU1MzY7fWVsc2UgQSYmKGwtPTMpPi0xJiZULnB1c2goMjM5LDE5MSwxODkpO2lmKEE9bnVsbCxmPDEyOCl7aWYoKGwtPTEpPDApYnJlYWs7VC5wdXNoKGYpO31lbHNlIGlmKGY8MjA0OCl7aWYoKGwtPTIpPDApYnJlYWs7VC5wdXNoKGY+PjZ8MTkyLGYmNjN8MTI4KTt9ZWxzZSBpZihmPDY1NTM2KXtpZigobC09Myk8MClicmVhaztULnB1c2goZj4+MTJ8MjI0LGY+PjYmNjN8MTI4LGYmNjN8MTI4KTt9ZWxzZSBpZihmPDExMTQxMTIpe2lmKChsLT00KTwwKWJyZWFrO1QucHVzaChmPj4xOHwyNDAsZj4+MTImNjN8MTI4LGY+PjYmNjN8MTI4LGYmNjN8MTI4KTt9ZWxzZSB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGNvZGUgcG9pbnRcIil9cmV0dXJuIFR9ZnVuY3Rpb24gV2cocCl7bGV0IGw9W107Zm9yKGxldCBmPTA7ZjxwLmxlbmd0aDsrK2YpbC5wdXNoKHAuY2hhckNvZGVBdChmKSYyNTUpO3JldHVybiBsfWZ1bmN0aW9uICRnKHAsbCl7bGV0IGYsYixBLFQ9W107Zm9yKGxldCBPPTA7TzxwLmxlbmd0aCYmISgobC09Mik8MCk7KytPKWY9cC5jaGFyQ29kZUF0KE8pLGI9Zj4+OCxBPWYlMjU2LFQucHVzaChBKSxULnB1c2goYik7cmV0dXJuIFR9ZnVuY3Rpb24gQ2wocCl7cmV0dXJuIHQudG9CeXRlQXJyYXkoRmcocCkpfWZ1bmN0aW9uIHFpKHAsbCxmLGIpe2xldCBBO2ZvcihBPTA7QTxiJiYhKEErZj49bC5sZW5ndGh8fEE+PXAubGVuZ3RoKTsrK0EpbFtBK2ZdPXBbQV07cmV0dXJuIEF9ZnVuY3Rpb24gWWUocCxsKXtyZXR1cm4gcCBpbnN0YW5jZW9mIGx8fHAhPW51bGwmJnAuY29uc3RydWN0b3IhPW51bGwmJnAuY29uc3RydWN0b3IubmFtZSE9bnVsbCYmcC5jb25zdHJ1Y3Rvci5uYW1lPT09bC5uYW1lfWZ1bmN0aW9uIGhzKHApe3JldHVybiBwIT09cH1sZXQgSGc9ZnVuY3Rpb24oKXtsZXQgcD1cIjAxMjM0NTY3ODlhYmNkZWZcIixsPW5ldyBBcnJheSgyNTYpO2ZvcihsZXQgZj0wO2Y8MTY7KytmKXtsZXQgYj1mKjE2O2ZvcihsZXQgQT0wO0E8MTY7KytBKWxbYitBXT1wW2ZdK3BbQV07fXJldHVybiBsfSgpO2Z1bmN0aW9uIHh0KHApe3JldHVybiB0eXBlb2YgQmlnSW50PlwidVwiP1ZnOnB9ZnVuY3Rpb24gVmcoKXt0aHJvdyBuZXcgRXJyb3IoXCJCaWdJbnQgbm90IHN1cHBvcnRlZFwiKX1yZXR1cm4gSnR9dmFyIHVpLFZ1LFdpLHp1LEp0LEt1LEx0LHgsZXksdHkseWU9d2UoKCk9Pnt2KCk7bSgpO18oKTt1aT17fSxWdT0hMTtXaT17fSx6dT0hMTtKdD17fSxLdT0hMTtMdD1aZygpO0x0LkJ1ZmZlcjtMdC5TbG93QnVmZmVyO0x0LklOU1BFQ1RfTUFYX0JZVEVTO0x0LmtNYXhMZW5ndGg7eD1MdC5CdWZmZXIsZXk9THQuSU5TUEVDVF9NQVhfQllURVMsdHk9THQua01heExlbmd0aDt9KTt2YXIgdj13ZSgoKT0+e3llKCk7fSk7dmFyIEd1PU0od3M9Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkod3MsXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSk7dmFyIGJzPWNsYXNze2NvbnN0cnVjdG9yKGUpe3RoaXMuYWxpYXNUb1RvcGljPXt9LHRoaXMubWF4PWU7fXB1dChlLHIpe3JldHVybiByPT09MHx8cj50aGlzLm1heD8hMToodGhpcy5hbGlhc1RvVG9waWNbcl09ZSx0aGlzLmxlbmd0aD1PYmplY3Qua2V5cyh0aGlzLmFsaWFzVG9Ub3BpYykubGVuZ3RoLCEwKX1nZXRUb3BpY0J5QWxpYXMoZSl7cmV0dXJuIHRoaXMuYWxpYXNUb1RvcGljW2VdfWNsZWFyKCl7dGhpcy5hbGlhc1RvVG9waWM9e307fX07d3MuZGVmYXVsdD1iczt9KTt2YXIgY2U9TSgoUEEsUXUpPT57digpO20oKTtfKCk7UXUuZXhwb3J0cz17QXJyYXlJc0FycmF5KHQpe3JldHVybiBBcnJheS5pc0FycmF5KHQpfSxBcnJheVByb3RvdHlwZUluY2x1ZGVzKHQsZSl7cmV0dXJuIHQuaW5jbHVkZXMoZSl9LEFycmF5UHJvdG90eXBlSW5kZXhPZih0LGUpe3JldHVybiB0LmluZGV4T2YoZSl9LEFycmF5UHJvdG90eXBlSm9pbih0LGUpe3JldHVybiB0LmpvaW4oZSl9LEFycmF5UHJvdG90eXBlTWFwKHQsZSl7cmV0dXJuIHQubWFwKGUpfSxBcnJheVByb3RvdHlwZVBvcCh0LGUpe3JldHVybiB0LnBvcChlKX0sQXJyYXlQcm90b3R5cGVQdXNoKHQsZSl7cmV0dXJuIHQucHVzaChlKX0sQXJyYXlQcm90b3R5cGVTbGljZSh0LGUscil7cmV0dXJuIHQuc2xpY2UoZSxyKX0sRXJyb3IsRnVuY3Rpb25Qcm90b3R5cGVDYWxsKHQsZSwuLi5yKXtyZXR1cm4gdC5jYWxsKGUsLi4ucil9LEZ1bmN0aW9uUHJvdG90eXBlU3ltYm9sSGFzSW5zdGFuY2UodCxlKXtyZXR1cm4gRnVuY3Rpb24ucHJvdG90eXBlW1N5bWJvbC5oYXNJbnN0YW5jZV0uY2FsbCh0LGUpfSxNYXRoRmxvb3I6TWF0aC5mbG9vcixOdW1iZXIsTnVtYmVySXNJbnRlZ2VyOk51bWJlci5pc0ludGVnZXIsTnVtYmVySXNOYU46TnVtYmVyLmlzTmFOLE51bWJlck1BWF9TQUZFX0lOVEVHRVI6TnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIsTnVtYmVyTUlOX1NBRkVfSU5URUdFUjpOdW1iZXIuTUlOX1NBRkVfSU5URUdFUixOdW1iZXJQYXJzZUludDpOdW1iZXIucGFyc2VJbnQsT2JqZWN0RGVmaW5lUHJvcGVydGllcyh0LGUpe3JldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh0LGUpfSxPYmplY3REZWZpbmVQcm9wZXJ0eSh0LGUscil7cmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LGUscil9LE9iamVjdEdldE93blByb3BlcnR5RGVzY3JpcHRvcih0LGUpe3JldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHQsZSl9LE9iamVjdEtleXModCl7cmV0dXJuIE9iamVjdC5rZXlzKHQpfSxPYmplY3RTZXRQcm90b3R5cGVPZih0LGUpe3JldHVybiBPYmplY3Quc2V0UHJvdG90eXBlT2YodCxlKX0sUHJvbWlzZSxQcm9taXNlUHJvdG90eXBlQ2F0Y2godCxlKXtyZXR1cm4gdC5jYXRjaChlKX0sUHJvbWlzZVByb3RvdHlwZVRoZW4odCxlLHIpe3JldHVybiB0LnRoZW4oZSxyKX0sUHJvbWlzZVJlamVjdCh0KXtyZXR1cm4gUHJvbWlzZS5yZWplY3QodCl9LFJlZmxlY3RBcHBseTpSZWZsZWN0LmFwcGx5LFJlZ0V4cFByb3RvdHlwZVRlc3QodCxlKXtyZXR1cm4gdC50ZXN0KGUpfSxTYWZlU2V0OlNldCxTdHJpbmcsU3RyaW5nUHJvdG90eXBlU2xpY2UodCxlLHIpe3JldHVybiB0LnNsaWNlKGUscil9LFN0cmluZ1Byb3RvdHlwZVRvTG93ZXJDYXNlKHQpe3JldHVybiB0LnRvTG93ZXJDYXNlKCl9LFN0cmluZ1Byb3RvdHlwZVRvVXBwZXJDYXNlKHQpe3JldHVybiB0LnRvVXBwZXJDYXNlKCl9LFN0cmluZ1Byb3RvdHlwZVRyaW0odCl7cmV0dXJuIHQudHJpbSgpfSxTeW1ib2wsU3ltYm9sRm9yOlN5bWJvbC5mb3IsU3ltYm9sQXN5bmNJdGVyYXRvcjpTeW1ib2wuYXN5bmNJdGVyYXRvcixTeW1ib2xIYXNJbnN0YW5jZTpTeW1ib2wuaGFzSW5zdGFuY2UsU3ltYm9sSXRlcmF0b3I6U3ltYm9sLml0ZXJhdG9yLFR5cGVkQXJyYXlQcm90b3R5cGVTZXQodCxlLHIpe3JldHVybiB0LnNldChlLHIpfSxVaW50OEFycmF5fTt9KTt2YXIgSmU9TSgoakEsbXMpPT57digpO20oKTtfKCk7dmFyIHJ5PSh5ZSgpLFgoX2UpKSxpeT1PYmplY3QuZ2V0UHJvdG90eXBlT2YoYXN5bmMgZnVuY3Rpb24oKXt9KS5jb25zdHJ1Y3RvcixZdT1nbG9iYWxUaGlzLkJsb2J8fHJ5LkJsb2Isbnk9dHlwZW9mIFl1PFwidVwiP2Z1bmN0aW9uKGUpe3JldHVybiBlIGluc3RhbmNlb2YgWXV9OmZ1bmN0aW9uKGUpe3JldHVybiAhMX0sX3M9Y2xhc3MgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihlKXtpZighQXJyYXkuaXNBcnJheShlKSl0aHJvdyBuZXcgVHlwZUVycm9yKGBFeHBlY3RlZCBpbnB1dCB0byBiZSBhbiBBcnJheSwgZ290ICR7dHlwZW9mIGV9YCk7bGV0IHI9XCJcIjtmb3IobGV0IGk9MDtpPGUubGVuZ3RoO2krKylyKz1gICAgICR7ZVtpXS5zdGFja31cbmA7c3VwZXIociksdGhpcy5uYW1lPVwiQWdncmVnYXRlRXJyb3JcIix0aGlzLmVycm9ycz1lO319O21zLmV4cG9ydHM9e0FnZ3JlZ2F0ZUVycm9yOl9zLGtFbXB0eU9iamVjdDpPYmplY3QuZnJlZXplKHt9KSxvbmNlKHQpe2xldCBlPSExO3JldHVybiBmdW5jdGlvbiguLi5yKXtlfHwoZT0hMCx0LmFwcGx5KHRoaXMscikpO319LGNyZWF0ZURlZmVycmVkUHJvbWlzZTpmdW5jdGlvbigpe2xldCB0LGU7cmV0dXJuIHtwcm9taXNlOm5ldyBQcm9taXNlKChpLG4pPT57dD1pLGU9bjt9KSxyZXNvbHZlOnQscmVqZWN0OmV9fSxwcm9taXNpZnkodCl7cmV0dXJuIG5ldyBQcm9taXNlKChlLHIpPT57dCgoaSwuLi5uKT0+aT9yKGkpOmUoLi4ubikpO30pfSxkZWJ1Z2xvZygpe3JldHVybiBmdW5jdGlvbigpe319LGZvcm1hdCh0LC4uLmUpe3JldHVybiB0LnJlcGxhY2UoLyUoW3NkaWZqXSkvZyxmdW5jdGlvbiguLi5bcixpXSl7bGV0IG49ZS5zaGlmdCgpO3JldHVybiBpPT09XCJmXCI/bi50b0ZpeGVkKDYpOmk9PT1cImpcIj9KU09OLnN0cmluZ2lmeShuKTppPT09XCJzXCImJnR5cGVvZiBuPT1cIm9iamVjdFwiP2Ake24uY29uc3RydWN0b3IhPT1PYmplY3Q/bi5jb25zdHJ1Y3Rvci5uYW1lOlwiXCJ9IHt9YC50cmltKCk6bi50b1N0cmluZygpfSl9LGluc3BlY3QodCl7c3dpdGNoKHR5cGVvZiB0KXtjYXNlXCJzdHJpbmdcIjppZih0LmluY2x1ZGVzKFwiJ1wiKSlpZih0LmluY2x1ZGVzKCdcIicpKXtpZighdC5pbmNsdWRlcyhcImBcIikmJiF0LmluY2x1ZGVzKFwiJHtcIikpcmV0dXJuIGBcXGAke3R9XFxgYH1lbHNlIHJldHVybiBgXCIke3R9XCJgO3JldHVybiBgJyR7dH0nYDtjYXNlXCJudW1iZXJcIjpyZXR1cm4gaXNOYU4odCk/XCJOYU5cIjpPYmplY3QuaXModCwtMCk/U3RyaW5nKHQpOnQ7Y2FzZVwiYmlnaW50XCI6cmV0dXJuIGAke1N0cmluZyh0KX1uYDtjYXNlXCJib29sZWFuXCI6Y2FzZVwidW5kZWZpbmVkXCI6cmV0dXJuIFN0cmluZyh0KTtjYXNlXCJvYmplY3RcIjpyZXR1cm4gXCJ7fVwifX0sdHlwZXM6e2lzQXN5bmNGdW5jdGlvbih0KXtyZXR1cm4gdCBpbnN0YW5jZW9mIGl5fSxpc0FycmF5QnVmZmVyVmlldyh0KXtyZXR1cm4gQXJyYXlCdWZmZXIuaXNWaWV3KHQpfX0saXNCbG9iOm55fTttcy5leHBvcnRzLnByb21pc2lmeS5jdXN0b209U3ltYm9sLmZvcihcIm5vZGVqcy51dGlsLnByb21pc2lmeS5jdXN0b21cIik7fSk7dmFyIEhpPU0oKFlBLCRpKT0+e3YoKTttKCk7XygpO3ZhcntBYm9ydENvbnRyb2xsZXI6SnUsQWJvcnRTaWduYWw6c3l9PXR5cGVvZiBzZWxmPFwidVwiP3NlbGY6dHlwZW9mIHdpbmRvdzxcInVcIj93aW5kb3c6dm9pZCAwOyRpLmV4cG9ydHM9SnU7JGkuZXhwb3J0cy5BYm9ydFNpZ25hbD1zeTskaS5leHBvcnRzLmRlZmF1bHQ9SnU7fSk7dmFyIFNlPU0oKG9JLGVmKT0+e3YoKTttKCk7XygpO3Zhcntmb3JtYXQ6b3ksaW5zcGVjdDpWaSxBZ2dyZWdhdGVFcnJvcjpheX09SmUoKSxseT1nbG9iYWxUaGlzLkFnZ3JlZ2F0ZUVycm9yfHxheSx1eT1TeW1ib2woXCJrSXNOb2RlRXJyb3JcIiksZnk9W1wic3RyaW5nXCIsXCJmdW5jdGlvblwiLFwibnVtYmVyXCIsXCJvYmplY3RcIixcIkZ1bmN0aW9uXCIsXCJPYmplY3RcIixcImJvb2xlYW5cIixcImJpZ2ludFwiLFwic3ltYm9sXCJdLGN5PS9eKFtBLVpdW2EtejAtOV0qKSskLyxoeT1cIl9fbm9kZV9pbnRlcm5hbF9cIix6aT17fTtmdW5jdGlvbiBYdCh0LGUpe2lmKCF0KXRocm93IG5ldyB6aS5FUlJfSU5URVJOQUxfQVNTRVJUSU9OKGUpfWZ1bmN0aW9uIFh1KHQpe2xldCBlPVwiXCIscj10Lmxlbmd0aCxpPXRbMF09PT1cIi1cIj8xOjA7Zm9yKDtyPj1pKzQ7ci09MyllPWBfJHt0LnNsaWNlKHItMyxyKX0ke2V9YDtyZXR1cm4gYCR7dC5zbGljZSgwLHIpfSR7ZX1gfWZ1bmN0aW9uIGR5KHQsZSxyKXtpZih0eXBlb2YgZT09XCJmdW5jdGlvblwiKXJldHVybiBYdChlLmxlbmd0aDw9ci5sZW5ndGgsYENvZGU6ICR7dH07IFRoZSBwcm92aWRlZCBhcmd1bWVudHMgbGVuZ3RoICgke3IubGVuZ3RofSkgZG9lcyBub3QgbWF0Y2ggdGhlIHJlcXVpcmVkIG9uZXMgKCR7ZS5sZW5ndGh9KS5gKSxlKC4uLnIpO2xldCBpPShlLm1hdGNoKC8lW2RmaWpvT3NdL2cpfHxbXSkubGVuZ3RoO3JldHVybiBYdChpPT09ci5sZW5ndGgsYENvZGU6ICR7dH07IFRoZSBwcm92aWRlZCBhcmd1bWVudHMgbGVuZ3RoICgke3IubGVuZ3RofSkgZG9lcyBub3QgbWF0Y2ggdGhlIHJlcXVpcmVkIG9uZXMgKCR7aX0pLmApLHIubGVuZ3RoPT09MD9lOm95KGUsLi4ucil9ZnVuY3Rpb24gbWUodCxlLHIpe3J8fChyPUVycm9yKTtjbGFzcyBpIGV4dGVuZHMgcntjb25zdHJ1Y3RvciguLi5vKXtzdXBlcihkeSh0LGUsbykpO310b1N0cmluZygpe3JldHVybiBgJHt0aGlzLm5hbWV9IFske3R9XTogJHt0aGlzLm1lc3NhZ2V9YH19T2JqZWN0LmRlZmluZVByb3BlcnRpZXMoaS5wcm90b3R5cGUse25hbWU6e3ZhbHVlOnIubmFtZSx3cml0YWJsZTohMCxlbnVtZXJhYmxlOiExLGNvbmZpZ3VyYWJsZTohMH0sdG9TdHJpbmc6e3ZhbHVlKCl7cmV0dXJuIGAke3RoaXMubmFtZX0gWyR7dH1dOiAke3RoaXMubWVzc2FnZX1gfSx3cml0YWJsZTohMCxlbnVtZXJhYmxlOiExLGNvbmZpZ3VyYWJsZTohMH19KSxpLnByb3RvdHlwZS5jb2RlPXQsaS5wcm90b3R5cGVbdXldPSEwLHppW3RdPWk7fWZ1bmN0aW9uIFp1KHQpe2xldCBlPWh5K3QubmFtZTtyZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KHQsXCJuYW1lXCIse3ZhbHVlOmV9KSx0fWZ1bmN0aW9uIHB5KHQsZSl7aWYodCYmZSYmdCE9PWUpe2lmKEFycmF5LmlzQXJyYXkoZS5lcnJvcnMpKXJldHVybiBlLmVycm9ycy5wdXNoKHQpLGU7bGV0IHI9bmV3IGx5KFtlLHRdLGUubWVzc2FnZSk7cmV0dXJuIHIuY29kZT1lLmNvZGUscn1yZXR1cm4gdHx8ZX12YXIgdnM9Y2xhc3MgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihlPVwiVGhlIG9wZXJhdGlvbiB3YXMgYWJvcnRlZFwiLHI9dm9pZCAwKXtpZihyIT09dm9pZCAwJiZ0eXBlb2YgciE9XCJvYmplY3RcIil0aHJvdyBuZXcgemkuRVJSX0lOVkFMSURfQVJHX1RZUEUoXCJvcHRpb25zXCIsXCJPYmplY3RcIixyKTtzdXBlcihlLHIpLHRoaXMuY29kZT1cIkFCT1JUX0VSUlwiLHRoaXMubmFtZT1cIkFib3J0RXJyb3JcIjt9fTttZShcIkVSUl9BU1NFUlRJT05cIixcIiVzXCIsRXJyb3IpO21lKFwiRVJSX0lOVkFMSURfQVJHX1RZUEVcIiwodCxlLHIpPT57WHQodHlwZW9mIHQ9PVwic3RyaW5nXCIsXCInbmFtZScgbXVzdCBiZSBhIHN0cmluZ1wiKSxBcnJheS5pc0FycmF5KGUpfHwoZT1bZV0pO2xldCBpPVwiVGhlIFwiO3QuZW5kc1dpdGgoXCIgYXJndW1lbnRcIik/aSs9YCR7dH0gYDppKz1gXCIke3R9XCIgJHt0LmluY2x1ZGVzKFwiLlwiKT9cInByb3BlcnR5XCI6XCJhcmd1bWVudFwifSBgLGkrPVwibXVzdCBiZSBcIjtsZXQgbj1bXSxvPVtdLHM9W107Zm9yKGxldCB1IG9mIGUpWHQodHlwZW9mIHU9PVwic3RyaW5nXCIsXCJBbGwgZXhwZWN0ZWQgZW50cmllcyBoYXZlIHRvIGJlIG9mIHR5cGUgc3RyaW5nXCIpLGZ5LmluY2x1ZGVzKHUpP24ucHVzaCh1LnRvTG93ZXJDYXNlKCkpOmN5LnRlc3QodSk/by5wdXNoKHUpOihYdCh1IT09XCJvYmplY3RcIiwnVGhlIHZhbHVlIFwib2JqZWN0XCIgc2hvdWxkIGJlIHdyaXR0ZW4gYXMgXCJPYmplY3RcIicpLHMucHVzaCh1KSk7aWYoby5sZW5ndGg+MCl7bGV0IHU9bi5pbmRleE9mKFwib2JqZWN0XCIpO3UhPT0tMSYmKG4uc3BsaWNlKG4sdSwxKSxvLnB1c2goXCJPYmplY3RcIikpO31pZihuLmxlbmd0aD4wKXtzd2l0Y2gobi5sZW5ndGgpe2Nhc2UgMTppKz1gb2YgdHlwZSAke25bMF19YDticmVhaztjYXNlIDI6aSs9YG9uZSBvZiB0eXBlICR7blswXX0gb3IgJHtuWzFdfWA7YnJlYWs7ZGVmYXVsdDp7bGV0IHU9bi5wb3AoKTtpKz1gb25lIG9mIHR5cGUgJHtuLmpvaW4oXCIsIFwiKX0sIG9yICR7dX1gO319KG8ubGVuZ3RoPjB8fHMubGVuZ3RoPjApJiYoaSs9XCIgb3IgXCIpO31pZihvLmxlbmd0aD4wKXtzd2l0Y2goby5sZW5ndGgpe2Nhc2UgMTppKz1gYW4gaW5zdGFuY2Ugb2YgJHtvWzBdfWA7YnJlYWs7Y2FzZSAyOmkrPWBhbiBpbnN0YW5jZSBvZiAke29bMF19IG9yICR7b1sxXX1gO2JyZWFrO2RlZmF1bHQ6e2xldCB1PW8ucG9wKCk7aSs9YGFuIGluc3RhbmNlIG9mICR7by5qb2luKFwiLCBcIil9LCBvciAke3V9YDt9fXMubGVuZ3RoPjAmJihpKz1cIiBvciBcIik7fXN3aXRjaChzLmxlbmd0aCl7Y2FzZSAwOmJyZWFrO2Nhc2UgMTpzWzBdLnRvTG93ZXJDYXNlKCkhPT1zWzBdJiYoaSs9XCJhbiBcIiksaSs9YCR7c1swXX1gO2JyZWFrO2Nhc2UgMjppKz1gb25lIG9mICR7c1swXX0gb3IgJHtzWzFdfWA7YnJlYWs7ZGVmYXVsdDp7bGV0IHU9cy5wb3AoKTtpKz1gb25lIG9mICR7cy5qb2luKFwiLCBcIil9LCBvciAke3V9YDt9fWlmKHI9PW51bGwpaSs9YC4gUmVjZWl2ZWQgJHtyfWA7ZWxzZSBpZih0eXBlb2Ygcj09XCJmdW5jdGlvblwiJiZyLm5hbWUpaSs9YC4gUmVjZWl2ZWQgZnVuY3Rpb24gJHtyLm5hbWV9YDtlbHNlIGlmKHR5cGVvZiByPT1cIm9iamVjdFwiKXt2YXIgYTtpZigoYT1yLmNvbnN0cnVjdG9yKSE9PW51bGwmJmEhPT12b2lkIDAmJmEubmFtZSlpKz1gLiBSZWNlaXZlZCBhbiBpbnN0YW5jZSBvZiAke3IuY29uc3RydWN0b3IubmFtZX1gO2Vsc2Uge2xldCB1PVZpKHIse2RlcHRoOi0xfSk7aSs9YC4gUmVjZWl2ZWQgJHt1fWA7fX1lbHNlIHtsZXQgdT1WaShyLHtjb2xvcnM6ITF9KTt1Lmxlbmd0aD4yNSYmKHU9YCR7dS5zbGljZSgwLDI1KX0uLi5gKSxpKz1gLiBSZWNlaXZlZCB0eXBlICR7dHlwZW9mIHJ9ICgke3V9KWA7fXJldHVybiBpfSxUeXBlRXJyb3IpO21lKFwiRVJSX0lOVkFMSURfQVJHX1ZBTFVFXCIsKHQsZSxyPVwiaXMgaW52YWxpZFwiKT0+e2xldCBpPVZpKGUpO3JldHVybiBpLmxlbmd0aD4xMjgmJihpPWkuc2xpY2UoMCwxMjgpK1wiLi4uXCIpLGBUaGUgJHt0LmluY2x1ZGVzKFwiLlwiKT9cInByb3BlcnR5XCI6XCJhcmd1bWVudFwifSAnJHt0fScgJHtyfS4gUmVjZWl2ZWQgJHtpfWB9LFR5cGVFcnJvcik7bWUoXCJFUlJfSU5WQUxJRF9SRVRVUk5fVkFMVUVcIiwodCxlLHIpPT57dmFyIGk7bGV0IG49ciE9bnVsbCYmKGk9ci5jb25zdHJ1Y3RvcikhPT1udWxsJiZpIT09dm9pZCAwJiZpLm5hbWU/YGluc3RhbmNlIG9mICR7ci5jb25zdHJ1Y3Rvci5uYW1lfWA6YHR5cGUgJHt0eXBlb2Ygcn1gO3JldHVybiBgRXhwZWN0ZWQgJHt0fSB0byBiZSByZXR1cm5lZCBmcm9tIHRoZSBcIiR7ZX1cIiBmdW5jdGlvbiBidXQgZ290ICR7bn0uYH0sVHlwZUVycm9yKTttZShcIkVSUl9NSVNTSU5HX0FSR1NcIiwoLi4udCk9PntYdCh0Lmxlbmd0aD4wLFwiQXQgbGVhc3Qgb25lIGFyZyBuZWVkcyB0byBiZSBzcGVjaWZpZWRcIik7bGV0IGUscj10Lmxlbmd0aDtzd2l0Y2godD0oQXJyYXkuaXNBcnJheSh0KT90Olt0XSkubWFwKGk9PmBcIiR7aX1cImApLmpvaW4oXCIgb3IgXCIpLHIpe2Nhc2UgMTplKz1gVGhlICR7dFswXX0gYXJndW1lbnRgO2JyZWFrO2Nhc2UgMjplKz1gVGhlICR7dFswXX0gYW5kICR7dFsxXX0gYXJndW1lbnRzYDticmVhaztkZWZhdWx0OntsZXQgaT10LnBvcCgpO2UrPWBUaGUgJHt0LmpvaW4oXCIsIFwiKX0sIGFuZCAke2l9IGFyZ3VtZW50c2A7fWJyZWFrfXJldHVybiBgJHtlfSBtdXN0IGJlIHNwZWNpZmllZGB9LFR5cGVFcnJvcik7bWUoXCJFUlJfT1VUX09GX1JBTkdFXCIsKHQsZSxyKT0+e1h0KGUsJ01pc3NpbmcgXCJyYW5nZVwiIGFyZ3VtZW50Jyk7bGV0IGk7cmV0dXJuIE51bWJlci5pc0ludGVnZXIocikmJk1hdGguYWJzKHIpPjIqKjMyP2k9WHUoU3RyaW5nKHIpKTp0eXBlb2Ygcj09XCJiaWdpbnRcIj8oaT1TdHJpbmcociksKHI+Mm4qKjMybnx8cjwtKDJuKiozMm4pKSYmKGk9WHUoaSkpLGkrPVwiblwiKTppPVZpKHIpLGBUaGUgdmFsdWUgb2YgXCIke3R9XCIgaXMgb3V0IG9mIHJhbmdlLiBJdCBtdXN0IGJlICR7ZX0uIFJlY2VpdmVkICR7aX1gfSxSYW5nZUVycm9yKTttZShcIkVSUl9NVUxUSVBMRV9DQUxMQkFDS1wiLFwiQ2FsbGJhY2sgY2FsbGVkIG11bHRpcGxlIHRpbWVzXCIsRXJyb3IpO21lKFwiRVJSX01FVEhPRF9OT1RfSU1QTEVNRU5URURcIixcIlRoZSAlcyBtZXRob2QgaXMgbm90IGltcGxlbWVudGVkXCIsRXJyb3IpO21lKFwiRVJSX1NUUkVBTV9BTFJFQURZX0ZJTklTSEVEXCIsXCJDYW5ub3QgY2FsbCAlcyBhZnRlciBhIHN0cmVhbSB3YXMgZmluaXNoZWRcIixFcnJvcik7bWUoXCJFUlJfU1RSRUFNX0NBTk5PVF9QSVBFXCIsXCJDYW5ub3QgcGlwZSwgbm90IHJlYWRhYmxlXCIsRXJyb3IpO21lKFwiRVJSX1NUUkVBTV9ERVNUUk9ZRURcIixcIkNhbm5vdCBjYWxsICVzIGFmdGVyIGEgc3RyZWFtIHdhcyBkZXN0cm95ZWRcIixFcnJvcik7bWUoXCJFUlJfU1RSRUFNX05VTExfVkFMVUVTXCIsXCJNYXkgbm90IHdyaXRlIG51bGwgdmFsdWVzIHRvIHN0cmVhbVwiLFR5cGVFcnJvcik7bWUoXCJFUlJfU1RSRUFNX1BSRU1BVFVSRV9DTE9TRVwiLFwiUHJlbWF0dXJlIGNsb3NlXCIsRXJyb3IpO21lKFwiRVJSX1NUUkVBTV9QVVNIX0FGVEVSX0VPRlwiLFwic3RyZWFtLnB1c2goKSBhZnRlciBFT0ZcIixFcnJvcik7bWUoXCJFUlJfU1RSRUFNX1VOU0hJRlRfQUZURVJfRU5EX0VWRU5UXCIsXCJzdHJlYW0udW5zaGlmdCgpIGFmdGVyIGVuZCBldmVudFwiLEVycm9yKTttZShcIkVSUl9TVFJFQU1fV1JJVEVfQUZURVJfRU5EXCIsXCJ3cml0ZSBhZnRlciBlbmRcIixFcnJvcik7bWUoXCJFUlJfVU5LTk9XTl9FTkNPRElOR1wiLFwiVW5rbm93biBlbmNvZGluZzogJXNcIixUeXBlRXJyb3IpO2VmLmV4cG9ydHM9e0Fib3J0RXJyb3I6dnMsYWdncmVnYXRlVHdvRXJyb3JzOlp1KHB5KSxoaWRlU3RhY2tGcmFtZXM6WnUsY29kZXM6eml9O30pO3ZhciBmaT1NKCh5SSxmZik9Pnt2KCk7bSgpO18oKTt2YXJ7QXJyYXlJc0FycmF5OlNzLEFycmF5UHJvdG90eXBlSW5jbHVkZXM6c2YsQXJyYXlQcm90b3R5cGVKb2luOm9mLEFycmF5UHJvdG90eXBlTWFwOmd5LE51bWJlcklzSW50ZWdlcjpBcyxOdW1iZXJJc05hTjp5eSxOdW1iZXJNQVhfU0FGRV9JTlRFR0VSOmJ5LE51bWJlck1JTl9TQUZFX0lOVEVHRVI6d3ksTnVtYmVyUGFyc2VJbnQ6X3ksT2JqZWN0UHJvdG90eXBlSGFzT3duUHJvcGVydHk6bXksUmVnRXhwUHJvdG90eXBlRXhlYzphZixTdHJpbmc6dnksU3RyaW5nUHJvdG90eXBlVG9VcHBlckNhc2U6RXksU3RyaW5nUHJvdG90eXBlVHJpbTpTeX09Y2UoKSx7aGlkZVN0YWNrRnJhbWVzOlVlLGNvZGVzOntFUlJfU09DS0VUX0JBRF9QT1JUOkF5LEVSUl9JTlZBTElEX0FSR19UWVBFOkFlLEVSUl9JTlZBTElEX0FSR19WQUxVRTpNcixFUlJfT1VUX09GX1JBTkdFOlp0LEVSUl9VTktOT1dOX1NJR05BTDp0Zn19PVNlKCkse25vcm1hbGl6ZUVuY29kaW5nOkl5fT1KZSgpLHtpc0FzeW5jRnVuY3Rpb246VHksaXNBcnJheUJ1ZmZlclZpZXc6Unl9PUplKCkudHlwZXMscmY9e307ZnVuY3Rpb24gQ3kodCl7cmV0dXJuIHQ9PT0odHwwKX1mdW5jdGlvbiBCeSh0KXtyZXR1cm4gdD09PXQ+Pj4wfXZhciBQeT0vXlswLTddKyQvLE95PVwibXVzdCBiZSBhIDMyLWJpdCB1bnNpZ25lZCBpbnRlZ2VyIG9yIGFuIG9jdGFsIHN0cmluZ1wiO2Z1bmN0aW9uIGt5KHQsZSxyKXtpZih0eXBlb2YgdD5cInVcIiYmKHQ9ciksdHlwZW9mIHQ9PVwic3RyaW5nXCIpe2lmKGFmKFB5LHQpPT09bnVsbCl0aHJvdyBuZXcgTXIoZSx0LE95KTt0PV95KHQsOCk7fXJldHVybiBsZih0LGUpLHR9dmFyIHh5PVVlKCh0LGUscj13eSxpPWJ5KT0+e2lmKHR5cGVvZiB0IT1cIm51bWJlclwiKXRocm93IG5ldyBBZShlLFwibnVtYmVyXCIsdCk7aWYoIUFzKHQpKXRocm93IG5ldyBadChlLFwiYW4gaW50ZWdlclwiLHQpO2lmKHQ8cnx8dD5pKXRocm93IG5ldyBadChlLGA+PSAke3J9ICYmIDw9ICR7aX1gLHQpfSksTXk9VWUoKHQsZSxyPS0yMTQ3NDgzNjQ4LGk9MjE0NzQ4MzY0Nyk9PntpZih0eXBlb2YgdCE9XCJudW1iZXJcIil0aHJvdyBuZXcgQWUoZSxcIm51bWJlclwiLHQpO2lmKCFBcyh0KSl0aHJvdyBuZXcgWnQoZSxcImFuIGludGVnZXJcIix0KTtpZih0PHJ8fHQ+aSl0aHJvdyBuZXcgWnQoZSxgPj0gJHtyfSAmJiA8PSAke2l9YCx0KX0pLGxmPVVlKCh0LGUscj0hMSk9PntpZih0eXBlb2YgdCE9XCJudW1iZXJcIil0aHJvdyBuZXcgQWUoZSxcIm51bWJlclwiLHQpO2lmKCFBcyh0KSl0aHJvdyBuZXcgWnQoZSxcImFuIGludGVnZXJcIix0KTtsZXQgaT1yPzE6MCxuPTQyOTQ5NjcyOTU7aWYodDxpfHx0Pm4pdGhyb3cgbmV3IFp0KGUsYD49ICR7aX0gJiYgPD0gJHtufWAsdCl9KTtmdW5jdGlvbiBJcyh0LGUpe2lmKHR5cGVvZiB0IT1cInN0cmluZ1wiKXRocm93IG5ldyBBZShlLFwic3RyaW5nXCIsdCl9ZnVuY3Rpb24gTHkodCxlLHI9dm9pZCAwLGkpe2lmKHR5cGVvZiB0IT1cIm51bWJlclwiKXRocm93IG5ldyBBZShlLFwibnVtYmVyXCIsdCk7aWYociE9bnVsbCYmdDxyfHxpIT1udWxsJiZ0Pml8fChyIT1udWxsfHxpIT1udWxsKSYmeXkodCkpdGhyb3cgbmV3IFp0KGUsYCR7ciE9bnVsbD9gPj0gJHtyfWA6XCJcIn0ke3IhPW51bGwmJmkhPW51bGw/XCIgJiYgXCI6XCJcIn0ke2khPW51bGw/YDw9ICR7aX1gOlwiXCJ9YCx0KX12YXIgVXk9VWUoKHQsZSxyKT0+e2lmKCFzZihyLHQpKXtsZXQgbj1cIm11c3QgYmUgb25lIG9mOiBcIitvZihneShyLG89PnR5cGVvZiBvPT1cInN0cmluZ1wiP2AnJHtvfSdgOnZ5KG8pKSxcIiwgXCIpO3Rocm93IG5ldyBNcihlLHQsbil9fSk7ZnVuY3Rpb24gdWYodCxlKXtpZih0eXBlb2YgdCE9XCJib29sZWFuXCIpdGhyb3cgbmV3IEFlKGUsXCJib29sZWFuXCIsdCl9ZnVuY3Rpb24gRXModCxlLHIpe3JldHVybiB0PT1udWxsfHwhbXkodCxlKT9yOnRbZV19dmFyIE55PVVlKCh0LGUscj1udWxsKT0+e2xldCBpPUVzKHIsXCJhbGxvd0FycmF5XCIsITEpLG49RXMocixcImFsbG93RnVuY3Rpb25cIiwhMSk7aWYoIUVzKHIsXCJudWxsYWJsZVwiLCExKSYmdD09PW51bGx8fCFpJiZTcyh0KXx8dHlwZW9mIHQhPVwib2JqZWN0XCImJighbnx8dHlwZW9mIHQhPVwiZnVuY3Rpb25cIikpdGhyb3cgbmV3IEFlKGUsXCJPYmplY3RcIix0KX0pLHF5PVVlKCh0LGUpPT57aWYodCE9bnVsbCYmdHlwZW9mIHQhPVwib2JqZWN0XCImJnR5cGVvZiB0IT1cImZ1bmN0aW9uXCIpdGhyb3cgbmV3IEFlKGUsXCJhIGRpY3Rpb25hcnlcIix0KX0pLFRzPVVlKCh0LGUscj0wKT0+e2lmKCFTcyh0KSl0aHJvdyBuZXcgQWUoZSxcIkFycmF5XCIsdCk7aWYodC5sZW5ndGg8cil7bGV0IGk9YG11c3QgYmUgbG9uZ2VyIHRoYW4gJHtyfWA7dGhyb3cgbmV3IE1yKGUsdCxpKX19KTtmdW5jdGlvbiBEeSh0LGUpe1RzKHQsZSk7Zm9yKGxldCByPTA7cjx0Lmxlbmd0aDtyKyspSXModFtyXSxgJHtlfVske3J9XWApO31mdW5jdGlvbiBqeSh0LGUpe1RzKHQsZSk7Zm9yKGxldCByPTA7cjx0Lmxlbmd0aDtyKyspdWYodFtyXSxgJHtlfVske3J9XWApO31mdW5jdGlvbiBGeSh0LGU9XCJzaWduYWxcIil7aWYoSXModCxlKSxyZlt0XT09PXZvaWQgMCl0aHJvdyByZltFeSh0KV0hPT12b2lkIDA/bmV3IHRmKHQrXCIgKHNpZ25hbHMgbXVzdCB1c2UgYWxsIGNhcGl0YWwgbGV0dGVycylcIik6bmV3IHRmKHQpfXZhciBXeT1VZSgodCxlPVwiYnVmZmVyXCIpPT57aWYoIVJ5KHQpKXRocm93IG5ldyBBZShlLFtcIkJ1ZmZlclwiLFwiVHlwZWRBcnJheVwiLFwiRGF0YVZpZXdcIl0sdCl9KTtmdW5jdGlvbiAkeSh0LGUpe2xldCByPUl5KGUpLGk9dC5sZW5ndGg7aWYocj09PVwiaGV4XCImJmklMiE9PTApdGhyb3cgbmV3IE1yKFwiZW5jb2RpbmdcIixlLGBpcyBpbnZhbGlkIGZvciBkYXRhIG9mIGxlbmd0aCAke2l9YCl9ZnVuY3Rpb24gSHkodCxlPVwiUG9ydFwiLHI9ITApe2lmKHR5cGVvZiB0IT1cIm51bWJlclwiJiZ0eXBlb2YgdCE9XCJzdHJpbmdcInx8dHlwZW9mIHQ9PVwic3RyaW5nXCImJlN5KHQpLmxlbmd0aD09PTB8fCt0IT09K3Q+Pj4wfHx0PjY1NTM1fHx0PT09MCYmIXIpdGhyb3cgbmV3IEF5KGUsdCxyKTtyZXR1cm4gdHwwfXZhciBWeT1VZSgodCxlKT0+e2lmKHQhPT12b2lkIDAmJih0PT09bnVsbHx8dHlwZW9mIHQhPVwib2JqZWN0XCJ8fCEoXCJhYm9ydGVkXCJpbiB0KSkpdGhyb3cgbmV3IEFlKGUsXCJBYm9ydFNpZ25hbFwiLHQpfSksenk9VWUoKHQsZSk9PntpZih0eXBlb2YgdCE9XCJmdW5jdGlvblwiKXRocm93IG5ldyBBZShlLFwiRnVuY3Rpb25cIix0KX0pLEt5PVVlKCh0LGUpPT57aWYodHlwZW9mIHQhPVwiZnVuY3Rpb25cInx8VHkodCkpdGhyb3cgbmV3IEFlKGUsXCJGdW5jdGlvblwiLHQpfSksR3k9VWUoKHQsZSk9PntpZih0IT09dm9pZCAwKXRocm93IG5ldyBBZShlLFwidW5kZWZpbmVkXCIsdCl9KTtmdW5jdGlvbiBReSh0LGUscil7aWYoIXNmKHIsdCkpdGhyb3cgbmV3IEFlKGUsYCgnJHtvZihyLFwifFwiKX0nKWAsdCl9dmFyIFl5PS9eKD86PFtePl0qPikoPzpcXHMqO1xccypbXjtcIlxcc10rKD86PShcIik/W147XCJcXHNdKlxcMSk/KSokLztmdW5jdGlvbiBuZih0LGUpe2lmKHR5cGVvZiB0PlwidVwifHwhYWYoWXksdCkpdGhyb3cgbmV3IE1yKGUsdCwnbXVzdCBiZSBhbiBhcnJheSBvciBzdHJpbmcgb2YgZm9ybWF0IFwiPC9zdHlsZXMuY3NzPjsgcmVsPXByZWxvYWQ7IGFzPXN0eWxlXCInKX1mdW5jdGlvbiBKeSh0KXtpZih0eXBlb2YgdD09XCJzdHJpbmdcIilyZXR1cm4gbmYodCxcImhpbnRzXCIpLHQ7aWYoU3ModCkpe2xldCBlPXQubGVuZ3RoLHI9XCJcIjtpZihlPT09MClyZXR1cm4gcjtmb3IobGV0IGk9MDtpPGU7aSsrKXtsZXQgbj10W2ldO25mKG4sXCJoaW50c1wiKSxyKz1uLGkhPT1lLTEmJihyKz1cIiwgXCIpO31yZXR1cm4gcn10aHJvdyBuZXcgTXIoXCJoaW50c1wiLHQsJ211c3QgYmUgYW4gYXJyYXkgb3Igc3RyaW5nIG9mIGZvcm1hdCBcIjwvc3R5bGVzLmNzcz47IHJlbD1wcmVsb2FkOyBhcz1zdHlsZVwiJyl9ZmYuZXhwb3J0cz17aXNJbnQzMjpDeSxpc1VpbnQzMjpCeSxwYXJzZUZpbGVNb2RlOmt5LHZhbGlkYXRlQXJyYXk6VHMsdmFsaWRhdGVTdHJpbmdBcnJheTpEeSx2YWxpZGF0ZUJvb2xlYW5BcnJheTpqeSx2YWxpZGF0ZUJvb2xlYW46dWYsdmFsaWRhdGVCdWZmZXI6V3ksdmFsaWRhdGVEaWN0aW9uYXJ5OnF5LHZhbGlkYXRlRW5jb2Rpbmc6JHksdmFsaWRhdGVGdW5jdGlvbjp6eSx2YWxpZGF0ZUludDMyOk15LHZhbGlkYXRlSW50ZWdlcjp4eSx2YWxpZGF0ZU51bWJlcjpMeSx2YWxpZGF0ZU9iamVjdDpOeSx2YWxpZGF0ZU9uZU9mOlV5LHZhbGlkYXRlUGxhaW5GdW5jdGlvbjpLeSx2YWxpZGF0ZVBvcnQ6SHksdmFsaWRhdGVTaWduYWxOYW1lOkZ5LHZhbGlkYXRlU3RyaW5nOklzLHZhbGlkYXRlVWludDMyOmxmLHZhbGlkYXRlVW5kZWZpbmVkOkd5LHZhbGlkYXRlVW5pb246UXksdmFsaWRhdGVBYm9ydFNpZ25hbDpWeSx2YWxpZGF0ZUxpbmtIZWFkZXJWYWx1ZTpKeX07fSk7dmFyIFV0PU0oKFRJLHBmKT0+e3YoKTttKCk7XygpO3ZhciBhZT1wZi5leHBvcnRzPXt9LFhlLFplO2Z1bmN0aW9uIFJzKCl7dGhyb3cgbmV3IEVycm9yKFwic2V0VGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZFwiKX1mdW5jdGlvbiBDcygpe3Rocm93IG5ldyBFcnJvcihcImNsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZFwiKX0oZnVuY3Rpb24oKXt0cnl7dHlwZW9mIHNldFRpbWVvdXQ9PVwiZnVuY3Rpb25cIj9YZT1zZXRUaW1lb3V0OlhlPVJzO31jYXRjaHtYZT1Sczt9dHJ5e3R5cGVvZiBjbGVhclRpbWVvdXQ9PVwiZnVuY3Rpb25cIj9aZT1jbGVhclRpbWVvdXQ6WmU9Q3M7fWNhdGNoe1plPUNzO319KSgpO2Z1bmN0aW9uIGNmKHQpe2lmKFhlPT09c2V0VGltZW91dClyZXR1cm4gc2V0VGltZW91dCh0LDApO2lmKChYZT09PVJzfHwhWGUpJiZzZXRUaW1lb3V0KXJldHVybiBYZT1zZXRUaW1lb3V0LHNldFRpbWVvdXQodCwwKTt0cnl7cmV0dXJuIFhlKHQsMCl9Y2F0Y2h7dHJ5e3JldHVybiBYZS5jYWxsKG51bGwsdCwwKX1jYXRjaHtyZXR1cm4gWGUuY2FsbCh0aGlzLHQsMCl9fX1mdW5jdGlvbiBYeSh0KXtpZihaZT09PWNsZWFyVGltZW91dClyZXR1cm4gY2xlYXJUaW1lb3V0KHQpO2lmKChaZT09PUNzfHwhWmUpJiZjbGVhclRpbWVvdXQpcmV0dXJuIFplPWNsZWFyVGltZW91dCxjbGVhclRpbWVvdXQodCk7dHJ5e3JldHVybiBaZSh0KX1jYXRjaHt0cnl7cmV0dXJuIFplLmNhbGwobnVsbCx0KX1jYXRjaHtyZXR1cm4gWmUuY2FsbCh0aGlzLHQpfX19dmFyIHd0PVtdLExyPSExLGVyLEtpPS0xO2Z1bmN0aW9uIFp5KCl7IUxyfHwhZXJ8fChMcj0hMSxlci5sZW5ndGg/d3Q9ZXIuY29uY2F0KHd0KTpLaT0tMSx3dC5sZW5ndGgmJmhmKCkpO31mdW5jdGlvbiBoZigpe2lmKCFMcil7dmFyIHQ9Y2YoWnkpO0xyPSEwO2Zvcih2YXIgZT13dC5sZW5ndGg7ZTspe2Zvcihlcj13dCx3dD1bXTsrK0tpPGU7KWVyJiZlcltLaV0ucnVuKCk7S2k9LTEsZT13dC5sZW5ndGg7fWVyPW51bGwsTHI9ITEsWHkodCk7fX1hZS5uZXh0VGljaz1mdW5jdGlvbih0KXt2YXIgZT1uZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aC0xKTtpZihhcmd1bWVudHMubGVuZ3RoPjEpZm9yKHZhciByPTE7cjxhcmd1bWVudHMubGVuZ3RoO3IrKyllW3ItMV09YXJndW1lbnRzW3JdO3d0LnB1c2gobmV3IGRmKHQsZSkpLHd0Lmxlbmd0aD09PTEmJiFMciYmY2YoaGYpO307ZnVuY3Rpb24gZGYodCxlKXt0aGlzLmZ1bj10LHRoaXMuYXJyYXk9ZTt9ZGYucHJvdG90eXBlLnJ1bj1mdW5jdGlvbigpe3RoaXMuZnVuLmFwcGx5KG51bGwsdGhpcy5hcnJheSk7fTthZS50aXRsZT1cImJyb3dzZXJcIjthZS5icm93c2VyPSEwO2FlLmVudj17fTthZS5hcmd2PVtdO2FlLnZlcnNpb249XCJcIjthZS52ZXJzaW9ucz17fTtmdW5jdGlvbiBfdCgpe31hZS5vbj1fdDthZS5hZGRMaXN0ZW5lcj1fdDthZS5vbmNlPV90O2FlLm9mZj1fdDthZS5yZW1vdmVMaXN0ZW5lcj1fdDthZS5yZW1vdmVBbGxMaXN0ZW5lcnM9X3Q7YWUuZW1pdD1fdDthZS5wcmVwZW5kTGlzdGVuZXI9X3Q7YWUucHJlcGVuZE9uY2VMaXN0ZW5lcj1fdDthZS5saXN0ZW5lcnM9ZnVuY3Rpb24odCl7cmV0dXJuIFtdfTthZS5iaW5kaW5nPWZ1bmN0aW9uKHQpe3Rocm93IG5ldyBFcnJvcihcInByb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkXCIpfTthZS5jd2Q9ZnVuY3Rpb24oKXtyZXR1cm4gXCIvXCJ9O2FlLmNoZGlyPWZ1bmN0aW9uKHQpe3Rocm93IG5ldyBFcnJvcihcInByb2Nlc3MuY2hkaXIgaXMgbm90IHN1cHBvcnRlZFwiKX07YWUudW1hc2s9ZnVuY3Rpb24oKXtyZXR1cm4gMH07fSk7dmFyIHR0PU0oKFVJLFBmKT0+e3YoKTttKCk7XygpO3ZhcntTeW1ib2w6R2ksU3ltYm9sQXN5bmNJdGVyYXRvcjpnZixTeW1ib2xJdGVyYXRvcjp5ZixTeW1ib2xGb3I6YmZ9PWNlKCksd2Y9R2koXCJrRGVzdHJveWVkXCIpLF9mPUdpKFwia0lzRXJyb3JlZFwiKSxCcz1HaShcImtJc1JlYWRhYmxlXCIpLG1mPUdpKFwia0lzRGlzdHVyYmVkXCIpLGViPWJmKFwibm9kZWpzLndlYnN0cmVhbS5pc0Nsb3NlZFByb21pc2VcIiksdGI9YmYoXCJub2RlanMud2Vic3RyZWFtLmNvbnRyb2xsZXJFcnJvckZ1bmN0aW9uXCIpO2Z1bmN0aW9uIFFpKHQsZT0hMSl7dmFyIHI7cmV0dXJuICEhKHQmJnR5cGVvZiB0LnBpcGU9PVwiZnVuY3Rpb25cIiYmdHlwZW9mIHQub249PVwiZnVuY3Rpb25cIiYmKCFlfHx0eXBlb2YgdC5wYXVzZT09XCJmdW5jdGlvblwiJiZ0eXBlb2YgdC5yZXN1bWU9PVwiZnVuY3Rpb25cIikmJighdC5fd3JpdGFibGVTdGF0ZXx8KChyPXQuX3JlYWRhYmxlU3RhdGUpPT09bnVsbHx8cj09PXZvaWQgMD92b2lkIDA6ci5yZWFkYWJsZSkhPT0hMSkmJighdC5fd3JpdGFibGVTdGF0ZXx8dC5fcmVhZGFibGVTdGF0ZSkpfWZ1bmN0aW9uIFlpKHQpe3ZhciBlO3JldHVybiAhISh0JiZ0eXBlb2YgdC53cml0ZT09XCJmdW5jdGlvblwiJiZ0eXBlb2YgdC5vbj09XCJmdW5jdGlvblwiJiYoIXQuX3JlYWRhYmxlU3RhdGV8fCgoZT10Ll93cml0YWJsZVN0YXRlKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUud3JpdGFibGUpIT09ITEpKX1mdW5jdGlvbiByYih0KXtyZXR1cm4gISEodCYmdHlwZW9mIHQucGlwZT09XCJmdW5jdGlvblwiJiZ0Ll9yZWFkYWJsZVN0YXRlJiZ0eXBlb2YgdC5vbj09XCJmdW5jdGlvblwiJiZ0eXBlb2YgdC53cml0ZT09XCJmdW5jdGlvblwiKX1mdW5jdGlvbiBldCh0KXtyZXR1cm4gdCYmKHQuX3JlYWRhYmxlU3RhdGV8fHQuX3dyaXRhYmxlU3RhdGV8fHR5cGVvZiB0LndyaXRlPT1cImZ1bmN0aW9uXCImJnR5cGVvZiB0Lm9uPT1cImZ1bmN0aW9uXCJ8fHR5cGVvZiB0LnBpcGU9PVwiZnVuY3Rpb25cIiYmdHlwZW9mIHQub249PVwiZnVuY3Rpb25cIil9ZnVuY3Rpb24gdmYodCl7cmV0dXJuICEhKHQmJiFldCh0KSYmdHlwZW9mIHQucGlwZVRocm91Z2g9PVwiZnVuY3Rpb25cIiYmdHlwZW9mIHQuZ2V0UmVhZGVyPT1cImZ1bmN0aW9uXCImJnR5cGVvZiB0LmNhbmNlbD09XCJmdW5jdGlvblwiKX1mdW5jdGlvbiBFZih0KXtyZXR1cm4gISEodCYmIWV0KHQpJiZ0eXBlb2YgdC5nZXRXcml0ZXI9PVwiZnVuY3Rpb25cIiYmdHlwZW9mIHQuYWJvcnQ9PVwiZnVuY3Rpb25cIil9ZnVuY3Rpb24gU2YodCl7cmV0dXJuICEhKHQmJiFldCh0KSYmdHlwZW9mIHQucmVhZGFibGU9PVwib2JqZWN0XCImJnR5cGVvZiB0LndyaXRhYmxlPT1cIm9iamVjdFwiKX1mdW5jdGlvbiBpYih0KXtyZXR1cm4gdmYodCl8fEVmKHQpfHxTZih0KX1mdW5jdGlvbiBuYih0LGUpe3JldHVybiB0PT1udWxsPyExOmU9PT0hMD90eXBlb2YgdFtnZl09PVwiZnVuY3Rpb25cIjplPT09ITE/dHlwZW9mIHRbeWZdPT1cImZ1bmN0aW9uXCI6dHlwZW9mIHRbZ2ZdPT1cImZ1bmN0aW9uXCJ8fHR5cGVvZiB0W3lmXT09XCJmdW5jdGlvblwifWZ1bmN0aW9uIEppKHQpe2lmKCFldCh0KSlyZXR1cm4gbnVsbDtsZXQgZT10Ll93cml0YWJsZVN0YXRlLHI9dC5fcmVhZGFibGVTdGF0ZSxpPWV8fHI7cmV0dXJuICEhKHQuZGVzdHJveWVkfHx0W3dmXXx8aSE9bnVsbCYmaS5kZXN0cm95ZWQpfWZ1bmN0aW9uIEFmKHQpe2lmKCFZaSh0KSlyZXR1cm4gbnVsbDtpZih0LndyaXRhYmxlRW5kZWQ9PT0hMClyZXR1cm4gITA7bGV0IGU9dC5fd3JpdGFibGVTdGF0ZTtyZXR1cm4gZSE9bnVsbCYmZS5lcnJvcmVkPyExOnR5cGVvZiBlPy5lbmRlZCE9XCJib29sZWFuXCI/bnVsbDplLmVuZGVkfWZ1bmN0aW9uIHNiKHQsZSl7aWYoIVlpKHQpKXJldHVybiBudWxsO2lmKHQud3JpdGFibGVGaW5pc2hlZD09PSEwKXJldHVybiAhMDtsZXQgcj10Ll93cml0YWJsZVN0YXRlO3JldHVybiByIT1udWxsJiZyLmVycm9yZWQ/ITE6dHlwZW9mIHI/LmZpbmlzaGVkIT1cImJvb2xlYW5cIj9udWxsOiEhKHIuZmluaXNoZWR8fGU9PT0hMSYmci5lbmRlZD09PSEwJiZyLmxlbmd0aD09PTApfWZ1bmN0aW9uIG9iKHQpe2lmKCFRaSh0KSlyZXR1cm4gbnVsbDtpZih0LnJlYWRhYmxlRW5kZWQ9PT0hMClyZXR1cm4gITA7bGV0IGU9dC5fcmVhZGFibGVTdGF0ZTtyZXR1cm4gIWV8fGUuZXJyb3JlZD8hMTp0eXBlb2YgZT8uZW5kZWQhPVwiYm9vbGVhblwiP251bGw6ZS5lbmRlZH1mdW5jdGlvbiBJZih0LGUpe2lmKCFRaSh0KSlyZXR1cm4gbnVsbDtsZXQgcj10Ll9yZWFkYWJsZVN0YXRlO3JldHVybiByIT1udWxsJiZyLmVycm9yZWQ/ITE6dHlwZW9mIHI/LmVuZEVtaXR0ZWQhPVwiYm9vbGVhblwiP251bGw6ISEoci5lbmRFbWl0dGVkfHxlPT09ITEmJnIuZW5kZWQ9PT0hMCYmci5sZW5ndGg9PT0wKX1mdW5jdGlvbiBUZih0KXtyZXR1cm4gdCYmdFtCc10hPW51bGw/dFtCc106dHlwZW9mIHQ/LnJlYWRhYmxlIT1cImJvb2xlYW5cIj9udWxsOkppKHQpPyExOlFpKHQpJiZ0LnJlYWRhYmxlJiYhSWYodCl9ZnVuY3Rpb24gUmYodCl7cmV0dXJuIHR5cGVvZiB0Py53cml0YWJsZSE9XCJib29sZWFuXCI/bnVsbDpKaSh0KT8hMTpZaSh0KSYmdC53cml0YWJsZSYmIUFmKHQpfWZ1bmN0aW9uIGFiKHQsZSl7cmV0dXJuIGV0KHQpP0ppKHQpPyEwOiEoZT8ucmVhZGFibGUhPT0hMSYmVGYodCl8fGU/LndyaXRhYmxlIT09ITEmJlJmKHQpKTpudWxsfWZ1bmN0aW9uIGxiKHQpe3ZhciBlLHI7cmV0dXJuIGV0KHQpP3Qud3JpdGFibGVFcnJvcmVkP3Qud3JpdGFibGVFcnJvcmVkOihlPShyPXQuX3dyaXRhYmxlU3RhdGUpPT09bnVsbHx8cj09PXZvaWQgMD92b2lkIDA6ci5lcnJvcmVkKSE9PW51bGwmJmUhPT12b2lkIDA/ZTpudWxsOm51bGx9ZnVuY3Rpb24gdWIodCl7dmFyIGUscjtyZXR1cm4gZXQodCk/dC5yZWFkYWJsZUVycm9yZWQ/dC5yZWFkYWJsZUVycm9yZWQ6KGU9KHI9dC5fcmVhZGFibGVTdGF0ZSk9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmVycm9yZWQpIT09bnVsbCYmZSE9PXZvaWQgMD9lOm51bGw6bnVsbH1mdW5jdGlvbiBmYih0KXtpZighZXQodCkpcmV0dXJuIG51bGw7aWYodHlwZW9mIHQuY2xvc2VkPT1cImJvb2xlYW5cIilyZXR1cm4gdC5jbG9zZWQ7bGV0IGU9dC5fd3JpdGFibGVTdGF0ZSxyPXQuX3JlYWRhYmxlU3RhdGU7cmV0dXJuIHR5cGVvZiBlPy5jbG9zZWQ9PVwiYm9vbGVhblwifHx0eXBlb2Ygcj8uY2xvc2VkPT1cImJvb2xlYW5cIj9lPy5jbG9zZWR8fHI/LmNsb3NlZDp0eXBlb2YgdC5fY2xvc2VkPT1cImJvb2xlYW5cIiYmQ2YodCk/dC5fY2xvc2VkOm51bGx9ZnVuY3Rpb24gQ2YodCl7cmV0dXJuIHR5cGVvZiB0Ll9jbG9zZWQ9PVwiYm9vbGVhblwiJiZ0eXBlb2YgdC5fZGVmYXVsdEtlZXBBbGl2ZT09XCJib29sZWFuXCImJnR5cGVvZiB0Ll9yZW1vdmVkQ29ubmVjdGlvbj09XCJib29sZWFuXCImJnR5cGVvZiB0Ll9yZW1vdmVkQ29udExlbj09XCJib29sZWFuXCJ9ZnVuY3Rpb24gQmYodCl7cmV0dXJuIHR5cGVvZiB0Ll9zZW50MTAwPT1cImJvb2xlYW5cIiYmQ2YodCl9ZnVuY3Rpb24gY2IodCl7dmFyIGU7cmV0dXJuIHR5cGVvZiB0Ll9jb25zdW1pbmc9PVwiYm9vbGVhblwiJiZ0eXBlb2YgdC5fZHVtcGVkPT1cImJvb2xlYW5cIiYmKChlPXQucmVxKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUudXBncmFkZU9yQ29ubmVjdCk9PT12b2lkIDB9ZnVuY3Rpb24gaGIodCl7aWYoIWV0KHQpKXJldHVybiBudWxsO2xldCBlPXQuX3dyaXRhYmxlU3RhdGUscj10Ll9yZWFkYWJsZVN0YXRlLGk9ZXx8cjtyZXR1cm4gIWkmJkJmKHQpfHwhIShpJiZpLmF1dG9EZXN0cm95JiZpLmVtaXRDbG9zZSYmaS5jbG9zZWQ9PT0hMSl9ZnVuY3Rpb24gZGIodCl7dmFyIGU7cmV0dXJuICEhKHQmJigoZT10W21mXSkhPT1udWxsJiZlIT09dm9pZCAwP2U6dC5yZWFkYWJsZURpZFJlYWR8fHQucmVhZGFibGVBYm9ydGVkKSl9ZnVuY3Rpb24gcGIodCl7dmFyIGUscixpLG4sbyxzLGEsdSxjLGg7cmV0dXJuICEhKHQmJigoZT0ocj0oaT0obj0obz0ocz10W19mXSkhPT1udWxsJiZzIT09dm9pZCAwP3M6dC5yZWFkYWJsZUVycm9yZWQpIT09bnVsbCYmbyE9PXZvaWQgMD9vOnQud3JpdGFibGVFcnJvcmVkKSE9PW51bGwmJm4hPT12b2lkIDA/bjooYT10Ll9yZWFkYWJsZVN0YXRlKT09PW51bGx8fGE9PT12b2lkIDA/dm9pZCAwOmEuZXJyb3JFbWl0dGVkKSE9PW51bGwmJmkhPT12b2lkIDA/aToodT10Ll93cml0YWJsZVN0YXRlKT09PW51bGx8fHU9PT12b2lkIDA/dm9pZCAwOnUuZXJyb3JFbWl0dGVkKSE9PW51bGwmJnIhPT12b2lkIDA/cjooYz10Ll9yZWFkYWJsZVN0YXRlKT09PW51bGx8fGM9PT12b2lkIDA/dm9pZCAwOmMuZXJyb3JlZCkhPT1udWxsJiZlIT09dm9pZCAwP2U6ISgoaD10Ll93cml0YWJsZVN0YXRlKT09PW51bGx8fGg9PT12b2lkIDApJiZoLmVycm9yZWQpKX1QZi5leHBvcnRzPXtrRGVzdHJveWVkOndmLGlzRGlzdHVyYmVkOmRiLGtJc0Rpc3R1cmJlZDptZixpc0Vycm9yZWQ6cGIsa0lzRXJyb3JlZDpfZixpc1JlYWRhYmxlOlRmLGtJc1JlYWRhYmxlOkJzLGtJc0Nsb3NlZFByb21pc2U6ZWIsa0NvbnRyb2xsZXJFcnJvckZ1bmN0aW9uOnRiLGlzQ2xvc2VkOmZiLGlzRGVzdHJveWVkOkppLGlzRHVwbGV4Tm9kZVN0cmVhbTpyYixpc0ZpbmlzaGVkOmFiLGlzSXRlcmFibGU6bmIsaXNSZWFkYWJsZU5vZGVTdHJlYW06UWksaXNSZWFkYWJsZVN0cmVhbTp2Zixpc1JlYWRhYmxlRW5kZWQ6b2IsaXNSZWFkYWJsZUZpbmlzaGVkOklmLGlzUmVhZGFibGVFcnJvcmVkOnViLGlzTm9kZVN0cmVhbTpldCxpc1dlYlN0cmVhbTppYixpc1dyaXRhYmxlOlJmLGlzV3JpdGFibGVOb2RlU3RyZWFtOllpLGlzV3JpdGFibGVTdHJlYW06RWYsaXNXcml0YWJsZUVuZGVkOkFmLGlzV3JpdGFibGVGaW5pc2hlZDpzYixpc1dyaXRhYmxlRXJyb3JlZDpsYixpc1NlcnZlclJlcXVlc3Q6Y2IsaXNTZXJ2ZXJSZXNwb25zZTpCZix3aWxsRW1pdENsb3NlOmhiLGlzVHJhbnNmb3JtU3RyZWFtOlNmfTt9KTt2YXIgbXQ9TSgoekksTXMpPT57digpO20oKTtfKCk7dmFyIE50PVV0KCkse0Fib3J0RXJyb3I6RGYsY29kZXM6Z2J9PVNlKCkse0VSUl9JTlZBTElEX0FSR19UWVBFOnliLEVSUl9TVFJFQU1fUFJFTUFUVVJFX0NMT1NFOk9mfT1nYix7a0VtcHR5T2JqZWN0Ok9zLG9uY2U6a3N9PUplKCkse3ZhbGlkYXRlQWJvcnRTaWduYWw6YmIsdmFsaWRhdGVGdW5jdGlvbjp3Yix2YWxpZGF0ZU9iamVjdDpfYix2YWxpZGF0ZUJvb2xlYW46bWJ9PWZpKCkse1Byb21pc2U6dmIsUHJvbWlzZVByb3RvdHlwZVRoZW46RWJ9PWNlKCkse2lzQ2xvc2VkOlNiLGlzUmVhZGFibGU6a2YsaXNSZWFkYWJsZU5vZGVTdHJlYW06UHMsaXNSZWFkYWJsZVN0cmVhbTpBYixpc1JlYWRhYmxlRmluaXNoZWQ6eGYsaXNSZWFkYWJsZUVycm9yZWQ6TWYsaXNXcml0YWJsZTpMZixpc1dyaXRhYmxlTm9kZVN0cmVhbTpVZixpc1dyaXRhYmxlU3RyZWFtOkliLGlzV3JpdGFibGVGaW5pc2hlZDpOZixpc1dyaXRhYmxlRXJyb3JlZDpxZixpc05vZGVTdHJlYW06VGIsd2lsbEVtaXRDbG9zZTpSYixrSXNDbG9zZWRQcm9taXNlOkNifT10dCgpO2Z1bmN0aW9uIEJiKHQpe3JldHVybiB0LnNldEhlYWRlciYmdHlwZW9mIHQuYWJvcnQ9PVwiZnVuY3Rpb25cIn12YXIgeHM9KCk9Pnt9O2Z1bmN0aW9uIGpmKHQsZSxyKXt2YXIgaSxuO2lmKGFyZ3VtZW50cy5sZW5ndGg9PT0yPyhyPWUsZT1Pcyk6ZT09bnVsbD9lPU9zOl9iKGUsXCJvcHRpb25zXCIpLHdiKHIsXCJjYWxsYmFja1wiKSxiYihlLnNpZ25hbCxcIm9wdGlvbnMuc2lnbmFsXCIpLHI9a3MociksQWIodCl8fEliKHQpKXJldHVybiBQYih0LGUscik7aWYoIVRiKHQpKXRocm93IG5ldyB5YihcInN0cmVhbVwiLFtcIlJlYWRhYmxlU3RyZWFtXCIsXCJXcml0YWJsZVN0cmVhbVwiLFwiU3RyZWFtXCJdLHQpO2xldCBvPShpPWUucmVhZGFibGUpIT09bnVsbCYmaSE9PXZvaWQgMD9pOlBzKHQpLHM9KG49ZS53cml0YWJsZSkhPT1udWxsJiZuIT09dm9pZCAwP246VWYodCksYT10Ll93cml0YWJsZVN0YXRlLHU9dC5fcmVhZGFibGVTdGF0ZSxjPSgpPT57dC53cml0YWJsZXx8ZygpO30saD1SYih0KSYmUHModCk9PT1vJiZVZih0KT09PXMsZD1OZih0LCExKSxnPSgpPT57ZD0hMCx0LmRlc3Ryb3llZCYmKGg9ITEpLCEoaCYmKCF0LnJlYWRhYmxlfHxvKSkmJighb3x8eSkmJnIuY2FsbCh0KTt9LHk9eGYodCwhMSksdz0oKT0+e3k9ITAsdC5kZXN0cm95ZWQmJihoPSExKSwhKGgmJighdC53cml0YWJsZXx8cykpJiYoIXN8fGQpJiZyLmNhbGwodCk7fSxFPU49PntyLmNhbGwodCxOKTt9LFM9U2IodCksST0oKT0+e1M9ITA7bGV0IE49cWYodCl8fE1mKHQpO2lmKE4mJnR5cGVvZiBOIT1cImJvb2xlYW5cIilyZXR1cm4gci5jYWxsKHQsTik7aWYobyYmIXkmJlBzKHQsITApJiYheGYodCwhMSkpcmV0dXJuIHIuY2FsbCh0LG5ldyBPZik7aWYocyYmIWQmJiFOZih0LCExKSlyZXR1cm4gci5jYWxsKHQsbmV3IE9mKTtyLmNhbGwodCk7fSxDPSgpPT57Uz0hMDtsZXQgTj1xZih0KXx8TWYodCk7aWYoTiYmdHlwZW9mIE4hPVwiYm9vbGVhblwiKXJldHVybiByLmNhbGwodCxOKTtyLmNhbGwodCk7fSxSPSgpPT57dC5yZXEub24oXCJmaW5pc2hcIixnKTt9O0JiKHQpPyh0Lm9uKFwiY29tcGxldGVcIixnKSxofHx0Lm9uKFwiYWJvcnRcIixJKSx0LnJlcT9SKCk6dC5vbihcInJlcXVlc3RcIixSKSk6cyYmIWEmJih0Lm9uKFwiZW5kXCIsYyksdC5vbihcImNsb3NlXCIsYykpLCFoJiZ0eXBlb2YgdC5hYm9ydGVkPT1cImJvb2xlYW5cIiYmdC5vbihcImFib3J0ZWRcIixJKSx0Lm9uKFwiZW5kXCIsdyksdC5vbihcImZpbmlzaFwiLGcpLGUuZXJyb3IhPT0hMSYmdC5vbihcImVycm9yXCIsRSksdC5vbihcImNsb3NlXCIsSSksUz9OdC5uZXh0VGljayhJKTphIT1udWxsJiZhLmVycm9yRW1pdHRlZHx8dSE9bnVsbCYmdS5lcnJvckVtaXR0ZWQ/aHx8TnQubmV4dFRpY2soQyk6KCFvJiYoIWh8fGtmKHQpKSYmKGR8fExmKHQpPT09ITEpfHwhcyYmKCFofHxMZih0KSkmJih5fHxrZih0KT09PSExKXx8dSYmdC5yZXEmJnQuYWJvcnRlZCkmJk50Lm5leHRUaWNrKEMpO2xldCBVPSgpPT57cj14cyx0LnJlbW92ZUxpc3RlbmVyKFwiYWJvcnRlZFwiLEkpLHQucmVtb3ZlTGlzdGVuZXIoXCJjb21wbGV0ZVwiLGcpLHQucmVtb3ZlTGlzdGVuZXIoXCJhYm9ydFwiLEkpLHQucmVtb3ZlTGlzdGVuZXIoXCJyZXF1ZXN0XCIsUiksdC5yZXEmJnQucmVxLnJlbW92ZUxpc3RlbmVyKFwiZmluaXNoXCIsZyksdC5yZW1vdmVMaXN0ZW5lcihcImVuZFwiLGMpLHQucmVtb3ZlTGlzdGVuZXIoXCJjbG9zZVwiLGMpLHQucmVtb3ZlTGlzdGVuZXIoXCJmaW5pc2hcIixnKSx0LnJlbW92ZUxpc3RlbmVyKFwiZW5kXCIsdyksdC5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsRSksdC5yZW1vdmVMaXN0ZW5lcihcImNsb3NlXCIsSSk7fTtpZihlLnNpZ25hbCYmIVMpe2xldCBOPSgpPT57bGV0IFc9cjtVKCksVy5jYWxsKHQsbmV3IERmKHZvaWQgMCx7Y2F1c2U6ZS5zaWduYWwucmVhc29ufSkpO307aWYoZS5zaWduYWwuYWJvcnRlZClOdC5uZXh0VGljayhOKTtlbHNlIHtsZXQgVz1yO3I9a3MoKC4uLkspPT57ZS5zaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsTiksVy5hcHBseSh0LEspO30pLGUuc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLE4pO319cmV0dXJuIFV9ZnVuY3Rpb24gUGIodCxlLHIpe2xldCBpPSExLG49eHM7aWYoZS5zaWduYWwpaWYobj0oKT0+e2k9ITAsci5jYWxsKHQsbmV3IERmKHZvaWQgMCx7Y2F1c2U6ZS5zaWduYWwucmVhc29ufSkpO30sZS5zaWduYWwuYWJvcnRlZClOdC5uZXh0VGljayhuKTtlbHNlIHtsZXQgcz1yO3I9a3MoKC4uLmEpPT57ZS5zaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsbikscy5hcHBseSh0LGEpO30pLGUuc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLG4pO31sZXQgbz0oLi4ucyk9PntpfHxOdC5uZXh0VGljaygoKT0+ci5hcHBseSh0LHMpKTt9O3JldHVybiBFYih0W0NiXS5wcm9taXNlLG8sbykseHN9ZnVuY3Rpb24gT2IodCxlKXt2YXIgcjtsZXQgaT0hMTtyZXR1cm4gZT09PW51bGwmJihlPU9zKSwocj1lKSE9PW51bGwmJnIhPT12b2lkIDAmJnIuY2xlYW51cCYmKG1iKGUuY2xlYW51cCxcImNsZWFudXBcIiksaT1lLmNsZWFudXApLG5ldyB2YigobixvKT0+e2xldCBzPWpmKHQsZSxhPT57aSYmcygpLGE/byhhKTpuKCk7fSk7fSl9TXMuZXhwb3J0cz1qZjtNcy5leHBvcnRzLmZpbmlzaGVkPU9iO30pO3ZhciB0cj1NKChyVCxHZik9Pnt2KCk7bSgpO18oKTt2YXIgcnQ9VXQoKSx7YWdncmVnYXRlVHdvRXJyb3JzOmtiLGNvZGVzOntFUlJfTVVMVElQTEVfQ0FMTEJBQ0s6eGJ9LEFib3J0RXJyb3I6TWJ9PVNlKCkse1N5bWJvbDokZn09Y2UoKSx7a0Rlc3Ryb3llZDpMYixpc0Rlc3Ryb3llZDpVYixpc0ZpbmlzaGVkOk5iLGlzU2VydmVyUmVxdWVzdDpxYn09dHQoKSxIZj0kZihcImtEZXN0cm95XCIpLExzPSRmKFwia0NvbnN0cnVjdFwiKTtmdW5jdGlvbiBWZih0LGUscil7dCYmKHQuc3RhY2ssZSYmIWUuZXJyb3JlZCYmKGUuZXJyb3JlZD10KSxyJiYhci5lcnJvcmVkJiYoci5lcnJvcmVkPXQpKTt9ZnVuY3Rpb24gRGIodCxlKXtsZXQgcj10aGlzLl9yZWFkYWJsZVN0YXRlLGk9dGhpcy5fd3JpdGFibGVTdGF0ZSxuPWl8fHI7cmV0dXJuIGkhPW51bGwmJmkuZGVzdHJveWVkfHxyIT1udWxsJiZyLmRlc3Ryb3llZD8odHlwZW9mIGU9PVwiZnVuY3Rpb25cIiYmZSgpLHRoaXMpOihWZih0LGksciksaSYmKGkuZGVzdHJveWVkPSEwKSxyJiYoci5kZXN0cm95ZWQ9ITApLG4uY29uc3RydWN0ZWQ/RmYodGhpcyx0LGUpOnRoaXMub25jZShIZixmdW5jdGlvbihvKXtGZih0aGlzLGtiKG8sdCksZSk7fSksdGhpcyl9ZnVuY3Rpb24gRmYodCxlLHIpe2xldCBpPSExO2Z1bmN0aW9uIG4obyl7aWYoaSlyZXR1cm47aT0hMDtsZXQgcz10Ll9yZWFkYWJsZVN0YXRlLGE9dC5fd3JpdGFibGVTdGF0ZTtWZihvLGEscyksYSYmKGEuY2xvc2VkPSEwKSxzJiYocy5jbG9zZWQ9ITApLHR5cGVvZiByPT1cImZ1bmN0aW9uXCImJnIobyksbz9ydC5uZXh0VGljayhqYix0LG8pOnJ0Lm5leHRUaWNrKHpmLHQpO310cnl7dC5fZGVzdHJveShlfHxudWxsLG4pO31jYXRjaChvKXtuKG8pO319ZnVuY3Rpb24gamIodCxlKXtVcyh0LGUpLHpmKHQpO31mdW5jdGlvbiB6Zih0KXtsZXQgZT10Ll9yZWFkYWJsZVN0YXRlLHI9dC5fd3JpdGFibGVTdGF0ZTtyJiYoci5jbG9zZUVtaXR0ZWQ9ITApLGUmJihlLmNsb3NlRW1pdHRlZD0hMCksKHIhPW51bGwmJnIuZW1pdENsb3NlfHxlIT1udWxsJiZlLmVtaXRDbG9zZSkmJnQuZW1pdChcImNsb3NlXCIpO31mdW5jdGlvbiBVcyh0LGUpe2xldCByPXQuX3JlYWRhYmxlU3RhdGUsaT10Ll93cml0YWJsZVN0YXRlO2khPW51bGwmJmkuZXJyb3JFbWl0dGVkfHxyIT1udWxsJiZyLmVycm9yRW1pdHRlZHx8KGkmJihpLmVycm9yRW1pdHRlZD0hMCksciYmKHIuZXJyb3JFbWl0dGVkPSEwKSx0LmVtaXQoXCJlcnJvclwiLGUpKTt9ZnVuY3Rpb24gRmIoKXtsZXQgdD10aGlzLl9yZWFkYWJsZVN0YXRlLGU9dGhpcy5fd3JpdGFibGVTdGF0ZTt0JiYodC5jb25zdHJ1Y3RlZD0hMCx0LmNsb3NlZD0hMSx0LmNsb3NlRW1pdHRlZD0hMSx0LmRlc3Ryb3llZD0hMSx0LmVycm9yZWQ9bnVsbCx0LmVycm9yRW1pdHRlZD0hMSx0LnJlYWRpbmc9ITEsdC5lbmRlZD10LnJlYWRhYmxlPT09ITEsdC5lbmRFbWl0dGVkPXQucmVhZGFibGU9PT0hMSksZSYmKGUuY29uc3RydWN0ZWQ9ITAsZS5kZXN0cm95ZWQ9ITEsZS5jbG9zZWQ9ITEsZS5jbG9zZUVtaXR0ZWQ9ITEsZS5lcnJvcmVkPW51bGwsZS5lcnJvckVtaXR0ZWQ9ITEsZS5maW5hbENhbGxlZD0hMSxlLnByZWZpbmlzaGVkPSExLGUuZW5kZWQ9ZS53cml0YWJsZT09PSExLGUuZW5kaW5nPWUud3JpdGFibGU9PT0hMSxlLmZpbmlzaGVkPWUud3JpdGFibGU9PT0hMSk7fWZ1bmN0aW9uIE5zKHQsZSxyKXtsZXQgaT10Ll9yZWFkYWJsZVN0YXRlLG49dC5fd3JpdGFibGVTdGF0ZTtpZihuIT1udWxsJiZuLmRlc3Ryb3llZHx8aSE9bnVsbCYmaS5kZXN0cm95ZWQpcmV0dXJuIHRoaXM7aSE9bnVsbCYmaS5hdXRvRGVzdHJveXx8biE9bnVsbCYmbi5hdXRvRGVzdHJveT90LmRlc3Ryb3koZSk6ZSYmKGUuc3RhY2ssbiYmIW4uZXJyb3JlZCYmKG4uZXJyb3JlZD1lKSxpJiYhaS5lcnJvcmVkJiYoaS5lcnJvcmVkPWUpLHI/cnQubmV4dFRpY2soVXMsdCxlKTpVcyh0LGUpKTt9ZnVuY3Rpb24gV2IodCxlKXtpZih0eXBlb2YgdC5fY29uc3RydWN0IT1cImZ1bmN0aW9uXCIpcmV0dXJuO2xldCByPXQuX3JlYWRhYmxlU3RhdGUsaT10Ll93cml0YWJsZVN0YXRlO3ImJihyLmNvbnN0cnVjdGVkPSExKSxpJiYoaS5jb25zdHJ1Y3RlZD0hMSksdC5vbmNlKExzLGUpLCEodC5saXN0ZW5lckNvdW50KExzKT4xKSYmcnQubmV4dFRpY2soJGIsdCk7fWZ1bmN0aW9uICRiKHQpe2xldCBlPSExO2Z1bmN0aW9uIHIoaSl7aWYoZSl7TnModCxpPz9uZXcgeGIpO3JldHVybn1lPSEwO2xldCBuPXQuX3JlYWRhYmxlU3RhdGUsbz10Ll93cml0YWJsZVN0YXRlLHM9b3x8bjtuJiYobi5jb25zdHJ1Y3RlZD0hMCksbyYmKG8uY29uc3RydWN0ZWQ9ITApLHMuZGVzdHJveWVkP3QuZW1pdChIZixpKTppP05zKHQsaSwhMCk6cnQubmV4dFRpY2soSGIsdCk7fXRyeXt0Ll9jb25zdHJ1Y3QoaT0+e3J0Lm5leHRUaWNrKHIsaSk7fSk7fWNhdGNoKGkpe3J0Lm5leHRUaWNrKHIsaSk7fX1mdW5jdGlvbiBIYih0KXt0LmVtaXQoTHMpO31mdW5jdGlvbiBXZih0KXtyZXR1cm4gdD8uc2V0SGVhZGVyJiZ0eXBlb2YgdC5hYm9ydD09XCJmdW5jdGlvblwifWZ1bmN0aW9uIEtmKHQpe3QuZW1pdChcImNsb3NlXCIpO31mdW5jdGlvbiBWYih0LGUpe3QuZW1pdChcImVycm9yXCIsZSkscnQubmV4dFRpY2soS2YsdCk7fWZ1bmN0aW9uIHpiKHQsZSl7IXR8fFViKHQpfHwoIWUmJiFOYih0KSYmKGU9bmV3IE1iKSxxYih0KT8odC5zb2NrZXQ9bnVsbCx0LmRlc3Ryb3koZSkpOldmKHQpP3QuYWJvcnQoKTpXZih0LnJlcSk/dC5yZXEuYWJvcnQoKTp0eXBlb2YgdC5kZXN0cm95PT1cImZ1bmN0aW9uXCI/dC5kZXN0cm95KGUpOnR5cGVvZiB0LmNsb3NlPT1cImZ1bmN0aW9uXCI/dC5jbG9zZSgpOmU/cnQubmV4dFRpY2soVmIsdCxlKTpydC5uZXh0VGljayhLZix0KSx0LmRlc3Ryb3llZHx8KHRbTGJdPSEwKSk7fUdmLmV4cG9ydHM9e2NvbnN0cnVjdDpXYixkZXN0cm95ZXI6emIsZGVzdHJveTpEYix1bmRlc3Ryb3k6RmIsZXJyb3JPckRlc3Ryb3k6TnN9O30pO2Z1bmN0aW9uIFkoKXtZLmluaXQuY2FsbCh0aGlzKTt9ZnVuY3Rpb24gWGkodCl7aWYodHlwZW9mIHQhPVwiZnVuY3Rpb25cIil0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgb2YgdHlwZSBGdW5jdGlvbi4gUmVjZWl2ZWQgdHlwZSAnK3R5cGVvZiB0KX1mdW5jdGlvbiBuYyh0KXtyZXR1cm4gdC5fbWF4TGlzdGVuZXJzPT09dm9pZCAwP1kuZGVmYXVsdE1heExpc3RlbmVyczp0Ll9tYXhMaXN0ZW5lcnN9ZnVuY3Rpb24gWGYodCxlLHIsaSl7dmFyIG4sbyxzLGE7aWYoWGkociksKG89dC5fZXZlbnRzKT09PXZvaWQgMD8obz10Ll9ldmVudHM9T2JqZWN0LmNyZWF0ZShudWxsKSx0Ll9ldmVudHNDb3VudD0wKTooby5uZXdMaXN0ZW5lciE9PXZvaWQgMCYmKHQuZW1pdChcIm5ld0xpc3RlbmVyXCIsZSxyLmxpc3RlbmVyP3IubGlzdGVuZXI6ciksbz10Ll9ldmVudHMpLHM9b1tlXSkscz09PXZvaWQgMClzPW9bZV09ciwrK3QuX2V2ZW50c0NvdW50O2Vsc2UgaWYodHlwZW9mIHM9PVwiZnVuY3Rpb25cIj9zPW9bZV09aT9bcixzXTpbcyxyXTppP3MudW5zaGlmdChyKTpzLnB1c2gociksKG49bmModCkpPjAmJnMubGVuZ3RoPm4mJiFzLndhcm5lZCl7cy53YXJuZWQ9ITA7dmFyIHU9bmV3IEVycm9yKFwiUG9zc2libGUgRXZlbnRFbWl0dGVyIG1lbW9yeSBsZWFrIGRldGVjdGVkLiBcIitzLmxlbmd0aCtcIiBcIitTdHJpbmcoZSkrXCIgbGlzdGVuZXJzIGFkZGVkLiBVc2UgZW1pdHRlci5zZXRNYXhMaXN0ZW5lcnMoKSB0byBpbmNyZWFzZSBsaW1pdFwiKTt1Lm5hbWU9XCJNYXhMaXN0ZW5lcnNFeGNlZWRlZFdhcm5pbmdcIix1LmVtaXR0ZXI9dCx1LnR5cGU9ZSx1LmNvdW50PXMubGVuZ3RoLGE9dSxjb25zb2xlJiZjb25zb2xlLndhcm4mJmNvbnNvbGUud2FybihhKTt9cmV0dXJuIHR9ZnVuY3Rpb24gS2IoKXtpZighdGhpcy5maXJlZClyZXR1cm4gdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLHRoaXMud3JhcEZuKSx0aGlzLmZpcmVkPSEwLGFyZ3VtZW50cy5sZW5ndGg9PT0wP3RoaXMubGlzdGVuZXIuY2FsbCh0aGlzLnRhcmdldCk6dGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCxhcmd1bWVudHMpfWZ1bmN0aW9uIFpmKHQsZSxyKXt2YXIgaT17ZmlyZWQ6ITEsd3JhcEZuOnZvaWQgMCx0YXJnZXQ6dCx0eXBlOmUsbGlzdGVuZXI6cn0sbj1LYi5iaW5kKGkpO3JldHVybiBuLmxpc3RlbmVyPXIsaS53cmFwRm49bixufWZ1bmN0aW9uIGVjKHQsZSxyKXt2YXIgaT10Ll9ldmVudHM7aWYoaT09PXZvaWQgMClyZXR1cm4gW107dmFyIG49aVtlXTtyZXR1cm4gbj09PXZvaWQgMD9bXTp0eXBlb2Ygbj09XCJmdW5jdGlvblwiP3I/W24ubGlzdGVuZXJ8fG5dOltuXTpyP2Z1bmN0aW9uKG8pe2Zvcih2YXIgcz1uZXcgQXJyYXkoby5sZW5ndGgpLGE9MDthPHMubGVuZ3RoOysrYSlzW2FdPW9bYV0ubGlzdGVuZXJ8fG9bYV07cmV0dXJuIHN9KG4pOnNjKG4sbi5sZW5ndGgpfWZ1bmN0aW9uIHRjKHQpe3ZhciBlPXRoaXMuX2V2ZW50cztpZihlIT09dm9pZCAwKXt2YXIgcj1lW3RdO2lmKHR5cGVvZiByPT1cImZ1bmN0aW9uXCIpcmV0dXJuIDE7aWYociE9PXZvaWQgMClyZXR1cm4gci5sZW5ndGh9cmV0dXJuIDB9ZnVuY3Rpb24gc2ModCxlKXtmb3IodmFyIHI9bmV3IEFycmF5KGUpLGk9MDtpPGU7KytpKXJbaV09dFtpXTtyZXR1cm4gcn12YXIgcmMsaWMsVXIsUWYsWWYsSmYsQmUscXM9d2UoKCk9Pnt2KCk7bSgpO18oKTtVcj10eXBlb2YgUmVmbGVjdD09XCJvYmplY3RcIj9SZWZsZWN0Om51bGwsUWY9VXImJnR5cGVvZiBVci5hcHBseT09XCJmdW5jdGlvblwiP1VyLmFwcGx5OmZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gRnVuY3Rpb24ucHJvdG90eXBlLmFwcGx5LmNhbGwodCxlLHIpfTtpYz1VciYmdHlwZW9mIFVyLm93bktleXM9PVwiZnVuY3Rpb25cIj9Vci5vd25LZXlzOk9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHM/ZnVuY3Rpb24odCl7cmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHQpLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHQpKX06ZnVuY3Rpb24odCl7cmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHQpfTtZZj1OdW1iZXIuaXNOYU58fGZ1bmN0aW9uKHQpe3JldHVybiB0IT10fTtyYz1ZLFkuRXZlbnRFbWl0dGVyPVksWS5wcm90b3R5cGUuX2V2ZW50cz12b2lkIDAsWS5wcm90b3R5cGUuX2V2ZW50c0NvdW50PTAsWS5wcm90b3R5cGUuX21heExpc3RlbmVycz12b2lkIDA7SmY9MTA7T2JqZWN0LmRlZmluZVByb3BlcnR5KFksXCJkZWZhdWx0TWF4TGlzdGVuZXJzXCIse2VudW1lcmFibGU6ITAsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIEpmfSxzZXQ6ZnVuY3Rpb24odCl7aWYodHlwZW9mIHQhPVwibnVtYmVyXCJ8fHQ8MHx8WWYodCkpdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RoZSB2YWx1ZSBvZiBcImRlZmF1bHRNYXhMaXN0ZW5lcnNcIiBpcyBvdXQgb2YgcmFuZ2UuIEl0IG11c3QgYmUgYSBub24tbmVnYXRpdmUgbnVtYmVyLiBSZWNlaXZlZCAnK3QrXCIuXCIpO0pmPXQ7fX0pLFkuaW5pdD1mdW5jdGlvbigpe3RoaXMuX2V2ZW50cyE9PXZvaWQgMCYmdGhpcy5fZXZlbnRzIT09T2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMpLl9ldmVudHN8fCh0aGlzLl9ldmVudHM9T2JqZWN0LmNyZWF0ZShudWxsKSx0aGlzLl9ldmVudHNDb3VudD0wKSx0aGlzLl9tYXhMaXN0ZW5lcnM9dGhpcy5fbWF4TGlzdGVuZXJzfHx2b2lkIDA7fSxZLnByb3RvdHlwZS5zZXRNYXhMaXN0ZW5lcnM9ZnVuY3Rpb24odCl7aWYodHlwZW9mIHQhPVwibnVtYmVyXCJ8fHQ8MHx8WWYodCkpdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RoZSB2YWx1ZSBvZiBcIm5cIiBpcyBvdXQgb2YgcmFuZ2UuIEl0IG11c3QgYmUgYSBub24tbmVnYXRpdmUgbnVtYmVyLiBSZWNlaXZlZCAnK3QrXCIuXCIpO3JldHVybiB0aGlzLl9tYXhMaXN0ZW5lcnM9dCx0aGlzfSxZLnByb3RvdHlwZS5nZXRNYXhMaXN0ZW5lcnM9ZnVuY3Rpb24oKXtyZXR1cm4gbmModGhpcyl9LFkucHJvdG90eXBlLmVtaXQ9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPVtdLHI9MTtyPGFyZ3VtZW50cy5sZW5ndGg7cisrKWUucHVzaChhcmd1bWVudHNbcl0pO3ZhciBpPXQ9PT1cImVycm9yXCIsbj10aGlzLl9ldmVudHM7aWYobiE9PXZvaWQgMClpPWkmJm4uZXJyb3I9PT12b2lkIDA7ZWxzZSBpZighaSlyZXR1cm4gITE7aWYoaSl7dmFyIG87aWYoZS5sZW5ndGg+MCYmKG89ZVswXSksbyBpbnN0YW5jZW9mIEVycm9yKXRocm93IG87dmFyIHM9bmV3IEVycm9yKFwiVW5oYW5kbGVkIGVycm9yLlwiKyhvP1wiIChcIitvLm1lc3NhZ2UrXCIpXCI6XCJcIikpO3Rocm93IHMuY29udGV4dD1vLHN9dmFyIGE9blt0XTtpZihhPT09dm9pZCAwKXJldHVybiAhMTtpZih0eXBlb2YgYT09XCJmdW5jdGlvblwiKVFmKGEsdGhpcyxlKTtlbHNlIHt2YXIgdT1hLmxlbmd0aCxjPXNjKGEsdSk7Zm9yKHI9MDtyPHU7KytyKVFmKGNbcl0sdGhpcyxlKTt9cmV0dXJuICEwfSxZLnByb3RvdHlwZS5hZGRMaXN0ZW5lcj1mdW5jdGlvbih0LGUpe3JldHVybiBYZih0aGlzLHQsZSwhMSl9LFkucHJvdG90eXBlLm9uPVkucHJvdG90eXBlLmFkZExpc3RlbmVyLFkucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lcj1mdW5jdGlvbih0LGUpe3JldHVybiBYZih0aGlzLHQsZSwhMCl9LFkucHJvdG90eXBlLm9uY2U9ZnVuY3Rpb24odCxlKXtyZXR1cm4gWGkoZSksdGhpcy5vbih0LFpmKHRoaXMsdCxlKSksdGhpc30sWS5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lcj1mdW5jdGlvbih0LGUpe3JldHVybiBYaShlKSx0aGlzLnByZXBlbmRMaXN0ZW5lcih0LFpmKHRoaXMsdCxlKSksdGhpc30sWS5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXI9ZnVuY3Rpb24odCxlKXt2YXIgcixpLG4sbyxzO2lmKFhpKGUpLChpPXRoaXMuX2V2ZW50cyk9PT12b2lkIDApcmV0dXJuIHRoaXM7aWYoKHI9aVt0XSk9PT12b2lkIDApcmV0dXJuIHRoaXM7aWYocj09PWV8fHIubGlzdGVuZXI9PT1lKS0tdGhpcy5fZXZlbnRzQ291bnQ9PTA/dGhpcy5fZXZlbnRzPU9iamVjdC5jcmVhdGUobnVsbCk6KGRlbGV0ZSBpW3RdLGkucmVtb3ZlTGlzdGVuZXImJnRoaXMuZW1pdChcInJlbW92ZUxpc3RlbmVyXCIsdCxyLmxpc3RlbmVyfHxlKSk7ZWxzZSBpZih0eXBlb2YgciE9XCJmdW5jdGlvblwiKXtmb3Iobj0tMSxvPXIubGVuZ3RoLTE7bz49MDtvLS0paWYocltvXT09PWV8fHJbb10ubGlzdGVuZXI9PT1lKXtzPXJbb10ubGlzdGVuZXIsbj1vO2JyZWFrfWlmKG48MClyZXR1cm4gdGhpcztuPT09MD9yLnNoaWZ0KCk6ZnVuY3Rpb24oYSx1KXtmb3IoO3UrMTxhLmxlbmd0aDt1KyspYVt1XT1hW3UrMV07YS5wb3AoKTt9KHIsbiksci5sZW5ndGg9PT0xJiYoaVt0XT1yWzBdKSxpLnJlbW92ZUxpc3RlbmVyIT09dm9pZCAwJiZ0aGlzLmVtaXQoXCJyZW1vdmVMaXN0ZW5lclwiLHQsc3x8ZSk7fXJldHVybiB0aGlzfSxZLnByb3RvdHlwZS5vZmY9WS5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIsWS5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzPWZ1bmN0aW9uKHQpe3ZhciBlLHIsaTtpZigocj10aGlzLl9ldmVudHMpPT09dm9pZCAwKXJldHVybiB0aGlzO2lmKHIucmVtb3ZlTGlzdGVuZXI9PT12b2lkIDApcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGg9PT0wPyh0aGlzLl9ldmVudHM9T2JqZWN0LmNyZWF0ZShudWxsKSx0aGlzLl9ldmVudHNDb3VudD0wKTpyW3RdIT09dm9pZCAwJiYoLS10aGlzLl9ldmVudHNDb3VudD09MD90aGlzLl9ldmVudHM9T2JqZWN0LmNyZWF0ZShudWxsKTpkZWxldGUgclt0XSksdGhpcztpZihhcmd1bWVudHMubGVuZ3RoPT09MCl7dmFyIG4sbz1PYmplY3Qua2V5cyhyKTtmb3IoaT0wO2k8by5sZW5ndGg7KytpKShuPW9baV0pIT09XCJyZW1vdmVMaXN0ZW5lclwiJiZ0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhuKTtyZXR1cm4gdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoXCJyZW1vdmVMaXN0ZW5lclwiKSx0aGlzLl9ldmVudHM9T2JqZWN0LmNyZWF0ZShudWxsKSx0aGlzLl9ldmVudHNDb3VudD0wLHRoaXN9aWYodHlwZW9mKGU9clt0XSk9PVwiZnVuY3Rpb25cIil0aGlzLnJlbW92ZUxpc3RlbmVyKHQsZSk7ZWxzZSBpZihlIT09dm9pZCAwKWZvcihpPWUubGVuZ3RoLTE7aT49MDtpLS0pdGhpcy5yZW1vdmVMaXN0ZW5lcih0LGVbaV0pO3JldHVybiB0aGlzfSxZLnByb3RvdHlwZS5saXN0ZW5lcnM9ZnVuY3Rpb24odCl7cmV0dXJuIGVjKHRoaXMsdCwhMCl9LFkucHJvdG90eXBlLnJhd0xpc3RlbmVycz1mdW5jdGlvbih0KXtyZXR1cm4gZWModGhpcyx0LCExKX0sWS5saXN0ZW5lckNvdW50PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHR5cGVvZiB0Lmxpc3RlbmVyQ291bnQ9PVwiZnVuY3Rpb25cIj90Lmxpc3RlbmVyQ291bnQoZSk6dGMuY2FsbCh0LGUpfSxZLnByb3RvdHlwZS5saXN0ZW5lckNvdW50PXRjLFkucHJvdG90eXBlLmV2ZW50TmFtZXM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQ+MD9pYyh0aGlzLl9ldmVudHMpOltdfTtCZT1yYztCZS5FdmVudEVtaXR0ZXI7QmUuZGVmYXVsdE1heExpc3RlbmVycztCZS5pbml0O0JlLmxpc3RlbmVyQ291bnQ7QmUuRXZlbnRFbWl0dGVyO0JlLmRlZmF1bHRNYXhMaXN0ZW5lcnM7QmUuaW5pdDtCZS5saXN0ZW5lckNvdW50O30pO3ZhciBycj17fTtRdChycix7RXZlbnRFbWl0dGVyOigpPT5HYixkZWZhdWx0OigpPT5CZSxkZWZhdWx0TWF4TGlzdGVuZXJzOigpPT5RYixpbml0OigpPT5ZYixsaXN0ZW5lckNvdW50OigpPT5KYixvbjooKT0+WGIsb25jZTooKT0+WmJ9KTt2YXIgR2IsUWIsWWIsSmIsWGIsWmIsaXI9d2UoKCk9Pnt2KCk7bSgpO18oKTtxcygpO3FzKCk7QmUub25jZT1mdW5jdGlvbih0LGUpe3JldHVybiBuZXcgUHJvbWlzZSgocixpKT0+e2Z1bmN0aW9uIG4oLi4ucyl7byE9PXZvaWQgMCYmdC5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsbykscihzKTt9bGV0IG87ZSE9PVwiZXJyb3JcIiYmKG89cz0+e3QucmVtb3ZlTGlzdGVuZXIobmFtZSxuKSxpKHMpO30sdC5vbmNlKFwiZXJyb3JcIixvKSksdC5vbmNlKGUsbik7fSl9O0JlLm9uPWZ1bmN0aW9uKHQsZSl7bGV0IHI9W10saT1bXSxuPW51bGwsbz0hMSxzPXthc3luYyBuZXh0KCl7bGV0IGM9ci5zaGlmdCgpO2lmKGMpcmV0dXJuIGNyZWF0ZUl0ZXJSZXN1bHQoYywhMSk7aWYobil7bGV0IGg9UHJvbWlzZS5yZWplY3Qobik7cmV0dXJuIG49bnVsbCxofXJldHVybiBvP2NyZWF0ZUl0ZXJSZXN1bHQodm9pZCAwLCEwKTpuZXcgUHJvbWlzZSgoaCxkKT0+aS5wdXNoKHtyZXNvbHZlOmgscmVqZWN0OmR9KSl9LGFzeW5jIHJldHVybigpe3QucmVtb3ZlTGlzdGVuZXIoZSxhKSx0LnJlbW92ZUxpc3RlbmVyKFwiZXJyb3JcIix1KSxvPSEwO2ZvcihsZXQgYyBvZiBpKWMucmVzb2x2ZShjcmVhdGVJdGVyUmVzdWx0KHZvaWQgMCwhMCkpO3JldHVybiBjcmVhdGVJdGVyUmVzdWx0KHZvaWQgMCwhMCl9LHRocm93KGMpe249Yyx0LnJlbW92ZUxpc3RlbmVyKGUsYSksdC5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsdSk7fSxbU3ltYm9sLmFzeW5jSXRlcmF0b3JdKCl7cmV0dXJuIHRoaXN9fTtyZXR1cm4gdC5vbihlLGEpLHQub24oXCJlcnJvclwiLHUpLHM7ZnVuY3Rpb24gYSguLi5jKXtsZXQgaD1pLnNoaWZ0KCk7aD9oLnJlc29sdmUoY3JlYXRlSXRlclJlc3VsdChjLCExKSk6ci5wdXNoKGMpO31mdW5jdGlvbiB1KGMpe289ITA7bGV0IGg9aS5zaGlmdCgpO2g/aC5yZWplY3QoYyk6bj1jLHMucmV0dXJuKCk7fX07KHtFdmVudEVtaXR0ZXI6R2IsZGVmYXVsdE1heExpc3RlbmVyczpRYixpbml0OlliLGxpc3RlbmVyQ291bnQ6SmIsb246WGIsb25jZTpaYn09QmUpO30pO3ZhciB0bj1NKCh4VCxhYyk9Pnt2KCk7bSgpO18oKTt2YXJ7QXJyYXlJc0FycmF5OmV3LE9iamVjdFNldFByb3RvdHlwZU9mOm9jfT1jZSgpLHtFdmVudEVtaXR0ZXI6Wml9PShpcigpLFgocnIpKTtmdW5jdGlvbiBlbih0KXtaaS5jYWxsKHRoaXMsdCk7fW9jKGVuLnByb3RvdHlwZSxaaS5wcm90b3R5cGUpO29jKGVuLFppKTtlbi5wcm90b3R5cGUucGlwZT1mdW5jdGlvbih0LGUpe2xldCByPXRoaXM7ZnVuY3Rpb24gaShoKXt0LndyaXRhYmxlJiZ0LndyaXRlKGgpPT09ITEmJnIucGF1c2UmJnIucGF1c2UoKTt9ci5vbihcImRhdGFcIixpKTtmdW5jdGlvbiBuKCl7ci5yZWFkYWJsZSYmci5yZXN1bWUmJnIucmVzdW1lKCk7fXQub24oXCJkcmFpblwiLG4pLCF0Ll9pc1N0ZGlvJiYoIWV8fGUuZW5kIT09ITEpJiYoci5vbihcImVuZFwiLHMpLHIub24oXCJjbG9zZVwiLGEpKTtsZXQgbz0hMTtmdW5jdGlvbiBzKCl7b3x8KG89ITAsdC5lbmQoKSk7fWZ1bmN0aW9uIGEoKXtvfHwobz0hMCx0eXBlb2YgdC5kZXN0cm95PT1cImZ1bmN0aW9uXCImJnQuZGVzdHJveSgpKTt9ZnVuY3Rpb24gdShoKXtjKCksWmkubGlzdGVuZXJDb3VudCh0aGlzLFwiZXJyb3JcIik9PT0wJiZ0aGlzLmVtaXQoXCJlcnJvclwiLGgpO31EcyhyLFwiZXJyb3JcIix1KSxEcyh0LFwiZXJyb3JcIix1KTtmdW5jdGlvbiBjKCl7ci5yZW1vdmVMaXN0ZW5lcihcImRhdGFcIixpKSx0LnJlbW92ZUxpc3RlbmVyKFwiZHJhaW5cIixuKSxyLnJlbW92ZUxpc3RlbmVyKFwiZW5kXCIscyksci5yZW1vdmVMaXN0ZW5lcihcImNsb3NlXCIsYSksci5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsdSksdC5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsdSksci5yZW1vdmVMaXN0ZW5lcihcImVuZFwiLGMpLHIucmVtb3ZlTGlzdGVuZXIoXCJjbG9zZVwiLGMpLHQucmVtb3ZlTGlzdGVuZXIoXCJjbG9zZVwiLGMpO31yZXR1cm4gci5vbihcImVuZFwiLGMpLHIub24oXCJjbG9zZVwiLGMpLHQub24oXCJjbG9zZVwiLGMpLHQuZW1pdChcInBpcGVcIixyKSx0fTtmdW5jdGlvbiBEcyh0LGUscil7aWYodHlwZW9mIHQucHJlcGVuZExpc3RlbmVyPT1cImZ1bmN0aW9uXCIpcmV0dXJuIHQucHJlcGVuZExpc3RlbmVyKGUscik7IXQuX2V2ZW50c3x8IXQuX2V2ZW50c1tlXT90Lm9uKGUscik6ZXcodC5fZXZlbnRzW2VdKT90Ll9ldmVudHNbZV0udW5zaGlmdChyKTp0Ll9ldmVudHNbZV09W3IsdC5fZXZlbnRzW2VdXTt9YWMuZXhwb3J0cz17U3RyZWFtOmVuLHByZXBlbmRMaXN0ZW5lcjpEc307fSk7dmFyIGNpPU0oKCRULHJuKT0+e3YoKTttKCk7XygpO3ZhcntBYm9ydEVycm9yOmxjLGNvZGVzOnR3fT1TZSgpLHtpc05vZGVTdHJlYW06dWMsaXNXZWJTdHJlYW06cncsa0NvbnRyb2xsZXJFcnJvckZ1bmN0aW9uOml3fT10dCgpLG53PW10KCkse0VSUl9JTlZBTElEX0FSR19UWVBFOmZjfT10dyxzdz0odCxlKT0+e2lmKHR5cGVvZiB0IT1cIm9iamVjdFwifHwhKFwiYWJvcnRlZFwiaW4gdCkpdGhyb3cgbmV3IGZjKGUsXCJBYm9ydFNpZ25hbFwiLHQpfTtybi5leHBvcnRzLmFkZEFib3J0U2lnbmFsPWZ1bmN0aW9uKGUscil7aWYoc3coZSxcInNpZ25hbFwiKSwhdWMocikmJiFydyhyKSl0aHJvdyBuZXcgZmMoXCJzdHJlYW1cIixbXCJSZWFkYWJsZVN0cmVhbVwiLFwiV3JpdGFibGVTdHJlYW1cIixcIlN0cmVhbVwiXSxyKTtyZXR1cm4gcm4uZXhwb3J0cy5hZGRBYm9ydFNpZ25hbE5vVmFsaWRhdGUoZSxyKX07cm4uZXhwb3J0cy5hZGRBYm9ydFNpZ25hbE5vVmFsaWRhdGU9ZnVuY3Rpb24odCxlKXtpZih0eXBlb2YgdCE9XCJvYmplY3RcInx8IShcImFib3J0ZWRcImluIHQpKXJldHVybiBlO2xldCByPXVjKGUpPygpPT57ZS5kZXN0cm95KG5ldyBsYyh2b2lkIDAse2NhdXNlOnQucmVhc29ufSkpO306KCk9PntlW2l3XShuZXcgbGModm9pZCAwLHtjYXVzZTp0LnJlYXNvbn0pKTt9O3JldHVybiB0LmFib3J0ZWQ/cigpOih0LmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLHIpLG53KGUsKCk9PnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIscikpKSxlfTt9KTt2YXIgZGM9TSgoZTIsaGMpPT57digpO20oKTtfKCk7dmFye1N0cmluZ1Byb3RvdHlwZVNsaWNlOmNjLFN5bWJvbEl0ZXJhdG9yOm93LFR5cGVkQXJyYXlQcm90b3R5cGVTZXQ6bm4sVWludDhBcnJheTphd309Y2UoKSx7QnVmZmVyOmpzfT0oeWUoKSxYKF9lKSkse2luc3BlY3Q6bHd9PUplKCk7aGMuZXhwb3J0cz1jbGFzc3tjb25zdHJ1Y3Rvcigpe3RoaXMuaGVhZD1udWxsLHRoaXMudGFpbD1udWxsLHRoaXMubGVuZ3RoPTA7fXB1c2goZSl7bGV0IHI9e2RhdGE6ZSxuZXh0Om51bGx9O3RoaXMubGVuZ3RoPjA/dGhpcy50YWlsLm5leHQ9cjp0aGlzLmhlYWQ9cix0aGlzLnRhaWw9ciwrK3RoaXMubGVuZ3RoO311bnNoaWZ0KGUpe2xldCByPXtkYXRhOmUsbmV4dDp0aGlzLmhlYWR9O3RoaXMubGVuZ3RoPT09MCYmKHRoaXMudGFpbD1yKSx0aGlzLmhlYWQ9ciwrK3RoaXMubGVuZ3RoO31zaGlmdCgpe2lmKHRoaXMubGVuZ3RoPT09MClyZXR1cm47bGV0IGU9dGhpcy5oZWFkLmRhdGE7cmV0dXJuIHRoaXMubGVuZ3RoPT09MT90aGlzLmhlYWQ9dGhpcy50YWlsPW51bGw6dGhpcy5oZWFkPXRoaXMuaGVhZC5uZXh0LC0tdGhpcy5sZW5ndGgsZX1jbGVhcigpe3RoaXMuaGVhZD10aGlzLnRhaWw9bnVsbCx0aGlzLmxlbmd0aD0wO31qb2luKGUpe2lmKHRoaXMubGVuZ3RoPT09MClyZXR1cm4gXCJcIjtsZXQgcj10aGlzLmhlYWQsaT1cIlwiK3IuZGF0YTtmb3IoOyhyPXIubmV4dCkhPT1udWxsOylpKz1lK3IuZGF0YTtyZXR1cm4gaX1jb25jYXQoZSl7aWYodGhpcy5sZW5ndGg9PT0wKXJldHVybiBqcy5hbGxvYygwKTtsZXQgcj1qcy5hbGxvY1Vuc2FmZShlPj4+MCksaT10aGlzLmhlYWQsbj0wO2Zvcig7aTspbm4ocixpLmRhdGEsbiksbis9aS5kYXRhLmxlbmd0aCxpPWkubmV4dDtyZXR1cm4gcn1jb25zdW1lKGUscil7bGV0IGk9dGhpcy5oZWFkLmRhdGE7aWYoZTxpLmxlbmd0aCl7bGV0IG49aS5zbGljZSgwLGUpO3JldHVybiB0aGlzLmhlYWQuZGF0YT1pLnNsaWNlKGUpLG59cmV0dXJuIGU9PT1pLmxlbmd0aD90aGlzLnNoaWZ0KCk6cj90aGlzLl9nZXRTdHJpbmcoZSk6dGhpcy5fZ2V0QnVmZmVyKGUpfWZpcnN0KCl7cmV0dXJuIHRoaXMuaGVhZC5kYXRhfSpbb3ddKCl7Zm9yKGxldCBlPXRoaXMuaGVhZDtlO2U9ZS5uZXh0KXlpZWxkIGUuZGF0YTt9X2dldFN0cmluZyhlKXtsZXQgcj1cIlwiLGk9dGhpcy5oZWFkLG49MDtkb3tsZXQgbz1pLmRhdGE7aWYoZT5vLmxlbmd0aClyKz1vLGUtPW8ubGVuZ3RoO2Vsc2Uge2U9PT1vLmxlbmd0aD8ocis9bywrK24saS5uZXh0P3RoaXMuaGVhZD1pLm5leHQ6dGhpcy5oZWFkPXRoaXMudGFpbD1udWxsKToocis9Y2MobywwLGUpLHRoaXMuaGVhZD1pLGkuZGF0YT1jYyhvLGUpKTticmVha30rK247fXdoaWxlKChpPWkubmV4dCkhPT1udWxsKTtyZXR1cm4gdGhpcy5sZW5ndGgtPW4scn1fZ2V0QnVmZmVyKGUpe2xldCByPWpzLmFsbG9jVW5zYWZlKGUpLGk9ZSxuPXRoaXMuaGVhZCxvPTA7ZG97bGV0IHM9bi5kYXRhO2lmKGU+cy5sZW5ndGgpbm4ocixzLGktZSksZS09cy5sZW5ndGg7ZWxzZSB7ZT09PXMubGVuZ3RoPyhubihyLHMsaS1lKSwrK28sbi5uZXh0P3RoaXMuaGVhZD1uLm5leHQ6dGhpcy5oZWFkPXRoaXMudGFpbD1udWxsKToobm4ocixuZXcgYXcocy5idWZmZXIscy5ieXRlT2Zmc2V0LGUpLGktZSksdGhpcy5oZWFkPW4sbi5kYXRhPXMuc2xpY2UoZSkpO2JyZWFrfSsrbzt9d2hpbGUoKG49bi5uZXh0KSE9PW51bGwpO3JldHVybiB0aGlzLmxlbmd0aC09byxyfVtTeW1ib2wuZm9yKFwibm9kZWpzLnV0aWwuaW5zcGVjdC5jdXN0b21cIildKGUscil7cmV0dXJuIGx3KHRoaXMsey4uLnIsZGVwdGg6MCxjdXN0b21JbnNwZWN0OiExfSl9fTt9KTt2YXIgc249TSgoZjIsZ2MpPT57digpO20oKTtfKCk7dmFye01hdGhGbG9vcjp1dyxOdW1iZXJJc0ludGVnZXI6Znd9PWNlKCkse0VSUl9JTlZBTElEX0FSR19WQUxVRTpjd309U2UoKS5jb2RlcztmdW5jdGlvbiBodyh0LGUscil7cmV0dXJuIHQuaGlnaFdhdGVyTWFyayE9bnVsbD90LmhpZ2hXYXRlck1hcms6ZT90W3JdOm51bGx9ZnVuY3Rpb24gcGModCl7cmV0dXJuIHQ/MTY6MTYqMTAyNH1mdW5jdGlvbiBkdyh0LGUscixpKXtsZXQgbj1odyhlLGkscik7aWYobiE9bnVsbCl7aWYoIWZ3KG4pfHxuPDApe2xldCBvPWk/YG9wdGlvbnMuJHtyfWA6XCJvcHRpb25zLmhpZ2hXYXRlck1hcmtcIjt0aHJvdyBuZXcgY3cobyxuKX1yZXR1cm4gdXcobil9cmV0dXJuIHBjKHQub2JqZWN0TW9kZSl9Z2MuZXhwb3J0cz17Z2V0SGlnaFdhdGVyTWFyazpkdyxnZXREZWZhdWx0SGlnaFdhdGVyTWFyazpwY307fSk7ZnVuY3Rpb24gd2ModCl7dmFyIGU9dC5sZW5ndGg7aWYoZSU0PjApdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzdHJpbmcuIExlbmd0aCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNFwiKTt2YXIgcj10LmluZGV4T2YoXCI9XCIpO3JldHVybiByPT09LTEmJihyPWUpLFtyLHI9PT1lPzA6NC1yJTRdfWZ1bmN0aW9uIHB3KHQsZSxyKXtmb3IodmFyIGksbixvPVtdLHM9ZTtzPHI7cys9MylpPSh0W3NdPDwxNiYxNjcxMTY4MCkrKHRbcysxXTw8OCY2NTI4MCkrKDI1NSZ0W3MrMl0pLG8ucHVzaCgkZVsobj1pKT4+MTgmNjNdKyRlW24+PjEyJjYzXSskZVtuPj42JjYzXSskZVs2MyZuXSk7cmV0dXJuIG8uam9pbihcIlwiKX1mdW5jdGlvbiB2dCh0KXtpZih0PjIxNDc0ODM2NDcpdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RoZSB2YWx1ZSBcIicrdCsnXCIgaXMgaW52YWxpZCBmb3Igb3B0aW9uIFwic2l6ZVwiJyk7dmFyIGU9bmV3IFVpbnQ4QXJyYXkodCk7cmV0dXJuIE9iamVjdC5zZXRQcm90b3R5cGVPZihlLGsucHJvdG90eXBlKSxlfWZ1bmN0aW9uIGsodCxlLHIpe2lmKHR5cGVvZiB0PT1cIm51bWJlclwiKXtpZih0eXBlb2YgZT09XCJzdHJpbmdcIil0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgXCJzdHJpbmdcIiBhcmd1bWVudCBtdXN0IGJlIG9mIHR5cGUgc3RyaW5nLiBSZWNlaXZlZCB0eXBlIG51bWJlcicpO3JldHVybiBIcyh0KX1yZXR1cm4gQ2ModCxlLHIpfWZ1bmN0aW9uIENjKHQsZSxyKXtpZih0eXBlb2YgdD09XCJzdHJpbmdcIilyZXR1cm4gZnVuY3Rpb24obyxzKXtpZih0eXBlb2Ygcz09XCJzdHJpbmdcIiYmcyE9PVwiXCJ8fChzPVwidXRmOFwiKSwhay5pc0VuY29kaW5nKHMpKXRocm93IG5ldyBUeXBlRXJyb3IoXCJVbmtub3duIGVuY29kaW5nOiBcIitzKTt2YXIgYT0wfFBjKG8scyksdT12dChhKSxjPXUud3JpdGUobyxzKTtyZXR1cm4gYyE9PWEmJih1PXUuc2xpY2UoMCxjKSksdX0odCxlKTtpZihBcnJheUJ1ZmZlci5pc1ZpZXcodCkpcmV0dXJuIEZzKHQpO2lmKHQ9PW51bGwpdGhyb3cgbmV3IFR5cGVFcnJvcihcIlRoZSBmaXJzdCBhcmd1bWVudCBtdXN0IGJlIG9uZSBvZiB0eXBlIHN0cmluZywgQnVmZmVyLCBBcnJheUJ1ZmZlciwgQXJyYXksIG9yIEFycmF5LWxpa2UgT2JqZWN0LiBSZWNlaXZlZCB0eXBlIFwiK3R5cGVvZiB0KTtpZihFdCh0LEFycmF5QnVmZmVyKXx8dCYmRXQodC5idWZmZXIsQXJyYXlCdWZmZXIpfHx0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXI8XCJ1XCImJihFdCh0LFNoYXJlZEFycmF5QnVmZmVyKXx8dCYmRXQodC5idWZmZXIsU2hhcmVkQXJyYXlCdWZmZXIpKSlyZXR1cm4gbWModCxlLHIpO2lmKHR5cGVvZiB0PT1cIm51bWJlclwiKXRocm93IG5ldyBUeXBlRXJyb3IoJ1RoZSBcInZhbHVlXCIgYXJndW1lbnQgbXVzdCBub3QgYmUgb2YgdHlwZSBudW1iZXIuIFJlY2VpdmVkIHR5cGUgbnVtYmVyJyk7dmFyIGk9dC52YWx1ZU9mJiZ0LnZhbHVlT2YoKTtpZihpIT1udWxsJiZpIT09dClyZXR1cm4gay5mcm9tKGksZSxyKTt2YXIgbj1mdW5jdGlvbihvKXtpZihrLmlzQnVmZmVyKG8pKXt2YXIgcz0wfEtzKG8ubGVuZ3RoKSxhPXZ0KHMpO3JldHVybiBhLmxlbmd0aD09PTB8fG8uY29weShhLDAsMCxzKSxhfWlmKG8ubGVuZ3RoIT09dm9pZCAwKXJldHVybiB0eXBlb2Ygby5sZW5ndGghPVwibnVtYmVyXCJ8fEdzKG8ubGVuZ3RoKT92dCgwKTpGcyhvKTtpZihvLnR5cGU9PT1cIkJ1ZmZlclwiJiZBcnJheS5pc0FycmF5KG8uZGF0YSkpcmV0dXJuIEZzKG8uZGF0YSl9KHQpO2lmKG4pcmV0dXJuIG47aWYodHlwZW9mIFN5bWJvbDxcInVcIiYmU3ltYm9sLnRvUHJpbWl0aXZlIT1udWxsJiZ0eXBlb2YgdFtTeW1ib2wudG9QcmltaXRpdmVdPT1cImZ1bmN0aW9uXCIpcmV0dXJuIGsuZnJvbSh0W1N5bWJvbC50b1ByaW1pdGl2ZV0oXCJzdHJpbmdcIiksZSxyKTt0aHJvdyBuZXcgVHlwZUVycm9yKFwiVGhlIGZpcnN0IGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgc3RyaW5nLCBCdWZmZXIsIEFycmF5QnVmZmVyLCBBcnJheSwgb3IgQXJyYXktbGlrZSBPYmplY3QuIFJlY2VpdmVkIHR5cGUgXCIrdHlwZW9mIHQpfWZ1bmN0aW9uIEJjKHQpe2lmKHR5cGVvZiB0IT1cIm51bWJlclwiKXRocm93IG5ldyBUeXBlRXJyb3IoJ1wic2l6ZVwiIGFyZ3VtZW50IG11c3QgYmUgb2YgdHlwZSBudW1iZXInKTtpZih0PDApdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RoZSB2YWx1ZSBcIicrdCsnXCIgaXMgaW52YWxpZCBmb3Igb3B0aW9uIFwic2l6ZVwiJyl9ZnVuY3Rpb24gSHModCl7cmV0dXJuIEJjKHQpLHZ0KHQ8MD8wOjB8S3ModCkpfWZ1bmN0aW9uIEZzKHQpe2Zvcih2YXIgZT10Lmxlbmd0aDwwPzA6MHxLcyh0Lmxlbmd0aCkscj12dChlKSxpPTA7aTxlO2krPTEpcltpXT0yNTUmdFtpXTtyZXR1cm4gcn1mdW5jdGlvbiBtYyh0LGUscil7aWYoZTwwfHx0LmJ5dGVMZW5ndGg8ZSl0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJvZmZzZXRcIiBpcyBvdXRzaWRlIG9mIGJ1ZmZlciBib3VuZHMnKTtpZih0LmJ5dGVMZW5ndGg8ZSsocnx8MCkpdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1wibGVuZ3RoXCIgaXMgb3V0c2lkZSBvZiBidWZmZXIgYm91bmRzJyk7dmFyIGk7cmV0dXJuIGk9ZT09PXZvaWQgMCYmcj09PXZvaWQgMD9uZXcgVWludDhBcnJheSh0KTpyPT09dm9pZCAwP25ldyBVaW50OEFycmF5KHQsZSk6bmV3IFVpbnQ4QXJyYXkodCxlLHIpLE9iamVjdC5zZXRQcm90b3R5cGVPZihpLGsucHJvdG90eXBlKSxpfWZ1bmN0aW9uIEtzKHQpe2lmKHQ+PTIxNDc0ODM2NDcpdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJBdHRlbXB0IHRvIGFsbG9jYXRlIEJ1ZmZlciBsYXJnZXIgdGhhbiBtYXhpbXVtIHNpemU6IDB4XCIrMjE0NzQ4MzY0NyAudG9TdHJpbmcoMTYpK1wiIGJ5dGVzXCIpO3JldHVybiAwfHR9ZnVuY3Rpb24gUGModCxlKXtpZihrLmlzQnVmZmVyKHQpKXJldHVybiB0Lmxlbmd0aDtpZihBcnJheUJ1ZmZlci5pc1ZpZXcodCl8fEV0KHQsQXJyYXlCdWZmZXIpKXJldHVybiB0LmJ5dGVMZW5ndGg7aWYodHlwZW9mIHQhPVwic3RyaW5nXCIpdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIFwic3RyaW5nXCIgYXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdHlwZSBzdHJpbmcsIEJ1ZmZlciwgb3IgQXJyYXlCdWZmZXIuIFJlY2VpdmVkIHR5cGUgJyt0eXBlb2YgdCk7dmFyIHI9dC5sZW5ndGgsaT1hcmd1bWVudHMubGVuZ3RoPjImJmFyZ3VtZW50c1syXT09PSEwO2lmKCFpJiZyPT09MClyZXR1cm4gMDtmb3IodmFyIG49ITE7Oylzd2l0Y2goZSl7Y2FzZVwiYXNjaWlcIjpjYXNlXCJsYXRpbjFcIjpjYXNlXCJiaW5hcnlcIjpyZXR1cm4gcjtjYXNlXCJ1dGY4XCI6Y2FzZVwidXRmLThcIjpyZXR1cm4gVnModCkubGVuZ3RoO2Nhc2VcInVjczJcIjpjYXNlXCJ1Y3MtMlwiOmNhc2VcInV0ZjE2bGVcIjpjYXNlXCJ1dGYtMTZsZVwiOnJldHVybiAyKnI7Y2FzZVwiaGV4XCI6cmV0dXJuIHI+Pj4xO2Nhc2VcImJhc2U2NFwiOnJldHVybiBNYyh0KS5sZW5ndGg7ZGVmYXVsdDppZihuKXJldHVybiBpPy0xOlZzKHQpLmxlbmd0aDtlPShcIlwiK2UpLnRvTG93ZXJDYXNlKCksbj0hMDt9fWZ1bmN0aW9uIHl3KHQsZSxyKXt2YXIgaT0hMTtpZigoZT09PXZvaWQgMHx8ZTwwKSYmKGU9MCksZT50aGlzLmxlbmd0aHx8KChyPT09dm9pZCAwfHxyPnRoaXMubGVuZ3RoKSYmKHI9dGhpcy5sZW5ndGgpLHI8PTApfHwocj4+Pj0wKTw9KGU+Pj49MCkpcmV0dXJuIFwiXCI7Zm9yKHR8fCh0PVwidXRmOFwiKTs7KXN3aXRjaCh0KXtjYXNlXCJoZXhcIjpyZXR1cm4gSXcodGhpcyxlLHIpO2Nhc2VcInV0ZjhcIjpjYXNlXCJ1dGYtOFwiOnJldHVybiBrYyh0aGlzLGUscik7Y2FzZVwiYXNjaWlcIjpyZXR1cm4gU3codGhpcyxlLHIpO2Nhc2VcImxhdGluMVwiOmNhc2VcImJpbmFyeVwiOnJldHVybiBBdyh0aGlzLGUscik7Y2FzZVwiYmFzZTY0XCI6cmV0dXJuIEV3KHRoaXMsZSxyKTtjYXNlXCJ1Y3MyXCI6Y2FzZVwidWNzLTJcIjpjYXNlXCJ1dGYxNmxlXCI6Y2FzZVwidXRmLTE2bGVcIjpyZXR1cm4gVHcodGhpcyxlLHIpO2RlZmF1bHQ6aWYoaSl0aHJvdyBuZXcgVHlwZUVycm9yKFwiVW5rbm93biBlbmNvZGluZzogXCIrdCk7dD0odCtcIlwiKS50b0xvd2VyQ2FzZSgpLGk9ITA7fX1mdW5jdGlvbiBzcih0LGUscil7dmFyIGk9dFtlXTt0W2VdPXRbcl0sdFtyXT1pO31mdW5jdGlvbiB2Yyh0LGUscixpLG4pe2lmKHQubGVuZ3RoPT09MClyZXR1cm4gLTE7aWYodHlwZW9mIHI9PVwic3RyaW5nXCI/KGk9cixyPTApOnI+MjE0NzQ4MzY0Nz9yPTIxNDc0ODM2NDc6cjwtMjE0NzQ4MzY0OCYmKHI9LTIxNDc0ODM2NDgpLEdzKHI9K3IpJiYocj1uPzA6dC5sZW5ndGgtMSkscjwwJiYocj10Lmxlbmd0aCtyKSxyPj10Lmxlbmd0aCl7aWYobilyZXR1cm4gLTE7cj10Lmxlbmd0aC0xO31lbHNlIGlmKHI8MCl7aWYoIW4pcmV0dXJuIC0xO3I9MDt9aWYodHlwZW9mIGU9PVwic3RyaW5nXCImJihlPWsuZnJvbShlLGkpKSxrLmlzQnVmZmVyKGUpKXJldHVybiBlLmxlbmd0aD09PTA/LTE6RWModCxlLHIsaSxuKTtpZih0eXBlb2YgZT09XCJudW1iZXJcIilyZXR1cm4gZSY9MjU1LHR5cGVvZiBVaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mPT1cImZ1bmN0aW9uXCI/bj9VaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwodCxlLHIpOlVpbnQ4QXJyYXkucHJvdG90eXBlLmxhc3RJbmRleE9mLmNhbGwodCxlLHIpOkVjKHQsW2VdLHIsaSxuKTt0aHJvdyBuZXcgVHlwZUVycm9yKFwidmFsIG11c3QgYmUgc3RyaW5nLCBudW1iZXIgb3IgQnVmZmVyXCIpfWZ1bmN0aW9uIEVjKHQsZSxyLGksbil7dmFyIG8scz0xLGE9dC5sZW5ndGgsdT1lLmxlbmd0aDtpZihpIT09dm9pZCAwJiYoKGk9U3RyaW5nKGkpLnRvTG93ZXJDYXNlKCkpPT09XCJ1Y3MyXCJ8fGk9PT1cInVjcy0yXCJ8fGk9PT1cInV0ZjE2bGVcInx8aT09PVwidXRmLTE2bGVcIikpe2lmKHQubGVuZ3RoPDJ8fGUubGVuZ3RoPDIpcmV0dXJuIC0xO3M9MixhLz0yLHUvPTIsci89Mjt9ZnVuY3Rpb24gYyh5LHcpe3JldHVybiBzPT09MT95W3ddOnkucmVhZFVJbnQxNkJFKHcqcyl9aWYobil7dmFyIGg9LTE7Zm9yKG89cjtvPGE7bysrKWlmKGModCxvKT09PWMoZSxoPT09LTE/MDpvLWgpKXtpZihoPT09LTEmJihoPW8pLG8taCsxPT09dSlyZXR1cm4gaCpzfWVsc2UgaCE9PS0xJiYoby09by1oKSxoPS0xO31lbHNlIGZvcihyK3U+YSYmKHI9YS11KSxvPXI7bz49MDtvLS0pe2Zvcih2YXIgZD0hMCxnPTA7Zzx1O2crKylpZihjKHQsbytnKSE9PWMoZSxnKSl7ZD0hMTticmVha31pZihkKXJldHVybiBvfXJldHVybiAtMX1mdW5jdGlvbiBidyh0LGUscixpKXtyPU51bWJlcihyKXx8MDt2YXIgbj10Lmxlbmd0aC1yO2k/KGk9TnVtYmVyKGkpKT5uJiYoaT1uKTppPW47dmFyIG89ZS5sZW5ndGg7aT5vLzImJihpPW8vMik7Zm9yKHZhciBzPTA7czxpOysrcyl7dmFyIGE9cGFyc2VJbnQoZS5zdWJzdHIoMipzLDIpLDE2KTtpZihHcyhhKSlyZXR1cm4gczt0W3Irc109YTt9cmV0dXJuIHN9ZnVuY3Rpb24gd3codCxlLHIsaSl7cmV0dXJuIHVuKFZzKGUsdC5sZW5ndGgtciksdCxyLGkpfWZ1bmN0aW9uIE9jKHQsZSxyLGkpe3JldHVybiB1bihmdW5jdGlvbihuKXtmb3IodmFyIG89W10scz0wO3M8bi5sZW5ndGg7KytzKW8ucHVzaCgyNTUmbi5jaGFyQ29kZUF0KHMpKTtyZXR1cm4gb30oZSksdCxyLGkpfWZ1bmN0aW9uIF93KHQsZSxyLGkpe3JldHVybiBPYyh0LGUscixpKX1mdW5jdGlvbiBtdyh0LGUscixpKXtyZXR1cm4gdW4oTWMoZSksdCxyLGkpfWZ1bmN0aW9uIHZ3KHQsZSxyLGkpe3JldHVybiB1bihmdW5jdGlvbihuLG8pe2Zvcih2YXIgcyxhLHUsYz1bXSxoPTA7aDxuLmxlbmd0aCYmISgoby09Mik8MCk7KytoKXM9bi5jaGFyQ29kZUF0KGgpLGE9cz4+OCx1PXMlMjU2LGMucHVzaCh1KSxjLnB1c2goYSk7cmV0dXJuIGN9KGUsdC5sZW5ndGgtciksdCxyLGkpfWZ1bmN0aW9uIEV3KHQsZSxyKXtyZXR1cm4gZT09PTAmJnI9PT10Lmxlbmd0aD8kcy5mcm9tQnl0ZUFycmF5KHQpOiRzLmZyb21CeXRlQXJyYXkodC5zbGljZShlLHIpKX1mdW5jdGlvbiBrYyh0LGUscil7cj1NYXRoLm1pbih0Lmxlbmd0aCxyKTtmb3IodmFyIGk9W10sbj1lO248cjspe3ZhciBvLHMsYSx1LGM9dFtuXSxoPW51bGwsZD1jPjIzOT80OmM+MjIzPzM6Yz4xOTE/MjoxO2lmKG4rZDw9cilzd2l0Y2goZCl7Y2FzZSAxOmM8MTI4JiYoaD1jKTticmVhaztjYXNlIDI6KDE5MiYobz10W24rMV0pKT09MTI4JiYodT0oMzEmYyk8PDZ8NjMmbyk+MTI3JiYoaD11KTticmVhaztjYXNlIDM6bz10W24rMV0scz10W24rMl0sKDE5MiZvKT09MTI4JiYoMTkyJnMpPT0xMjgmJih1PSgxNSZjKTw8MTJ8KDYzJm8pPDw2fDYzJnMpPjIwNDcmJih1PDU1Mjk2fHx1PjU3MzQzKSYmKGg9dSk7YnJlYWs7Y2FzZSA0Om89dFtuKzFdLHM9dFtuKzJdLGE9dFtuKzNdLCgxOTImbyk9PTEyOCYmKDE5MiZzKT09MTI4JiYoMTkyJmEpPT0xMjgmJih1PSgxNSZjKTw8MTh8KDYzJm8pPDwxMnwoNjMmcyk8PDZ8NjMmYSk+NjU1MzUmJnU8MTExNDExMiYmKGg9dSk7fWg9PT1udWxsPyhoPTY1NTMzLGQ9MSk6aD42NTUzNSYmKGgtPTY1NTM2LGkucHVzaChoPj4+MTAmMTAyM3w1NTI5NiksaD01NjMyMHwxMDIzJmgpLGkucHVzaChoKSxuKz1kO31yZXR1cm4gZnVuY3Rpb24oZyl7dmFyIHk9Zy5sZW5ndGg7aWYoeTw9NDA5NilyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsZyk7Zm9yKHZhciB3PVwiXCIsRT0wO0U8eTspdys9U3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsZy5zbGljZShFLEUrPTQwOTYpKTtyZXR1cm4gd30oaSl9ZnVuY3Rpb24gU3codCxlLHIpe3ZhciBpPVwiXCI7cj1NYXRoLm1pbih0Lmxlbmd0aCxyKTtmb3IodmFyIG49ZTtuPHI7KytuKWkrPVN0cmluZy5mcm9tQ2hhckNvZGUoMTI3JnRbbl0pO3JldHVybiBpfWZ1bmN0aW9uIEF3KHQsZSxyKXt2YXIgaT1cIlwiO3I9TWF0aC5taW4odC5sZW5ndGgscik7Zm9yKHZhciBuPWU7bjxyOysrbilpKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHRbbl0pO3JldHVybiBpfWZ1bmN0aW9uIEl3KHQsZSxyKXt2YXIgaT10Lmxlbmd0aDsoIWV8fGU8MCkmJihlPTApLCghcnx8cjwwfHxyPmkpJiYocj1pKTtmb3IodmFyIG49XCJcIixvPWU7bzxyOysrbyluKz1Dd1t0W29dXTtyZXR1cm4gbn1mdW5jdGlvbiBUdyh0LGUscil7Zm9yKHZhciBpPXQuc2xpY2UoZSxyKSxuPVwiXCIsbz0wO288aS5sZW5ndGg7bys9MiluKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGlbb10rMjU2KmlbbysxXSk7cmV0dXJuIG59ZnVuY3Rpb24gYmUodCxlLHIpe2lmKHQlMSE9MHx8dDwwKXRocm93IG5ldyBSYW5nZUVycm9yKFwib2Zmc2V0IGlzIG5vdCB1aW50XCIpO2lmKHQrZT5yKXRocm93IG5ldyBSYW5nZUVycm9yKFwiVHJ5aW5nIHRvIGFjY2VzcyBiZXlvbmQgYnVmZmVyIGxlbmd0aFwiKX1mdW5jdGlvbiBQZSh0LGUscixpLG4sbyl7aWYoIWsuaXNCdWZmZXIodCkpdGhyb3cgbmV3IFR5cGVFcnJvcignXCJidWZmZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyIGluc3RhbmNlJyk7aWYoZT5ufHxlPG8pdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1widmFsdWVcIiBhcmd1bWVudCBpcyBvdXQgb2YgYm91bmRzJyk7aWYocitpPnQubGVuZ3RoKXRocm93IG5ldyBSYW5nZUVycm9yKFwiSW5kZXggb3V0IG9mIHJhbmdlXCIpfWZ1bmN0aW9uIHhjKHQsZSxyLGksbixvKXtpZihyK2k+dC5sZW5ndGgpdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJJbmRleCBvdXQgb2YgcmFuZ2VcIik7aWYocjwwKXRocm93IG5ldyBSYW5nZUVycm9yKFwiSW5kZXggb3V0IG9mIHJhbmdlXCIpfWZ1bmN0aW9uIFNjKHQsZSxyLGksbil7cmV0dXJuIGU9K2Uscj4+Pj0wLG58fHhjKHQsMCxyLDQpLE5yLndyaXRlKHQsZSxyLGksMjMsNCkscis0fWZ1bmN0aW9uIEFjKHQsZSxyLGksbil7cmV0dXJuIGU9K2Uscj4+Pj0wLG58fHhjKHQsMCxyLDgpLE5yLndyaXRlKHQsZSxyLGksNTIsOCkscis4fWZ1bmN0aW9uIFZzKHQsZSl7dmFyIHI7ZT1lfHwxLzA7Zm9yKHZhciBpPXQubGVuZ3RoLG49bnVsbCxvPVtdLHM9MDtzPGk7KytzKXtpZigocj10LmNoYXJDb2RlQXQocykpPjU1Mjk1JiZyPDU3MzQ0KXtpZighbil7aWYocj41NjMxOSl7KGUtPTMpPi0xJiZvLnB1c2goMjM5LDE5MSwxODkpO2NvbnRpbnVlfWlmKHMrMT09PWkpeyhlLT0zKT4tMSYmby5wdXNoKDIzOSwxOTEsMTg5KTtjb250aW51ZX1uPXI7Y29udGludWV9aWYocjw1NjMyMCl7KGUtPTMpPi0xJiZvLnB1c2goMjM5LDE5MSwxODkpLG49cjtjb250aW51ZX1yPTY1NTM2KyhuLTU1Mjk2PDwxMHxyLTU2MzIwKTt9ZWxzZSBuJiYoZS09Myk+LTEmJm8ucHVzaCgyMzksMTkxLDE4OSk7aWYobj1udWxsLHI8MTI4KXtpZigoZS09MSk8MClicmVhaztvLnB1c2gocik7fWVsc2UgaWYocjwyMDQ4KXtpZigoZS09Mik8MClicmVhaztvLnB1c2gocj4+NnwxOTIsNjMmcnwxMjgpO31lbHNlIGlmKHI8NjU1MzYpe2lmKChlLT0zKTwwKWJyZWFrO28ucHVzaChyPj4xMnwyMjQscj4+NiY2M3wxMjgsNjMmcnwxMjgpO31lbHNlIHtpZighKHI8MTExNDExMikpdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBjb2RlIHBvaW50XCIpO2lmKChlLT00KTwwKWJyZWFrO28ucHVzaChyPj4xOHwyNDAscj4+MTImNjN8MTI4LHI+PjYmNjN8MTI4LDYzJnJ8MTI4KTt9fXJldHVybiBvfWZ1bmN0aW9uIE1jKHQpe3JldHVybiAkcy50b0J5dGVBcnJheShmdW5jdGlvbihlKXtpZigoZT0oZT1lLnNwbGl0KFwiPVwiKVswXSkudHJpbSgpLnJlcGxhY2UoUncsXCJcIikpLmxlbmd0aDwyKXJldHVybiBcIlwiO2Zvcig7ZS5sZW5ndGglNCE9MDspZSs9XCI9XCI7cmV0dXJuIGV9KHQpKX1mdW5jdGlvbiB1bih0LGUscixpKXtmb3IodmFyIG49MDtuPGkmJiEobityPj1lLmxlbmd0aHx8bj49dC5sZW5ndGgpOysrbillW24rcl09dFtuXTtyZXR1cm4gbn1mdW5jdGlvbiBFdCh0LGUpe3JldHVybiB0IGluc3RhbmNlb2YgZXx8dCE9bnVsbCYmdC5jb25zdHJ1Y3RvciE9bnVsbCYmdC5jb25zdHJ1Y3Rvci5uYW1lIT1udWxsJiZ0LmNvbnN0cnVjdG9yLm5hbWU9PT1lLm5hbWV9ZnVuY3Rpb24gR3ModCl7cmV0dXJuIHQhPXR9ZnVuY3Rpb24gSWModCxlKXtmb3IodmFyIHIgaW4gdCllW3JdPXRbcl07fWZ1bmN0aW9uIG9yKHQsZSxyKXtyZXR1cm4gaXQodCxlLHIpfWZ1bmN0aW9uIGhpKHQpe3ZhciBlO3N3aXRjaCh0aGlzLmVuY29kaW5nPWZ1bmN0aW9uKHIpe3ZhciBpPWZ1bmN0aW9uKG4pe2lmKCFuKXJldHVybiBcInV0ZjhcIjtmb3IodmFyIG87Oylzd2l0Y2gobil7Y2FzZVwidXRmOFwiOmNhc2VcInV0Zi04XCI6cmV0dXJuIFwidXRmOFwiO2Nhc2VcInVjczJcIjpjYXNlXCJ1Y3MtMlwiOmNhc2VcInV0ZjE2bGVcIjpjYXNlXCJ1dGYtMTZsZVwiOnJldHVybiBcInV0ZjE2bGVcIjtjYXNlXCJsYXRpbjFcIjpjYXNlXCJiaW5hcnlcIjpyZXR1cm4gXCJsYXRpbjFcIjtjYXNlXCJiYXNlNjRcIjpjYXNlXCJhc2NpaVwiOmNhc2VcImhleFwiOnJldHVybiBuO2RlZmF1bHQ6aWYobylyZXR1cm47bj0oXCJcIituKS50b0xvd2VyQ2FzZSgpLG89ITA7fX0ocik7aWYodHlwZW9mIGkhPVwic3RyaW5nXCImJih6cy5pc0VuY29kaW5nPT09VGN8fCFUYyhyKSkpdGhyb3cgbmV3IEVycm9yKFwiVW5rbm93biBlbmNvZGluZzogXCIrcik7cmV0dXJuIGl8fHJ9KHQpLHRoaXMuZW5jb2Rpbmcpe2Nhc2VcInV0ZjE2bGVcIjp0aGlzLnRleHQ9T3csdGhpcy5lbmQ9a3csZT00O2JyZWFrO2Nhc2VcInV0ZjhcIjp0aGlzLmZpbGxMYXN0PVB3LGU9NDticmVhaztjYXNlXCJiYXNlNjRcIjp0aGlzLnRleHQ9eHcsdGhpcy5lbmQ9TXcsZT0zO2JyZWFrO2RlZmF1bHQ6cmV0dXJuIHRoaXMud3JpdGU9THcsdGhpcy5lbmQ9VXcsdm9pZCAwfXRoaXMubGFzdE5lZWQ9MCx0aGlzLmxhc3RUb3RhbD0wLHRoaXMubGFzdENoYXI9enMuYWxsb2NVbnNhZmUoZSk7fWZ1bmN0aW9uIFdzKHQpe3JldHVybiB0PD0xMjc/MDp0Pj41PT02PzI6dD4+ND09MTQ/Mzp0Pj4zPT0zMD80OnQ+PjY9PTI/LTE6LTJ9ZnVuY3Rpb24gUHcodCl7dmFyIGU9dGhpcy5sYXN0VG90YWwtdGhpcy5sYXN0TmVlZCxyPWZ1bmN0aW9uKGksbixvKXtpZigoMTkyJm5bMF0pIT0xMjgpcmV0dXJuIGkubGFzdE5lZWQ9MCxcIlxcdUZGRkRcIjtpZihpLmxhc3ROZWVkPjEmJm4ubGVuZ3RoPjEpe2lmKCgxOTImblsxXSkhPTEyOClyZXR1cm4gaS5sYXN0TmVlZD0xLFwiXFx1RkZGRFwiO2lmKGkubGFzdE5lZWQ+MiYmbi5sZW5ndGg+MiYmKDE5MiZuWzJdKSE9MTI4KXJldHVybiBpLmxhc3ROZWVkPTIsXCJcXHVGRkZEXCJ9fSh0aGlzLHQpO3JldHVybiByIT09dm9pZCAwP3I6dGhpcy5sYXN0TmVlZDw9dC5sZW5ndGg/KHQuY29weSh0aGlzLmxhc3RDaGFyLGUsMCx0aGlzLmxhc3ROZWVkKSx0aGlzLmxhc3RDaGFyLnRvU3RyaW5nKHRoaXMuZW5jb2RpbmcsMCx0aGlzLmxhc3RUb3RhbCkpOih0LmNvcHkodGhpcy5sYXN0Q2hhcixlLDAsdC5sZW5ndGgpLHRoaXMubGFzdE5lZWQtPXQubGVuZ3RoLHZvaWQgMCl9ZnVuY3Rpb24gT3codCxlKXtpZigodC5sZW5ndGgtZSklMj09MCl7dmFyIHI9dC50b1N0cmluZyhcInV0ZjE2bGVcIixlKTtpZihyKXt2YXIgaT1yLmNoYXJDb2RlQXQoci5sZW5ndGgtMSk7aWYoaT49NTUyOTYmJmk8PTU2MzE5KXJldHVybiB0aGlzLmxhc3ROZWVkPTIsdGhpcy5sYXN0VG90YWw9NCx0aGlzLmxhc3RDaGFyWzBdPXRbdC5sZW5ndGgtMl0sdGhpcy5sYXN0Q2hhclsxXT10W3QubGVuZ3RoLTFdLHIuc2xpY2UoMCwtMSl9cmV0dXJuIHJ9cmV0dXJuIHRoaXMubGFzdE5lZWQ9MSx0aGlzLmxhc3RUb3RhbD0yLHRoaXMubGFzdENoYXJbMF09dFt0Lmxlbmd0aC0xXSx0LnRvU3RyaW5nKFwidXRmMTZsZVwiLGUsdC5sZW5ndGgtMSl9ZnVuY3Rpb24ga3codCl7dmFyIGU9dCYmdC5sZW5ndGg/dGhpcy53cml0ZSh0KTpcIlwiO2lmKHRoaXMubGFzdE5lZWQpe3ZhciByPXRoaXMubGFzdFRvdGFsLXRoaXMubGFzdE5lZWQ7cmV0dXJuIGUrdGhpcy5sYXN0Q2hhci50b1N0cmluZyhcInV0ZjE2bGVcIiwwLHIpfXJldHVybiBlfWZ1bmN0aW9uIHh3KHQsZSl7dmFyIHI9KHQubGVuZ3RoLWUpJTM7cmV0dXJuIHI9PT0wP3QudG9TdHJpbmcoXCJiYXNlNjRcIixlKToodGhpcy5sYXN0TmVlZD0zLXIsdGhpcy5sYXN0VG90YWw9MyxyPT09MT90aGlzLmxhc3RDaGFyWzBdPXRbdC5sZW5ndGgtMV06KHRoaXMubGFzdENoYXJbMF09dFt0Lmxlbmd0aC0yXSx0aGlzLmxhc3RDaGFyWzFdPXRbdC5sZW5ndGgtMV0pLHQudG9TdHJpbmcoXCJiYXNlNjRcIixlLHQubGVuZ3RoLXIpKX1mdW5jdGlvbiBNdyh0KXt2YXIgZT10JiZ0Lmxlbmd0aD90aGlzLndyaXRlKHQpOlwiXCI7cmV0dXJuIHRoaXMubGFzdE5lZWQ/ZSt0aGlzLmxhc3RDaGFyLnRvU3RyaW5nKFwiYmFzZTY0XCIsMCwzLXRoaXMubGFzdE5lZWQpOmV9ZnVuY3Rpb24gTHcodCl7cmV0dXJuIHQudG9TdHJpbmcodGhpcy5lbmNvZGluZyl9ZnVuY3Rpb24gVXcodCl7cmV0dXJuIHQmJnQubGVuZ3RoP3RoaXMud3JpdGUodCk6XCJcIn12YXIgUmMsJGUsa2UseWMsb24sbnIsYmMsZ3csU3QsJHMsTnIsX2MsUncsQ3csYW4sbG4saXQsQncsYXIsenMsVGMsUXM9d2UoKCk9Pnt2KCk7bSgpO18oKTtmb3IoUmM9e2J5dGVMZW5ndGg6ZnVuY3Rpb24odCl7dmFyIGU9d2ModCkscj1lWzBdLGk9ZVsxXTtyZXR1cm4gMyoocitpKS80LWl9LHRvQnl0ZUFycmF5OmZ1bmN0aW9uKHQpe3ZhciBlLHIsaT13Yyh0KSxuPWlbMF0sbz1pWzFdLHM9bmV3IHljKGZ1bmN0aW9uKGMsaCxkKXtyZXR1cm4gMyooaCtkKS80LWR9KDAsbixvKSksYT0wLHU9bz4wP24tNDpuO2ZvcihyPTA7cjx1O3IrPTQpZT1rZVt0LmNoYXJDb2RlQXQocildPDwxOHxrZVt0LmNoYXJDb2RlQXQocisxKV08PDEyfGtlW3QuY2hhckNvZGVBdChyKzIpXTw8NnxrZVt0LmNoYXJDb2RlQXQociszKV0sc1thKytdPWU+PjE2JjI1NSxzW2ErK109ZT4+OCYyNTUsc1thKytdPTI1NSZlO3JldHVybiBvPT09MiYmKGU9a2VbdC5jaGFyQ29kZUF0KHIpXTw8MnxrZVt0LmNoYXJDb2RlQXQocisxKV0+PjQsc1thKytdPTI1NSZlKSxvPT09MSYmKGU9a2VbdC5jaGFyQ29kZUF0KHIpXTw8MTB8a2VbdC5jaGFyQ29kZUF0KHIrMSldPDw0fGtlW3QuY2hhckNvZGVBdChyKzIpXT4+MixzW2ErK109ZT4+OCYyNTUsc1thKytdPTI1NSZlKSxzfSxmcm9tQnl0ZUFycmF5OmZ1bmN0aW9uKHQpe2Zvcih2YXIgZSxyPXQubGVuZ3RoLGk9ciUzLG49W10sbz0wLHM9ci1pO288cztvKz0xNjM4MyluLnB1c2gocHcodCxvLG8rMTYzODM+cz9zOm8rMTYzODMpKTtyZXR1cm4gaT09PTE/KGU9dFtyLTFdLG4ucHVzaCgkZVtlPj4yXSskZVtlPDw0JjYzXStcIj09XCIpKTppPT09MiYmKGU9KHRbci0yXTw8OCkrdFtyLTFdLG4ucHVzaCgkZVtlPj4xMF0rJGVbZT4+NCY2M10rJGVbZTw8MiY2M10rXCI9XCIpKSxuLmpvaW4oXCJcIil9fSwkZT1bXSxrZT1bXSx5Yz10eXBlb2YgVWludDhBcnJheTxcInVcIj9VaW50OEFycmF5OkFycmF5LG9uPVwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrL1wiLG5yPTAsYmM9b24ubGVuZ3RoO25yPGJjOysrbnIpJGVbbnJdPW9uW25yXSxrZVtvbi5jaGFyQ29kZUF0KG5yKV09bnI7a2VbXCItXCIuY2hhckNvZGVBdCgwKV09NjIsa2VbXCJfXCIuY2hhckNvZGVBdCgwKV09NjM7Z3c9e3JlYWQ6ZnVuY3Rpb24odCxlLHIsaSxuKXt2YXIgbyxzLGE9OCpuLWktMSx1PSgxPDxhKS0xLGM9dT4+MSxoPS03LGQ9cj9uLTE6MCxnPXI/LTE6MSx5PXRbZStkXTtmb3IoZCs9ZyxvPXkmKDE8PC1oKS0xLHk+Pj0taCxoKz1hO2g+MDtvPTI1NipvK3RbZStkXSxkKz1nLGgtPTgpO2ZvcihzPW8mKDE8PC1oKS0xLG8+Pj0taCxoKz1pO2g+MDtzPTI1NipzK3RbZStkXSxkKz1nLGgtPTgpO2lmKG89PT0wKW89MS1jO2Vsc2Uge2lmKG89PT11KXJldHVybiBzP05hTjoxLzAqKHk/LTE6MSk7cys9TWF0aC5wb3coMixpKSxvLT1jO31yZXR1cm4gKHk/LTE6MSkqcypNYXRoLnBvdygyLG8taSl9LHdyaXRlOmZ1bmN0aW9uKHQsZSxyLGksbixvKXt2YXIgcyxhLHUsYz04Km8tbi0xLGg9KDE8PGMpLTEsZD1oPj4xLGc9bj09PTIzP01hdGgucG93KDIsLTI0KS1NYXRoLnBvdygyLC03Nyk6MCx5PWk/MDpvLTEsdz1pPzE6LTEsRT1lPDB8fGU9PT0wJiYxL2U8MD8xOjA7Zm9yKGU9TWF0aC5hYnMoZSksaXNOYU4oZSl8fGU9PT0xLzA/KGE9aXNOYU4oZSk/MTowLHM9aCk6KHM9TWF0aC5mbG9vcihNYXRoLmxvZyhlKS9NYXRoLkxOMiksZSoodT1NYXRoLnBvdygyLC1zKSk8MSYmKHMtLSx1Kj0yKSwoZSs9cytkPj0xP2cvdTpnKk1hdGgucG93KDIsMS1kKSkqdT49MiYmKHMrKyx1Lz0yKSxzK2Q+PWg/KGE9MCxzPWgpOnMrZD49MT8oYT0oZSp1LTEpKk1hdGgucG93KDIsbikscys9ZCk6KGE9ZSpNYXRoLnBvdygyLGQtMSkqTWF0aC5wb3coMixuKSxzPTApKTtuPj04O3Rbcit5XT0yNTUmYSx5Kz13LGEvPTI1NixuLT04KTtmb3Iocz1zPDxufGEsYys9bjtjPjA7dFtyK3ldPTI1NSZzLHkrPXcscy89MjU2LGMtPTgpO3Rbcit5LXddfD0xMjgqRTt9fSxTdD17fSwkcz1SYyxOcj1ndyxfYz10eXBlb2YgU3ltYm9sPT1cImZ1bmN0aW9uXCImJnR5cGVvZiBTeW1ib2wuZm9yPT1cImZ1bmN0aW9uXCI/U3ltYm9sLmZvcihcIm5vZGVqcy51dGlsLmluc3BlY3QuY3VzdG9tXCIpOm51bGw7U3QuQnVmZmVyPWssU3QuU2xvd0J1ZmZlcj1mdW5jdGlvbih0KXtyZXR1cm4gK3QhPXQmJih0PTApLGsuYWxsb2MoK3QpfSxTdC5JTlNQRUNUX01BWF9CWVRFUz01MDtTdC5rTWF4TGVuZ3RoPTIxNDc0ODM2NDcsay5UWVBFRF9BUlJBWV9TVVBQT1JUPWZ1bmN0aW9uKCl7dHJ5e3ZhciB0PW5ldyBVaW50OEFycmF5KDEpLGU9e2ZvbzpmdW5jdGlvbigpe3JldHVybiA0Mn19O3JldHVybiBPYmplY3Quc2V0UHJvdG90eXBlT2YoZSxVaW50OEFycmF5LnByb3RvdHlwZSksT2JqZWN0LnNldFByb3RvdHlwZU9mKHQsZSksdC5mb28oKT09PTQyfWNhdGNoe3JldHVybiAhMX19KCksay5UWVBFRF9BUlJBWV9TVVBQT1JUfHx0eXBlb2YgY29uc29sZT5cInVcInx8dHlwZW9mIGNvbnNvbGUuZXJyb3IhPVwiZnVuY3Rpb25cInx8Y29uc29sZS5lcnJvcihcIlRoaXMgYnJvd3NlciBsYWNrcyB0eXBlZCBhcnJheSAoVWludDhBcnJheSkgc3VwcG9ydCB3aGljaCBpcyByZXF1aXJlZCBieSBgYnVmZmVyYCB2NS54LiBVc2UgYGJ1ZmZlcmAgdjQueCBpZiB5b3UgcmVxdWlyZSBvbGQgYnJvd3NlciBzdXBwb3J0LlwiKSxPYmplY3QuZGVmaW5lUHJvcGVydHkoay5wcm90b3R5cGUsXCJwYXJlbnRcIix7ZW51bWVyYWJsZTohMCxnZXQ6ZnVuY3Rpb24oKXtpZihrLmlzQnVmZmVyKHRoaXMpKXJldHVybiB0aGlzLmJ1ZmZlcn19KSxPYmplY3QuZGVmaW5lUHJvcGVydHkoay5wcm90b3R5cGUsXCJvZmZzZXRcIix7ZW51bWVyYWJsZTohMCxnZXQ6ZnVuY3Rpb24oKXtpZihrLmlzQnVmZmVyKHRoaXMpKXJldHVybiB0aGlzLmJ5dGVPZmZzZXR9fSksay5wb29sU2l6ZT04MTkyLGsuZnJvbT1mdW5jdGlvbih0LGUscil7cmV0dXJuIENjKHQsZSxyKX0sT2JqZWN0LnNldFByb3RvdHlwZU9mKGsucHJvdG90eXBlLFVpbnQ4QXJyYXkucHJvdG90eXBlKSxPYmplY3Quc2V0UHJvdG90eXBlT2YoayxVaW50OEFycmF5KSxrLmFsbG9jPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gZnVuY3Rpb24oaSxuLG8pe3JldHVybiBCYyhpKSxpPD0wP3Z0KGkpOm4hPT12b2lkIDA/dHlwZW9mIG89PVwic3RyaW5nXCI/dnQoaSkuZmlsbChuLG8pOnZ0KGkpLmZpbGwobik6dnQoaSl9KHQsZSxyKX0say5hbGxvY1Vuc2FmZT1mdW5jdGlvbih0KXtyZXR1cm4gSHModCl9LGsuYWxsb2NVbnNhZmVTbG93PWZ1bmN0aW9uKHQpe3JldHVybiBIcyh0KX0say5pc0J1ZmZlcj1mdW5jdGlvbih0KXtyZXR1cm4gdCE9bnVsbCYmdC5faXNCdWZmZXI9PT0hMCYmdCE9PWsucHJvdG90eXBlfSxrLmNvbXBhcmU9ZnVuY3Rpb24odCxlKXtpZihFdCh0LFVpbnQ4QXJyYXkpJiYodD1rLmZyb20odCx0Lm9mZnNldCx0LmJ5dGVMZW5ndGgpKSxFdChlLFVpbnQ4QXJyYXkpJiYoZT1rLmZyb20oZSxlLm9mZnNldCxlLmJ5dGVMZW5ndGgpKSwhay5pc0J1ZmZlcih0KXx8IWsuaXNCdWZmZXIoZSkpdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIFwiYnVmMVwiLCBcImJ1ZjJcIiBhcmd1bWVudHMgbXVzdCBiZSBvbmUgb2YgdHlwZSBCdWZmZXIgb3IgVWludDhBcnJheScpO2lmKHQ9PT1lKXJldHVybiAwO2Zvcih2YXIgcj10Lmxlbmd0aCxpPWUubGVuZ3RoLG49MCxvPU1hdGgubWluKHIsaSk7bjxvOysrbilpZih0W25dIT09ZVtuXSl7cj10W25dLGk9ZVtuXTticmVha31yZXR1cm4gcjxpPy0xOmk8cj8xOjB9LGsuaXNFbmNvZGluZz1mdW5jdGlvbih0KXtzd2l0Y2goU3RyaW5nKHQpLnRvTG93ZXJDYXNlKCkpe2Nhc2VcImhleFwiOmNhc2VcInV0ZjhcIjpjYXNlXCJ1dGYtOFwiOmNhc2VcImFzY2lpXCI6Y2FzZVwibGF0aW4xXCI6Y2FzZVwiYmluYXJ5XCI6Y2FzZVwiYmFzZTY0XCI6Y2FzZVwidWNzMlwiOmNhc2VcInVjcy0yXCI6Y2FzZVwidXRmMTZsZVwiOmNhc2VcInV0Zi0xNmxlXCI6cmV0dXJuICEwO2RlZmF1bHQ6cmV0dXJuICExfX0say5jb25jYXQ9ZnVuY3Rpb24odCxlKXtpZighQXJyYXkuaXNBcnJheSh0KSl0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RcIiBhcmd1bWVudCBtdXN0IGJlIGFuIEFycmF5IG9mIEJ1ZmZlcnMnKTtpZih0Lmxlbmd0aD09PTApcmV0dXJuIGsuYWxsb2MoMCk7dmFyIHI7aWYoZT09PXZvaWQgMClmb3IoZT0wLHI9MDtyPHQubGVuZ3RoOysrcillKz10W3JdLmxlbmd0aDt2YXIgaT1rLmFsbG9jVW5zYWZlKGUpLG49MDtmb3Iocj0wO3I8dC5sZW5ndGg7KytyKXt2YXIgbz10W3JdO2lmKEV0KG8sVWludDhBcnJheSkmJihvPWsuZnJvbShvKSksIWsuaXNCdWZmZXIobykpdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0XCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJyk7by5jb3B5KGksbiksbis9by5sZW5ndGg7fXJldHVybiBpfSxrLmJ5dGVMZW5ndGg9UGMsay5wcm90b3R5cGUuX2lzQnVmZmVyPSEwLGsucHJvdG90eXBlLnN3YXAxNj1mdW5jdGlvbigpe3ZhciB0PXRoaXMubGVuZ3RoO2lmKHQlMiE9MCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIkJ1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAxNi1iaXRzXCIpO2Zvcih2YXIgZT0wO2U8dDtlKz0yKXNyKHRoaXMsZSxlKzEpO3JldHVybiB0aGlzfSxrLnByb3RvdHlwZS5zd2FwMzI9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmxlbmd0aDtpZih0JTQhPTApdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMzItYml0c1wiKTtmb3IodmFyIGU9MDtlPHQ7ZSs9NClzcih0aGlzLGUsZSszKSxzcih0aGlzLGUrMSxlKzIpO3JldHVybiB0aGlzfSxrLnByb3RvdHlwZS5zd2FwNjQ9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmxlbmd0aDtpZih0JTghPTApdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNjQtYml0c1wiKTtmb3IodmFyIGU9MDtlPHQ7ZSs9OClzcih0aGlzLGUsZSs3KSxzcih0aGlzLGUrMSxlKzYpLHNyKHRoaXMsZSsyLGUrNSksc3IodGhpcyxlKzMsZSs0KTtyZXR1cm4gdGhpc30say5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmxlbmd0aDtyZXR1cm4gdD09PTA/XCJcIjphcmd1bWVudHMubGVuZ3RoPT09MD9rYyh0aGlzLDAsdCk6eXcuYXBwbHkodGhpcyxhcmd1bWVudHMpfSxrLnByb3RvdHlwZS50b0xvY2FsZVN0cmluZz1rLnByb3RvdHlwZS50b1N0cmluZyxrLnByb3RvdHlwZS5lcXVhbHM9ZnVuY3Rpb24odCl7aWYoIWsuaXNCdWZmZXIodCkpdGhyb3cgbmV3IFR5cGVFcnJvcihcIkFyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXJcIik7cmV0dXJuIHRoaXM9PT10fHxrLmNvbXBhcmUodGhpcyx0KT09PTB9LGsucHJvdG90eXBlLmluc3BlY3Q9ZnVuY3Rpb24oKXt2YXIgdD1cIlwiLGU9U3QuSU5TUEVDVF9NQVhfQllURVM7cmV0dXJuIHQ9dGhpcy50b1N0cmluZyhcImhleFwiLDAsZSkucmVwbGFjZSgvKC57Mn0pL2csXCIkMSBcIikudHJpbSgpLHRoaXMubGVuZ3RoPmUmJih0Kz1cIiAuLi4gXCIpLFwiPEJ1ZmZlciBcIit0K1wiPlwifSxfYyYmKGsucHJvdG90eXBlW19jXT1rLnByb3RvdHlwZS5pbnNwZWN0KSxrLnByb3RvdHlwZS5jb21wYXJlPWZ1bmN0aW9uKHQsZSxyLGksbil7aWYoRXQodCxVaW50OEFycmF5KSYmKHQ9ay5mcm9tKHQsdC5vZmZzZXQsdC5ieXRlTGVuZ3RoKSksIWsuaXNCdWZmZXIodCkpdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIFwidGFyZ2V0XCIgYXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdHlwZSBCdWZmZXIgb3IgVWludDhBcnJheS4gUmVjZWl2ZWQgdHlwZSAnK3R5cGVvZiB0KTtpZihlPT09dm9pZCAwJiYoZT0wKSxyPT09dm9pZCAwJiYocj10P3QubGVuZ3RoOjApLGk9PT12b2lkIDAmJihpPTApLG49PT12b2lkIDAmJihuPXRoaXMubGVuZ3RoKSxlPDB8fHI+dC5sZW5ndGh8fGk8MHx8bj50aGlzLmxlbmd0aCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIm91dCBvZiByYW5nZSBpbmRleFwiKTtpZihpPj1uJiZlPj1yKXJldHVybiAwO2lmKGk+PW4pcmV0dXJuIC0xO2lmKGU+PXIpcmV0dXJuIDE7aWYodGhpcz09PXQpcmV0dXJuIDA7Zm9yKHZhciBvPShuPj4+PTApLShpPj4+PTApLHM9KHI+Pj49MCktKGU+Pj49MCksYT1NYXRoLm1pbihvLHMpLHU9dGhpcy5zbGljZShpLG4pLGM9dC5zbGljZShlLHIpLGg9MDtoPGE7KytoKWlmKHVbaF0hPT1jW2hdKXtvPXVbaF0scz1jW2hdO2JyZWFrfXJldHVybiBvPHM/LTE6czxvPzE6MH0say5wcm90b3R5cGUuaW5jbHVkZXM9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0aGlzLmluZGV4T2YodCxlLHIpIT09LTF9LGsucHJvdG90eXBlLmluZGV4T2Y9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB2Yyh0aGlzLHQsZSxyLCEwKX0say5wcm90b3R5cGUubGFzdEluZGV4T2Y9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB2Yyh0aGlzLHQsZSxyLCExKX0say5wcm90b3R5cGUud3JpdGU9ZnVuY3Rpb24odCxlLHIsaSl7aWYoZT09PXZvaWQgMClpPVwidXRmOFwiLHI9dGhpcy5sZW5ndGgsZT0wO2Vsc2UgaWYocj09PXZvaWQgMCYmdHlwZW9mIGU9PVwic3RyaW5nXCIpaT1lLHI9dGhpcy5sZW5ndGgsZT0wO2Vsc2Uge2lmKCFpc0Zpbml0ZShlKSl0aHJvdyBuZXcgRXJyb3IoXCJCdWZmZXIud3JpdGUoc3RyaW5nLCBlbmNvZGluZywgb2Zmc2V0WywgbGVuZ3RoXSkgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZFwiKTtlPj4+PTAsaXNGaW5pdGUocik/KHI+Pj49MCxpPT09dm9pZCAwJiYoaT1cInV0ZjhcIikpOihpPXIscj12b2lkIDApO312YXIgbj10aGlzLmxlbmd0aC1lO2lmKChyPT09dm9pZCAwfHxyPm4pJiYocj1uKSx0Lmxlbmd0aD4wJiYocjwwfHxlPDApfHxlPnRoaXMubGVuZ3RoKXRocm93IG5ldyBSYW5nZUVycm9yKFwiQXR0ZW1wdCB0byB3cml0ZSBvdXRzaWRlIGJ1ZmZlciBib3VuZHNcIik7aXx8KGk9XCJ1dGY4XCIpO2Zvcih2YXIgbz0hMTs7KXN3aXRjaChpKXtjYXNlXCJoZXhcIjpyZXR1cm4gYncodGhpcyx0LGUscik7Y2FzZVwidXRmOFwiOmNhc2VcInV0Zi04XCI6cmV0dXJuIHd3KHRoaXMsdCxlLHIpO2Nhc2VcImFzY2lpXCI6cmV0dXJuIE9jKHRoaXMsdCxlLHIpO2Nhc2VcImxhdGluMVwiOmNhc2VcImJpbmFyeVwiOnJldHVybiBfdyh0aGlzLHQsZSxyKTtjYXNlXCJiYXNlNjRcIjpyZXR1cm4gbXcodGhpcyx0LGUscik7Y2FzZVwidWNzMlwiOmNhc2VcInVjcy0yXCI6Y2FzZVwidXRmMTZsZVwiOmNhc2VcInV0Zi0xNmxlXCI6cmV0dXJuIHZ3KHRoaXMsdCxlLHIpO2RlZmF1bHQ6aWYobyl0aHJvdyBuZXcgVHlwZUVycm9yKFwiVW5rbm93biBlbmNvZGluZzogXCIraSk7aT0oXCJcIitpKS50b0xvd2VyQ2FzZSgpLG89ITA7fX0say5wcm90b3R5cGUudG9KU09OPWZ1bmN0aW9uKCl7cmV0dXJuIHt0eXBlOlwiQnVmZmVyXCIsZGF0YTpBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLl9hcnJ8fHRoaXMsMCl9fTtrLnByb3RvdHlwZS5zbGljZT1mdW5jdGlvbih0LGUpe3ZhciByPXRoaXMubGVuZ3RoOyh0PX5+dCk8MD8odCs9cik8MCYmKHQ9MCk6dD5yJiYodD1yKSwoZT1lPT09dm9pZCAwP3I6fn5lKTwwPyhlKz1yKTwwJiYoZT0wKTplPnImJihlPXIpLGU8dCYmKGU9dCk7dmFyIGk9dGhpcy5zdWJhcnJheSh0LGUpO3JldHVybiBPYmplY3Quc2V0UHJvdG90eXBlT2YoaSxrLnByb3RvdHlwZSksaX0say5wcm90b3R5cGUucmVhZFVJbnRMRT1mdW5jdGlvbih0LGUscil7dD4+Pj0wLGU+Pj49MCxyfHxiZSh0LGUsdGhpcy5sZW5ndGgpO2Zvcih2YXIgaT10aGlzW3RdLG49MSxvPTA7KytvPGUmJihuKj0yNTYpOylpKz10aGlzW3Qrb10qbjtyZXR1cm4gaX0say5wcm90b3R5cGUucmVhZFVJbnRCRT1mdW5jdGlvbih0LGUscil7dD4+Pj0wLGU+Pj49MCxyfHxiZSh0LGUsdGhpcy5sZW5ndGgpO2Zvcih2YXIgaT10aGlzW3QrLS1lXSxuPTE7ZT4wJiYobio9MjU2KTspaSs9dGhpc1t0Ky0tZV0qbjtyZXR1cm4gaX0say5wcm90b3R5cGUucmVhZFVJbnQ4PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQ+Pj49MCxlfHxiZSh0LDEsdGhpcy5sZW5ndGgpLHRoaXNbdF19LGsucHJvdG90eXBlLnJlYWRVSW50MTZMRT1mdW5jdGlvbih0LGUpe3JldHVybiB0Pj4+PTAsZXx8YmUodCwyLHRoaXMubGVuZ3RoKSx0aGlzW3RdfHRoaXNbdCsxXTw8OH0say5wcm90b3R5cGUucmVhZFVJbnQxNkJFPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQ+Pj49MCxlfHxiZSh0LDIsdGhpcy5sZW5ndGgpLHRoaXNbdF08PDh8dGhpc1t0KzFdfSxrLnByb3RvdHlwZS5yZWFkVUludDMyTEU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdD4+Pj0wLGV8fGJlKHQsNCx0aGlzLmxlbmd0aCksKHRoaXNbdF18dGhpc1t0KzFdPDw4fHRoaXNbdCsyXTw8MTYpKzE2Nzc3MjE2KnRoaXNbdCszXX0say5wcm90b3R5cGUucmVhZFVJbnQzMkJFPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQ+Pj49MCxlfHxiZSh0LDQsdGhpcy5sZW5ndGgpLDE2Nzc3MjE2KnRoaXNbdF0rKHRoaXNbdCsxXTw8MTZ8dGhpc1t0KzJdPDw4fHRoaXNbdCszXSl9LGsucHJvdG90eXBlLnJlYWRJbnRMRT1mdW5jdGlvbih0LGUscil7dD4+Pj0wLGU+Pj49MCxyfHxiZSh0LGUsdGhpcy5sZW5ndGgpO2Zvcih2YXIgaT10aGlzW3RdLG49MSxvPTA7KytvPGUmJihuKj0yNTYpOylpKz10aGlzW3Qrb10qbjtyZXR1cm4gaT49KG4qPTEyOCkmJihpLT1NYXRoLnBvdygyLDgqZSkpLGl9LGsucHJvdG90eXBlLnJlYWRJbnRCRT1mdW5jdGlvbih0LGUscil7dD4+Pj0wLGU+Pj49MCxyfHxiZSh0LGUsdGhpcy5sZW5ndGgpO2Zvcih2YXIgaT1lLG49MSxvPXRoaXNbdCstLWldO2k+MCYmKG4qPTI1Nik7KW8rPXRoaXNbdCstLWldKm47cmV0dXJuIG8+PShuKj0xMjgpJiYoby09TWF0aC5wb3coMiw4KmUpKSxvfSxrLnByb3RvdHlwZS5yZWFkSW50OD1mdW5jdGlvbih0LGUpe3JldHVybiB0Pj4+PTAsZXx8YmUodCwxLHRoaXMubGVuZ3RoKSwxMjgmdGhpc1t0XT8tMSooMjU1LXRoaXNbdF0rMSk6dGhpc1t0XX0say5wcm90b3R5cGUucmVhZEludDE2TEU9ZnVuY3Rpb24odCxlKXt0Pj4+PTAsZXx8YmUodCwyLHRoaXMubGVuZ3RoKTt2YXIgcj10aGlzW3RdfHRoaXNbdCsxXTw8ODtyZXR1cm4gMzI3Njgmcj80Mjk0OTAxNzYwfHI6cn0say5wcm90b3R5cGUucmVhZEludDE2QkU9ZnVuY3Rpb24odCxlKXt0Pj4+PTAsZXx8YmUodCwyLHRoaXMubGVuZ3RoKTt2YXIgcj10aGlzW3QrMV18dGhpc1t0XTw8ODtyZXR1cm4gMzI3Njgmcj80Mjk0OTAxNzYwfHI6cn0say5wcm90b3R5cGUucmVhZEludDMyTEU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdD4+Pj0wLGV8fGJlKHQsNCx0aGlzLmxlbmd0aCksdGhpc1t0XXx0aGlzW3QrMV08PDh8dGhpc1t0KzJdPDwxNnx0aGlzW3QrM108PDI0fSxrLnByb3RvdHlwZS5yZWFkSW50MzJCRT1mdW5jdGlvbih0LGUpe3JldHVybiB0Pj4+PTAsZXx8YmUodCw0LHRoaXMubGVuZ3RoKSx0aGlzW3RdPDwyNHx0aGlzW3QrMV08PDE2fHRoaXNbdCsyXTw8OHx0aGlzW3QrM119LGsucHJvdG90eXBlLnJlYWRGbG9hdExFPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQ+Pj49MCxlfHxiZSh0LDQsdGhpcy5sZW5ndGgpLE5yLnJlYWQodGhpcyx0LCEwLDIzLDQpfSxrLnByb3RvdHlwZS5yZWFkRmxvYXRCRT1mdW5jdGlvbih0LGUpe3JldHVybiB0Pj4+PTAsZXx8YmUodCw0LHRoaXMubGVuZ3RoKSxOci5yZWFkKHRoaXMsdCwhMSwyMyw0KX0say5wcm90b3R5cGUucmVhZERvdWJsZUxFPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQ+Pj49MCxlfHxiZSh0LDgsdGhpcy5sZW5ndGgpLE5yLnJlYWQodGhpcyx0LCEwLDUyLDgpfSxrLnByb3RvdHlwZS5yZWFkRG91YmxlQkU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdD4+Pj0wLGV8fGJlKHQsOCx0aGlzLmxlbmd0aCksTnIucmVhZCh0aGlzLHQsITEsNTIsOCl9LGsucHJvdG90eXBlLndyaXRlVUludExFPWZ1bmN0aW9uKHQsZSxyLGkpe3Q9K3QsZT4+Pj0wLHI+Pj49MCxpfHxQZSh0aGlzLHQsZSxyLE1hdGgucG93KDIsOCpyKS0xLDApO3ZhciBuPTEsbz0wO2Zvcih0aGlzW2VdPTI1NSZ0OysrbzxyJiYobio9MjU2KTspdGhpc1tlK29dPXQvbiYyNTU7cmV0dXJuIGUrcn0say5wcm90b3R5cGUud3JpdGVVSW50QkU9ZnVuY3Rpb24odCxlLHIsaSl7dD0rdCxlPj4+PTAscj4+Pj0wLGl8fFBlKHRoaXMsdCxlLHIsTWF0aC5wb3coMiw4KnIpLTEsMCk7dmFyIG49ci0xLG89MTtmb3IodGhpc1tlK25dPTI1NSZ0Oy0tbj49MCYmKG8qPTI1Nik7KXRoaXNbZStuXT10L28mMjU1O3JldHVybiBlK3J9LGsucHJvdG90eXBlLndyaXRlVUludDg9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0PSt0LGU+Pj49MCxyfHxQZSh0aGlzLHQsZSwxLDI1NSwwKSx0aGlzW2VdPTI1NSZ0LGUrMX0say5wcm90b3R5cGUud3JpdGVVSW50MTZMRT1mdW5jdGlvbih0LGUscil7cmV0dXJuIHQ9K3QsZT4+Pj0wLHJ8fFBlKHRoaXMsdCxlLDIsNjU1MzUsMCksdGhpc1tlXT0yNTUmdCx0aGlzW2UrMV09dD4+PjgsZSsyfSxrLnByb3RvdHlwZS53cml0ZVVJbnQxNkJFPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gdD0rdCxlPj4+PTAscnx8UGUodGhpcyx0LGUsMiw2NTUzNSwwKSx0aGlzW2VdPXQ+Pj44LHRoaXNbZSsxXT0yNTUmdCxlKzJ9LGsucHJvdG90eXBlLndyaXRlVUludDMyTEU9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0PSt0LGU+Pj49MCxyfHxQZSh0aGlzLHQsZSw0LDQyOTQ5NjcyOTUsMCksdGhpc1tlKzNdPXQ+Pj4yNCx0aGlzW2UrMl09dD4+PjE2LHRoaXNbZSsxXT10Pj4+OCx0aGlzW2VdPTI1NSZ0LGUrNH0say5wcm90b3R5cGUud3JpdGVVSW50MzJCRT1mdW5jdGlvbih0LGUscil7cmV0dXJuIHQ9K3QsZT4+Pj0wLHJ8fFBlKHRoaXMsdCxlLDQsNDI5NDk2NzI5NSwwKSx0aGlzW2VdPXQ+Pj4yNCx0aGlzW2UrMV09dD4+PjE2LHRoaXNbZSsyXT10Pj4+OCx0aGlzW2UrM109MjU1JnQsZSs0fSxrLnByb3RvdHlwZS53cml0ZUludExFPWZ1bmN0aW9uKHQsZSxyLGkpe2lmKHQ9K3QsZT4+Pj0wLCFpKXt2YXIgbj1NYXRoLnBvdygyLDgqci0xKTtQZSh0aGlzLHQsZSxyLG4tMSwtbik7fXZhciBvPTAscz0xLGE9MDtmb3IodGhpc1tlXT0yNTUmdDsrK288ciYmKHMqPTI1Nik7KXQ8MCYmYT09PTAmJnRoaXNbZStvLTFdIT09MCYmKGE9MSksdGhpc1tlK29dPSh0L3M+PjApLWEmMjU1O3JldHVybiBlK3J9LGsucHJvdG90eXBlLndyaXRlSW50QkU9ZnVuY3Rpb24odCxlLHIsaSl7aWYodD0rdCxlPj4+PTAsIWkpe3ZhciBuPU1hdGgucG93KDIsOCpyLTEpO1BlKHRoaXMsdCxlLHIsbi0xLC1uKTt9dmFyIG89ci0xLHM9MSxhPTA7Zm9yKHRoaXNbZStvXT0yNTUmdDstLW8+PTAmJihzKj0yNTYpOyl0PDAmJmE9PT0wJiZ0aGlzW2UrbysxXSE9PTAmJihhPTEpLHRoaXNbZStvXT0odC9zPj4wKS1hJjI1NTtyZXR1cm4gZStyfSxrLnByb3RvdHlwZS53cml0ZUludDg9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0PSt0LGU+Pj49MCxyfHxQZSh0aGlzLHQsZSwxLDEyNywtMTI4KSx0PDAmJih0PTI1NSt0KzEpLHRoaXNbZV09MjU1JnQsZSsxfSxrLnByb3RvdHlwZS53cml0ZUludDE2TEU9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0PSt0LGU+Pj49MCxyfHxQZSh0aGlzLHQsZSwyLDMyNzY3LC0zMjc2OCksdGhpc1tlXT0yNTUmdCx0aGlzW2UrMV09dD4+PjgsZSsyfSxrLnByb3RvdHlwZS53cml0ZUludDE2QkU9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0PSt0LGU+Pj49MCxyfHxQZSh0aGlzLHQsZSwyLDMyNzY3LC0zMjc2OCksdGhpc1tlXT10Pj4+OCx0aGlzW2UrMV09MjU1JnQsZSsyfSxrLnByb3RvdHlwZS53cml0ZUludDMyTEU9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB0PSt0LGU+Pj49MCxyfHxQZSh0aGlzLHQsZSw0LDIxNDc0ODM2NDcsLTIxNDc0ODM2NDgpLHRoaXNbZV09MjU1JnQsdGhpc1tlKzFdPXQ+Pj44LHRoaXNbZSsyXT10Pj4+MTYsdGhpc1tlKzNdPXQ+Pj4yNCxlKzR9LGsucHJvdG90eXBlLndyaXRlSW50MzJCRT1mdW5jdGlvbih0LGUscil7cmV0dXJuIHQ9K3QsZT4+Pj0wLHJ8fFBlKHRoaXMsdCxlLDQsMjE0NzQ4MzY0NywtMjE0NzQ4MzY0OCksdDwwJiYodD00Mjk0OTY3Mjk1K3QrMSksdGhpc1tlXT10Pj4+MjQsdGhpc1tlKzFdPXQ+Pj4xNix0aGlzW2UrMl09dD4+PjgsdGhpc1tlKzNdPTI1NSZ0LGUrNH0say5wcm90b3R5cGUud3JpdGVGbG9hdExFPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gU2ModGhpcyx0LGUsITAscil9LGsucHJvdG90eXBlLndyaXRlRmxvYXRCRT1mdW5jdGlvbih0LGUscil7cmV0dXJuIFNjKHRoaXMsdCxlLCExLHIpfSxrLnByb3RvdHlwZS53cml0ZURvdWJsZUxFPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gQWModGhpcyx0LGUsITAscil9LGsucHJvdG90eXBlLndyaXRlRG91YmxlQkU9ZnVuY3Rpb24odCxlLHIpe3JldHVybiBBYyh0aGlzLHQsZSwhMSxyKX0say5wcm90b3R5cGUuY29weT1mdW5jdGlvbih0LGUscixpKXtpZighay5pc0J1ZmZlcih0KSl0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgc2hvdWxkIGJlIGEgQnVmZmVyXCIpO2lmKHJ8fChyPTApLGl8fGk9PT0wfHwoaT10aGlzLmxlbmd0aCksZT49dC5sZW5ndGgmJihlPXQubGVuZ3RoKSxlfHwoZT0wKSxpPjAmJmk8ciYmKGk9ciksaT09PXJ8fHQubGVuZ3RoPT09MHx8dGhpcy5sZW5ndGg9PT0wKXJldHVybiAwO2lmKGU8MCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcInRhcmdldFN0YXJ0IG91dCBvZiBib3VuZHNcIik7aWYocjwwfHxyPj10aGlzLmxlbmd0aCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIkluZGV4IG91dCBvZiByYW5nZVwiKTtpZihpPDApdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJzb3VyY2VFbmQgb3V0IG9mIGJvdW5kc1wiKTtpPnRoaXMubGVuZ3RoJiYoaT10aGlzLmxlbmd0aCksdC5sZW5ndGgtZTxpLXImJihpPXQubGVuZ3RoLWUrcik7dmFyIG49aS1yO2lmKHRoaXM9PT10JiZ0eXBlb2YgVWludDhBcnJheS5wcm90b3R5cGUuY29weVdpdGhpbj09XCJmdW5jdGlvblwiKXRoaXMuY29weVdpdGhpbihlLHIsaSk7ZWxzZSBpZih0aGlzPT09dCYmcjxlJiZlPGkpZm9yKHZhciBvPW4tMTtvPj0wOy0tbyl0W28rZV09dGhpc1tvK3JdO2Vsc2UgVWludDhBcnJheS5wcm90b3R5cGUuc2V0LmNhbGwodCx0aGlzLnN1YmFycmF5KHIsaSksZSk7cmV0dXJuIG59LGsucHJvdG90eXBlLmZpbGw9ZnVuY3Rpb24odCxlLHIsaSl7aWYodHlwZW9mIHQ9PVwic3RyaW5nXCIpe2lmKHR5cGVvZiBlPT1cInN0cmluZ1wiPyhpPWUsZT0wLHI9dGhpcy5sZW5ndGgpOnR5cGVvZiByPT1cInN0cmluZ1wiJiYoaT1yLHI9dGhpcy5sZW5ndGgpLGkhPT12b2lkIDAmJnR5cGVvZiBpIT1cInN0cmluZ1wiKXRocm93IG5ldyBUeXBlRXJyb3IoXCJlbmNvZGluZyBtdXN0IGJlIGEgc3RyaW5nXCIpO2lmKHR5cGVvZiBpPT1cInN0cmluZ1wiJiYhay5pc0VuY29kaW5nKGkpKXRocm93IG5ldyBUeXBlRXJyb3IoXCJVbmtub3duIGVuY29kaW5nOiBcIitpKTtpZih0Lmxlbmd0aD09PTEpe3ZhciBuPXQuY2hhckNvZGVBdCgwKTsoaT09PVwidXRmOFwiJiZuPDEyOHx8aT09PVwibGF0aW4xXCIpJiYodD1uKTt9fWVsc2UgdHlwZW9mIHQ9PVwibnVtYmVyXCI/dCY9MjU1OnR5cGVvZiB0PT1cImJvb2xlYW5cIiYmKHQ9TnVtYmVyKHQpKTtpZihlPDB8fHRoaXMubGVuZ3RoPGV8fHRoaXMubGVuZ3RoPHIpdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJPdXQgb2YgcmFuZ2UgaW5kZXhcIik7aWYocjw9ZSlyZXR1cm4gdGhpczt2YXIgbztpZihlPj4+PTAscj1yPT09dm9pZCAwP3RoaXMubGVuZ3RoOnI+Pj4wLHR8fCh0PTApLHR5cGVvZiB0PT1cIm51bWJlclwiKWZvcihvPWU7bzxyOysrbyl0aGlzW29dPXQ7ZWxzZSB7dmFyIHM9ay5pc0J1ZmZlcih0KT90OmsuZnJvbSh0LGkpLGE9cy5sZW5ndGg7aWYoYT09PTApdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIHZhbHVlIFwiJyt0KydcIiBpcyBpbnZhbGlkIGZvciBhcmd1bWVudCBcInZhbHVlXCInKTtmb3Iobz0wO288ci1lOysrbyl0aGlzW28rZV09c1tvJWFdO31yZXR1cm4gdGhpc307Unc9L1teKy8wLTlBLVphLXotX10vZztDdz1mdW5jdGlvbigpe2Zvcih2YXIgdD1uZXcgQXJyYXkoMjU2KSxlPTA7ZTwxNjsrK2UpZm9yKHZhciByPTE2KmUsaT0wO2k8MTY7KytpKXRbcitpXT1cIjAxMjM0NTY3ODlhYmNkZWZcIltlXStcIjAxMjM0NTY3ODlhYmNkZWZcIltpXTtyZXR1cm4gdH0oKTtTdC5CdWZmZXI7U3QuSU5TUEVDVF9NQVhfQllURVM7U3Qua01heExlbmd0aDthbj17fSxsbj1TdCxpdD1sbi5CdWZmZXI7aXQuZnJvbSYmaXQuYWxsb2MmJml0LmFsbG9jVW5zYWZlJiZpdC5hbGxvY1Vuc2FmZVNsb3c/YW49bG46KEljKGxuLGFuKSxhbi5CdWZmZXI9b3IpLG9yLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGl0LnByb3RvdHlwZSksSWMoaXQsb3IpLG9yLmZyb209ZnVuY3Rpb24odCxlLHIpe2lmKHR5cGVvZiB0PT1cIm51bWJlclwiKXRocm93IG5ldyBUeXBlRXJyb3IoXCJBcmd1bWVudCBtdXN0IG5vdCBiZSBhIG51bWJlclwiKTtyZXR1cm4gaXQodCxlLHIpfSxvci5hbGxvYz1mdW5jdGlvbih0LGUscil7aWYodHlwZW9mIHQhPVwibnVtYmVyXCIpdGhyb3cgbmV3IFR5cGVFcnJvcihcIkFyZ3VtZW50IG11c3QgYmUgYSBudW1iZXJcIik7dmFyIGk9aXQodCk7cmV0dXJuIGUhPT12b2lkIDA/dHlwZW9mIHI9PVwic3RyaW5nXCI/aS5maWxsKGUscik6aS5maWxsKGUpOmkuZmlsbCgwKSxpfSxvci5hbGxvY1Vuc2FmZT1mdW5jdGlvbih0KXtpZih0eXBlb2YgdCE9XCJudW1iZXJcIil0aHJvdyBuZXcgVHlwZUVycm9yKFwiQXJndW1lbnQgbXVzdCBiZSBhIG51bWJlclwiKTtyZXR1cm4gaXQodCl9LG9yLmFsbG9jVW5zYWZlU2xvdz1mdW5jdGlvbih0KXtpZih0eXBlb2YgdCE9XCJudW1iZXJcIil0aHJvdyBuZXcgVHlwZUVycm9yKFwiQXJndW1lbnQgbXVzdCBiZSBhIG51bWJlclwiKTtyZXR1cm4gbG4uU2xvd0J1ZmZlcih0KX07Qnc9YW4sYXI9e30senM9QncuQnVmZmVyLFRjPXpzLmlzRW5jb2Rpbmd8fGZ1bmN0aW9uKHQpe3N3aXRjaCgodD1cIlwiK3QpJiZ0LnRvTG93ZXJDYXNlKCkpe2Nhc2VcImhleFwiOmNhc2VcInV0ZjhcIjpjYXNlXCJ1dGYtOFwiOmNhc2VcImFzY2lpXCI6Y2FzZVwiYmluYXJ5XCI6Y2FzZVwiYmFzZTY0XCI6Y2FzZVwidWNzMlwiOmNhc2VcInVjcy0yXCI6Y2FzZVwidXRmMTZsZVwiOmNhc2VcInV0Zi0xNmxlXCI6Y2FzZVwicmF3XCI6cmV0dXJuICEwO2RlZmF1bHQ6cmV0dXJuICExfX07YXIuU3RyaW5nRGVjb2Rlcj1oaSxoaS5wcm90b3R5cGUud3JpdGU9ZnVuY3Rpb24odCl7aWYodC5sZW5ndGg9PT0wKXJldHVybiBcIlwiO3ZhciBlLHI7aWYodGhpcy5sYXN0TmVlZCl7aWYoKGU9dGhpcy5maWxsTGFzdCh0KSk9PT12b2lkIDApcmV0dXJuIFwiXCI7cj10aGlzLmxhc3ROZWVkLHRoaXMubGFzdE5lZWQ9MDt9ZWxzZSByPTA7cmV0dXJuIHI8dC5sZW5ndGg/ZT9lK3RoaXMudGV4dCh0LHIpOnRoaXMudGV4dCh0LHIpOmV8fFwiXCJ9LGhpLnByb3RvdHlwZS5lbmQ9ZnVuY3Rpb24odCl7dmFyIGU9dCYmdC5sZW5ndGg/dGhpcy53cml0ZSh0KTpcIlwiO3JldHVybiB0aGlzLmxhc3ROZWVkP2UrXCJcXHVGRkZEXCI6ZX0saGkucHJvdG90eXBlLnRleHQ9ZnVuY3Rpb24odCxlKXt2YXIgcj1mdW5jdGlvbihuLG8scyl7dmFyIGE9by5sZW5ndGgtMTtpZihhPHMpcmV0dXJuIDA7dmFyIHU9V3Mob1thXSk7cmV0dXJuIHU+PTA/KHU+MCYmKG4ubGFzdE5lZWQ9dS0xKSx1KTotLWE8c3x8dT09PS0yPzA6KHU9V3Mob1thXSkpPj0wPyh1PjAmJihuLmxhc3ROZWVkPXUtMiksdSk6LS1hPHN8fHU9PT0tMj8wOih1PVdzKG9bYV0pKT49MD8odT4wJiYodT09PTI/dT0wOm4ubGFzdE5lZWQ9dS0zKSx1KTowfSh0aGlzLHQsZSk7aWYoIXRoaXMubGFzdE5lZWQpcmV0dXJuIHQudG9TdHJpbmcoXCJ1dGY4XCIsZSk7dGhpcy5sYXN0VG90YWw9cjt2YXIgaT10Lmxlbmd0aC0oci10aGlzLmxhc3ROZWVkKTtyZXR1cm4gdC5jb3B5KHRoaXMubGFzdENoYXIsMCxpKSx0LnRvU3RyaW5nKFwidXRmOFwiLGUsaSl9LGhpLnByb3RvdHlwZS5maWxsTGFzdD1mdW5jdGlvbih0KXtpZih0aGlzLmxhc3ROZWVkPD10Lmxlbmd0aClyZXR1cm4gdC5jb3B5KHRoaXMubGFzdENoYXIsdGhpcy5sYXN0VG90YWwtdGhpcy5sYXN0TmVlZCwwLHRoaXMubGFzdE5lZWQpLHRoaXMubGFzdENoYXIudG9TdHJpbmcodGhpcy5lbmNvZGluZywwLHRoaXMubGFzdFRvdGFsKTt0LmNvcHkodGhpcy5sYXN0Q2hhcix0aGlzLmxhc3RUb3RhbC10aGlzLmxhc3ROZWVkLDAsdC5sZW5ndGgpLHRoaXMubGFzdE5lZWQtPXQubGVuZ3RoO307YXIuU3RyaW5nRGVjb2Rlcjthci5TdHJpbmdEZWNvZGVyO30pO3ZhciBMYz17fTtRdChMYyx7U3RyaW5nRGVjb2RlcjooKT0+TncsZGVmYXVsdDooKT0+YXJ9KTt2YXIgTncsVWM9d2UoKCk9Pnt2KCk7bSgpO18oKTtRcygpO1FzKCk7Tnc9YXIuU3RyaW5nRGVjb2Rlcjt9KTt2YXIgWXM9TSgoRjIsamMpPT57digpO20oKTtfKCk7dmFyIE5jPVV0KCkse1Byb21pc2VQcm90b3R5cGVUaGVuOnF3LFN5bWJvbEFzeW5jSXRlcmF0b3I6cWMsU3ltYm9sSXRlcmF0b3I6RGN9PWNlKCkse0J1ZmZlcjpEd309KHllKCksWChfZSkpLHtFUlJfSU5WQUxJRF9BUkdfVFlQRTpqdyxFUlJfU1RSRUFNX05VTExfVkFMVUVTOkZ3fT1TZSgpLmNvZGVzO2Z1bmN0aW9uIFd3KHQsZSxyKXtsZXQgaTtpZih0eXBlb2YgZT09XCJzdHJpbmdcInx8ZSBpbnN0YW5jZW9mIER3KXJldHVybiBuZXcgdCh7b2JqZWN0TW9kZTohMCwuLi5yLHJlYWQoKXt0aGlzLnB1c2goZSksdGhpcy5wdXNoKG51bGwpO319KTtsZXQgbjtpZihlJiZlW3FjXSluPSEwLGk9ZVtxY10oKTtlbHNlIGlmKGUmJmVbRGNdKW49ITEsaT1lW0RjXSgpO2Vsc2UgdGhyb3cgbmV3IGp3KFwiaXRlcmFibGVcIixbXCJJdGVyYWJsZVwiXSxlKTtsZXQgbz1uZXcgdCh7b2JqZWN0TW9kZTohMCxoaWdoV2F0ZXJNYXJrOjEsLi4ucn0pLHM9ITE7by5fcmVhZD1mdW5jdGlvbigpe3N8fChzPSEwLHUoKSk7fSxvLl9kZXN0cm95PWZ1bmN0aW9uKGMsaCl7cXcoYShjKSwoKT0+TmMubmV4dFRpY2soaCxjKSxkPT5OYy5uZXh0VGljayhoLGR8fGMpKTt9O2FzeW5jIGZ1bmN0aW9uIGEoYyl7bGV0IGg9YyE9bnVsbCxkPXR5cGVvZiBpLnRocm93PT1cImZ1bmN0aW9uXCI7aWYoaCYmZCl7bGV0e3ZhbHVlOmcsZG9uZTp5fT1hd2FpdCBpLnRocm93KGMpO2lmKGF3YWl0IGcseSlyZXR1cm59aWYodHlwZW9mIGkucmV0dXJuPT1cImZ1bmN0aW9uXCIpe2xldHt2YWx1ZTpnfT1hd2FpdCBpLnJldHVybigpO2F3YWl0IGc7fX1hc3luYyBmdW5jdGlvbiB1KCl7Zm9yKDs7KXt0cnl7bGV0e3ZhbHVlOmMsZG9uZTpofT1uP2F3YWl0IGkubmV4dCgpOmkubmV4dCgpO2lmKGgpby5wdXNoKG51bGwpO2Vsc2Uge2xldCBkPWMmJnR5cGVvZiBjLnRoZW49PVwiZnVuY3Rpb25cIj9hd2FpdCBjOmM7aWYoZD09PW51bGwpdGhyb3cgcz0hMSxuZXcgRnc7aWYoby5wdXNoKGQpKWNvbnRpbnVlO3M9ITE7fX1jYXRjaChjKXtvLmRlc3Ryb3koYyk7fWJyZWFrfX1yZXR1cm4gb31qYy5leHBvcnRzPVd3O30pO3ZhciBkaT1NKChKMixaYyk9Pnt2KCk7bSgpO18oKTt2YXIgSGU9VXQoKSx7QXJyYXlQcm90b3R5cGVJbmRleE9mOiR3LE51bWJlcklzSW50ZWdlcjpIdyxOdW1iZXJJc05hTjpWdyxOdW1iZXJQYXJzZUludDp6dyxPYmplY3REZWZpbmVQcm9wZXJ0aWVzOiRjLE9iamVjdEtleXM6S3csT2JqZWN0U2V0UHJvdG90eXBlT2Y6SGMsUHJvbWlzZTpHdyxTYWZlU2V0OlF3LFN5bWJvbEFzeW5jSXRlcmF0b3I6WXcsU3ltYm9sOkp3fT1jZSgpO1pjLmV4cG9ydHM9RjtGLlJlYWRhYmxlU3RhdGU9cm87dmFye0V2ZW50RW1pdHRlcjpYd309KGlyKCksWChycikpLHtTdHJlYW06cXQscHJlcGVuZExpc3RlbmVyOlp3fT10bigpLHtCdWZmZXI6SnN9PSh5ZSgpLFgoX2UpKSx7YWRkQWJvcnRTaWduYWw6ZV99PWNpKCksdF89bXQoKSxIPUplKCkuZGVidWdsb2coXCJzdHJlYW1cIix0PT57SD10O30pLHJfPWRjKCksRHI9dHIoKSx7Z2V0SGlnaFdhdGVyTWFyazppXyxnZXREZWZhdWx0SGlnaFdhdGVyTWFyazpuX309c24oKSx7YWdncmVnYXRlVHdvRXJyb3JzOkZjLGNvZGVzOntFUlJfSU5WQUxJRF9BUkdfVFlQRTpzXyxFUlJfTUVUSE9EX05PVF9JTVBMRU1FTlRFRDpvXyxFUlJfT1VUX09GX1JBTkdFOmFfLEVSUl9TVFJFQU1fUFVTSF9BRlRFUl9FT0Y6bF8sRVJSX1NUUkVBTV9VTlNISUZUX0FGVEVSX0VORF9FVkVOVDp1X319PVNlKCkse3ZhbGlkYXRlT2JqZWN0OmZffT1maSgpLGxyPUp3KFwia1BhdXNlZFwiKSx7U3RyaW5nRGVjb2RlcjpWY309KFVjKCksWChMYykpLGNfPVlzKCk7SGMoRi5wcm90b3R5cGUscXQucHJvdG90eXBlKTtIYyhGLHF0KTt2YXIgWHM9KCk9Pnt9LHtlcnJvck9yRGVzdHJveTpxcn09RHI7ZnVuY3Rpb24gcm8odCxlLHIpe3R5cGVvZiByIT1cImJvb2xlYW5cIiYmKHI9ZSBpbnN0YW5jZW9mIG50KCkpLHRoaXMub2JqZWN0TW9kZT0hISh0JiZ0Lm9iamVjdE1vZGUpLHImJih0aGlzLm9iamVjdE1vZGU9dGhpcy5vYmplY3RNb2RlfHwhISh0JiZ0LnJlYWRhYmxlT2JqZWN0TW9kZSkpLHRoaXMuaGlnaFdhdGVyTWFyaz10P2lfKHRoaXMsdCxcInJlYWRhYmxlSGlnaFdhdGVyTWFya1wiLHIpOm5fKCExKSx0aGlzLmJ1ZmZlcj1uZXcgcl8sdGhpcy5sZW5ndGg9MCx0aGlzLnBpcGVzPVtdLHRoaXMuZmxvd2luZz1udWxsLHRoaXMuZW5kZWQ9ITEsdGhpcy5lbmRFbWl0dGVkPSExLHRoaXMucmVhZGluZz0hMSx0aGlzLmNvbnN0cnVjdGVkPSEwLHRoaXMuc3luYz0hMCx0aGlzLm5lZWRSZWFkYWJsZT0hMSx0aGlzLmVtaXR0ZWRSZWFkYWJsZT0hMSx0aGlzLnJlYWRhYmxlTGlzdGVuaW5nPSExLHRoaXMucmVzdW1lU2NoZWR1bGVkPSExLHRoaXNbbHJdPW51bGwsdGhpcy5lcnJvckVtaXR0ZWQ9ITEsdGhpcy5lbWl0Q2xvc2U9IXR8fHQuZW1pdENsb3NlIT09ITEsdGhpcy5hdXRvRGVzdHJveT0hdHx8dC5hdXRvRGVzdHJveSE9PSExLHRoaXMuZGVzdHJveWVkPSExLHRoaXMuZXJyb3JlZD1udWxsLHRoaXMuY2xvc2VkPSExLHRoaXMuY2xvc2VFbWl0dGVkPSExLHRoaXMuZGVmYXVsdEVuY29kaW5nPXQmJnQuZGVmYXVsdEVuY29kaW5nfHxcInV0ZjhcIix0aGlzLmF3YWl0RHJhaW5Xcml0ZXJzPW51bGwsdGhpcy5tdWx0aUF3YWl0RHJhaW49ITEsdGhpcy5yZWFkaW5nTW9yZT0hMSx0aGlzLmRhdGFFbWl0dGVkPSExLHRoaXMuZGVjb2Rlcj1udWxsLHRoaXMuZW5jb2Rpbmc9bnVsbCx0JiZ0LmVuY29kaW5nJiYodGhpcy5kZWNvZGVyPW5ldyBWYyh0LmVuY29kaW5nKSx0aGlzLmVuY29kaW5nPXQuZW5jb2RpbmcpO31mdW5jdGlvbiBGKHQpe2lmKCEodGhpcyBpbnN0YW5jZW9mIEYpKXJldHVybiBuZXcgRih0KTtsZXQgZT10aGlzIGluc3RhbmNlb2YgbnQoKTt0aGlzLl9yZWFkYWJsZVN0YXRlPW5ldyBybyh0LHRoaXMsZSksdCYmKHR5cGVvZiB0LnJlYWQ9PVwiZnVuY3Rpb25cIiYmKHRoaXMuX3JlYWQ9dC5yZWFkKSx0eXBlb2YgdC5kZXN0cm95PT1cImZ1bmN0aW9uXCImJih0aGlzLl9kZXN0cm95PXQuZGVzdHJveSksdHlwZW9mIHQuY29uc3RydWN0PT1cImZ1bmN0aW9uXCImJih0aGlzLl9jb25zdHJ1Y3Q9dC5jb25zdHJ1Y3QpLHQuc2lnbmFsJiYhZSYmZV8odC5zaWduYWwsdGhpcykpLHF0LmNhbGwodGhpcyx0KSxEci5jb25zdHJ1Y3QodGhpcywoKT0+e3RoaXMuX3JlYWRhYmxlU3RhdGUubmVlZFJlYWRhYmxlJiZmbih0aGlzLHRoaXMuX3JlYWRhYmxlU3RhdGUpO30pO31GLnByb3RvdHlwZS5kZXN0cm95PURyLmRlc3Ryb3k7Ri5wcm90b3R5cGUuX3VuZGVzdHJveT1Eci51bmRlc3Ryb3k7Ri5wcm90b3R5cGUuX2Rlc3Ryb3k9ZnVuY3Rpb24odCxlKXtlKHQpO307Ri5wcm90b3R5cGVbWHcuY2FwdHVyZVJlamVjdGlvblN5bWJvbF09ZnVuY3Rpb24odCl7dGhpcy5kZXN0cm95KHQpO307Ri5wcm90b3R5cGUucHVzaD1mdW5jdGlvbih0LGUpe3JldHVybiB6Yyh0aGlzLHQsZSwhMSl9O0YucHJvdG90eXBlLnVuc2hpZnQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gemModGhpcyx0LGUsITApfTtmdW5jdGlvbiB6Yyh0LGUscixpKXtIKFwicmVhZGFibGVBZGRDaHVua1wiLGUpO2xldCBuPXQuX3JlYWRhYmxlU3RhdGUsbztpZihuLm9iamVjdE1vZGV8fCh0eXBlb2YgZT09XCJzdHJpbmdcIj8ocj1yfHxuLmRlZmF1bHRFbmNvZGluZyxuLmVuY29kaW5nIT09ciYmKGkmJm4uZW5jb2Rpbmc/ZT1Kcy5mcm9tKGUscikudG9TdHJpbmcobi5lbmNvZGluZyk6KGU9SnMuZnJvbShlLHIpLHI9XCJcIikpKTplIGluc3RhbmNlb2YgSnM/cj1cIlwiOnF0Ll9pc1VpbnQ4QXJyYXkoZSk/KGU9cXQuX3VpbnQ4QXJyYXlUb0J1ZmZlcihlKSxyPVwiXCIpOmUhPW51bGwmJihvPW5ldyBzXyhcImNodW5rXCIsW1wic3RyaW5nXCIsXCJCdWZmZXJcIixcIlVpbnQ4QXJyYXlcIl0sZSkpKSxvKXFyKHQsbyk7ZWxzZSBpZihlPT09bnVsbCluLnJlYWRpbmc9ITEscF8odCxuKTtlbHNlIGlmKG4ub2JqZWN0TW9kZXx8ZSYmZS5sZW5ndGg+MClpZihpKWlmKG4uZW5kRW1pdHRlZClxcih0LG5ldyB1Xyk7ZWxzZSB7aWYobi5kZXN0cm95ZWR8fG4uZXJyb3JlZClyZXR1cm4gITE7WnModCxuLGUsITApO31lbHNlIGlmKG4uZW5kZWQpcXIodCxuZXcgbF8pO2Vsc2Uge2lmKG4uZGVzdHJveWVkfHxuLmVycm9yZWQpcmV0dXJuICExO24ucmVhZGluZz0hMSxuLmRlY29kZXImJiFyPyhlPW4uZGVjb2Rlci53cml0ZShlKSxuLm9iamVjdE1vZGV8fGUubGVuZ3RoIT09MD9acyh0LG4sZSwhMSk6Zm4odCxuKSk6WnModCxuLGUsITEpO31lbHNlIGl8fChuLnJlYWRpbmc9ITEsZm4odCxuKSk7cmV0dXJuICFuLmVuZGVkJiYobi5sZW5ndGg8bi5oaWdoV2F0ZXJNYXJrfHxuLmxlbmd0aD09PTApfWZ1bmN0aW9uIFpzKHQsZSxyLGkpe2UuZmxvd2luZyYmZS5sZW5ndGg9PT0wJiYhZS5zeW5jJiZ0Lmxpc3RlbmVyQ291bnQoXCJkYXRhXCIpPjA/KGUubXVsdGlBd2FpdERyYWluP2UuYXdhaXREcmFpbldyaXRlcnMuY2xlYXIoKTplLmF3YWl0RHJhaW5Xcml0ZXJzPW51bGwsZS5kYXRhRW1pdHRlZD0hMCx0LmVtaXQoXCJkYXRhXCIscikpOihlLmxlbmd0aCs9ZS5vYmplY3RNb2RlPzE6ci5sZW5ndGgsaT9lLmJ1ZmZlci51bnNoaWZ0KHIpOmUuYnVmZmVyLnB1c2gociksZS5uZWVkUmVhZGFibGUmJmNuKHQpKSxmbih0LGUpO31GLnByb3RvdHlwZS5pc1BhdXNlZD1mdW5jdGlvbigpe2xldCB0PXRoaXMuX3JlYWRhYmxlU3RhdGU7cmV0dXJuIHRbbHJdPT09ITB8fHQuZmxvd2luZz09PSExfTtGLnByb3RvdHlwZS5zZXRFbmNvZGluZz1mdW5jdGlvbih0KXtsZXQgZT1uZXcgVmModCk7dGhpcy5fcmVhZGFibGVTdGF0ZS5kZWNvZGVyPWUsdGhpcy5fcmVhZGFibGVTdGF0ZS5lbmNvZGluZz10aGlzLl9yZWFkYWJsZVN0YXRlLmRlY29kZXIuZW5jb2Rpbmc7bGV0IHI9dGhpcy5fcmVhZGFibGVTdGF0ZS5idWZmZXIsaT1cIlwiO2ZvcihsZXQgbiBvZiByKWkrPWUud3JpdGUobik7cmV0dXJuIHIuY2xlYXIoKSxpIT09XCJcIiYmci5wdXNoKGkpLHRoaXMuX3JlYWRhYmxlU3RhdGUubGVuZ3RoPWkubGVuZ3RoLHRoaXN9O3ZhciBoXz0xMDczNzQxODI0O2Z1bmN0aW9uIGRfKHQpe2lmKHQ+aF8pdGhyb3cgbmV3IGFfKFwic2l6ZVwiLFwiPD0gMUdpQlwiLHQpO3JldHVybiB0LS0sdHw9dD4+PjEsdHw9dD4+PjIsdHw9dD4+PjQsdHw9dD4+PjgsdHw9dD4+PjE2LHQrKyx0fWZ1bmN0aW9uIFdjKHQsZSl7cmV0dXJuIHQ8PTB8fGUubGVuZ3RoPT09MCYmZS5lbmRlZD8wOmUub2JqZWN0TW9kZT8xOlZ3KHQpP2UuZmxvd2luZyYmZS5sZW5ndGg/ZS5idWZmZXIuZmlyc3QoKS5sZW5ndGg6ZS5sZW5ndGg6dDw9ZS5sZW5ndGg/dDplLmVuZGVkP2UubGVuZ3RoOjB9Ri5wcm90b3R5cGUucmVhZD1mdW5jdGlvbih0KXtIKFwicmVhZFwiLHQpLHQ9PT12b2lkIDA/dD1OYU46SHcodCl8fCh0PXp3KHQsMTApKTtsZXQgZT10aGlzLl9yZWFkYWJsZVN0YXRlLHI9dDtpZih0PmUuaGlnaFdhdGVyTWFyayYmKGUuaGlnaFdhdGVyTWFyaz1kXyh0KSksdCE9PTAmJihlLmVtaXR0ZWRSZWFkYWJsZT0hMSksdD09PTAmJmUubmVlZFJlYWRhYmxlJiYoKGUuaGlnaFdhdGVyTWFyayE9PTA/ZS5sZW5ndGg+PWUuaGlnaFdhdGVyTWFyazplLmxlbmd0aD4wKXx8ZS5lbmRlZCkpcmV0dXJuIEgoXCJyZWFkOiBlbWl0UmVhZGFibGVcIixlLmxlbmd0aCxlLmVuZGVkKSxlLmxlbmd0aD09PTAmJmUuZW5kZWQ/ZW8odGhpcyk6Y24odGhpcyksbnVsbDtpZih0PVdjKHQsZSksdD09PTAmJmUuZW5kZWQpcmV0dXJuIGUubGVuZ3RoPT09MCYmZW8odGhpcyksbnVsbDtsZXQgaT1lLm5lZWRSZWFkYWJsZTtpZihIKFwibmVlZCByZWFkYWJsZVwiLGkpLChlLmxlbmd0aD09PTB8fGUubGVuZ3RoLXQ8ZS5oaWdoV2F0ZXJNYXJrKSYmKGk9ITAsSChcImxlbmd0aCBsZXNzIHRoYW4gd2F0ZXJtYXJrXCIsaSkpLGUuZW5kZWR8fGUucmVhZGluZ3x8ZS5kZXN0cm95ZWR8fGUuZXJyb3JlZHx8IWUuY29uc3RydWN0ZWQpaT0hMSxIKFwicmVhZGluZywgZW5kZWQgb3IgY29uc3RydWN0aW5nXCIsaSk7ZWxzZSBpZihpKXtIKFwiZG8gcmVhZFwiKSxlLnJlYWRpbmc9ITAsZS5zeW5jPSEwLGUubGVuZ3RoPT09MCYmKGUubmVlZFJlYWRhYmxlPSEwKTt0cnl7dGhpcy5fcmVhZChlLmhpZ2hXYXRlck1hcmspO31jYXRjaChvKXtxcih0aGlzLG8pO31lLnN5bmM9ITEsZS5yZWFkaW5nfHwodD1XYyhyLGUpKTt9bGV0IG47cmV0dXJuIHQ+MD9uPUpjKHQsZSk6bj1udWxsLG49PT1udWxsPyhlLm5lZWRSZWFkYWJsZT1lLmxlbmd0aDw9ZS5oaWdoV2F0ZXJNYXJrLHQ9MCk6KGUubGVuZ3RoLT10LGUubXVsdGlBd2FpdERyYWluP2UuYXdhaXREcmFpbldyaXRlcnMuY2xlYXIoKTplLmF3YWl0RHJhaW5Xcml0ZXJzPW51bGwpLGUubGVuZ3RoPT09MCYmKGUuZW5kZWR8fChlLm5lZWRSZWFkYWJsZT0hMCksciE9PXQmJmUuZW5kZWQmJmVvKHRoaXMpKSxuIT09bnVsbCYmIWUuZXJyb3JFbWl0dGVkJiYhZS5jbG9zZUVtaXR0ZWQmJihlLmRhdGFFbWl0dGVkPSEwLHRoaXMuZW1pdChcImRhdGFcIixuKSksbn07ZnVuY3Rpb24gcF8odCxlKXtpZihIKFwib25Fb2ZDaHVua1wiKSwhZS5lbmRlZCl7aWYoZS5kZWNvZGVyKXtsZXQgcj1lLmRlY29kZXIuZW5kKCk7ciYmci5sZW5ndGgmJihlLmJ1ZmZlci5wdXNoKHIpLGUubGVuZ3RoKz1lLm9iamVjdE1vZGU/MTpyLmxlbmd0aCk7fWUuZW5kZWQ9ITAsZS5zeW5jP2NuKHQpOihlLm5lZWRSZWFkYWJsZT0hMSxlLmVtaXR0ZWRSZWFkYWJsZT0hMCxLYyh0KSk7fX1mdW5jdGlvbiBjbih0KXtsZXQgZT10Ll9yZWFkYWJsZVN0YXRlO0goXCJlbWl0UmVhZGFibGVcIixlLm5lZWRSZWFkYWJsZSxlLmVtaXR0ZWRSZWFkYWJsZSksZS5uZWVkUmVhZGFibGU9ITEsZS5lbWl0dGVkUmVhZGFibGV8fChIKFwiZW1pdFJlYWRhYmxlXCIsZS5mbG93aW5nKSxlLmVtaXR0ZWRSZWFkYWJsZT0hMCxIZS5uZXh0VGljayhLYyx0KSk7fWZ1bmN0aW9uIEtjKHQpe2xldCBlPXQuX3JlYWRhYmxlU3RhdGU7SChcImVtaXRSZWFkYWJsZV9cIixlLmRlc3Ryb3llZCxlLmxlbmd0aCxlLmVuZGVkKSwhZS5kZXN0cm95ZWQmJiFlLmVycm9yZWQmJihlLmxlbmd0aHx8ZS5lbmRlZCkmJih0LmVtaXQoXCJyZWFkYWJsZVwiKSxlLmVtaXR0ZWRSZWFkYWJsZT0hMSksZS5uZWVkUmVhZGFibGU9IWUuZmxvd2luZyYmIWUuZW5kZWQmJmUubGVuZ3RoPD1lLmhpZ2hXYXRlck1hcmssUWModCk7fWZ1bmN0aW9uIGZuKHQsZSl7IWUucmVhZGluZ01vcmUmJmUuY29uc3RydWN0ZWQmJihlLnJlYWRpbmdNb3JlPSEwLEhlLm5leHRUaWNrKGdfLHQsZSkpO31mdW5jdGlvbiBnXyh0LGUpe2Zvcig7IWUucmVhZGluZyYmIWUuZW5kZWQmJihlLmxlbmd0aDxlLmhpZ2hXYXRlck1hcmt8fGUuZmxvd2luZyYmZS5sZW5ndGg9PT0wKTspe2xldCByPWUubGVuZ3RoO2lmKEgoXCJtYXliZVJlYWRNb3JlIHJlYWQgMFwiKSx0LnJlYWQoMCkscj09PWUubGVuZ3RoKWJyZWFrfWUucmVhZGluZ01vcmU9ITE7fUYucHJvdG90eXBlLl9yZWFkPWZ1bmN0aW9uKHQpe3Rocm93IG5ldyBvXyhcIl9yZWFkKClcIil9O0YucHJvdG90eXBlLnBpcGU9ZnVuY3Rpb24odCxlKXtsZXQgcj10aGlzLGk9dGhpcy5fcmVhZGFibGVTdGF0ZTtpLnBpcGVzLmxlbmd0aD09PTEmJihpLm11bHRpQXdhaXREcmFpbnx8KGkubXVsdGlBd2FpdERyYWluPSEwLGkuYXdhaXREcmFpbldyaXRlcnM9bmV3IFF3KGkuYXdhaXREcmFpbldyaXRlcnM/W2kuYXdhaXREcmFpbldyaXRlcnNdOltdKSkpLGkucGlwZXMucHVzaCh0KSxIKFwicGlwZSBjb3VudD0lZCBvcHRzPSVqXCIsaS5waXBlcy5sZW5ndGgsZSk7bGV0IG89KCFlfHxlLmVuZCE9PSExKSYmdCE9PUhlLnN0ZG91dCYmdCE9PUhlLnN0ZGVycj9hOlM7aS5lbmRFbWl0dGVkP0hlLm5leHRUaWNrKG8pOnIub25jZShcImVuZFwiLG8pLHQub24oXCJ1bnBpcGVcIixzKTtmdW5jdGlvbiBzKEksQyl7SChcIm9udW5waXBlXCIpLEk9PT1yJiZDJiZDLmhhc1VucGlwZWQ9PT0hMSYmKEMuaGFzVW5waXBlZD0hMCxoKCkpO31mdW5jdGlvbiBhKCl7SChcIm9uZW5kXCIpLHQuZW5kKCk7fWxldCB1LGM9ITE7ZnVuY3Rpb24gaCgpe0goXCJjbGVhbnVwXCIpLHQucmVtb3ZlTGlzdGVuZXIoXCJjbG9zZVwiLHcpLHQucmVtb3ZlTGlzdGVuZXIoXCJmaW5pc2hcIixFKSx1JiZ0LnJlbW92ZUxpc3RlbmVyKFwiZHJhaW5cIix1KSx0LnJlbW92ZUxpc3RlbmVyKFwiZXJyb3JcIix5KSx0LnJlbW92ZUxpc3RlbmVyKFwidW5waXBlXCIscyksci5yZW1vdmVMaXN0ZW5lcihcImVuZFwiLGEpLHIucmVtb3ZlTGlzdGVuZXIoXCJlbmRcIixTKSxyLnJlbW92ZUxpc3RlbmVyKFwiZGF0YVwiLGcpLGM9ITAsdSYmaS5hd2FpdERyYWluV3JpdGVycyYmKCF0Ll93cml0YWJsZVN0YXRlfHx0Ll93cml0YWJsZVN0YXRlLm5lZWREcmFpbikmJnUoKTt9ZnVuY3Rpb24gZCgpe2N8fChpLnBpcGVzLmxlbmd0aD09PTEmJmkucGlwZXNbMF09PT10PyhIKFwiZmFsc2Ugd3JpdGUgcmVzcG9uc2UsIHBhdXNlXCIsMCksaS5hd2FpdERyYWluV3JpdGVycz10LGkubXVsdGlBd2FpdERyYWluPSExKTppLnBpcGVzLmxlbmd0aD4xJiZpLnBpcGVzLmluY2x1ZGVzKHQpJiYoSChcImZhbHNlIHdyaXRlIHJlc3BvbnNlLCBwYXVzZVwiLGkuYXdhaXREcmFpbldyaXRlcnMuc2l6ZSksaS5hd2FpdERyYWluV3JpdGVycy5hZGQodCkpLHIucGF1c2UoKSksdXx8KHU9eV8ocix0KSx0Lm9uKFwiZHJhaW5cIix1KSk7fXIub24oXCJkYXRhXCIsZyk7ZnVuY3Rpb24gZyhJKXtIKFwib25kYXRhXCIpO2xldCBDPXQud3JpdGUoSSk7SChcImRlc3Qud3JpdGVcIixDKSxDPT09ITEmJmQoKTt9ZnVuY3Rpb24geShJKXtpZihIKFwib25lcnJvclwiLEkpLFMoKSx0LnJlbW92ZUxpc3RlbmVyKFwiZXJyb3JcIix5KSx0Lmxpc3RlbmVyQ291bnQoXCJlcnJvclwiKT09PTApe2xldCBDPXQuX3dyaXRhYmxlU3RhdGV8fHQuX3JlYWRhYmxlU3RhdGU7QyYmIUMuZXJyb3JFbWl0dGVkP3FyKHQsSSk6dC5lbWl0KFwiZXJyb3JcIixJKTt9fVp3KHQsXCJlcnJvclwiLHkpO2Z1bmN0aW9uIHcoKXt0LnJlbW92ZUxpc3RlbmVyKFwiZmluaXNoXCIsRSksUygpO310Lm9uY2UoXCJjbG9zZVwiLHcpO2Z1bmN0aW9uIEUoKXtIKFwib25maW5pc2hcIiksdC5yZW1vdmVMaXN0ZW5lcihcImNsb3NlXCIsdyksUygpO310Lm9uY2UoXCJmaW5pc2hcIixFKTtmdW5jdGlvbiBTKCl7SChcInVucGlwZVwiKSxyLnVucGlwZSh0KTt9cmV0dXJuIHQuZW1pdChcInBpcGVcIixyKSx0LndyaXRhYmxlTmVlZERyYWluPT09ITA/aS5mbG93aW5nJiZkKCk6aS5mbG93aW5nfHwoSChcInBpcGUgcmVzdW1lXCIpLHIucmVzdW1lKCkpLHR9O2Z1bmN0aW9uIHlfKHQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7bGV0IGk9dC5fcmVhZGFibGVTdGF0ZTtpLmF3YWl0RHJhaW5Xcml0ZXJzPT09ZT8oSChcInBpcGVPbkRyYWluXCIsMSksaS5hd2FpdERyYWluV3JpdGVycz1udWxsKTppLm11bHRpQXdhaXREcmFpbiYmKEgoXCJwaXBlT25EcmFpblwiLGkuYXdhaXREcmFpbldyaXRlcnMuc2l6ZSksaS5hd2FpdERyYWluV3JpdGVycy5kZWxldGUoZSkpLCghaS5hd2FpdERyYWluV3JpdGVyc3x8aS5hd2FpdERyYWluV3JpdGVycy5zaXplPT09MCkmJnQubGlzdGVuZXJDb3VudChcImRhdGFcIikmJnQucmVzdW1lKCk7fX1GLnByb3RvdHlwZS51bnBpcGU9ZnVuY3Rpb24odCl7bGV0IGU9dGhpcy5fcmVhZGFibGVTdGF0ZSxyPXtoYXNVbnBpcGVkOiExfTtpZihlLnBpcGVzLmxlbmd0aD09PTApcmV0dXJuIHRoaXM7aWYoIXQpe2xldCBuPWUucGlwZXM7ZS5waXBlcz1bXSx0aGlzLnBhdXNlKCk7Zm9yKGxldCBvPTA7bzxuLmxlbmd0aDtvKyspbltvXS5lbWl0KFwidW5waXBlXCIsdGhpcyx7aGFzVW5waXBlZDohMX0pO3JldHVybiB0aGlzfWxldCBpPSR3KGUucGlwZXMsdCk7cmV0dXJuIGk9PT0tMT90aGlzOihlLnBpcGVzLnNwbGljZShpLDEpLGUucGlwZXMubGVuZ3RoPT09MCYmdGhpcy5wYXVzZSgpLHQuZW1pdChcInVucGlwZVwiLHRoaXMsciksdGhpcyl9O0YucHJvdG90eXBlLm9uPWZ1bmN0aW9uKHQsZSl7bGV0IHI9cXQucHJvdG90eXBlLm9uLmNhbGwodGhpcyx0LGUpLGk9dGhpcy5fcmVhZGFibGVTdGF0ZTtyZXR1cm4gdD09PVwiZGF0YVwiPyhpLnJlYWRhYmxlTGlzdGVuaW5nPXRoaXMubGlzdGVuZXJDb3VudChcInJlYWRhYmxlXCIpPjAsaS5mbG93aW5nIT09ITEmJnRoaXMucmVzdW1lKCkpOnQ9PT1cInJlYWRhYmxlXCImJiFpLmVuZEVtaXR0ZWQmJiFpLnJlYWRhYmxlTGlzdGVuaW5nJiYoaS5yZWFkYWJsZUxpc3RlbmluZz1pLm5lZWRSZWFkYWJsZT0hMCxpLmZsb3dpbmc9ITEsaS5lbWl0dGVkUmVhZGFibGU9ITEsSChcIm9uIHJlYWRhYmxlXCIsaS5sZW5ndGgsaS5yZWFkaW5nKSxpLmxlbmd0aD9jbih0aGlzKTppLnJlYWRpbmd8fEhlLm5leHRUaWNrKGJfLHRoaXMpKSxyfTtGLnByb3RvdHlwZS5hZGRMaXN0ZW5lcj1GLnByb3RvdHlwZS5vbjtGLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lcj1mdW5jdGlvbih0LGUpe2xldCByPXF0LnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lci5jYWxsKHRoaXMsdCxlKTtyZXR1cm4gdD09PVwicmVhZGFibGVcIiYmSGUubmV4dFRpY2soR2MsdGhpcykscn07Ri5wcm90b3R5cGUub2ZmPUYucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyO0YucHJvdG90eXBlLnJlbW92ZUFsbExpc3RlbmVycz1mdW5jdGlvbih0KXtsZXQgZT1xdC5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzLmFwcGx5KHRoaXMsYXJndW1lbnRzKTtyZXR1cm4gKHQ9PT1cInJlYWRhYmxlXCJ8fHQ9PT12b2lkIDApJiZIZS5uZXh0VGljayhHYyx0aGlzKSxlfTtmdW5jdGlvbiBHYyh0KXtsZXQgZT10Ll9yZWFkYWJsZVN0YXRlO2UucmVhZGFibGVMaXN0ZW5pbmc9dC5saXN0ZW5lckNvdW50KFwicmVhZGFibGVcIik+MCxlLnJlc3VtZVNjaGVkdWxlZCYmZVtscl09PT0hMT9lLmZsb3dpbmc9ITA6dC5saXN0ZW5lckNvdW50KFwiZGF0YVwiKT4wP3QucmVzdW1lKCk6ZS5yZWFkYWJsZUxpc3RlbmluZ3x8KGUuZmxvd2luZz1udWxsKTt9ZnVuY3Rpb24gYl8odCl7SChcInJlYWRhYmxlIG5leHR0aWNrIHJlYWQgMFwiKSx0LnJlYWQoMCk7fUYucHJvdG90eXBlLnJlc3VtZT1mdW5jdGlvbigpe2xldCB0PXRoaXMuX3JlYWRhYmxlU3RhdGU7cmV0dXJuIHQuZmxvd2luZ3x8KEgoXCJyZXN1bWVcIiksdC5mbG93aW5nPSF0LnJlYWRhYmxlTGlzdGVuaW5nLHdfKHRoaXMsdCkpLHRbbHJdPSExLHRoaXN9O2Z1bmN0aW9uIHdfKHQsZSl7ZS5yZXN1bWVTY2hlZHVsZWR8fChlLnJlc3VtZVNjaGVkdWxlZD0hMCxIZS5uZXh0VGljayhfXyx0LGUpKTt9ZnVuY3Rpb24gX18odCxlKXtIKFwicmVzdW1lXCIsZS5yZWFkaW5nKSxlLnJlYWRpbmd8fHQucmVhZCgwKSxlLnJlc3VtZVNjaGVkdWxlZD0hMSx0LmVtaXQoXCJyZXN1bWVcIiksUWModCksZS5mbG93aW5nJiYhZS5yZWFkaW5nJiZ0LnJlYWQoMCk7fUYucHJvdG90eXBlLnBhdXNlPWZ1bmN0aW9uKCl7cmV0dXJuIEgoXCJjYWxsIHBhdXNlIGZsb3dpbmc9JWpcIix0aGlzLl9yZWFkYWJsZVN0YXRlLmZsb3dpbmcpLHRoaXMuX3JlYWRhYmxlU3RhdGUuZmxvd2luZyE9PSExJiYoSChcInBhdXNlXCIpLHRoaXMuX3JlYWRhYmxlU3RhdGUuZmxvd2luZz0hMSx0aGlzLmVtaXQoXCJwYXVzZVwiKSksdGhpcy5fcmVhZGFibGVTdGF0ZVtscl09ITAsdGhpc307ZnVuY3Rpb24gUWModCl7bGV0IGU9dC5fcmVhZGFibGVTdGF0ZTtmb3IoSChcImZsb3dcIixlLmZsb3dpbmcpO2UuZmxvd2luZyYmdC5yZWFkKCkhPT1udWxsOyk7fUYucHJvdG90eXBlLndyYXA9ZnVuY3Rpb24odCl7bGV0IGU9ITE7dC5vbihcImRhdGFcIixpPT57IXRoaXMucHVzaChpKSYmdC5wYXVzZSYmKGU9ITAsdC5wYXVzZSgpKTt9KSx0Lm9uKFwiZW5kXCIsKCk9Pnt0aGlzLnB1c2gobnVsbCk7fSksdC5vbihcImVycm9yXCIsaT0+e3FyKHRoaXMsaSk7fSksdC5vbihcImNsb3NlXCIsKCk9Pnt0aGlzLmRlc3Ryb3koKTt9KSx0Lm9uKFwiZGVzdHJveVwiLCgpPT57dGhpcy5kZXN0cm95KCk7fSksdGhpcy5fcmVhZD0oKT0+e2UmJnQucmVzdW1lJiYoZT0hMSx0LnJlc3VtZSgpKTt9O2xldCByPUt3KHQpO2ZvcihsZXQgaT0xO2k8ci5sZW5ndGg7aSsrKXtsZXQgbj1yW2ldO3RoaXNbbl09PT12b2lkIDAmJnR5cGVvZiB0W25dPT1cImZ1bmN0aW9uXCImJih0aGlzW25dPXRbbl0uYmluZCh0KSk7fXJldHVybiB0aGlzfTtGLnByb3RvdHlwZVtZd109ZnVuY3Rpb24oKXtyZXR1cm4gWWModGhpcyl9O0YucHJvdG90eXBlLml0ZXJhdG9yPWZ1bmN0aW9uKHQpe3JldHVybiB0IT09dm9pZCAwJiZmXyh0LFwib3B0aW9uc1wiKSxZYyh0aGlzLHQpfTtmdW5jdGlvbiBZYyh0LGUpe3R5cGVvZiB0LnJlYWQhPVwiZnVuY3Rpb25cIiYmKHQ9Ri53cmFwKHQse29iamVjdE1vZGU6ITB9KSk7bGV0IHI9bV8odCxlKTtyZXR1cm4gci5zdHJlYW09dCxyfWFzeW5jIGZ1bmN0aW9uKm1fKHQsZSl7bGV0IHI9WHM7ZnVuY3Rpb24gaShzKXt0aGlzPT09dD8ocigpLHI9WHMpOnI9czt9dC5vbihcInJlYWRhYmxlXCIsaSk7bGV0IG4sbz10Xyh0LHt3cml0YWJsZTohMX0scz0+e249cz9GYyhuLHMpOm51bGwscigpLHI9WHM7fSk7dHJ5e2Zvcig7Oyl7bGV0IHM9dC5kZXN0cm95ZWQ/bnVsbDp0LnJlYWQoKTtpZihzIT09bnVsbCl5aWVsZCBzO2Vsc2Uge2lmKG4pdGhyb3cgbjtpZihuPT09bnVsbClyZXR1cm47YXdhaXQgbmV3IEd3KGkpO319fWNhdGNoKHMpe3Rocm93IG49RmMobixzKSxufWZpbmFsbHl7KG58fGU/LmRlc3Ryb3lPblJldHVybiE9PSExKSYmKG49PT12b2lkIDB8fHQuX3JlYWRhYmxlU3RhdGUuYXV0b0Rlc3Ryb3kpP0RyLmRlc3Ryb3llcih0LG51bGwpOih0Lm9mZihcInJlYWRhYmxlXCIsaSksbygpKTt9fSRjKEYucHJvdG90eXBlLHtyZWFkYWJsZTp7X19wcm90b19fOm51bGwsZ2V0KCl7bGV0IHQ9dGhpcy5fcmVhZGFibGVTdGF0ZTtyZXR1cm4gISF0JiZ0LnJlYWRhYmxlIT09ITEmJiF0LmRlc3Ryb3llZCYmIXQuZXJyb3JFbWl0dGVkJiYhdC5lbmRFbWl0dGVkfSxzZXQodCl7dGhpcy5fcmVhZGFibGVTdGF0ZSYmKHRoaXMuX3JlYWRhYmxlU3RhdGUucmVhZGFibGU9ISF0KTt9fSxyZWFkYWJsZURpZFJlYWQ6e19fcHJvdG9fXzpudWxsLGVudW1lcmFibGU6ITEsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3JlYWRhYmxlU3RhdGUuZGF0YUVtaXR0ZWR9fSxyZWFkYWJsZUFib3J0ZWQ6e19fcHJvdG9fXzpudWxsLGVudW1lcmFibGU6ITEsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuICEhKHRoaXMuX3JlYWRhYmxlU3RhdGUucmVhZGFibGUhPT0hMSYmKHRoaXMuX3JlYWRhYmxlU3RhdGUuZGVzdHJveWVkfHx0aGlzLl9yZWFkYWJsZVN0YXRlLmVycm9yZWQpJiYhdGhpcy5fcmVhZGFibGVTdGF0ZS5lbmRFbWl0dGVkKX19LHJlYWRhYmxlSGlnaFdhdGVyTWFyazp7X19wcm90b19fOm51bGwsZW51bWVyYWJsZTohMSxnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fcmVhZGFibGVTdGF0ZS5oaWdoV2F0ZXJNYXJrfX0scmVhZGFibGVCdWZmZXI6e19fcHJvdG9fXzpudWxsLGVudW1lcmFibGU6ITEsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3JlYWRhYmxlU3RhdGUmJnRoaXMuX3JlYWRhYmxlU3RhdGUuYnVmZmVyfX0scmVhZGFibGVGbG93aW5nOntfX3Byb3RvX186bnVsbCxlbnVtZXJhYmxlOiExLGdldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLl9yZWFkYWJsZVN0YXRlLmZsb3dpbmd9LHNldDpmdW5jdGlvbih0KXt0aGlzLl9yZWFkYWJsZVN0YXRlJiYodGhpcy5fcmVhZGFibGVTdGF0ZS5mbG93aW5nPXQpO319LHJlYWRhYmxlTGVuZ3RoOntfX3Byb3RvX186bnVsbCxlbnVtZXJhYmxlOiExLGdldCgpe3JldHVybiB0aGlzLl9yZWFkYWJsZVN0YXRlLmxlbmd0aH19LHJlYWRhYmxlT2JqZWN0TW9kZTp7X19wcm90b19fOm51bGwsZW51bWVyYWJsZTohMSxnZXQoKXtyZXR1cm4gdGhpcy5fcmVhZGFibGVTdGF0ZT90aGlzLl9yZWFkYWJsZVN0YXRlLm9iamVjdE1vZGU6ITF9fSxyZWFkYWJsZUVuY29kaW5nOntfX3Byb3RvX186bnVsbCxlbnVtZXJhYmxlOiExLGdldCgpe3JldHVybiB0aGlzLl9yZWFkYWJsZVN0YXRlP3RoaXMuX3JlYWRhYmxlU3RhdGUuZW5jb2Rpbmc6bnVsbH19LGVycm9yZWQ6e19fcHJvdG9fXzpudWxsLGVudW1lcmFibGU6ITEsZ2V0KCl7cmV0dXJuIHRoaXMuX3JlYWRhYmxlU3RhdGU/dGhpcy5fcmVhZGFibGVTdGF0ZS5lcnJvcmVkOm51bGx9fSxjbG9zZWQ6e19fcHJvdG9fXzpudWxsLGdldCgpe3JldHVybiB0aGlzLl9yZWFkYWJsZVN0YXRlP3RoaXMuX3JlYWRhYmxlU3RhdGUuY2xvc2VkOiExfX0sZGVzdHJveWVkOntfX3Byb3RvX186bnVsbCxlbnVtZXJhYmxlOiExLGdldCgpe3JldHVybiB0aGlzLl9yZWFkYWJsZVN0YXRlP3RoaXMuX3JlYWRhYmxlU3RhdGUuZGVzdHJveWVkOiExfSxzZXQodCl7dGhpcy5fcmVhZGFibGVTdGF0ZSYmKHRoaXMuX3JlYWRhYmxlU3RhdGUuZGVzdHJveWVkPXQpO319LHJlYWRhYmxlRW5kZWQ6e19fcHJvdG9fXzpudWxsLGVudW1lcmFibGU6ITEsZ2V0KCl7cmV0dXJuIHRoaXMuX3JlYWRhYmxlU3RhdGU/dGhpcy5fcmVhZGFibGVTdGF0ZS5lbmRFbWl0dGVkOiExfX19KTskYyhyby5wcm90b3R5cGUse3BpcGVzQ291bnQ6e19fcHJvdG9fXzpudWxsLGdldCgpe3JldHVybiB0aGlzLnBpcGVzLmxlbmd0aH19LHBhdXNlZDp7X19wcm90b19fOm51bGwsZ2V0KCl7cmV0dXJuIHRoaXNbbHJdIT09ITF9LHNldCh0KXt0aGlzW2xyXT0hIXQ7fX19KTtGLl9mcm9tTGlzdD1KYztmdW5jdGlvbiBKYyh0LGUpe2lmKGUubGVuZ3RoPT09MClyZXR1cm4gbnVsbDtsZXQgcjtyZXR1cm4gZS5vYmplY3RNb2RlP3I9ZS5idWZmZXIuc2hpZnQoKTohdHx8dD49ZS5sZW5ndGg/KGUuZGVjb2Rlcj9yPWUuYnVmZmVyLmpvaW4oXCJcIik6ZS5idWZmZXIubGVuZ3RoPT09MT9yPWUuYnVmZmVyLmZpcnN0KCk6cj1lLmJ1ZmZlci5jb25jYXQoZS5sZW5ndGgpLGUuYnVmZmVyLmNsZWFyKCkpOnI9ZS5idWZmZXIuY29uc3VtZSh0LGUuZGVjb2Rlcikscn1mdW5jdGlvbiBlbyh0KXtsZXQgZT10Ll9yZWFkYWJsZVN0YXRlO0goXCJlbmRSZWFkYWJsZVwiLGUuZW5kRW1pdHRlZCksZS5lbmRFbWl0dGVkfHwoZS5lbmRlZD0hMCxIZS5uZXh0VGljayh2XyxlLHQpKTt9ZnVuY3Rpb24gdl8odCxlKXtpZihIKFwiZW5kUmVhZGFibGVOVFwiLHQuZW5kRW1pdHRlZCx0Lmxlbmd0aCksIXQuZXJyb3JlZCYmIXQuY2xvc2VFbWl0dGVkJiYhdC5lbmRFbWl0dGVkJiZ0Lmxlbmd0aD09PTApe2lmKHQuZW5kRW1pdHRlZD0hMCxlLmVtaXQoXCJlbmRcIiksZS53cml0YWJsZSYmZS5hbGxvd0hhbGZPcGVuPT09ITEpSGUubmV4dFRpY2soRV8sZSk7ZWxzZSBpZih0LmF1dG9EZXN0cm95KXtsZXQgcj1lLl93cml0YWJsZVN0YXRlOyghcnx8ci5hdXRvRGVzdHJveSYmKHIuZmluaXNoZWR8fHIud3JpdGFibGU9PT0hMSkpJiZlLmRlc3Ryb3koKTt9fX1mdW5jdGlvbiBFXyh0KXt0LndyaXRhYmxlJiYhdC53cml0YWJsZUVuZGVkJiYhdC5kZXN0cm95ZWQmJnQuZW5kKCk7fUYuZnJvbT1mdW5jdGlvbih0LGUpe3JldHVybiBjXyhGLHQsZSl9O3ZhciB0bztmdW5jdGlvbiBYYygpe3JldHVybiB0bz09PXZvaWQgMCYmKHRvPXt9KSx0b31GLmZyb21XZWI9ZnVuY3Rpb24odCxlKXtyZXR1cm4gWGMoKS5uZXdTdHJlYW1SZWFkYWJsZUZyb21SZWFkYWJsZVN0cmVhbSh0LGUpfTtGLnRvV2ViPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIFhjKCkubmV3UmVhZGFibGVTdHJlYW1Gcm9tU3RyZWFtUmVhZGFibGUodCxlKX07Ri53cmFwPWZ1bmN0aW9uKHQsZSl7dmFyIHIsaTtyZXR1cm4gbmV3IEYoe29iamVjdE1vZGU6KHI9KGk9dC5yZWFkYWJsZU9iamVjdE1vZGUpIT09bnVsbCYmaSE9PXZvaWQgMD9pOnQub2JqZWN0TW9kZSkhPT1udWxsJiZyIT09dm9pZCAwP3I6ITAsLi4uZSxkZXN0cm95KG4sbyl7RHIuZGVzdHJveWVyKHQsbiksbyhuKTt9fSkud3JhcCh0KX07fSk7dmFyIHVvPU0oKGFSLGNoKT0+e3YoKTttKCk7XygpO3ZhciB1cj1VdCgpLHtBcnJheVByb3RvdHlwZVNsaWNlOnJoLEVycm9yOlNfLEZ1bmN0aW9uUHJvdG90eXBlU3ltYm9sSGFzSW5zdGFuY2U6aWgsT2JqZWN0RGVmaW5lUHJvcGVydHk6bmgsT2JqZWN0RGVmaW5lUHJvcGVydGllczpBXyxPYmplY3RTZXRQcm90b3R5cGVPZjpzaCxTdHJpbmdQcm90b3R5cGVUb0xvd2VyQ2FzZTpJXyxTeW1ib2w6VF8sU3ltYm9sSGFzSW5zdGFuY2U6Ul99PWNlKCk7Y2guZXhwb3J0cz1pZTtpZS5Xcml0YWJsZVN0YXRlPXlpO3ZhcntFdmVudEVtaXR0ZXI6Q199PShpcigpLFgocnIpKSxwaT10bigpLlN0cmVhbSx7QnVmZmVyOmhufT0oeWUoKSxYKF9lKSksZ249dHIoKSx7YWRkQWJvcnRTaWduYWw6Ql99PWNpKCkse2dldEhpZ2hXYXRlck1hcms6UF8sZ2V0RGVmYXVsdEhpZ2hXYXRlck1hcms6T199PXNuKCkse0VSUl9JTlZBTElEX0FSR19UWVBFOmtfLEVSUl9NRVRIT0RfTk9UX0lNUExFTUVOVEVEOnhfLEVSUl9NVUxUSVBMRV9DQUxMQkFDSzpvaCxFUlJfU1RSRUFNX0NBTk5PVF9QSVBFOk1fLEVSUl9TVFJFQU1fREVTVFJPWUVEOmdpLEVSUl9TVFJFQU1fQUxSRUFEWV9GSU5JU0hFRDpMXyxFUlJfU1RSRUFNX05VTExfVkFMVUVTOlVfLEVSUl9TVFJFQU1fV1JJVEVfQUZURVJfRU5EOk5fLEVSUl9VTktOT1dOX0VOQ09ESU5HOmFofT1TZSgpLmNvZGVzLHtlcnJvck9yRGVzdHJveTpqcn09Z247c2goaWUucHJvdG90eXBlLHBpLnByb3RvdHlwZSk7c2goaWUscGkpO2Z1bmN0aW9uIHNvKCl7fXZhciBGcj1UXyhcImtPbkZpbmlzaGVkXCIpO2Z1bmN0aW9uIHlpKHQsZSxyKXt0eXBlb2YgciE9XCJib29sZWFuXCImJihyPWUgaW5zdGFuY2VvZiBudCgpKSx0aGlzLm9iamVjdE1vZGU9ISEodCYmdC5vYmplY3RNb2RlKSxyJiYodGhpcy5vYmplY3RNb2RlPXRoaXMub2JqZWN0TW9kZXx8ISEodCYmdC53cml0YWJsZU9iamVjdE1vZGUpKSx0aGlzLmhpZ2hXYXRlck1hcms9dD9QXyh0aGlzLHQsXCJ3cml0YWJsZUhpZ2hXYXRlck1hcmtcIixyKTpPXyghMSksdGhpcy5maW5hbENhbGxlZD0hMSx0aGlzLm5lZWREcmFpbj0hMSx0aGlzLmVuZGluZz0hMSx0aGlzLmVuZGVkPSExLHRoaXMuZmluaXNoZWQ9ITEsdGhpcy5kZXN0cm95ZWQ9ITE7bGV0IGk9ISEodCYmdC5kZWNvZGVTdHJpbmdzPT09ITEpO3RoaXMuZGVjb2RlU3RyaW5ncz0haSx0aGlzLmRlZmF1bHRFbmNvZGluZz10JiZ0LmRlZmF1bHRFbmNvZGluZ3x8XCJ1dGY4XCIsdGhpcy5sZW5ndGg9MCx0aGlzLndyaXRpbmc9ITEsdGhpcy5jb3JrZWQ9MCx0aGlzLnN5bmM9ITAsdGhpcy5idWZmZXJQcm9jZXNzaW5nPSExLHRoaXMub253cml0ZT1EXy5iaW5kKHZvaWQgMCxlKSx0aGlzLndyaXRlY2I9bnVsbCx0aGlzLndyaXRlbGVuPTAsdGhpcy5hZnRlcldyaXRlVGlja0luZm89bnVsbCxwbih0aGlzKSx0aGlzLnBlbmRpbmdjYj0wLHRoaXMuY29uc3RydWN0ZWQ9ITAsdGhpcy5wcmVmaW5pc2hlZD0hMSx0aGlzLmVycm9yRW1pdHRlZD0hMSx0aGlzLmVtaXRDbG9zZT0hdHx8dC5lbWl0Q2xvc2UhPT0hMSx0aGlzLmF1dG9EZXN0cm95PSF0fHx0LmF1dG9EZXN0cm95IT09ITEsdGhpcy5lcnJvcmVkPW51bGwsdGhpcy5jbG9zZWQ9ITEsdGhpcy5jbG9zZUVtaXR0ZWQ9ITEsdGhpc1tGcl09W107fWZ1bmN0aW9uIHBuKHQpe3QuYnVmZmVyZWQ9W10sdC5idWZmZXJlZEluZGV4PTAsdC5hbGxCdWZmZXJzPSEwLHQuYWxsTm9vcD0hMDt9eWkucHJvdG90eXBlLmdldEJ1ZmZlcj1mdW5jdGlvbigpe3JldHVybiByaCh0aGlzLmJ1ZmZlcmVkLHRoaXMuYnVmZmVyZWRJbmRleCl9O25oKHlpLnByb3RvdHlwZSxcImJ1ZmZlcmVkUmVxdWVzdENvdW50XCIse19fcHJvdG9fXzpudWxsLGdldCgpe3JldHVybiB0aGlzLmJ1ZmZlcmVkLmxlbmd0aC10aGlzLmJ1ZmZlcmVkSW5kZXh9fSk7ZnVuY3Rpb24gaWUodCl7bGV0IGU9dGhpcyBpbnN0YW5jZW9mIG50KCk7aWYoIWUmJiFpaChpZSx0aGlzKSlyZXR1cm4gbmV3IGllKHQpO3RoaXMuX3dyaXRhYmxlU3RhdGU9bmV3IHlpKHQsdGhpcyxlKSx0JiYodHlwZW9mIHQud3JpdGU9PVwiZnVuY3Rpb25cIiYmKHRoaXMuX3dyaXRlPXQud3JpdGUpLHR5cGVvZiB0LndyaXRldj09XCJmdW5jdGlvblwiJiYodGhpcy5fd3JpdGV2PXQud3JpdGV2KSx0eXBlb2YgdC5kZXN0cm95PT1cImZ1bmN0aW9uXCImJih0aGlzLl9kZXN0cm95PXQuZGVzdHJveSksdHlwZW9mIHQuZmluYWw9PVwiZnVuY3Rpb25cIiYmKHRoaXMuX2ZpbmFsPXQuZmluYWwpLHR5cGVvZiB0LmNvbnN0cnVjdD09XCJmdW5jdGlvblwiJiYodGhpcy5fY29uc3RydWN0PXQuY29uc3RydWN0KSx0LnNpZ25hbCYmQl8odC5zaWduYWwsdGhpcykpLHBpLmNhbGwodGhpcyx0KSxnbi5jb25zdHJ1Y3QodGhpcywoKT0+e2xldCByPXRoaXMuX3dyaXRhYmxlU3RhdGU7ci53cml0aW5nfHxhbyh0aGlzLHIpLGxvKHRoaXMscik7fSk7fW5oKGllLFJfLHtfX3Byb3RvX186bnVsbCx2YWx1ZTpmdW5jdGlvbih0KXtyZXR1cm4gaWgodGhpcyx0KT8hMDp0aGlzIT09aWU/ITE6dCYmdC5fd3JpdGFibGVTdGF0ZSBpbnN0YW5jZW9mIHlpfX0pO2llLnByb3RvdHlwZS5waXBlPWZ1bmN0aW9uKCl7anIodGhpcyxuZXcgTV8pO307ZnVuY3Rpb24gbGgodCxlLHIsaSl7bGV0IG49dC5fd3JpdGFibGVTdGF0ZTtpZih0eXBlb2Ygcj09XCJmdW5jdGlvblwiKWk9cixyPW4uZGVmYXVsdEVuY29kaW5nO2Vsc2Uge2lmKCFyKXI9bi5kZWZhdWx0RW5jb2Rpbmc7ZWxzZSBpZihyIT09XCJidWZmZXJcIiYmIWhuLmlzRW5jb2RpbmcocikpdGhyb3cgbmV3IGFoKHIpO3R5cGVvZiBpIT1cImZ1bmN0aW9uXCImJihpPXNvKTt9aWYoZT09PW51bGwpdGhyb3cgbmV3IFVfO2lmKCFuLm9iamVjdE1vZGUpaWYodHlwZW9mIGU9PVwic3RyaW5nXCIpbi5kZWNvZGVTdHJpbmdzIT09ITEmJihlPWhuLmZyb20oZSxyKSxyPVwiYnVmZmVyXCIpO2Vsc2UgaWYoZSBpbnN0YW5jZW9mIGhuKXI9XCJidWZmZXJcIjtlbHNlIGlmKHBpLl9pc1VpbnQ4QXJyYXkoZSkpZT1waS5fdWludDhBcnJheVRvQnVmZmVyKGUpLHI9XCJidWZmZXJcIjtlbHNlIHRocm93IG5ldyBrXyhcImNodW5rXCIsW1wic3RyaW5nXCIsXCJCdWZmZXJcIixcIlVpbnQ4QXJyYXlcIl0sZSk7bGV0IG87cmV0dXJuIG4uZW5kaW5nP289bmV3IE5fOm4uZGVzdHJveWVkJiYobz1uZXcgZ2koXCJ3cml0ZVwiKSksbz8odXIubmV4dFRpY2soaSxvKSxqcih0LG8sITApLG8pOihuLnBlbmRpbmdjYisrLHFfKHQsbixlLHIsaSkpfWllLnByb3RvdHlwZS53cml0ZT1mdW5jdGlvbih0LGUscil7cmV0dXJuIGxoKHRoaXMsdCxlLHIpPT09ITB9O2llLnByb3RvdHlwZS5jb3JrPWZ1bmN0aW9uKCl7dGhpcy5fd3JpdGFibGVTdGF0ZS5jb3JrZWQrKzt9O2llLnByb3RvdHlwZS51bmNvcms9ZnVuY3Rpb24oKXtsZXQgdD10aGlzLl93cml0YWJsZVN0YXRlO3QuY29ya2VkJiYodC5jb3JrZWQtLSx0LndyaXRpbmd8fGFvKHRoaXMsdCkpO307aWUucHJvdG90eXBlLnNldERlZmF1bHRFbmNvZGluZz1mdW5jdGlvbihlKXtpZih0eXBlb2YgZT09XCJzdHJpbmdcIiYmKGU9SV8oZSkpLCFobi5pc0VuY29kaW5nKGUpKXRocm93IG5ldyBhaChlKTtyZXR1cm4gdGhpcy5fd3JpdGFibGVTdGF0ZS5kZWZhdWx0RW5jb2Rpbmc9ZSx0aGlzfTtmdW5jdGlvbiBxXyh0LGUscixpLG4pe2xldCBvPWUub2JqZWN0TW9kZT8xOnIubGVuZ3RoO2UubGVuZ3RoKz1vO2xldCBzPWUubGVuZ3RoPGUuaGlnaFdhdGVyTWFyaztyZXR1cm4gc3x8KGUubmVlZERyYWluPSEwKSxlLndyaXRpbmd8fGUuY29ya2VkfHxlLmVycm9yZWR8fCFlLmNvbnN0cnVjdGVkPyhlLmJ1ZmZlcmVkLnB1c2goe2NodW5rOnIsZW5jb2Rpbmc6aSxjYWxsYmFjazpufSksZS5hbGxCdWZmZXJzJiZpIT09XCJidWZmZXJcIiYmKGUuYWxsQnVmZmVycz0hMSksZS5hbGxOb29wJiZuIT09c28mJihlLmFsbE5vb3A9ITEpKTooZS53cml0ZWxlbj1vLGUud3JpdGVjYj1uLGUud3JpdGluZz0hMCxlLnN5bmM9ITAsdC5fd3JpdGUocixpLGUub253cml0ZSksZS5zeW5jPSExKSxzJiYhZS5lcnJvcmVkJiYhZS5kZXN0cm95ZWR9ZnVuY3Rpb24gZWgodCxlLHIsaSxuLG8scyl7ZS53cml0ZWxlbj1pLGUud3JpdGVjYj1zLGUud3JpdGluZz0hMCxlLnN5bmM9ITAsZS5kZXN0cm95ZWQ/ZS5vbndyaXRlKG5ldyBnaShcIndyaXRlXCIpKTpyP3QuX3dyaXRldihuLGUub253cml0ZSk6dC5fd3JpdGUobixvLGUub253cml0ZSksZS5zeW5jPSExO31mdW5jdGlvbiB0aCh0LGUscixpKXstLWUucGVuZGluZ2NiLGkociksb28oZSksanIodCxyKTt9ZnVuY3Rpb24gRF8odCxlKXtsZXQgcj10Ll93cml0YWJsZVN0YXRlLGk9ci5zeW5jLG49ci53cml0ZWNiO2lmKHR5cGVvZiBuIT1cImZ1bmN0aW9uXCIpe2pyKHQsbmV3IG9oKTtyZXR1cm59ci53cml0aW5nPSExLHIud3JpdGVjYj1udWxsLHIubGVuZ3RoLT1yLndyaXRlbGVuLHIud3JpdGVsZW49MCxlPyhlLnN0YWNrLHIuZXJyb3JlZHx8KHIuZXJyb3JlZD1lKSx0Ll9yZWFkYWJsZVN0YXRlJiYhdC5fcmVhZGFibGVTdGF0ZS5lcnJvcmVkJiYodC5fcmVhZGFibGVTdGF0ZS5lcnJvcmVkPWUpLGk/dXIubmV4dFRpY2sodGgsdCxyLGUsbik6dGgodCxyLGUsbikpOihyLmJ1ZmZlcmVkLmxlbmd0aD5yLmJ1ZmZlcmVkSW5kZXgmJmFvKHQsciksaT9yLmFmdGVyV3JpdGVUaWNrSW5mbyE9PW51bGwmJnIuYWZ0ZXJXcml0ZVRpY2tJbmZvLmNiPT09bj9yLmFmdGVyV3JpdGVUaWNrSW5mby5jb3VudCsrOihyLmFmdGVyV3JpdGVUaWNrSW5mbz17Y291bnQ6MSxjYjpuLHN0cmVhbTp0LHN0YXRlOnJ9LHVyLm5leHRUaWNrKGpfLHIuYWZ0ZXJXcml0ZVRpY2tJbmZvKSk6dWgodCxyLDEsbikpO31mdW5jdGlvbiBqXyh7c3RyZWFtOnQsc3RhdGU6ZSxjb3VudDpyLGNiOml9KXtyZXR1cm4gZS5hZnRlcldyaXRlVGlja0luZm89bnVsbCx1aCh0LGUscixpKX1mdW5jdGlvbiB1aCh0LGUscixpKXtmb3IoIWUuZW5kaW5nJiYhdC5kZXN0cm95ZWQmJmUubGVuZ3RoPT09MCYmZS5uZWVkRHJhaW4mJihlLm5lZWREcmFpbj0hMSx0LmVtaXQoXCJkcmFpblwiKSk7ci0tID4wOyllLnBlbmRpbmdjYi0tLGkoKTtlLmRlc3Ryb3llZCYmb28oZSksbG8odCxlKTt9ZnVuY3Rpb24gb28odCl7aWYodC53cml0aW5nKXJldHVybjtmb3IobGV0IG49dC5idWZmZXJlZEluZGV4O248dC5idWZmZXJlZC5sZW5ndGg7KytuKXt2YXIgZTtsZXR7Y2h1bms6byxjYWxsYmFjazpzfT10LmJ1ZmZlcmVkW25dLGE9dC5vYmplY3RNb2RlPzE6by5sZW5ndGg7dC5sZW5ndGgtPWEscygoZT10LmVycm9yZWQpIT09bnVsbCYmZSE9PXZvaWQgMD9lOm5ldyBnaShcIndyaXRlXCIpKTt9bGV0IHI9dFtGcl0uc3BsaWNlKDApO2ZvcihsZXQgbj0wO248ci5sZW5ndGg7bisrKXt2YXIgaTtyW25dKChpPXQuZXJyb3JlZCkhPT1udWxsJiZpIT09dm9pZCAwP2k6bmV3IGdpKFwiZW5kXCIpKTt9cG4odCk7fWZ1bmN0aW9uIGFvKHQsZSl7aWYoZS5jb3JrZWR8fGUuYnVmZmVyUHJvY2Vzc2luZ3x8ZS5kZXN0cm95ZWR8fCFlLmNvbnN0cnVjdGVkKXJldHVybjtsZXR7YnVmZmVyZWQ6cixidWZmZXJlZEluZGV4Omksb2JqZWN0TW9kZTpufT1lLG89ci5sZW5ndGgtaTtpZighbylyZXR1cm47bGV0IHM9aTtpZihlLmJ1ZmZlclByb2Nlc3Npbmc9ITAsbz4xJiZ0Ll93cml0ZXYpe2UucGVuZGluZ2NiLT1vLTE7bGV0IGE9ZS5hbGxOb29wP3NvOmM9Pntmb3IobGV0IGg9cztoPHIubGVuZ3RoOysraClyW2hdLmNhbGxiYWNrKGMpO30sdT1lLmFsbE5vb3AmJnM9PT0wP3I6cmgocixzKTt1LmFsbEJ1ZmZlcnM9ZS5hbGxCdWZmZXJzLGVoKHQsZSwhMCxlLmxlbmd0aCx1LFwiXCIsYSkscG4oZSk7fWVsc2Uge2Rve2xldHtjaHVuazphLGVuY29kaW5nOnUsY2FsbGJhY2s6Y309cltzXTtyW3MrK109bnVsbDtsZXQgaD1uPzE6YS5sZW5ndGg7ZWgodCxlLCExLGgsYSx1LGMpO313aGlsZShzPHIubGVuZ3RoJiYhZS53cml0aW5nKTtzPT09ci5sZW5ndGg/cG4oZSk6cz4yNTY/KHIuc3BsaWNlKDAscyksZS5idWZmZXJlZEluZGV4PTApOmUuYnVmZmVyZWRJbmRleD1zO31lLmJ1ZmZlclByb2Nlc3Npbmc9ITE7fWllLnByb3RvdHlwZS5fd3JpdGU9ZnVuY3Rpb24odCxlLHIpe2lmKHRoaXMuX3dyaXRldil0aGlzLl93cml0ZXYoW3tjaHVuazp0LGVuY29kaW5nOmV9XSxyKTtlbHNlIHRocm93IG5ldyB4XyhcIl93cml0ZSgpXCIpfTtpZS5wcm90b3R5cGUuX3dyaXRldj1udWxsO2llLnByb3RvdHlwZS5lbmQ9ZnVuY3Rpb24odCxlLHIpe2xldCBpPXRoaXMuX3dyaXRhYmxlU3RhdGU7dHlwZW9mIHQ9PVwiZnVuY3Rpb25cIj8ocj10LHQ9bnVsbCxlPW51bGwpOnR5cGVvZiBlPT1cImZ1bmN0aW9uXCImJihyPWUsZT1udWxsKTtsZXQgbjtpZih0IT1udWxsKXtsZXQgbz1saCh0aGlzLHQsZSk7byBpbnN0YW5jZW9mIFNfJiYobj1vKTt9cmV0dXJuIGkuY29ya2VkJiYoaS5jb3JrZWQ9MSx0aGlzLnVuY29yaygpKSxufHwoIWkuZXJyb3JlZCYmIWkuZW5kaW5nPyhpLmVuZGluZz0hMCxsbyh0aGlzLGksITApLGkuZW5kZWQ9ITApOmkuZmluaXNoZWQ/bj1uZXcgTF8oXCJlbmRcIik6aS5kZXN0cm95ZWQmJihuPW5ldyBnaShcImVuZFwiKSkpLHR5cGVvZiByPT1cImZ1bmN0aW9uXCImJihufHxpLmZpbmlzaGVkP3VyLm5leHRUaWNrKHIsbik6aVtGcl0ucHVzaChyKSksdGhpc307ZnVuY3Rpb24gZG4odCl7cmV0dXJuIHQuZW5kaW5nJiYhdC5kZXN0cm95ZWQmJnQuY29uc3RydWN0ZWQmJnQubGVuZ3RoPT09MCYmIXQuZXJyb3JlZCYmdC5idWZmZXJlZC5sZW5ndGg9PT0wJiYhdC5maW5pc2hlZCYmIXQud3JpdGluZyYmIXQuZXJyb3JFbWl0dGVkJiYhdC5jbG9zZUVtaXR0ZWR9ZnVuY3Rpb24gRl8odCxlKXtsZXQgcj0hMTtmdW5jdGlvbiBpKG4pe2lmKHIpe2pyKHQsbj8/b2goKSk7cmV0dXJufWlmKHI9ITAsZS5wZW5kaW5nY2ItLSxuKXtsZXQgbz1lW0ZyXS5zcGxpY2UoMCk7Zm9yKGxldCBzPTA7czxvLmxlbmd0aDtzKyspb1tzXShuKTtqcih0LG4sZS5zeW5jKTt9ZWxzZSBkbihlKSYmKGUucHJlZmluaXNoZWQ9ITAsdC5lbWl0KFwicHJlZmluaXNoXCIpLGUucGVuZGluZ2NiKyssdXIubmV4dFRpY2sobm8sdCxlKSk7fWUuc3luYz0hMCxlLnBlbmRpbmdjYisrO3RyeXt0Ll9maW5hbChpKTt9Y2F0Y2gobil7aShuKTt9ZS5zeW5jPSExO31mdW5jdGlvbiBXXyh0LGUpeyFlLnByZWZpbmlzaGVkJiYhZS5maW5hbENhbGxlZCYmKHR5cGVvZiB0Ll9maW5hbD09XCJmdW5jdGlvblwiJiYhZS5kZXN0cm95ZWQ/KGUuZmluYWxDYWxsZWQ9ITAsRl8odCxlKSk6KGUucHJlZmluaXNoZWQ9ITAsdC5lbWl0KFwicHJlZmluaXNoXCIpKSk7fWZ1bmN0aW9uIGxvKHQsZSxyKXtkbihlKSYmKFdfKHQsZSksZS5wZW5kaW5nY2I9PT0wJiYocj8oZS5wZW5kaW5nY2IrKyx1ci5uZXh0VGljaygoaSxuKT0+e2RuKG4pP25vKGksbik6bi5wZW5kaW5nY2ItLTt9LHQsZSkpOmRuKGUpJiYoZS5wZW5kaW5nY2IrKyxubyh0LGUpKSkpO31mdW5jdGlvbiBubyh0LGUpe2UucGVuZGluZ2NiLS0sZS5maW5pc2hlZD0hMDtsZXQgcj1lW0ZyXS5zcGxpY2UoMCk7Zm9yKGxldCBpPTA7aTxyLmxlbmd0aDtpKyspcltpXSgpO2lmKHQuZW1pdChcImZpbmlzaFwiKSxlLmF1dG9EZXN0cm95KXtsZXQgaT10Ll9yZWFkYWJsZVN0YXRlOyghaXx8aS5hdXRvRGVzdHJveSYmKGkuZW5kRW1pdHRlZHx8aS5yZWFkYWJsZT09PSExKSkmJnQuZGVzdHJveSgpO319QV8oaWUucHJvdG90eXBlLHtjbG9zZWQ6e19fcHJvdG9fXzpudWxsLGdldCgpe3JldHVybiB0aGlzLl93cml0YWJsZVN0YXRlP3RoaXMuX3dyaXRhYmxlU3RhdGUuY2xvc2VkOiExfX0sZGVzdHJveWVkOntfX3Byb3RvX186bnVsbCxnZXQoKXtyZXR1cm4gdGhpcy5fd3JpdGFibGVTdGF0ZT90aGlzLl93cml0YWJsZVN0YXRlLmRlc3Ryb3llZDohMX0sc2V0KHQpe3RoaXMuX3dyaXRhYmxlU3RhdGUmJih0aGlzLl93cml0YWJsZVN0YXRlLmRlc3Ryb3llZD10KTt9fSx3cml0YWJsZTp7X19wcm90b19fOm51bGwsZ2V0KCl7bGV0IHQ9dGhpcy5fd3JpdGFibGVTdGF0ZTtyZXR1cm4gISF0JiZ0LndyaXRhYmxlIT09ITEmJiF0LmRlc3Ryb3llZCYmIXQuZXJyb3JlZCYmIXQuZW5kaW5nJiYhdC5lbmRlZH0sc2V0KHQpe3RoaXMuX3dyaXRhYmxlU3RhdGUmJih0aGlzLl93cml0YWJsZVN0YXRlLndyaXRhYmxlPSEhdCk7fX0sd3JpdGFibGVGaW5pc2hlZDp7X19wcm90b19fOm51bGwsZ2V0KCl7cmV0dXJuIHRoaXMuX3dyaXRhYmxlU3RhdGU/dGhpcy5fd3JpdGFibGVTdGF0ZS5maW5pc2hlZDohMX19LHdyaXRhYmxlT2JqZWN0TW9kZTp7X19wcm90b19fOm51bGwsZ2V0KCl7cmV0dXJuIHRoaXMuX3dyaXRhYmxlU3RhdGU/dGhpcy5fd3JpdGFibGVTdGF0ZS5vYmplY3RNb2RlOiExfX0sd3JpdGFibGVCdWZmZXI6e19fcHJvdG9fXzpudWxsLGdldCgpe3JldHVybiB0aGlzLl93cml0YWJsZVN0YXRlJiZ0aGlzLl93cml0YWJsZVN0YXRlLmdldEJ1ZmZlcigpfX0sd3JpdGFibGVFbmRlZDp7X19wcm90b19fOm51bGwsZ2V0KCl7cmV0dXJuIHRoaXMuX3dyaXRhYmxlU3RhdGU/dGhpcy5fd3JpdGFibGVTdGF0ZS5lbmRpbmc6ITF9fSx3cml0YWJsZU5lZWREcmFpbjp7X19wcm90b19fOm51bGwsZ2V0KCl7bGV0IHQ9dGhpcy5fd3JpdGFibGVTdGF0ZTtyZXR1cm4gdD8hdC5kZXN0cm95ZWQmJiF0LmVuZGluZyYmdC5uZWVkRHJhaW46ITF9fSx3cml0YWJsZUhpZ2hXYXRlck1hcms6e19fcHJvdG9fXzpudWxsLGdldCgpe3JldHVybiB0aGlzLl93cml0YWJsZVN0YXRlJiZ0aGlzLl93cml0YWJsZVN0YXRlLmhpZ2hXYXRlck1hcmt9fSx3cml0YWJsZUNvcmtlZDp7X19wcm90b19fOm51bGwsZ2V0KCl7cmV0dXJuIHRoaXMuX3dyaXRhYmxlU3RhdGU/dGhpcy5fd3JpdGFibGVTdGF0ZS5jb3JrZWQ6MH19LHdyaXRhYmxlTGVuZ3RoOntfX3Byb3RvX186bnVsbCxnZXQoKXtyZXR1cm4gdGhpcy5fd3JpdGFibGVTdGF0ZSYmdGhpcy5fd3JpdGFibGVTdGF0ZS5sZW5ndGh9fSxlcnJvcmVkOntfX3Byb3RvX186bnVsbCxlbnVtZXJhYmxlOiExLGdldCgpe3JldHVybiB0aGlzLl93cml0YWJsZVN0YXRlP3RoaXMuX3dyaXRhYmxlU3RhdGUuZXJyb3JlZDpudWxsfX0sd3JpdGFibGVBYm9ydGVkOntfX3Byb3RvX186bnVsbCxlbnVtZXJhYmxlOiExLGdldDpmdW5jdGlvbigpe3JldHVybiAhISh0aGlzLl93cml0YWJsZVN0YXRlLndyaXRhYmxlIT09ITEmJih0aGlzLl93cml0YWJsZVN0YXRlLmRlc3Ryb3llZHx8dGhpcy5fd3JpdGFibGVTdGF0ZS5lcnJvcmVkKSYmIXRoaXMuX3dyaXRhYmxlU3RhdGUuZmluaXNoZWQpfX19KTt2YXIgJF89Z24uZGVzdHJveTtpZS5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbih0LGUpe2xldCByPXRoaXMuX3dyaXRhYmxlU3RhdGU7cmV0dXJuICFyLmRlc3Ryb3llZCYmKHIuYnVmZmVyZWRJbmRleDxyLmJ1ZmZlcmVkLmxlbmd0aHx8cltGcl0ubGVuZ3RoKSYmdXIubmV4dFRpY2sob28sciksJF8uY2FsbCh0aGlzLHQsZSksdGhpc307aWUucHJvdG90eXBlLl91bmRlc3Ryb3k9Z24udW5kZXN0cm95O2llLnByb3RvdHlwZS5fZGVzdHJveT1mdW5jdGlvbih0LGUpe2UodCk7fTtpZS5wcm90b3R5cGVbQ18uY2FwdHVyZVJlamVjdGlvblN5bWJvbF09ZnVuY3Rpb24odCl7dGhpcy5kZXN0cm95KHQpO307dmFyIGlvO2Z1bmN0aW9uIGZoKCl7cmV0dXJuIGlvPT09dm9pZCAwJiYoaW89e30pLGlvfWllLmZyb21XZWI9ZnVuY3Rpb24odCxlKXtyZXR1cm4gZmgoKS5uZXdTdHJlYW1Xcml0YWJsZUZyb21Xcml0YWJsZVN0cmVhbSh0LGUpfTtpZS50b1dlYj1mdW5jdGlvbih0KXtyZXR1cm4gZmgoKS5uZXdXcml0YWJsZVN0cmVhbUZyb21TdHJlYW1Xcml0YWJsZSh0KX07fSk7dmFyIFNoPU0oKGJSLEVoKT0+e3YoKTttKCk7XygpO3ZhciBmbz1VdCgpLEhfPSh5ZSgpLFgoX2UpKSx7aXNSZWFkYWJsZTpWXyxpc1dyaXRhYmxlOnpfLGlzSXRlcmFibGU6aGgsaXNOb2RlU3RyZWFtOktfLGlzUmVhZGFibGVOb2RlU3RyZWFtOmRoLGlzV3JpdGFibGVOb2RlU3RyZWFtOnBoLGlzRHVwbGV4Tm9kZVN0cmVhbTpHX309dHQoKSxnaD1tdCgpLHtBYm9ydEVycm9yOnZoLGNvZGVzOntFUlJfSU5WQUxJRF9BUkdfVFlQRTpRXyxFUlJfSU5WQUxJRF9SRVRVUk5fVkFMVUU6eWh9fT1TZSgpLHtkZXN0cm95ZXI6V3J9PXRyKCksWV89bnQoKSxKXz1kaSgpLHtjcmVhdGVEZWZlcnJlZFByb21pc2U6Ymh9PUplKCksd2g9WXMoKSxfaD1nbG9iYWxUaGlzLkJsb2J8fEhfLkJsb2IsWF89dHlwZW9mIF9oPFwidVwiP2Z1bmN0aW9uKGUpe3JldHVybiBlIGluc3RhbmNlb2YgX2h9OmZ1bmN0aW9uKGUpe3JldHVybiAhMX0sWl89Z2xvYmFsVGhpcy5BYm9ydENvbnRyb2xsZXJ8fEhpKCkuQWJvcnRDb250cm9sbGVyLHtGdW5jdGlvblByb3RvdHlwZUNhbGw6bWh9PWNlKCksZnI9Y2xhc3MgZXh0ZW5kcyBZX3tjb25zdHJ1Y3RvcihlKXtzdXBlcihlKSxlPy5yZWFkYWJsZT09PSExJiYodGhpcy5fcmVhZGFibGVTdGF0ZS5yZWFkYWJsZT0hMSx0aGlzLl9yZWFkYWJsZVN0YXRlLmVuZGVkPSEwLHRoaXMuX3JlYWRhYmxlU3RhdGUuZW5kRW1pdHRlZD0hMCksZT8ud3JpdGFibGU9PT0hMSYmKHRoaXMuX3dyaXRhYmxlU3RhdGUud3JpdGFibGU9ITEsdGhpcy5fd3JpdGFibGVTdGF0ZS5lbmRpbmc9ITAsdGhpcy5fd3JpdGFibGVTdGF0ZS5lbmRlZD0hMCx0aGlzLl93cml0YWJsZVN0YXRlLmZpbmlzaGVkPSEwKTt9fTtFaC5leHBvcnRzPWZ1bmN0aW9uIHQoZSxyKXtpZihHXyhlKSlyZXR1cm4gZTtpZihkaChlKSlyZXR1cm4geW4oe3JlYWRhYmxlOmV9KTtpZihwaChlKSlyZXR1cm4geW4oe3dyaXRhYmxlOmV9KTtpZihLXyhlKSlyZXR1cm4geW4oe3dyaXRhYmxlOiExLHJlYWRhYmxlOiExfSk7aWYodHlwZW9mIGU9PVwiZnVuY3Rpb25cIil7bGV0e3ZhbHVlOm4sd3JpdGU6byxmaW5hbDpzLGRlc3Ryb3k6YX09ZTAoZSk7aWYoaGgobikpcmV0dXJuIHdoKGZyLG4se29iamVjdE1vZGU6ITAsd3JpdGU6byxmaW5hbDpzLGRlc3Ryb3k6YX0pO2xldCB1PW4/LnRoZW47aWYodHlwZW9mIHU9PVwiZnVuY3Rpb25cIil7bGV0IGMsaD1taCh1LG4sZD0+e2lmKGQhPW51bGwpdGhyb3cgbmV3IHloKFwibnVsbHlcIixcImJvZHlcIixkKX0sZD0+e1dyKGMsZCk7fSk7cmV0dXJuIGM9bmV3IGZyKHtvYmplY3RNb2RlOiEwLHJlYWRhYmxlOiExLHdyaXRlOm8sZmluYWwoZCl7cyhhc3luYygpPT57dHJ5e2F3YWl0IGgsZm8ubmV4dFRpY2soZCxudWxsKTt9Y2F0Y2goZyl7Zm8ubmV4dFRpY2soZCxnKTt9fSk7fSxkZXN0cm95OmF9KX10aHJvdyBuZXcgeWgoXCJJdGVyYWJsZSwgQXN5bmNJdGVyYWJsZSBvciBBc3luY0Z1bmN0aW9uXCIscixuKX1pZihYXyhlKSlyZXR1cm4gdChlLmFycmF5QnVmZmVyKCkpO2lmKGhoKGUpKXJldHVybiB3aChmcixlLHtvYmplY3RNb2RlOiEwLHdyaXRhYmxlOiExfSk7aWYodHlwZW9mIGU/LndyaXRhYmxlPT1cIm9iamVjdFwifHx0eXBlb2YgZT8ucmVhZGFibGU9PVwib2JqZWN0XCIpe2xldCBuPWUhPW51bGwmJmUucmVhZGFibGU/ZGgoZT8ucmVhZGFibGUpP2U/LnJlYWRhYmxlOnQoZS5yZWFkYWJsZSk6dm9pZCAwLG89ZSE9bnVsbCYmZS53cml0YWJsZT9waChlPy53cml0YWJsZSk/ZT8ud3JpdGFibGU6dChlLndyaXRhYmxlKTp2b2lkIDA7cmV0dXJuIHluKHtyZWFkYWJsZTpuLHdyaXRhYmxlOm99KX1sZXQgaT1lPy50aGVuO2lmKHR5cGVvZiBpPT1cImZ1bmN0aW9uXCIpe2xldCBuO3JldHVybiBtaChpLGUsbz0+e28hPW51bGwmJm4ucHVzaChvKSxuLnB1c2gobnVsbCk7fSxvPT57V3IobixvKTt9KSxuPW5ldyBmcih7b2JqZWN0TW9kZTohMCx3cml0YWJsZTohMSxyZWFkKCl7fX0pfXRocm93IG5ldyBRXyhyLFtcIkJsb2JcIixcIlJlYWRhYmxlU3RyZWFtXCIsXCJXcml0YWJsZVN0cmVhbVwiLFwiU3RyZWFtXCIsXCJJdGVyYWJsZVwiLFwiQXN5bmNJdGVyYWJsZVwiLFwiRnVuY3Rpb25cIixcInsgcmVhZGFibGUsIHdyaXRhYmxlIH0gcGFpclwiLFwiUHJvbWlzZVwiXSxlKX07ZnVuY3Rpb24gZTAodCl7bGV0e3Byb21pc2U6ZSxyZXNvbHZlOnJ9PWJoKCksaT1uZXcgWl8sbj1pLnNpZ25hbDtyZXR1cm4ge3ZhbHVlOnQoYXN5bmMgZnVuY3Rpb24qKCl7Zm9yKDs7KXtsZXQgcz1lO2U9bnVsbDtsZXR7Y2h1bms6YSxkb25lOnUsY2I6Y309YXdhaXQgcztpZihmby5uZXh0VGljayhjKSx1KXJldHVybjtpZihuLmFib3J0ZWQpdGhyb3cgbmV3IHZoKHZvaWQgMCx7Y2F1c2U6bi5yZWFzb259KTsoKHtwcm9taXNlOmUscmVzb2x2ZTpyfT1iaCgpKSkseWllbGQgYTt9fSgpLHtzaWduYWw6bn0pLHdyaXRlKHMsYSx1KXtsZXQgYz1yO3I9bnVsbCxjKHtjaHVuazpzLGRvbmU6ITEsY2I6dX0pO30sZmluYWwocyl7bGV0IGE9cjtyPW51bGwsYSh7ZG9uZTohMCxjYjpzfSk7fSxkZXN0cm95KHMsYSl7aS5hYm9ydCgpLGEocyk7fX19ZnVuY3Rpb24geW4odCl7bGV0IGU9dC5yZWFkYWJsZSYmdHlwZW9mIHQucmVhZGFibGUucmVhZCE9XCJmdW5jdGlvblwiP0pfLndyYXAodC5yZWFkYWJsZSk6dC5yZWFkYWJsZSxyPXQud3JpdGFibGUsaT0hIVZfKGUpLG49ISF6XyhyKSxvLHMsYSx1LGM7ZnVuY3Rpb24gaChkKXtsZXQgZz11O3U9bnVsbCxnP2coZCk6ZCYmYy5kZXN0cm95KGQpO31yZXR1cm4gYz1uZXcgZnIoe3JlYWRhYmxlT2JqZWN0TW9kZTohIShlIT1udWxsJiZlLnJlYWRhYmxlT2JqZWN0TW9kZSksd3JpdGFibGVPYmplY3RNb2RlOiEhKHIhPW51bGwmJnIud3JpdGFibGVPYmplY3RNb2RlKSxyZWFkYWJsZTppLHdyaXRhYmxlOm59KSxuJiYoZ2gocixkPT57bj0hMSxkJiZXcihlLGQpLGgoZCk7fSksYy5fd3JpdGU9ZnVuY3Rpb24oZCxnLHkpe3Iud3JpdGUoZCxnKT95KCk6bz15O30sYy5fZmluYWw9ZnVuY3Rpb24oZCl7ci5lbmQoKSxzPWQ7fSxyLm9uKFwiZHJhaW5cIixmdW5jdGlvbigpe2lmKG8pe2xldCBkPW87bz1udWxsLGQoKTt9fSksci5vbihcImZpbmlzaFwiLGZ1bmN0aW9uKCl7aWYocyl7bGV0IGQ9cztzPW51bGwsZCgpO319KSksaSYmKGdoKGUsZD0+e2k9ITEsZCYmV3IoZSxkKSxoKGQpO30pLGUub24oXCJyZWFkYWJsZVwiLGZ1bmN0aW9uKCl7aWYoYSl7bGV0IGQ9YTthPW51bGwsZCgpO319KSxlLm9uKFwiZW5kXCIsZnVuY3Rpb24oKXtjLnB1c2gobnVsbCk7fSksYy5fcmVhZD1mdW5jdGlvbigpe2Zvcig7Oyl7bGV0IGQ9ZS5yZWFkKCk7aWYoZD09PW51bGwpe2E9Yy5fcmVhZDtyZXR1cm59aWYoIWMucHVzaChkKSlyZXR1cm59fSksYy5fZGVzdHJveT1mdW5jdGlvbihkLGcpeyFkJiZ1IT09bnVsbCYmKGQ9bmV3IHZoKSxhPW51bGwsbz1udWxsLHM9bnVsbCx1PT09bnVsbD9nKGQpOih1PWcsV3IocixkKSxXcihlLGQpKTt9LGN9fSk7dmFyIG50PU0oKFJSLFRoKT0+e3YoKTttKCk7XygpO3ZhcntPYmplY3REZWZpbmVQcm9wZXJ0aWVzOnQwLE9iamVjdEdldE93blByb3BlcnR5RGVzY3JpcHRvcjpBdCxPYmplY3RLZXlzOnIwLE9iamVjdFNldFByb3RvdHlwZU9mOkFofT1jZSgpO1RoLmV4cG9ydHM9VmU7dmFyIHBvPWRpKCksTmU9dW8oKTtBaChWZS5wcm90b3R5cGUscG8ucHJvdG90eXBlKTtBaChWZSxwbyk7e2xldCB0PXIwKE5lLnByb3RvdHlwZSk7Zm9yKGxldCBlPTA7ZTx0Lmxlbmd0aDtlKyspe2xldCByPXRbZV07VmUucHJvdG90eXBlW3JdfHwoVmUucHJvdG90eXBlW3JdPU5lLnByb3RvdHlwZVtyXSk7fX1mdW5jdGlvbiBWZSh0KXtpZighKHRoaXMgaW5zdGFuY2VvZiBWZSkpcmV0dXJuIG5ldyBWZSh0KTtwby5jYWxsKHRoaXMsdCksTmUuY2FsbCh0aGlzLHQpLHQ/KHRoaXMuYWxsb3dIYWxmT3Blbj10LmFsbG93SGFsZk9wZW4hPT0hMSx0LnJlYWRhYmxlPT09ITEmJih0aGlzLl9yZWFkYWJsZVN0YXRlLnJlYWRhYmxlPSExLHRoaXMuX3JlYWRhYmxlU3RhdGUuZW5kZWQ9ITAsdGhpcy5fcmVhZGFibGVTdGF0ZS5lbmRFbWl0dGVkPSEwKSx0LndyaXRhYmxlPT09ITEmJih0aGlzLl93cml0YWJsZVN0YXRlLndyaXRhYmxlPSExLHRoaXMuX3dyaXRhYmxlU3RhdGUuZW5kaW5nPSEwLHRoaXMuX3dyaXRhYmxlU3RhdGUuZW5kZWQ9ITAsdGhpcy5fd3JpdGFibGVTdGF0ZS5maW5pc2hlZD0hMCkpOnRoaXMuYWxsb3dIYWxmT3Blbj0hMDt9dDAoVmUucHJvdG90eXBlLHt3cml0YWJsZTp7X19wcm90b19fOm51bGwsLi4uQXQoTmUucHJvdG90eXBlLFwid3JpdGFibGVcIil9LHdyaXRhYmxlSGlnaFdhdGVyTWFyazp7X19wcm90b19fOm51bGwsLi4uQXQoTmUucHJvdG90eXBlLFwid3JpdGFibGVIaWdoV2F0ZXJNYXJrXCIpfSx3cml0YWJsZU9iamVjdE1vZGU6e19fcHJvdG9fXzpudWxsLC4uLkF0KE5lLnByb3RvdHlwZSxcIndyaXRhYmxlT2JqZWN0TW9kZVwiKX0sd3JpdGFibGVCdWZmZXI6e19fcHJvdG9fXzpudWxsLC4uLkF0KE5lLnByb3RvdHlwZSxcIndyaXRhYmxlQnVmZmVyXCIpfSx3cml0YWJsZUxlbmd0aDp7X19wcm90b19fOm51bGwsLi4uQXQoTmUucHJvdG90eXBlLFwid3JpdGFibGVMZW5ndGhcIil9LHdyaXRhYmxlRmluaXNoZWQ6e19fcHJvdG9fXzpudWxsLC4uLkF0KE5lLnByb3RvdHlwZSxcIndyaXRhYmxlRmluaXNoZWRcIil9LHdyaXRhYmxlQ29ya2VkOntfX3Byb3RvX186bnVsbCwuLi5BdChOZS5wcm90b3R5cGUsXCJ3cml0YWJsZUNvcmtlZFwiKX0sd3JpdGFibGVFbmRlZDp7X19wcm90b19fOm51bGwsLi4uQXQoTmUucHJvdG90eXBlLFwid3JpdGFibGVFbmRlZFwiKX0sd3JpdGFibGVOZWVkRHJhaW46e19fcHJvdG9fXzpudWxsLC4uLkF0KE5lLnByb3RvdHlwZSxcIndyaXRhYmxlTmVlZERyYWluXCIpfSxkZXN0cm95ZWQ6e19fcHJvdG9fXzpudWxsLGdldCgpe3JldHVybiB0aGlzLl9yZWFkYWJsZVN0YXRlPT09dm9pZCAwfHx0aGlzLl93cml0YWJsZVN0YXRlPT09dm9pZCAwPyExOnRoaXMuX3JlYWRhYmxlU3RhdGUuZGVzdHJveWVkJiZ0aGlzLl93cml0YWJsZVN0YXRlLmRlc3Ryb3llZH0sc2V0KHQpe3RoaXMuX3JlYWRhYmxlU3RhdGUmJnRoaXMuX3dyaXRhYmxlU3RhdGUmJih0aGlzLl9yZWFkYWJsZVN0YXRlLmRlc3Ryb3llZD10LHRoaXMuX3dyaXRhYmxlU3RhdGUuZGVzdHJveWVkPXQpO319fSk7dmFyIGNvO2Z1bmN0aW9uIEloKCl7cmV0dXJuIGNvPT09dm9pZCAwJiYoY289e30pLGNvfVZlLmZyb21XZWI9ZnVuY3Rpb24odCxlKXtyZXR1cm4gSWgoKS5uZXdTdHJlYW1EdXBsZXhGcm9tUmVhZGFibGVXcml0YWJsZVBhaXIodCxlKX07VmUudG9XZWI9ZnVuY3Rpb24odCl7cmV0dXJuIEloKCkubmV3UmVhZGFibGVXcml0YWJsZVBhaXJGcm9tRHVwbGV4KHQpfTt2YXIgaG87VmUuZnJvbT1mdW5jdGlvbih0KXtyZXR1cm4gaG98fChobz1TaCgpKSxobyh0LFwiYm9keVwiKX07fSk7dmFyIGJvPU0oKE5SLENoKT0+e3YoKTttKCk7XygpO3ZhcntPYmplY3RTZXRQcm90b3R5cGVPZjpSaCxTeW1ib2w6aTB9PWNlKCk7Q2guZXhwb3J0cz1JdDt2YXJ7RVJSX01FVEhPRF9OT1RfSU1QTEVNRU5URUQ6bjB9PVNlKCkuY29kZXMseW89bnQoKSx7Z2V0SGlnaFdhdGVyTWFyazpzMH09c24oKTtSaChJdC5wcm90b3R5cGUseW8ucHJvdG90eXBlKTtSaChJdCx5byk7dmFyIGJpPWkwKFwia0NhbGxiYWNrXCIpO2Z1bmN0aW9uIEl0KHQpe2lmKCEodGhpcyBpbnN0YW5jZW9mIEl0KSlyZXR1cm4gbmV3IEl0KHQpO2xldCBlPXQ/czAodGhpcyx0LFwicmVhZGFibGVIaWdoV2F0ZXJNYXJrXCIsITApOm51bGw7ZT09PTAmJih0PXsuLi50LGhpZ2hXYXRlck1hcms6bnVsbCxyZWFkYWJsZUhpZ2hXYXRlck1hcms6ZSx3cml0YWJsZUhpZ2hXYXRlck1hcms6dC53cml0YWJsZUhpZ2hXYXRlck1hcmt8fDB9KSx5by5jYWxsKHRoaXMsdCksdGhpcy5fcmVhZGFibGVTdGF0ZS5zeW5jPSExLHRoaXNbYmldPW51bGwsdCYmKHR5cGVvZiB0LnRyYW5zZm9ybT09XCJmdW5jdGlvblwiJiYodGhpcy5fdHJhbnNmb3JtPXQudHJhbnNmb3JtKSx0eXBlb2YgdC5mbHVzaD09XCJmdW5jdGlvblwiJiYodGhpcy5fZmx1c2g9dC5mbHVzaCkpLHRoaXMub24oXCJwcmVmaW5pc2hcIixvMCk7fWZ1bmN0aW9uIGdvKHQpe3R5cGVvZiB0aGlzLl9mbHVzaD09XCJmdW5jdGlvblwiJiYhdGhpcy5kZXN0cm95ZWQ/dGhpcy5fZmx1c2goKGUscik9PntpZihlKXt0P3QoZSk6dGhpcy5kZXN0cm95KGUpO3JldHVybn1yIT1udWxsJiZ0aGlzLnB1c2gociksdGhpcy5wdXNoKG51bGwpLHQmJnQoKTt9KToodGhpcy5wdXNoKG51bGwpLHQmJnQoKSk7fWZ1bmN0aW9uIG8wKCl7dGhpcy5fZmluYWwhPT1nbyYmZ28uY2FsbCh0aGlzKTt9SXQucHJvdG90eXBlLl9maW5hbD1nbztJdC5wcm90b3R5cGUuX3RyYW5zZm9ybT1mdW5jdGlvbih0LGUscil7dGhyb3cgbmV3IG4wKFwiX3RyYW5zZm9ybSgpXCIpfTtJdC5wcm90b3R5cGUuX3dyaXRlPWZ1bmN0aW9uKHQsZSxyKXtsZXQgaT10aGlzLl9yZWFkYWJsZVN0YXRlLG49dGhpcy5fd3JpdGFibGVTdGF0ZSxvPWkubGVuZ3RoO3RoaXMuX3RyYW5zZm9ybSh0LGUsKHMsYSk9PntpZihzKXtyKHMpO3JldHVybn1hIT1udWxsJiZ0aGlzLnB1c2goYSksbi5lbmRlZHx8bz09PWkubGVuZ3RofHxpLmxlbmd0aDxpLmhpZ2hXYXRlck1hcms/cigpOnRoaXNbYmldPXI7fSk7fTtJdC5wcm90b3R5cGUuX3JlYWQ9ZnVuY3Rpb24oKXtpZih0aGlzW2JpXSl7bGV0IHQ9dGhpc1tiaV07dGhpc1tiaV09bnVsbCx0KCk7fX07fSk7dmFyIF9vPU0oKEtSLFBoKT0+e3YoKTttKCk7XygpO3ZhcntPYmplY3RTZXRQcm90b3R5cGVPZjpCaH09Y2UoKTtQaC5leHBvcnRzPSRyO3ZhciB3bz1ibygpO0JoKCRyLnByb3RvdHlwZSx3by5wcm90b3R5cGUpO0JoKCRyLHdvKTtmdW5jdGlvbiAkcih0KXtpZighKHRoaXMgaW5zdGFuY2VvZiAkcikpcmV0dXJuIG5ldyAkcih0KTt3by5jYWxsKHRoaXMsdCk7fSRyLnByb3RvdHlwZS5fdHJhbnNmb3JtPWZ1bmN0aW9uKHQsZSxyKXtyKG51bGwsdCk7fTt9KTt2YXIgbW49TSgoaUMsTGgpPT57digpO20oKTtfKCk7dmFyIHdpPVV0KCkse0FycmF5SXNBcnJheTphMCxQcm9taXNlOmwwLFN5bWJvbEFzeW5jSXRlcmF0b3I6dTB9PWNlKCksX249bXQoKSx7b25jZTpmMH09SmUoKSxjMD10cigpLE9oPW50KCkse2FnZ3JlZ2F0ZVR3b0Vycm9yczpoMCxjb2Rlczp7RVJSX0lOVkFMSURfQVJHX1RZUEU6Um8sRVJSX0lOVkFMSURfUkVUVVJOX1ZBTFVFOm1vLEVSUl9NSVNTSU5HX0FSR1M6ZDAsRVJSX1NUUkVBTV9ERVNUUk9ZRUQ6cDAsRVJSX1NUUkVBTV9QUkVNQVRVUkVfQ0xPU0U6ZzB9LEFib3J0RXJyb3I6eTB9PVNlKCkse3ZhbGlkYXRlRnVuY3Rpb246YjAsdmFsaWRhdGVBYm9ydFNpZ25hbDp3MH09ZmkoKSx7aXNJdGVyYWJsZTpjcixpc1JlYWRhYmxlOnZvLGlzUmVhZGFibGVOb2RlU3RyZWFtOnduLGlzTm9kZVN0cmVhbTpraCxpc1RyYW5zZm9ybVN0cmVhbTpIcixpc1dlYlN0cmVhbTpfMCxpc1JlYWRhYmxlU3RyZWFtOkVvLGlzUmVhZGFibGVFbmRlZDptMH09dHQoKSx2MD1nbG9iYWxUaGlzLkFib3J0Q29udHJvbGxlcnx8SGkoKS5BYm9ydENvbnRyb2xsZXIsU28sQW87ZnVuY3Rpb24geGgodCxlLHIpe2xldCBpPSExO3Qub24oXCJjbG9zZVwiLCgpPT57aT0hMDt9KTtsZXQgbj1fbih0LHtyZWFkYWJsZTplLHdyaXRhYmxlOnJ9LG89PntpPSFvO30pO3JldHVybiB7ZGVzdHJveTpvPT57aXx8KGk9ITAsYzAuZGVzdHJveWVyKHQsb3x8bmV3IHAwKFwicGlwZVwiKSkpO30sY2xlYW51cDpufX1mdW5jdGlvbiBFMCh0KXtyZXR1cm4gYjAodFt0Lmxlbmd0aC0xXSxcInN0cmVhbXNbc3RyZWFtLmxlbmd0aCAtIDFdXCIpLHQucG9wKCl9ZnVuY3Rpb24gSW8odCl7aWYoY3IodCkpcmV0dXJuIHQ7aWYod24odCkpcmV0dXJuIFMwKHQpO3Rocm93IG5ldyBSbyhcInZhbFwiLFtcIlJlYWRhYmxlXCIsXCJJdGVyYWJsZVwiLFwiQXN5bmNJdGVyYWJsZVwiXSx0KX1hc3luYyBmdW5jdGlvbipTMCh0KXtBb3x8KEFvPWRpKCkpLHlpZWxkKkFvLnByb3RvdHlwZVt1MF0uY2FsbCh0KTt9YXN5bmMgZnVuY3Rpb24gYm4odCxlLHIse2VuZDppfSl7bGV0IG4sbz1udWxsLHM9Yz0+e2lmKGMmJihuPWMpLG8pe2xldCBoPW87bz1udWxsLGgoKTt9fSxhPSgpPT5uZXcgbDAoKGMsaCk9PntuP2gobik6bz0oKT0+e24/aChuKTpjKCk7fTt9KTtlLm9uKFwiZHJhaW5cIixzKTtsZXQgdT1fbihlLHtyZWFkYWJsZTohMX0scyk7dHJ5e2Uud3JpdGFibGVOZWVkRHJhaW4mJmF3YWl0IGEoKTtmb3IgYXdhaXQobGV0IGMgb2YgdCllLndyaXRlKGMpfHxhd2FpdCBhKCk7aSYmZS5lbmQoKSxhd2FpdCBhKCkscigpO31jYXRjaChjKXtyKG4hPT1jP2gwKG4sYyk6Yyk7fWZpbmFsbHl7dSgpLGUub2ZmKFwiZHJhaW5cIixzKTt9fWFzeW5jIGZ1bmN0aW9uIFRvKHQsZSxyLHtlbmQ6aX0pe0hyKGUpJiYoZT1lLndyaXRhYmxlKTtsZXQgbj1lLmdldFdyaXRlcigpO3RyeXtmb3IgYXdhaXQobGV0IG8gb2YgdClhd2FpdCBuLnJlYWR5LG4ud3JpdGUobykuY2F0Y2goKCk9Pnt9KTthd2FpdCBuLnJlYWR5LGkmJmF3YWl0IG4uY2xvc2UoKSxyKCk7fWNhdGNoKG8pe3RyeXthd2FpdCBuLmFib3J0KG8pLHIobyk7fWNhdGNoKHMpe3Iocyk7fX19ZnVuY3Rpb24gQTAoLi4udCl7cmV0dXJuIE1oKHQsZjAoRTAodCkpKX1mdW5jdGlvbiBNaCh0LGUscil7aWYodC5sZW5ndGg9PT0xJiZhMCh0WzBdKSYmKHQ9dFswXSksdC5sZW5ndGg8Mil0aHJvdyBuZXcgZDAoXCJzdHJlYW1zXCIpO2xldCBpPW5ldyB2MCxuPWkuc2lnbmFsLG89cj8uc2lnbmFsLHM9W107dzAobyxcIm9wdGlvbnMuc2lnbmFsXCIpO2Z1bmN0aW9uIGEoKXt5KG5ldyB5MCk7fW8/LmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLGEpO2xldCB1LGMsaD1bXSxkPTA7ZnVuY3Rpb24gZyhDKXt5KEMsLS1kPT09MCk7fWZ1bmN0aW9uIHkoQyxSKXtpZihDJiYoIXV8fHUuY29kZT09PVwiRVJSX1NUUkVBTV9QUkVNQVRVUkVfQ0xPU0VcIikmJih1PUMpLCEoIXUmJiFSKSl7Zm9yKDtoLmxlbmd0aDspaC5zaGlmdCgpKHUpO28/LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLGEpLGkuYWJvcnQoKSxSJiYodXx8cy5mb3JFYWNoKFU9PlUoKSksd2kubmV4dFRpY2soZSx1LGMpKTt9fWxldCB3O2ZvcihsZXQgQz0wO0M8dC5sZW5ndGg7QysrKXtsZXQgUj10W0NdLFU9Qzx0Lmxlbmd0aC0xLE49Qz4wLFc9VXx8cj8uZW5kIT09ITEsSz1DPT09dC5sZW5ndGgtMTtpZihraChSKSl7bGV0IHo9ZnVuY3Rpb24oUSl7USYmUS5uYW1lIT09XCJBYm9ydEVycm9yXCImJlEuY29kZSE9PVwiRVJSX1NUUkVBTV9QUkVNQVRVUkVfQ0xPU0VcIiYmZyhRKTt9O2lmKFcpe2xldHtkZXN0cm95OlEsY2xlYW51cDpkZX09eGgoUixVLE4pO2gucHVzaChRKSx2byhSKSYmSyYmcy5wdXNoKGRlKTt9Ui5vbihcImVycm9yXCIseiksdm8oUikmJksmJnMucHVzaCgoKT0+e1IucmVtb3ZlTGlzdGVuZXIoXCJlcnJvclwiLHopO30pO31pZihDPT09MClpZih0eXBlb2YgUj09XCJmdW5jdGlvblwiKXtpZih3PVIoe3NpZ25hbDpufSksIWNyKHcpKXRocm93IG5ldyBtbyhcIkl0ZXJhYmxlLCBBc3luY0l0ZXJhYmxlIG9yIFN0cmVhbVwiLFwic291cmNlXCIsdyl9ZWxzZSBjcihSKXx8d24oUil8fEhyKFIpP3c9Ujp3PU9oLmZyb20oUik7ZWxzZSBpZih0eXBlb2YgUj09XCJmdW5jdGlvblwiKXtpZihIcih3KSl7dmFyIEU7dz1JbygoRT13KT09PW51bGx8fEU9PT12b2lkIDA/dm9pZCAwOkUucmVhZGFibGUpO31lbHNlIHc9SW8odyk7aWYodz1SKHcse3NpZ25hbDpufSksVSl7aWYoIWNyKHcsITApKXRocm93IG5ldyBtbyhcIkFzeW5jSXRlcmFibGVcIixgdHJhbnNmb3JtWyR7Qy0xfV1gLHcpfWVsc2Uge3ZhciBTO1NvfHwoU289X28oKSk7bGV0IHo9bmV3IFNvKHtvYmplY3RNb2RlOiEwfSksUT0oUz13KT09PW51bGx8fFM9PT12b2lkIDA/dm9pZCAwOlMudGhlbjtpZih0eXBlb2YgUT09XCJmdW5jdGlvblwiKWQrKyxRLmNhbGwodyxwZT0+e2M9cGUscGUhPW51bGwmJnoud3JpdGUocGUpLFcmJnouZW5kKCksd2kubmV4dFRpY2soZyk7fSxwZT0+e3ouZGVzdHJveShwZSksd2kubmV4dFRpY2soZyxwZSk7fSk7ZWxzZSBpZihjcih3LCEwKSlkKyssYm4odyx6LGcse2VuZDpXfSk7ZWxzZSBpZihFbyh3KXx8SHIodykpe2xldCBwZT13LnJlYWRhYmxlfHx3O2QrKyxibihwZSx6LGcse2VuZDpXfSk7fWVsc2UgdGhyb3cgbmV3IG1vKFwiQXN5bmNJdGVyYWJsZSBvciBQcm9taXNlXCIsXCJkZXN0aW5hdGlvblwiLHcpO3c9ejtsZXR7ZGVzdHJveTpkZSxjbGVhbnVwOkd0fT14aCh3LCExLCEwKTtoLnB1c2goZGUpLEsmJnMucHVzaChHdCk7fX1lbHNlIGlmKGtoKFIpKXtpZih3bih3KSl7ZCs9MjtsZXQgej1JMCh3LFIsZyx7ZW5kOld9KTt2byhSKSYmSyYmcy5wdXNoKHopO31lbHNlIGlmKEhyKHcpfHxFbyh3KSl7bGV0IHo9dy5yZWFkYWJsZXx8dztkKyssYm4oeixSLGcse2VuZDpXfSk7fWVsc2UgaWYoY3IodykpZCsrLGJuKHcsUixnLHtlbmQ6V30pO2Vsc2UgdGhyb3cgbmV3IFJvKFwidmFsXCIsW1wiUmVhZGFibGVcIixcIkl0ZXJhYmxlXCIsXCJBc3luY0l0ZXJhYmxlXCIsXCJSZWFkYWJsZVN0cmVhbVwiLFwiVHJhbnNmb3JtU3RyZWFtXCJdLHcpO3c9Ujt9ZWxzZSBpZihfMChSKSl7aWYod24odykpZCsrLFRvKElvKHcpLFIsZyx7ZW5kOld9KTtlbHNlIGlmKEVvKHcpfHxjcih3KSlkKyssVG8odyxSLGcse2VuZDpXfSk7ZWxzZSBpZihIcih3KSlkKyssVG8ody5yZWFkYWJsZSxSLGcse2VuZDpXfSk7ZWxzZSB0aHJvdyBuZXcgUm8oXCJ2YWxcIixbXCJSZWFkYWJsZVwiLFwiSXRlcmFibGVcIixcIkFzeW5jSXRlcmFibGVcIixcIlJlYWRhYmxlU3RyZWFtXCIsXCJUcmFuc2Zvcm1TdHJlYW1cIl0sdyk7dz1SO31lbHNlIHc9T2guZnJvbShSKTt9cmV0dXJuIChuIT1udWxsJiZuLmFib3J0ZWR8fG8hPW51bGwmJm8uYWJvcnRlZCkmJndpLm5leHRUaWNrKGEpLHd9ZnVuY3Rpb24gSTAodCxlLHIse2VuZDppfSl7bGV0IG49ITE7aWYoZS5vbihcImNsb3NlXCIsKCk9PntufHxyKG5ldyBnMCk7fSksdC5waXBlKGUse2VuZDohMX0pLGkpe2xldCBzPWZ1bmN0aW9uKCl7bj0hMCxlLmVuZCgpO307bTAodCk/d2kubmV4dFRpY2socyk6dC5vbmNlKFwiZW5kXCIscyk7fWVsc2UgcigpO3JldHVybiBfbih0LHtyZWFkYWJsZTohMCx3cml0YWJsZTohMX0scz0+e2xldCBhPXQuX3JlYWRhYmxlU3RhdGU7cyYmcy5jb2RlPT09XCJFUlJfU1RSRUFNX1BSRU1BVFVSRV9DTE9TRVwiJiZhJiZhLmVuZGVkJiYhYS5lcnJvcmVkJiYhYS5lcnJvckVtaXR0ZWQ/dC5vbmNlKFwiZW5kXCIscikub25jZShcImVycm9yXCIscik6cihzKTt9KSxfbihlLHtyZWFkYWJsZTohMSx3cml0YWJsZTohMH0scil9TGguZXhwb3J0cz17cGlwZWxpbmVJbXBsOk1oLHBpcGVsaW5lOkEwfTt9KTt2YXIgQm89TSgoZEMsRmgpPT57digpO20oKTtfKCk7dmFye3BpcGVsaW5lOlQwfT1tbigpLHZuPW50KCkse2Rlc3Ryb3llcjpSMH09dHIoKSx7aXNOb2RlU3RyZWFtOkVuLGlzUmVhZGFibGU6VWgsaXNXcml0YWJsZTpOaCxpc1dlYlN0cmVhbTpDbyxpc1RyYW5zZm9ybVN0cmVhbTpocixpc1dyaXRhYmxlU3RyZWFtOnFoLGlzUmVhZGFibGVTdHJlYW06RGh9PXR0KCkse0Fib3J0RXJyb3I6QzAsY29kZXM6e0VSUl9JTlZBTElEX0FSR19WQUxVRTpqaCxFUlJfTUlTU0lOR19BUkdTOkIwfX09U2UoKSxQMD1tdCgpO0ZoLmV4cG9ydHM9ZnVuY3Rpb24oLi4uZSl7aWYoZS5sZW5ndGg9PT0wKXRocm93IG5ldyBCMChcInN0cmVhbXNcIik7aWYoZS5sZW5ndGg9PT0xKXJldHVybiB2bi5mcm9tKGVbMF0pO2xldCByPVsuLi5lXTtpZih0eXBlb2YgZVswXT09XCJmdW5jdGlvblwiJiYoZVswXT12bi5mcm9tKGVbMF0pKSx0eXBlb2YgZVtlLmxlbmd0aC0xXT09XCJmdW5jdGlvblwiKXtsZXQgeT1lLmxlbmd0aC0xO2VbeV09dm4uZnJvbShlW3ldKTt9Zm9yKGxldCB5PTA7eTxlLmxlbmd0aDsrK3kpaWYoISghRW4oZVt5XSkmJiFDbyhlW3ldKSkpe2lmKHk8ZS5sZW5ndGgtMSYmIShVaChlW3ldKXx8RGgoZVt5XSl8fGhyKGVbeV0pKSl0aHJvdyBuZXcgamgoYHN0cmVhbXNbJHt5fV1gLHJbeV0sXCJtdXN0IGJlIHJlYWRhYmxlXCIpO2lmKHk+MCYmIShOaChlW3ldKXx8cWgoZVt5XSl8fGhyKGVbeV0pKSl0aHJvdyBuZXcgamgoYHN0cmVhbXNbJHt5fV1gLHJbeV0sXCJtdXN0IGJlIHdyaXRhYmxlXCIpfWxldCBpLG4sbyxzLGE7ZnVuY3Rpb24gdSh5KXtsZXQgdz1zO3M9bnVsbCx3P3coeSk6eT9hLmRlc3Ryb3koeSk6IWcmJiFkJiZhLmRlc3Ryb3koKTt9bGV0IGM9ZVswXSxoPVQwKGUsdSksZD0hIShOaChjKXx8cWgoYyl8fGhyKGMpKSxnPSEhKFVoKGgpfHxEaChoKXx8aHIoaCkpO2lmKGE9bmV3IHZuKHt3cml0YWJsZU9iamVjdE1vZGU6ISEoYyE9bnVsbCYmYy53cml0YWJsZU9iamVjdE1vZGUpLHJlYWRhYmxlT2JqZWN0TW9kZTohIShoIT1udWxsJiZoLndyaXRhYmxlT2JqZWN0TW9kZSksd3JpdGFibGU6ZCxyZWFkYWJsZTpnfSksZCl7aWYoRW4oYykpYS5fd3JpdGU9ZnVuY3Rpb24odyxFLFMpe2Mud3JpdGUodyxFKT9TKCk6aT1TO30sYS5fZmluYWw9ZnVuY3Rpb24odyl7Yy5lbmQoKSxuPXc7fSxjLm9uKFwiZHJhaW5cIixmdW5jdGlvbigpe2lmKGkpe2xldCB3PWk7aT1udWxsLHcoKTt9fSk7ZWxzZSBpZihDbyhjKSl7bGV0IEU9KGhyKGMpP2Mud3JpdGFibGU6YykuZ2V0V3JpdGVyKCk7YS5fd3JpdGU9YXN5bmMgZnVuY3Rpb24oUyxJLEMpe3RyeXthd2FpdCBFLnJlYWR5LEUud3JpdGUoUykuY2F0Y2goKCk9Pnt9KSxDKCk7fWNhdGNoKFIpe0MoUik7fX0sYS5fZmluYWw9YXN5bmMgZnVuY3Rpb24oUyl7dHJ5e2F3YWl0IEUucmVhZHksRS5jbG9zZSgpLmNhdGNoKCgpPT57fSksbj1TO31jYXRjaChJKXtTKEkpO319O31sZXQgeT1ocihoKT9oLnJlYWRhYmxlOmg7UDAoeSwoKT0+e2lmKG4pe2xldCB3PW47bj1udWxsLHcoKTt9fSk7fWlmKGcpe2lmKEVuKGgpKWgub24oXCJyZWFkYWJsZVwiLGZ1bmN0aW9uKCl7aWYobyl7bGV0IHk9bztvPW51bGwseSgpO319KSxoLm9uKFwiZW5kXCIsZnVuY3Rpb24oKXthLnB1c2gobnVsbCk7fSksYS5fcmVhZD1mdW5jdGlvbigpe2Zvcig7Oyl7bGV0IHk9aC5yZWFkKCk7aWYoeT09PW51bGwpe289YS5fcmVhZDtyZXR1cm59aWYoIWEucHVzaCh5KSlyZXR1cm59fTtlbHNlIGlmKENvKGgpKXtsZXQgdz0oaHIoaCk/aC5yZWFkYWJsZTpoKS5nZXRSZWFkZXIoKTthLl9yZWFkPWFzeW5jIGZ1bmN0aW9uKCl7Zm9yKDs7KXRyeXtsZXR7dmFsdWU6RSxkb25lOlN9PWF3YWl0IHcucmVhZCgpO2lmKCFhLnB1c2goRSkpcmV0dXJuO2lmKFMpe2EucHVzaChudWxsKTtyZXR1cm59fWNhdGNoe3JldHVybn19O319cmV0dXJuIGEuX2Rlc3Ryb3k9ZnVuY3Rpb24oeSx3KXsheSYmcyE9PW51bGwmJih5PW5ldyBDMCksbz1udWxsLGk9bnVsbCxuPW51bGwscz09PW51bGw/dyh5KToocz13LEVuKGgpJiZSMChoLHkpKTt9LGF9O30pO3ZhciBRaD1NKChTQyxrbyk9Pnt2KCk7bSgpO18oKTt2YXIgVmg9Z2xvYmFsVGhpcy5BYm9ydENvbnRyb2xsZXJ8fEhpKCkuQWJvcnRDb250cm9sbGVyLHtjb2Rlczp7RVJSX0lOVkFMSURfQVJHX1ZBTFVFOk8wLEVSUl9JTlZBTElEX0FSR19UWVBFOl9pLEVSUl9NSVNTSU5HX0FSR1M6azAsRVJSX09VVF9PRl9SQU5HRTp4MH0sQWJvcnRFcnJvcjpzdH09U2UoKSx7dmFsaWRhdGVBYm9ydFNpZ25hbDpkcix2YWxpZGF0ZUludGVnZXI6TTAsdmFsaWRhdGVPYmplY3Q6cHJ9PWZpKCksTDA9Y2UoKS5TeW1ib2woXCJrV2Vha1wiKSx7ZmluaXNoZWQ6VTB9PW10KCksTjA9Qm8oKSx7YWRkQWJvcnRTaWduYWxOb1ZhbGlkYXRlOnEwfT1jaSgpLHtpc1dyaXRhYmxlOkQwLGlzTm9kZVN0cmVhbTpqMH09dHQoKSx7QXJyYXlQcm90b3R5cGVQdXNoOkYwLE1hdGhGbG9vcjpXMCxOdW1iZXI6JDAsTnVtYmVySXNOYU46SDAsUHJvbWlzZTpXaCxQcm9taXNlUmVqZWN0OiRoLFByb21pc2VQcm90b3R5cGVUaGVuOlYwLFN5bWJvbDp6aH09Y2UoKSxTbj16aChcImtFbXB0eVwiKSxIaD16aChcImtFb2ZcIik7ZnVuY3Rpb24gejAodCxlKXtpZihlIT1udWxsJiZwcihlLFwib3B0aW9uc1wiKSxlPy5zaWduYWwhPW51bGwmJmRyKGUuc2lnbmFsLFwib3B0aW9ucy5zaWduYWxcIiksajAodCkmJiFEMCh0KSl0aHJvdyBuZXcgTzAoXCJzdHJlYW1cIix0LFwibXVzdCBiZSB3cml0YWJsZVwiKTtsZXQgcj1OMCh0aGlzLHQpO3JldHVybiBlIT1udWxsJiZlLnNpZ25hbCYmcTAoZS5zaWduYWwscikscn1mdW5jdGlvbiBBbih0LGUpe2lmKHR5cGVvZiB0IT1cImZ1bmN0aW9uXCIpdGhyb3cgbmV3IF9pKFwiZm5cIixbXCJGdW5jdGlvblwiLFwiQXN5bmNGdW5jdGlvblwiXSx0KTtlIT1udWxsJiZwcihlLFwib3B0aW9uc1wiKSxlPy5zaWduYWwhPW51bGwmJmRyKGUuc2lnbmFsLFwib3B0aW9ucy5zaWduYWxcIik7bGV0IHI9MTtyZXR1cm4gZT8uY29uY3VycmVuY3khPW51bGwmJihyPVcwKGUuY29uY3VycmVuY3kpKSxNMChyLFwiY29uY3VycmVuY3lcIiwxKSxhc3luYyBmdW5jdGlvbiooKXt2YXIgbixvO2xldCBzPW5ldyBWaCxhPXRoaXMsdT1bXSxjPXMuc2lnbmFsLGg9e3NpZ25hbDpjfSxkPSgpPT5zLmFib3J0KCk7ZSE9bnVsbCYmKG49ZS5zaWduYWwpIT09bnVsbCYmbiE9PXZvaWQgMCYmbi5hYm9ydGVkJiZkKCksZT09bnVsbHx8KG89ZS5zaWduYWwpPT09bnVsbHx8bz09PXZvaWQgMHx8by5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIixkKTtsZXQgZyx5LHc9ITE7ZnVuY3Rpb24gRSgpe3c9ITA7fWFzeW5jIGZ1bmN0aW9uIFMoKXt0cnl7Zm9yIGF3YWl0KGxldCBSIG9mIGEpe3ZhciBJO2lmKHcpcmV0dXJuO2lmKGMuYWJvcnRlZCl0aHJvdyBuZXcgc3Q7dHJ5e1I9dChSLGgpO31jYXRjaChVKXtSPSRoKFUpO31SIT09U24mJih0eXBlb2YoKEk9Uik9PT1udWxsfHxJPT09dm9pZCAwP3ZvaWQgMDpJLmNhdGNoKT09XCJmdW5jdGlvblwiJiZSLmNhdGNoKEUpLHUucHVzaChSKSxnJiYoZygpLGc9bnVsbCksIXcmJnUubGVuZ3RoJiZ1Lmxlbmd0aD49ciYmYXdhaXQgbmV3IFdoKFU9Pnt5PVU7fSkpO311LnB1c2goSGgpO31jYXRjaChSKXtsZXQgVT0kaChSKTtWMChVLHZvaWQgMCxFKSx1LnB1c2goVSk7fWZpbmFsbHl7dmFyIEM7dz0hMCxnJiYoZygpLGc9bnVsbCksZT09bnVsbHx8KEM9ZS5zaWduYWwpPT09bnVsbHx8Qz09PXZvaWQgMHx8Qy5yZW1vdmVFdmVudExpc3RlbmVyKFwiYWJvcnRcIixkKTt9fVMoKTt0cnl7Zm9yKDs7KXtmb3IoO3UubGVuZ3RoPjA7KXtsZXQgST1hd2FpdCB1WzBdO2lmKEk9PT1IaClyZXR1cm47aWYoYy5hYm9ydGVkKXRocm93IG5ldyBzdDtJIT09U24mJih5aWVsZCBJKSx1LnNoaWZ0KCkseSYmKHkoKSx5PW51bGwpO31hd2FpdCBuZXcgV2goST0+e2c9STt9KTt9fWZpbmFsbHl7cy5hYm9ydCgpLHc9ITAseSYmKHkoKSx5PW51bGwpO319LmNhbGwodGhpcyl9ZnVuY3Rpb24gSzAodD12b2lkIDApe3JldHVybiB0IT1udWxsJiZwcih0LFwib3B0aW9uc1wiKSx0Py5zaWduYWwhPW51bGwmJmRyKHQuc2lnbmFsLFwib3B0aW9ucy5zaWduYWxcIiksYXN5bmMgZnVuY3Rpb24qKCl7bGV0IHI9MDtmb3IgYXdhaXQobGV0IG4gb2YgdGhpcyl7dmFyIGk7aWYodCE9bnVsbCYmKGk9dC5zaWduYWwpIT09bnVsbCYmaSE9PXZvaWQgMCYmaS5hYm9ydGVkKXRocm93IG5ldyBzdCh7Y2F1c2U6dC5zaWduYWwucmVhc29ufSk7eWllbGQgW3IrKyxuXTt9fS5jYWxsKHRoaXMpfWFzeW5jIGZ1bmN0aW9uIEtoKHQsZT12b2lkIDApe2ZvciBhd2FpdChsZXQgciBvZiBPby5jYWxsKHRoaXMsdCxlKSlyZXR1cm4gITA7cmV0dXJuICExfWFzeW5jIGZ1bmN0aW9uIEcwKHQsZT12b2lkIDApe2lmKHR5cGVvZiB0IT1cImZ1bmN0aW9uXCIpdGhyb3cgbmV3IF9pKFwiZm5cIixbXCJGdW5jdGlvblwiLFwiQXN5bmNGdW5jdGlvblwiXSx0KTtyZXR1cm4gIWF3YWl0IEtoLmNhbGwodGhpcyxhc3luYyguLi5yKT0+IWF3YWl0IHQoLi4uciksZSl9YXN5bmMgZnVuY3Rpb24gUTAodCxlKXtmb3IgYXdhaXQobGV0IHIgb2YgT28uY2FsbCh0aGlzLHQsZSkpcmV0dXJuIHJ9YXN5bmMgZnVuY3Rpb24gWTAodCxlKXtpZih0eXBlb2YgdCE9XCJmdW5jdGlvblwiKXRocm93IG5ldyBfaShcImZuXCIsW1wiRnVuY3Rpb25cIixcIkFzeW5jRnVuY3Rpb25cIl0sdCk7YXN5bmMgZnVuY3Rpb24gcihpLG4pe3JldHVybiBhd2FpdCB0KGksbiksU259Zm9yIGF3YWl0KGxldCBpIG9mIEFuLmNhbGwodGhpcyxyLGUpKTt9ZnVuY3Rpb24gT28odCxlKXtpZih0eXBlb2YgdCE9XCJmdW5jdGlvblwiKXRocm93IG5ldyBfaShcImZuXCIsW1wiRnVuY3Rpb25cIixcIkFzeW5jRnVuY3Rpb25cIl0sdCk7YXN5bmMgZnVuY3Rpb24gcihpLG4pe3JldHVybiBhd2FpdCB0KGksbik/aTpTbn1yZXR1cm4gQW4uY2FsbCh0aGlzLHIsZSl9dmFyIFBvPWNsYXNzIGV4dGVuZHMgazB7Y29uc3RydWN0b3IoKXtzdXBlcihcInJlZHVjZVwiKSx0aGlzLm1lc3NhZ2U9XCJSZWR1Y2Ugb2YgYW4gZW1wdHkgc3RyZWFtIHJlcXVpcmVzIGFuIGluaXRpYWwgdmFsdWVcIjt9fTthc3luYyBmdW5jdGlvbiBKMCh0LGUscil7dmFyIGk7aWYodHlwZW9mIHQhPVwiZnVuY3Rpb25cIil0aHJvdyBuZXcgX2koXCJyZWR1Y2VyXCIsW1wiRnVuY3Rpb25cIixcIkFzeW5jRnVuY3Rpb25cIl0sdCk7ciE9bnVsbCYmcHIocixcIm9wdGlvbnNcIikscj8uc2lnbmFsIT1udWxsJiZkcihyLnNpZ25hbCxcIm9wdGlvbnMuc2lnbmFsXCIpO2xldCBuPWFyZ3VtZW50cy5sZW5ndGg+MTtpZihyIT1udWxsJiYoaT1yLnNpZ25hbCkhPT1udWxsJiZpIT09dm9pZCAwJiZpLmFib3J0ZWQpe2xldCBjPW5ldyBzdCh2b2lkIDAse2NhdXNlOnIuc2lnbmFsLnJlYXNvbn0pO3Rocm93IHRoaXMub25jZShcImVycm9yXCIsKCk9Pnt9KSxhd2FpdCBVMCh0aGlzLmRlc3Ryb3koYykpLGN9bGV0IG89bmV3IFZoLHM9by5zaWduYWw7aWYociE9bnVsbCYmci5zaWduYWwpe2xldCBjPXtvbmNlOiEwLFtMMF06dGhpc307ci5zaWduYWwuYWRkRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsKCk9Pm8uYWJvcnQoKSxjKTt9bGV0IGE9ITE7dHJ5e2ZvciBhd2FpdChsZXQgYyBvZiB0aGlzKXt2YXIgdTtpZihhPSEwLHIhPW51bGwmJih1PXIuc2lnbmFsKSE9PW51bGwmJnUhPT12b2lkIDAmJnUuYWJvcnRlZCl0aHJvdyBuZXcgc3Q7bj9lPWF3YWl0IHQoZSxjLHtzaWduYWw6c30pOihlPWMsbj0hMCk7fWlmKCFhJiYhbil0aHJvdyBuZXcgUG99ZmluYWxseXtvLmFib3J0KCk7fXJldHVybiBlfWFzeW5jIGZ1bmN0aW9uIFgwKHQpe3QhPW51bGwmJnByKHQsXCJvcHRpb25zXCIpLHQ/LnNpZ25hbCE9bnVsbCYmZHIodC5zaWduYWwsXCJvcHRpb25zLnNpZ25hbFwiKTtsZXQgZT1bXTtmb3IgYXdhaXQobGV0IGkgb2YgdGhpcyl7dmFyIHI7aWYodCE9bnVsbCYmKHI9dC5zaWduYWwpIT09bnVsbCYmciE9PXZvaWQgMCYmci5hYm9ydGVkKXRocm93IG5ldyBzdCh2b2lkIDAse2NhdXNlOnQuc2lnbmFsLnJlYXNvbn0pO0YwKGUsaSk7fXJldHVybiBlfWZ1bmN0aW9uIFowKHQsZSl7bGV0IHI9QW4uY2FsbCh0aGlzLHQsZSk7cmV0dXJuIGFzeW5jIGZ1bmN0aW9uKigpe2ZvciBhd2FpdChsZXQgbiBvZiByKXlpZWxkKm47fS5jYWxsKHRoaXMpfWZ1bmN0aW9uIEdoKHQpe2lmKHQ9JDAodCksSDAodCkpcmV0dXJuIDA7aWYodDwwKXRocm93IG5ldyB4MChcIm51bWJlclwiLFwiPj0gMFwiLHQpO3JldHVybiB0fWZ1bmN0aW9uIGVtKHQsZT12b2lkIDApe3JldHVybiBlIT1udWxsJiZwcihlLFwib3B0aW9uc1wiKSxlPy5zaWduYWwhPW51bGwmJmRyKGUuc2lnbmFsLFwib3B0aW9ucy5zaWduYWxcIiksdD1HaCh0KSxhc3luYyBmdW5jdGlvbiooKXt2YXIgaTtpZihlIT1udWxsJiYoaT1lLnNpZ25hbCkhPT1udWxsJiZpIT09dm9pZCAwJiZpLmFib3J0ZWQpdGhyb3cgbmV3IHN0O2ZvciBhd2FpdChsZXQgbyBvZiB0aGlzKXt2YXIgbjtpZihlIT1udWxsJiYobj1lLnNpZ25hbCkhPT1udWxsJiZuIT09dm9pZCAwJiZuLmFib3J0ZWQpdGhyb3cgbmV3IHN0O3QtLTw9MCYmKHlpZWxkIG8pO319LmNhbGwodGhpcyl9ZnVuY3Rpb24gdG0odCxlPXZvaWQgMCl7cmV0dXJuIGUhPW51bGwmJnByKGUsXCJvcHRpb25zXCIpLGU/LnNpZ25hbCE9bnVsbCYmZHIoZS5zaWduYWwsXCJvcHRpb25zLnNpZ25hbFwiKSx0PUdoKHQpLGFzeW5jIGZ1bmN0aW9uKigpe3ZhciBpO2lmKGUhPW51bGwmJihpPWUuc2lnbmFsKSE9PW51bGwmJmkhPT12b2lkIDAmJmkuYWJvcnRlZCl0aHJvdyBuZXcgc3Q7Zm9yIGF3YWl0KGxldCBvIG9mIHRoaXMpe3ZhciBuO2lmKGUhPW51bGwmJihuPWUuc2lnbmFsKSE9PW51bGwmJm4hPT12b2lkIDAmJm4uYWJvcnRlZCl0aHJvdyBuZXcgc3Q7aWYodC0tID4wKXlpZWxkIG87ZWxzZSByZXR1cm59fS5jYWxsKHRoaXMpfWtvLmV4cG9ydHMuc3RyZWFtUmV0dXJuaW5nT3BlcmF0b3JzPXthc0luZGV4ZWRQYWlyczpLMCxkcm9wOmVtLGZpbHRlcjpPbyxmbGF0TWFwOlowLG1hcDpBbix0YWtlOnRtLGNvbXBvc2U6ejB9O2tvLmV4cG9ydHMucHJvbWlzZVJldHVybmluZ09wZXJhdG9ycz17ZXZlcnk6RzAsZm9yRWFjaDpZMCxyZWR1Y2U6SjAsdG9BcnJheTpYMCxzb21lOktoLGZpbmQ6UTB9O30pO3ZhciB4bz1NKCh4QyxZaCk9Pnt2KCk7bSgpO18oKTt2YXJ7QXJyYXlQcm90b3R5cGVQb3A6cm0sUHJvbWlzZTppbX09Y2UoKSx7aXNJdGVyYWJsZTpubSxpc05vZGVTdHJlYW06c20saXNXZWJTdHJlYW06b219PXR0KCkse3BpcGVsaW5lSW1wbDphbX09bW4oKSx7ZmluaXNoZWQ6bG19PW10KCk7TW8oKTtmdW5jdGlvbiB1bSguLi50KXtyZXR1cm4gbmV3IGltKChlLHIpPT57bGV0IGksbixvPXRbdC5sZW5ndGgtMV07aWYobyYmdHlwZW9mIG89PVwib2JqZWN0XCImJiFzbShvKSYmIW5tKG8pJiYhb20obykpe2xldCBzPXJtKHQpO2k9cy5zaWduYWwsbj1zLmVuZDt9YW0odCwocyxhKT0+e3M/cihzKTplKGEpO30se3NpZ25hbDppLGVuZDpufSk7fSl9WWguZXhwb3J0cz17ZmluaXNoZWQ6bG0scGlwZWxpbmU6dW19O30pO3ZhciBNbz1NKCgkQyxzZCk9Pnt2KCk7bSgpO18oKTt2YXJ7QnVmZmVyOmZtfT0oeWUoKSxYKF9lKSkse09iamVjdERlZmluZVByb3BlcnR5OlR0LE9iamVjdEtleXM6WmgsUmVmbGVjdEFwcGx5OmVkfT1jZSgpLHtwcm9taXNpZnk6e2N1c3RvbTp0ZH19PUplKCkse3N0cmVhbVJldHVybmluZ09wZXJhdG9yczpKaCxwcm9taXNlUmV0dXJuaW5nT3BlcmF0b3JzOlhofT1RaCgpLHtjb2Rlczp7RVJSX0lMTEVHQUxfQ09OU1RSVUNUT1I6cmR9fT1TZSgpLGNtPUJvKCkse3BpcGVsaW5lOmlkfT1tbigpLHtkZXN0cm95ZXI6aG19PXRyKCksbmQ9bXQoKSxMbz14bygpLFVvPXR0KCksbGU9c2QuZXhwb3J0cz10bigpLlN0cmVhbTtsZS5pc0Rpc3R1cmJlZD1Vby5pc0Rpc3R1cmJlZDtsZS5pc0Vycm9yZWQ9VW8uaXNFcnJvcmVkO2xlLmlzUmVhZGFibGU9VW8uaXNSZWFkYWJsZTtsZS5SZWFkYWJsZT1kaSgpO2ZvcihsZXQgdCBvZiBaaChKaCkpe2xldCByPWZ1bmN0aW9uKC4uLmkpe2lmKG5ldy50YXJnZXQpdGhyb3cgcmQoKTtyZXR1cm4gbGUuUmVhZGFibGUuZnJvbShlZChlLHRoaXMsaSkpfTtsZXQgZT1KaFt0XTtUdChyLFwibmFtZVwiLHtfX3Byb3RvX186bnVsbCx2YWx1ZTplLm5hbWV9KSxUdChyLFwibGVuZ3RoXCIse19fcHJvdG9fXzpudWxsLHZhbHVlOmUubGVuZ3RofSksVHQobGUuUmVhZGFibGUucHJvdG90eXBlLHQse19fcHJvdG9fXzpudWxsLHZhbHVlOnIsZW51bWVyYWJsZTohMSxjb25maWd1cmFibGU6ITAsd3JpdGFibGU6ITB9KTt9Zm9yKGxldCB0IG9mIFpoKFhoKSl7bGV0IHI9ZnVuY3Rpb24oLi4ubil7aWYobmV3LnRhcmdldCl0aHJvdyByZCgpO3JldHVybiBlZChlLHRoaXMsbil9O2xldCBlPVhoW3RdO1R0KHIsXCJuYW1lXCIse19fcHJvdG9fXzpudWxsLHZhbHVlOmUubmFtZX0pLFR0KHIsXCJsZW5ndGhcIix7X19wcm90b19fOm51bGwsdmFsdWU6ZS5sZW5ndGh9KSxUdChsZS5SZWFkYWJsZS5wcm90b3R5cGUsdCx7X19wcm90b19fOm51bGwsdmFsdWU6cixlbnVtZXJhYmxlOiExLGNvbmZpZ3VyYWJsZTohMCx3cml0YWJsZTohMH0pO31sZS5Xcml0YWJsZT11bygpO2xlLkR1cGxleD1udCgpO2xlLlRyYW5zZm9ybT1ibygpO2xlLlBhc3NUaHJvdWdoPV9vKCk7bGUucGlwZWxpbmU9aWQ7dmFye2FkZEFib3J0U2lnbmFsOmRtfT1jaSgpO2xlLmFkZEFib3J0U2lnbmFsPWRtO2xlLmZpbmlzaGVkPW5kO2xlLmRlc3Ryb3k9aG07bGUuY29tcG9zZT1jbTtUdChsZSxcInByb21pc2VzXCIse19fcHJvdG9fXzpudWxsLGNvbmZpZ3VyYWJsZTohMCxlbnVtZXJhYmxlOiEwLGdldCgpe3JldHVybiBMb319KTtUdChpZCx0ZCx7X19wcm90b19fOm51bGwsZW51bWVyYWJsZTohMCxnZXQoKXtyZXR1cm4gTG8ucGlwZWxpbmV9fSk7VHQobmQsdGQse19fcHJvdG9fXzpudWxsLGVudW1lcmFibGU6ITAsZ2V0KCl7cmV0dXJuIExvLmZpbmlzaGVkfX0pO2xlLlN0cmVhbT1sZTtsZS5faXNVaW50OEFycmF5PWZ1bmN0aW9uKGUpe3JldHVybiBlIGluc3RhbmNlb2YgVWludDhBcnJheX07bGUuX3VpbnQ4QXJyYXlUb0J1ZmZlcj1mdW5jdGlvbihlKXtyZXR1cm4gZm0uZnJvbShlLmJ1ZmZlcixlLmJ5dGVPZmZzZXQsZS5ieXRlTGVuZ3RoKX07fSk7dmFyIER0PU0oKFpDLHVlKT0+e3YoKTttKCk7XygpO3ZhciBoZT1NbygpLHBtPXhvKCksZ209aGUuUmVhZGFibGUuZGVzdHJveTt1ZS5leHBvcnRzPWhlLlJlYWRhYmxlO3VlLmV4cG9ydHMuX3VpbnQ4QXJyYXlUb0J1ZmZlcj1oZS5fdWludDhBcnJheVRvQnVmZmVyO3VlLmV4cG9ydHMuX2lzVWludDhBcnJheT1oZS5faXNVaW50OEFycmF5O3VlLmV4cG9ydHMuaXNEaXN0dXJiZWQ9aGUuaXNEaXN0dXJiZWQ7dWUuZXhwb3J0cy5pc0Vycm9yZWQ9aGUuaXNFcnJvcmVkO3VlLmV4cG9ydHMuaXNSZWFkYWJsZT1oZS5pc1JlYWRhYmxlO3VlLmV4cG9ydHMuUmVhZGFibGU9aGUuUmVhZGFibGU7dWUuZXhwb3J0cy5Xcml0YWJsZT1oZS5Xcml0YWJsZTt1ZS5leHBvcnRzLkR1cGxleD1oZS5EdXBsZXg7dWUuZXhwb3J0cy5UcmFuc2Zvcm09aGUuVHJhbnNmb3JtO3VlLmV4cG9ydHMuUGFzc1Rocm91Z2g9aGUuUGFzc1Rocm91Z2g7dWUuZXhwb3J0cy5hZGRBYm9ydFNpZ25hbD1oZS5hZGRBYm9ydFNpZ25hbDt1ZS5leHBvcnRzLmZpbmlzaGVkPWhlLmZpbmlzaGVkO3VlLmV4cG9ydHMuZGVzdHJveT1oZS5kZXN0cm95O3VlLmV4cG9ydHMuZGVzdHJveT1nbTt1ZS5leHBvcnRzLnBpcGVsaW5lPWhlLnBpcGVsaW5lO3VlLmV4cG9ydHMuY29tcG9zZT1oZS5jb21wb3NlO09iamVjdC5kZWZpbmVQcm9wZXJ0eShoZSxcInByb21pc2VzXCIse2NvbmZpZ3VyYWJsZTohMCxlbnVtZXJhYmxlOiEwLGdldCgpe3JldHVybiBwbX19KTt1ZS5leHBvcnRzLlN0cmVhbT1oZS5TdHJlYW07dWUuZXhwb3J0cy5kZWZhdWx0PXVlLmV4cG9ydHM7fSk7dmFyIG9kPU0oKHVCLHFvKT0+e3YoKTttKCk7XygpO3R5cGVvZiBPYmplY3QuY3JlYXRlPT1cImZ1bmN0aW9uXCI/cW8uZXhwb3J0cz1mdW5jdGlvbihlLHIpe3ImJihlLnN1cGVyXz1yLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoci5wcm90b3R5cGUse2NvbnN0cnVjdG9yOnt2YWx1ZTplLGVudW1lcmFibGU6ITEsd3JpdGFibGU6ITAsY29uZmlndXJhYmxlOiEwfX0pKTt9OnFvLmV4cG9ydHM9ZnVuY3Rpb24oZSxyKXtpZihyKXtlLnN1cGVyXz1yO3ZhciBpPWZ1bmN0aW9uKCl7fTtpLnByb3RvdHlwZT1yLnByb3RvdHlwZSxlLnByb3RvdHlwZT1uZXcgaSxlLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1lO319O30pO3ZhciB1ZD1NKChfQixsZCk9Pnt2KCk7bSgpO18oKTt2YXJ7QnVmZmVyOnplfT0oeWUoKSxYKF9lKSksYWQ9U3ltYm9sLmZvcihcIkJ1ZmZlckxpc3RcIik7ZnVuY3Rpb24gZWUodCl7aWYoISh0aGlzIGluc3RhbmNlb2YgZWUpKXJldHVybiBuZXcgZWUodCk7ZWUuX2luaXQuY2FsbCh0aGlzLHQpO31lZS5faW5pdD1mdW5jdGlvbihlKXtPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcyxhZCx7dmFsdWU6ITB9KSx0aGlzLl9idWZzPVtdLHRoaXMubGVuZ3RoPTAsZSYmdGhpcy5hcHBlbmQoZSk7fTtlZS5wcm90b3R5cGUuX25ldz1mdW5jdGlvbihlKXtyZXR1cm4gbmV3IGVlKGUpfTtlZS5wcm90b3R5cGUuX29mZnNldD1mdW5jdGlvbihlKXtpZihlPT09MClyZXR1cm4gWzAsMF07bGV0IHI9MDtmb3IobGV0IGk9MDtpPHRoaXMuX2J1ZnMubGVuZ3RoO2krKyl7bGV0IG49cit0aGlzLl9idWZzW2ldLmxlbmd0aDtpZihlPG58fGk9PT10aGlzLl9idWZzLmxlbmd0aC0xKXJldHVybiBbaSxlLXJdO3I9bjt9fTtlZS5wcm90b3R5cGUuX3JldmVyc2VPZmZzZXQ9ZnVuY3Rpb24odCl7bGV0IGU9dFswXSxyPXRbMV07Zm9yKGxldCBpPTA7aTxlO2krKylyKz10aGlzLl9idWZzW2ldLmxlbmd0aDtyZXR1cm4gcn07ZWUucHJvdG90eXBlLmdldD1mdW5jdGlvbihlKXtpZihlPnRoaXMubGVuZ3RofHxlPDApcmV0dXJuO2xldCByPXRoaXMuX29mZnNldChlKTtyZXR1cm4gdGhpcy5fYnVmc1tyWzBdXVtyWzFdXX07ZWUucHJvdG90eXBlLnNsaWNlPWZ1bmN0aW9uKGUscil7cmV0dXJuIHR5cGVvZiBlPT1cIm51bWJlclwiJiZlPDAmJihlKz10aGlzLmxlbmd0aCksdHlwZW9mIHI9PVwibnVtYmVyXCImJnI8MCYmKHIrPXRoaXMubGVuZ3RoKSx0aGlzLmNvcHkobnVsbCwwLGUscil9O2VlLnByb3RvdHlwZS5jb3B5PWZ1bmN0aW9uKGUscixpLG4pe2lmKCh0eXBlb2YgaSE9XCJudW1iZXJcInx8aTwwKSYmKGk9MCksKHR5cGVvZiBuIT1cIm51bWJlclwifHxuPnRoaXMubGVuZ3RoKSYmKG49dGhpcy5sZW5ndGgpLGk+PXRoaXMubGVuZ3RofHxuPD0wKXJldHVybiBlfHx6ZS5hbGxvYygwKTtsZXQgbz0hIWUscz10aGlzLl9vZmZzZXQoaSksYT1uLWksdT1hLGM9byYmcnx8MCxoPXNbMV07aWYoaT09PTAmJm49PT10aGlzLmxlbmd0aCl7aWYoIW8pcmV0dXJuIHRoaXMuX2J1ZnMubGVuZ3RoPT09MT90aGlzLl9idWZzWzBdOnplLmNvbmNhdCh0aGlzLl9idWZzLHRoaXMubGVuZ3RoKTtmb3IobGV0IGQ9MDtkPHRoaXMuX2J1ZnMubGVuZ3RoO2QrKyl0aGlzLl9idWZzW2RdLmNvcHkoZSxjKSxjKz10aGlzLl9idWZzW2RdLmxlbmd0aDtyZXR1cm4gZX1pZih1PD10aGlzLl9idWZzW3NbMF1dLmxlbmd0aC1oKXJldHVybiBvP3RoaXMuX2J1ZnNbc1swXV0uY29weShlLHIsaCxoK3UpOnRoaXMuX2J1ZnNbc1swXV0uc2xpY2UoaCxoK3UpO298fChlPXplLmFsbG9jVW5zYWZlKGEpKTtmb3IobGV0IGQ9c1swXTtkPHRoaXMuX2J1ZnMubGVuZ3RoO2QrKyl7bGV0IGc9dGhpcy5fYnVmc1tkXS5sZW5ndGgtaDtpZih1PmcpdGhpcy5fYnVmc1tkXS5jb3B5KGUsYyxoKSxjKz1nO2Vsc2Uge3RoaXMuX2J1ZnNbZF0uY29weShlLGMsaCxoK3UpLGMrPWc7YnJlYWt9dS09ZyxoJiYoaD0wKTt9cmV0dXJuIGUubGVuZ3RoPmM/ZS5zbGljZSgwLGMpOmV9O2VlLnByb3RvdHlwZS5zaGFsbG93U2xpY2U9ZnVuY3Rpb24oZSxyKXtpZihlPWV8fDAscj10eXBlb2YgciE9XCJudW1iZXJcIj90aGlzLmxlbmd0aDpyLGU8MCYmKGUrPXRoaXMubGVuZ3RoKSxyPDAmJihyKz10aGlzLmxlbmd0aCksZT09PXIpcmV0dXJuIHRoaXMuX25ldygpO2xldCBpPXRoaXMuX29mZnNldChlKSxuPXRoaXMuX29mZnNldChyKSxvPXRoaXMuX2J1ZnMuc2xpY2UoaVswXSxuWzBdKzEpO3JldHVybiBuWzFdPT09MD9vLnBvcCgpOm9bby5sZW5ndGgtMV09b1tvLmxlbmd0aC0xXS5zbGljZSgwLG5bMV0pLGlbMV0hPT0wJiYob1swXT1vWzBdLnNsaWNlKGlbMV0pKSx0aGlzLl9uZXcobyl9O2VlLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbihlLHIsaSl7cmV0dXJuIHRoaXMuc2xpY2UocixpKS50b1N0cmluZyhlKX07ZWUucHJvdG90eXBlLmNvbnN1bWU9ZnVuY3Rpb24oZSl7aWYoZT1NYXRoLnRydW5jKGUpLE51bWJlci5pc05hTihlKXx8ZTw9MClyZXR1cm4gdGhpcztmb3IoO3RoaXMuX2J1ZnMubGVuZ3RoOylpZihlPj10aGlzLl9idWZzWzBdLmxlbmd0aCllLT10aGlzLl9idWZzWzBdLmxlbmd0aCx0aGlzLmxlbmd0aC09dGhpcy5fYnVmc1swXS5sZW5ndGgsdGhpcy5fYnVmcy5zaGlmdCgpO2Vsc2Uge3RoaXMuX2J1ZnNbMF09dGhpcy5fYnVmc1swXS5zbGljZShlKSx0aGlzLmxlbmd0aC09ZTticmVha31yZXR1cm4gdGhpc307ZWUucHJvdG90eXBlLmR1cGxpY2F0ZT1mdW5jdGlvbigpe2xldCBlPXRoaXMuX25ldygpO2ZvcihsZXQgcj0wO3I8dGhpcy5fYnVmcy5sZW5ndGg7cisrKWUuYXBwZW5kKHRoaXMuX2J1ZnNbcl0pO3JldHVybiBlfTtlZS5wcm90b3R5cGUuYXBwZW5kPWZ1bmN0aW9uKGUpe2lmKGU9PW51bGwpcmV0dXJuIHRoaXM7aWYoZS5idWZmZXIpdGhpcy5fYXBwZW5kQnVmZmVyKHplLmZyb20oZS5idWZmZXIsZS5ieXRlT2Zmc2V0LGUuYnl0ZUxlbmd0aCkpO2Vsc2UgaWYoQXJyYXkuaXNBcnJheShlKSlmb3IobGV0IHI9MDtyPGUubGVuZ3RoO3IrKyl0aGlzLmFwcGVuZChlW3JdKTtlbHNlIGlmKHRoaXMuX2lzQnVmZmVyTGlzdChlKSlmb3IobGV0IHI9MDtyPGUuX2J1ZnMubGVuZ3RoO3IrKyl0aGlzLmFwcGVuZChlLl9idWZzW3JdKTtlbHNlIHR5cGVvZiBlPT1cIm51bWJlclwiJiYoZT1lLnRvU3RyaW5nKCkpLHRoaXMuX2FwcGVuZEJ1ZmZlcih6ZS5mcm9tKGUpKTtyZXR1cm4gdGhpc307ZWUucHJvdG90eXBlLl9hcHBlbmRCdWZmZXI9ZnVuY3Rpb24oZSl7dGhpcy5fYnVmcy5wdXNoKGUpLHRoaXMubGVuZ3RoKz1lLmxlbmd0aDt9O2VlLnByb3RvdHlwZS5pbmRleE9mPWZ1bmN0aW9uKHQsZSxyKXtpZihyPT09dm9pZCAwJiZ0eXBlb2YgZT09XCJzdHJpbmdcIiYmKHI9ZSxlPXZvaWQgMCksdHlwZW9mIHQ9PVwiZnVuY3Rpb25cInx8QXJyYXkuaXNBcnJheSh0KSl0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgXCJ2YWx1ZVwiIGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgc3RyaW5nLCBCdWZmZXIsIEJ1ZmZlckxpc3QsIG9yIFVpbnQ4QXJyYXkuJyk7aWYodHlwZW9mIHQ9PVwibnVtYmVyXCI/dD16ZS5mcm9tKFt0XSk6dHlwZW9mIHQ9PVwic3RyaW5nXCI/dD16ZS5mcm9tKHQscik6dGhpcy5faXNCdWZmZXJMaXN0KHQpP3Q9dC5zbGljZSgpOkFycmF5LmlzQXJyYXkodC5idWZmZXIpP3Q9emUuZnJvbSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQsdC5ieXRlTGVuZ3RoKTp6ZS5pc0J1ZmZlcih0KXx8KHQ9emUuZnJvbSh0KSksZT1OdW1iZXIoZXx8MCksaXNOYU4oZSkmJihlPTApLGU8MCYmKGU9dGhpcy5sZW5ndGgrZSksZTwwJiYoZT0wKSx0Lmxlbmd0aD09PTApcmV0dXJuIGU+dGhpcy5sZW5ndGg/dGhpcy5sZW5ndGg6ZTtsZXQgaT10aGlzLl9vZmZzZXQoZSksbj1pWzBdLG89aVsxXTtmb3IoO248dGhpcy5fYnVmcy5sZW5ndGg7bisrKXtsZXQgcz10aGlzLl9idWZzW25dO2Zvcig7bzxzLmxlbmd0aDspaWYocy5sZW5ndGgtbz49dC5sZW5ndGgpe2xldCB1PXMuaW5kZXhPZih0LG8pO2lmKHUhPT0tMSlyZXR1cm4gdGhpcy5fcmV2ZXJzZU9mZnNldChbbix1XSk7bz1zLmxlbmd0aC10Lmxlbmd0aCsxO31lbHNlIHtsZXQgdT10aGlzLl9yZXZlcnNlT2Zmc2V0KFtuLG9dKTtpZih0aGlzLl9tYXRjaCh1LHQpKXJldHVybiB1O28rKzt9bz0wO31yZXR1cm4gLTF9O2VlLnByb3RvdHlwZS5fbWF0Y2g9ZnVuY3Rpb24odCxlKXtpZih0aGlzLmxlbmd0aC10PGUubGVuZ3RoKXJldHVybiAhMTtmb3IobGV0IHI9MDtyPGUubGVuZ3RoO3IrKylpZih0aGlzLmdldCh0K3IpIT09ZVtyXSlyZXR1cm4gITE7cmV0dXJuICEwfTsoZnVuY3Rpb24oKXtsZXQgdD17cmVhZERvdWJsZUJFOjgscmVhZERvdWJsZUxFOjgscmVhZEZsb2F0QkU6NCxyZWFkRmxvYXRMRTo0LHJlYWRCaWdJbnQ2NEJFOjgscmVhZEJpZ0ludDY0TEU6OCxyZWFkQmlnVUludDY0QkU6OCxyZWFkQmlnVUludDY0TEU6OCxyZWFkSW50MzJCRTo0LHJlYWRJbnQzMkxFOjQscmVhZFVJbnQzMkJFOjQscmVhZFVJbnQzMkxFOjQscmVhZEludDE2QkU6MixyZWFkSW50MTZMRToyLHJlYWRVSW50MTZCRToyLHJlYWRVSW50MTZMRToyLHJlYWRJbnQ4OjEscmVhZFVJbnQ4OjEscmVhZEludEJFOm51bGwscmVhZEludExFOm51bGwscmVhZFVJbnRCRTpudWxsLHJlYWRVSW50TEU6bnVsbH07Zm9yKGxldCBlIGluIHQpKGZ1bmN0aW9uKHIpe3Rbcl09PT1udWxsP2VlLnByb3RvdHlwZVtyXT1mdW5jdGlvbihpLG4pe3JldHVybiB0aGlzLnNsaWNlKGksaStuKVtyXSgwLG4pfTplZS5wcm90b3R5cGVbcl09ZnVuY3Rpb24oaT0wKXtyZXR1cm4gdGhpcy5zbGljZShpLGkrdFtyXSlbcl0oMCl9O30pKGUpO30pKCk7ZWUucHJvdG90eXBlLl9pc0J1ZmZlckxpc3Q9ZnVuY3Rpb24oZSl7cmV0dXJuIGUgaW5zdGFuY2VvZiBlZXx8ZWUuaXNCdWZmZXJMaXN0KGUpfTtlZS5pc0J1ZmZlckxpc3Q9ZnVuY3Rpb24oZSl7cmV0dXJuIGUhPW51bGwmJmVbYWRdfTtsZC5leHBvcnRzPWVlO30pO3ZhciBmZD1NKChCQixJbik9Pnt2KCk7bSgpO18oKTt2YXIgRG89RHQoKS5EdXBsZXgseW09b2QoKSxtaT11ZCgpO2Z1bmN0aW9uIEVlKHQpe2lmKCEodGhpcyBpbnN0YW5jZW9mIEVlKSlyZXR1cm4gbmV3IEVlKHQpO2lmKHR5cGVvZiB0PT1cImZ1bmN0aW9uXCIpe3RoaXMuX2NhbGxiYWNrPXQ7bGV0IGU9ZnVuY3Rpb24oaSl7dGhpcy5fY2FsbGJhY2smJih0aGlzLl9jYWxsYmFjayhpKSx0aGlzLl9jYWxsYmFjaz1udWxsKTt9LmJpbmQodGhpcyk7dGhpcy5vbihcInBpcGVcIixmdW5jdGlvbihpKXtpLm9uKFwiZXJyb3JcIixlKTt9KSx0aGlzLm9uKFwidW5waXBlXCIsZnVuY3Rpb24oaSl7aS5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsZSk7fSksdD1udWxsO31taS5faW5pdC5jYWxsKHRoaXMsdCksRG8uY2FsbCh0aGlzKTt9eW0oRWUsRG8pO09iamVjdC5hc3NpZ24oRWUucHJvdG90eXBlLG1pLnByb3RvdHlwZSk7RWUucHJvdG90eXBlLl9uZXc9ZnVuY3Rpb24oZSl7cmV0dXJuIG5ldyBFZShlKX07RWUucHJvdG90eXBlLl93cml0ZT1mdW5jdGlvbihlLHIsaSl7dGhpcy5fYXBwZW5kQnVmZmVyKGUpLHR5cGVvZiBpPT1cImZ1bmN0aW9uXCImJmkoKTt9O0VlLnByb3RvdHlwZS5fcmVhZD1mdW5jdGlvbihlKXtpZighdGhpcy5sZW5ndGgpcmV0dXJuIHRoaXMucHVzaChudWxsKTtlPU1hdGgubWluKGUsdGhpcy5sZW5ndGgpLHRoaXMucHVzaCh0aGlzLnNsaWNlKDAsZSkpLHRoaXMuY29uc3VtZShlKTt9O0VlLnByb3RvdHlwZS5lbmQ9ZnVuY3Rpb24oZSl7RG8ucHJvdG90eXBlLmVuZC5jYWxsKHRoaXMsZSksdGhpcy5fY2FsbGJhY2smJih0aGlzLl9jYWxsYmFjayhudWxsLHRoaXMuc2xpY2UoKSksdGhpcy5fY2FsbGJhY2s9bnVsbCk7fTtFZS5wcm90b3R5cGUuX2Rlc3Ryb3k9ZnVuY3Rpb24oZSxyKXt0aGlzLl9idWZzLmxlbmd0aD0wLHRoaXMubGVuZ3RoPTAscihlKTt9O0VlLnByb3RvdHlwZS5faXNCdWZmZXJMaXN0PWZ1bmN0aW9uKGUpe3JldHVybiBlIGluc3RhbmNlb2YgRWV8fGUgaW5zdGFuY2VvZiBtaXx8RWUuaXNCdWZmZXJMaXN0KGUpfTtFZS5pc0J1ZmZlckxpc3Q9bWkuaXNCdWZmZXJMaXN0O0luLmV4cG9ydHM9RWU7SW4uZXhwb3J0cy5CdWZmZXJMaXN0U3RyZWFtPUVlO0luLmV4cG9ydHMuQnVmZmVyTGlzdD1taTt9KTt2YXIgaGQ9TSgoREIsY2QpPT57digpO20oKTtfKCk7dmFyIGpvPWNsYXNze2NvbnN0cnVjdG9yKCl7dGhpcy5jbWQ9bnVsbCx0aGlzLnJldGFpbj0hMSx0aGlzLnFvcz0wLHRoaXMuZHVwPSExLHRoaXMubGVuZ3RoPS0xLHRoaXMudG9waWM9bnVsbCx0aGlzLnBheWxvYWQ9bnVsbDt9fTtjZC5leHBvcnRzPWpvO30pO3ZhciBGbz1NKChRQixkZCk9Pnt2KCk7bSgpO18oKTt2YXIgTD1kZC5leHBvcnRzLHtCdWZmZXI6T2V9PSh5ZSgpLFgoX2UpKTtMLnR5cGVzPXswOlwicmVzZXJ2ZWRcIiwxOlwiY29ubmVjdFwiLDI6XCJjb25uYWNrXCIsMzpcInB1Ymxpc2hcIiw0OlwicHViYWNrXCIsNTpcInB1YnJlY1wiLDY6XCJwdWJyZWxcIiw3OlwicHViY29tcFwiLDg6XCJzdWJzY3JpYmVcIiw5Olwic3ViYWNrXCIsMTA6XCJ1bnN1YnNjcmliZVwiLDExOlwidW5zdWJhY2tcIiwxMjpcInBpbmdyZXFcIiwxMzpcInBpbmdyZXNwXCIsMTQ6XCJkaXNjb25uZWN0XCIsMTU6XCJhdXRoXCJ9O0wucmVxdWlyZWRIZWFkZXJGbGFncz17MTowLDI6MCw0OjAsNTowLDY6Miw3OjAsODoyLDk6MCwxMDoyLDExOjAsMTI6MCwxMzowLDE0OjAsMTU6MH07TC5yZXF1aXJlZEhlYWRlckZsYWdzRXJyb3JzPXt9O2ZvcihsZXQgdCBpbiBMLnJlcXVpcmVkSGVhZGVyRmxhZ3Mpe2xldCBlPUwucmVxdWlyZWRIZWFkZXJGbGFnc1t0XTtMLnJlcXVpcmVkSGVhZGVyRmxhZ3NFcnJvcnNbdF09XCJJbnZhbGlkIGhlYWRlciBmbGFnIGJpdHMsIG11c3QgYmUgMHhcIitlLnRvU3RyaW5nKDE2KStcIiBmb3IgXCIrTC50eXBlc1t0XStcIiBwYWNrZXRcIjt9TC5jb2Rlcz17fTtmb3IobGV0IHQgaW4gTC50eXBlcyl7bGV0IGU9TC50eXBlc1t0XTtMLmNvZGVzW2VdPXQ7fUwuQ01EX1NISUZUPTQ7TC5DTURfTUFTSz0yNDA7TC5EVVBfTUFTSz04O0wuUU9TX01BU0s9MztMLlFPU19TSElGVD0xO0wuUkVUQUlOX01BU0s9MTtMLlZBUkJZVEVJTlRfTUFTSz0xMjc7TC5WQVJCWVRFSU5UX0ZJTl9NQVNLPTEyODtMLlZBUkJZVEVJTlRfTUFYPTI2ODQzNTQ1NTtMLlNFU1NJT05QUkVTRU5UX01BU0s9MTtMLlNFU1NJT05QUkVTRU5UX0hFQURFUj1PZS5mcm9tKFtMLlNFU1NJT05QUkVTRU5UX01BU0tdKTtMLkNPTk5BQ0tfSEVBREVSPU9lLmZyb20oW0wuY29kZXMuY29ubmFjazw8TC5DTURfU0hJRlRdKTtMLlVTRVJOQU1FX01BU0s9MTI4O0wuUEFTU1dPUkRfTUFTSz02NDtMLldJTExfUkVUQUlOX01BU0s9MzI7TC5XSUxMX1FPU19NQVNLPTI0O0wuV0lMTF9RT1NfU0hJRlQ9MztMLldJTExfRkxBR19NQVNLPTQ7TC5DTEVBTl9TRVNTSU9OX01BU0s9MjtMLkNPTk5FQ1RfSEVBREVSPU9lLmZyb20oW0wuY29kZXMuY29ubmVjdDw8TC5DTURfU0hJRlRdKTtMLnByb3BlcnRpZXM9e3Nlc3Npb25FeHBpcnlJbnRlcnZhbDoxNyx3aWxsRGVsYXlJbnRlcnZhbDoyNCxyZWNlaXZlTWF4aW11bTozMyxtYXhpbXVtUGFja2V0U2l6ZTozOSx0b3BpY0FsaWFzTWF4aW11bTozNCxyZXF1ZXN0UmVzcG9uc2VJbmZvcm1hdGlvbjoyNSxyZXF1ZXN0UHJvYmxlbUluZm9ybWF0aW9uOjIzLHVzZXJQcm9wZXJ0aWVzOjM4LGF1dGhlbnRpY2F0aW9uTWV0aG9kOjIxLGF1dGhlbnRpY2F0aW9uRGF0YToyMixwYXlsb2FkRm9ybWF0SW5kaWNhdG9yOjEsbWVzc2FnZUV4cGlyeUludGVydmFsOjIsY29udGVudFR5cGU6MyxyZXNwb25zZVRvcGljOjgsY29ycmVsYXRpb25EYXRhOjksbWF4aW11bVFvUzozNixyZXRhaW5BdmFpbGFibGU6MzcsYXNzaWduZWRDbGllbnRJZGVudGlmaWVyOjE4LHJlYXNvblN0cmluZzozMSx3aWxkY2FyZFN1YnNjcmlwdGlvbkF2YWlsYWJsZTo0MCxzdWJzY3JpcHRpb25JZGVudGlmaWVyc0F2YWlsYWJsZTo0MSxzaGFyZWRTdWJzY3JpcHRpb25BdmFpbGFibGU6NDIsc2VydmVyS2VlcEFsaXZlOjE5LHJlc3BvbnNlSW5mb3JtYXRpb246MjYsc2VydmVyUmVmZXJlbmNlOjI4LHRvcGljQWxpYXM6MzUsc3Vic2NyaXB0aW9uSWRlbnRpZmllcjoxMX07TC5wcm9wZXJ0aWVzQ29kZXM9e307Zm9yKGxldCB0IGluIEwucHJvcGVydGllcyl7bGV0IGU9TC5wcm9wZXJ0aWVzW3RdO0wucHJvcGVydGllc0NvZGVzW2VdPXQ7fUwucHJvcGVydGllc1R5cGVzPXtzZXNzaW9uRXhwaXJ5SW50ZXJ2YWw6XCJpbnQzMlwiLHdpbGxEZWxheUludGVydmFsOlwiaW50MzJcIixyZWNlaXZlTWF4aW11bTpcImludDE2XCIsbWF4aW11bVBhY2tldFNpemU6XCJpbnQzMlwiLHRvcGljQWxpYXNNYXhpbXVtOlwiaW50MTZcIixyZXF1ZXN0UmVzcG9uc2VJbmZvcm1hdGlvbjpcImJ5dGVcIixyZXF1ZXN0UHJvYmxlbUluZm9ybWF0aW9uOlwiYnl0ZVwiLHVzZXJQcm9wZXJ0aWVzOlwicGFpclwiLGF1dGhlbnRpY2F0aW9uTWV0aG9kOlwic3RyaW5nXCIsYXV0aGVudGljYXRpb25EYXRhOlwiYmluYXJ5XCIscGF5bG9hZEZvcm1hdEluZGljYXRvcjpcImJ5dGVcIixtZXNzYWdlRXhwaXJ5SW50ZXJ2YWw6XCJpbnQzMlwiLGNvbnRlbnRUeXBlOlwic3RyaW5nXCIscmVzcG9uc2VUb3BpYzpcInN0cmluZ1wiLGNvcnJlbGF0aW9uRGF0YTpcImJpbmFyeVwiLG1heGltdW1Rb1M6XCJpbnQ4XCIscmV0YWluQXZhaWxhYmxlOlwiYnl0ZVwiLGFzc2lnbmVkQ2xpZW50SWRlbnRpZmllcjpcInN0cmluZ1wiLHJlYXNvblN0cmluZzpcInN0cmluZ1wiLHdpbGRjYXJkU3Vic2NyaXB0aW9uQXZhaWxhYmxlOlwiYnl0ZVwiLHN1YnNjcmlwdGlvbklkZW50aWZpZXJzQXZhaWxhYmxlOlwiYnl0ZVwiLHNoYXJlZFN1YnNjcmlwdGlvbkF2YWlsYWJsZTpcImJ5dGVcIixzZXJ2ZXJLZWVwQWxpdmU6XCJpbnQxNlwiLHJlc3BvbnNlSW5mb3JtYXRpb246XCJzdHJpbmdcIixzZXJ2ZXJSZWZlcmVuY2U6XCJzdHJpbmdcIix0b3BpY0FsaWFzOlwiaW50MTZcIixzdWJzY3JpcHRpb25JZGVudGlmaWVyOlwidmFyXCJ9O2Z1bmN0aW9uIGp0KHQpe3JldHVybiBbMCwxLDJdLm1hcChlPT5bMCwxXS5tYXAocj0+WzAsMV0ubWFwKGk9PntsZXQgbj1PZS5hbGxvYygxKTtyZXR1cm4gbi53cml0ZVVJbnQ4KEwuY29kZXNbdF08PEwuQ01EX1NISUZUfChyP0wuRFVQX01BU0s6MCl8ZTw8TC5RT1NfU0hJRlR8aSwwLCEwKSxufSkpKX1MLlBVQkxJU0hfSEVBREVSPWp0KFwicHVibGlzaFwiKTtMLlNVQlNDUklCRV9IRUFERVI9anQoXCJzdWJzY3JpYmVcIik7TC5TVUJTQ1JJQkVfT1BUSU9OU19RT1NfTUFTSz0zO0wuU1VCU0NSSUJFX09QVElPTlNfTkxfTUFTSz0xO0wuU1VCU0NSSUJFX09QVElPTlNfTkxfU0hJRlQ9MjtMLlNVQlNDUklCRV9PUFRJT05TX1JBUF9NQVNLPTE7TC5TVUJTQ1JJQkVfT1BUSU9OU19SQVBfU0hJRlQ9MztMLlNVQlNDUklCRV9PUFRJT05TX1JIX01BU0s9MztMLlNVQlNDUklCRV9PUFRJT05TX1JIX1NISUZUPTQ7TC5TVUJTQ1JJQkVfT1BUSU9OU19SSD1bMCwxNiwzMl07TC5TVUJTQ1JJQkVfT1BUSU9OU19OTD00O0wuU1VCU0NSSUJFX09QVElPTlNfUkFQPTg7TC5TVUJTQ1JJQkVfT1BUSU9OU19RT1M9WzAsMSwyXTtMLlVOU1VCU0NSSUJFX0hFQURFUj1qdChcInVuc3Vic2NyaWJlXCIpO0wuQUNLUz17dW5zdWJhY2s6anQoXCJ1bnN1YmFja1wiKSxwdWJhY2s6anQoXCJwdWJhY2tcIikscHViY29tcDpqdChcInB1YmNvbXBcIikscHVicmVsOmp0KFwicHVicmVsXCIpLHB1YnJlYzpqdChcInB1YnJlY1wiKX07TC5TVUJBQ0tfSEVBREVSPU9lLmZyb20oW0wuY29kZXMuc3ViYWNrPDxMLkNNRF9TSElGVF0pO0wuVkVSU0lPTjM9T2UuZnJvbShbM10pO0wuVkVSU0lPTjQ9T2UuZnJvbShbNF0pO0wuVkVSU0lPTjU9T2UuZnJvbShbNV0pO0wuVkVSU0lPTjEzMT1PZS5mcm9tKFsxMzFdKTtMLlZFUlNJT04xMzI9T2UuZnJvbShbMTMyXSk7TC5RT1M9WzAsMSwyXS5tYXAodD0+T2UuZnJvbShbdF0pKTtMLkVNUFRZPXtwaW5ncmVxOk9lLmZyb20oW0wuY29kZXMucGluZ3JlcTw8NCwwXSkscGluZ3Jlc3A6T2UuZnJvbShbTC5jb2Rlcy5waW5ncmVzcDw8NCwwXSksZGlzY29ubmVjdDpPZS5mcm9tKFtMLmNvZGVzLmRpc2Nvbm5lY3Q8PDQsMF0pfTtMLk1RVFQ1X1BVQkFDS19QVUJSRUNfQ09ERVM9ezA6XCJTdWNjZXNzXCIsMTY6XCJObyBtYXRjaGluZyBzdWJzY3JpYmVyc1wiLDEyODpcIlVuc3BlY2lmaWVkIGVycm9yXCIsMTMxOlwiSW1wbGVtZW50YXRpb24gc3BlY2lmaWMgZXJyb3JcIiwxMzU6XCJOb3QgYXV0aG9yaXplZFwiLDE0NDpcIlRvcGljIE5hbWUgaW52YWxpZFwiLDE0NTpcIlBhY2tldCBpZGVudGlmaWVyIGluIHVzZVwiLDE1MTpcIlF1b3RhIGV4Y2VlZGVkXCIsMTUzOlwiUGF5bG9hZCBmb3JtYXQgaW52YWxpZFwifTtMLk1RVFQ1X1BVQlJFTF9QVUJDT01QX0NPREVTPXswOlwiU3VjY2Vzc1wiLDE0NjpcIlBhY2tldCBJZGVudGlmaWVyIG5vdCBmb3VuZFwifTtMLk1RVFQ1X1NVQkFDS19DT0RFUz17MDpcIkdyYW50ZWQgUW9TIDBcIiwxOlwiR3JhbnRlZCBRb1MgMVwiLDI6XCJHcmFudGVkIFFvUyAyXCIsMTI4OlwiVW5zcGVjaWZpZWQgZXJyb3JcIiwxMzE6XCJJbXBsZW1lbnRhdGlvbiBzcGVjaWZpYyBlcnJvclwiLDEzNTpcIk5vdCBhdXRob3JpemVkXCIsMTQzOlwiVG9waWMgRmlsdGVyIGludmFsaWRcIiwxNDU6XCJQYWNrZXQgSWRlbnRpZmllciBpbiB1c2VcIiwxNTE6XCJRdW90YSBleGNlZWRlZFwiLDE1ODpcIlNoYXJlZCBTdWJzY3JpcHRpb25zIG5vdCBzdXBwb3J0ZWRcIiwxNjE6XCJTdWJzY3JpcHRpb24gSWRlbnRpZmllcnMgbm90IHN1cHBvcnRlZFwiLDE2MjpcIldpbGRjYXJkIFN1YnNjcmlwdGlvbnMgbm90IHN1cHBvcnRlZFwifTtMLk1RVFQ1X1VOU1VCQUNLX0NPREVTPXswOlwiU3VjY2Vzc1wiLDE3OlwiTm8gc3Vic2NyaXB0aW9uIGV4aXN0ZWRcIiwxMjg6XCJVbnNwZWNpZmllZCBlcnJvclwiLDEzMTpcIkltcGxlbWVudGF0aW9uIHNwZWNpZmljIGVycm9yXCIsMTM1OlwiTm90IGF1dGhvcml6ZWRcIiwxNDM6XCJUb3BpYyBGaWx0ZXIgaW52YWxpZFwiLDE0NTpcIlBhY2tldCBJZGVudGlmaWVyIGluIHVzZVwifTtMLk1RVFQ1X0RJU0NPTk5FQ1RfQ09ERVM9ezA6XCJOb3JtYWwgZGlzY29ubmVjdGlvblwiLDQ6XCJEaXNjb25uZWN0IHdpdGggV2lsbCBNZXNzYWdlXCIsMTI4OlwiVW5zcGVjaWZpZWQgZXJyb3JcIiwxMjk6XCJNYWxmb3JtZWQgUGFja2V0XCIsMTMwOlwiUHJvdG9jb2wgRXJyb3JcIiwxMzE6XCJJbXBsZW1lbnRhdGlvbiBzcGVjaWZpYyBlcnJvclwiLDEzNTpcIk5vdCBhdXRob3JpemVkXCIsMTM3OlwiU2VydmVyIGJ1c3lcIiwxMzk6XCJTZXJ2ZXIgc2h1dHRpbmcgZG93blwiLDE0MTpcIktlZXAgQWxpdmUgdGltZW91dFwiLDE0MjpcIlNlc3Npb24gdGFrZW4gb3ZlclwiLDE0MzpcIlRvcGljIEZpbHRlciBpbnZhbGlkXCIsMTQ0OlwiVG9waWMgTmFtZSBpbnZhbGlkXCIsMTQ3OlwiUmVjZWl2ZSBNYXhpbXVtIGV4Y2VlZGVkXCIsMTQ4OlwiVG9waWMgQWxpYXMgaW52YWxpZFwiLDE0OTpcIlBhY2tldCB0b28gbGFyZ2VcIiwxNTA6XCJNZXNzYWdlIHJhdGUgdG9vIGhpZ2hcIiwxNTE6XCJRdW90YSBleGNlZWRlZFwiLDE1MjpcIkFkbWluaXN0cmF0aXZlIGFjdGlvblwiLDE1MzpcIlBheWxvYWQgZm9ybWF0IGludmFsaWRcIiwxNTQ6XCJSZXRhaW4gbm90IHN1cHBvcnRlZFwiLDE1NTpcIlFvUyBub3Qgc3VwcG9ydGVkXCIsMTU2OlwiVXNlIGFub3RoZXIgc2VydmVyXCIsMTU3OlwiU2VydmVyIG1vdmVkXCIsMTU4OlwiU2hhcmVkIFN1YnNjcmlwdGlvbnMgbm90IHN1cHBvcnRlZFwiLDE1OTpcIkNvbm5lY3Rpb24gcmF0ZSBleGNlZWRlZFwiLDE2MDpcIk1heGltdW0gY29ubmVjdCB0aW1lXCIsMTYxOlwiU3Vic2NyaXB0aW9uIElkZW50aWZpZXJzIG5vdCBzdXBwb3J0ZWRcIiwxNjI6XCJXaWxkY2FyZCBTdWJzY3JpcHRpb25zIG5vdCBzdXBwb3J0ZWRcIn07TC5NUVRUNV9BVVRIX0NPREVTPXswOlwiU3VjY2Vzc1wiLDI0OlwiQ29udGludWUgYXV0aGVudGljYXRpb25cIiwyNTpcIlJlLWF1dGhlbnRpY2F0ZVwifTt9KTt2YXIgZ2Q9TSgoc1AscGQpPT57digpO20oKTtfKCk7dmFyIFZyPTFlMyx6cj1Wcio2MCxLcj16cio2MCxncj1LcioyNCxibT1ncio3LHdtPWdyKjM2NS4yNTtwZC5leHBvcnRzPWZ1bmN0aW9uKHQsZSl7ZT1lfHx7fTt2YXIgcj10eXBlb2YgdDtpZihyPT09XCJzdHJpbmdcIiYmdC5sZW5ndGg+MClyZXR1cm4gX20odCk7aWYocj09PVwibnVtYmVyXCImJmlzRmluaXRlKHQpKXJldHVybiBlLmxvbmc/dm0odCk6bW0odCk7dGhyb3cgbmV3IEVycm9yKFwidmFsIGlzIG5vdCBhIG5vbi1lbXB0eSBzdHJpbmcgb3IgYSB2YWxpZCBudW1iZXIuIHZhbD1cIitKU09OLnN0cmluZ2lmeSh0KSl9O2Z1bmN0aW9uIF9tKHQpe2lmKHQ9U3RyaW5nKHQpLCEodC5sZW5ndGg+MTAwKSl7dmFyIGU9L14oLT8oPzpcXGQrKT9cXC4/XFxkKykgKihtaWxsaXNlY29uZHM/fG1zZWNzP3xtc3xzZWNvbmRzP3xzZWNzP3xzfG1pbnV0ZXM/fG1pbnM/fG18aG91cnM/fGhycz98aHxkYXlzP3xkfHdlZWtzP3x3fHllYXJzP3x5cnM/fHkpPyQvaS5leGVjKHQpO2lmKGUpe3ZhciByPXBhcnNlRmxvYXQoZVsxXSksaT0oZVsyXXx8XCJtc1wiKS50b0xvd2VyQ2FzZSgpO3N3aXRjaChpKXtjYXNlXCJ5ZWFyc1wiOmNhc2VcInllYXJcIjpjYXNlXCJ5cnNcIjpjYXNlXCJ5clwiOmNhc2VcInlcIjpyZXR1cm4gcip3bTtjYXNlXCJ3ZWVrc1wiOmNhc2VcIndlZWtcIjpjYXNlXCJ3XCI6cmV0dXJuIHIqYm07Y2FzZVwiZGF5c1wiOmNhc2VcImRheVwiOmNhc2VcImRcIjpyZXR1cm4gcipncjtjYXNlXCJob3Vyc1wiOmNhc2VcImhvdXJcIjpjYXNlXCJocnNcIjpjYXNlXCJoclwiOmNhc2VcImhcIjpyZXR1cm4gcipLcjtjYXNlXCJtaW51dGVzXCI6Y2FzZVwibWludXRlXCI6Y2FzZVwibWluc1wiOmNhc2VcIm1pblwiOmNhc2VcIm1cIjpyZXR1cm4gcip6cjtjYXNlXCJzZWNvbmRzXCI6Y2FzZVwic2Vjb25kXCI6Y2FzZVwic2Vjc1wiOmNhc2VcInNlY1wiOmNhc2VcInNcIjpyZXR1cm4gcipWcjtjYXNlXCJtaWxsaXNlY29uZHNcIjpjYXNlXCJtaWxsaXNlY29uZFwiOmNhc2VcIm1zZWNzXCI6Y2FzZVwibXNlY1wiOmNhc2VcIm1zXCI6cmV0dXJuIHI7ZGVmYXVsdDpyZXR1cm59fX19ZnVuY3Rpb24gbW0odCl7dmFyIGU9TWF0aC5hYnModCk7cmV0dXJuIGU+PWdyP01hdGgucm91bmQodC9ncikrXCJkXCI6ZT49S3I/TWF0aC5yb3VuZCh0L0tyKStcImhcIjplPj16cj9NYXRoLnJvdW5kKHQvenIpK1wibVwiOmU+PVZyP01hdGgucm91bmQodC9WcikrXCJzXCI6dCtcIm1zXCJ9ZnVuY3Rpb24gdm0odCl7dmFyIGU9TWF0aC5hYnModCk7cmV0dXJuIGU+PWdyP1RuKHQsZSxncixcImRheVwiKTplPj1Lcj9Ubih0LGUsS3IsXCJob3VyXCIpOmU+PXpyP1RuKHQsZSx6cixcIm1pbnV0ZVwiKTplPj1Wcj9Ubih0LGUsVnIsXCJzZWNvbmRcIik6dCtcIiBtc1wifWZ1bmN0aW9uIFRuKHQsZSxyLGkpe3ZhciBuPWU+PXIqMS41O3JldHVybiBNYXRoLnJvdW5kKHQvcikrXCIgXCIraSsobj9cInNcIjpcIlwiKX19KTt2YXIgYmQ9TSgoZ1AseWQpPT57digpO20oKTtfKCk7ZnVuY3Rpb24gRW0odCl7ci5kZWJ1Zz1yLHIuZGVmYXVsdD1yLHIuY29lcmNlPXUsci5kaXNhYmxlPW8sci5lbmFibGU9bixyLmVuYWJsZWQ9cyxyLmh1bWFuaXplPWdkKCksci5kZXN0cm95PWMsT2JqZWN0LmtleXModCkuZm9yRWFjaChoPT57cltoXT10W2hdO30pLHIubmFtZXM9W10sci5za2lwcz1bXSxyLmZvcm1hdHRlcnM9e307ZnVuY3Rpb24gZShoKXtsZXQgZD0wO2ZvcihsZXQgZz0wO2c8aC5sZW5ndGg7ZysrKWQ9KGQ8PDUpLWQraC5jaGFyQ29kZUF0KGcpLGR8PTA7cmV0dXJuIHIuY29sb3JzW01hdGguYWJzKGQpJXIuY29sb3JzLmxlbmd0aF19ci5zZWxlY3RDb2xvcj1lO2Z1bmN0aW9uIHIoaCl7bGV0IGQsZz1udWxsLHksdztmdW5jdGlvbiBFKC4uLlMpe2lmKCFFLmVuYWJsZWQpcmV0dXJuO2xldCBJPUUsQz1OdW1iZXIobmV3IERhdGUpLFI9Qy0oZHx8Qyk7SS5kaWZmPVIsSS5wcmV2PWQsSS5jdXJyPUMsZD1DLFNbMF09ci5jb2VyY2UoU1swXSksdHlwZW9mIFNbMF0hPVwic3RyaW5nXCImJlMudW5zaGlmdChcIiVPXCIpO2xldCBVPTA7U1swXT1TWzBdLnJlcGxhY2UoLyUoW2EtekEtWiVdKS9nLChXLEspPT57aWYoVz09PVwiJSVcIilyZXR1cm4gXCIlXCI7VSsrO2xldCB6PXIuZm9ybWF0dGVyc1tLXTtpZih0eXBlb2Ygej09XCJmdW5jdGlvblwiKXtsZXQgUT1TW1VdO1c9ei5jYWxsKEksUSksUy5zcGxpY2UoVSwxKSxVLS07fXJldHVybiBXfSksci5mb3JtYXRBcmdzLmNhbGwoSSxTKSwoSS5sb2d8fHIubG9nKS5hcHBseShJLFMpO31yZXR1cm4gRS5uYW1lc3BhY2U9aCxFLnVzZUNvbG9ycz1yLnVzZUNvbG9ycygpLEUuY29sb3I9ci5zZWxlY3RDb2xvcihoKSxFLmV4dGVuZD1pLEUuZGVzdHJveT1yLmRlc3Ryb3ksT2JqZWN0LmRlZmluZVByb3BlcnR5KEUsXCJlbmFibGVkXCIse2VudW1lcmFibGU6ITAsY29uZmlndXJhYmxlOiExLGdldDooKT0+ZyE9PW51bGw/ZzooeSE9PXIubmFtZXNwYWNlcyYmKHk9ci5uYW1lc3BhY2VzLHc9ci5lbmFibGVkKGgpKSx3KSxzZXQ6Uz0+e2c9Uzt9fSksdHlwZW9mIHIuaW5pdD09XCJmdW5jdGlvblwiJiZyLmluaXQoRSksRX1mdW5jdGlvbiBpKGgsZCl7bGV0IGc9cih0aGlzLm5hbWVzcGFjZSsodHlwZW9mIGQ+XCJ1XCI/XCI6XCI6ZCkraCk7cmV0dXJuIGcubG9nPXRoaXMubG9nLGd9ZnVuY3Rpb24gbihoKXtyLnNhdmUoaCksci5uYW1lc3BhY2VzPWgsci5uYW1lcz1bXSxyLnNraXBzPVtdO2xldCBkLGc9KHR5cGVvZiBoPT1cInN0cmluZ1wiP2g6XCJcIikuc3BsaXQoL1tcXHMsXSsvKSx5PWcubGVuZ3RoO2ZvcihkPTA7ZDx5O2QrKylnW2RdJiYoaD1nW2RdLnJlcGxhY2UoL1xcKi9nLFwiLio/XCIpLGhbMF09PT1cIi1cIj9yLnNraXBzLnB1c2gobmV3IFJlZ0V4cChcIl5cIitoLnNsaWNlKDEpK1wiJFwiKSk6ci5uYW1lcy5wdXNoKG5ldyBSZWdFeHAoXCJeXCIraCtcIiRcIikpKTt9ZnVuY3Rpb24gbygpe2xldCBoPVsuLi5yLm5hbWVzLm1hcChhKSwuLi5yLnNraXBzLm1hcChhKS5tYXAoZD0+XCItXCIrZCldLmpvaW4oXCIsXCIpO3JldHVybiByLmVuYWJsZShcIlwiKSxofWZ1bmN0aW9uIHMoaCl7aWYoaFtoLmxlbmd0aC0xXT09PVwiKlwiKXJldHVybiAhMDtsZXQgZCxnO2ZvcihkPTAsZz1yLnNraXBzLmxlbmd0aDtkPGc7ZCsrKWlmKHIuc2tpcHNbZF0udGVzdChoKSlyZXR1cm4gITE7Zm9yKGQ9MCxnPXIubmFtZXMubGVuZ3RoO2Q8ZztkKyspaWYoci5uYW1lc1tkXS50ZXN0KGgpKXJldHVybiAhMDtyZXR1cm4gITF9ZnVuY3Rpb24gYShoKXtyZXR1cm4gaC50b1N0cmluZygpLnN1YnN0cmluZygyLGgudG9TdHJpbmcoKS5sZW5ndGgtMikucmVwbGFjZSgvXFwuXFwqXFw/JC8sXCIqXCIpfWZ1bmN0aW9uIHUoaCl7cmV0dXJuIGggaW5zdGFuY2VvZiBFcnJvcj9oLnN0YWNrfHxoLm1lc3NhZ2U6aH1mdW5jdGlvbiBjKCl7Y29uc29sZS53YXJuKFwiSW5zdGFuY2UgbWV0aG9kIGBkZWJ1Zy5kZXN0cm95KClgIGlzIGRlcHJlY2F0ZWQgYW5kIG5vIGxvbmdlciBkb2VzIGFueXRoaW5nLiBJdCB3aWxsIGJlIHJlbW92ZWQgaW4gdGhlIG5leHQgbWFqb3IgdmVyc2lvbiBvZiBgZGVidWdgLlwiKTt9cmV0dXJuIHIuZW5hYmxlKHIubG9hZCgpKSxyfXlkLmV4cG9ydHM9RW07fSk7dmFyIG90PU0oKHhlLFJuKT0+e3YoKTttKCk7XygpO3hlLmZvcm1hdEFyZ3M9QW07eGUuc2F2ZT1JbTt4ZS5sb2FkPVRtO3hlLnVzZUNvbG9ycz1TbTt4ZS5zdG9yYWdlPVJtKCk7eGUuZGVzdHJveT0oKCk9PntsZXQgdD0hMTtyZXR1cm4gKCk9Pnt0fHwodD0hMCxjb25zb2xlLndhcm4oXCJJbnN0YW5jZSBtZXRob2QgYGRlYnVnLmRlc3Ryb3koKWAgaXMgZGVwcmVjYXRlZCBhbmQgbm8gbG9uZ2VyIGRvZXMgYW55dGhpbmcuIEl0IHdpbGwgYmUgcmVtb3ZlZCBpbiB0aGUgbmV4dCBtYWpvciB2ZXJzaW9uIG9mIGBkZWJ1Z2AuXCIpKTt9fSkoKTt4ZS5jb2xvcnM9W1wiIzAwMDBDQ1wiLFwiIzAwMDBGRlwiLFwiIzAwMzNDQ1wiLFwiIzAwMzNGRlwiLFwiIzAwNjZDQ1wiLFwiIzAwNjZGRlwiLFwiIzAwOTlDQ1wiLFwiIzAwOTlGRlwiLFwiIzAwQ0MwMFwiLFwiIzAwQ0MzM1wiLFwiIzAwQ0M2NlwiLFwiIzAwQ0M5OVwiLFwiIzAwQ0NDQ1wiLFwiIzAwQ0NGRlwiLFwiIzMzMDBDQ1wiLFwiIzMzMDBGRlwiLFwiIzMzMzNDQ1wiLFwiIzMzMzNGRlwiLFwiIzMzNjZDQ1wiLFwiIzMzNjZGRlwiLFwiIzMzOTlDQ1wiLFwiIzMzOTlGRlwiLFwiIzMzQ0MwMFwiLFwiIzMzQ0MzM1wiLFwiIzMzQ0M2NlwiLFwiIzMzQ0M5OVwiLFwiIzMzQ0NDQ1wiLFwiIzMzQ0NGRlwiLFwiIzY2MDBDQ1wiLFwiIzY2MDBGRlwiLFwiIzY2MzNDQ1wiLFwiIzY2MzNGRlwiLFwiIzY2Q0MwMFwiLFwiIzY2Q0MzM1wiLFwiIzk5MDBDQ1wiLFwiIzk5MDBGRlwiLFwiIzk5MzNDQ1wiLFwiIzk5MzNGRlwiLFwiIzk5Q0MwMFwiLFwiIzk5Q0MzM1wiLFwiI0NDMDAwMFwiLFwiI0NDMDAzM1wiLFwiI0NDMDA2NlwiLFwiI0NDMDA5OVwiLFwiI0NDMDBDQ1wiLFwiI0NDMDBGRlwiLFwiI0NDMzMwMFwiLFwiI0NDMzMzM1wiLFwiI0NDMzM2NlwiLFwiI0NDMzM5OVwiLFwiI0NDMzNDQ1wiLFwiI0NDMzNGRlwiLFwiI0NDNjYwMFwiLFwiI0NDNjYzM1wiLFwiI0NDOTkwMFwiLFwiI0NDOTkzM1wiLFwiI0NDQ0MwMFwiLFwiI0NDQ0MzM1wiLFwiI0ZGMDAwMFwiLFwiI0ZGMDAzM1wiLFwiI0ZGMDA2NlwiLFwiI0ZGMDA5OVwiLFwiI0ZGMDBDQ1wiLFwiI0ZGMDBGRlwiLFwiI0ZGMzMwMFwiLFwiI0ZGMzMzM1wiLFwiI0ZGMzM2NlwiLFwiI0ZGMzM5OVwiLFwiI0ZGMzNDQ1wiLFwiI0ZGMzNGRlwiLFwiI0ZGNjYwMFwiLFwiI0ZGNjYzM1wiLFwiI0ZGOTkwMFwiLFwiI0ZGOTkzM1wiLFwiI0ZGQ0MwMFwiLFwiI0ZGQ0MzM1wiXTtmdW5jdGlvbiBTbSgpe3JldHVybiB0eXBlb2Ygd2luZG93PFwidVwiJiZ3aW5kb3cucHJvY2VzcyYmKHdpbmRvdy5wcm9jZXNzLnR5cGU9PT1cInJlbmRlcmVyXCJ8fHdpbmRvdy5wcm9jZXNzLl9fbndqcyk/ITA6dHlwZW9mIEI8XCJ1XCImJkIudXNlckFnZW50JiZCLnVzZXJBZ2VudC50b0xvd2VyQ2FzZSgpLm1hdGNoKC8oZWRnZXx0cmlkZW50KVxcLyhcXGQrKS8pPyExOnR5cGVvZiBkb2N1bWVudDxcInVcIiYmZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50JiZkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUmJmRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5XZWJraXRBcHBlYXJhbmNlfHx0eXBlb2Ygd2luZG93PFwidVwiJiZ3aW5kb3cuY29uc29sZSYmKHdpbmRvdy5jb25zb2xlLmZpcmVidWd8fHdpbmRvdy5jb25zb2xlLmV4Y2VwdGlvbiYmd2luZG93LmNvbnNvbGUudGFibGUpfHx0eXBlb2YgQjxcInVcIiYmQi51c2VyQWdlbnQmJkIudXNlckFnZW50LnRvTG93ZXJDYXNlKCkubWF0Y2goL2ZpcmVmb3hcXC8oXFxkKykvKSYmcGFyc2VJbnQoUmVnRXhwLiQxLDEwKT49MzF8fHR5cGVvZiBCPFwidVwiJiZCLnVzZXJBZ2VudCYmQi51c2VyQWdlbnQudG9Mb3dlckNhc2UoKS5tYXRjaCgvYXBwbGV3ZWJraXRcXC8oXFxkKykvKX1mdW5jdGlvbiBBbSh0KXtpZih0WzBdPSh0aGlzLnVzZUNvbG9ycz9cIiVjXCI6XCJcIikrdGhpcy5uYW1lc3BhY2UrKHRoaXMudXNlQ29sb3JzP1wiICVjXCI6XCIgXCIpK3RbMF0rKHRoaXMudXNlQ29sb3JzP1wiJWMgXCI6XCIgXCIpK1wiK1wiK1JuLmV4cG9ydHMuaHVtYW5pemUodGhpcy5kaWZmKSwhdGhpcy51c2VDb2xvcnMpcmV0dXJuO2xldCBlPVwiY29sb3I6IFwiK3RoaXMuY29sb3I7dC5zcGxpY2UoMSwwLGUsXCJjb2xvcjogaW5oZXJpdFwiKTtsZXQgcj0wLGk9MDt0WzBdLnJlcGxhY2UoLyVbYS16QS1aJV0vZyxuPT57biE9PVwiJSVcIiYmKHIrKyxuPT09XCIlY1wiJiYoaT1yKSk7fSksdC5zcGxpY2UoaSwwLGUpO314ZS5sb2c9Y29uc29sZS5kZWJ1Z3x8Y29uc29sZS5sb2d8fCgoKT0+e30pO2Z1bmN0aW9uIEltKHQpe3RyeXt0P3hlLnN0b3JhZ2Uuc2V0SXRlbShcImRlYnVnXCIsdCk6eGUuc3RvcmFnZS5yZW1vdmVJdGVtKFwiZGVidWdcIik7fWNhdGNoe319ZnVuY3Rpb24gVG0oKXtsZXQgdDt0cnl7dD14ZS5zdG9yYWdlLmdldEl0ZW0oXCJkZWJ1Z1wiKTt9Y2F0Y2h7fXJldHVybiAhdCYmdHlwZW9mIFA8XCJ1XCImJlwiZW52XCJpbiBQJiYodD1QLmVudi5ERUJVRyksdH1mdW5jdGlvbiBSbSgpe3RyeXtyZXR1cm4gbG9jYWxTdG9yYWdlfWNhdGNoe319Um4uZXhwb3J0cz1iZCgpKHhlKTt2YXJ7Zm9ybWF0dGVyczpDbX09Um4uZXhwb3J0cztDbS5qPWZ1bmN0aW9uKHQpe3RyeXtyZXR1cm4gSlNPTi5zdHJpbmdpZnkodCl9Y2F0Y2goZSl7cmV0dXJuIFwiW1VuZXhwZWN0ZWRKU09OUGFyc2VFcnJvcl06IFwiK2UubWVzc2FnZX19O30pO3ZhciBtZD1NKChNUCxfZCk9Pnt2KCk7bSgpO18oKTt2YXIgQm09ZmQoKSx7RXZlbnRFbWl0dGVyOlBtfT0oaXIoKSxYKHJyKSksd2Q9aGQoKSxWPUZvKCksRD1vdCgpKFwibXF0dC1wYWNrZXQ6cGFyc2VyXCIpLFdvPWNsYXNzIHQgZXh0ZW5kcyBQbXtjb25zdHJ1Y3Rvcigpe3N1cGVyKCksdGhpcy5wYXJzZXI9dGhpcy5jb25zdHJ1Y3Rvci5wYXJzZXI7fXN0YXRpYyBwYXJzZXIoZSl7cmV0dXJuIHRoaXMgaW5zdGFuY2VvZiB0Pyh0aGlzLnNldHRpbmdzPWV8fHt9LHRoaXMuX3N0YXRlcz1bXCJfcGFyc2VIZWFkZXJcIixcIl9wYXJzZUxlbmd0aFwiLFwiX3BhcnNlUGF5bG9hZFwiLFwiX25ld1BhY2tldFwiXSx0aGlzLl9yZXNldFN0YXRlKCksdGhpcyk6bmV3IHQoKS5wYXJzZXIoZSl9X3Jlc2V0U3RhdGUoKXtEKFwiX3Jlc2V0U3RhdGU6IHJlc2V0dGluZyBwYWNrZXQsIGVycm9yLCBfbGlzdCwgYW5kIF9zdGF0ZUNvdW50ZXJcIiksdGhpcy5wYWNrZXQ9bmV3IHdkLHRoaXMuZXJyb3I9bnVsbCx0aGlzLl9saXN0PUJtKCksdGhpcy5fc3RhdGVDb3VudGVyPTA7fXBhcnNlKGUpe2Zvcih0aGlzLmVycm9yJiZ0aGlzLl9yZXNldFN0YXRlKCksdGhpcy5fbGlzdC5hcHBlbmQoZSksRChcInBhcnNlOiBjdXJyZW50IHN0YXRlOiAlc1wiLHRoaXMuX3N0YXRlc1t0aGlzLl9zdGF0ZUNvdW50ZXJdKTsodGhpcy5wYWNrZXQubGVuZ3RoIT09LTF8fHRoaXMuX2xpc3QubGVuZ3RoPjApJiZ0aGlzW3RoaXMuX3N0YXRlc1t0aGlzLl9zdGF0ZUNvdW50ZXJdXSgpJiYhdGhpcy5lcnJvcjspdGhpcy5fc3RhdGVDb3VudGVyKyssRChcInBhcnNlOiBzdGF0ZSBjb21wbGV0ZS4gX3N0YXRlQ291bnRlciBpcyBub3c6ICVkXCIsdGhpcy5fc3RhdGVDb3VudGVyKSxEKFwicGFyc2U6IHBhY2tldC5sZW5ndGg6ICVkLCBidWZmZXIgbGlzdCBsZW5ndGg6ICVkXCIsdGhpcy5wYWNrZXQubGVuZ3RoLHRoaXMuX2xpc3QubGVuZ3RoKSx0aGlzLl9zdGF0ZUNvdW50ZXI+PXRoaXMuX3N0YXRlcy5sZW5ndGgmJih0aGlzLl9zdGF0ZUNvdW50ZXI9MCk7cmV0dXJuIEQoXCJwYXJzZTogZXhpdGVkIHdoaWxlIGxvb3AuIHBhY2tldDogJWQsIGJ1ZmZlciBsaXN0IGxlbmd0aDogJWRcIix0aGlzLnBhY2tldC5sZW5ndGgsdGhpcy5fbGlzdC5sZW5ndGgpLHRoaXMuX2xpc3QubGVuZ3RofV9wYXJzZUhlYWRlcigpe2xldCBlPXRoaXMuX2xpc3QucmVhZFVJbnQ4KDApLHI9ZT4+Vi5DTURfU0hJRlQ7dGhpcy5wYWNrZXQuY21kPVYudHlwZXNbcl07bGV0IGk9ZSYxNSxuPVYucmVxdWlyZWRIZWFkZXJGbGFnc1tyXTtyZXR1cm4gbiE9bnVsbCYmaSE9PW4/dGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihWLnJlcXVpcmVkSGVhZGVyRmxhZ3NFcnJvcnNbcl0pKToodGhpcy5wYWNrZXQucmV0YWluPShlJlYuUkVUQUlOX01BU0spIT09MCx0aGlzLnBhY2tldC5xb3M9ZT4+Vi5RT1NfU0hJRlQmVi5RT1NfTUFTSyx0aGlzLnBhY2tldC5xb3M+Mj90aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiUGFja2V0IG11c3Qgbm90IGhhdmUgYm90aCBRb1MgYml0cyBzZXQgdG8gMVwiKSk6KHRoaXMucGFja2V0LmR1cD0oZSZWLkRVUF9NQVNLKSE9PTAsRChcIl9wYXJzZUhlYWRlcjogcGFja2V0OiAlb1wiLHRoaXMucGFja2V0KSx0aGlzLl9saXN0LmNvbnN1bWUoMSksITApKX1fcGFyc2VMZW5ndGgoKXtsZXQgZT10aGlzLl9wYXJzZVZhckJ5dGVOdW0oITApO3JldHVybiBlJiYodGhpcy5wYWNrZXQubGVuZ3RoPWUudmFsdWUsdGhpcy5fbGlzdC5jb25zdW1lKGUuYnl0ZXMpKSxEKFwiX3BhcnNlTGVuZ3RoICVkXCIsZS52YWx1ZSksISFlfV9wYXJzZVBheWxvYWQoKXtEKFwiX3BhcnNlUGF5bG9hZDogcGF5bG9hZCAlT1wiLHRoaXMuX2xpc3QpO2xldCBlPSExO2lmKHRoaXMucGFja2V0Lmxlbmd0aD09PTB8fHRoaXMuX2xpc3QubGVuZ3RoPj10aGlzLnBhY2tldC5sZW5ndGgpe3N3aXRjaCh0aGlzLl9wb3M9MCx0aGlzLnBhY2tldC5jbWQpe2Nhc2VcImNvbm5lY3RcIjp0aGlzLl9wYXJzZUNvbm5lY3QoKTticmVhaztjYXNlXCJjb25uYWNrXCI6dGhpcy5fcGFyc2VDb25uYWNrKCk7YnJlYWs7Y2FzZVwicHVibGlzaFwiOnRoaXMuX3BhcnNlUHVibGlzaCgpO2JyZWFrO2Nhc2VcInB1YmFja1wiOmNhc2VcInB1YnJlY1wiOmNhc2VcInB1YnJlbFwiOmNhc2VcInB1YmNvbXBcIjp0aGlzLl9wYXJzZUNvbmZpcm1hdGlvbigpO2JyZWFrO2Nhc2VcInN1YnNjcmliZVwiOnRoaXMuX3BhcnNlU3Vic2NyaWJlKCk7YnJlYWs7Y2FzZVwic3ViYWNrXCI6dGhpcy5fcGFyc2VTdWJhY2soKTticmVhaztjYXNlXCJ1bnN1YnNjcmliZVwiOnRoaXMuX3BhcnNlVW5zdWJzY3JpYmUoKTticmVhaztjYXNlXCJ1bnN1YmFja1wiOnRoaXMuX3BhcnNlVW5zdWJhY2soKTticmVhaztjYXNlXCJwaW5ncmVxXCI6Y2FzZVwicGluZ3Jlc3BcIjpicmVhaztjYXNlXCJkaXNjb25uZWN0XCI6dGhpcy5fcGFyc2VEaXNjb25uZWN0KCk7YnJlYWs7Y2FzZVwiYXV0aFwiOnRoaXMuX3BhcnNlQXV0aCgpO2JyZWFrO2RlZmF1bHQ6dGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIk5vdCBzdXBwb3J0ZWRcIikpO31lPSEwO31yZXR1cm4gRChcIl9wYXJzZVBheWxvYWQgY29tcGxldGUgcmVzdWx0OiAlc1wiLGUpLGV9X3BhcnNlQ29ubmVjdCgpe0QoXCJfcGFyc2VDb25uZWN0XCIpO2xldCBlLHIsaSxuLG89e30scz10aGlzLnBhY2tldCxhPXRoaXMuX3BhcnNlU3RyaW5nKCk7aWYoYT09PW51bGwpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJDYW5ub3QgcGFyc2UgcHJvdG9jb2xJZFwiKSk7aWYoYSE9PVwiTVFUVFwiJiZhIT09XCJNUUlzZHBcIilyZXR1cm4gdGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIkludmFsaWQgcHJvdG9jb2xJZFwiKSk7aWYocy5wcm90b2NvbElkPWEsdGhpcy5fcG9zPj10aGlzLl9saXN0Lmxlbmd0aClyZXR1cm4gdGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIlBhY2tldCB0b28gc2hvcnRcIikpO2lmKHMucHJvdG9jb2xWZXJzaW9uPXRoaXMuX2xpc3QucmVhZFVJbnQ4KHRoaXMuX3Bvcykscy5wcm90b2NvbFZlcnNpb24+PTEyOCYmKHMuYnJpZGdlTW9kZT0hMCxzLnByb3RvY29sVmVyc2lvbj1zLnByb3RvY29sVmVyc2lvbi0xMjgpLHMucHJvdG9jb2xWZXJzaW9uIT09MyYmcy5wcm90b2NvbFZlcnNpb24hPT00JiZzLnByb3RvY29sVmVyc2lvbiE9PTUpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJJbnZhbGlkIHByb3RvY29sIHZlcnNpb25cIikpO2lmKHRoaXMuX3BvcysrLHRoaXMuX3Bvcz49dGhpcy5fbGlzdC5sZW5ndGgpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJQYWNrZXQgdG9vIHNob3J0XCIpKTtpZih0aGlzLl9saXN0LnJlYWRVSW50OCh0aGlzLl9wb3MpJjEpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJDb25uZWN0IGZsYWcgYml0IDAgbXVzdCBiZSAwLCBidXQgZ290IDFcIikpO28udXNlcm5hbWU9dGhpcy5fbGlzdC5yZWFkVUludDgodGhpcy5fcG9zKSZWLlVTRVJOQU1FX01BU0ssby5wYXNzd29yZD10aGlzLl9saXN0LnJlYWRVSW50OCh0aGlzLl9wb3MpJlYuUEFTU1dPUkRfTUFTSyxvLndpbGw9dGhpcy5fbGlzdC5yZWFkVUludDgodGhpcy5fcG9zKSZWLldJTExfRkxBR19NQVNLO2xldCB1PSEhKHRoaXMuX2xpc3QucmVhZFVJbnQ4KHRoaXMuX3BvcykmVi5XSUxMX1JFVEFJTl9NQVNLKSxjPSh0aGlzLl9saXN0LnJlYWRVSW50OCh0aGlzLl9wb3MpJlYuV0lMTF9RT1NfTUFTSyk+PlYuV0lMTF9RT1NfU0hJRlQ7aWYoby53aWxsKXMud2lsbD17fSxzLndpbGwucmV0YWluPXUscy53aWxsLnFvcz1jO2Vsc2Uge2lmKHUpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJXaWxsIFJldGFpbiBGbGFnIG11c3QgYmUgc2V0IHRvIHplcm8gd2hlbiBXaWxsIEZsYWcgaXMgc2V0IHRvIDBcIikpO2lmKGMpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJXaWxsIFFvUyBtdXN0IGJlIHNldCB0byB6ZXJvIHdoZW4gV2lsbCBGbGFnIGlzIHNldCB0byAwXCIpKX1pZihzLmNsZWFuPSh0aGlzLl9saXN0LnJlYWRVSW50OCh0aGlzLl9wb3MpJlYuQ0xFQU5fU0VTU0lPTl9NQVNLKSE9PTAsdGhpcy5fcG9zKysscy5rZWVwYWxpdmU9dGhpcy5fcGFyc2VOdW0oKSxzLmtlZXBhbGl2ZT09PS0xKXJldHVybiB0aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiUGFja2V0IHRvbyBzaG9ydFwiKSk7aWYocy5wcm90b2NvbFZlcnNpb249PT01KXtsZXQgZD10aGlzLl9wYXJzZVByb3BlcnRpZXMoKTtPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhkKS5sZW5ndGgmJihzLnByb3BlcnRpZXM9ZCk7fWxldCBoPXRoaXMuX3BhcnNlU3RyaW5nKCk7aWYoaD09PW51bGwpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJQYWNrZXQgdG9vIHNob3J0XCIpKTtpZihzLmNsaWVudElkPWgsRChcIl9wYXJzZUNvbm5lY3Q6IHBhY2tldC5jbGllbnRJZDogJXNcIixzLmNsaWVudElkKSxvLndpbGwpe2lmKHMucHJvdG9jb2xWZXJzaW9uPT09NSl7bGV0IGQ9dGhpcy5fcGFyc2VQcm9wZXJ0aWVzKCk7T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoZCkubGVuZ3RoJiYocy53aWxsLnByb3BlcnRpZXM9ZCk7fWlmKGU9dGhpcy5fcGFyc2VTdHJpbmcoKSxlPT09bnVsbClyZXR1cm4gdGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIkNhbm5vdCBwYXJzZSB3aWxsIHRvcGljXCIpKTtpZihzLndpbGwudG9waWM9ZSxEKFwiX3BhcnNlQ29ubmVjdDogcGFja2V0LndpbGwudG9waWM6ICVzXCIscy53aWxsLnRvcGljKSxyPXRoaXMuX3BhcnNlQnVmZmVyKCkscj09PW51bGwpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJDYW5ub3QgcGFyc2Ugd2lsbCBwYXlsb2FkXCIpKTtzLndpbGwucGF5bG9hZD1yLEQoXCJfcGFyc2VDb25uZWN0OiBwYWNrZXQud2lsbC5wYXlsYW9kOiAlc1wiLHMud2lsbC5wYXlsb2FkKTt9aWYoby51c2VybmFtZSl7aWYobj10aGlzLl9wYXJzZVN0cmluZygpLG49PT1udWxsKXJldHVybiB0aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiQ2Fubm90IHBhcnNlIHVzZXJuYW1lXCIpKTtzLnVzZXJuYW1lPW4sRChcIl9wYXJzZUNvbm5lY3Q6IHBhY2tldC51c2VybmFtZTogJXNcIixzLnVzZXJuYW1lKTt9aWYoby5wYXNzd29yZCl7aWYoaT10aGlzLl9wYXJzZUJ1ZmZlcigpLGk9PT1udWxsKXJldHVybiB0aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiQ2Fubm90IHBhcnNlIHBhc3N3b3JkXCIpKTtzLnBhc3N3b3JkPWk7fXJldHVybiB0aGlzLnNldHRpbmdzPXMsRChcIl9wYXJzZUNvbm5lY3Q6IGNvbXBsZXRlXCIpLHN9X3BhcnNlQ29ubmFjaygpe0QoXCJfcGFyc2VDb25uYWNrXCIpO2xldCBlPXRoaXMucGFja2V0O2lmKHRoaXMuX2xpc3QubGVuZ3RoPDEpcmV0dXJuIG51bGw7bGV0IHI9dGhpcy5fbGlzdC5yZWFkVUludDgodGhpcy5fcG9zKyspO2lmKHI+MSlyZXR1cm4gdGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIkludmFsaWQgY29ubmFjayBmbGFncywgYml0cyA3LTEgbXVzdCBiZSBzZXQgdG8gMFwiKSk7aWYoZS5zZXNzaW9uUHJlc2VudD0hIShyJlYuU0VTU0lPTlBSRVNFTlRfTUFTSyksdGhpcy5zZXR0aW5ncy5wcm90b2NvbFZlcnNpb249PT01KXRoaXMuX2xpc3QubGVuZ3RoPj0yP2UucmVhc29uQ29kZT10aGlzLl9saXN0LnJlYWRVSW50OCh0aGlzLl9wb3MrKyk6ZS5yZWFzb25Db2RlPTA7ZWxzZSB7aWYodGhpcy5fbGlzdC5sZW5ndGg8MilyZXR1cm4gbnVsbDtlLnJldHVybkNvZGU9dGhpcy5fbGlzdC5yZWFkVUludDgodGhpcy5fcG9zKyspO31pZihlLnJldHVybkNvZGU9PT0tMXx8ZS5yZWFzb25Db2RlPT09LTEpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJDYW5ub3QgcGFyc2UgcmV0dXJuIGNvZGVcIikpO2lmKHRoaXMuc2V0dGluZ3MucHJvdG9jb2xWZXJzaW9uPT09NSl7bGV0IGk9dGhpcy5fcGFyc2VQcm9wZXJ0aWVzKCk7T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoaSkubGVuZ3RoJiYoZS5wcm9wZXJ0aWVzPWkpO31EKFwiX3BhcnNlQ29ubmFjazogY29tcGxldGVcIik7fV9wYXJzZVB1Ymxpc2goKXtEKFwiX3BhcnNlUHVibGlzaFwiKTtsZXQgZT10aGlzLnBhY2tldDtpZihlLnRvcGljPXRoaXMuX3BhcnNlU3RyaW5nKCksZS50b3BpYz09PW51bGwpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJDYW5ub3QgcGFyc2UgdG9waWNcIikpO2lmKCEoZS5xb3M+MCYmIXRoaXMuX3BhcnNlTWVzc2FnZUlkKCkpKXtpZih0aGlzLnNldHRpbmdzLnByb3RvY29sVmVyc2lvbj09PTUpe2xldCByPXRoaXMuX3BhcnNlUHJvcGVydGllcygpO09iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHIpLmxlbmd0aCYmKGUucHJvcGVydGllcz1yKTt9ZS5wYXlsb2FkPXRoaXMuX2xpc3Quc2xpY2UodGhpcy5fcG9zLGUubGVuZ3RoKSxEKFwiX3BhcnNlUHVibGlzaDogcGF5bG9hZCBmcm9tIGJ1ZmZlciBsaXN0OiAlb1wiLGUucGF5bG9hZCk7fX1fcGFyc2VTdWJzY3JpYmUoKXtEKFwiX3BhcnNlU3Vic2NyaWJlXCIpO2xldCBlPXRoaXMucGFja2V0LHIsaSxuLG8scyxhLHU7aWYoZS5zdWJzY3JpcHRpb25zPVtdLCEhdGhpcy5fcGFyc2VNZXNzYWdlSWQoKSl7aWYodGhpcy5zZXR0aW5ncy5wcm90b2NvbFZlcnNpb249PT01KXtsZXQgYz10aGlzLl9wYXJzZVByb3BlcnRpZXMoKTtPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhjKS5sZW5ndGgmJihlLnByb3BlcnRpZXM9Yyk7fWlmKGUubGVuZ3RoPD0wKXJldHVybiB0aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiTWFsZm9ybWVkIHN1YnNjcmliZSwgbm8gcGF5bG9hZCBzcGVjaWZpZWRcIikpO2Zvcig7dGhpcy5fcG9zPGUubGVuZ3RoOyl7aWYocj10aGlzLl9wYXJzZVN0cmluZygpLHI9PT1udWxsKXJldHVybiB0aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiQ2Fubm90IHBhcnNlIHRvcGljXCIpKTtpZih0aGlzLl9wb3M+PWUubGVuZ3RoKXJldHVybiB0aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiTWFsZm9ybWVkIFN1YnNjcmliZSBQYXlsb2FkXCIpKTtpZihpPXRoaXMuX3BhcnNlQnl0ZSgpLHRoaXMuc2V0dGluZ3MucHJvdG9jb2xWZXJzaW9uPT09NSl7aWYoaSYxOTIpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJJbnZhbGlkIHN1YnNjcmliZSB0b3BpYyBmbGFnIGJpdHMsIGJpdHMgNy02IG11c3QgYmUgMFwiKSl9ZWxzZSBpZihpJjI1MilyZXR1cm4gdGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIkludmFsaWQgc3Vic2NyaWJlIHRvcGljIGZsYWcgYml0cywgYml0cyA3LTIgbXVzdCBiZSAwXCIpKTtpZihuPWkmVi5TVUJTQ1JJQkVfT1BUSU9OU19RT1NfTUFTSyxuPjIpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJJbnZhbGlkIHN1YnNjcmliZSBRb1MsIG11c3QgYmUgPD0gMlwiKSk7aWYoYT0oaT4+Vi5TVUJTQ1JJQkVfT1BUSU9OU19OTF9TSElGVCZWLlNVQlNDUklCRV9PUFRJT05TX05MX01BU0spIT09MCxzPShpPj5WLlNVQlNDUklCRV9PUFRJT05TX1JBUF9TSElGVCZWLlNVQlNDUklCRV9PUFRJT05TX1JBUF9NQVNLKSE9PTAsbz1pPj5WLlNVQlNDUklCRV9PUFRJT05TX1JIX1NISUZUJlYuU1VCU0NSSUJFX09QVElPTlNfUkhfTUFTSyxvPjIpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJJbnZhbGlkIHJldGFpbiBoYW5kbGluZywgbXVzdCBiZSA8PSAyXCIpKTt1PXt0b3BpYzpyLHFvczpufSx0aGlzLnNldHRpbmdzLnByb3RvY29sVmVyc2lvbj09PTU/KHUubmw9YSx1LnJhcD1zLHUucmg9byk6dGhpcy5zZXR0aW5ncy5icmlkZ2VNb2RlJiYodS5yaD0wLHUucmFwPSEwLHUubmw9ITApLEQoXCJfcGFyc2VTdWJzY3JpYmU6IHB1c2ggc3Vic2NyaXB0aW9uIGAlc2AgdG8gc3Vic2NyaXB0aW9uXCIsdSksZS5zdWJzY3JpcHRpb25zLnB1c2godSk7fX19X3BhcnNlU3ViYWNrKCl7RChcIl9wYXJzZVN1YmFja1wiKTtsZXQgZT10aGlzLnBhY2tldDtpZih0aGlzLnBhY2tldC5ncmFudGVkPVtdLCEhdGhpcy5fcGFyc2VNZXNzYWdlSWQoKSl7aWYodGhpcy5zZXR0aW5ncy5wcm90b2NvbFZlcnNpb249PT01KXtsZXQgcj10aGlzLl9wYXJzZVByb3BlcnRpZXMoKTtPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhyKS5sZW5ndGgmJihlLnByb3BlcnRpZXM9cik7fWlmKGUubGVuZ3RoPD0wKXJldHVybiB0aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiTWFsZm9ybWVkIHN1YmFjaywgbm8gcGF5bG9hZCBzcGVjaWZpZWRcIikpO2Zvcig7dGhpcy5fcG9zPHRoaXMucGFja2V0Lmxlbmd0aDspe2xldCByPXRoaXMuX2xpc3QucmVhZFVJbnQ4KHRoaXMuX3BvcysrKTtpZih0aGlzLnNldHRpbmdzLnByb3RvY29sVmVyc2lvbj09PTUpe2lmKCFWLk1RVFQ1X1NVQkFDS19DT0RFU1tyXSlyZXR1cm4gdGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIkludmFsaWQgc3ViYWNrIGNvZGVcIikpfWVsc2UgaWYocj4yJiZyIT09MTI4KXJldHVybiB0aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiSW52YWxpZCBzdWJhY2sgUW9TLCBtdXN0IGJlIDAsIDEsIDIgb3IgMTI4XCIpKTt0aGlzLnBhY2tldC5ncmFudGVkLnB1c2gocik7fX19X3BhcnNlVW5zdWJzY3JpYmUoKXtEKFwiX3BhcnNlVW5zdWJzY3JpYmVcIik7bGV0IGU9dGhpcy5wYWNrZXQ7aWYoZS51bnN1YnNjcmlwdGlvbnM9W10sISF0aGlzLl9wYXJzZU1lc3NhZ2VJZCgpKXtpZih0aGlzLnNldHRpbmdzLnByb3RvY29sVmVyc2lvbj09PTUpe2xldCByPXRoaXMuX3BhcnNlUHJvcGVydGllcygpO09iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHIpLmxlbmd0aCYmKGUucHJvcGVydGllcz1yKTt9aWYoZS5sZW5ndGg8PTApcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJNYWxmb3JtZWQgdW5zdWJzY3JpYmUsIG5vIHBheWxvYWQgc3BlY2lmaWVkXCIpKTtmb3IoO3RoaXMuX3BvczxlLmxlbmd0aDspe2xldCByPXRoaXMuX3BhcnNlU3RyaW5nKCk7aWYocj09PW51bGwpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJDYW5ub3QgcGFyc2UgdG9waWNcIikpO0QoXCJfcGFyc2VVbnN1YnNjcmliZTogcHVzaCB0b3BpYyBgJXNgIHRvIHVuc3Vic2NyaXB0aW9uc1wiLHIpLGUudW5zdWJzY3JpcHRpb25zLnB1c2gocik7fX19X3BhcnNlVW5zdWJhY2soKXtEKFwiX3BhcnNlVW5zdWJhY2tcIik7bGV0IGU9dGhpcy5wYWNrZXQ7aWYoIXRoaXMuX3BhcnNlTWVzc2FnZUlkKCkpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJDYW5ub3QgcGFyc2UgbWVzc2FnZUlkXCIpKTtpZigodGhpcy5zZXR0aW5ncy5wcm90b2NvbFZlcnNpb249PT0zfHx0aGlzLnNldHRpbmdzLnByb3RvY29sVmVyc2lvbj09PTQpJiZlLmxlbmd0aCE9PTIpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJNYWxmb3JtZWQgdW5zdWJhY2ssIHBheWxvYWQgbGVuZ3RoIG11c3QgYmUgMlwiKSk7aWYoZS5sZW5ndGg8PTApcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJNYWxmb3JtZWQgdW5zdWJhY2ssIG5vIHBheWxvYWQgc3BlY2lmaWVkXCIpKTtpZih0aGlzLnNldHRpbmdzLnByb3RvY29sVmVyc2lvbj09PTUpe2xldCByPXRoaXMuX3BhcnNlUHJvcGVydGllcygpO2ZvcihPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhyKS5sZW5ndGgmJihlLnByb3BlcnRpZXM9ciksZS5ncmFudGVkPVtdO3RoaXMuX3Bvczx0aGlzLnBhY2tldC5sZW5ndGg7KXtsZXQgaT10aGlzLl9saXN0LnJlYWRVSW50OCh0aGlzLl9wb3MrKyk7aWYoIVYuTVFUVDVfVU5TVUJBQ0tfQ09ERVNbaV0pcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJJbnZhbGlkIHVuc3ViYWNrIGNvZGVcIikpO3RoaXMucGFja2V0LmdyYW50ZWQucHVzaChpKTt9fX1fcGFyc2VDb25maXJtYXRpb24oKXtEKFwiX3BhcnNlQ29uZmlybWF0aW9uOiBwYWNrZXQuY21kOiBgJXNgXCIsdGhpcy5wYWNrZXQuY21kKTtsZXQgZT10aGlzLnBhY2tldDtpZih0aGlzLl9wYXJzZU1lc3NhZ2VJZCgpLHRoaXMuc2V0dGluZ3MucHJvdG9jb2xWZXJzaW9uPT09NSl7aWYoZS5sZW5ndGg+Mil7c3dpdGNoKGUucmVhc29uQ29kZT10aGlzLl9wYXJzZUJ5dGUoKSx0aGlzLnBhY2tldC5jbWQpe2Nhc2VcInB1YmFja1wiOmNhc2VcInB1YnJlY1wiOmlmKCFWLk1RVFQ1X1BVQkFDS19QVUJSRUNfQ09ERVNbZS5yZWFzb25Db2RlXSlyZXR1cm4gdGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIkludmFsaWQgXCIrdGhpcy5wYWNrZXQuY21kK1wiIHJlYXNvbiBjb2RlXCIpKTticmVhaztjYXNlXCJwdWJyZWxcIjpjYXNlXCJwdWJjb21wXCI6aWYoIVYuTVFUVDVfUFVCUkVMX1BVQkNPTVBfQ09ERVNbZS5yZWFzb25Db2RlXSlyZXR1cm4gdGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIkludmFsaWQgXCIrdGhpcy5wYWNrZXQuY21kK1wiIHJlYXNvbiBjb2RlXCIpKTticmVha31EKFwiX3BhcnNlQ29uZmlybWF0aW9uOiBwYWNrZXQucmVhc29uQ29kZSBgJWRgXCIsZS5yZWFzb25Db2RlKTt9ZWxzZSBlLnJlYXNvbkNvZGU9MDtpZihlLmxlbmd0aD4zKXtsZXQgcj10aGlzLl9wYXJzZVByb3BlcnRpZXMoKTtPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhyKS5sZW5ndGgmJihlLnByb3BlcnRpZXM9cik7fX1yZXR1cm4gITB9X3BhcnNlRGlzY29ubmVjdCgpe2xldCBlPXRoaXMucGFja2V0O2lmKEQoXCJfcGFyc2VEaXNjb25uZWN0XCIpLHRoaXMuc2V0dGluZ3MucHJvdG9jb2xWZXJzaW9uPT09NSl7dGhpcy5fbGlzdC5sZW5ndGg+MD8oZS5yZWFzb25Db2RlPXRoaXMuX3BhcnNlQnl0ZSgpLFYuTVFUVDVfRElTQ09OTkVDVF9DT0RFU1tlLnJlYXNvbkNvZGVdfHx0aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiSW52YWxpZCBkaXNjb25uZWN0IHJlYXNvbiBjb2RlXCIpKSk6ZS5yZWFzb25Db2RlPTA7bGV0IHI9dGhpcy5fcGFyc2VQcm9wZXJ0aWVzKCk7T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMocikubGVuZ3RoJiYoZS5wcm9wZXJ0aWVzPXIpO31yZXR1cm4gRChcIl9wYXJzZURpc2Nvbm5lY3QgcmVzdWx0OiB0cnVlXCIpLCEwfV9wYXJzZUF1dGgoKXtEKFwiX3BhcnNlQXV0aFwiKTtsZXQgZT10aGlzLnBhY2tldDtpZih0aGlzLnNldHRpbmdzLnByb3RvY29sVmVyc2lvbiE9PTUpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJOb3Qgc3VwcG9ydGVkIGF1dGggcGFja2V0IGZvciB0aGlzIHZlcnNpb24gTVFUVFwiKSk7aWYoZS5yZWFzb25Db2RlPXRoaXMuX3BhcnNlQnl0ZSgpLCFWLk1RVFQ1X0FVVEhfQ09ERVNbZS5yZWFzb25Db2RlXSlyZXR1cm4gdGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIkludmFsaWQgYXV0aCByZWFzb24gY29kZVwiKSk7bGV0IHI9dGhpcy5fcGFyc2VQcm9wZXJ0aWVzKCk7cmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHIpLmxlbmd0aCYmKGUucHJvcGVydGllcz1yKSxEKFwiX3BhcnNlQXV0aDogcmVzdWx0OiB0cnVlXCIpLCEwfV9wYXJzZU1lc3NhZ2VJZCgpe2xldCBlPXRoaXMucGFja2V0O3JldHVybiBlLm1lc3NhZ2VJZD10aGlzLl9wYXJzZU51bSgpLGUubWVzc2FnZUlkPT09bnVsbD8odGhpcy5fZW1pdEVycm9yKG5ldyBFcnJvcihcIkNhbm5vdCBwYXJzZSBtZXNzYWdlSWRcIikpLCExKTooRChcIl9wYXJzZU1lc3NhZ2VJZDogcGFja2V0Lm1lc3NhZ2VJZCAlZFwiLGUubWVzc2FnZUlkKSwhMCl9X3BhcnNlU3RyaW5nKGUpe2xldCByPXRoaXMuX3BhcnNlTnVtKCksaT1yK3RoaXMuX3BvcztpZihyPT09LTF8fGk+dGhpcy5fbGlzdC5sZW5ndGh8fGk+dGhpcy5wYWNrZXQubGVuZ3RoKXJldHVybiBudWxsO2xldCBuPXRoaXMuX2xpc3QudG9TdHJpbmcoXCJ1dGY4XCIsdGhpcy5fcG9zLGkpO3JldHVybiB0aGlzLl9wb3MrPXIsRChcIl9wYXJzZVN0cmluZzogcmVzdWx0OiAlc1wiLG4pLG59X3BhcnNlU3RyaW5nUGFpcigpe3JldHVybiBEKFwiX3BhcnNlU3RyaW5nUGFpclwiKSx7bmFtZTp0aGlzLl9wYXJzZVN0cmluZygpLHZhbHVlOnRoaXMuX3BhcnNlU3RyaW5nKCl9fV9wYXJzZUJ1ZmZlcigpe2xldCBlPXRoaXMuX3BhcnNlTnVtKCkscj1lK3RoaXMuX3BvcztpZihlPT09LTF8fHI+dGhpcy5fbGlzdC5sZW5ndGh8fHI+dGhpcy5wYWNrZXQubGVuZ3RoKXJldHVybiBudWxsO2xldCBpPXRoaXMuX2xpc3Quc2xpY2UodGhpcy5fcG9zLHIpO3JldHVybiB0aGlzLl9wb3MrPWUsRChcIl9wYXJzZUJ1ZmZlcjogcmVzdWx0OiAlb1wiLGkpLGl9X3BhcnNlTnVtKCl7aWYodGhpcy5fbGlzdC5sZW5ndGgtdGhpcy5fcG9zPDIpcmV0dXJuIC0xO2xldCBlPXRoaXMuX2xpc3QucmVhZFVJbnQxNkJFKHRoaXMuX3Bvcyk7cmV0dXJuIHRoaXMuX3Bvcys9MixEKFwiX3BhcnNlTnVtOiByZXN1bHQ6ICVzXCIsZSksZX1fcGFyc2U0Qnl0ZU51bSgpe2lmKHRoaXMuX2xpc3QubGVuZ3RoLXRoaXMuX3Bvczw0KXJldHVybiAtMTtsZXQgZT10aGlzLl9saXN0LnJlYWRVSW50MzJCRSh0aGlzLl9wb3MpO3JldHVybiB0aGlzLl9wb3MrPTQsRChcIl9wYXJzZTRCeXRlTnVtOiByZXN1bHQ6ICVzXCIsZSksZX1fcGFyc2VWYXJCeXRlTnVtKGUpe0QoXCJfcGFyc2VWYXJCeXRlTnVtXCIpO2xldCByPTQsaT0wLG49MSxvPTAscz0hMSxhLHU9dGhpcy5fcG9zP3RoaXMuX3BvczowO2Zvcig7aTxyJiZ1K2k8dGhpcy5fbGlzdC5sZW5ndGg7KXtpZihhPXRoaXMuX2xpc3QucmVhZFVJbnQ4KHUraSsrKSxvKz1uKihhJlYuVkFSQllURUlOVF9NQVNLKSxuKj0xMjgsIShhJlYuVkFSQllURUlOVF9GSU5fTUFTSykpe3M9ITA7YnJlYWt9aWYodGhpcy5fbGlzdC5sZW5ndGg8PWkpYnJlYWt9cmV0dXJuICFzJiZpPT09ciYmdGhpcy5fbGlzdC5sZW5ndGg+PWkmJnRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJJbnZhbGlkIHZhcmlhYmxlIGJ5dGUgaW50ZWdlclwiKSksdSYmKHRoaXMuX3Bvcys9aSkscz9lP3M9e2J5dGVzOmksdmFsdWU6b306cz1vOnM9ITEsRChcIl9wYXJzZVZhckJ5dGVOdW06IHJlc3VsdDogJW9cIixzKSxzfV9wYXJzZUJ5dGUoKXtsZXQgZTtyZXR1cm4gdGhpcy5fcG9zPHRoaXMuX2xpc3QubGVuZ3RoJiYoZT10aGlzLl9saXN0LnJlYWRVSW50OCh0aGlzLl9wb3MpLHRoaXMuX3BvcysrKSxEKFwiX3BhcnNlQnl0ZTogcmVzdWx0OiAlb1wiLGUpLGV9X3BhcnNlQnlUeXBlKGUpe3N3aXRjaChEKFwiX3BhcnNlQnlUeXBlOiB0eXBlOiAlc1wiLGUpLGUpe2Nhc2VcImJ5dGVcIjpyZXR1cm4gdGhpcy5fcGFyc2VCeXRlKCkhPT0wO2Nhc2VcImludDhcIjpyZXR1cm4gdGhpcy5fcGFyc2VCeXRlKCk7Y2FzZVwiaW50MTZcIjpyZXR1cm4gdGhpcy5fcGFyc2VOdW0oKTtjYXNlXCJpbnQzMlwiOnJldHVybiB0aGlzLl9wYXJzZTRCeXRlTnVtKCk7Y2FzZVwidmFyXCI6cmV0dXJuIHRoaXMuX3BhcnNlVmFyQnl0ZU51bSgpO2Nhc2VcInN0cmluZ1wiOnJldHVybiB0aGlzLl9wYXJzZVN0cmluZygpO2Nhc2VcInBhaXJcIjpyZXR1cm4gdGhpcy5fcGFyc2VTdHJpbmdQYWlyKCk7Y2FzZVwiYmluYXJ5XCI6cmV0dXJuIHRoaXMuX3BhcnNlQnVmZmVyKCl9fV9wYXJzZVByb3BlcnRpZXMoKXtEKFwiX3BhcnNlUHJvcGVydGllc1wiKTtsZXQgZT10aGlzLl9wYXJzZVZhckJ5dGVOdW0oKSxpPXRoaXMuX3BvcytlLG49e307Zm9yKDt0aGlzLl9wb3M8aTspe2xldCBvPXRoaXMuX3BhcnNlQnl0ZSgpO2lmKCFvKXJldHVybiB0aGlzLl9lbWl0RXJyb3IobmV3IEVycm9yKFwiQ2Fubm90IHBhcnNlIHByb3BlcnR5IGNvZGUgdHlwZVwiKSksITE7bGV0IHM9Vi5wcm9wZXJ0aWVzQ29kZXNbb107aWYoIXMpcmV0dXJuIHRoaXMuX2VtaXRFcnJvcihuZXcgRXJyb3IoXCJVbmtub3duIHByb3BlcnR5XCIpKSwhMTtpZihzPT09XCJ1c2VyUHJvcGVydGllc1wiKXtuW3NdfHwobltzXT1PYmplY3QuY3JlYXRlKG51bGwpKTtsZXQgYT10aGlzLl9wYXJzZUJ5VHlwZShWLnByb3BlcnRpZXNUeXBlc1tzXSk7aWYobltzXVthLm5hbWVdKWlmKEFycmF5LmlzQXJyYXkobltzXVthLm5hbWVdKSluW3NdW2EubmFtZV0ucHVzaChhLnZhbHVlKTtlbHNlIHtsZXQgdT1uW3NdW2EubmFtZV07bltzXVthLm5hbWVdPVt1XSxuW3NdW2EubmFtZV0ucHVzaChhLnZhbHVlKTt9ZWxzZSBuW3NdW2EubmFtZV09YS52YWx1ZTtjb250aW51ZX1uW3NdP0FycmF5LmlzQXJyYXkobltzXSk/bltzXS5wdXNoKHRoaXMuX3BhcnNlQnlUeXBlKFYucHJvcGVydGllc1R5cGVzW3NdKSk6KG5bc109W25bc11dLG5bc10ucHVzaCh0aGlzLl9wYXJzZUJ5VHlwZShWLnByb3BlcnRpZXNUeXBlc1tzXSkpKTpuW3NdPXRoaXMuX3BhcnNlQnlUeXBlKFYucHJvcGVydGllc1R5cGVzW3NdKTt9cmV0dXJuIG59X25ld1BhY2tldCgpe3JldHVybiBEKFwiX25ld1BhY2tldFwiKSx0aGlzLnBhY2tldCYmKHRoaXMuX2xpc3QuY29uc3VtZSh0aGlzLnBhY2tldC5sZW5ndGgpLEQoXCJfbmV3UGFja2V0OiBwYXJzZXIgZW1pdCBwYWNrZXQ6IHBhY2tldC5jbWQ6ICVzLCBwYWNrZXQucGF5bG9hZDogJXMsIHBhY2tldC5sZW5ndGg6ICVkXCIsdGhpcy5wYWNrZXQuY21kLHRoaXMucGFja2V0LnBheWxvYWQsdGhpcy5wYWNrZXQubGVuZ3RoKSx0aGlzLmVtaXQoXCJwYWNrZXRcIix0aGlzLnBhY2tldCkpLEQoXCJfbmV3UGFja2V0OiBuZXcgcGFja2V0XCIpLHRoaXMucGFja2V0PW5ldyB3ZCx0aGlzLl9wb3M9MCwhMH1fZW1pdEVycm9yKGUpe0QoXCJfZW1pdEVycm9yXCIsZSksdGhpcy5lcnJvcj1lLHRoaXMuZW1pdChcImVycm9yXCIsZSk7fX07X2QuZXhwb3J0cz1Xbzt9KTt2YXIgQWQ9TSgoSFAsU2QpPT57digpO20oKTtfKCk7dmFye0J1ZmZlcjp2aX09KHllKCksWChfZSkpLE9tPTY1NTM2LHZkPXt9LGttPXZpLmlzQnVmZmVyKHZpLmZyb20oWzEsMl0pLnN1YmFycmF5KDAsMSkpO2Z1bmN0aW9uIEVkKHQpe2xldCBlPXZpLmFsbG9jVW5zYWZlKDIpO3JldHVybiBlLndyaXRlVUludDgodD4+OCwwKSxlLndyaXRlVUludDgodCYyNTUsMCsxKSxlfWZ1bmN0aW9uIHhtKCl7Zm9yKGxldCB0PTA7dDxPbTt0KyspdmRbdF09RWQodCk7fWZ1bmN0aW9uIE1tKHQpe2xldCByPTAsaT0wLG49dmkuYWxsb2NVbnNhZmUoNCk7ZG8gcj10JTEyOHwwLHQ9dC8xMjh8MCx0PjAmJihyPXJ8MTI4KSxuLndyaXRlVUludDgocixpKyspO3doaWxlKHQ+MCYmaTw0KTtyZXR1cm4gdD4wJiYoaT0wKSxrbT9uLnN1YmFycmF5KDAsaSk6bi5zbGljZSgwLGkpfWZ1bmN0aW9uIExtKHQpe2xldCBlPXZpLmFsbG9jVW5zYWZlKDQpO3JldHVybiBlLndyaXRlVUludDMyQkUodCwwKSxlfVNkLmV4cG9ydHM9e2NhY2hlOnZkLGdlbmVyYXRlQ2FjaGU6eG0sZ2VuZXJhdGVOdW1iZXI6RWQsZ2VuQnVmVmFyaWFibGVCeXRlSW50Ok1tLGdlbmVyYXRlNEJ5dGVCdWZmZXI6TG19O30pO3ZhciBJZD1NKChlTywkbyk9Pnt2KCk7bSgpO18oKTt0eXBlb2YgUD5cInVcInx8IVAudmVyc2lvbnx8UC52ZXJzaW9uLmluZGV4T2YoXCJ2MC5cIik9PT0wfHxQLnZlcnNpb24uaW5kZXhPZihcInYxLlwiKT09PTAmJlAudmVyc2lvbi5pbmRleE9mKFwidjEuOC5cIikhPT0wPyRvLmV4cG9ydHM9e25leHRUaWNrOlVtfTokby5leHBvcnRzPVA7ZnVuY3Rpb24gVW0odCxlLHIsaSl7aWYodHlwZW9mIHQhPVwiZnVuY3Rpb25cIil0aHJvdyBuZXcgVHlwZUVycm9yKCdcImNhbGxiYWNrXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7dmFyIG49YXJndW1lbnRzLmxlbmd0aCxvLHM7c3dpdGNoKG4pe2Nhc2UgMDpjYXNlIDE6cmV0dXJuIFAubmV4dFRpY2sodCk7Y2FzZSAyOnJldHVybiBQLm5leHRUaWNrKGZ1bmN0aW9uKCl7dC5jYWxsKG51bGwsZSk7fSk7Y2FzZSAzOnJldHVybiBQLm5leHRUaWNrKGZ1bmN0aW9uKCl7dC5jYWxsKG51bGwsZSxyKTt9KTtjYXNlIDQ6cmV0dXJuIFAubmV4dFRpY2soZnVuY3Rpb24oKXt0LmNhbGwobnVsbCxlLHIsaSk7fSk7ZGVmYXVsdDpmb3Iobz1uZXcgQXJyYXkobi0xKSxzPTA7czxvLmxlbmd0aDspb1tzKytdPWFyZ3VtZW50c1tzXTtyZXR1cm4gUC5uZXh0VGljayhmdW5jdGlvbigpe3QuYXBwbHkobnVsbCxvKTt9KX19fSk7dmFyIHpvPU0oKGZPLHhkKT0+e3YoKTttKCk7XygpO3ZhciBqPUZvKCkse0J1ZmZlcjpxfT0oeWUoKSxYKF9lKSksTm09cS5hbGxvY1Vuc2FmZSgwKSxxbT1xLmZyb20oWzBdKSxFaT1BZCgpLERtPUlkKCkubmV4dFRpY2sscWU9b3QoKShcIm1xdHQtcGFja2V0OndyaXRlVG9TdHJlYW1cIiksQ249RWkuY2FjaGUsam09RWkuZ2VuZXJhdGVOdW1iZXIsRm09RWkuZ2VuZXJhdGVDYWNoZSxIbz1FaS5nZW5CdWZWYXJpYWJsZUJ5dGVJbnQsV209RWkuZ2VuZXJhdGU0Qnl0ZUJ1ZmZlcixJZT1WbyxCbj0hMDtmdW5jdGlvbiBPZCh0LGUscil7c3dpdGNoKHFlKFwiZ2VuZXJhdGUgY2FsbGVkXCIpLGUuY29yayYmKGUuY29yaygpLERtKCRtLGUpKSxCbiYmKEJuPSExLEZtKCkpLHFlKFwiZ2VuZXJhdGU6IHBhY2tldC5jbWQ6ICVzXCIsdC5jbWQpLHQuY21kKXtjYXNlXCJjb25uZWN0XCI6cmV0dXJuIEhtKHQsZSk7Y2FzZVwiY29ubmFja1wiOnJldHVybiBWbSh0LGUscik7Y2FzZVwicHVibGlzaFwiOnJldHVybiB6bSh0LGUscik7Y2FzZVwicHViYWNrXCI6Y2FzZVwicHVicmVjXCI6Y2FzZVwicHVicmVsXCI6Y2FzZVwicHViY29tcFwiOnJldHVybiBLbSh0LGUscik7Y2FzZVwic3Vic2NyaWJlXCI6cmV0dXJuIEdtKHQsZSxyKTtjYXNlXCJzdWJhY2tcIjpyZXR1cm4gUW0odCxlLHIpO2Nhc2VcInVuc3Vic2NyaWJlXCI6cmV0dXJuIFltKHQsZSxyKTtjYXNlXCJ1bnN1YmFja1wiOnJldHVybiBKbSh0LGUscik7Y2FzZVwicGluZ3JlcVwiOmNhc2VcInBpbmdyZXNwXCI6cmV0dXJuIFhtKHQsZSk7Y2FzZVwiZGlzY29ubmVjdFwiOnJldHVybiBabSh0LGUscik7Y2FzZVwiYXV0aFwiOnJldHVybiBlMSh0LGUscik7ZGVmYXVsdDpyZXR1cm4gZS5kZXN0cm95KG5ldyBFcnJvcihcIlVua25vd24gY29tbWFuZFwiKSksITF9fU9iamVjdC5kZWZpbmVQcm9wZXJ0eShPZCxcImNhY2hlTnVtYmVyc1wiLHtnZXQoKXtyZXR1cm4gSWU9PT1Wb30sc2V0KHQpe3Q/KCghQ258fE9iamVjdC5rZXlzKENuKS5sZW5ndGg9PT0wKSYmKEJuPSEwKSxJZT1Wbyk6KEJuPSExLEllPXQxKTt9fSk7ZnVuY3Rpb24gJG0odCl7dC51bmNvcmsoKTt9ZnVuY3Rpb24gSG0odCxlLHIpe2xldCBpPXR8fHt9LG49aS5wcm90b2NvbElkfHxcIk1RVFRcIixvPWkucHJvdG9jb2xWZXJzaW9ufHw0LHM9aS53aWxsLGE9aS5jbGVhbix1PWkua2VlcGFsaXZlfHwwLGM9aS5jbGllbnRJZHx8XCJcIixoPWkudXNlcm5hbWUsZD1pLnBhc3N3b3JkLGc9aS5wcm9wZXJ0aWVzO2E9PT12b2lkIDAmJihhPSEwKTtsZXQgeT0wO2lmKCFufHx0eXBlb2YgbiE9XCJzdHJpbmdcIiYmIXEuaXNCdWZmZXIobikpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIHByb3RvY29sSWRcIikpLCExO2lmKHkrPW4ubGVuZ3RoKzIsbyE9PTMmJm8hPT00JiZvIT09NSlyZXR1cm4gZS5kZXN0cm95KG5ldyBFcnJvcihcIkludmFsaWQgcHJvdG9jb2wgdmVyc2lvblwiKSksITE7aWYoeSs9MSwodHlwZW9mIGM9PVwic3RyaW5nXCJ8fHEuaXNCdWZmZXIoYykpJiYoY3x8bz49NCkmJihjfHxhKSl5Kz1xLmJ5dGVMZW5ndGgoYykrMjtlbHNlIHtpZihvPDQpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJjbGllbnRJZCBtdXN0IGJlIHN1cHBsaWVkIGJlZm9yZSAzLjEuMVwiKSksITE7aWYoYSoxPT09MClyZXR1cm4gZS5kZXN0cm95KG5ldyBFcnJvcihcImNsaWVudElkIG11c3QgYmUgZ2l2ZW4gaWYgY2xlYW5TZXNzaW9uIHNldCB0byAwXCIpKSwhMX1pZih0eXBlb2YgdSE9XCJudW1iZXJcInx8dTwwfHx1PjY1NTM1fHx1JTEhPT0wKXJldHVybiBlLmRlc3Ryb3kobmV3IEVycm9yKFwiSW52YWxpZCBrZWVwYWxpdmVcIikpLCExO3krPTIseSs9MTtsZXQgdyxFO2lmKG89PT01KXtpZih3PUZ0KGUsZyksIXcpcmV0dXJuICExO3krPXcubGVuZ3RoO31pZihzKXtpZih0eXBlb2YgcyE9XCJvYmplY3RcIilyZXR1cm4gZS5kZXN0cm95KG5ldyBFcnJvcihcIkludmFsaWQgd2lsbFwiKSksITE7aWYoIXMudG9waWN8fHR5cGVvZiBzLnRvcGljIT1cInN0cmluZ1wiKXJldHVybiBlLmRlc3Ryb3kobmV3IEVycm9yKFwiSW52YWxpZCB3aWxsIHRvcGljXCIpKSwhMTtpZih5Kz1xLmJ5dGVMZW5ndGgocy50b3BpYykrMix5Kz0yLHMucGF5bG9hZClpZihzLnBheWxvYWQubGVuZ3RoPj0wKXR5cGVvZiBzLnBheWxvYWQ9PVwic3RyaW5nXCI/eSs9cS5ieXRlTGVuZ3RoKHMucGF5bG9hZCk6eSs9cy5wYXlsb2FkLmxlbmd0aDtlbHNlIHJldHVybiBlLmRlc3Ryb3kobmV3IEVycm9yKFwiSW52YWxpZCB3aWxsIHBheWxvYWRcIikpLCExO2lmKEU9e30sbz09PTUpe2lmKEU9RnQoZSxzLnByb3BlcnRpZXMpLCFFKXJldHVybiAhMTt5Kz1FLmxlbmd0aDt9fWxldCBTPSExO2lmKGghPW51bGwpaWYoUGQoaCkpUz0hMCx5Kz1xLmJ5dGVMZW5ndGgoaCkrMjtlbHNlIHJldHVybiBlLmRlc3Ryb3kobmV3IEVycm9yKFwiSW52YWxpZCB1c2VybmFtZVwiKSksITE7aWYoZCE9bnVsbCl7aWYoIVMpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJVc2VybmFtZSBpcyByZXF1aXJlZCB0byB1c2UgcGFzc3dvcmRcIikpLCExO2lmKFBkKGQpKXkrPWtkKGQpKzI7ZWxzZSByZXR1cm4gZS5kZXN0cm95KG5ldyBFcnJvcihcIkludmFsaWQgcGFzc3dvcmRcIikpLCExfWUud3JpdGUoai5DT05ORUNUX0hFQURFUiksRGUoZSx5KSxHcihlLG4pLGkuYnJpZGdlTW9kZSYmKG8rPTEyOCksZS53cml0ZShvPT09MTMxP2ouVkVSU0lPTjEzMTpvPT09MTMyP2ouVkVSU0lPTjEzMjpvPT09ND9qLlZFUlNJT040Om89PT01P2ouVkVSU0lPTjU6ai5WRVJTSU9OMyk7bGV0IEk9MDtyZXR1cm4gSXw9aCE9bnVsbD9qLlVTRVJOQU1FX01BU0s6MCxJfD1kIT1udWxsP2ouUEFTU1dPUkRfTUFTSzowLEl8PXMmJnMucmV0YWluP2ouV0lMTF9SRVRBSU5fTUFTSzowLEl8PXMmJnMucW9zP3MucW9zPDxqLldJTExfUU9TX1NISUZUOjAsSXw9cz9qLldJTExfRkxBR19NQVNLOjAsSXw9YT9qLkNMRUFOX1NFU1NJT05fTUFTSzowLGUud3JpdGUocS5mcm9tKFtJXSkpLEllKGUsdSksbz09PTUmJncud3JpdGUoKSxHcihlLGMpLHMmJihvPT09NSYmRS53cml0ZSgpLHlyKGUscy50b3BpYyksR3IoZSxzLnBheWxvYWQpKSxoIT1udWxsJiZHcihlLGgpLGQhPW51bGwmJkdyKGUsZCksITB9ZnVuY3Rpb24gVm0odCxlLHIpe2xldCBpPXI/ci5wcm90b2NvbFZlcnNpb246NCxuPXR8fHt9LG89aT09PTU/bi5yZWFzb25Db2RlOm4ucmV0dXJuQ29kZSxzPW4ucHJvcGVydGllcyxhPTI7aWYodHlwZW9mIG8hPVwibnVtYmVyXCIpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIHJldHVybiBjb2RlXCIpKSwhMTtsZXQgdT1udWxsO2lmKGk9PT01KXtpZih1PUZ0KGUscyksIXUpcmV0dXJuICExO2ErPXUubGVuZ3RoO31yZXR1cm4gZS53cml0ZShqLkNPTk5BQ0tfSEVBREVSKSxEZShlLGEpLGUud3JpdGUobi5zZXNzaW9uUHJlc2VudD9qLlNFU1NJT05QUkVTRU5UX0hFQURFUjpxbSksZS53cml0ZShxLmZyb20oW29dKSksdT8ud3JpdGUoKSwhMH1mdW5jdGlvbiB6bSh0LGUscil7cWUoXCJwdWJsaXNoOiBwYWNrZXQ6ICVvXCIsdCk7bGV0IGk9cj9yLnByb3RvY29sVmVyc2lvbjo0LG49dHx8e30sbz1uLnFvc3x8MCxzPW4ucmV0YWluP2ouUkVUQUlOX01BU0s6MCxhPW4udG9waWMsdT1uLnBheWxvYWR8fE5tLGM9bi5tZXNzYWdlSWQsaD1uLnByb3BlcnRpZXMsZD0wO2lmKHR5cGVvZiBhPT1cInN0cmluZ1wiKWQrPXEuYnl0ZUxlbmd0aChhKSsyO2Vsc2UgaWYocS5pc0J1ZmZlcihhKSlkKz1hLmxlbmd0aCsyO2Vsc2UgcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIHRvcGljXCIpKSwhMTtpZihxLmlzQnVmZmVyKHUpP2QrPXUubGVuZ3RoOmQrPXEuYnl0ZUxlbmd0aCh1KSxvJiZ0eXBlb2YgYyE9XCJudW1iZXJcIilyZXR1cm4gZS5kZXN0cm95KG5ldyBFcnJvcihcIkludmFsaWQgbWVzc2FnZUlkXCIpKSwhMTtvJiYoZCs9Mik7bGV0IGc9bnVsbDtpZihpPT09NSl7aWYoZz1GdChlLGgpLCFnKXJldHVybiAhMTtkKz1nLmxlbmd0aDt9cmV0dXJuIGUud3JpdGUoai5QVUJMSVNIX0hFQURFUltvXVtuLmR1cD8xOjBdW3M/MTowXSksRGUoZSxkKSxJZShlLGtkKGEpKSxlLndyaXRlKGEpLG8+MCYmSWUoZSxjKSxnPy53cml0ZSgpLHFlKFwicHVibGlzaDogcGF5bG9hZDogJW9cIix1KSxlLndyaXRlKHUpfWZ1bmN0aW9uIEttKHQsZSxyKXtsZXQgaT1yP3IucHJvdG9jb2xWZXJzaW9uOjQsbj10fHx7fSxvPW4uY21kfHxcInB1YmFja1wiLHM9bi5tZXNzYWdlSWQsYT1uLmR1cCYmbz09PVwicHVicmVsXCI/ai5EVVBfTUFTSzowLHU9MCxjPW4ucmVhc29uQ29kZSxoPW4ucHJvcGVydGllcyxkPWk9PT01PzM6MjtpZihvPT09XCJwdWJyZWxcIiYmKHU9MSksdHlwZW9mIHMhPVwibnVtYmVyXCIpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIG1lc3NhZ2VJZFwiKSksITE7bGV0IGc9bnVsbDtpZihpPT09NSYmdHlwZW9mIGg9PVwib2JqZWN0XCIpe2lmKGc9U2koZSxoLHIsZCksIWcpcmV0dXJuICExO2QrPWcubGVuZ3RoO31yZXR1cm4gZS53cml0ZShqLkFDS1Nbb11bdV1bYV1bMF0pLGQ9PT0zJiYoZCs9YyE9PTA/MTotMSksRGUoZSxkKSxJZShlLHMpLGk9PT01JiZkIT09MiYmZS53cml0ZShxLmZyb20oW2NdKSksZyE9PW51bGw/Zy53cml0ZSgpOmQ9PT00JiZlLndyaXRlKHEuZnJvbShbMF0pKSwhMH1mdW5jdGlvbiBHbSh0LGUscil7cWUoXCJzdWJzY3JpYmU6IHBhY2tldDogXCIpO2xldCBpPXI/ci5wcm90b2NvbFZlcnNpb246NCxuPXR8fHt9LG89bi5kdXA/ai5EVVBfTUFTSzowLHM9bi5tZXNzYWdlSWQsYT1uLnN1YnNjcmlwdGlvbnMsdT1uLnByb3BlcnRpZXMsYz0wO2lmKHR5cGVvZiBzIT1cIm51bWJlclwiKXJldHVybiBlLmRlc3Ryb3kobmV3IEVycm9yKFwiSW52YWxpZCBtZXNzYWdlSWRcIikpLCExO2MrPTI7bGV0IGg9bnVsbDtpZihpPT09NSl7aWYoaD1GdChlLHUpLCFoKXJldHVybiAhMTtjKz1oLmxlbmd0aDt9aWYodHlwZW9mIGE9PVwib2JqZWN0XCImJmEubGVuZ3RoKWZvcihsZXQgZz0wO2c8YS5sZW5ndGg7Zys9MSl7bGV0IHk9YVtnXS50b3BpYyx3PWFbZ10ucW9zO2lmKHR5cGVvZiB5IT1cInN0cmluZ1wiKXJldHVybiBlLmRlc3Ryb3kobmV3IEVycm9yKFwiSW52YWxpZCBzdWJzY3JpcHRpb25zIC0gaW52YWxpZCB0b3BpY1wiKSksITE7aWYodHlwZW9mIHchPVwibnVtYmVyXCIpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIHN1YnNjcmlwdGlvbnMgLSBpbnZhbGlkIHFvc1wiKSksITE7aWYoaT09PTUpe2lmKHR5cGVvZihhW2ddLm5sfHwhMSkhPVwiYm9vbGVhblwiKXJldHVybiBlLmRlc3Ryb3kobmV3IEVycm9yKFwiSW52YWxpZCBzdWJzY3JpcHRpb25zIC0gaW52YWxpZCBObyBMb2NhbFwiKSksITE7aWYodHlwZW9mKGFbZ10ucmFwfHwhMSkhPVwiYm9vbGVhblwiKXJldHVybiBlLmRlc3Ryb3kobmV3IEVycm9yKFwiSW52YWxpZCBzdWJzY3JpcHRpb25zIC0gaW52YWxpZCBSZXRhaW4gYXMgUHVibGlzaGVkXCIpKSwhMTtsZXQgST1hW2ddLnJofHwwO2lmKHR5cGVvZiBJIT1cIm51bWJlclwifHxJPjIpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIHN1YnNjcmlwdGlvbnMgLSBpbnZhbGlkIFJldGFpbiBIYW5kbGluZ1wiKSksITF9Yys9cS5ieXRlTGVuZ3RoKHkpKzIrMTt9ZWxzZSByZXR1cm4gZS5kZXN0cm95KG5ldyBFcnJvcihcIkludmFsaWQgc3Vic2NyaXB0aW9uc1wiKSksITE7cWUoXCJzdWJzY3JpYmU6IHdyaXRpbmcgdG8gc3RyZWFtOiAlb1wiLGouU1VCU0NSSUJFX0hFQURFUiksZS53cml0ZShqLlNVQlNDUklCRV9IRUFERVJbMV1bbz8xOjBdWzBdKSxEZShlLGMpLEllKGUscyksaCE9PW51bGwmJmgud3JpdGUoKTtsZXQgZD0hMDtmb3IobGV0IGcgb2YgYSl7bGV0IHk9Zy50b3BpYyx3PWcucW9zLEU9K2cubmwsUz0rZy5yYXAsST1nLnJoLEM7eXIoZSx5KSxDPWouU1VCU0NSSUJFX09QVElPTlNfUU9TW3ddLGk9PT01JiYoQ3w9RT9qLlNVQlNDUklCRV9PUFRJT05TX05MOjAsQ3w9Uz9qLlNVQlNDUklCRV9PUFRJT05TX1JBUDowLEN8PUk/ai5TVUJTQ1JJQkVfT1BUSU9OU19SSFtJXTowKSxkPWUud3JpdGUocS5mcm9tKFtDXSkpO31yZXR1cm4gZH1mdW5jdGlvbiBRbSh0LGUscil7bGV0IGk9cj9yLnByb3RvY29sVmVyc2lvbjo0LG49dHx8e30sbz1uLm1lc3NhZ2VJZCxzPW4uZ3JhbnRlZCxhPW4ucHJvcGVydGllcyx1PTA7aWYodHlwZW9mIG8hPVwibnVtYmVyXCIpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIG1lc3NhZ2VJZFwiKSksITE7aWYodSs9Mix0eXBlb2Ygcz09XCJvYmplY3RcIiYmcy5sZW5ndGgpZm9yKGxldCBoPTA7aDxzLmxlbmd0aDtoKz0xKXtpZih0eXBlb2Ygc1toXSE9XCJudW1iZXJcIilyZXR1cm4gZS5kZXN0cm95KG5ldyBFcnJvcihcIkludmFsaWQgcW9zIHZlY3RvclwiKSksITE7dSs9MTt9ZWxzZSByZXR1cm4gZS5kZXN0cm95KG5ldyBFcnJvcihcIkludmFsaWQgcW9zIHZlY3RvclwiKSksITE7bGV0IGM9bnVsbDtpZihpPT09NSl7aWYoYz1TaShlLGEscix1KSwhYylyZXR1cm4gITE7dSs9Yy5sZW5ndGg7fXJldHVybiBlLndyaXRlKGouU1VCQUNLX0hFQURFUiksRGUoZSx1KSxJZShlLG8pLGMhPT1udWxsJiZjLndyaXRlKCksZS53cml0ZShxLmZyb20ocykpfWZ1bmN0aW9uIFltKHQsZSxyKXtsZXQgaT1yP3IucHJvdG9jb2xWZXJzaW9uOjQsbj10fHx7fSxvPW4ubWVzc2FnZUlkLHM9bi5kdXA/ai5EVVBfTUFTSzowLGE9bi51bnN1YnNjcmlwdGlvbnMsdT1uLnByb3BlcnRpZXMsYz0wO2lmKHR5cGVvZiBvIT1cIm51bWJlclwiKXJldHVybiBlLmRlc3Ryb3kobmV3IEVycm9yKFwiSW52YWxpZCBtZXNzYWdlSWRcIikpLCExO2lmKGMrPTIsdHlwZW9mIGE9PVwib2JqZWN0XCImJmEubGVuZ3RoKWZvcihsZXQgZz0wO2c8YS5sZW5ndGg7Zys9MSl7aWYodHlwZW9mIGFbZ10hPVwic3RyaW5nXCIpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIHVuc3Vic2NyaXB0aW9uc1wiKSksITE7Yys9cS5ieXRlTGVuZ3RoKGFbZ10pKzI7fWVsc2UgcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIHVuc3Vic2NyaXB0aW9uc1wiKSksITE7bGV0IGg9bnVsbDtpZihpPT09NSl7aWYoaD1GdChlLHUpLCFoKXJldHVybiAhMTtjKz1oLmxlbmd0aDt9ZS53cml0ZShqLlVOU1VCU0NSSUJFX0hFQURFUlsxXVtzPzE6MF1bMF0pLERlKGUsYyksSWUoZSxvKSxoIT09bnVsbCYmaC53cml0ZSgpO2xldCBkPSEwO2ZvcihsZXQgZz0wO2c8YS5sZW5ndGg7ZysrKWQ9eXIoZSxhW2ddKTtyZXR1cm4gZH1mdW5jdGlvbiBKbSh0LGUscil7bGV0IGk9cj9yLnByb3RvY29sVmVyc2lvbjo0LG49dHx8e30sbz1uLm1lc3NhZ2VJZCxzPW4uZHVwP2ouRFVQX01BU0s6MCxhPW4uZ3JhbnRlZCx1PW4ucHJvcGVydGllcyxjPW4uY21kLGg9MCxkPTI7aWYodHlwZW9mIG8hPVwibnVtYmVyXCIpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIG1lc3NhZ2VJZFwiKSksITE7aWYoaT09PTUpaWYodHlwZW9mIGE9PVwib2JqZWN0XCImJmEubGVuZ3RoKWZvcihsZXQgeT0wO3k8YS5sZW5ndGg7eSs9MSl7aWYodHlwZW9mIGFbeV0hPVwibnVtYmVyXCIpcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIHFvcyB2ZWN0b3JcIikpLCExO2QrPTE7fWVsc2UgcmV0dXJuIGUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIHFvcyB2ZWN0b3JcIikpLCExO2xldCBnPW51bGw7aWYoaT09PTUpe2lmKGc9U2koZSx1LHIsZCksIWcpcmV0dXJuICExO2QrPWcubGVuZ3RoO31yZXR1cm4gZS53cml0ZShqLkFDS1NbY11baF1bc11bMF0pLERlKGUsZCksSWUoZSxvKSxnIT09bnVsbCYmZy53cml0ZSgpLGk9PT01JiZlLndyaXRlKHEuZnJvbShhKSksITB9ZnVuY3Rpb24gWG0odCxlLHIpe3JldHVybiBlLndyaXRlKGouRU1QVFlbdC5jbWRdKX1mdW5jdGlvbiBabSh0LGUscil7bGV0IGk9cj9yLnByb3RvY29sVmVyc2lvbjo0LG49dHx8e30sbz1uLnJlYXNvbkNvZGUscz1uLnByb3BlcnRpZXMsYT1pPT09NT8xOjAsdT1udWxsO2lmKGk9PT01KXtpZih1PVNpKGUscyxyLGEpLCF1KXJldHVybiAhMTthKz11Lmxlbmd0aDt9cmV0dXJuIGUud3JpdGUocS5mcm9tKFtqLmNvZGVzLmRpc2Nvbm5lY3Q8PDRdKSksRGUoZSxhKSxpPT09NSYmZS53cml0ZShxLmZyb20oW29dKSksdSE9PW51bGwmJnUud3JpdGUoKSwhMH1mdW5jdGlvbiBlMSh0LGUscil7bGV0IGk9cj9yLnByb3RvY29sVmVyc2lvbjo0LG49dHx8e30sbz1uLnJlYXNvbkNvZGUscz1uLnByb3BlcnRpZXMsYT1pPT09NT8xOjA7aSE9PTUmJmUuZGVzdHJveShuZXcgRXJyb3IoXCJJbnZhbGlkIG1xdHQgdmVyc2lvbiBmb3IgYXV0aCBwYWNrZXRcIikpO2xldCB1PVNpKGUscyxyLGEpO3JldHVybiB1PyhhKz11Lmxlbmd0aCxlLndyaXRlKHEuZnJvbShbai5jb2Rlcy5hdXRoPDw0XSkpLERlKGUsYSksZS53cml0ZShxLmZyb20oW29dKSksdSE9PW51bGwmJnUud3JpdGUoKSwhMCk6ITF9dmFyIFRkPXt9O2Z1bmN0aW9uIERlKHQsZSl7aWYoZT5qLlZBUkJZVEVJTlRfTUFYKXJldHVybiB0LmRlc3Ryb3kobmV3IEVycm9yKGBJbnZhbGlkIHZhcmlhYmxlIGJ5dGUgaW50ZWdlcjogJHtlfWApKSwhMTtsZXQgcj1UZFtlXTtyZXR1cm4gcnx8KHI9SG8oZSksZTwxNjM4NCYmKFRkW2VdPXIpKSxxZShcIndyaXRlVmFyQnl0ZUludDogd3JpdGluZyB0byBzdHJlYW06ICVvXCIsciksdC53cml0ZShyKX1mdW5jdGlvbiB5cih0LGUpe2xldCByPXEuYnl0ZUxlbmd0aChlKTtyZXR1cm4gSWUodCxyKSxxZShcIndyaXRlU3RyaW5nOiAlc1wiLGUpLHQud3JpdGUoZSxcInV0ZjhcIil9ZnVuY3Rpb24gUmQodCxlLHIpe3lyKHQsZSkseXIodCxyKTt9ZnVuY3Rpb24gVm8odCxlKXtyZXR1cm4gcWUoXCJ3cml0ZU51bWJlckNhY2hlZDogbnVtYmVyOiAlZFwiLGUpLHFlKFwid3JpdGVOdW1iZXJDYWNoZWQ6ICVvXCIsQ25bZV0pLHQud3JpdGUoQ25bZV0pfWZ1bmN0aW9uIHQxKHQsZSl7bGV0IHI9am0oZSk7cmV0dXJuIHFlKFwid3JpdGVOdW1iZXJHZW5lcmF0ZWQ6ICVvXCIsciksdC53cml0ZShyKX1mdW5jdGlvbiByMSh0LGUpe2xldCByPVdtKGUpO3JldHVybiBxZShcIndyaXRlNEJ5dGVOdW1iZXI6ICVvXCIsciksdC53cml0ZShyKX1mdW5jdGlvbiBHcih0LGUpe3R5cGVvZiBlPT1cInN0cmluZ1wiP3lyKHQsZSk6ZT8oSWUodCxlLmxlbmd0aCksdC53cml0ZShlKSk6SWUodCwwKTt9ZnVuY3Rpb24gRnQodCxlKXtpZih0eXBlb2YgZSE9XCJvYmplY3RcInx8ZS5sZW5ndGghPW51bGwpcmV0dXJuIHtsZW5ndGg6MSx3cml0ZSgpe0JkKHQse30sMCk7fX07bGV0IHI9MDtmdW5jdGlvbiBpKG8scyl7bGV0IGE9ai5wcm9wZXJ0aWVzVHlwZXNbb10sdT0wO3N3aXRjaChhKXtjYXNlXCJieXRlXCI6e2lmKHR5cGVvZiBzIT1cImJvb2xlYW5cIilyZXR1cm4gdC5kZXN0cm95KG5ldyBFcnJvcihgSW52YWxpZCAke299OiAke3N9YCkpLCExO3UrPTErMTticmVha31jYXNlXCJpbnQ4XCI6e2lmKHR5cGVvZiBzIT1cIm51bWJlclwifHxzPDB8fHM+MjU1KXJldHVybiB0LmRlc3Ryb3kobmV3IEVycm9yKGBJbnZhbGlkICR7b306ICR7c31gKSksITE7dSs9MSsxO2JyZWFrfWNhc2VcImJpbmFyeVwiOntpZihzJiZzPT09bnVsbClyZXR1cm4gdC5kZXN0cm95KG5ldyBFcnJvcihgSW52YWxpZCAke299OiAke3N9YCkpLCExO3UrPTErcS5ieXRlTGVuZ3RoKHMpKzI7YnJlYWt9Y2FzZVwiaW50MTZcIjp7aWYodHlwZW9mIHMhPVwibnVtYmVyXCJ8fHM8MHx8cz42NTUzNSlyZXR1cm4gdC5kZXN0cm95KG5ldyBFcnJvcihgSW52YWxpZCAke299OiAke3N9YCkpLCExO3UrPTErMjticmVha31jYXNlXCJpbnQzMlwiOntpZih0eXBlb2YgcyE9XCJudW1iZXJcInx8czwwfHxzPjQyOTQ5NjcyOTUpcmV0dXJuIHQuZGVzdHJveShuZXcgRXJyb3IoYEludmFsaWQgJHtvfTogJHtzfWApKSwhMTt1Kz0xKzQ7YnJlYWt9Y2FzZVwidmFyXCI6e2lmKHR5cGVvZiBzIT1cIm51bWJlclwifHxzPDB8fHM+MjY4NDM1NDU1KXJldHVybiB0LmRlc3Ryb3kobmV3IEVycm9yKGBJbnZhbGlkICR7b306ICR7c31gKSksITE7dSs9MStxLmJ5dGVMZW5ndGgoSG8ocykpO2JyZWFrfWNhc2VcInN0cmluZ1wiOntpZih0eXBlb2YgcyE9XCJzdHJpbmdcIilyZXR1cm4gdC5kZXN0cm95KG5ldyBFcnJvcihgSW52YWxpZCAke299OiAke3N9YCkpLCExO3UrPTErMitxLmJ5dGVMZW5ndGgocy50b1N0cmluZygpKTticmVha31jYXNlXCJwYWlyXCI6e2lmKHR5cGVvZiBzIT1cIm9iamVjdFwiKXJldHVybiB0LmRlc3Ryb3kobmV3IEVycm9yKGBJbnZhbGlkICR7b306ICR7c31gKSksITE7dSs9T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMocykucmVkdWNlKChjLGgpPT57bGV0IGQ9c1toXTtyZXR1cm4gQXJyYXkuaXNBcnJheShkKT9jKz1kLnJlZHVjZSgoZyx5KT0+KGcrPTErMitxLmJ5dGVMZW5ndGgoaC50b1N0cmluZygpKSsyK3EuYnl0ZUxlbmd0aCh5LnRvU3RyaW5nKCkpLGcpLDApOmMrPTErMitxLmJ5dGVMZW5ndGgoaC50b1N0cmluZygpKSsyK3EuYnl0ZUxlbmd0aChzW2hdLnRvU3RyaW5nKCkpLGN9LDApO2JyZWFrfWRlZmF1bHQ6cmV0dXJuIHQuZGVzdHJveShuZXcgRXJyb3IoYEludmFsaWQgcHJvcGVydHkgJHtvfTogJHtzfWApKSwhMX1yZXR1cm4gdX1pZihlKWZvcihsZXQgbyBpbiBlKXtsZXQgcz0wLGE9MCx1PWVbb107aWYoQXJyYXkuaXNBcnJheSh1KSlmb3IobGV0IGM9MDtjPHUubGVuZ3RoO2MrKyl7aWYoYT1pKG8sdVtjXSksIWEpcmV0dXJuICExO3MrPWE7fWVsc2Uge2lmKGE9aShvLHUpLCFhKXJldHVybiAhMTtzPWE7fWlmKCFzKXJldHVybiAhMTtyKz1zO31yZXR1cm4ge2xlbmd0aDpxLmJ5dGVMZW5ndGgoSG8ocikpK3Isd3JpdGUoKXtCZCh0LGUscik7fX19ZnVuY3Rpb24gU2kodCxlLHIsaSl7bGV0IG49W1wicmVhc29uU3RyaW5nXCIsXCJ1c2VyUHJvcGVydGllc1wiXSxvPXImJnIucHJvcGVydGllcyYmci5wcm9wZXJ0aWVzLm1heGltdW1QYWNrZXRTaXplP3IucHJvcGVydGllcy5tYXhpbXVtUGFja2V0U2l6ZTowLHM9RnQodCxlKTtpZihvKWZvcig7aStzLmxlbmd0aD5vOyl7bGV0IGE9bi5zaGlmdCgpO2lmKGEmJmVbYV0pZGVsZXRlIGVbYV0scz1GdCh0LGUpO2Vsc2UgcmV0dXJuICExfXJldHVybiBzfWZ1bmN0aW9uIENkKHQsZSxyKXtzd2l0Y2goai5wcm9wZXJ0aWVzVHlwZXNbZV0pe2Nhc2VcImJ5dGVcIjp7dC53cml0ZShxLmZyb20oW2oucHJvcGVydGllc1tlXV0pKSx0LndyaXRlKHEuZnJvbShbK3JdKSk7YnJlYWt9Y2FzZVwiaW50OFwiOnt0LndyaXRlKHEuZnJvbShbai5wcm9wZXJ0aWVzW2VdXSkpLHQud3JpdGUocS5mcm9tKFtyXSkpO2JyZWFrfWNhc2VcImJpbmFyeVwiOnt0LndyaXRlKHEuZnJvbShbai5wcm9wZXJ0aWVzW2VdXSkpLEdyKHQscik7YnJlYWt9Y2FzZVwiaW50MTZcIjp7dC53cml0ZShxLmZyb20oW2oucHJvcGVydGllc1tlXV0pKSxJZSh0LHIpO2JyZWFrfWNhc2VcImludDMyXCI6e3Qud3JpdGUocS5mcm9tKFtqLnByb3BlcnRpZXNbZV1dKSkscjEodCxyKTticmVha31jYXNlXCJ2YXJcIjp7dC53cml0ZShxLmZyb20oW2oucHJvcGVydGllc1tlXV0pKSxEZSh0LHIpO2JyZWFrfWNhc2VcInN0cmluZ1wiOnt0LndyaXRlKHEuZnJvbShbai5wcm9wZXJ0aWVzW2VdXSkpLHlyKHQscik7YnJlYWt9Y2FzZVwicGFpclwiOntPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhyKS5mb3JFYWNoKG49PntsZXQgbz1yW25dO0FycmF5LmlzQXJyYXkobyk/by5mb3JFYWNoKHM9Pnt0LndyaXRlKHEuZnJvbShbai5wcm9wZXJ0aWVzW2VdXSkpLFJkKHQsbi50b1N0cmluZygpLHMudG9TdHJpbmcoKSk7fSk6KHQud3JpdGUocS5mcm9tKFtqLnByb3BlcnRpZXNbZV1dKSksUmQodCxuLnRvU3RyaW5nKCksby50b1N0cmluZygpKSk7fSk7YnJlYWt9ZGVmYXVsdDpyZXR1cm4gdC5kZXN0cm95KG5ldyBFcnJvcihgSW52YWxpZCBwcm9wZXJ0eSAke2V9IHZhbHVlOiAke3J9YCkpLCExfX1mdW5jdGlvbiBCZCh0LGUscil7RGUodCxyKTtmb3IobGV0IGkgaW4gZSlpZihPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZSxpKSYmZVtpXSE9PW51bGwpe2xldCBuPWVbaV07aWYoQXJyYXkuaXNBcnJheShuKSlmb3IobGV0IG89MDtvPG4ubGVuZ3RoO28rKylDZCh0LGksbltvXSk7ZWxzZSBDZCh0LGksbik7fX1mdW5jdGlvbiBrZCh0KXtyZXR1cm4gdD90IGluc3RhbmNlb2YgcT90Lmxlbmd0aDpxLmJ5dGVMZW5ndGgodCk6MH1mdW5jdGlvbiBQZCh0KXtyZXR1cm4gdHlwZW9mIHQ9PVwic3RyaW5nXCJ8fHQgaW5zdGFuY2VvZiBxfXhkLmV4cG9ydHM9T2Q7fSk7dmFyIFVkPU0oKG1PLExkKT0+e3YoKTttKCk7XygpO3ZhciBpMT16bygpLHtFdmVudEVtaXR0ZXI6bjF9PShpcigpLFgocnIpKSx7QnVmZmVyOk1kfT0oeWUoKSxYKF9lKSk7ZnVuY3Rpb24gczEodCxlKXtsZXQgcj1uZXcgS287cmV0dXJuIGkxKHQscixlKSxyLmNvbmNhdCgpfXZhciBLbz1jbGFzcyBleHRlbmRzIG4xe2NvbnN0cnVjdG9yKCl7c3VwZXIoKSx0aGlzLl9hcnJheT1uZXcgQXJyYXkoMjApLHRoaXMuX2k9MDt9d3JpdGUoZSl7cmV0dXJuIHRoaXMuX2FycmF5W3RoaXMuX2krK109ZSwhMH1jb25jYXQoKXtsZXQgZT0wLHI9bmV3IEFycmF5KHRoaXMuX2FycmF5Lmxlbmd0aCksaT10aGlzLl9hcnJheSxuPTAsbztmb3Iobz0wO288aS5sZW5ndGgmJmlbb10hPT12b2lkIDA7bysrKXR5cGVvZiBpW29dIT1cInN0cmluZ1wiP3Jbb109aVtvXS5sZW5ndGg6cltvXT1NZC5ieXRlTGVuZ3RoKGlbb10pLGUrPXJbb107bGV0IHM9TWQuYWxsb2NVbnNhZmUoZSk7Zm9yKG89MDtvPGkubGVuZ3RoJiZpW29dIT09dm9pZCAwO28rKyl0eXBlb2YgaVtvXSE9XCJzdHJpbmdcIj8oaVtvXS5jb3B5KHMsbiksbis9cltvXSk6KHMud3JpdGUoaVtvXSxuKSxuKz1yW29dKTtyZXR1cm4gc31kZXN0cm95KGUpe2UmJnRoaXMuZW1pdChcImVycm9yXCIsZSk7fX07TGQuZXhwb3J0cz1zMTt9KTt2YXIgTmQ9TShQbj0+e3YoKTttKCk7XygpO1BuLnBhcnNlcj1tZCgpLnBhcnNlcjtQbi5nZW5lcmF0ZT1VZCgpO1BuLndyaXRlVG9TdHJlYW09em8oKTt9KTt2YXIgWW89TShRbz0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShRbyxcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTt2YXIgR289Y2xhc3N7Y29uc3RydWN0b3IoKXt0aGlzLm5leHRJZD1NYXRoLm1heCgxLE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSo2NTUzNSkpO31hbGxvY2F0ZSgpe2xldCBlPXRoaXMubmV4dElkKys7cmV0dXJuIHRoaXMubmV4dElkPT09NjU1MzYmJih0aGlzLm5leHRJZD0xKSxlfWdldExhc3RBbGxvY2F0ZWQoKXtyZXR1cm4gdGhpcy5uZXh0SWQ9PT0xPzY1NTM1OnRoaXMubmV4dElkLTF9cmVnaXN0ZXIoZSl7cmV0dXJuICEwfWRlYWxsb2NhdGUoZSl7fWNsZWFyKCl7fX07UW8uZGVmYXVsdD1Hbzt9KTt2YXIgRGQ9TSgoWU8scWQpPT57digpO20oKTtfKCk7cWQuZXhwb3J0cz1vMTtmdW5jdGlvbiBRcih0KXtyZXR1cm4gdCBpbnN0YW5jZW9mIHg/eC5mcm9tKHQpOm5ldyB0LmNvbnN0cnVjdG9yKHQuYnVmZmVyLnNsaWNlKCksdC5ieXRlT2Zmc2V0LHQubGVuZ3RoKX1mdW5jdGlvbiBvMSh0KXtpZih0PXR8fHt9LHQuY2lyY2xlcylyZXR1cm4gYTEodCk7cmV0dXJuIHQucHJvdG8/aTpyO2Z1bmN0aW9uIGUobixvKXtmb3IodmFyIHM9T2JqZWN0LmtleXMobiksYT1uZXcgQXJyYXkocy5sZW5ndGgpLHU9MDt1PHMubGVuZ3RoO3UrKyl7dmFyIGM9c1t1XSxoPW5bY107dHlwZW9mIGghPVwib2JqZWN0XCJ8fGg9PT1udWxsP2FbY109aDpoIGluc3RhbmNlb2YgRGF0ZT9hW2NdPW5ldyBEYXRlKGgpOkFycmF5QnVmZmVyLmlzVmlldyhoKT9hW2NdPVFyKGgpOmFbY109byhoKTt9cmV0dXJuIGF9ZnVuY3Rpb24gcihuKXtpZih0eXBlb2YgbiE9XCJvYmplY3RcInx8bj09PW51bGwpcmV0dXJuIG47aWYobiBpbnN0YW5jZW9mIERhdGUpcmV0dXJuIG5ldyBEYXRlKG4pO2lmKEFycmF5LmlzQXJyYXkobikpcmV0dXJuIGUobixyKTtpZihuIGluc3RhbmNlb2YgTWFwKXJldHVybiBuZXcgTWFwKGUoQXJyYXkuZnJvbShuKSxyKSk7aWYobiBpbnN0YW5jZW9mIFNldClyZXR1cm4gbmV3IFNldChlKEFycmF5LmZyb20obikscikpO3ZhciBvPXt9O2Zvcih2YXIgcyBpbiBuKWlmKE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKG4scykhPT0hMSl7dmFyIGE9bltzXTt0eXBlb2YgYSE9XCJvYmplY3RcInx8YT09PW51bGw/b1tzXT1hOmEgaW5zdGFuY2VvZiBEYXRlP29bc109bmV3IERhdGUoYSk6YSBpbnN0YW5jZW9mIE1hcD9vW3NdPW5ldyBNYXAoZShBcnJheS5mcm9tKGEpLHIpKTphIGluc3RhbmNlb2YgU2V0P29bc109bmV3IFNldChlKEFycmF5LmZyb20oYSkscikpOkFycmF5QnVmZmVyLmlzVmlldyhhKT9vW3NdPVFyKGEpOm9bc109cihhKTt9cmV0dXJuIG99ZnVuY3Rpb24gaShuKXtpZih0eXBlb2YgbiE9XCJvYmplY3RcInx8bj09PW51bGwpcmV0dXJuIG47aWYobiBpbnN0YW5jZW9mIERhdGUpcmV0dXJuIG5ldyBEYXRlKG4pO2lmKEFycmF5LmlzQXJyYXkobikpcmV0dXJuIGUobixpKTtpZihuIGluc3RhbmNlb2YgTWFwKXJldHVybiBuZXcgTWFwKGUoQXJyYXkuZnJvbShuKSxpKSk7aWYobiBpbnN0YW5jZW9mIFNldClyZXR1cm4gbmV3IFNldChlKEFycmF5LmZyb20obiksaSkpO3ZhciBvPXt9O2Zvcih2YXIgcyBpbiBuKXt2YXIgYT1uW3NdO3R5cGVvZiBhIT1cIm9iamVjdFwifHxhPT09bnVsbD9vW3NdPWE6YSBpbnN0YW5jZW9mIERhdGU/b1tzXT1uZXcgRGF0ZShhKTphIGluc3RhbmNlb2YgTWFwP29bc109bmV3IE1hcChlKEFycmF5LmZyb20oYSksaSkpOmEgaW5zdGFuY2VvZiBTZXQ/b1tzXT1uZXcgU2V0KGUoQXJyYXkuZnJvbShhKSxpKSk6QXJyYXlCdWZmZXIuaXNWaWV3KGEpP29bc109UXIoYSk6b1tzXT1pKGEpO31yZXR1cm4gb319ZnVuY3Rpb24gYTEodCl7dmFyIGU9W10scj1bXTtyZXR1cm4gdC5wcm90bz9vOm47ZnVuY3Rpb24gaShzLGEpe2Zvcih2YXIgdT1PYmplY3Qua2V5cyhzKSxjPW5ldyBBcnJheSh1Lmxlbmd0aCksaD0wO2g8dS5sZW5ndGg7aCsrKXt2YXIgZD11W2hdLGc9c1tkXTtpZih0eXBlb2YgZyE9XCJvYmplY3RcInx8Zz09PW51bGwpY1tkXT1nO2Vsc2UgaWYoZyBpbnN0YW5jZW9mIERhdGUpY1tkXT1uZXcgRGF0ZShnKTtlbHNlIGlmKEFycmF5QnVmZmVyLmlzVmlldyhnKSljW2RdPVFyKGcpO2Vsc2Uge3ZhciB5PWUuaW5kZXhPZihnKTt5IT09LTE/Y1tkXT1yW3ldOmNbZF09YShnKTt9fXJldHVybiBjfWZ1bmN0aW9uIG4ocyl7aWYodHlwZW9mIHMhPVwib2JqZWN0XCJ8fHM9PT1udWxsKXJldHVybiBzO2lmKHMgaW5zdGFuY2VvZiBEYXRlKXJldHVybiBuZXcgRGF0ZShzKTtpZihBcnJheS5pc0FycmF5KHMpKXJldHVybiBpKHMsbik7aWYocyBpbnN0YW5jZW9mIE1hcClyZXR1cm4gbmV3IE1hcChpKEFycmF5LmZyb20ocyksbikpO2lmKHMgaW5zdGFuY2VvZiBTZXQpcmV0dXJuIG5ldyBTZXQoaShBcnJheS5mcm9tKHMpLG4pKTt2YXIgYT17fTtlLnB1c2gocyksci5wdXNoKGEpO2Zvcih2YXIgdSBpbiBzKWlmKE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsdSkhPT0hMSl7dmFyIGM9c1t1XTtpZih0eXBlb2YgYyE9XCJvYmplY3RcInx8Yz09PW51bGwpYVt1XT1jO2Vsc2UgaWYoYyBpbnN0YW5jZW9mIERhdGUpYVt1XT1uZXcgRGF0ZShjKTtlbHNlIGlmKGMgaW5zdGFuY2VvZiBNYXApYVt1XT1uZXcgTWFwKGkoQXJyYXkuZnJvbShjKSxuKSk7ZWxzZSBpZihjIGluc3RhbmNlb2YgU2V0KWFbdV09bmV3IFNldChpKEFycmF5LmZyb20oYyksbikpO2Vsc2UgaWYoQXJyYXlCdWZmZXIuaXNWaWV3KGMpKWFbdV09UXIoYyk7ZWxzZSB7dmFyIGg9ZS5pbmRleE9mKGMpO2ghPT0tMT9hW3VdPXJbaF06YVt1XT1uKGMpO319cmV0dXJuIGUucG9wKCksci5wb3AoKSxhfWZ1bmN0aW9uIG8ocyl7aWYodHlwZW9mIHMhPVwib2JqZWN0XCJ8fHM9PT1udWxsKXJldHVybiBzO2lmKHMgaW5zdGFuY2VvZiBEYXRlKXJldHVybiBuZXcgRGF0ZShzKTtpZihBcnJheS5pc0FycmF5KHMpKXJldHVybiBpKHMsbyk7aWYocyBpbnN0YW5jZW9mIE1hcClyZXR1cm4gbmV3IE1hcChpKEFycmF5LmZyb20ocyksbykpO2lmKHMgaW5zdGFuY2VvZiBTZXQpcmV0dXJuIG5ldyBTZXQoaShBcnJheS5mcm9tKHMpLG8pKTt2YXIgYT17fTtlLnB1c2gocyksci5wdXNoKGEpO2Zvcih2YXIgdSBpbiBzKXt2YXIgYz1zW3VdO2lmKHR5cGVvZiBjIT1cIm9iamVjdFwifHxjPT09bnVsbClhW3VdPWM7ZWxzZSBpZihjIGluc3RhbmNlb2YgRGF0ZSlhW3VdPW5ldyBEYXRlKGMpO2Vsc2UgaWYoYyBpbnN0YW5jZW9mIE1hcClhW3VdPW5ldyBNYXAoaShBcnJheS5mcm9tKGMpLG8pKTtlbHNlIGlmKGMgaW5zdGFuY2VvZiBTZXQpYVt1XT1uZXcgU2V0KGkoQXJyYXkuZnJvbShjKSxvKSk7ZWxzZSBpZihBcnJheUJ1ZmZlci5pc1ZpZXcoYykpYVt1XT1RcihjKTtlbHNlIHt2YXIgaD1lLmluZGV4T2YoYyk7aCE9PS0xP2FbdV09cltoXTphW3VdPW8oYyk7fX1yZXR1cm4gZS5wb3AoKSxyLnBvcCgpLGF9fX0pO3ZhciBGZD1NKChvayxqZCk9Pnt2KCk7bSgpO18oKTtqZC5leHBvcnRzPURkKCkoKTt9KTt2YXIgJGQ9TShZcj0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShZcixcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTtZci52YWxpZGF0ZVRvcGljcz1Zci52YWxpZGF0ZVRvcGljPXZvaWQgMDtmdW5jdGlvbiBXZCh0KXtsZXQgZT10LnNwbGl0KFwiL1wiKTtmb3IobGV0IHI9MDtyPGUubGVuZ3RoO3IrKylpZihlW3JdIT09XCIrXCIpe2lmKGVbcl09PT1cIiNcIilyZXR1cm4gcj09PWUubGVuZ3RoLTE7aWYoZVtyXS5pbmRleE9mKFwiK1wiKSE9PS0xfHxlW3JdLmluZGV4T2YoXCIjXCIpIT09LTEpcmV0dXJuICExfXJldHVybiAhMH1Zci52YWxpZGF0ZVRvcGljPVdkO2Z1bmN0aW9uIGwxKHQpe2lmKHQubGVuZ3RoPT09MClyZXR1cm4gXCJlbXB0eV90b3BpY19saXN0XCI7Zm9yKGxldCBlPTA7ZTx0Lmxlbmd0aDtlKyspaWYoIVdkKHRbZV0pKXJldHVybiB0W2VdO3JldHVybiBudWxsfVlyLnZhbGlkYXRlVG9waWNzPWwxO30pO3ZhciBabz1NKFhvPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KFhvLFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO3ZhciB1MT1EdCgpLGYxPXtvYmplY3RNb2RlOiEwfSxjMT17Y2xlYW46ITB9LEpvPWNsYXNze2NvbnN0cnVjdG9yKGUpe3RoaXMub3B0aW9ucz1lfHx7fSx0aGlzLm9wdGlvbnM9T2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGMxKSxlKSx0aGlzLl9pbmZsaWdodHM9bmV3IE1hcDt9cHV0KGUscil7cmV0dXJuIHRoaXMuX2luZmxpZ2h0cy5zZXQoZS5tZXNzYWdlSWQsZSksciYmcigpLHRoaXN9Y3JlYXRlU3RyZWFtKCl7bGV0IGU9bmV3IHUxLlJlYWRhYmxlKGYxKSxyPVtdLGk9ITEsbj0wO3JldHVybiB0aGlzLl9pbmZsaWdodHMuZm9yRWFjaCgobyxzKT0+e3IucHVzaChvKTt9KSxlLl9yZWFkPSgpPT57IWkmJm48ci5sZW5ndGg/ZS5wdXNoKHJbbisrXSk6ZS5wdXNoKG51bGwpO30sZS5kZXN0cm95PW89PntpZighaSlyZXR1cm4gaT0hMCxzZXRUaW1lb3V0KCgpPT57ZS5lbWl0KFwiY2xvc2VcIik7fSwwKSxlfSxlfWRlbChlLHIpe2xldCBpPXRoaXMuX2luZmxpZ2h0cy5nZXQoZS5tZXNzYWdlSWQpO3JldHVybiBpPyh0aGlzLl9pbmZsaWdodHMuZGVsZXRlKGUubWVzc2FnZUlkKSxyKG51bGwsaSkpOnImJnIobmV3IEVycm9yKFwibWlzc2luZyBwYWNrZXRcIikpLHRoaXN9Z2V0KGUscil7bGV0IGk9dGhpcy5faW5mbGlnaHRzLmdldChlLm1lc3NhZ2VJZCk7cmV0dXJuIGk/cihudWxsLGkpOnImJnIobmV3IEVycm9yKFwibWlzc2luZyBwYWNrZXRcIikpLHRoaXN9Y2xvc2UoZSl7dGhpcy5vcHRpb25zLmNsZWFuJiYodGhpcy5faW5mbGlnaHRzPW51bGwpLGUmJmUoKTt9fTtYby5kZWZhdWx0PUpvO30pO3ZhciBWZD1NKGVhPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGVhLFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO3ZhciBIZD1bMCwxNiwxMjgsMTMxLDEzNSwxNDQsMTQ1LDE1MSwxNTNdLGgxPSh0LGUscik9Pnt0LmxvZyhcImhhbmRsZVB1Ymxpc2g6IHBhY2tldCAlb1wiLGUpLHI9dHlwZW9mIHI8XCJ1XCI/cjp0Lm5vb3A7bGV0IGk9ZS50b3BpYy50b1N0cmluZygpLG49ZS5wYXlsb2FkLHtxb3M6b309ZSx7bWVzc2FnZUlkOnN9PWUse29wdGlvbnM6YX09dDtpZih0Lm9wdGlvbnMucHJvdG9jb2xWZXJzaW9uPT09NSl7bGV0IHU7aWYoZS5wcm9wZXJ0aWVzJiYodT1lLnByb3BlcnRpZXMudG9waWNBbGlhcyksdHlwZW9mIHU8XCJ1XCIpaWYoaS5sZW5ndGg9PT0wKWlmKHU+MCYmdTw9NjU1MzUpe2xldCBjPXQudG9waWNBbGlhc1JlY3YuZ2V0VG9waWNCeUFsaWFzKHUpO2lmKGMpaT1jLHQubG9nKFwiaGFuZGxlUHVibGlzaCA6OiB0b3BpYyBjb21wbGVtZW50ZWQgYnkgYWxpYXMuIHRvcGljOiAlcyAtIGFsaWFzOiAlZFwiLGksdSk7ZWxzZSB7dC5sb2coXCJoYW5kbGVQdWJsaXNoIDo6IHVucmVnaXN0ZXJlZCB0b3BpYyBhbGlhcy4gYWxpYXM6ICVkXCIsdSksdC5lbWl0KFwiZXJyb3JcIixuZXcgRXJyb3IoXCJSZWNlaXZlZCB1bnJlZ2lzdGVyZWQgVG9waWMgQWxpYXNcIikpO3JldHVybn19ZWxzZSB7dC5sb2coXCJoYW5kbGVQdWJsaXNoIDo6IHRvcGljIGFsaWFzIG91dCBvZiByYW5nZS4gYWxpYXM6ICVkXCIsdSksdC5lbWl0KFwiZXJyb3JcIixuZXcgRXJyb3IoXCJSZWNlaXZlZCBUb3BpYyBBbGlhcyBpcyBvdXQgb2YgcmFuZ2VcIikpO3JldHVybn1lbHNlIGlmKHQudG9waWNBbGlhc1JlY3YucHV0KGksdSkpdC5sb2coXCJoYW5kbGVQdWJsaXNoIDo6IHJlZ2lzdGVyZWQgdG9waWM6ICVzIC0gYWxpYXM6ICVkXCIsaSx1KTtlbHNlIHt0LmxvZyhcImhhbmRsZVB1Ymxpc2ggOjogdG9waWMgYWxpYXMgb3V0IG9mIHJhbmdlLiBhbGlhczogJWRcIix1KSx0LmVtaXQoXCJlcnJvclwiLG5ldyBFcnJvcihcIlJlY2VpdmVkIFRvcGljIEFsaWFzIGlzIG91dCBvZiByYW5nZVwiKSk7cmV0dXJufX1zd2l0Y2godC5sb2coXCJoYW5kbGVQdWJsaXNoOiBxb3MgJWRcIixvKSxvKXtjYXNlIDI6e2EuY3VzdG9tSGFuZGxlQWNrcyhpLG4sZSwodSxjKT0+e2lmKHR5cGVvZiB1PT1cIm51bWJlclwiJiYoYz11LHU9bnVsbCksdSlyZXR1cm4gdC5lbWl0KFwiZXJyb3JcIix1KTtpZihIZC5pbmRleE9mKGMpPT09LTEpcmV0dXJuIHQuZW1pdChcImVycm9yXCIsbmV3IEVycm9yKFwiV3JvbmcgcmVhc29uIGNvZGUgZm9yIHB1YnJlY1wiKSk7Yz90Ll9zZW5kUGFja2V0KHtjbWQ6XCJwdWJyZWNcIixtZXNzYWdlSWQ6cyxyZWFzb25Db2RlOmN9LHIpOnQuaW5jb21pbmdTdG9yZS5wdXQoZSwoKT0+e3QuX3NlbmRQYWNrZXQoe2NtZDpcInB1YnJlY1wiLG1lc3NhZ2VJZDpzfSxyKTt9KTt9KTticmVha31jYXNlIDE6e2EuY3VzdG9tSGFuZGxlQWNrcyhpLG4sZSwodSxjKT0+e2lmKHR5cGVvZiB1PT1cIm51bWJlclwiJiYoYz11LHU9bnVsbCksdSlyZXR1cm4gdC5lbWl0KFwiZXJyb3JcIix1KTtpZihIZC5pbmRleE9mKGMpPT09LTEpcmV0dXJuIHQuZW1pdChcImVycm9yXCIsbmV3IEVycm9yKFwiV3JvbmcgcmVhc29uIGNvZGUgZm9yIHB1YmFja1wiKSk7Y3x8dC5lbWl0KFwibWVzc2FnZVwiLGksbixlKSx0LmhhbmRsZU1lc3NhZ2UoZSxoPT57aWYoaClyZXR1cm4gciYmcihoKTt0Ll9zZW5kUGFja2V0KHtjbWQ6XCJwdWJhY2tcIixtZXNzYWdlSWQ6cyxyZWFzb25Db2RlOmN9LHIpO30pO30pO2JyZWFrfWNhc2UgMDp0LmVtaXQoXCJtZXNzYWdlXCIsaSxuLGUpLHQuaGFuZGxlTWVzc2FnZShlLHIpO2JyZWFrO2RlZmF1bHQ6dC5sb2coXCJoYW5kbGVQdWJsaXNoOiB1bmtub3duIFFvUy4gRG9pbmcgbm90aGluZy5cIik7YnJlYWt9fTtlYS5kZWZhdWx0PWgxO30pO3ZhciBKcj1NKFd0PT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KFd0LFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO1d0Lm5leHRUaWNrPVd0LmFwcGx5TWl4aW49V3QuRXJyb3JXaXRoUmVhc29uQ29kZT12b2lkIDA7dmFyIHRhPWNsYXNzIHQgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihlLHIpe3N1cGVyKGUpLHRoaXMuY29kZT1yLE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLHQucHJvdG90eXBlKSxPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcykubmFtZT1cIkVycm9yV2l0aFJlYXNvbkNvZGVcIjt9fTtXdC5FcnJvcldpdGhSZWFzb25Db2RlPXRhO2Z1bmN0aW9uIGQxKHQsZSxyPSExKXt2YXIgaTtsZXQgbj1bZV07Zm9yKDs7KXtsZXQgbz1uWzBdLHM9T2JqZWN0LmdldFByb3RvdHlwZU9mKG8pO2lmKHM/LnByb3RvdHlwZSluLnVuc2hpZnQocyk7ZWxzZSBicmVha31mb3IobGV0IG8gb2Ygbilmb3IobGV0IHMgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoby5wcm90b3R5cGUpKShyfHxzIT09XCJjb25zdHJ1Y3RvclwiKSYmT2JqZWN0LmRlZmluZVByb3BlcnR5KHQucHJvdG90eXBlLHMsKGk9T2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvLnByb3RvdHlwZSxzKSkhPT1udWxsJiZpIT09dm9pZCAwP2k6T2JqZWN0LmNyZWF0ZShudWxsKSk7fVd0LmFwcGx5TWl4aW49ZDE7V3QubmV4dFRpY2s9dHlwZW9mKFA9PT1udWxsfHxQPT09dm9pZCAwP3ZvaWQgMDpQLm5leHRUaWNrKT09XCJmdW5jdGlvblwiP1AubmV4dFRpY2s6dD0+e3NldFRpbWVvdXQodCwwKTt9O30pO3ZhciBBaT1NKGJyPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGJyLFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO2JyLlJlYXNvbkNvZGVzPXZvaWQgMDtici5SZWFzb25Db2Rlcz17MDpcIlwiLDE6XCJVbmFjY2VwdGFibGUgcHJvdG9jb2wgdmVyc2lvblwiLDI6XCJJZGVudGlmaWVyIHJlamVjdGVkXCIsMzpcIlNlcnZlciB1bmF2YWlsYWJsZVwiLDQ6XCJCYWQgdXNlcm5hbWUgb3IgcGFzc3dvcmRcIiw1OlwiTm90IGF1dGhvcml6ZWRcIiwxNjpcIk5vIG1hdGNoaW5nIHN1YnNjcmliZXJzXCIsMTc6XCJObyBzdWJzY3JpcHRpb24gZXhpc3RlZFwiLDEyODpcIlVuc3BlY2lmaWVkIGVycm9yXCIsMTI5OlwiTWFsZm9ybWVkIFBhY2tldFwiLDEzMDpcIlByb3RvY29sIEVycm9yXCIsMTMxOlwiSW1wbGVtZW50YXRpb24gc3BlY2lmaWMgZXJyb3JcIiwxMzI6XCJVbnN1cHBvcnRlZCBQcm90b2NvbCBWZXJzaW9uXCIsMTMzOlwiQ2xpZW50IElkZW50aWZpZXIgbm90IHZhbGlkXCIsMTM0OlwiQmFkIFVzZXIgTmFtZSBvciBQYXNzd29yZFwiLDEzNTpcIk5vdCBhdXRob3JpemVkXCIsMTM2OlwiU2VydmVyIHVuYXZhaWxhYmxlXCIsMTM3OlwiU2VydmVyIGJ1c3lcIiwxMzg6XCJCYW5uZWRcIiwxMzk6XCJTZXJ2ZXIgc2h1dHRpbmcgZG93blwiLDE0MDpcIkJhZCBhdXRoZW50aWNhdGlvbiBtZXRob2RcIiwxNDE6XCJLZWVwIEFsaXZlIHRpbWVvdXRcIiwxNDI6XCJTZXNzaW9uIHRha2VuIG92ZXJcIiwxNDM6XCJUb3BpYyBGaWx0ZXIgaW52YWxpZFwiLDE0NDpcIlRvcGljIE5hbWUgaW52YWxpZFwiLDE0NTpcIlBhY2tldCBpZGVudGlmaWVyIGluIHVzZVwiLDE0NjpcIlBhY2tldCBJZGVudGlmaWVyIG5vdCBmb3VuZFwiLDE0NzpcIlJlY2VpdmUgTWF4aW11bSBleGNlZWRlZFwiLDE0ODpcIlRvcGljIEFsaWFzIGludmFsaWRcIiwxNDk6XCJQYWNrZXQgdG9vIGxhcmdlXCIsMTUwOlwiTWVzc2FnZSByYXRlIHRvbyBoaWdoXCIsMTUxOlwiUXVvdGEgZXhjZWVkZWRcIiwxNTI6XCJBZG1pbmlzdHJhdGl2ZSBhY3Rpb25cIiwxNTM6XCJQYXlsb2FkIGZvcm1hdCBpbnZhbGlkXCIsMTU0OlwiUmV0YWluIG5vdCBzdXBwb3J0ZWRcIiwxNTU6XCJRb1Mgbm90IHN1cHBvcnRlZFwiLDE1NjpcIlVzZSBhbm90aGVyIHNlcnZlclwiLDE1NzpcIlNlcnZlciBtb3ZlZFwiLDE1ODpcIlNoYXJlZCBTdWJzY3JpcHRpb25zIG5vdCBzdXBwb3J0ZWRcIiwxNTk6XCJDb25uZWN0aW9uIHJhdGUgZXhjZWVkZWRcIiwxNjA6XCJNYXhpbXVtIGNvbm5lY3QgdGltZVwiLDE2MTpcIlN1YnNjcmlwdGlvbiBJZGVudGlmaWVycyBub3Qgc3VwcG9ydGVkXCIsMTYyOlwiV2lsZGNhcmQgU3Vic2NyaXB0aW9ucyBub3Qgc3VwcG9ydGVkXCJ9O3ZhciBwMT0odCxlKT0+e2xldHttZXNzYWdlSWQ6cn09ZSxpPWUuY21kLG49bnVsbCxvPXQub3V0Z29pbmdbcl0/dC5vdXRnb2luZ1tyXS5jYjpudWxsLHM7aWYoIW8pe3QubG9nKFwiX2hhbmRsZUFjayA6OiBTZXJ2ZXIgc2VudCBhbiBhY2sgaW4gZXJyb3IuIElnbm9yaW5nLlwiKTtyZXR1cm59c3dpdGNoKHQubG9nKFwiX2hhbmRsZUFjayA6OiBwYWNrZXQgdHlwZVwiLGkpLGkpe2Nhc2VcInB1YmNvbXBcIjpjYXNlXCJwdWJhY2tcIjp7bGV0IGE9ZS5yZWFzb25Db2RlO2EmJmE+MCYmYSE9PTE2PyhzPW5ldyBFcnJvcihgUHVibGlzaCBlcnJvcjogJHtici5SZWFzb25Db2Rlc1thXX1gKSxzLmNvZGU9YSx0Ll9yZW1vdmVPdXRnb2luZ0FuZFN0b3JlTWVzc2FnZShyLCgpPT57byhzLGUpO30pKTp0Ll9yZW1vdmVPdXRnb2luZ0FuZFN0b3JlTWVzc2FnZShyLG8pO2JyZWFrfWNhc2VcInB1YnJlY1wiOntuPXtjbWQ6XCJwdWJyZWxcIixxb3M6MixtZXNzYWdlSWQ6cn07bGV0IGE9ZS5yZWFzb25Db2RlO2EmJmE+MCYmYSE9PTE2PyhzPW5ldyBFcnJvcihgUHVibGlzaCBlcnJvcjogJHtici5SZWFzb25Db2Rlc1thXX1gKSxzLmNvZGU9YSx0Ll9yZW1vdmVPdXRnb2luZ0FuZFN0b3JlTWVzc2FnZShyLCgpPT57byhzLGUpO30pKTp0Ll9zZW5kUGFja2V0KG4pO2JyZWFrfWNhc2VcInN1YmFja1wiOntkZWxldGUgdC5vdXRnb2luZ1tyXSx0Lm1lc3NhZ2VJZFByb3ZpZGVyLmRlYWxsb2NhdGUocik7bGV0IGE9ZS5ncmFudGVkO2ZvcihsZXQgdT0wO3U8YS5sZW5ndGg7dSsrKWlmKGFbdV0mMTI4KXtsZXQgYz10Lm1lc3NhZ2VJZFRvVG9waWNbcl07YyYmYy5mb3JFYWNoKGg9PntkZWxldGUgdC5fcmVzdWJzY3JpYmVUb3BpY3NbaF07fSk7fWRlbGV0ZSB0Lm1lc3NhZ2VJZFRvVG9waWNbcl0sdC5faW52b2tlU3RvcmVQcm9jZXNzaW5nUXVldWUoKSxvKG51bGwsZSk7YnJlYWt9Y2FzZVwidW5zdWJhY2tcIjp7ZGVsZXRlIHQub3V0Z29pbmdbcl0sdC5tZXNzYWdlSWRQcm92aWRlci5kZWFsbG9jYXRlKHIpLHQuX2ludm9rZVN0b3JlUHJvY2Vzc2luZ1F1ZXVlKCksbyhudWxsKTticmVha31kZWZhdWx0OnQuZW1pdChcImVycm9yXCIsbmV3IEVycm9yKFwidW5yZWNvZ25pemVkIHBhY2tldCB0eXBlXCIpKTt9dC5kaXNjb25uZWN0aW5nJiZPYmplY3Qua2V5cyh0Lm91dGdvaW5nKS5sZW5ndGg9PT0wJiZ0LmVtaXQoXCJvdXRnb2luZ0VtcHR5XCIpO307YnIuZGVmYXVsdD1wMTt9KTt2YXIgS2Q9TShyYT0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShyYSxcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTt2YXIgemQ9SnIoKSxnMT1BaSgpLHkxPSh0LGUpPT57bGV0e29wdGlvbnM6cn09dCxpPXIucHJvdG9jb2xWZXJzaW9uLG49aT09PTU/ZS5yZWFzb25Db2RlOmUucmV0dXJuQ29kZTtpZihpIT09NSl7bGV0IG89bmV3IHpkLkVycm9yV2l0aFJlYXNvbkNvZGUoYFByb3RvY29sIGVycm9yOiBBdXRoIHBhY2tldHMgYXJlIG9ubHkgc3VwcG9ydGVkIGluIE1RVFQgNS4gWW91ciB2ZXJzaW9uOiR7aX1gLG4pO3QuZW1pdChcImVycm9yXCIsbyk7cmV0dXJufXQuaGFuZGxlQXV0aChlLChvLHMpPT57aWYobyl7dC5lbWl0KFwiZXJyb3JcIixvKTtyZXR1cm59aWYobj09PTI0KXQucmVjb25uZWN0aW5nPSExLHQuX3NlbmRQYWNrZXQocyk7ZWxzZSB7bGV0IGE9bmV3IHpkLkVycm9yV2l0aFJlYXNvbkNvZGUoYENvbm5lY3Rpb24gcmVmdXNlZDogJHtnMS5SZWFzb25Db2Rlc1tuXX1gLG4pO3QuZW1pdChcImVycm9yXCIsYSk7fX0pO307cmEuZGVmYXVsdD15MTt9KTt2YXIgWGQ9TShrbj0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShrbixcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTtrbi5MUlVDYWNoZT12b2lkIDA7dmFyIElpPXR5cGVvZiBwZXJmb3JtYW5jZT09XCJvYmplY3RcIiYmcGVyZm9ybWFuY2UmJnR5cGVvZiBwZXJmb3JtYW5jZS5ub3c9PVwiZnVuY3Rpb25cIj9wZXJmb3JtYW5jZTpEYXRlLFFkPW5ldyBTZXQsaWE9dHlwZW9mIFA9PVwib2JqZWN0XCImJlA/UDp7fSxZZD0odCxlLHIsaSk9Pnt0eXBlb2YgaWEuZW1pdFdhcm5pbmc9PVwiZnVuY3Rpb25cIj9pYS5lbWl0V2FybmluZyh0LGUscixpKTpjb25zb2xlLmVycm9yKGBbJHtyfV0gJHtlfTogJHt0fWApO30sT249Z2xvYmFsVGhpcy5BYm9ydENvbnRyb2xsZXIsR2Q9Z2xvYmFsVGhpcy5BYm9ydFNpZ25hbDtpZih0eXBlb2YgT24+XCJ1XCIpe0dkPWNsYXNze29uYWJvcnQ7X29uYWJvcnQ9W107cmVhc29uO2Fib3J0ZWQ9ITE7YWRkRXZlbnRMaXN0ZW5lcihpLG4pe3RoaXMuX29uYWJvcnQucHVzaChuKTt9fSxPbj1jbGFzc3tjb25zdHJ1Y3Rvcigpe2UoKTt9c2lnbmFsPW5ldyBHZDthYm9ydChpKXtpZighdGhpcy5zaWduYWwuYWJvcnRlZCl7dGhpcy5zaWduYWwucmVhc29uPWksdGhpcy5zaWduYWwuYWJvcnRlZD0hMDtmb3IobGV0IG4gb2YgdGhpcy5zaWduYWwuX29uYWJvcnQpbihpKTt0aGlzLnNpZ25hbC5vbmFib3J0Py4oaSk7fX19O2xldCB0PWlhLmVudj8uTFJVX0NBQ0hFX0lHTk9SRV9BQ19XQVJOSU5HIT09XCIxXCIsZT0oKT0+e3QmJih0PSExLFlkKFwiQWJvcnRDb250cm9sbGVyIGlzIG5vdCBkZWZpbmVkLiBJZiB1c2luZyBscnUtY2FjaGUgaW4gbm9kZSAxNCwgbG9hZCBhbiBBYm9ydENvbnRyb2xsZXIgcG9seWZpbGwgZnJvbSB0aGUgYG5vZGUtYWJvcnQtY29udHJvbGxlcmAgcGFja2FnZS4gQSBtaW5pbWFsIHBvbHlmaWxsIGlzIHByb3ZpZGVkIGZvciB1c2UgYnkgTFJVQ2FjaGUuZmV0Y2goKSwgYnV0IGl0IHNob3VsZCBub3QgYmUgcmVsaWVkIHVwb24gaW4gb3RoZXIgY29udGV4dHMgKGVnLCBwYXNzaW5nIGl0IHRvIG90aGVyIEFQSXMgdGhhdCB1c2UgQWJvcnRDb250cm9sbGVyL0Fib3J0U2lnbmFsIG1pZ2h0IGhhdmUgdW5kZXNpcmFibGUgZWZmZWN0cykuIFlvdSBtYXkgZGlzYWJsZSB0aGlzIHdpdGggTFJVX0NBQ0hFX0lHTk9SRV9BQ19XQVJOSU5HPTEgaW4gdGhlIGVudi5cIixcIk5PX0FCT1JUX0NPTlRST0xMRVJcIixcIkVOT1RTVVBcIixlKSk7fTt9dmFyIGIxPXQ9PiFRZC5oYXModCksJHQ9dD0+dCYmdD09PU1hdGguZmxvb3IodCkmJnQ+MCYmaXNGaW5pdGUodCksSmQ9dD0+JHQodCk/dDw9TWF0aC5wb3coMiw4KT9VaW50OEFycmF5OnQ8PU1hdGgucG93KDIsMTYpP1VpbnQxNkFycmF5OnQ8PU1hdGgucG93KDIsMzIpP1VpbnQzMkFycmF5OnQ8PU51bWJlci5NQVhfU0FGRV9JTlRFR0VSP1hyOm51bGw6bnVsbCxYcj1jbGFzcyBleHRlbmRzIEFycmF5e2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpLHRoaXMuZmlsbCgwKTt9fSxuYT1jbGFzcyB0e2hlYXA7bGVuZ3RoO3N0YXRpYyNsPSExO3N0YXRpYyBjcmVhdGUoZSl7bGV0IHI9SmQoZSk7aWYoIXIpcmV0dXJuIFtdO3QuI2w9ITA7bGV0IGk9bmV3IHQoZSxyKTtyZXR1cm4gdC4jbD0hMSxpfWNvbnN0cnVjdG9yKGUscil7aWYoIXQuI2wpdGhyb3cgbmV3IFR5cGVFcnJvcihcImluc3RhbnRpYXRlIFN0YWNrIHVzaW5nIFN0YWNrLmNyZWF0ZShuKVwiKTt0aGlzLmhlYXA9bmV3IHIoZSksdGhpcy5sZW5ndGg9MDt9cHVzaChlKXt0aGlzLmhlYXBbdGhpcy5sZW5ndGgrK109ZTt9cG9wKCl7cmV0dXJuIHRoaXMuaGVhcFstLXRoaXMubGVuZ3RoXX19LHNhPWNsYXNzIHR7I2w7I2M7I3A7I2c7I0I7dHRsO3R0bFJlc29sdXRpb247dHRsQXV0b3B1cmdlO3VwZGF0ZUFnZU9uR2V0O3VwZGF0ZUFnZU9uSGFzO2FsbG93U3RhbGU7bm9EaXNwb3NlT25TZXQ7bm9VcGRhdGVUVEw7bWF4RW50cnlTaXplO3NpemVDYWxjdWxhdGlvbjtub0RlbGV0ZU9uRmV0Y2hSZWplY3Rpb247bm9EZWxldGVPblN0YWxlR2V0O2FsbG93U3RhbGVPbkZldGNoQWJvcnQ7YWxsb3dTdGFsZU9uRmV0Y2hSZWplY3Rpb247aWdub3JlRmV0Y2hBYm9ydDsjaTsjeTsjbjsjcjsjZTsjdTsjaDsjYTsjczsjYjsjbzsjRTsjUzsjdzsjXzsjSTsjZjtzdGF0aWMgdW5zYWZlRXhwb3NlSW50ZXJuYWxzKGUpe3JldHVybiB7c3RhcnRzOmUuI1MsdHRsczplLiN3LHNpemVzOmUuI0Usa2V5TWFwOmUuI24sa2V5TGlzdDplLiNyLHZhbExpc3Q6ZS4jZSxuZXh0OmUuI3UscHJldjplLiNoLGdldCBoZWFkKCl7cmV0dXJuIGUuI2F9LGdldCB0YWlsKCl7cmV0dXJuIGUuI3N9LGZyZWU6ZS4jYixpc0JhY2tncm91bmRGZXRjaDpyPT5lLiN0KHIpLGJhY2tncm91bmRGZXRjaDoocixpLG4sbyk9PmUuI2socixpLG4sbyksbW92ZVRvVGFpbDpyPT5lLiNDKHIpLGluZGV4ZXM6cj0+ZS4jbShyKSxyaW5kZXhlczpyPT5lLiN2KHIpLGlzU3RhbGU6cj0+ZS4jZChyKX19Z2V0IG1heCgpe3JldHVybiB0aGlzLiNsfWdldCBtYXhTaXplKCl7cmV0dXJuIHRoaXMuI2N9Z2V0IGNhbGN1bGF0ZWRTaXplKCl7cmV0dXJuIHRoaXMuI3l9Z2V0IHNpemUoKXtyZXR1cm4gdGhpcy4jaX1nZXQgZmV0Y2hNZXRob2QoKXtyZXR1cm4gdGhpcy4jQn1nZXQgZGlzcG9zZSgpe3JldHVybiB0aGlzLiNwfWdldCBkaXNwb3NlQWZ0ZXIoKXtyZXR1cm4gdGhpcy4jZ31jb25zdHJ1Y3RvcihlKXtsZXR7bWF4OnI9MCx0dGw6aSx0dGxSZXNvbHV0aW9uOm49MSx0dGxBdXRvcHVyZ2U6byx1cGRhdGVBZ2VPbkdldDpzLHVwZGF0ZUFnZU9uSGFzOmEsYWxsb3dTdGFsZTp1LGRpc3Bvc2U6YyxkaXNwb3NlQWZ0ZXI6aCxub0Rpc3Bvc2VPblNldDpkLG5vVXBkYXRlVFRMOmcsbWF4U2l6ZTp5PTAsbWF4RW50cnlTaXplOnc9MCxzaXplQ2FsY3VsYXRpb246RSxmZXRjaE1ldGhvZDpTLG5vRGVsZXRlT25GZXRjaFJlamVjdGlvbjpJLG5vRGVsZXRlT25TdGFsZUdldDpDLGFsbG93U3RhbGVPbkZldGNoUmVqZWN0aW9uOlIsYWxsb3dTdGFsZU9uRmV0Y2hBYm9ydDpVLGlnbm9yZUZldGNoQWJvcnQ6Tn09ZTtpZihyIT09MCYmISR0KHIpKXRocm93IG5ldyBUeXBlRXJyb3IoXCJtYXggb3B0aW9uIG11c3QgYmUgYSBub25uZWdhdGl2ZSBpbnRlZ2VyXCIpO2xldCBXPXI/SmQocik6QXJyYXk7aWYoIVcpdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBtYXggdmFsdWU6IFwiK3IpO2lmKHRoaXMuI2w9cix0aGlzLiNjPXksdGhpcy5tYXhFbnRyeVNpemU9d3x8dGhpcy4jYyx0aGlzLnNpemVDYWxjdWxhdGlvbj1FLHRoaXMuc2l6ZUNhbGN1bGF0aW9uKXtpZighdGhpcy4jYyYmIXRoaXMubWF4RW50cnlTaXplKXRocm93IG5ldyBUeXBlRXJyb3IoXCJjYW5ub3Qgc2V0IHNpemVDYWxjdWxhdGlvbiB3aXRob3V0IHNldHRpbmcgbWF4U2l6ZSBvciBtYXhFbnRyeVNpemVcIik7aWYodHlwZW9mIHRoaXMuc2l6ZUNhbGN1bGF0aW9uIT1cImZ1bmN0aW9uXCIpdGhyb3cgbmV3IFR5cGVFcnJvcihcInNpemVDYWxjdWxhdGlvbiBzZXQgdG8gbm9uLWZ1bmN0aW9uXCIpfWlmKFMhPT12b2lkIDAmJnR5cGVvZiBTIT1cImZ1bmN0aW9uXCIpdGhyb3cgbmV3IFR5cGVFcnJvcihcImZldGNoTWV0aG9kIG11c3QgYmUgYSBmdW5jdGlvbiBpZiBzcGVjaWZpZWRcIik7aWYodGhpcy4jQj1TLHRoaXMuI0k9ISFTLHRoaXMuI249bmV3IE1hcCx0aGlzLiNyPW5ldyBBcnJheShyKS5maWxsKHZvaWQgMCksdGhpcy4jZT1uZXcgQXJyYXkocikuZmlsbCh2b2lkIDApLHRoaXMuI3U9bmV3IFcociksdGhpcy4jaD1uZXcgVyhyKSx0aGlzLiNhPTAsdGhpcy4jcz0wLHRoaXMuI2I9bmEuY3JlYXRlKHIpLHRoaXMuI2k9MCx0aGlzLiN5PTAsdHlwZW9mIGM9PVwiZnVuY3Rpb25cIiYmKHRoaXMuI3A9YyksdHlwZW9mIGg9PVwiZnVuY3Rpb25cIj8odGhpcy4jZz1oLHRoaXMuI289W10pOih0aGlzLiNnPXZvaWQgMCx0aGlzLiNvPXZvaWQgMCksdGhpcy4jXz0hIXRoaXMuI3AsdGhpcy4jZj0hIXRoaXMuI2csdGhpcy5ub0Rpc3Bvc2VPblNldD0hIWQsdGhpcy5ub1VwZGF0ZVRUTD0hIWcsdGhpcy5ub0RlbGV0ZU9uRmV0Y2hSZWplY3Rpb249ISFJLHRoaXMuYWxsb3dTdGFsZU9uRmV0Y2hSZWplY3Rpb249ISFSLHRoaXMuYWxsb3dTdGFsZU9uRmV0Y2hBYm9ydD0hIVUsdGhpcy5pZ25vcmVGZXRjaEFib3J0PSEhTix0aGlzLm1heEVudHJ5U2l6ZSE9PTApe2lmKHRoaXMuI2MhPT0wJiYhJHQodGhpcy4jYykpdGhyb3cgbmV3IFR5cGVFcnJvcihcIm1heFNpemUgbXVzdCBiZSBhIHBvc2l0aXZlIGludGVnZXIgaWYgc3BlY2lmaWVkXCIpO2lmKCEkdCh0aGlzLm1heEVudHJ5U2l6ZSkpdGhyb3cgbmV3IFR5cGVFcnJvcihcIm1heEVudHJ5U2l6ZSBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlciBpZiBzcGVjaWZpZWRcIik7dGhpcy4jcSgpO31pZih0aGlzLmFsbG93U3RhbGU9ISF1LHRoaXMubm9EZWxldGVPblN0YWxlR2V0PSEhQyx0aGlzLnVwZGF0ZUFnZU9uR2V0PSEhcyx0aGlzLnVwZGF0ZUFnZU9uSGFzPSEhYSx0aGlzLnR0bFJlc29sdXRpb249JHQobil8fG49PT0wP246MSx0aGlzLnR0bEF1dG9wdXJnZT0hIW8sdGhpcy50dGw9aXx8MCx0aGlzLnR0bCl7aWYoISR0KHRoaXMudHRsKSl0aHJvdyBuZXcgVHlwZUVycm9yKFwidHRsIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyIGlmIHNwZWNpZmllZFwiKTt0aGlzLiN4KCk7fWlmKHRoaXMuI2w9PT0wJiZ0aGlzLnR0bD09PTAmJnRoaXMuI2M9PT0wKXRocm93IG5ldyBUeXBlRXJyb3IoXCJBdCBsZWFzdCBvbmUgb2YgbWF4LCBtYXhTaXplLCBvciB0dGwgaXMgcmVxdWlyZWRcIik7aWYoIXRoaXMudHRsQXV0b3B1cmdlJiYhdGhpcy4jbCYmIXRoaXMuI2Mpe2xldCBLPVwiTFJVX0NBQ0hFX1VOQk9VTkRFRFwiO2IxKEspJiYoUWQuYWRkKEspLFlkKFwiVFRMIGNhY2hpbmcgd2l0aG91dCB0dGxBdXRvcHVyZ2UsIG1heCwgb3IgbWF4U2l6ZSBjYW4gcmVzdWx0IGluIHVuYm91bmRlZCBtZW1vcnkgY29uc3VtcHRpb24uXCIsXCJVbmJvdW5kZWRDYWNoZVdhcm5pbmdcIixLLHQpKTt9fWdldFJlbWFpbmluZ1RUTChlKXtyZXR1cm4gdGhpcy4jbi5oYXMoZSk/MS8wOjB9I3goKXtsZXQgZT1uZXcgWHIodGhpcy4jbCkscj1uZXcgWHIodGhpcy4jbCk7dGhpcy4jdz1lLHRoaXMuI1M9cix0aGlzLiNNPShvLHMsYT1JaS5ub3coKSk9PntpZihyW29dPXMhPT0wP2E6MCxlW29dPXMscyE9PTAmJnRoaXMudHRsQXV0b3B1cmdlKXtsZXQgdT1zZXRUaW1lb3V0KCgpPT57dGhpcy4jZChvKSYmdGhpcy5kZWxldGUodGhpcy4jcltvXSk7fSxzKzEpO3UudW5yZWYmJnUudW5yZWYoKTt9fSx0aGlzLiNUPW89PntyW29dPWVbb10hPT0wP0lpLm5vdygpOjA7fSx0aGlzLiNBPShvLHMpPT57aWYoZVtzXSl7bGV0IGE9ZVtzXSx1PXJbc107by50dGw9YSxvLnN0YXJ0PXUsby5ub3c9aXx8bigpO2xldCBjPW8ubm93LXU7by5yZW1haW5pbmdUVEw9YS1jO319O2xldCBpPTAsbj0oKT0+e2xldCBvPUlpLm5vdygpO2lmKHRoaXMudHRsUmVzb2x1dGlvbj4wKXtpPW87bGV0IHM9c2V0VGltZW91dCgoKT0+aT0wLHRoaXMudHRsUmVzb2x1dGlvbik7cy51bnJlZiYmcy51bnJlZigpO31yZXR1cm4gb307dGhpcy5nZXRSZW1haW5pbmdUVEw9bz0+e2xldCBzPXRoaXMuI24uZ2V0KG8pO2lmKHM9PT12b2lkIDApcmV0dXJuIDA7bGV0IGE9ZVtzXSx1PXJbc107aWYoYT09PTB8fHU9PT0wKXJldHVybiAxLzA7bGV0IGM9KGl8fG4oKSktdTtyZXR1cm4gYS1jfSx0aGlzLiNkPW89PmVbb10hPT0wJiZyW29dIT09MCYmKGl8fG4oKSktcltvXT5lW29dO30jVD0oKT0+e307I0E9KCk9Pnt9OyNNPSgpPT57fTsjZD0oKT0+ITE7I3EoKXtsZXQgZT1uZXcgWHIodGhpcy4jbCk7dGhpcy4jeT0wLHRoaXMuI0U9ZSx0aGlzLiNSPXI9Pnt0aGlzLiN5LT1lW3JdLGVbcl09MDt9LHRoaXMuI0w9KHIsaSxuLG8pPT57aWYodGhpcy4jdChpKSlyZXR1cm4gMDtpZighJHQobikpaWYobyl7aWYodHlwZW9mIG8hPVwiZnVuY3Rpb25cIil0aHJvdyBuZXcgVHlwZUVycm9yKFwic2l6ZUNhbGN1bGF0aW9uIG11c3QgYmUgYSBmdW5jdGlvblwiKTtpZihuPW8oaSxyKSwhJHQobikpdGhyb3cgbmV3IFR5cGVFcnJvcihcInNpemVDYWxjdWxhdGlvbiByZXR1cm4gaW52YWxpZCAoZXhwZWN0IHBvc2l0aXZlIGludGVnZXIpXCIpfWVsc2UgdGhyb3cgbmV3IFR5cGVFcnJvcihcImludmFsaWQgc2l6ZSB2YWx1ZSAobXVzdCBiZSBwb3NpdGl2ZSBpbnRlZ2VyKS4gV2hlbiBtYXhTaXplIG9yIG1heEVudHJ5U2l6ZSBpcyB1c2VkLCBzaXplQ2FsY3VsYXRpb24gb3Igc2l6ZSBtdXN0IGJlIHNldC5cIik7cmV0dXJuIG59LHRoaXMuI1A9KHIsaSxuKT0+e2lmKGVbcl09aSx0aGlzLiNjKXtsZXQgbz10aGlzLiNjLWVbcl07Zm9yKDt0aGlzLiN5Pm87KXRoaXMuI08oITApO310aGlzLiN5Kz1lW3JdLG4mJihuLmVudHJ5U2l6ZT1pLG4udG90YWxDYWxjdWxhdGVkU2l6ZT10aGlzLiN5KTt9O30jUj1lPT57fTsjUD0oZSxyLGkpPT57fTsjTD0oZSxyLGksbik9PntpZihpfHxuKXRocm93IG5ldyBUeXBlRXJyb3IoXCJjYW5ub3Qgc2V0IHNpemUgd2l0aG91dCBzZXR0aW5nIG1heFNpemUgb3IgbWF4RW50cnlTaXplIG9uIGNhY2hlXCIpO3JldHVybiAwfTsqI20oe2FsbG93U3RhbGU6ZT10aGlzLmFsbG93U3RhbGV9PXt9KXtpZih0aGlzLiNpKWZvcihsZXQgcj10aGlzLiNzOyEoIXRoaXMuI1Uocil8fCgoZXx8IXRoaXMuI2QocikpJiYoeWllbGQgcikscj09PXRoaXMuI2EpKTspcj10aGlzLiNoW3JdO30qI3Yoe2FsbG93U3RhbGU6ZT10aGlzLmFsbG93U3RhbGV9PXt9KXtpZih0aGlzLiNpKWZvcihsZXQgcj10aGlzLiNhOyEoIXRoaXMuI1Uocil8fCgoZXx8IXRoaXMuI2QocikpJiYoeWllbGQgcikscj09PXRoaXMuI3MpKTspcj10aGlzLiN1W3JdO30jVShlKXtyZXR1cm4gZSE9PXZvaWQgMCYmdGhpcy4jbi5nZXQodGhpcy4jcltlXSk9PT1lfSplbnRyaWVzKCl7Zm9yKGxldCBlIG9mIHRoaXMuI20oKSl0aGlzLiNlW2VdIT09dm9pZCAwJiZ0aGlzLiNyW2VdIT09dm9pZCAwJiYhdGhpcy4jdCh0aGlzLiNlW2VdKSYmKHlpZWxkIFt0aGlzLiNyW2VdLHRoaXMuI2VbZV1dKTt9KnJlbnRyaWVzKCl7Zm9yKGxldCBlIG9mIHRoaXMuI3YoKSl0aGlzLiNlW2VdIT09dm9pZCAwJiZ0aGlzLiNyW2VdIT09dm9pZCAwJiYhdGhpcy4jdCh0aGlzLiNlW2VdKSYmKHlpZWxkIFt0aGlzLiNyW2VdLHRoaXMuI2VbZV1dKTt9KmtleXMoKXtmb3IobGV0IGUgb2YgdGhpcy4jbSgpKXtsZXQgcj10aGlzLiNyW2VdO3IhPT12b2lkIDAmJiF0aGlzLiN0KHRoaXMuI2VbZV0pJiYoeWllbGQgcik7fX0qcmtleXMoKXtmb3IobGV0IGUgb2YgdGhpcy4jdigpKXtsZXQgcj10aGlzLiNyW2VdO3IhPT12b2lkIDAmJiF0aGlzLiN0KHRoaXMuI2VbZV0pJiYoeWllbGQgcik7fX0qdmFsdWVzKCl7Zm9yKGxldCBlIG9mIHRoaXMuI20oKSl0aGlzLiNlW2VdIT09dm9pZCAwJiYhdGhpcy4jdCh0aGlzLiNlW2VdKSYmKHlpZWxkIHRoaXMuI2VbZV0pO30qcnZhbHVlcygpe2ZvcihsZXQgZSBvZiB0aGlzLiN2KCkpdGhpcy4jZVtlXSE9PXZvaWQgMCYmIXRoaXMuI3QodGhpcy4jZVtlXSkmJih5aWVsZCB0aGlzLiNlW2VdKTt9W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gdGhpcy5lbnRyaWVzKCl9ZmluZChlLHI9e30pe2ZvcihsZXQgaSBvZiB0aGlzLiNtKCkpe2xldCBuPXRoaXMuI2VbaV0sbz10aGlzLiN0KG4pP24uX19zdGFsZVdoaWxlRmV0Y2hpbmc6bjtpZihvIT09dm9pZCAwJiZlKG8sdGhpcy4jcltpXSx0aGlzKSlyZXR1cm4gdGhpcy5nZXQodGhpcy4jcltpXSxyKX19Zm9yRWFjaChlLHI9dGhpcyl7Zm9yKGxldCBpIG9mIHRoaXMuI20oKSl7bGV0IG49dGhpcy4jZVtpXSxvPXRoaXMuI3Qobik/bi5fX3N0YWxlV2hpbGVGZXRjaGluZzpuO28hPT12b2lkIDAmJmUuY2FsbChyLG8sdGhpcy4jcltpXSx0aGlzKTt9fXJmb3JFYWNoKGUscj10aGlzKXtmb3IobGV0IGkgb2YgdGhpcy4jdigpKXtsZXQgbj10aGlzLiNlW2ldLG89dGhpcy4jdChuKT9uLl9fc3RhbGVXaGlsZUZldGNoaW5nOm47byE9PXZvaWQgMCYmZS5jYWxsKHIsbyx0aGlzLiNyW2ldLHRoaXMpO319cHVyZ2VTdGFsZSgpe2xldCBlPSExO2ZvcihsZXQgciBvZiB0aGlzLiN2KHthbGxvd1N0YWxlOiEwfSkpdGhpcy4jZChyKSYmKHRoaXMuZGVsZXRlKHRoaXMuI3Jbcl0pLGU9ITApO3JldHVybiBlfWR1bXAoKXtsZXQgZT1bXTtmb3IobGV0IHIgb2YgdGhpcy4jbSh7YWxsb3dTdGFsZTohMH0pKXtsZXQgaT10aGlzLiNyW3JdLG49dGhpcy4jZVtyXSxvPXRoaXMuI3Qobik/bi5fX3N0YWxlV2hpbGVGZXRjaGluZzpuO2lmKG89PT12b2lkIDB8fGk9PT12b2lkIDApY29udGludWU7bGV0IHM9e3ZhbHVlOm99O2lmKHRoaXMuI3cmJnRoaXMuI1Mpe3MudHRsPXRoaXMuI3dbcl07bGV0IGE9SWkubm93KCktdGhpcy4jU1tyXTtzLnN0YXJ0PU1hdGguZmxvb3IoRGF0ZS5ub3coKS1hKTt9dGhpcy4jRSYmKHMuc2l6ZT10aGlzLiNFW3JdKSxlLnVuc2hpZnQoW2ksc10pO31yZXR1cm4gZX1sb2FkKGUpe3RoaXMuY2xlYXIoKTtmb3IobGV0W3IsaV1vZiBlKXtpZihpLnN0YXJ0KXtsZXQgbj1EYXRlLm5vdygpLWkuc3RhcnQ7aS5zdGFydD1JaS5ub3coKS1uO310aGlzLnNldChyLGkudmFsdWUsaSk7fX1zZXQoZSxyLGk9e30pe2lmKHI9PT12b2lkIDApcmV0dXJuIHRoaXMuZGVsZXRlKGUpLHRoaXM7bGV0e3R0bDpuPXRoaXMudHRsLHN0YXJ0Om8sbm9EaXNwb3NlT25TZXQ6cz10aGlzLm5vRGlzcG9zZU9uU2V0LHNpemVDYWxjdWxhdGlvbjphPXRoaXMuc2l6ZUNhbGN1bGF0aW9uLHN0YXR1czp1fT1pLHtub1VwZGF0ZVRUTDpjPXRoaXMubm9VcGRhdGVUVEx9PWksaD10aGlzLiNMKGUscixpLnNpemV8fDAsYSk7aWYodGhpcy5tYXhFbnRyeVNpemUmJmg+dGhpcy5tYXhFbnRyeVNpemUpcmV0dXJuIHUmJih1LnNldD1cIm1pc3NcIix1Lm1heEVudHJ5U2l6ZUV4Y2VlZGVkPSEwKSx0aGlzLmRlbGV0ZShlKSx0aGlzO2xldCBkPXRoaXMuI2k9PT0wP3ZvaWQgMDp0aGlzLiNuLmdldChlKTtpZihkPT09dm9pZCAwKWQ9dGhpcy4jaT09PTA/dGhpcy4jczp0aGlzLiNiLmxlbmd0aCE9PTA/dGhpcy4jYi5wb3AoKTp0aGlzLiNpPT09dGhpcy4jbD90aGlzLiNPKCExKTp0aGlzLiNpLHRoaXMuI3JbZF09ZSx0aGlzLiNlW2RdPXIsdGhpcy4jbi5zZXQoZSxkKSx0aGlzLiN1W3RoaXMuI3NdPWQsdGhpcy4jaFtkXT10aGlzLiNzLHRoaXMuI3M9ZCx0aGlzLiNpKyssdGhpcy4jUChkLGgsdSksdSYmKHUuc2V0PVwiYWRkXCIpLGM9ITE7ZWxzZSB7dGhpcy4jQyhkKTtsZXQgZz10aGlzLiNlW2RdO2lmKHIhPT1nKXtpZih0aGlzLiNJJiZ0aGlzLiN0KGcpKXtnLl9fYWJvcnRDb250cm9sbGVyLmFib3J0KG5ldyBFcnJvcihcInJlcGxhY2VkXCIpKTtsZXR7X19zdGFsZVdoaWxlRmV0Y2hpbmc6eX09Zzt5IT09dm9pZCAwJiYhcyYmKHRoaXMuI18mJnRoaXMuI3A/Lih5LGUsXCJzZXRcIiksdGhpcy4jZiYmdGhpcy4jbz8ucHVzaChbeSxlLFwic2V0XCJdKSk7fWVsc2Ugc3x8KHRoaXMuI18mJnRoaXMuI3A/LihnLGUsXCJzZXRcIiksdGhpcy4jZiYmdGhpcy4jbz8ucHVzaChbZyxlLFwic2V0XCJdKSk7aWYodGhpcy4jUihkKSx0aGlzLiNQKGQsaCx1KSx0aGlzLiNlW2RdPXIsdSl7dS5zZXQ9XCJyZXBsYWNlXCI7bGV0IHk9ZyYmdGhpcy4jdChnKT9nLl9fc3RhbGVXaGlsZUZldGNoaW5nOmc7eSE9PXZvaWQgMCYmKHUub2xkVmFsdWU9eSk7fX1lbHNlIHUmJih1LnNldD1cInVwZGF0ZVwiKTt9aWYobiE9PTAmJiF0aGlzLiN3JiZ0aGlzLiN4KCksdGhpcy4jdyYmKGN8fHRoaXMuI00oZCxuLG8pLHUmJnRoaXMuI0EodSxkKSksIXMmJnRoaXMuI2YmJnRoaXMuI28pe2xldCBnPXRoaXMuI28seTtmb3IoO3k9Zz8uc2hpZnQoKTspdGhpcy4jZz8uKC4uLnkpO31yZXR1cm4gdGhpc31wb3AoKXt0cnl7Zm9yKDt0aGlzLiNpOyl7bGV0IGU9dGhpcy4jZVt0aGlzLiNhXTtpZih0aGlzLiNPKCEwKSx0aGlzLiN0KGUpKXtpZihlLl9fc3RhbGVXaGlsZUZldGNoaW5nKXJldHVybiBlLl9fc3RhbGVXaGlsZUZldGNoaW5nfWVsc2UgaWYoZSE9PXZvaWQgMClyZXR1cm4gZX19ZmluYWxseXtpZih0aGlzLiNmJiZ0aGlzLiNvKXtsZXQgZT10aGlzLiNvLHI7Zm9yKDtyPWU/LnNoaWZ0KCk7KXRoaXMuI2c/LiguLi5yKTt9fX0jTyhlKXtsZXQgcj10aGlzLiNhLGk9dGhpcy4jcltyXSxuPXRoaXMuI2Vbcl07cmV0dXJuIHRoaXMuI0kmJnRoaXMuI3Qobik/bi5fX2Fib3J0Q29udHJvbGxlci5hYm9ydChuZXcgRXJyb3IoXCJldmljdGVkXCIpKToodGhpcy4jX3x8dGhpcy4jZikmJih0aGlzLiNfJiZ0aGlzLiNwPy4obixpLFwiZXZpY3RcIiksdGhpcy4jZiYmdGhpcy4jbz8ucHVzaChbbixpLFwiZXZpY3RcIl0pKSx0aGlzLiNSKHIpLGUmJih0aGlzLiNyW3JdPXZvaWQgMCx0aGlzLiNlW3JdPXZvaWQgMCx0aGlzLiNiLnB1c2gocikpLHRoaXMuI2k9PT0xPyh0aGlzLiNhPXRoaXMuI3M9MCx0aGlzLiNiLmxlbmd0aD0wKTp0aGlzLiNhPXRoaXMuI3Vbcl0sdGhpcy4jbi5kZWxldGUoaSksdGhpcy4jaS0tLHJ9aGFzKGUscj17fSl7bGV0e3VwZGF0ZUFnZU9uSGFzOmk9dGhpcy51cGRhdGVBZ2VPbkhhcyxzdGF0dXM6bn09cixvPXRoaXMuI24uZ2V0KGUpO2lmKG8hPT12b2lkIDApe2xldCBzPXRoaXMuI2Vbb107aWYodGhpcy4jdChzKSYmcy5fX3N0YWxlV2hpbGVGZXRjaGluZz09PXZvaWQgMClyZXR1cm4gITE7aWYodGhpcy4jZChvKSluJiYobi5oYXM9XCJzdGFsZVwiLHRoaXMuI0EobixvKSk7ZWxzZSByZXR1cm4gaSYmdGhpcy4jVChvKSxuJiYobi5oYXM9XCJoaXRcIix0aGlzLiNBKG4sbykpLCEwfWVsc2UgbiYmKG4uaGFzPVwibWlzc1wiKTtyZXR1cm4gITF9cGVlayhlLHI9e30pe2xldHthbGxvd1N0YWxlOmk9dGhpcy5hbGxvd1N0YWxlfT1yLG49dGhpcy4jbi5nZXQoZSk7aWYobiE9PXZvaWQgMCYmKGl8fCF0aGlzLiNkKG4pKSl7bGV0IG89dGhpcy4jZVtuXTtyZXR1cm4gdGhpcy4jdChvKT9vLl9fc3RhbGVXaGlsZUZldGNoaW5nOm99fSNrKGUscixpLG4pe2xldCBvPXI9PT12b2lkIDA/dm9pZCAwOnRoaXMuI2Vbcl07aWYodGhpcy4jdChvKSlyZXR1cm4gbztsZXQgcz1uZXcgT24se3NpZ25hbDphfT1pO2E/LmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCgpPT5zLmFib3J0KGEucmVhc29uKSx7c2lnbmFsOnMuc2lnbmFsfSk7bGV0IHU9e3NpZ25hbDpzLnNpZ25hbCxvcHRpb25zOmksY29udGV4dDpufSxjPShFLFM9ITEpPT57bGV0e2Fib3J0ZWQ6SX09cy5zaWduYWwsQz1pLmlnbm9yZUZldGNoQWJvcnQmJkUhPT12b2lkIDA7aWYoaS5zdGF0dXMmJihJJiYhUz8oaS5zdGF0dXMuZmV0Y2hBYm9ydGVkPSEwLGkuc3RhdHVzLmZldGNoRXJyb3I9cy5zaWduYWwucmVhc29uLEMmJihpLnN0YXR1cy5mZXRjaEFib3J0SWdub3JlZD0hMCkpOmkuc3RhdHVzLmZldGNoUmVzb2x2ZWQ9ITApLEkmJiFDJiYhUylyZXR1cm4gZChzLnNpZ25hbC5yZWFzb24pO2xldCBSPXk7cmV0dXJuIHRoaXMuI2Vbcl09PT15JiYoRT09PXZvaWQgMD9SLl9fc3RhbGVXaGlsZUZldGNoaW5nP3RoaXMuI2Vbcl09Ui5fX3N0YWxlV2hpbGVGZXRjaGluZzp0aGlzLmRlbGV0ZShlKTooaS5zdGF0dXMmJihpLnN0YXR1cy5mZXRjaFVwZGF0ZWQ9ITApLHRoaXMuc2V0KGUsRSx1Lm9wdGlvbnMpKSksRX0saD1FPT4oaS5zdGF0dXMmJihpLnN0YXR1cy5mZXRjaFJlamVjdGVkPSEwLGkuc3RhdHVzLmZldGNoRXJyb3I9RSksZChFKSksZD1FPT57bGV0e2Fib3J0ZWQ6U309cy5zaWduYWwsST1TJiZpLmFsbG93U3RhbGVPbkZldGNoQWJvcnQsQz1JfHxpLmFsbG93U3RhbGVPbkZldGNoUmVqZWN0aW9uLFI9Q3x8aS5ub0RlbGV0ZU9uRmV0Y2hSZWplY3Rpb24sVT15O2lmKHRoaXMuI2Vbcl09PT15JiYoIVJ8fFUuX19zdGFsZVdoaWxlRmV0Y2hpbmc9PT12b2lkIDA/dGhpcy5kZWxldGUoZSk6SXx8KHRoaXMuI2Vbcl09VS5fX3N0YWxlV2hpbGVGZXRjaGluZykpLEMpcmV0dXJuIGkuc3RhdHVzJiZVLl9fc3RhbGVXaGlsZUZldGNoaW5nIT09dm9pZCAwJiYoaS5zdGF0dXMucmV0dXJuZWRTdGFsZT0hMCksVS5fX3N0YWxlV2hpbGVGZXRjaGluZztpZihVLl9fcmV0dXJuZWQ9PT1VKXRocm93IEV9LGc9KEUsUyk9PntsZXQgST10aGlzLiNCPy4oZSxvLHUpO0kmJkkgaW5zdGFuY2VvZiBQcm9taXNlJiZJLnRoZW4oQz0+RShDPT09dm9pZCAwP3ZvaWQgMDpDKSxTKSxzLnNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwoKT0+eyghaS5pZ25vcmVGZXRjaEFib3J0fHxpLmFsbG93U3RhbGVPbkZldGNoQWJvcnQpJiYoRSh2b2lkIDApLGkuYWxsb3dTdGFsZU9uRmV0Y2hBYm9ydCYmKEU9Qz0+YyhDLCEwKSkpO30pO307aS5zdGF0dXMmJihpLnN0YXR1cy5mZXRjaERpc3BhdGNoZWQ9ITApO2xldCB5PW5ldyBQcm9taXNlKGcpLnRoZW4oYyxoKSx3PU9iamVjdC5hc3NpZ24oeSx7X19hYm9ydENvbnRyb2xsZXI6cyxfX3N0YWxlV2hpbGVGZXRjaGluZzpvLF9fcmV0dXJuZWQ6dm9pZCAwfSk7cmV0dXJuIHI9PT12b2lkIDA/KHRoaXMuc2V0KGUsdyx7Li4udS5vcHRpb25zLHN0YXR1czp2b2lkIDB9KSxyPXRoaXMuI24uZ2V0KGUpKTp0aGlzLiNlW3JdPXcsd30jdChlKXtpZighdGhpcy4jSSlyZXR1cm4gITE7bGV0IHI9ZTtyZXR1cm4gISFyJiZyIGluc3RhbmNlb2YgUHJvbWlzZSYmci5oYXNPd25Qcm9wZXJ0eShcIl9fc3RhbGVXaGlsZUZldGNoaW5nXCIpJiZyLl9fYWJvcnRDb250cm9sbGVyIGluc3RhbmNlb2YgT259YXN5bmMgZmV0Y2goZSxyPXt9KXtsZXR7YWxsb3dTdGFsZTppPXRoaXMuYWxsb3dTdGFsZSx1cGRhdGVBZ2VPbkdldDpuPXRoaXMudXBkYXRlQWdlT25HZXQsbm9EZWxldGVPblN0YWxlR2V0Om89dGhpcy5ub0RlbGV0ZU9uU3RhbGVHZXQsdHRsOnM9dGhpcy50dGwsbm9EaXNwb3NlT25TZXQ6YT10aGlzLm5vRGlzcG9zZU9uU2V0LHNpemU6dT0wLHNpemVDYWxjdWxhdGlvbjpjPXRoaXMuc2l6ZUNhbGN1bGF0aW9uLG5vVXBkYXRlVFRMOmg9dGhpcy5ub1VwZGF0ZVRUTCxub0RlbGV0ZU9uRmV0Y2hSZWplY3Rpb246ZD10aGlzLm5vRGVsZXRlT25GZXRjaFJlamVjdGlvbixhbGxvd1N0YWxlT25GZXRjaFJlamVjdGlvbjpnPXRoaXMuYWxsb3dTdGFsZU9uRmV0Y2hSZWplY3Rpb24saWdub3JlRmV0Y2hBYm9ydDp5PXRoaXMuaWdub3JlRmV0Y2hBYm9ydCxhbGxvd1N0YWxlT25GZXRjaEFib3J0Onc9dGhpcy5hbGxvd1N0YWxlT25GZXRjaEFib3J0LGNvbnRleHQ6RSxmb3JjZVJlZnJlc2g6Uz0hMSxzdGF0dXM6SSxzaWduYWw6Q309cjtpZighdGhpcy4jSSlyZXR1cm4gSSYmKEkuZmV0Y2g9XCJnZXRcIiksdGhpcy5nZXQoZSx7YWxsb3dTdGFsZTppLHVwZGF0ZUFnZU9uR2V0Om4sbm9EZWxldGVPblN0YWxlR2V0Om8sc3RhdHVzOkl9KTtsZXQgUj17YWxsb3dTdGFsZTppLHVwZGF0ZUFnZU9uR2V0Om4sbm9EZWxldGVPblN0YWxlR2V0Om8sdHRsOnMsbm9EaXNwb3NlT25TZXQ6YSxzaXplOnUsc2l6ZUNhbGN1bGF0aW9uOmMsbm9VcGRhdGVUVEw6aCxub0RlbGV0ZU9uRmV0Y2hSZWplY3Rpb246ZCxhbGxvd1N0YWxlT25GZXRjaFJlamVjdGlvbjpnLGFsbG93U3RhbGVPbkZldGNoQWJvcnQ6dyxpZ25vcmVGZXRjaEFib3J0Onksc3RhdHVzOkksc2lnbmFsOkN9LFU9dGhpcy4jbi5nZXQoZSk7aWYoVT09PXZvaWQgMCl7SSYmKEkuZmV0Y2g9XCJtaXNzXCIpO2xldCBOPXRoaXMuI2soZSxVLFIsRSk7cmV0dXJuIE4uX19yZXR1cm5lZD1OfWVsc2Uge2xldCBOPXRoaXMuI2VbVV07aWYodGhpcy4jdChOKSl7bGV0IGRlPWkmJk4uX19zdGFsZVdoaWxlRmV0Y2hpbmchPT12b2lkIDA7cmV0dXJuIEkmJihJLmZldGNoPVwiaW5mbGlnaHRcIixkZSYmKEkucmV0dXJuZWRTdGFsZT0hMCkpLGRlP04uX19zdGFsZVdoaWxlRmV0Y2hpbmc6Ti5fX3JldHVybmVkPU59bGV0IFc9dGhpcy4jZChVKTtpZighUyYmIVcpcmV0dXJuIEkmJihJLmZldGNoPVwiaGl0XCIpLHRoaXMuI0MoVSksbiYmdGhpcy4jVChVKSxJJiZ0aGlzLiNBKEksVSksTjtsZXQgSz10aGlzLiNrKGUsVSxSLEUpLFE9Sy5fX3N0YWxlV2hpbGVGZXRjaGluZyE9PXZvaWQgMCYmaTtyZXR1cm4gSSYmKEkuZmV0Y2g9Vz9cInN0YWxlXCI6XCJyZWZyZXNoXCIsUSYmVyYmKEkucmV0dXJuZWRTdGFsZT0hMCkpLFE/Sy5fX3N0YWxlV2hpbGVGZXRjaGluZzpLLl9fcmV0dXJuZWQ9S319Z2V0KGUscj17fSl7bGV0e2FsbG93U3RhbGU6aT10aGlzLmFsbG93U3RhbGUsdXBkYXRlQWdlT25HZXQ6bj10aGlzLnVwZGF0ZUFnZU9uR2V0LG5vRGVsZXRlT25TdGFsZUdldDpvPXRoaXMubm9EZWxldGVPblN0YWxlR2V0LHN0YXR1czpzfT1yLGE9dGhpcy4jbi5nZXQoZSk7aWYoYSE9PXZvaWQgMCl7bGV0IHU9dGhpcy4jZVthXSxjPXRoaXMuI3QodSk7cmV0dXJuIHMmJnRoaXMuI0EocyxhKSx0aGlzLiNkKGEpPyhzJiYocy5nZXQ9XCJzdGFsZVwiKSxjPyhzJiZpJiZ1Ll9fc3RhbGVXaGlsZUZldGNoaW5nIT09dm9pZCAwJiYocy5yZXR1cm5lZFN0YWxlPSEwKSxpP3UuX19zdGFsZVdoaWxlRmV0Y2hpbmc6dm9pZCAwKToob3x8dGhpcy5kZWxldGUoZSkscyYmaSYmKHMucmV0dXJuZWRTdGFsZT0hMCksaT91OnZvaWQgMCkpOihzJiYocy5nZXQ9XCJoaXRcIiksYz91Ll9fc3RhbGVXaGlsZUZldGNoaW5nOih0aGlzLiNDKGEpLG4mJnRoaXMuI1QoYSksdSkpfWVsc2UgcyYmKHMuZ2V0PVwibWlzc1wiKTt9I04oZSxyKXt0aGlzLiNoW3JdPWUsdGhpcy4jdVtlXT1yO30jQyhlKXtlIT09dGhpcy4jcyYmKGU9PT10aGlzLiNhP3RoaXMuI2E9dGhpcy4jdVtlXTp0aGlzLiNOKHRoaXMuI2hbZV0sdGhpcy4jdVtlXSksdGhpcy4jTih0aGlzLiNzLGUpLHRoaXMuI3M9ZSk7fWRlbGV0ZShlKXtsZXQgcj0hMTtpZih0aGlzLiNpIT09MCl7bGV0IGk9dGhpcy4jbi5nZXQoZSk7aWYoaSE9PXZvaWQgMClpZihyPSEwLHRoaXMuI2k9PT0xKXRoaXMuY2xlYXIoKTtlbHNlIHt0aGlzLiNSKGkpO2xldCBuPXRoaXMuI2VbaV07dGhpcy4jdChuKT9uLl9fYWJvcnRDb250cm9sbGVyLmFib3J0KG5ldyBFcnJvcihcImRlbGV0ZWRcIikpOih0aGlzLiNffHx0aGlzLiNmKSYmKHRoaXMuI18mJnRoaXMuI3A/LihuLGUsXCJkZWxldGVcIiksdGhpcy4jZiYmdGhpcy4jbz8ucHVzaChbbixlLFwiZGVsZXRlXCJdKSksdGhpcy4jbi5kZWxldGUoZSksdGhpcy4jcltpXT12b2lkIDAsdGhpcy4jZVtpXT12b2lkIDAsaT09PXRoaXMuI3M/dGhpcy4jcz10aGlzLiNoW2ldOmk9PT10aGlzLiNhP3RoaXMuI2E9dGhpcy4jdVtpXToodGhpcy4jdVt0aGlzLiNoW2ldXT10aGlzLiN1W2ldLHRoaXMuI2hbdGhpcy4jdVtpXV09dGhpcy4jaFtpXSksdGhpcy4jaS0tLHRoaXMuI2IucHVzaChpKTt9fWlmKHRoaXMuI2YmJnRoaXMuI28/Lmxlbmd0aCl7bGV0IGk9dGhpcy4jbyxuO2Zvcig7bj1pPy5zaGlmdCgpOyl0aGlzLiNnPy4oLi4ubik7fXJldHVybiByfWNsZWFyKCl7Zm9yKGxldCBlIG9mIHRoaXMuI3Yoe2FsbG93U3RhbGU6ITB9KSl7bGV0IHI9dGhpcy4jZVtlXTtpZih0aGlzLiN0KHIpKXIuX19hYm9ydENvbnRyb2xsZXIuYWJvcnQobmV3IEVycm9yKFwiZGVsZXRlZFwiKSk7ZWxzZSB7bGV0IGk9dGhpcy4jcltlXTt0aGlzLiNfJiZ0aGlzLiNwPy4ocixpLFwiZGVsZXRlXCIpLHRoaXMuI2YmJnRoaXMuI28/LnB1c2goW3IsaSxcImRlbGV0ZVwiXSk7fX1pZih0aGlzLiNuLmNsZWFyKCksdGhpcy4jZS5maWxsKHZvaWQgMCksdGhpcy4jci5maWxsKHZvaWQgMCksdGhpcy4jdyYmdGhpcy4jUyYmKHRoaXMuI3cuZmlsbCgwKSx0aGlzLiNTLmZpbGwoMCkpLHRoaXMuI0UmJnRoaXMuI0UuZmlsbCgwKSx0aGlzLiNhPTAsdGhpcy4jcz0wLHRoaXMuI2IubGVuZ3RoPTAsdGhpcy4jeT0wLHRoaXMuI2k9MCx0aGlzLiNmJiZ0aGlzLiNvKXtsZXQgZT10aGlzLiNvLHI7Zm9yKDtyPWU/LnNoaWZ0KCk7KXRoaXMuI2c/LiguLi5yKTt9fX07a24uTFJVQ2FjaGU9c2E7fSk7dmFyIGF0PU0oSHQ9Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoSHQsXCJ0XCIse3ZhbHVlOiEwfSk7SHQuQ29udGFpbmVySXRlcmF0b3I9SHQuQ29udGFpbmVyPUh0LkJhc2U9dm9pZCAwO3ZhciBvYT1jbGFzc3tjb25zdHJ1Y3RvcihlPTApe3RoaXMuaXRlcmF0b3JUeXBlPWU7fWVxdWFscyhlKXtyZXR1cm4gdGhpcy5vPT09ZS5vfX07SHQuQ29udGFpbmVySXRlcmF0b3I9b2E7dmFyIHhuPWNsYXNze2NvbnN0cnVjdG9yKCl7dGhpcy5pPTA7fWdldCBsZW5ndGgoKXtyZXR1cm4gdGhpcy5pfXNpemUoKXtyZXR1cm4gdGhpcy5pfWVtcHR5KCl7cmV0dXJuIHRoaXMuaT09PTB9fTtIdC5CYXNlPXhuO3ZhciBhYT1jbGFzcyBleHRlbmRzIHhue307SHQuQ29udGFpbmVyPWFhO30pO3ZhciBaZD1NKE1uPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KE1uLFwidFwiLHt2YWx1ZTohMH0pO01uLmRlZmF1bHQ9dm9pZCAwO3ZhciB3MT1hdCgpLGxhPWNsYXNzIGV4dGVuZHMgdzEuQmFzZXtjb25zdHJ1Y3RvcihlPVtdKXtzdXBlcigpLHRoaXMuUz1bXTtsZXQgcj10aGlzO2UuZm9yRWFjaChmdW5jdGlvbihpKXtyLnB1c2goaSk7fSk7fWNsZWFyKCl7dGhpcy5pPTAsdGhpcy5TPVtdO31wdXNoKGUpe3JldHVybiB0aGlzLlMucHVzaChlKSx0aGlzLmkrPTEsdGhpcy5pfXBvcCgpe2lmKHRoaXMuaSE9PTApcmV0dXJuIHRoaXMuaS09MSx0aGlzLlMucG9wKCl9dG9wKCl7cmV0dXJuIHRoaXMuU1t0aGlzLmktMV19fSxfMT1sYTtNbi5kZWZhdWx0PV8xO30pO3ZhciBlcD1NKExuPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KExuLFwidFwiLHt2YWx1ZTohMH0pO0xuLmRlZmF1bHQ9dm9pZCAwO3ZhciBtMT1hdCgpLHVhPWNsYXNzIGV4dGVuZHMgbTEuQmFzZXtjb25zdHJ1Y3RvcihlPVtdKXtzdXBlcigpLHRoaXMuaj0wLHRoaXMucT1bXTtsZXQgcj10aGlzO2UuZm9yRWFjaChmdW5jdGlvbihpKXtyLnB1c2goaSk7fSk7fWNsZWFyKCl7dGhpcy5xPVtdLHRoaXMuaT10aGlzLmo9MDt9cHVzaChlKXtsZXQgcj10aGlzLnEubGVuZ3RoO2lmKHRoaXMuai9yPi41JiZ0aGlzLmordGhpcy5pPj1yJiZyPjQwOTYpe2xldCBpPXRoaXMuaTtmb3IobGV0IG49MDtuPGk7KytuKXRoaXMucVtuXT10aGlzLnFbdGhpcy5qK25dO3RoaXMuaj0wLHRoaXMucVt0aGlzLmldPWU7fWVsc2UgdGhpcy5xW3RoaXMuait0aGlzLmldPWU7cmV0dXJuICsrdGhpcy5pfXBvcCgpe2lmKHRoaXMuaT09PTApcmV0dXJuO2xldCBlPXRoaXMucVt0aGlzLmorK107cmV0dXJuIHRoaXMuaS09MSxlfWZyb250KCl7aWYodGhpcy5pIT09MClyZXR1cm4gdGhpcy5xW3RoaXMual19fSx2MT11YTtMbi5kZWZhdWx0PXYxO30pO3ZhciB0cD1NKFVuPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KFVuLFwidFwiLHt2YWx1ZTohMH0pO1VuLmRlZmF1bHQ9dm9pZCAwO3ZhciBFMT1hdCgpLGZhPWNsYXNzIGV4dGVuZHMgRTEuQmFzZXtjb25zdHJ1Y3RvcihlPVtdLHI9ZnVuY3Rpb24obixvKXtyZXR1cm4gbj5vPy0xOm48bz8xOjB9LGk9ITApe2lmKHN1cGVyKCksdGhpcy52PXIsQXJyYXkuaXNBcnJheShlKSl0aGlzLkM9aT9bLi4uZV06ZTtlbHNlIHt0aGlzLkM9W107bGV0IG89dGhpcztlLmZvckVhY2goZnVuY3Rpb24ocyl7by5DLnB1c2gocyk7fSk7fXRoaXMuaT10aGlzLkMubGVuZ3RoO2xldCBuPXRoaXMuaT4+MTtmb3IobGV0IG89dGhpcy5pLTE+PjE7bz49MDstLW8pdGhpcy5rKG8sbik7fW0oZSl7bGV0IHI9dGhpcy5DW2VdO2Zvcig7ZT4wOyl7bGV0IGk9ZS0xPj4xLG49dGhpcy5DW2ldO2lmKHRoaXMudihuLHIpPD0wKWJyZWFrO3RoaXMuQ1tlXT1uLGU9aTt9dGhpcy5DW2VdPXI7fWsoZSxyKXtsZXQgaT10aGlzLkNbZV07Zm9yKDtlPHI7KXtsZXQgbj1lPDwxfDEsbz1uKzEscz10aGlzLkNbbl07aWYobzx0aGlzLmkmJnRoaXMudihzLHRoaXMuQ1tvXSk+MCYmKG49byxzPXRoaXMuQ1tvXSksdGhpcy52KHMsaSk+PTApYnJlYWs7dGhpcy5DW2VdPXMsZT1uO310aGlzLkNbZV09aTt9Y2xlYXIoKXt0aGlzLmk9MCx0aGlzLkMubGVuZ3RoPTA7fXB1c2goZSl7dGhpcy5DLnB1c2goZSksdGhpcy5tKHRoaXMuaSksdGhpcy5pKz0xO31wb3AoKXtpZih0aGlzLmk9PT0wKXJldHVybjtsZXQgZT10aGlzLkNbMF0scj10aGlzLkMucG9wKCk7cmV0dXJuIHRoaXMuaS09MSx0aGlzLmkmJih0aGlzLkNbMF09cix0aGlzLmsoMCx0aGlzLmk+PjEpKSxlfXRvcCgpe3JldHVybiB0aGlzLkNbMF19ZmluZChlKXtyZXR1cm4gdGhpcy5DLmluZGV4T2YoZSk+PTB9cmVtb3ZlKGUpe2xldCByPXRoaXMuQy5pbmRleE9mKGUpO3JldHVybiByPDA/ITE6KHI9PT0wP3RoaXMucG9wKCk6cj09PXRoaXMuaS0xPyh0aGlzLkMucG9wKCksdGhpcy5pLT0xKToodGhpcy5DLnNwbGljZShyLDEsdGhpcy5DLnBvcCgpKSx0aGlzLmktPTEsdGhpcy5tKHIpLHRoaXMuayhyLHRoaXMuaT4+MSkpLCEwKX11cGRhdGVJdGVtKGUpe2xldCByPXRoaXMuQy5pbmRleE9mKGUpO3JldHVybiByPDA/ITE6KHRoaXMubShyKSx0aGlzLmsocix0aGlzLmk+PjEpLCEwKX10b0FycmF5KCl7cmV0dXJuIFsuLi50aGlzLkNdfX0sUzE9ZmE7VW4uZGVmYXVsdD1TMTt9KTt2YXIgcW49TShObj0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShObixcInRcIix7dmFsdWU6ITB9KTtObi5kZWZhdWx0PXZvaWQgMDt2YXIgQTE9YXQoKSxjYT1jbGFzcyBleHRlbmRzIEExLkNvbnRhaW5lcnt9LEkxPWNhO05uLmRlZmF1bHQ9STE7fSk7dmFyIGx0PU0oaGE9Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoaGEsXCJ0XCIse3ZhbHVlOiEwfSk7aGEudGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yPVQxO2Z1bmN0aW9uIFQxKCl7dGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJJdGVyYXRvciBhY2Nlc3MgZGVuaWVkIVwiKX19KTt2YXIgcGE9TShqbj0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShqbixcInRcIix7dmFsdWU6ITB9KTtqbi5SYW5kb21JdGVyYXRvcj12b2lkIDA7dmFyIFIxPWF0KCksRG49bHQoKSxkYT1jbGFzcyBleHRlbmRzIFIxLkNvbnRhaW5lckl0ZXJhdG9ye2NvbnN0cnVjdG9yKGUscil7c3VwZXIociksdGhpcy5vPWUsdGhpcy5pdGVyYXRvclR5cGU9PT0wPyh0aGlzLnByZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLm89PT0wJiYoMCwgRG4udGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpLHRoaXMuby09MSx0aGlzfSx0aGlzLm5leHQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5vPT09dGhpcy5jb250YWluZXIuc2l6ZSgpJiYoMCwgRG4udGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpLHRoaXMubys9MSx0aGlzfSk6KHRoaXMucHJlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubz09PXRoaXMuY29udGFpbmVyLnNpemUoKS0xJiYoMCwgRG4udGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpLHRoaXMubys9MSx0aGlzfSx0aGlzLm5leHQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5vPT09LTEmJigwLCBEbi50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vLT0xLHRoaXN9KTt9Z2V0IHBvaW50ZXIoKXtyZXR1cm4gdGhpcy5jb250YWluZXIuZ2V0RWxlbWVudEJ5UG9zKHRoaXMubyl9c2V0IHBvaW50ZXIoZSl7dGhpcy5jb250YWluZXIuc2V0RWxlbWVudEJ5UG9zKHRoaXMubyxlKTt9fTtqbi5SYW5kb21JdGVyYXRvcj1kYTt9KTt2YXIgcnA9TShGbj0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShGbixcInRcIix7dmFsdWU6ITB9KTtGbi5kZWZhdWx0PXZvaWQgMDt2YXIgQzE9UDEocW4oKSksQjE9cGEoKTtmdW5jdGlvbiBQMSh0KXtyZXR1cm4gdCYmdC50P3Q6e2RlZmF1bHQ6dH19dmFyIHdyPWNsYXNzIHQgZXh0ZW5kcyBCMS5SYW5kb21JdGVyYXRvcntjb25zdHJ1Y3RvcihlLHIsaSl7c3VwZXIoZSxpKSx0aGlzLmNvbnRhaW5lcj1yO31jb3B5KCl7cmV0dXJuIG5ldyB0KHRoaXMubyx0aGlzLmNvbnRhaW5lcix0aGlzLml0ZXJhdG9yVHlwZSl9fSxnYT1jbGFzcyBleHRlbmRzIEMxLmRlZmF1bHR7Y29uc3RydWN0b3IoZT1bXSxyPSEwKXtpZihzdXBlcigpLEFycmF5LmlzQXJyYXkoZSkpdGhpcy5KPXI/Wy4uLmVdOmUsdGhpcy5pPWUubGVuZ3RoO2Vsc2Uge3RoaXMuSj1bXTtsZXQgaT10aGlzO2UuZm9yRWFjaChmdW5jdGlvbihuKXtpLnB1c2hCYWNrKG4pO30pO319Y2xlYXIoKXt0aGlzLmk9MCx0aGlzLkoubGVuZ3RoPTA7fWJlZ2luKCl7cmV0dXJuIG5ldyB3cigwLHRoaXMpfWVuZCgpe3JldHVybiBuZXcgd3IodGhpcy5pLHRoaXMpfXJCZWdpbigpe3JldHVybiBuZXcgd3IodGhpcy5pLTEsdGhpcywxKX1yRW5kKCl7cmV0dXJuIG5ldyB3cigtMSx0aGlzLDEpfWZyb250KCl7cmV0dXJuIHRoaXMuSlswXX1iYWNrKCl7cmV0dXJuIHRoaXMuSlt0aGlzLmktMV19Z2V0RWxlbWVudEJ5UG9zKGUpe2lmKGU8MHx8ZT50aGlzLmktMSl0aHJvdyBuZXcgUmFuZ2VFcnJvcjtyZXR1cm4gdGhpcy5KW2VdfWVyYXNlRWxlbWVudEJ5UG9zKGUpe2lmKGU8MHx8ZT50aGlzLmktMSl0aHJvdyBuZXcgUmFuZ2VFcnJvcjtyZXR1cm4gdGhpcy5KLnNwbGljZShlLDEpLHRoaXMuaS09MSx0aGlzLml9ZXJhc2VFbGVtZW50QnlWYWx1ZShlKXtsZXQgcj0wO2ZvcihsZXQgaT0wO2k8dGhpcy5pOysraSl0aGlzLkpbaV0hPT1lJiYodGhpcy5KW3IrK109dGhpcy5KW2ldKTtyZXR1cm4gdGhpcy5pPXRoaXMuSi5sZW5ndGg9cix0aGlzLml9ZXJhc2VFbGVtZW50QnlJdGVyYXRvcihlKXtsZXQgcj1lLm87cmV0dXJuIGU9ZS5uZXh0KCksdGhpcy5lcmFzZUVsZW1lbnRCeVBvcyhyKSxlfXB1c2hCYWNrKGUpe3JldHVybiB0aGlzLkoucHVzaChlKSx0aGlzLmkrPTEsdGhpcy5pfXBvcEJhY2soKXtpZih0aGlzLmkhPT0wKXJldHVybiB0aGlzLmktPTEsdGhpcy5KLnBvcCgpfXNldEVsZW1lbnRCeVBvcyhlLHIpe2lmKGU8MHx8ZT50aGlzLmktMSl0aHJvdyBuZXcgUmFuZ2VFcnJvcjt0aGlzLkpbZV09cjt9aW5zZXJ0KGUscixpPTEpe2lmKGU8MHx8ZT50aGlzLmkpdGhyb3cgbmV3IFJhbmdlRXJyb3I7cmV0dXJuIHRoaXMuSi5zcGxpY2UoZSwwLC4uLm5ldyBBcnJheShpKS5maWxsKHIpKSx0aGlzLmkrPWksdGhpcy5pfWZpbmQoZSl7Zm9yKGxldCByPTA7cjx0aGlzLmk7KytyKWlmKHRoaXMuSltyXT09PWUpcmV0dXJuIG5ldyB3cihyLHRoaXMpO3JldHVybiB0aGlzLmVuZCgpfXJldmVyc2UoKXt0aGlzLkoucmV2ZXJzZSgpO311bmlxdWUoKXtsZXQgZT0xO2ZvcihsZXQgcj0xO3I8dGhpcy5pOysrcil0aGlzLkpbcl0hPT10aGlzLkpbci0xXSYmKHRoaXMuSltlKytdPXRoaXMuSltyXSk7cmV0dXJuIHRoaXMuaT10aGlzLkoubGVuZ3RoPWUsdGhpcy5pfXNvcnQoZSl7dGhpcy5KLnNvcnQoZSk7fWZvckVhY2goZSl7Zm9yKGxldCByPTA7cjx0aGlzLmk7KytyKWUodGhpcy5KW3JdLHIsdGhpcyk7fVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIGZ1bmN0aW9uKigpe3lpZWxkKnRoaXMuSjt9LmJpbmQodGhpcykoKX19LE8xPWdhO0ZuLmRlZmF1bHQ9TzE7fSk7dmFyIGlwPU0oV249Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoV24sXCJ0XCIse3ZhbHVlOiEwfSk7V24uZGVmYXVsdD12b2lkIDA7dmFyIGsxPU0xKHFuKCkpLHgxPWF0KCksX3I9bHQoKTtmdW5jdGlvbiBNMSh0KXtyZXR1cm4gdCYmdC50P3Q6e2RlZmF1bHQ6dH19dmFyIG1yPWNsYXNzIHQgZXh0ZW5kcyB4MS5Db250YWluZXJJdGVyYXRvcntjb25zdHJ1Y3RvcihlLHIsaSxuKXtzdXBlcihuKSx0aGlzLm89ZSx0aGlzLmg9cix0aGlzLmNvbnRhaW5lcj1pLHRoaXMuaXRlcmF0b3JUeXBlPT09MD8odGhpcy5wcmU9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5vLkw9PT10aGlzLmgmJigwLCBfci50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vPXRoaXMuby5MLHRoaXN9LHRoaXMubmV4dD1mdW5jdGlvbigpe3JldHVybiB0aGlzLm89PT10aGlzLmgmJigwLCBfci50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vPXRoaXMuby5CLHRoaXN9KToodGhpcy5wcmU9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5vLkI9PT10aGlzLmgmJigwLCBfci50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vPXRoaXMuby5CLHRoaXN9LHRoaXMubmV4dD1mdW5jdGlvbigpe3JldHVybiB0aGlzLm89PT10aGlzLmgmJigwLCBfci50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vPXRoaXMuby5MLHRoaXN9KTt9Z2V0IHBvaW50ZXIoKXtyZXR1cm4gdGhpcy5vPT09dGhpcy5oJiYoMCwgX3IudGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpLHRoaXMuby5sfXNldCBwb2ludGVyKGUpe3RoaXMubz09PXRoaXMuaCYmKDAsIF9yLnRocm93SXRlcmF0b3JBY2Nlc3NFcnJvcikoKSx0aGlzLm8ubD1lO31jb3B5KCl7cmV0dXJuIG5ldyB0KHRoaXMubyx0aGlzLmgsdGhpcy5jb250YWluZXIsdGhpcy5pdGVyYXRvclR5cGUpfX0seWE9Y2xhc3MgZXh0ZW5kcyBrMS5kZWZhdWx0e2NvbnN0cnVjdG9yKGU9W10pe3N1cGVyKCksdGhpcy5oPXt9LHRoaXMucD10aGlzLl89dGhpcy5oLkw9dGhpcy5oLkI9dGhpcy5oO2xldCByPXRoaXM7ZS5mb3JFYWNoKGZ1bmN0aW9uKGkpe3IucHVzaEJhY2soaSk7fSk7fVYoZSl7bGV0e0w6cixCOml9PWU7ci5CPWksaS5MPXIsZT09PXRoaXMucCYmKHRoaXMucD1pKSxlPT09dGhpcy5fJiYodGhpcy5fPXIpLHRoaXMuaS09MTt9RyhlLHIpe2xldCBpPXIuQixuPXtsOmUsTDpyLEI6aX07ci5CPW4saS5MPW4scj09PXRoaXMuaCYmKHRoaXMucD1uKSxpPT09dGhpcy5oJiYodGhpcy5fPW4pLHRoaXMuaSs9MTt9Y2xlYXIoKXt0aGlzLmk9MCx0aGlzLnA9dGhpcy5fPXRoaXMuaC5MPXRoaXMuaC5CPXRoaXMuaDt9YmVnaW4oKXtyZXR1cm4gbmV3IG1yKHRoaXMucCx0aGlzLmgsdGhpcyl9ZW5kKCl7cmV0dXJuIG5ldyBtcih0aGlzLmgsdGhpcy5oLHRoaXMpfXJCZWdpbigpe3JldHVybiBuZXcgbXIodGhpcy5fLHRoaXMuaCx0aGlzLDEpfXJFbmQoKXtyZXR1cm4gbmV3IG1yKHRoaXMuaCx0aGlzLmgsdGhpcywxKX1mcm9udCgpe3JldHVybiB0aGlzLnAubH1iYWNrKCl7cmV0dXJuIHRoaXMuXy5sfWdldEVsZW1lbnRCeVBvcyhlKXtpZihlPDB8fGU+dGhpcy5pLTEpdGhyb3cgbmV3IFJhbmdlRXJyb3I7bGV0IHI9dGhpcy5wO2Zvcig7ZS0tOylyPXIuQjtyZXR1cm4gci5sfWVyYXNlRWxlbWVudEJ5UG9zKGUpe2lmKGU8MHx8ZT50aGlzLmktMSl0aHJvdyBuZXcgUmFuZ2VFcnJvcjtsZXQgcj10aGlzLnA7Zm9yKDtlLS07KXI9ci5CO3JldHVybiB0aGlzLlYociksdGhpcy5pfWVyYXNlRWxlbWVudEJ5VmFsdWUoZSl7bGV0IHI9dGhpcy5wO2Zvcig7ciE9PXRoaXMuaDspci5sPT09ZSYmdGhpcy5WKHIpLHI9ci5CO3JldHVybiB0aGlzLml9ZXJhc2VFbGVtZW50QnlJdGVyYXRvcihlKXtsZXQgcj1lLm87cmV0dXJuIHI9PT10aGlzLmgmJigwLCBfci50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksZT1lLm5leHQoKSx0aGlzLlYociksZX1wdXNoQmFjayhlKXtyZXR1cm4gdGhpcy5HKGUsdGhpcy5fKSx0aGlzLml9cG9wQmFjaygpe2lmKHRoaXMuaT09PTApcmV0dXJuO2xldCBlPXRoaXMuXy5sO3JldHVybiB0aGlzLlYodGhpcy5fKSxlfXB1c2hGcm9udChlKXtyZXR1cm4gdGhpcy5HKGUsdGhpcy5oKSx0aGlzLml9cG9wRnJvbnQoKXtpZih0aGlzLmk9PT0wKXJldHVybjtsZXQgZT10aGlzLnAubDtyZXR1cm4gdGhpcy5WKHRoaXMucCksZX1zZXRFbGVtZW50QnlQb3MoZSxyKXtpZihlPDB8fGU+dGhpcy5pLTEpdGhyb3cgbmV3IFJhbmdlRXJyb3I7bGV0IGk9dGhpcy5wO2Zvcig7ZS0tOylpPWkuQjtpLmw9cjt9aW5zZXJ0KGUscixpPTEpe2lmKGU8MHx8ZT50aGlzLmkpdGhyb3cgbmV3IFJhbmdlRXJyb3I7aWYoaTw9MClyZXR1cm4gdGhpcy5pO2lmKGU9PT0wKWZvcig7aS0tOyl0aGlzLnB1c2hGcm9udChyKTtlbHNlIGlmKGU9PT10aGlzLmkpZm9yKDtpLS07KXRoaXMucHVzaEJhY2socik7ZWxzZSB7bGV0IG49dGhpcy5wO2ZvcihsZXQgcz0xO3M8ZTsrK3Mpbj1uLkI7bGV0IG89bi5CO2Zvcih0aGlzLmkrPWk7aS0tOyluLkI9e2w6cixMOm59LG4uQi5MPW4sbj1uLkI7bi5CPW8sby5MPW47fXJldHVybiB0aGlzLml9ZmluZChlKXtsZXQgcj10aGlzLnA7Zm9yKDtyIT09dGhpcy5oOyl7aWYoci5sPT09ZSlyZXR1cm4gbmV3IG1yKHIsdGhpcy5oLHRoaXMpO3I9ci5CO31yZXR1cm4gdGhpcy5lbmQoKX1yZXZlcnNlKCl7aWYodGhpcy5pPD0xKXJldHVybjtsZXQgZT10aGlzLnAscj10aGlzLl8saT0wO2Zvcig7aTw8MTx0aGlzLmk7KXtsZXQgbj1lLmw7ZS5sPXIubCxyLmw9bixlPWUuQixyPXIuTCxpKz0xO319dW5pcXVlKCl7aWYodGhpcy5pPD0xKXJldHVybiB0aGlzLmk7bGV0IGU9dGhpcy5wO2Zvcig7ZSE9PXRoaXMuaDspe2xldCByPWU7Zm9yKDtyLkIhPT10aGlzLmgmJnIubD09PXIuQi5sOylyPXIuQix0aGlzLmktPTE7ZS5CPXIuQixlLkIuTD1lLGU9ZS5CO31yZXR1cm4gdGhpcy5pfXNvcnQoZSl7aWYodGhpcy5pPD0xKXJldHVybjtsZXQgcj1bXTt0aGlzLmZvckVhY2goZnVuY3Rpb24obil7ci5wdXNoKG4pO30pLHIuc29ydChlKTtsZXQgaT10aGlzLnA7ci5mb3JFYWNoKGZ1bmN0aW9uKG4pe2kubD1uLGk9aS5CO30pO31tZXJnZShlKXtsZXQgcj10aGlzO2lmKHRoaXMuaT09PTApZS5mb3JFYWNoKGZ1bmN0aW9uKGkpe3IucHVzaEJhY2soaSk7fSk7ZWxzZSB7bGV0IGk9dGhpcy5wO2UuZm9yRWFjaChmdW5jdGlvbihuKXtmb3IoO2khPT1yLmgmJmkubDw9bjspaT1pLkI7ci5HKG4saS5MKTt9KTt9cmV0dXJuIHRoaXMuaX1mb3JFYWNoKGUpe2xldCByPXRoaXMucCxpPTA7Zm9yKDtyIT09dGhpcy5oOyllKHIubCxpKyssdGhpcykscj1yLkI7fVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIGZ1bmN0aW9uKigpe2lmKHRoaXMuaT09PTApcmV0dXJuO2xldCBlPXRoaXMucDtmb3IoO2UhPT10aGlzLmg7KXlpZWxkIGUubCxlPWUuQjt9LmJpbmQodGhpcykoKX19LEwxPXlhO1duLmRlZmF1bHQ9TDE7fSk7dmFyIG5wPU0oJG49Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoJG4sXCJ0XCIse3ZhbHVlOiEwfSk7JG4uZGVmYXVsdD12b2lkIDA7dmFyIFUxPXExKHFuKCkpLE4xPXBhKCk7ZnVuY3Rpb24gcTEodCl7cmV0dXJuIHQmJnQudD90OntkZWZhdWx0OnR9fXZhciB2cj1jbGFzcyB0IGV4dGVuZHMgTjEuUmFuZG9tSXRlcmF0b3J7Y29uc3RydWN0b3IoZSxyLGkpe3N1cGVyKGUsaSksdGhpcy5jb250YWluZXI9cjt9Y29weSgpe3JldHVybiBuZXcgdCh0aGlzLm8sdGhpcy5jb250YWluZXIsdGhpcy5pdGVyYXRvclR5cGUpfX0sYmE9Y2xhc3MgZXh0ZW5kcyBVMS5kZWZhdWx0e2NvbnN0cnVjdG9yKGU9W10scj00MDk2KXtzdXBlcigpLHRoaXMuaj0wLHRoaXMuRD0wLHRoaXMuUj0wLHRoaXMuTj0wLHRoaXMuUD0wLHRoaXMuQT1bXTtsZXQgaT0oKCk9PntpZih0eXBlb2YgZS5sZW5ndGg9PVwibnVtYmVyXCIpcmV0dXJuIGUubGVuZ3RoO2lmKHR5cGVvZiBlLnNpemU9PVwibnVtYmVyXCIpcmV0dXJuIGUuc2l6ZTtpZih0eXBlb2YgZS5zaXplPT1cImZ1bmN0aW9uXCIpcmV0dXJuIGUuc2l6ZSgpO3Rocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgZ2V0IHRoZSBsZW5ndGggb3Igc2l6ZSBvZiB0aGUgY29udGFpbmVyXCIpfSkoKTt0aGlzLkY9cix0aGlzLlA9TWF0aC5tYXgoTWF0aC5jZWlsKGkvdGhpcy5GKSwxKTtmb3IobGV0IHM9MDtzPHRoaXMuUDsrK3MpdGhpcy5BLnB1c2gobmV3IEFycmF5KHRoaXMuRikpO2xldCBuPU1hdGguY2VpbChpL3RoaXMuRik7dGhpcy5qPXRoaXMuUj0odGhpcy5QPj4xKS0obj4+MSksdGhpcy5EPXRoaXMuTj10aGlzLkYtaSV0aGlzLkY+PjE7bGV0IG89dGhpcztlLmZvckVhY2goZnVuY3Rpb24ocyl7by5wdXNoQmFjayhzKTt9KTt9VCgpe2xldCBlPVtdLHI9TWF0aC5tYXgodGhpcy5QPj4xLDEpO2ZvcihsZXQgaT0wO2k8cjsrK2kpZVtpXT1uZXcgQXJyYXkodGhpcy5GKTtmb3IobGV0IGk9dGhpcy5qO2k8dGhpcy5QOysraSllW2UubGVuZ3RoXT10aGlzLkFbaV07Zm9yKGxldCBpPTA7aTx0aGlzLlI7KytpKWVbZS5sZW5ndGhdPXRoaXMuQVtpXTtlW2UubGVuZ3RoXT1bLi4udGhpcy5BW3RoaXMuUl1dLHRoaXMuaj1yLHRoaXMuUj1lLmxlbmd0aC0xO2ZvcihsZXQgaT0wO2k8cjsrK2kpZVtlLmxlbmd0aF09bmV3IEFycmF5KHRoaXMuRik7dGhpcy5BPWUsdGhpcy5QPWUubGVuZ3RoO31PKGUpe2xldCByPXRoaXMuRCtlKzEsaT1yJXRoaXMuRixuPWktMSxvPXRoaXMuaisoci1pKS90aGlzLkY7cmV0dXJuIGk9PT0wJiYoby09MSksbyU9dGhpcy5QLG48MCYmKG4rPXRoaXMuRikse2N1ck5vZGVCdWNrZXRJbmRleDpvLGN1ck5vZGVQb2ludGVySW5kZXg6bn19Y2xlYXIoKXt0aGlzLkE9W25ldyBBcnJheSh0aGlzLkYpXSx0aGlzLlA9MSx0aGlzLmo9dGhpcy5SPXRoaXMuaT0wLHRoaXMuRD10aGlzLk49dGhpcy5GPj4xO31iZWdpbigpe3JldHVybiBuZXcgdnIoMCx0aGlzKX1lbmQoKXtyZXR1cm4gbmV3IHZyKHRoaXMuaSx0aGlzKX1yQmVnaW4oKXtyZXR1cm4gbmV3IHZyKHRoaXMuaS0xLHRoaXMsMSl9ckVuZCgpe3JldHVybiBuZXcgdnIoLTEsdGhpcywxKX1mcm9udCgpe2lmKHRoaXMuaSE9PTApcmV0dXJuIHRoaXMuQVt0aGlzLmpdW3RoaXMuRF19YmFjaygpe2lmKHRoaXMuaSE9PTApcmV0dXJuIHRoaXMuQVt0aGlzLlJdW3RoaXMuTl19cHVzaEJhY2soZSl7cmV0dXJuIHRoaXMuaSYmKHRoaXMuTjx0aGlzLkYtMT90aGlzLk4rPTE6dGhpcy5SPHRoaXMuUC0xPyh0aGlzLlIrPTEsdGhpcy5OPTApOih0aGlzLlI9MCx0aGlzLk49MCksdGhpcy5SPT09dGhpcy5qJiZ0aGlzLk49PT10aGlzLkQmJnRoaXMuVCgpKSx0aGlzLmkrPTEsdGhpcy5BW3RoaXMuUl1bdGhpcy5OXT1lLHRoaXMuaX1wb3BCYWNrKCl7aWYodGhpcy5pPT09MClyZXR1cm47bGV0IGU9dGhpcy5BW3RoaXMuUl1bdGhpcy5OXTtyZXR1cm4gdGhpcy5pIT09MSYmKHRoaXMuTj4wP3RoaXMuTi09MTp0aGlzLlI+MD8odGhpcy5SLT0xLHRoaXMuTj10aGlzLkYtMSk6KHRoaXMuUj10aGlzLlAtMSx0aGlzLk49dGhpcy5GLTEpKSx0aGlzLmktPTEsZX1wdXNoRnJvbnQoZSl7cmV0dXJuIHRoaXMuaSYmKHRoaXMuRD4wP3RoaXMuRC09MTp0aGlzLmo+MD8odGhpcy5qLT0xLHRoaXMuRD10aGlzLkYtMSk6KHRoaXMuaj10aGlzLlAtMSx0aGlzLkQ9dGhpcy5GLTEpLHRoaXMuaj09PXRoaXMuUiYmdGhpcy5EPT09dGhpcy5OJiZ0aGlzLlQoKSksdGhpcy5pKz0xLHRoaXMuQVt0aGlzLmpdW3RoaXMuRF09ZSx0aGlzLml9cG9wRnJvbnQoKXtpZih0aGlzLmk9PT0wKXJldHVybjtsZXQgZT10aGlzLkFbdGhpcy5qXVt0aGlzLkRdO3JldHVybiB0aGlzLmkhPT0xJiYodGhpcy5EPHRoaXMuRi0xP3RoaXMuRCs9MTp0aGlzLmo8dGhpcy5QLTE/KHRoaXMuais9MSx0aGlzLkQ9MCk6KHRoaXMuaj0wLHRoaXMuRD0wKSksdGhpcy5pLT0xLGV9Z2V0RWxlbWVudEJ5UG9zKGUpe2lmKGU8MHx8ZT50aGlzLmktMSl0aHJvdyBuZXcgUmFuZ2VFcnJvcjtsZXR7Y3VyTm9kZUJ1Y2tldEluZGV4OnIsY3VyTm9kZVBvaW50ZXJJbmRleDppfT10aGlzLk8oZSk7cmV0dXJuIHRoaXMuQVtyXVtpXX1zZXRFbGVtZW50QnlQb3MoZSxyKXtpZihlPDB8fGU+dGhpcy5pLTEpdGhyb3cgbmV3IFJhbmdlRXJyb3I7bGV0e2N1ck5vZGVCdWNrZXRJbmRleDppLGN1ck5vZGVQb2ludGVySW5kZXg6bn09dGhpcy5PKGUpO3RoaXMuQVtpXVtuXT1yO31pbnNlcnQoZSxyLGk9MSl7aWYoZTwwfHxlPnRoaXMuaSl0aHJvdyBuZXcgUmFuZ2VFcnJvcjtpZihlPT09MClmb3IoO2ktLTspdGhpcy5wdXNoRnJvbnQocik7ZWxzZSBpZihlPT09dGhpcy5pKWZvcig7aS0tOyl0aGlzLnB1c2hCYWNrKHIpO2Vsc2Uge2xldCBuPVtdO2ZvcihsZXQgbz1lO288dGhpcy5pOysrbyluLnB1c2godGhpcy5nZXRFbGVtZW50QnlQb3MobykpO3RoaXMuY3V0KGUtMSk7Zm9yKGxldCBvPTA7bzxpOysrbyl0aGlzLnB1c2hCYWNrKHIpO2ZvcihsZXQgbz0wO288bi5sZW5ndGg7KytvKXRoaXMucHVzaEJhY2sobltvXSk7fXJldHVybiB0aGlzLml9Y3V0KGUpe2lmKGU8MClyZXR1cm4gdGhpcy5jbGVhcigpLDA7bGV0e2N1ck5vZGVCdWNrZXRJbmRleDpyLGN1ck5vZGVQb2ludGVySW5kZXg6aX09dGhpcy5PKGUpO3JldHVybiB0aGlzLlI9cix0aGlzLk49aSx0aGlzLmk9ZSsxLHRoaXMuaX1lcmFzZUVsZW1lbnRCeVBvcyhlKXtpZihlPDB8fGU+dGhpcy5pLTEpdGhyb3cgbmV3IFJhbmdlRXJyb3I7aWYoZT09PTApdGhpcy5wb3BGcm9udCgpO2Vsc2UgaWYoZT09PXRoaXMuaS0xKXRoaXMucG9wQmFjaygpO2Vsc2Uge2xldCByPVtdO2ZvcihsZXQgbj1lKzE7bjx0aGlzLmk7KytuKXIucHVzaCh0aGlzLmdldEVsZW1lbnRCeVBvcyhuKSk7dGhpcy5jdXQoZSksdGhpcy5wb3BCYWNrKCk7bGV0IGk9dGhpcztyLmZvckVhY2goZnVuY3Rpb24obil7aS5wdXNoQmFjayhuKTt9KTt9cmV0dXJuIHRoaXMuaX1lcmFzZUVsZW1lbnRCeVZhbHVlKGUpe2lmKHRoaXMuaT09PTApcmV0dXJuIDA7bGV0IHI9W107Zm9yKGxldCBuPTA7bjx0aGlzLmk7KytuKXtsZXQgbz10aGlzLmdldEVsZW1lbnRCeVBvcyhuKTtvIT09ZSYmci5wdXNoKG8pO31sZXQgaT1yLmxlbmd0aDtmb3IobGV0IG49MDtuPGk7KytuKXRoaXMuc2V0RWxlbWVudEJ5UG9zKG4scltuXSk7cmV0dXJuIHRoaXMuY3V0KGktMSl9ZXJhc2VFbGVtZW50QnlJdGVyYXRvcihlKXtsZXQgcj1lLm87cmV0dXJuIHRoaXMuZXJhc2VFbGVtZW50QnlQb3MociksZT1lLm5leHQoKSxlfWZpbmQoZSl7Zm9yKGxldCByPTA7cjx0aGlzLmk7KytyKWlmKHRoaXMuZ2V0RWxlbWVudEJ5UG9zKHIpPT09ZSlyZXR1cm4gbmV3IHZyKHIsdGhpcyk7cmV0dXJuIHRoaXMuZW5kKCl9cmV2ZXJzZSgpe2xldCBlPTAscj10aGlzLmktMTtmb3IoO2U8cjspe2xldCBpPXRoaXMuZ2V0RWxlbWVudEJ5UG9zKGUpO3RoaXMuc2V0RWxlbWVudEJ5UG9zKGUsdGhpcy5nZXRFbGVtZW50QnlQb3MocikpLHRoaXMuc2V0RWxlbWVudEJ5UG9zKHIsaSksZSs9MSxyLT0xO319dW5pcXVlKCl7aWYodGhpcy5pPD0xKXJldHVybiB0aGlzLmk7bGV0IGU9MSxyPXRoaXMuZ2V0RWxlbWVudEJ5UG9zKDApO2ZvcihsZXQgaT0xO2k8dGhpcy5pOysraSl7bGV0IG49dGhpcy5nZXRFbGVtZW50QnlQb3MoaSk7biE9PXImJihyPW4sdGhpcy5zZXRFbGVtZW50QnlQb3MoZSsrLG4pKTt9Zm9yKDt0aGlzLmk+ZTspdGhpcy5wb3BCYWNrKCk7cmV0dXJuIHRoaXMuaX1zb3J0KGUpe2xldCByPVtdO2ZvcihsZXQgaT0wO2k8dGhpcy5pOysraSlyLnB1c2godGhpcy5nZXRFbGVtZW50QnlQb3MoaSkpO3Iuc29ydChlKTtmb3IobGV0IGk9MDtpPHRoaXMuaTsrK2kpdGhpcy5zZXRFbGVtZW50QnlQb3MoaSxyW2ldKTt9c2hyaW5rVG9GaXQoKXtpZih0aGlzLmk9PT0wKXJldHVybjtsZXQgZT1bXTt0aGlzLmZvckVhY2goZnVuY3Rpb24ocil7ZS5wdXNoKHIpO30pLHRoaXMuUD1NYXRoLm1heChNYXRoLmNlaWwodGhpcy5pL3RoaXMuRiksMSksdGhpcy5pPXRoaXMuaj10aGlzLlI9dGhpcy5EPXRoaXMuTj0wLHRoaXMuQT1bXTtmb3IobGV0IHI9MDtyPHRoaXMuUDsrK3IpdGhpcy5BLnB1c2gobmV3IEFycmF5KHRoaXMuRikpO2ZvcihsZXQgcj0wO3I8ZS5sZW5ndGg7KytyKXRoaXMucHVzaEJhY2soZVtyXSk7fWZvckVhY2goZSl7Zm9yKGxldCByPTA7cjx0aGlzLmk7KytyKWUodGhpcy5nZXRFbGVtZW50QnlQb3Mocikscix0aGlzKTt9W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gZnVuY3Rpb24qKCl7Zm9yKGxldCBlPTA7ZTx0aGlzLmk7KytlKXlpZWxkIHRoaXMuZ2V0RWxlbWVudEJ5UG9zKGUpO30uYmluZCh0aGlzKSgpfX0sRDE9YmE7JG4uZGVmYXVsdD1EMTt9KTt2YXIgc3A9TShacj0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShacixcInRcIix7dmFsdWU6ITB9KTtaci5UcmVlTm9kZUVuYWJsZUluZGV4PVpyLlRyZWVOb2RlPXZvaWQgMDt2YXIgSG49Y2xhc3N7Y29uc3RydWN0b3IoZSxyKXt0aGlzLmVlPTEsdGhpcy51PXZvaWQgMCx0aGlzLmw9dm9pZCAwLHRoaXMuVT12b2lkIDAsdGhpcy5XPXZvaWQgMCx0aGlzLnR0PXZvaWQgMCx0aGlzLnU9ZSx0aGlzLmw9cjt9TCgpe2xldCBlPXRoaXM7aWYoZS5lZT09PTEmJmUudHQudHQ9PT1lKWU9ZS5XO2Vsc2UgaWYoZS5VKWZvcihlPWUuVTtlLlc7KWU9ZS5XO2Vsc2Uge2xldCByPWUudHQ7Zm9yKDtyLlU9PT1lOyllPXIscj1lLnR0O2U9cjt9cmV0dXJuIGV9Qigpe2xldCBlPXRoaXM7aWYoZS5XKXtmb3IoZT1lLlc7ZS5VOyllPWUuVTtyZXR1cm4gZX1lbHNlIHtsZXQgcj1lLnR0O2Zvcig7ci5XPT09ZTspZT1yLHI9ZS50dDtyZXR1cm4gZS5XIT09cj9yOmV9fXRlKCl7bGV0IGU9dGhpcy50dCxyPXRoaXMuVyxpPXIuVTtyZXR1cm4gZS50dD09PXRoaXM/ZS50dD1yOmUuVT09PXRoaXM/ZS5VPXI6ZS5XPXIsci50dD1lLHIuVT10aGlzLHRoaXMudHQ9cix0aGlzLlc9aSxpJiYoaS50dD10aGlzKSxyfXNlKCl7bGV0IGU9dGhpcy50dCxyPXRoaXMuVSxpPXIuVztyZXR1cm4gZS50dD09PXRoaXM/ZS50dD1yOmUuVT09PXRoaXM/ZS5VPXI6ZS5XPXIsci50dD1lLHIuVz10aGlzLHRoaXMudHQ9cix0aGlzLlU9aSxpJiYoaS50dD10aGlzKSxyfX07WnIuVHJlZU5vZGU9SG47dmFyIHdhPWNsYXNzIGV4dGVuZHMgSG57Y29uc3RydWN0b3IoKXtzdXBlciguLi5hcmd1bWVudHMpLHRoaXMucnQ9MTt9dGUoKXtsZXQgZT1zdXBlci50ZSgpO3JldHVybiB0aGlzLmllKCksZS5pZSgpLGV9c2UoKXtsZXQgZT1zdXBlci5zZSgpO3JldHVybiB0aGlzLmllKCksZS5pZSgpLGV9aWUoKXt0aGlzLnJ0PTEsdGhpcy5VJiYodGhpcy5ydCs9dGhpcy5VLnJ0KSx0aGlzLlcmJih0aGlzLnJ0Kz10aGlzLlcucnQpO319O1pyLlRyZWVOb2RlRW5hYmxlSW5kZXg9d2E7fSk7dmFyIG1hPU0oVm49Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoVm4sXCJ0XCIse3ZhbHVlOiEwfSk7Vm4uZGVmYXVsdD12b2lkIDA7dmFyIG9wPXNwKCksajE9YXQoKSxhcD1sdCgpLF9hPWNsYXNzIGV4dGVuZHMgajEuQ29udGFpbmVye2NvbnN0cnVjdG9yKGU9ZnVuY3Rpb24oaSxuKXtyZXR1cm4gaTxuPy0xOmk+bj8xOjB9LHI9ITEpe3N1cGVyKCksdGhpcy5ZPXZvaWQgMCx0aGlzLnY9ZSxyPyh0aGlzLnJlPW9wLlRyZWVOb2RlRW5hYmxlSW5kZXgsdGhpcy5NPWZ1bmN0aW9uKGksbixvKXtsZXQgcz10aGlzLm5lKGksbixvKTtpZihzKXtsZXQgYT1zLnR0O2Zvcig7YSE9PXRoaXMuaDspYS5ydCs9MSxhPWEudHQ7bGV0IHU9dGhpcy5oZShzKTtpZih1KXtsZXR7cGFyZW50Tm9kZTpjLGdyYW5kUGFyZW50OmgsY3VyTm9kZTpkfT11O2MuaWUoKSxoLmllKCksZC5pZSgpO319cmV0dXJuIHRoaXMuaX0sdGhpcy5WPWZ1bmN0aW9uKGkpe2xldCBuPXRoaXMuZmUoaSk7Zm9yKDtuIT09dGhpcy5oOyluLnJ0LT0xLG49bi50dDt9KToodGhpcy5yZT1vcC5UcmVlTm9kZSx0aGlzLk09ZnVuY3Rpb24oaSxuLG8pe2xldCBzPXRoaXMubmUoaSxuLG8pO3JldHVybiBzJiZ0aGlzLmhlKHMpLHRoaXMuaX0sdGhpcy5WPXRoaXMuZmUpLHRoaXMuaD1uZXcgdGhpcy5yZTt9WChlLHIpe2xldCBpPXRoaXMuaDtmb3IoO2U7KXtsZXQgbj10aGlzLnYoZS51LHIpO2lmKG48MCllPWUuVztlbHNlIGlmKG4+MClpPWUsZT1lLlU7ZWxzZSByZXR1cm4gZX1yZXR1cm4gaX1aKGUscil7bGV0IGk9dGhpcy5oO2Zvcig7ZTspdGhpcy52KGUudSxyKTw9MD9lPWUuVzooaT1lLGU9ZS5VKTtyZXR1cm4gaX0kKGUscil7bGV0IGk9dGhpcy5oO2Zvcig7ZTspe2xldCBuPXRoaXMudihlLnUscik7aWYobjwwKWk9ZSxlPWUuVztlbHNlIGlmKG4+MCllPWUuVTtlbHNlIHJldHVybiBlfXJldHVybiBpfXJyKGUscil7bGV0IGk9dGhpcy5oO2Zvcig7ZTspdGhpcy52KGUudSxyKTwwPyhpPWUsZT1lLlcpOmU9ZS5VO3JldHVybiBpfXVlKGUpe2Zvcig7Oyl7bGV0IHI9ZS50dDtpZihyPT09dGhpcy5oKXJldHVybjtpZihlLmVlPT09MSl7ZS5lZT0wO3JldHVybn1pZihlPT09ci5VKXtsZXQgaT1yLlc7aWYoaS5lZT09PTEpaS5lZT0wLHIuZWU9MSxyPT09dGhpcy5ZP3RoaXMuWT1yLnRlKCk6ci50ZSgpO2Vsc2UgaWYoaS5XJiZpLlcuZWU9PT0xKXtpLmVlPXIuZWUsci5lZT0wLGkuVy5lZT0wLHI9PT10aGlzLlk/dGhpcy5ZPXIudGUoKTpyLnRlKCk7cmV0dXJufWVsc2UgaS5VJiZpLlUuZWU9PT0xPyhpLmVlPTEsaS5VLmVlPTAsaS5zZSgpKTooaS5lZT0xLGU9cik7fWVsc2Uge2xldCBpPXIuVTtpZihpLmVlPT09MSlpLmVlPTAsci5lZT0xLHI9PT10aGlzLlk/dGhpcy5ZPXIuc2UoKTpyLnNlKCk7ZWxzZSBpZihpLlUmJmkuVS5lZT09PTEpe2kuZWU9ci5lZSxyLmVlPTAsaS5VLmVlPTAscj09PXRoaXMuWT90aGlzLlk9ci5zZSgpOnIuc2UoKTtyZXR1cm59ZWxzZSBpLlcmJmkuVy5lZT09PTE/KGkuZWU9MSxpLlcuZWU9MCxpLnRlKCkpOihpLmVlPTEsZT1yKTt9fX1mZShlKXtpZih0aGlzLmk9PT0xKXJldHVybiB0aGlzLmNsZWFyKCksdGhpcy5oO2xldCByPWU7Zm9yKDtyLlV8fHIuVzspe2lmKHIuVylmb3Iocj1yLlc7ci5VOylyPXIuVTtlbHNlIHI9ci5VO1tlLnUsci51XT1bci51LGUudV0sW2UubCxyLmxdPVtyLmwsZS5sXSxlPXI7fXRoaXMuaC5VPT09cj90aGlzLmguVT1yLnR0OnRoaXMuaC5XPT09ciYmKHRoaXMuaC5XPXIudHQpLHRoaXMudWUocik7bGV0IGk9ci50dDtyZXR1cm4gcj09PWkuVT9pLlU9dm9pZCAwOmkuVz12b2lkIDAsdGhpcy5pLT0xLHRoaXMuWS5lZT0wLGl9b2UoZSxyKXtyZXR1cm4gZT09PXZvaWQgMD8hMTp0aGlzLm9lKGUuVSxyKXx8cihlKT8hMDp0aGlzLm9lKGUuVyxyKX1oZShlKXtmb3IoOzspe2xldCByPWUudHQ7aWYoci5lZT09PTApcmV0dXJuO2xldCBpPXIudHQ7aWYocj09PWkuVSl7bGV0IG49aS5XO2lmKG4mJm4uZWU9PT0xKXtpZihuLmVlPXIuZWU9MCxpPT09dGhpcy5ZKXJldHVybjtpLmVlPTEsZT1pO2NvbnRpbnVlfWVsc2UgaWYoZT09PXIuVyl7aWYoZS5lZT0wLGUuVSYmKGUuVS50dD1yKSxlLlcmJihlLlcudHQ9aSksci5XPWUuVSxpLlU9ZS5XLGUuVT1yLGUuVz1pLGk9PT10aGlzLlkpdGhpcy5ZPWUsdGhpcy5oLnR0PWU7ZWxzZSB7bGV0IG89aS50dDtvLlU9PT1pP28uVT1lOm8uVz1lO31yZXR1cm4gZS50dD1pLnR0LHIudHQ9ZSxpLnR0PWUsaS5lZT0xLHtwYXJlbnROb2RlOnIsZ3JhbmRQYXJlbnQ6aSxjdXJOb2RlOmV9fWVsc2Ugci5lZT0wLGk9PT10aGlzLlk/dGhpcy5ZPWkuc2UoKTppLnNlKCksaS5lZT0xO31lbHNlIHtsZXQgbj1pLlU7aWYobiYmbi5lZT09PTEpe2lmKG4uZWU9ci5lZT0wLGk9PT10aGlzLlkpcmV0dXJuO2kuZWU9MSxlPWk7Y29udGludWV9ZWxzZSBpZihlPT09ci5VKXtpZihlLmVlPTAsZS5VJiYoZS5VLnR0PWkpLGUuVyYmKGUuVy50dD1yKSxpLlc9ZS5VLHIuVT1lLlcsZS5VPWksZS5XPXIsaT09PXRoaXMuWSl0aGlzLlk9ZSx0aGlzLmgudHQ9ZTtlbHNlIHtsZXQgbz1pLnR0O28uVT09PWk/by5VPWU6by5XPWU7fXJldHVybiBlLnR0PWkudHQsci50dD1lLGkudHQ9ZSxpLmVlPTEse3BhcmVudE5vZGU6cixncmFuZFBhcmVudDppLGN1ck5vZGU6ZX19ZWxzZSByLmVlPTAsaT09PXRoaXMuWT90aGlzLlk9aS50ZSgpOmkudGUoKSxpLmVlPTE7fXJldHVybn19bmUoZSxyLGkpe2lmKHRoaXMuWT09PXZvaWQgMCl7dGhpcy5pKz0xLHRoaXMuWT1uZXcgdGhpcy5yZShlLHIpLHRoaXMuWS5lZT0wLHRoaXMuWS50dD10aGlzLmgsdGhpcy5oLnR0PXRoaXMuWSx0aGlzLmguVT10aGlzLlksdGhpcy5oLlc9dGhpcy5ZO3JldHVybn1sZXQgbixvPXRoaXMuaC5VLHM9dGhpcy52KG8udSxlKTtpZihzPT09MCl7by5sPXI7cmV0dXJufWVsc2UgaWYocz4wKW8uVT1uZXcgdGhpcy5yZShlLHIpLG8uVS50dD1vLG49by5VLHRoaXMuaC5VPW47ZWxzZSB7bGV0IGE9dGhpcy5oLlcsdT10aGlzLnYoYS51LGUpO2lmKHU9PT0wKXthLmw9cjtyZXR1cm59ZWxzZSBpZih1PDApYS5XPW5ldyB0aGlzLnJlKGUsciksYS5XLnR0PWEsbj1hLlcsdGhpcy5oLlc9bjtlbHNlIHtpZihpIT09dm9pZCAwKXtsZXQgYz1pLm87aWYoYyE9PXRoaXMuaCl7bGV0IGg9dGhpcy52KGMudSxlKTtpZihoPT09MCl7Yy5sPXI7cmV0dXJufWVsc2UgaWYoaD4wKXtsZXQgZD1jLkwoKSxnPXRoaXMudihkLnUsZSk7aWYoZz09PTApe2QubD1yO3JldHVybn1lbHNlIGc8MCYmKG49bmV3IHRoaXMucmUoZSxyKSxkLlc9PT12b2lkIDA/KGQuVz1uLG4udHQ9ZCk6KGMuVT1uLG4udHQ9YykpO319fWlmKG49PT12b2lkIDApZm9yKG49dGhpcy5ZOzspe2xldCBjPXRoaXMudihuLnUsZSk7aWYoYz4wKXtpZihuLlU9PT12b2lkIDApe24uVT1uZXcgdGhpcy5yZShlLHIpLG4uVS50dD1uLG49bi5VO2JyZWFrfW49bi5VO31lbHNlIGlmKGM8MCl7aWYobi5XPT09dm9pZCAwKXtuLlc9bmV3IHRoaXMucmUoZSxyKSxuLlcudHQ9bixuPW4uVzticmVha31uPW4uVzt9ZWxzZSB7bi5sPXI7cmV0dXJufX19fXJldHVybiB0aGlzLmkrPTEsbn1JKGUscil7Zm9yKDtlOyl7bGV0IGk9dGhpcy52KGUudSxyKTtpZihpPDApZT1lLlc7ZWxzZSBpZihpPjApZT1lLlU7ZWxzZSByZXR1cm4gZX1yZXR1cm4gZXx8dGhpcy5ofWNsZWFyKCl7dGhpcy5pPTAsdGhpcy5ZPXZvaWQgMCx0aGlzLmgudHQ9dm9pZCAwLHRoaXMuaC5VPXRoaXMuaC5XPXZvaWQgMDt9dXBkYXRlS2V5QnlJdGVyYXRvcihlLHIpe2xldCBpPWUubztpZihpPT09dGhpcy5oJiYoMCwgYXAudGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpLHRoaXMuaT09PTEpcmV0dXJuIGkudT1yLCEwO2lmKGk9PT10aGlzLmguVSlyZXR1cm4gdGhpcy52KGkuQigpLnUscik+MD8oaS51PXIsITApOiExO2lmKGk9PT10aGlzLmguVylyZXR1cm4gdGhpcy52KGkuTCgpLnUscik8MD8oaS51PXIsITApOiExO2xldCBuPWkuTCgpLnU7aWYodGhpcy52KG4scik+PTApcmV0dXJuICExO2xldCBvPWkuQigpLnU7cmV0dXJuIHRoaXMudihvLHIpPD0wPyExOihpLnU9ciwhMCl9ZXJhc2VFbGVtZW50QnlQb3MoZSl7aWYoZTwwfHxlPnRoaXMuaS0xKXRocm93IG5ldyBSYW5nZUVycm9yO2xldCByPTAsaT10aGlzO3JldHVybiB0aGlzLm9lKHRoaXMuWSxmdW5jdGlvbihuKXtyZXR1cm4gZT09PXI/KGkuVihuKSwhMCk6KHIrPTEsITEpfSksdGhpcy5pfWVyYXNlRWxlbWVudEJ5S2V5KGUpe2lmKHRoaXMuaT09PTApcmV0dXJuICExO2xldCByPXRoaXMuSSh0aGlzLlksZSk7cmV0dXJuIHI9PT10aGlzLmg/ITE6KHRoaXMuVihyKSwhMCl9ZXJhc2VFbGVtZW50QnlJdGVyYXRvcihlKXtsZXQgcj1lLm87cj09PXRoaXMuaCYmKDAsIGFwLnRocm93SXRlcmF0b3JBY2Nlc3NFcnJvcikoKTtsZXQgaT1yLlc9PT12b2lkIDA7cmV0dXJuIGUuaXRlcmF0b3JUeXBlPT09MD9pJiZlLm5leHQoKTooIWl8fHIuVT09PXZvaWQgMCkmJmUubmV4dCgpLHRoaXMuVihyKSxlfWZvckVhY2goZSl7bGV0IHI9MDtmb3IobGV0IGkgb2YgdGhpcyllKGkscisrLHRoaXMpO31nZXRFbGVtZW50QnlQb3MoZSl7aWYoZTwwfHxlPnRoaXMuaS0xKXRocm93IG5ldyBSYW5nZUVycm9yO2xldCByLGk9MDtmb3IobGV0IG4gb2YgdGhpcyl7aWYoaT09PWUpe3I9bjticmVha31pKz0xO31yZXR1cm4gcn1nZXRIZWlnaHQoKXtpZih0aGlzLmk9PT0wKXJldHVybiAwO2xldCBlPWZ1bmN0aW9uKHIpe3JldHVybiByP01hdGgubWF4KGUoci5VKSxlKHIuVykpKzE6MH07cmV0dXJuIGUodGhpcy5ZKX19LEYxPV9hO1ZuLmRlZmF1bHQ9RjE7fSk7dmFyIEVhPU0oS249Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoS24sXCJ0XCIse3ZhbHVlOiEwfSk7S24uZGVmYXVsdD12b2lkIDA7dmFyIFcxPWF0KCksem49bHQoKSx2YT1jbGFzcyBleHRlbmRzIFcxLkNvbnRhaW5lckl0ZXJhdG9ye2NvbnN0cnVjdG9yKGUscixpKXtzdXBlcihpKSx0aGlzLm89ZSx0aGlzLmg9cix0aGlzLml0ZXJhdG9yVHlwZT09PTA/KHRoaXMucHJlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubz09PXRoaXMuaC5VJiYoMCwgem4udGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpLHRoaXMubz10aGlzLm8uTCgpLHRoaXN9LHRoaXMubmV4dD1mdW5jdGlvbigpe3JldHVybiB0aGlzLm89PT10aGlzLmgmJigwLCB6bi50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vPXRoaXMuby5CKCksdGhpc30pOih0aGlzLnByZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLm89PT10aGlzLmguVyYmKDAsIHpuLnRocm93SXRlcmF0b3JBY2Nlc3NFcnJvcikoKSx0aGlzLm89dGhpcy5vLkIoKSx0aGlzfSx0aGlzLm5leHQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5vPT09dGhpcy5oJiYoMCwgem4udGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpLHRoaXMubz10aGlzLm8uTCgpLHRoaXN9KTt9Z2V0IGluZGV4KCl7bGV0IGU9dGhpcy5vLHI9dGhpcy5oLnR0O2lmKGU9PT10aGlzLmgpcmV0dXJuIHI/ci5ydC0xOjA7bGV0IGk9MDtmb3IoZS5VJiYoaSs9ZS5VLnJ0KTtlIT09cjspe2xldCBuPWUudHQ7ZT09PW4uVyYmKGkrPTEsbi5VJiYoaSs9bi5VLnJ0KSksZT1uO31yZXR1cm4gaX19LCQxPXZhO0tuLmRlZmF1bHQ9JDE7fSk7dmFyIHVwPU0oR249Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoR24sXCJ0XCIse3ZhbHVlOiEwfSk7R24uZGVmYXVsdD12b2lkIDA7dmFyIEgxPWxwKG1hKCkpLFYxPWxwKEVhKCkpLHoxPWx0KCk7ZnVuY3Rpb24gbHAodCl7cmV0dXJuIHQmJnQudD90OntkZWZhdWx0OnR9fXZhciBLZT1jbGFzcyB0IGV4dGVuZHMgVjEuZGVmYXVsdHtjb25zdHJ1Y3RvcihlLHIsaSxuKXtzdXBlcihlLHIsbiksdGhpcy5jb250YWluZXI9aTt9Z2V0IHBvaW50ZXIoKXtyZXR1cm4gdGhpcy5vPT09dGhpcy5oJiYoMCwgejEudGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpLHRoaXMuby51fWNvcHkoKXtyZXR1cm4gbmV3IHQodGhpcy5vLHRoaXMuaCx0aGlzLmNvbnRhaW5lcix0aGlzLml0ZXJhdG9yVHlwZSl9fSxTYT1jbGFzcyBleHRlbmRzIEgxLmRlZmF1bHR7Y29uc3RydWN0b3IoZT1bXSxyLGkpe3N1cGVyKHIsaSk7bGV0IG49dGhpcztlLmZvckVhY2goZnVuY3Rpb24obyl7bi5pbnNlcnQobyk7fSk7fSpLKGUpe2UhPT12b2lkIDAmJih5aWVsZCp0aGlzLksoZS5VKSx5aWVsZCBlLnUseWllbGQqdGhpcy5LKGUuVykpO31iZWdpbigpe3JldHVybiBuZXcgS2UodGhpcy5oLlV8fHRoaXMuaCx0aGlzLmgsdGhpcyl9ZW5kKCl7cmV0dXJuIG5ldyBLZSh0aGlzLmgsdGhpcy5oLHRoaXMpfXJCZWdpbigpe3JldHVybiBuZXcgS2UodGhpcy5oLld8fHRoaXMuaCx0aGlzLmgsdGhpcywxKX1yRW5kKCl7cmV0dXJuIG5ldyBLZSh0aGlzLmgsdGhpcy5oLHRoaXMsMSl9ZnJvbnQoKXtyZXR1cm4gdGhpcy5oLlU/dGhpcy5oLlUudTp2b2lkIDB9YmFjaygpe3JldHVybiB0aGlzLmguVz90aGlzLmguVy51OnZvaWQgMH1pbnNlcnQoZSxyKXtyZXR1cm4gdGhpcy5NKGUsdm9pZCAwLHIpfWZpbmQoZSl7bGV0IHI9dGhpcy5JKHRoaXMuWSxlKTtyZXR1cm4gbmV3IEtlKHIsdGhpcy5oLHRoaXMpfWxvd2VyQm91bmQoZSl7bGV0IHI9dGhpcy5YKHRoaXMuWSxlKTtyZXR1cm4gbmV3IEtlKHIsdGhpcy5oLHRoaXMpfXVwcGVyQm91bmQoZSl7bGV0IHI9dGhpcy5aKHRoaXMuWSxlKTtyZXR1cm4gbmV3IEtlKHIsdGhpcy5oLHRoaXMpfXJldmVyc2VMb3dlckJvdW5kKGUpe2xldCByPXRoaXMuJCh0aGlzLlksZSk7cmV0dXJuIG5ldyBLZShyLHRoaXMuaCx0aGlzKX1yZXZlcnNlVXBwZXJCb3VuZChlKXtsZXQgcj10aGlzLnJyKHRoaXMuWSxlKTtyZXR1cm4gbmV3IEtlKHIsdGhpcy5oLHRoaXMpfXVuaW9uKGUpe2xldCByPXRoaXM7cmV0dXJuIGUuZm9yRWFjaChmdW5jdGlvbihpKXtyLmluc2VydChpKTt9KSx0aGlzLml9W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gdGhpcy5LKHRoaXMuWSl9fSxLMT1TYTtHbi5kZWZhdWx0PUsxO30pO3ZhciBjcD1NKFFuPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KFFuLFwidFwiLHt2YWx1ZTohMH0pO1FuLmRlZmF1bHQ9dm9pZCAwO3ZhciBHMT1mcChtYSgpKSxRMT1mcChFYSgpKSxZMT1sdCgpO2Z1bmN0aW9uIGZwKHQpe3JldHVybiB0JiZ0LnQ/dDp7ZGVmYXVsdDp0fX12YXIgR2U9Y2xhc3MgdCBleHRlbmRzIFExLmRlZmF1bHR7Y29uc3RydWN0b3IoZSxyLGksbil7c3VwZXIoZSxyLG4pLHRoaXMuY29udGFpbmVyPWk7fWdldCBwb2ludGVyKCl7dGhpcy5vPT09dGhpcy5oJiYoMCwgWTEudGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpO2xldCBlPXRoaXM7cmV0dXJuIG5ldyBQcm94eShbXSx7Z2V0KHIsaSl7aWYoaT09PVwiMFwiKXJldHVybiBlLm8udTtpZihpPT09XCIxXCIpcmV0dXJuIGUuby5sfSxzZXQocixpLG4pe2lmKGkhPT1cIjFcIil0aHJvdyBuZXcgVHlwZUVycm9yKFwicHJvcHMgbXVzdCBiZSAxXCIpO3JldHVybiBlLm8ubD1uLCEwfX0pfWNvcHkoKXtyZXR1cm4gbmV3IHQodGhpcy5vLHRoaXMuaCx0aGlzLmNvbnRhaW5lcix0aGlzLml0ZXJhdG9yVHlwZSl9fSxBYT1jbGFzcyBleHRlbmRzIEcxLmRlZmF1bHR7Y29uc3RydWN0b3IoZT1bXSxyLGkpe3N1cGVyKHIsaSk7bGV0IG49dGhpcztlLmZvckVhY2goZnVuY3Rpb24obyl7bi5zZXRFbGVtZW50KG9bMF0sb1sxXSk7fSk7fSpLKGUpe2UhPT12b2lkIDAmJih5aWVsZCp0aGlzLksoZS5VKSx5aWVsZCBbZS51LGUubF0seWllbGQqdGhpcy5LKGUuVykpO31iZWdpbigpe3JldHVybiBuZXcgR2UodGhpcy5oLlV8fHRoaXMuaCx0aGlzLmgsdGhpcyl9ZW5kKCl7cmV0dXJuIG5ldyBHZSh0aGlzLmgsdGhpcy5oLHRoaXMpfXJCZWdpbigpe3JldHVybiBuZXcgR2UodGhpcy5oLld8fHRoaXMuaCx0aGlzLmgsdGhpcywxKX1yRW5kKCl7cmV0dXJuIG5ldyBHZSh0aGlzLmgsdGhpcy5oLHRoaXMsMSl9ZnJvbnQoKXtpZih0aGlzLmk9PT0wKXJldHVybjtsZXQgZT10aGlzLmguVTtyZXR1cm4gW2UudSxlLmxdfWJhY2soKXtpZih0aGlzLmk9PT0wKXJldHVybjtsZXQgZT10aGlzLmguVztyZXR1cm4gW2UudSxlLmxdfWxvd2VyQm91bmQoZSl7bGV0IHI9dGhpcy5YKHRoaXMuWSxlKTtyZXR1cm4gbmV3IEdlKHIsdGhpcy5oLHRoaXMpfXVwcGVyQm91bmQoZSl7bGV0IHI9dGhpcy5aKHRoaXMuWSxlKTtyZXR1cm4gbmV3IEdlKHIsdGhpcy5oLHRoaXMpfXJldmVyc2VMb3dlckJvdW5kKGUpe2xldCByPXRoaXMuJCh0aGlzLlksZSk7cmV0dXJuIG5ldyBHZShyLHRoaXMuaCx0aGlzKX1yZXZlcnNlVXBwZXJCb3VuZChlKXtsZXQgcj10aGlzLnJyKHRoaXMuWSxlKTtyZXR1cm4gbmV3IEdlKHIsdGhpcy5oLHRoaXMpfXNldEVsZW1lbnQoZSxyLGkpe3JldHVybiB0aGlzLk0oZSxyLGkpfWZpbmQoZSl7bGV0IHI9dGhpcy5JKHRoaXMuWSxlKTtyZXR1cm4gbmV3IEdlKHIsdGhpcy5oLHRoaXMpfWdldEVsZW1lbnRCeUtleShlKXtyZXR1cm4gdGhpcy5JKHRoaXMuWSxlKS5sfXVuaW9uKGUpe2xldCByPXRoaXM7cmV0dXJuIGUuZm9yRWFjaChmdW5jdGlvbihpKXtyLnNldEVsZW1lbnQoaVswXSxpWzFdKTt9KSx0aGlzLml9W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gdGhpcy5LKHRoaXMuWSl9fSxKMT1BYTtRbi5kZWZhdWx0PUoxO30pO3ZhciBUYT1NKElhPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KElhLFwidFwiLHt2YWx1ZTohMH0pO0lhLmRlZmF1bHQ9WDE7ZnVuY3Rpb24gWDEodCl7bGV0IGU9dHlwZW9mIHQ7cmV0dXJuIGU9PT1cIm9iamVjdFwiJiZ0IT09bnVsbHx8ZT09PVwiZnVuY3Rpb25cIn19KTt2YXIgUGE9TShlaT0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShlaSxcInRcIix7dmFsdWU6ITB9KTtlaS5IYXNoQ29udGFpbmVySXRlcmF0b3I9ZWkuSGFzaENvbnRhaW5lcj12b2lkIDA7dmFyIGhwPWF0KCksUmE9WjEoVGEoKSksVGk9bHQoKTtmdW5jdGlvbiBaMSh0KXtyZXR1cm4gdCYmdC50P3Q6e2RlZmF1bHQ6dH19dmFyIENhPWNsYXNzIGV4dGVuZHMgaHAuQ29udGFpbmVySXRlcmF0b3J7Y29uc3RydWN0b3IoZSxyLGkpe3N1cGVyKGkpLHRoaXMubz1lLHRoaXMuaD1yLHRoaXMuaXRlcmF0b3JUeXBlPT09MD8odGhpcy5wcmU9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5vLkw9PT10aGlzLmgmJigwLCBUaS50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vPXRoaXMuby5MLHRoaXN9LHRoaXMubmV4dD1mdW5jdGlvbigpe3JldHVybiB0aGlzLm89PT10aGlzLmgmJigwLCBUaS50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vPXRoaXMuby5CLHRoaXN9KToodGhpcy5wcmU9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5vLkI9PT10aGlzLmgmJigwLCBUaS50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vPXRoaXMuby5CLHRoaXN9LHRoaXMubmV4dD1mdW5jdGlvbigpe3JldHVybiB0aGlzLm89PT10aGlzLmgmJigwLCBUaS50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vPXRoaXMuby5MLHRoaXN9KTt9fTtlaS5IYXNoQ29udGFpbmVySXRlcmF0b3I9Q2E7dmFyIEJhPWNsYXNzIGV4dGVuZHMgaHAuQ29udGFpbmVye2NvbnN0cnVjdG9yKCl7c3VwZXIoKSx0aGlzLkg9W10sdGhpcy5nPXt9LHRoaXMuSEFTSF9UQUc9U3ltYm9sKFwiQEBIQVNIX1RBR1wiKSxPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcy5nLG51bGwpLHRoaXMuaD17fSx0aGlzLmguTD10aGlzLmguQj10aGlzLnA9dGhpcy5fPXRoaXMuaDt9VihlKXtsZXR7TDpyLEI6aX09ZTtyLkI9aSxpLkw9cixlPT09dGhpcy5wJiYodGhpcy5wPWkpLGU9PT10aGlzLl8mJih0aGlzLl89ciksdGhpcy5pLT0xO31NKGUscixpKXtpPT09dm9pZCAwJiYoaT0oMCwgUmEuZGVmYXVsdCkoZSkpO2xldCBuO2lmKGkpe2xldCBvPWVbdGhpcy5IQVNIX1RBR107aWYobyE9PXZvaWQgMClyZXR1cm4gdGhpcy5IW29dLmw9cix0aGlzLmk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGUsdGhpcy5IQVNIX1RBRyx7dmFsdWU6dGhpcy5ILmxlbmd0aCxjb25maWd1cmFibGU6ITB9KSxuPXt1OmUsbDpyLEw6dGhpcy5fLEI6dGhpcy5ofSx0aGlzLkgucHVzaChuKTt9ZWxzZSB7bGV0IG89dGhpcy5nW2VdO2lmKG8pcmV0dXJuIG8ubD1yLHRoaXMuaTtuPXt1OmUsbDpyLEw6dGhpcy5fLEI6dGhpcy5ofSx0aGlzLmdbZV09bjt9cmV0dXJuIHRoaXMuaT09PTA/KHRoaXMucD1uLHRoaXMuaC5CPW4pOnRoaXMuXy5CPW4sdGhpcy5fPW4sdGhpcy5oLkw9biwrK3RoaXMuaX1JKGUscil7aWYocj09PXZvaWQgMCYmKHI9KDAsIFJhLmRlZmF1bHQpKGUpKSxyKXtsZXQgaT1lW3RoaXMuSEFTSF9UQUddO3JldHVybiBpPT09dm9pZCAwP3RoaXMuaDp0aGlzLkhbaV19ZWxzZSByZXR1cm4gdGhpcy5nW2VdfHx0aGlzLmh9Y2xlYXIoKXtsZXQgZT10aGlzLkhBU0hfVEFHO3RoaXMuSC5mb3JFYWNoKGZ1bmN0aW9uKHIpe2RlbGV0ZSByLnVbZV07fSksdGhpcy5IPVtdLHRoaXMuZz17fSxPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcy5nLG51bGwpLHRoaXMuaT0wLHRoaXMucD10aGlzLl89dGhpcy5oLkw9dGhpcy5oLkI9dGhpcy5oO31lcmFzZUVsZW1lbnRCeUtleShlLHIpe2xldCBpO2lmKHI9PT12b2lkIDAmJihyPSgwLCBSYS5kZWZhdWx0KShlKSkscil7bGV0IG49ZVt0aGlzLkhBU0hfVEFHXTtpZihuPT09dm9pZCAwKXJldHVybiAhMTtkZWxldGUgZVt0aGlzLkhBU0hfVEFHXSxpPXRoaXMuSFtuXSxkZWxldGUgdGhpcy5IW25dO31lbHNlIHtpZihpPXRoaXMuZ1tlXSxpPT09dm9pZCAwKXJldHVybiAhMTtkZWxldGUgdGhpcy5nW2VdO31yZXR1cm4gdGhpcy5WKGkpLCEwfWVyYXNlRWxlbWVudEJ5SXRlcmF0b3IoZSl7bGV0IHI9ZS5vO3JldHVybiByPT09dGhpcy5oJiYoMCwgVGkudGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpLHRoaXMuVihyKSxlLm5leHQoKX1lcmFzZUVsZW1lbnRCeVBvcyhlKXtpZihlPDB8fGU+dGhpcy5pLTEpdGhyb3cgbmV3IFJhbmdlRXJyb3I7bGV0IHI9dGhpcy5wO2Zvcig7ZS0tOylyPXIuQjtyZXR1cm4gdGhpcy5WKHIpLHRoaXMuaX19O2VpLkhhc2hDb250YWluZXI9QmE7fSk7dmFyIHBwPU0oWW49Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoWW4sXCJ0XCIse3ZhbHVlOiEwfSk7WW4uZGVmYXVsdD12b2lkIDA7dmFyIGRwPVBhKCksZXY9bHQoKSxFcj1jbGFzcyB0IGV4dGVuZHMgZHAuSGFzaENvbnRhaW5lckl0ZXJhdG9ye2NvbnN0cnVjdG9yKGUscixpLG4pe3N1cGVyKGUscixuKSx0aGlzLmNvbnRhaW5lcj1pO31nZXQgcG9pbnRlcigpe3JldHVybiB0aGlzLm89PT10aGlzLmgmJigwLCBldi50aHJvd0l0ZXJhdG9yQWNjZXNzRXJyb3IpKCksdGhpcy5vLnV9Y29weSgpe3JldHVybiBuZXcgdCh0aGlzLm8sdGhpcy5oLHRoaXMuY29udGFpbmVyLHRoaXMuaXRlcmF0b3JUeXBlKX19LE9hPWNsYXNzIGV4dGVuZHMgZHAuSGFzaENvbnRhaW5lcntjb25zdHJ1Y3RvcihlPVtdKXtzdXBlcigpO2xldCByPXRoaXM7ZS5mb3JFYWNoKGZ1bmN0aW9uKGkpe3IuaW5zZXJ0KGkpO30pO31iZWdpbigpe3JldHVybiBuZXcgRXIodGhpcy5wLHRoaXMuaCx0aGlzKX1lbmQoKXtyZXR1cm4gbmV3IEVyKHRoaXMuaCx0aGlzLmgsdGhpcyl9ckJlZ2luKCl7cmV0dXJuIG5ldyBFcih0aGlzLl8sdGhpcy5oLHRoaXMsMSl9ckVuZCgpe3JldHVybiBuZXcgRXIodGhpcy5oLHRoaXMuaCx0aGlzLDEpfWZyb250KCl7cmV0dXJuIHRoaXMucC51fWJhY2soKXtyZXR1cm4gdGhpcy5fLnV9aW5zZXJ0KGUscil7cmV0dXJuIHRoaXMuTShlLHZvaWQgMCxyKX1nZXRFbGVtZW50QnlQb3MoZSl7aWYoZTwwfHxlPnRoaXMuaS0xKXRocm93IG5ldyBSYW5nZUVycm9yO2xldCByPXRoaXMucDtmb3IoO2UtLTspcj1yLkI7cmV0dXJuIHIudX1maW5kKGUscil7bGV0IGk9dGhpcy5JKGUscik7cmV0dXJuIG5ldyBFcihpLHRoaXMuaCx0aGlzKX1mb3JFYWNoKGUpe2xldCByPTAsaT10aGlzLnA7Zm9yKDtpIT09dGhpcy5oOyllKGkudSxyKyssdGhpcyksaT1pLkI7fVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIGZ1bmN0aW9uKigpe2xldCBlPXRoaXMucDtmb3IoO2UhPT10aGlzLmg7KXlpZWxkIGUudSxlPWUuQjt9LmJpbmQodGhpcykoKX19LHR2PU9hO1luLmRlZmF1bHQ9dHY7fSk7dmFyIHlwPU0oSm49Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoSm4sXCJ0XCIse3ZhbHVlOiEwfSk7Sm4uZGVmYXVsdD12b2lkIDA7dmFyIGdwPVBhKCkscnY9bnYoVGEoKSksaXY9bHQoKTtmdW5jdGlvbiBudih0KXtyZXR1cm4gdCYmdC50P3Q6e2RlZmF1bHQ6dH19dmFyIFNyPWNsYXNzIHQgZXh0ZW5kcyBncC5IYXNoQ29udGFpbmVySXRlcmF0b3J7Y29uc3RydWN0b3IoZSxyLGksbil7c3VwZXIoZSxyLG4pLHRoaXMuY29udGFpbmVyPWk7fWdldCBwb2ludGVyKCl7dGhpcy5vPT09dGhpcy5oJiYoMCwgaXYudGhyb3dJdGVyYXRvckFjY2Vzc0Vycm9yKSgpO2xldCBlPXRoaXM7cmV0dXJuIG5ldyBQcm94eShbXSx7Z2V0KHIsaSl7aWYoaT09PVwiMFwiKXJldHVybiBlLm8udTtpZihpPT09XCIxXCIpcmV0dXJuIGUuby5sfSxzZXQocixpLG4pe2lmKGkhPT1cIjFcIil0aHJvdyBuZXcgVHlwZUVycm9yKFwicHJvcHMgbXVzdCBiZSAxXCIpO3JldHVybiBlLm8ubD1uLCEwfX0pfWNvcHkoKXtyZXR1cm4gbmV3IHQodGhpcy5vLHRoaXMuaCx0aGlzLmNvbnRhaW5lcix0aGlzLml0ZXJhdG9yVHlwZSl9fSxrYT1jbGFzcyBleHRlbmRzIGdwLkhhc2hDb250YWluZXJ7Y29uc3RydWN0b3IoZT1bXSl7c3VwZXIoKTtsZXQgcj10aGlzO2UuZm9yRWFjaChmdW5jdGlvbihpKXtyLnNldEVsZW1lbnQoaVswXSxpWzFdKTt9KTt9YmVnaW4oKXtyZXR1cm4gbmV3IFNyKHRoaXMucCx0aGlzLmgsdGhpcyl9ZW5kKCl7cmV0dXJuIG5ldyBTcih0aGlzLmgsdGhpcy5oLHRoaXMpfXJCZWdpbigpe3JldHVybiBuZXcgU3IodGhpcy5fLHRoaXMuaCx0aGlzLDEpfXJFbmQoKXtyZXR1cm4gbmV3IFNyKHRoaXMuaCx0aGlzLmgsdGhpcywxKX1mcm9udCgpe2lmKHRoaXMuaSE9PTApcmV0dXJuIFt0aGlzLnAudSx0aGlzLnAubF19YmFjaygpe2lmKHRoaXMuaSE9PTApcmV0dXJuIFt0aGlzLl8udSx0aGlzLl8ubF19c2V0RWxlbWVudChlLHIsaSl7cmV0dXJuIHRoaXMuTShlLHIsaSl9Z2V0RWxlbWVudEJ5S2V5KGUscil7aWYocj09PXZvaWQgMCYmKHI9KDAsIHJ2LmRlZmF1bHQpKGUpKSxyKXtsZXQgbj1lW3RoaXMuSEFTSF9UQUddO3JldHVybiBuIT09dm9pZCAwP3RoaXMuSFtuXS5sOnZvaWQgMH1sZXQgaT10aGlzLmdbZV07cmV0dXJuIGk/aS5sOnZvaWQgMH1nZXRFbGVtZW50QnlQb3MoZSl7aWYoZTwwfHxlPnRoaXMuaS0xKXRocm93IG5ldyBSYW5nZUVycm9yO2xldCByPXRoaXMucDtmb3IoO2UtLTspcj1yLkI7cmV0dXJuIFtyLnUsci5sXX1maW5kKGUscil7bGV0IGk9dGhpcy5JKGUscik7cmV0dXJuIG5ldyBTcihpLHRoaXMuaCx0aGlzKX1mb3JFYWNoKGUpe2xldCByPTAsaT10aGlzLnA7Zm9yKDtpIT09dGhpcy5oOyllKFtpLnUsaS5sXSxyKyssdGhpcyksaT1pLkI7fVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIGZ1bmN0aW9uKigpe2xldCBlPXRoaXMucDtmb3IoO2UhPT10aGlzLmg7KXlpZWxkIFtlLnUsZS5sXSxlPWUuQjt9LmJpbmQodGhpcykoKX19LHN2PWthO0puLmRlZmF1bHQ9c3Y7fSk7dmFyIGJwPU0oamU9Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoamUsXCJ0XCIse3ZhbHVlOiEwfSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGplLFwiRGVxdWVcIix7ZW51bWVyYWJsZTohMCxnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gY3YuZGVmYXVsdH19KTtPYmplY3QuZGVmaW5lUHJvcGVydHkoamUsXCJIYXNoTWFwXCIse2VudW1lcmFibGU6ITAsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIGd2LmRlZmF1bHR9fSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGplLFwiSGFzaFNldFwiLHtlbnVtZXJhYmxlOiEwLGdldDpmdW5jdGlvbigpe3JldHVybiBwdi5kZWZhdWx0fX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eShqZSxcIkxpbmtMaXN0XCIse2VudW1lcmFibGU6ITAsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIGZ2LmRlZmF1bHR9fSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGplLFwiT3JkZXJlZE1hcFwiLHtlbnVtZXJhYmxlOiEwLGdldDpmdW5jdGlvbigpe3JldHVybiBkdi5kZWZhdWx0fX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eShqZSxcIk9yZGVyZWRTZXRcIix7ZW51bWVyYWJsZTohMCxnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gaHYuZGVmYXVsdH19KTtPYmplY3QuZGVmaW5lUHJvcGVydHkoamUsXCJQcmlvcml0eVF1ZXVlXCIse2VudW1lcmFibGU6ITAsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIGx2LmRlZmF1bHR9fSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGplLFwiUXVldWVcIix7ZW51bWVyYWJsZTohMCxnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gYXYuZGVmYXVsdH19KTtPYmplY3QuZGVmaW5lUHJvcGVydHkoamUsXCJTdGFja1wiLHtlbnVtZXJhYmxlOiEwLGdldDpmdW5jdGlvbigpe3JldHVybiBvdi5kZWZhdWx0fX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0eShqZSxcIlZlY3RvclwiLHtlbnVtZXJhYmxlOiEwLGdldDpmdW5jdGlvbigpe3JldHVybiB1di5kZWZhdWx0fX0pO3ZhciBvdj11dChaZCgpKSxhdj11dChlcCgpKSxsdj11dCh0cCgpKSx1dj11dChycCgpKSxmdj11dChpcCgpKSxjdj11dChucCgpKSxodj11dCh1cCgpKSxkdj11dChjcCgpKSxwdj11dChwcCgpKSxndj11dCh5cCgpKTtmdW5jdGlvbiB1dCh0KXtyZXR1cm4gdCYmdC50P3Q6e2RlZmF1bHQ6dH19fSk7dmFyIF9wPU0oKG1OLHdwKT0+e3YoKTttKCk7XygpO3ZhciB5dj1icCgpLk9yZGVyZWRTZXQsZnQ9b3QoKShcIm51bWJlci1hbGxvY2F0b3I6dHJhY2VcIiksYnY9b3QoKShcIm51bWJlci1hbGxvY2F0b3I6ZXJyb3JcIik7ZnVuY3Rpb24gVGUodCxlKXt0aGlzLmxvdz10LHRoaXMuaGlnaD1lO31UZS5wcm90b3R5cGUuZXF1YWxzPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmxvdz09PXQubG93JiZ0aGlzLmhpZ2g9PT10LmhpZ2h9O1RlLnByb3RvdHlwZS5jb21wYXJlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmxvdzx0LmxvdyYmdGhpcy5oaWdoPHQubG93Py0xOnQubG93PHRoaXMubG93JiZ0LmhpZ2g8dGhpcy5sb3c/MTowfTtmdW5jdGlvbiBjdCh0LGUpe2lmKCEodGhpcyBpbnN0YW5jZW9mIGN0KSlyZXR1cm4gbmV3IGN0KHQsZSk7dGhpcy5taW49dCx0aGlzLm1heD1lLHRoaXMuc3M9bmV3IHl2KFtdLChyLGkpPT5yLmNvbXBhcmUoaSkpLGZ0KFwiQ3JlYXRlXCIpLHRoaXMuY2xlYXIoKTt9Y3QucHJvdG90eXBlLmZpcnN0VmFjYW50PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuc3Muc2l6ZSgpPT09MD9udWxsOnRoaXMuc3MuZnJvbnQoKS5sb3d9O2N0LnByb3RvdHlwZS5hbGxvYz1mdW5jdGlvbigpe2lmKHRoaXMuc3Muc2l6ZSgpPT09MClyZXR1cm4gZnQoXCJhbGxvYygpOmVtcHR5XCIpLG51bGw7bGV0IHQ9dGhpcy5zcy5iZWdpbigpLGU9dC5wb2ludGVyLmxvdyxyPXQucG9pbnRlci5oaWdoLGk9ZTtyZXR1cm4gaSsxPD1yP3RoaXMuc3MudXBkYXRlS2V5QnlJdGVyYXRvcih0LG5ldyBUZShlKzEscikpOnRoaXMuc3MuZXJhc2VFbGVtZW50QnlQb3MoMCksZnQoXCJhbGxvYygpOlwiK2kpLGl9O2N0LnByb3RvdHlwZS51c2U9ZnVuY3Rpb24odCl7bGV0IGU9bmV3IFRlKHQsdCkscj10aGlzLnNzLmxvd2VyQm91bmQoZSk7aWYoIXIuZXF1YWxzKHRoaXMuc3MuZW5kKCkpKXtsZXQgaT1yLnBvaW50ZXIubG93LG49ci5wb2ludGVyLmhpZ2g7cmV0dXJuIHIucG9pbnRlci5lcXVhbHMoZSk/KHRoaXMuc3MuZXJhc2VFbGVtZW50QnlJdGVyYXRvcihyKSxmdChcInVzZSgpOlwiK3QpLCEwKTppPnQ/ITE6aT09PXQ/KHRoaXMuc3MudXBkYXRlS2V5QnlJdGVyYXRvcihyLG5ldyBUZShpKzEsbikpLGZ0KFwidXNlKCk6XCIrdCksITApOm49PT10Pyh0aGlzLnNzLnVwZGF0ZUtleUJ5SXRlcmF0b3IocixuZXcgVGUoaSxuLTEpKSxmdChcInVzZSgpOlwiK3QpLCEwKToodGhpcy5zcy51cGRhdGVLZXlCeUl0ZXJhdG9yKHIsbmV3IFRlKHQrMSxuKSksdGhpcy5zcy5pbnNlcnQobmV3IFRlKGksdC0xKSksZnQoXCJ1c2UoKTpcIit0KSwhMCl9cmV0dXJuIGZ0KFwidXNlKCk6ZmFpbGVkXCIpLCExfTtjdC5wcm90b3R5cGUuZnJlZT1mdW5jdGlvbih0KXtpZih0PHRoaXMubWlufHx0PnRoaXMubWF4KXtidihcImZyZWUoKTpcIit0K1wiIGlzIG91dCBvZiByYW5nZVwiKTtyZXR1cm59bGV0IGU9bmV3IFRlKHQsdCkscj10aGlzLnNzLnVwcGVyQm91bmQoZSk7aWYoci5lcXVhbHModGhpcy5zcy5lbmQoKSkpe2lmKHIuZXF1YWxzKHRoaXMuc3MuYmVnaW4oKSkpe3RoaXMuc3MuaW5zZXJ0KGUpO3JldHVybn1yLnByZSgpO2xldCBpPXIucG9pbnRlci5oaWdoO3IucG9pbnRlci5oaWdoKzE9PT10P3RoaXMuc3MudXBkYXRlS2V5QnlJdGVyYXRvcihyLG5ldyBUZShpLHQpKTp0aGlzLnNzLmluc2VydChlKTt9ZWxzZSBpZihyLmVxdWFscyh0aGlzLnNzLmJlZ2luKCkpKWlmKHQrMT09PXIucG9pbnRlci5sb3cpe2xldCBpPXIucG9pbnRlci5oaWdoO3RoaXMuc3MudXBkYXRlS2V5QnlJdGVyYXRvcihyLG5ldyBUZSh0LGkpKTt9ZWxzZSB0aGlzLnNzLmluc2VydChlKTtlbHNlIHtsZXQgaT1yLnBvaW50ZXIubG93LG49ci5wb2ludGVyLmhpZ2g7ci5wcmUoKTtsZXQgbz1yLnBvaW50ZXIubG93O3IucG9pbnRlci5oaWdoKzE9PT10P3QrMT09PWk/KHRoaXMuc3MuZXJhc2VFbGVtZW50QnlJdGVyYXRvcihyKSx0aGlzLnNzLnVwZGF0ZUtleUJ5SXRlcmF0b3IocixuZXcgVGUobyxuKSkpOnRoaXMuc3MudXBkYXRlS2V5QnlJdGVyYXRvcihyLG5ldyBUZShvLHQpKTp0KzE9PT1pPyh0aGlzLnNzLmVyYXNlRWxlbWVudEJ5SXRlcmF0b3Ioci5uZXh0KCkpLHRoaXMuc3MuaW5zZXJ0KG5ldyBUZSh0LG4pKSk6dGhpcy5zcy5pbnNlcnQoZSk7fWZ0KFwiZnJlZSgpOlwiK3QpO307Y3QucHJvdG90eXBlLmNsZWFyPWZ1bmN0aW9uKCl7ZnQoXCJjbGVhcigpXCIpLHRoaXMuc3MuY2xlYXIoKSx0aGlzLnNzLmluc2VydChuZXcgVGUodGhpcy5taW4sdGhpcy5tYXgpKTt9O2N0LnByb3RvdHlwZS5pbnRlcnZhbENvdW50PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuc3Muc2l6ZSgpfTtjdC5wcm90b3R5cGUuZHVtcD1mdW5jdGlvbigpe2NvbnNvbGUubG9nKFwibGVuZ3RoOlwiK3RoaXMuc3Muc2l6ZSgpKTtmb3IobGV0IHQgb2YgdGhpcy5zcyljb25zb2xlLmxvZyh0KTt9O3dwLmV4cG9ydHM9Y3Q7fSk7dmFyIHhhPU0oKFBOLG1wKT0+e3YoKTttKCk7XygpO3ZhciB3dj1fcCgpO21wLmV4cG9ydHMuTnVtYmVyQWxsb2NhdG9yPXd2O30pO3ZhciB2cD1NKExhPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KExhLFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO3ZhciBfdj1YZCgpLG12PXhhKCksTWE9Y2xhc3N7Y29uc3RydWN0b3IoZSl7ZT4wJiYodGhpcy5hbGlhc1RvVG9waWM9bmV3IF92LkxSVUNhY2hlKHttYXg6ZX0pLHRoaXMudG9waWNUb0FsaWFzPXt9LHRoaXMubnVtYmVyQWxsb2NhdG9yPW5ldyBtdi5OdW1iZXJBbGxvY2F0b3IoMSxlKSx0aGlzLm1heD1lLHRoaXMubGVuZ3RoPTApO31wdXQoZSxyKXtpZihyPT09MHx8cj50aGlzLm1heClyZXR1cm4gITE7bGV0IGk9dGhpcy5hbGlhc1RvVG9waWMuZ2V0KHIpO3JldHVybiBpJiZkZWxldGUgdGhpcy50b3BpY1RvQWxpYXNbaV0sdGhpcy5hbGlhc1RvVG9waWMuc2V0KHIsZSksdGhpcy50b3BpY1RvQWxpYXNbZV09cix0aGlzLm51bWJlckFsbG9jYXRvci51c2UociksdGhpcy5sZW5ndGg9dGhpcy5hbGlhc1RvVG9waWMuc2l6ZSwhMH1nZXRUb3BpY0J5QWxpYXMoZSl7cmV0dXJuIHRoaXMuYWxpYXNUb1RvcGljLmdldChlKX1nZXRBbGlhc0J5VG9waWMoZSl7bGV0IHI9dGhpcy50b3BpY1RvQWxpYXNbZV07cmV0dXJuIHR5cGVvZiByPFwidVwiJiZ0aGlzLmFsaWFzVG9Ub3BpYy5nZXQocikscn1jbGVhcigpe3RoaXMuYWxpYXNUb1RvcGljLmNsZWFyKCksdGhpcy50b3BpY1RvQWxpYXM9e30sdGhpcy5udW1iZXJBbGxvY2F0b3IuY2xlYXIoKSx0aGlzLmxlbmd0aD0wO31nZXRMcnVBbGlhcygpe2xldCBlPXRoaXMubnVtYmVyQWxsb2NhdG9yLmZpcnN0VmFjYW50KCk7cmV0dXJuIGV8fFsuLi50aGlzLmFsaWFzVG9Ub3BpYy5rZXlzKCldW3RoaXMuYWxpYXNUb1RvcGljLnNpemUtMV19fTtMYS5kZWZhdWx0PU1hO30pO3ZhciBFcD1NKFJpPT57digpO20oKTtfKCk7dmFyIHZ2PVJpJiZSaS5fX2ltcG9ydERlZmF1bHR8fGZ1bmN0aW9uKHQpe3JldHVybiB0JiZ0Ll9fZXNNb2R1bGU/dDp7ZGVmYXVsdDp0fX07T2JqZWN0LmRlZmluZVByb3BlcnR5KFJpLFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO3ZhciBFdj1BaSgpLFN2PXZ2KHZwKCkpLEF2PUpyKCksSXY9KHQsZSk9Pnt0LmxvZyhcIl9oYW5kbGVDb25uYWNrXCIpO2xldHtvcHRpb25zOnJ9PXQsbj1yLnByb3RvY29sVmVyc2lvbj09PTU/ZS5yZWFzb25Db2RlOmUucmV0dXJuQ29kZTtpZihjbGVhclRpbWVvdXQodC5jb25uYWNrVGltZXIpLGRlbGV0ZSB0LnRvcGljQWxpYXNTZW5kLGUucHJvcGVydGllcyl7aWYoZS5wcm9wZXJ0aWVzLnRvcGljQWxpYXNNYXhpbXVtKXtpZihlLnByb3BlcnRpZXMudG9waWNBbGlhc01heGltdW0+NjU1MzUpe3QuZW1pdChcImVycm9yXCIsbmV3IEVycm9yKFwidG9waWNBbGlhc01heGltdW0gZnJvbSBicm9rZXIgaXMgb3V0IG9mIHJhbmdlXCIpKTtyZXR1cm59ZS5wcm9wZXJ0aWVzLnRvcGljQWxpYXNNYXhpbXVtPjAmJih0LnRvcGljQWxpYXNTZW5kPW5ldyBTdi5kZWZhdWx0KGUucHJvcGVydGllcy50b3BpY0FsaWFzTWF4aW11bSkpO31lLnByb3BlcnRpZXMuc2VydmVyS2VlcEFsaXZlJiZyLmtlZXBhbGl2ZSYmKHIua2VlcGFsaXZlPWUucHJvcGVydGllcy5zZXJ2ZXJLZWVwQWxpdmUsdC5fc2hpZnRQaW5nSW50ZXJ2YWwoKSksZS5wcm9wZXJ0aWVzLm1heGltdW1QYWNrZXRTaXplJiYoci5wcm9wZXJ0aWVzfHwoci5wcm9wZXJ0aWVzPXt9KSxyLnByb3BlcnRpZXMubWF4aW11bVBhY2tldFNpemU9ZS5wcm9wZXJ0aWVzLm1heGltdW1QYWNrZXRTaXplKTt9aWYobj09PTApdC5yZWNvbm5lY3Rpbmc9ITEsdC5fb25Db25uZWN0KGUpO2Vsc2UgaWYobj4wKXtsZXQgbz1uZXcgQXYuRXJyb3JXaXRoUmVhc29uQ29kZShgQ29ubmVjdGlvbiByZWZ1c2VkOiAke0V2LlJlYXNvbkNvZGVzW25dfWAsbik7dC5lbWl0KFwiZXJyb3JcIixvKTt9fTtSaS5kZWZhdWx0PUl2O30pO3ZhciBTcD1NKFVhPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KFVhLFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO3ZhciBUdj0odCxlLHIpPT57dC5sb2coXCJoYW5kbGluZyBwdWJyZWwgcGFja2V0XCIpO2xldCBpPXR5cGVvZiByPFwidVwiP3I6dC5ub29wLHttZXNzYWdlSWQ6bn09ZSxvPXtjbWQ6XCJwdWJjb21wXCIsbWVzc2FnZUlkOm59O3QuaW5jb21pbmdTdG9yZS5nZXQoZSwocyxhKT0+e3M/dC5fc2VuZFBhY2tldChvLGkpOih0LmVtaXQoXCJtZXNzYWdlXCIsYS50b3BpYyxhLnBheWxvYWQsYSksdC5oYW5kbGVNZXNzYWdlKGEsdT0+e2lmKHUpcmV0dXJuIGkodSk7dC5pbmNvbWluZ1N0b3JlLmRlbChhLHQubm9vcCksdC5fc2VuZFBhY2tldChvLGkpO30pKTt9KTt9O1VhLmRlZmF1bHQ9VHY7fSk7dmFyIEFwPU0oQ2k9Pnt2KCk7bSgpO18oKTt2YXIgQmk9Q2kmJkNpLl9faW1wb3J0RGVmYXVsdHx8ZnVuY3Rpb24odCl7cmV0dXJuIHQmJnQuX19lc01vZHVsZT90OntkZWZhdWx0OnR9fTtPYmplY3QuZGVmaW5lUHJvcGVydHkoQ2ksXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSk7dmFyIFJ2PUJpKFZkKCkpLEN2PUJpKEtkKCkpLEJ2PUJpKEVwKCkpLFB2PUJpKEFpKCkpLE92PUJpKFNwKCkpLGt2PSh0LGUscik9PntsZXR7b3B0aW9uczppfT10O2lmKGkucHJvdG9jb2xWZXJzaW9uPT09NSYmaS5wcm9wZXJ0aWVzJiZpLnByb3BlcnRpZXMubWF4aW11bVBhY2tldFNpemUmJmkucHJvcGVydGllcy5tYXhpbXVtUGFja2V0U2l6ZTxlLmxlbmd0aClyZXR1cm4gdC5lbWl0KFwiZXJyb3JcIixuZXcgRXJyb3IoYGV4Y2VlZGluZyBwYWNrZXRzIHNpemUgJHtlLmNtZH1gKSksdC5lbmQoe3JlYXNvbkNvZGU6MTQ5LHByb3BlcnRpZXM6e3JlYXNvblN0cmluZzpcIk1heGltdW0gcGFja2V0IHNpemUgd2FzIGV4Y2VlZGVkXCJ9fSksdDtzd2l0Y2godC5sb2coXCJfaGFuZGxlUGFja2V0IDo6IGVtaXR0aW5nIHBhY2tldHJlY2VpdmVcIiksdC5lbWl0KFwicGFja2V0cmVjZWl2ZVwiLGUpLGUuY21kKXtjYXNlXCJwdWJsaXNoXCI6KDAsIFJ2LmRlZmF1bHQpKHQsZSxyKTticmVhaztjYXNlXCJwdWJhY2tcIjpjYXNlXCJwdWJyZWNcIjpjYXNlXCJwdWJjb21wXCI6Y2FzZVwic3ViYWNrXCI6Y2FzZVwidW5zdWJhY2tcIjooMCwgUHYuZGVmYXVsdCkodCxlKSxyKCk7YnJlYWs7Y2FzZVwicHVicmVsXCI6KDAsIE92LmRlZmF1bHQpKHQsZSxyKTticmVhaztjYXNlXCJjb25uYWNrXCI6KDAsIEJ2LmRlZmF1bHQpKHQsZSkscigpO2JyZWFrO2Nhc2VcImF1dGhcIjooMCwgQ3YuZGVmYXVsdCkodCxlKSxyKCk7YnJlYWs7Y2FzZVwicGluZ3Jlc3BcIjp0LnBpbmdSZXNwPSEwLHIoKTticmVhaztjYXNlXCJkaXNjb25uZWN0XCI6dC5lbWl0KFwiZGlzY29ubmVjdFwiLGUpLHIoKTticmVhaztkZWZhdWx0OnQubG9nKFwiX2hhbmRsZVBhY2tldCA6OiB1bmtub3duIGNvbW1hbmRcIikscigpO2JyZWFrfX07Q2kuZGVmYXVsdD1rdjt9KTt2YXIgSXA9TSh0aT0+e3YoKTttKCk7XygpO3ZhciB4dj10aSYmdGkuX19pbXBvcnREZWZhdWx0fHxmdW5jdGlvbih0KXtyZXR1cm4gdCYmdC5fX2VzTW9kdWxlP3Q6e2RlZmF1bHQ6dH19O09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aSxcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTt0aS5UeXBlZEV2ZW50RW1pdHRlcj12b2lkIDA7dmFyIE12PXh2KChpcigpLFgocnIpKSksTHY9SnIoKSxYbj1jbGFzc3t9O3RpLlR5cGVkRXZlbnRFbWl0dGVyPVhuOygwLCBMdi5hcHBseU1peGluKShYbixNdi5kZWZhdWx0KTt9KTt2YXIgUGk9TShBcj0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShBcixcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTtBci5pc1JlYWN0TmF0aXZlQnJvd3Nlcj1Bci5pc1dlYldvcmtlcj12b2lkIDA7dmFyIFV2PSgpPT50eXBlb2Ygd2luZG93PFwidVwiJiZ0eXBlb2Ygd2luZG93LmRvY3VtZW50PFwidVwiLFRwPSgpPT57dmFyIHQsZTtyZXR1cm4gISEodHlwZW9mIHNlbGY9PVwib2JqZWN0XCImJighKChlPSh0PXNlbGY/LmNvbnN0cnVjdG9yKT09PW51bGx8fHQ9PT12b2lkIDA/dm9pZCAwOnQubmFtZSk9PT1udWxsfHxlPT09dm9pZCAwKSYmZS5pbmNsdWRlcyhcIldvcmtlckdsb2JhbFNjb3BlXCIpKSl9LFJwPSgpPT50eXBlb2YgQjxcInVcIiYmQi5wcm9kdWN0PT09XCJSZWFjdE5hdGl2ZVwiLE52PVV2KCl8fFRwKCl8fFJwKCk7QXIuaXNXZWJXb3JrZXI9VHAoKTtBci5pc1JlYWN0TmF0aXZlQnJvd3Nlcj1ScCgpO0FyLmRlZmF1bHQ9TnY7fSk7dmFyIEJwPU0oKFpuLENwKT0+e3YoKTttKCk7XygpOyhmdW5jdGlvbih0LGUpe3R5cGVvZiBabj09XCJvYmplY3RcIiYmdHlwZW9mIENwPFwidVwiP2UoWm4pOnR5cGVvZiBkZWZpbmU9PVwiZnVuY3Rpb25cIiYmZGVmaW5lLmFtZD9kZWZpbmUoW1wiZXhwb3J0c1wiXSxlKToodD10eXBlb2YgZ2xvYmFsVGhpczxcInVcIj9nbG9iYWxUaGlzOnR8fHNlbGYsZSh0LmZhc3RVbmlxdWVOdW1iZXJzPXt9KSk7fSkoWm4sZnVuY3Rpb24odCl7dmFyIGU9ZnVuY3Rpb24oZyl7cmV0dXJuIGZ1bmN0aW9uKHkpe3ZhciB3PWcoeSk7cmV0dXJuIHkuYWRkKHcpLHd9fSxyPWZ1bmN0aW9uKGcpe3JldHVybiBmdW5jdGlvbih5LHcpe3JldHVybiBnLnNldCh5LHcpLHd9fSxpPU51bWJlci5NQVhfU0FGRV9JTlRFR0VSPT09dm9pZCAwPzkwMDcxOTkyNTQ3NDA5OTE6TnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIsbj01MzY4NzA5MTIsbz1uKjIscz1mdW5jdGlvbihnLHkpe3JldHVybiBmdW5jdGlvbih3KXt2YXIgRT15LmdldCh3KSxTPUU9PT12b2lkIDA/dy5zaXplOkU8bz9FKzE6MDtpZighdy5oYXMoUykpcmV0dXJuIGcodyxTKTtpZih3LnNpemU8bil7Zm9yKDt3LmhhcyhTKTspUz1NYXRoLmZsb29yKE1hdGgucmFuZG9tKCkqbyk7cmV0dXJuIGcodyxTKX1pZih3LnNpemU+aSl0aHJvdyBuZXcgRXJyb3IoXCJDb25ncmF0dWxhdGlvbnMsIHlvdSBjcmVhdGVkIGEgY29sbGVjdGlvbiBvZiB1bmlxdWUgbnVtYmVycyB3aGljaCB1c2VzIGFsbCBhdmFpbGFibGUgaW50ZWdlcnMhXCIpO2Zvcig7dy5oYXMoUyk7KVM9TWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpKmkpO3JldHVybiBnKHcsUyl9fSxhPW5ldyBXZWFrTWFwLHU9cihhKSxjPXModSxhKSxoPWUoYyk7dC5hZGRVbmlxdWVOdW1iZXI9aCx0LmdlbmVyYXRlVW5pcXVlTnVtYmVyPWM7fSk7fSk7dmFyIE9wPU0oKGVzLFBwKT0+e3YoKTttKCk7XygpOyhmdW5jdGlvbih0LGUpe3R5cGVvZiBlcz09XCJvYmplY3RcIiYmdHlwZW9mIFBwPFwidVwiP2UoZXMsQnAoKSk6dHlwZW9mIGRlZmluZT09XCJmdW5jdGlvblwiJiZkZWZpbmUuYW1kP2RlZmluZShbXCJleHBvcnRzXCIsXCJmYXN0LXVuaXF1ZS1udW1iZXJzXCJdLGUpOih0PXR5cGVvZiBnbG9iYWxUaGlzPFwidVwiP2dsb2JhbFRoaXM6dHx8c2VsZixlKHQud29ya2VyVGltZXJzQnJva2VyPXt9LHQuZmFzdFVuaXF1ZU51bWJlcnMpKTt9KShlcyxmdW5jdGlvbih0LGUpe3ZhciByPWZ1bmN0aW9uKHMpe3JldHVybiBzLm1ldGhvZCE9PXZvaWQgMCYmcy5tZXRob2Q9PT1cImNhbGxcIn0saT1mdW5jdGlvbihzKXtyZXR1cm4gcy5lcnJvcj09PW51bGwmJnR5cGVvZiBzLmlkPT1cIm51bWJlclwifSxuPWZ1bmN0aW9uKHMpe3ZhciBhPW5ldyBNYXAoW1swLGZ1bmN0aW9uKCl7fV1dKSx1PW5ldyBNYXAoW1swLGZ1bmN0aW9uKCl7fV1dKSxjPW5ldyBNYXAsaD1uZXcgV29ya2VyKHMpO2guYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIixmdW5jdGlvbihFKXt2YXIgUz1FLmRhdGE7aWYocihTKSl7dmFyIEk9Uy5wYXJhbXMsQz1JLnRpbWVySWQsUj1JLnRpbWVyVHlwZTtpZihSPT09XCJpbnRlcnZhbFwiKXt2YXIgVT1hLmdldChDKTtpZih0eXBlb2YgVT09XCJudW1iZXJcIil7dmFyIE49Yy5nZXQoVSk7aWYoTj09PXZvaWQgMHx8Ti50aW1lcklkIT09Q3x8Ti50aW1lclR5cGUhPT1SKXRocm93IG5ldyBFcnJvcihcIlRoZSB0aW1lciBpcyBpbiBhbiB1bmRlZmluZWQgc3RhdGUuXCIpfWVsc2UgaWYodHlwZW9mIFU8XCJ1XCIpVSgpO2Vsc2UgdGhyb3cgbmV3IEVycm9yKFwiVGhlIHRpbWVyIGlzIGluIGFuIHVuZGVmaW5lZCBzdGF0ZS5cIil9ZWxzZSBpZihSPT09XCJ0aW1lb3V0XCIpe3ZhciBXPXUuZ2V0KEMpO2lmKHR5cGVvZiBXPT1cIm51bWJlclwiKXt2YXIgSz1jLmdldChXKTtpZihLPT09dm9pZCAwfHxLLnRpbWVySWQhPT1DfHxLLnRpbWVyVHlwZSE9PVIpdGhyb3cgbmV3IEVycm9yKFwiVGhlIHRpbWVyIGlzIGluIGFuIHVuZGVmaW5lZCBzdGF0ZS5cIil9ZWxzZSBpZih0eXBlb2YgVzxcInVcIilXKCksdS5kZWxldGUoQyk7ZWxzZSB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgdGltZXIgaXMgaW4gYW4gdW5kZWZpbmVkIHN0YXRlLlwiKX19ZWxzZSBpZihpKFMpKXt2YXIgej1TLmlkLFE9Yy5nZXQoeik7aWYoUT09PXZvaWQgMCl0aHJvdyBuZXcgRXJyb3IoXCJUaGUgdGltZXIgaXMgaW4gYW4gdW5kZWZpbmVkIHN0YXRlLlwiKTt2YXIgZGU9US50aW1lcklkLEd0PVEudGltZXJUeXBlO2MuZGVsZXRlKHopLEd0PT09XCJpbnRlcnZhbFwiP2EuZGVsZXRlKGRlKTp1LmRlbGV0ZShkZSk7fWVsc2Uge3ZhciBwZT1TLmVycm9yLm1lc3NhZ2U7dGhyb3cgbmV3IEVycm9yKHBlKX19KTt2YXIgZD1mdW5jdGlvbihTKXt2YXIgST1lLmdlbmVyYXRlVW5pcXVlTnVtYmVyKGMpO2Muc2V0KEkse3RpbWVySWQ6Uyx0aW1lclR5cGU6XCJpbnRlcnZhbFwifSksYS5zZXQoUyxJKSxoLnBvc3RNZXNzYWdlKHtpZDpJLG1ldGhvZDpcImNsZWFyXCIscGFyYW1zOnt0aW1lcklkOlMsdGltZXJUeXBlOlwiaW50ZXJ2YWxcIn19KTt9LGc9ZnVuY3Rpb24oUyl7dmFyIEk9ZS5nZW5lcmF0ZVVuaXF1ZU51bWJlcihjKTtjLnNldChJLHt0aW1lcklkOlMsdGltZXJUeXBlOlwidGltZW91dFwifSksdS5zZXQoUyxJKSxoLnBvc3RNZXNzYWdlKHtpZDpJLG1ldGhvZDpcImNsZWFyXCIscGFyYW1zOnt0aW1lcklkOlMsdGltZXJUeXBlOlwidGltZW91dFwifX0pO30seT1mdW5jdGlvbihTKXt2YXIgST1hcmd1bWVudHMubGVuZ3RoPjEmJmFyZ3VtZW50c1sxXSE9PXZvaWQgMD9hcmd1bWVudHNbMV06MCxDPWUuZ2VuZXJhdGVVbmlxdWVOdW1iZXIoYSk7cmV0dXJuIGEuc2V0KEMsZnVuY3Rpb24oKXtTKCksdHlwZW9mIGEuZ2V0KEMpPT1cImZ1bmN0aW9uXCImJmgucG9zdE1lc3NhZ2Uoe2lkOm51bGwsbWV0aG9kOlwic2V0XCIscGFyYW1zOntkZWxheTpJLG5vdzpwZXJmb3JtYW5jZS5ub3coKSx0aW1lcklkOkMsdGltZXJUeXBlOlwiaW50ZXJ2YWxcIn19KTt9KSxoLnBvc3RNZXNzYWdlKHtpZDpudWxsLG1ldGhvZDpcInNldFwiLHBhcmFtczp7ZGVsYXk6SSxub3c6cGVyZm9ybWFuY2Uubm93KCksdGltZXJJZDpDLHRpbWVyVHlwZTpcImludGVydmFsXCJ9fSksQ30sdz1mdW5jdGlvbihTKXt2YXIgST1hcmd1bWVudHMubGVuZ3RoPjEmJmFyZ3VtZW50c1sxXSE9PXZvaWQgMD9hcmd1bWVudHNbMV06MCxDPWUuZ2VuZXJhdGVVbmlxdWVOdW1iZXIodSk7cmV0dXJuIHUuc2V0KEMsUyksaC5wb3N0TWVzc2FnZSh7aWQ6bnVsbCxtZXRob2Q6XCJzZXRcIixwYXJhbXM6e2RlbGF5Okksbm93OnBlcmZvcm1hbmNlLm5vdygpLHRpbWVySWQ6Qyx0aW1lclR5cGU6XCJ0aW1lb3V0XCJ9fSksQ307cmV0dXJuIHtjbGVhckludGVydmFsOmQsY2xlYXJUaW1lb3V0Omcsc2V0SW50ZXJ2YWw6eSxzZXRUaW1lb3V0Ond9fTt0LmxvYWQ9bjt9KTt9KTt2YXIgeHA9TSgodHMsa3ApPT57digpO20oKTtfKCk7KGZ1bmN0aW9uKHQsZSl7dHlwZW9mIHRzPT1cIm9iamVjdFwiJiZ0eXBlb2Yga3A8XCJ1XCI/ZSh0cyxPcCgpKTp0eXBlb2YgZGVmaW5lPT1cImZ1bmN0aW9uXCImJmRlZmluZS5hbWQ/ZGVmaW5lKFtcImV4cG9ydHNcIixcIndvcmtlci10aW1lcnMtYnJva2VyXCJdLGUpOih0PXR5cGVvZiBnbG9iYWxUaGlzPFwidVwiP2dsb2JhbFRoaXM6dHx8c2VsZixlKHQud29ya2VyVGltZXJzPXt9LHQud29ya2VyVGltZXJzQnJva2VyKSk7fSkodHMsZnVuY3Rpb24odCxlKXt2YXIgcj1mdW5jdGlvbihoLGQpe3ZhciBnPW51bGw7cmV0dXJuIGZ1bmN0aW9uKCl7aWYoZyE9PW51bGwpcmV0dXJuIGc7dmFyIHk9bmV3IEJsb2IoW2RdLHt0eXBlOlwiYXBwbGljYXRpb24vamF2YXNjcmlwdDsgY2hhcnNldD11dGYtOFwifSksdz1VUkwuY3JlYXRlT2JqZWN0VVJMKHkpO3JldHVybiBnPWgodyksc2V0VGltZW91dChmdW5jdGlvbigpe3JldHVybiBVUkwucmV2b2tlT2JqZWN0VVJMKHcpfSksZ319LGk9YCgoKT0+e3ZhciBlPXs0NzI6KGUsdCxyKT0+e3ZhciBvLGk7dm9pZCAwPT09KGk9XCJmdW5jdGlvblwiPT10eXBlb2Yobz1mdW5jdGlvbigpe1widXNlIHN0cmljdFwiO3ZhciBlPW5ldyBNYXAsdD1uZXcgTWFwLHI9ZnVuY3Rpb24odCl7dmFyIHI9ZS5nZXQodCk7aWYodm9pZCAwPT09cil0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIGludGVydmFsIHNjaGVkdWxlZCB3aXRoIHRoZSBnaXZlbiBpZCBcIicuY29uY2F0KHQsJ1wiLicpKTtjbGVhclRpbWVvdXQociksZS5kZWxldGUodCl9LG89ZnVuY3Rpb24oZSl7dmFyIHI9dC5nZXQoZSk7aWYodm9pZCAwPT09cil0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGlzIG5vIHRpbWVvdXQgc2NoZWR1bGVkIHdpdGggdGhlIGdpdmVuIGlkIFwiJy5jb25jYXQoZSwnXCIuJykpO2NsZWFyVGltZW91dChyKSx0LmRlbGV0ZShlKX0saT1mdW5jdGlvbihlLHQpe3ZhciByLG89cGVyZm9ybWFuY2Uubm93KCk7cmV0dXJue2V4cGVjdGVkOm8rKHI9ZS1NYXRoLm1heCgwLG8tdCkpLHJlbWFpbmluZ0RlbGF5OnJ9fSxuPWZ1bmN0aW9uIGUodCxyLG8saSl7dmFyIG49cGVyZm9ybWFuY2Uubm93KCk7bj5vP3Bvc3RNZXNzYWdlKHtpZDpudWxsLG1ldGhvZDpcImNhbGxcIixwYXJhbXM6e3RpbWVySWQ6cix0aW1lclR5cGU6aX19KTp0LnNldChyLHNldFRpbWVvdXQoZSxvLW4sdCxyLG8saSkpfSxhPWZ1bmN0aW9uKHQscixvKXt2YXIgYT1pKHQsbykscz1hLmV4cGVjdGVkLGQ9YS5yZW1haW5pbmdEZWxheTtlLnNldChyLHNldFRpbWVvdXQobixkLGUscixzLFwiaW50ZXJ2YWxcIikpfSxzPWZ1bmN0aW9uKGUscixvKXt2YXIgYT1pKGUsbykscz1hLmV4cGVjdGVkLGQ9YS5yZW1haW5pbmdEZWxheTt0LnNldChyLHNldFRpbWVvdXQobixkLHQscixzLFwidGltZW91dFwiKSl9O2FkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsKGZ1bmN0aW9uKGUpe3ZhciB0PWUuZGF0YTt0cnl7aWYoXCJjbGVhclwiPT09dC5tZXRob2Qpe3ZhciBpPXQuaWQsbj10LnBhcmFtcyxkPW4udGltZXJJZCxjPW4udGltZXJUeXBlO2lmKFwiaW50ZXJ2YWxcIj09PWMpcihkKSxwb3N0TWVzc2FnZSh7ZXJyb3I6bnVsbCxpZDppfSk7ZWxzZXtpZihcInRpbWVvdXRcIiE9PWMpdGhyb3cgbmV3IEVycm9yKCdUaGUgZ2l2ZW4gdHlwZSBcIicuY29uY2F0KGMsJ1wiIGlzIG5vdCBzdXBwb3J0ZWQnKSk7byhkKSxwb3N0TWVzc2FnZSh7ZXJyb3I6bnVsbCxpZDppfSl9fWVsc2V7aWYoXCJzZXRcIiE9PXQubWV0aG9kKXRocm93IG5ldyBFcnJvcignVGhlIGdpdmVuIG1ldGhvZCBcIicuY29uY2F0KHQubWV0aG9kLCdcIiBpcyBub3Qgc3VwcG9ydGVkJykpO3ZhciB1PXQucGFyYW1zLGw9dS5kZWxheSxwPXUubm93LG09dS50aW1lcklkLHY9dS50aW1lclR5cGU7aWYoXCJpbnRlcnZhbFwiPT09dilhKGwsbSxwKTtlbHNle2lmKFwidGltZW91dFwiIT09dil0aHJvdyBuZXcgRXJyb3IoJ1RoZSBnaXZlbiB0eXBlIFwiJy5jb25jYXQodiwnXCIgaXMgbm90IHN1cHBvcnRlZCcpKTtzKGwsbSxwKX19fWNhdGNoKGUpe3Bvc3RNZXNzYWdlKHtlcnJvcjp7bWVzc2FnZTplLm1lc3NhZ2V9LGlkOnQuaWQscmVzdWx0Om51bGx9KX19KSl9KT9vLmNhbGwodCxyLHQsZSk6byl8fChlLmV4cG9ydHM9aSl9fSx0PXt9O2Z1bmN0aW9uIHIobyl7dmFyIGk9dFtvXTtpZih2b2lkIDAhPT1pKXJldHVybiBpLmV4cG9ydHM7dmFyIG49dFtvXT17ZXhwb3J0czp7fX07cmV0dXJuIGVbb10obixuLmV4cG9ydHMsciksbi5leHBvcnRzfXIubj1lPT57dmFyIHQ9ZSYmZS5fX2VzTW9kdWxlPygpPT5lLmRlZmF1bHQ6KCk9PmU7cmV0dXJuIHIuZCh0LHthOnR9KSx0fSxyLmQ9KGUsdCk9Pntmb3IodmFyIG8gaW4gdClyLm8odCxvKSYmIXIubyhlLG8pJiZPYmplY3QuZGVmaW5lUHJvcGVydHkoZSxvLHtlbnVtZXJhYmxlOiEwLGdldDp0W29dfSl9LHIubz0oZSx0KT0+T2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGUsdCksKCgpPT57XCJ1c2Ugc3RyaWN0XCI7cig0NzIpfSkoKX0pKCk7YCxuPXIoZS5sb2FkLGkpLG89ZnVuY3Rpb24oaCl7cmV0dXJuIG4oKS5jbGVhckludGVydmFsKGgpfSxzPWZ1bmN0aW9uKGgpe3JldHVybiBuKCkuY2xlYXJUaW1lb3V0KGgpfSxhPWZ1bmN0aW9uKCl7dmFyIGg7cmV0dXJuIChoPW4oKSkuc2V0SW50ZXJ2YWwuYXBwbHkoaCxhcmd1bWVudHMpfSx1PWZ1bmN0aW9uKCl7dmFyIGg7cmV0dXJuIChoPW4oKSkuc2V0VGltZW91dC5hcHBseShoLGFyZ3VtZW50cyl9O3QuY2xlYXJJbnRlcnZhbD1vLHQuY2xlYXJUaW1lb3V0PXMsdC5zZXRJbnRlcnZhbD1hLHQuc2V0VGltZW91dD11O30pO30pO3ZhciBOcD1NKFJ0PT57digpO20oKTtfKCk7dmFyIHF2PVJ0JiZSdC5fX2NyZWF0ZUJpbmRpbmd8fChPYmplY3QuY3JlYXRlP2Z1bmN0aW9uKHQsZSxyLGkpe2k9PT12b2lkIDAmJihpPXIpO3ZhciBuPU9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoZSxyKTsoIW58fChcImdldFwiaW4gbj8hZS5fX2VzTW9kdWxlOm4ud3JpdGFibGV8fG4uY29uZmlndXJhYmxlKSkmJihuPXtlbnVtZXJhYmxlOiEwLGdldDpmdW5jdGlvbigpe3JldHVybiBlW3JdfX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LGksbik7fTpmdW5jdGlvbih0LGUscixpKXtpPT09dm9pZCAwJiYoaT1yKSx0W2ldPWVbcl07fSksRHY9UnQmJlJ0Ll9fc2V0TW9kdWxlRGVmYXVsdHx8KE9iamVjdC5jcmVhdGU/ZnVuY3Rpb24odCxlKXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxcImRlZmF1bHRcIix7ZW51bWVyYWJsZTohMCx2YWx1ZTplfSk7fTpmdW5jdGlvbih0LGUpe3QuZGVmYXVsdD1lO30pLGp2PVJ0JiZSdC5fX2ltcG9ydFN0YXJ8fGZ1bmN0aW9uKHQpe2lmKHQmJnQuX19lc01vZHVsZSlyZXR1cm4gdDt2YXIgZT17fTtpZih0IT1udWxsKWZvcih2YXIgciBpbiB0KXIhPT1cImRlZmF1bHRcIiYmT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHQscikmJnF2KGUsdCxyKTtyZXR1cm4gRHYoZSx0KSxlfTtPYmplY3QuZGVmaW5lUHJvcGVydHkoUnQsXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSk7dmFyIE5hPWp2KFBpKCkpLE1wPXhwKCksTHA9e3NldDpNcC5zZXRUaW1lb3V0LGNsZWFyOk1wLmNsZWFyVGltZW91dH0sVXA9e3NldDoodCxlKT0+c2V0VGltZW91dCh0LGUpLGNsZWFyOnQ9PmNsZWFyVGltZW91dCh0KX0sRnY9dD0+e3N3aXRjaCh0KXtjYXNlXCJuYXRpdmVcIjpyZXR1cm4gVXA7Y2FzZVwid29ya2VyXCI6cmV0dXJuIExwO2Nhc2VcImF1dG9cIjpkZWZhdWx0OnJldHVybiBOYS5kZWZhdWx0JiYhTmEuaXNXZWJXb3JrZXImJiFOYS5pc1JlYWN0TmF0aXZlQnJvd3Nlcj9McDpVcH19O1J0LmRlZmF1bHQ9RnY7fSk7dmFyIERhPU0oT2k9Pnt2KCk7bSgpO18oKTt2YXIgV3Y9T2kmJk9pLl9faW1wb3J0RGVmYXVsdHx8ZnVuY3Rpb24odCl7cmV0dXJuIHQmJnQuX19lc01vZHVsZT90OntkZWZhdWx0OnR9fTtPYmplY3QuZGVmaW5lUHJvcGVydHkoT2ksXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSk7dmFyICR2PVd2KE5wKCkpLHFhPWNsYXNze2NvbnN0cnVjdG9yKGUscixpKXt0aGlzLmtlZXBhbGl2ZT1lKjFlMyx0aGlzLmNoZWNrUGluZz1yLHRoaXMudGltZXI9KDAsICR2LmRlZmF1bHQpKGkpLHRoaXMucmVzY2hlZHVsZSgpO31jbGVhcigpe3RoaXMudGltZXJJZCYmKHRoaXMudGltZXIuY2xlYXIodGhpcy50aW1lcklkKSx0aGlzLnRpbWVySWQ9bnVsbCk7fXJlc2NoZWR1bGUoKXt0aGlzLmNsZWFyKCksdGhpcy50aW1lcklkPXRoaXMudGltZXIuc2V0KCgpPT57dGhpcy5jaGVja1BpbmcoKSx0aGlzLnRpbWVySWQmJnRoaXMucmVzY2hlZHVsZSgpO30sdGhpcy5rZWVwYWxpdmUpO319O09pLmRlZmF1bHQ9cWE7fSk7dmFyIG5zPU0oUWU9Pnt2KCk7bSgpO18oKTt2YXIgSHY9UWUmJlFlLl9fY3JlYXRlQmluZGluZ3x8KE9iamVjdC5jcmVhdGU/ZnVuY3Rpb24odCxlLHIsaSl7aT09PXZvaWQgMCYmKGk9cik7dmFyIG49T2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihlLHIpOyghbnx8KFwiZ2V0XCJpbiBuPyFlLl9fZXNNb2R1bGU6bi53cml0YWJsZXx8bi5jb25maWd1cmFibGUpKSYmKG49e2VudW1lcmFibGU6ITAsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIGVbcl19fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KHQsaSxuKTt9OmZ1bmN0aW9uKHQsZSxyLGkpe2k9PT12b2lkIDAmJihpPXIpLHRbaV09ZVtyXTt9KSxWdj1RZSYmUWUuX19zZXRNb2R1bGVEZWZhdWx0fHwoT2JqZWN0LmNyZWF0ZT9mdW5jdGlvbih0LGUpe09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LFwiZGVmYXVsdFwiLHtlbnVtZXJhYmxlOiEwLHZhbHVlOmV9KTt9OmZ1bmN0aW9uKHQsZSl7dC5kZWZhdWx0PWU7fSksV3A9UWUmJlFlLl9faW1wb3J0U3Rhcnx8ZnVuY3Rpb24odCl7aWYodCYmdC5fX2VzTW9kdWxlKXJldHVybiB0O3ZhciBlPXt9O2lmKHQhPW51bGwpZm9yKHZhciByIGluIHQpciE9PVwiZGVmYXVsdFwiJiZPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCxyKSYmSHYoZSx0LHIpO3JldHVybiBWdihlLHQpLGV9LFZ0PVFlJiZRZS5fX2ltcG9ydERlZmF1bHR8fGZ1bmN0aW9uKHQpe3JldHVybiB0JiZ0Ll9fZXNNb2R1bGU/dDp7ZGVmYXVsdDp0fX07T2JqZWN0LmRlZmluZVByb3BlcnR5KFFlLFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO3ZhciB6dj1WdChHdSgpKSxqYT1WdChOZCgpKSxLdj1WdChZbygpKSxHdj1EdCgpLHFwPVZ0KEZkKCkpLERwPVdwKCRkKCkpLFF2PVZ0KG90KCkpLHJzPVZ0KFpvKCkpLFl2PVZ0KEFwKCkpLFdhPUpyKCksSnY9SXAoKSxYdj1WdChEYSgpKSxqcD1XcChQaSgpKSxGYT1nbG9iYWxUaGlzLnNldEltbWVkaWF0ZXx8KCguLi50KT0+e2xldCBlPXQuc2hpZnQoKTsoMCwgV2EubmV4dFRpY2spKCgpPT57ZSguLi50KTt9KTt9KSxGcD17a2VlcGFsaXZlOjYwLHJlc2NoZWR1bGVQaW5nczohMCxwcm90b2NvbElkOlwiTVFUVFwiLHByb3RvY29sVmVyc2lvbjo0LHJlY29ubmVjdFBlcmlvZDoxZTMsY29ubmVjdFRpbWVvdXQ6MzAqMWUzLGNsZWFuOiEwLHJlc3Vic2NyaWJlOiEwLHdyaXRlQ2FjaGU6ITAsdGltZXJWYXJpYW50OlwiYXV0b1wifSxpcz1jbGFzcyB0IGV4dGVuZHMgSnYuVHlwZWRFdmVudEVtaXR0ZXJ7c3RhdGljIGRlZmF1bHRJZCgpe3JldHVybiBgbXF0dGpzXyR7TWF0aC5yYW5kb20oKS50b1N0cmluZygxNikuc3Vic3RyKDIsOCl9YH1jb25zdHJ1Y3RvcihlLHIpe3N1cGVyKCksdGhpcy5vcHRpb25zPXJ8fHt9O2ZvcihsZXQgaSBpbiBGcCl0eXBlb2YgdGhpcy5vcHRpb25zW2ldPlwidVwiP3RoaXMub3B0aW9uc1tpXT1GcFtpXTp0aGlzLm9wdGlvbnNbaV09cltpXTt0aGlzLmxvZz10aGlzLm9wdGlvbnMubG9nfHwoMCwgUXYuZGVmYXVsdCkoXCJtcXR0anM6Y2xpZW50XCIpLHRoaXMubm9vcD10aGlzLl9ub29wLmJpbmQodGhpcyksdGhpcy5sb2coXCJNcXR0Q2xpZW50IDo6IHZlcnNpb246XCIsdC5WRVJTSU9OKSxqcC5pc1dlYldvcmtlcj90aGlzLmxvZyhcIk1xdHRDbGllbnQgOjogZW52aXJvbm1lbnRcIixcIndlYndvcmtlclwiKTp0aGlzLmxvZyhcIk1xdHRDbGllbnQgOjogZW52aXJvbm1lbnRcIixqcC5kZWZhdWx0P1wiYnJvd3NlclwiOlwibm9kZVwiKSx0aGlzLmxvZyhcIk1xdHRDbGllbnQgOjogb3B0aW9ucy5wcm90b2NvbFwiLHIucHJvdG9jb2wpLHRoaXMubG9nKFwiTXF0dENsaWVudCA6OiBvcHRpb25zLnByb3RvY29sVmVyc2lvblwiLHIucHJvdG9jb2xWZXJzaW9uKSx0aGlzLmxvZyhcIk1xdHRDbGllbnQgOjogb3B0aW9ucy51c2VybmFtZVwiLHIudXNlcm5hbWUpLHRoaXMubG9nKFwiTXF0dENsaWVudCA6OiBvcHRpb25zLmtlZXBhbGl2ZVwiLHIua2VlcGFsaXZlKSx0aGlzLmxvZyhcIk1xdHRDbGllbnQgOjogb3B0aW9ucy5yZWNvbm5lY3RQZXJpb2RcIixyLnJlY29ubmVjdFBlcmlvZCksdGhpcy5sb2coXCJNcXR0Q2xpZW50IDo6IG9wdGlvbnMucmVqZWN0VW5hdXRob3JpemVkXCIsci5yZWplY3RVbmF1dGhvcml6ZWQpLHRoaXMubG9nKFwiTXF0dENsaWVudCA6OiBvcHRpb25zLnByb3BlcnRpZXMudG9waWNBbGlhc01heGltdW1cIixyLnByb3BlcnRpZXM/ci5wcm9wZXJ0aWVzLnRvcGljQWxpYXNNYXhpbXVtOnZvaWQgMCksdGhpcy5vcHRpb25zLmNsaWVudElkPXR5cGVvZiByLmNsaWVudElkPT1cInN0cmluZ1wiP3IuY2xpZW50SWQ6dC5kZWZhdWx0SWQoKSx0aGlzLmxvZyhcIk1xdHRDbGllbnQgOjogY2xpZW50SWRcIix0aGlzLm9wdGlvbnMuY2xpZW50SWQpLHRoaXMub3B0aW9ucy5jdXN0b21IYW5kbGVBY2tzPXIucHJvdG9jb2xWZXJzaW9uPT09NSYmci5jdXN0b21IYW5kbGVBY2tzP3IuY3VzdG9tSGFuZGxlQWNrczooLi4uaSk9PntpWzNdKG51bGwsMCk7fSx0aGlzLm9wdGlvbnMud3JpdGVDYWNoZXx8KGphLmRlZmF1bHQud3JpdGVUb1N0cmVhbS5jYWNoZU51bWJlcnM9ITEpLHRoaXMuc3RyZWFtQnVpbGRlcj1lLHRoaXMubWVzc2FnZUlkUHJvdmlkZXI9dHlwZW9mIHRoaXMub3B0aW9ucy5tZXNzYWdlSWRQcm92aWRlcj5cInVcIj9uZXcgS3YuZGVmYXVsdDp0aGlzLm9wdGlvbnMubWVzc2FnZUlkUHJvdmlkZXIsdGhpcy5vdXRnb2luZ1N0b3JlPXIub3V0Z29pbmdTdG9yZXx8bmV3IHJzLmRlZmF1bHQsdGhpcy5pbmNvbWluZ1N0b3JlPXIuaW5jb21pbmdTdG9yZXx8bmV3IHJzLmRlZmF1bHQsdGhpcy5xdWV1ZVFvU1plcm89ci5xdWV1ZVFvU1plcm89PT12b2lkIDA/ITA6ci5xdWV1ZVFvU1plcm8sdGhpcy5fcmVzdWJzY3JpYmVUb3BpY3M9e30sdGhpcy5tZXNzYWdlSWRUb1RvcGljPXt9LHRoaXMucGluZ1RpbWVyPW51bGwsdGhpcy5jb25uZWN0ZWQ9ITEsdGhpcy5kaXNjb25uZWN0aW5nPSExLHRoaXMucmVjb25uZWN0aW5nPSExLHRoaXMucXVldWU9W10sdGhpcy5jb25uYWNrVGltZXI9bnVsbCx0aGlzLnJlY29ubmVjdFRpbWVyPW51bGwsdGhpcy5fc3RvcmVQcm9jZXNzaW5nPSExLHRoaXMuX3BhY2tldElkc0R1cmluZ1N0b3JlUHJvY2Vzc2luZz17fSx0aGlzLl9zdG9yZVByb2Nlc3NpbmdRdWV1ZT1bXSx0aGlzLm91dGdvaW5nPXt9LHRoaXMuX2ZpcnN0Q29ubmVjdGlvbj0hMCxyLnByb3BlcnRpZXMmJnIucHJvcGVydGllcy50b3BpY0FsaWFzTWF4aW11bT4wJiYoci5wcm9wZXJ0aWVzLnRvcGljQWxpYXNNYXhpbXVtPjY1NTM1P3RoaXMubG9nKFwiTXF0dENsaWVudCA6OiBvcHRpb25zLnByb3BlcnRpZXMudG9waWNBbGlhc01heGltdW0gaXMgb3V0IG9mIHJhbmdlXCIpOnRoaXMudG9waWNBbGlhc1JlY3Y9bmV3IHp2LmRlZmF1bHQoci5wcm9wZXJ0aWVzLnRvcGljQWxpYXNNYXhpbXVtKSksdGhpcy5vbihcImNvbm5lY3RcIiwoKT0+e2xldHtxdWV1ZTppfT10aGlzLG49KCk9PntsZXQgbz1pLnNoaWZ0KCk7dGhpcy5sb2coXCJkZWxpdmVyIDo6IGVudHJ5ICVvXCIsbyk7bGV0IHM9bnVsbDtpZighbyl7dGhpcy5fcmVzdWJzY3JpYmUoKTtyZXR1cm59cz1vLnBhY2tldCx0aGlzLmxvZyhcImRlbGl2ZXIgOjogY2FsbCBfc2VuZFBhY2tldCBmb3IgJW9cIixzKTtsZXQgYT0hMDtzLm1lc3NhZ2VJZCYmcy5tZXNzYWdlSWQhPT0wJiYodGhpcy5tZXNzYWdlSWRQcm92aWRlci5yZWdpc3RlcihzLm1lc3NhZ2VJZCl8fChhPSExKSksYT90aGlzLl9zZW5kUGFja2V0KHMsdT0+e28uY2ImJm8uY2IodSksbigpO30pOih0aGlzLmxvZyhcIm1lc3NhZ2VJZDogJWQgaGFzIGFscmVhZHkgdXNlZC4gVGhlIG1lc3NhZ2UgaXMgc2tpcHBlZCBhbmQgcmVtb3ZlZC5cIixzLm1lc3NhZ2VJZCksbigpKTt9O3RoaXMubG9nKFwiY29ubmVjdCA6OiBzZW5kaW5nIHF1ZXVlZCBwYWNrZXRzXCIpLG4oKTt9KSx0aGlzLm9uKFwiY2xvc2VcIiwoKT0+e3RoaXMubG9nKFwiY2xvc2UgOjogY29ubmVjdGVkIHNldCB0byBgZmFsc2VgXCIpLHRoaXMuY29ubmVjdGVkPSExLHRoaXMubG9nKFwiY2xvc2UgOjogY2xlYXJpbmcgY29ubmFja1RpbWVyXCIpLGNsZWFyVGltZW91dCh0aGlzLmNvbm5hY2tUaW1lciksdGhpcy5sb2coXCJjbG9zZSA6OiBjbGVhcmluZyBwaW5nIHRpbWVyXCIpLHRoaXMucGluZ1RpbWVyJiYodGhpcy5waW5nVGltZXIuY2xlYXIoKSx0aGlzLnBpbmdUaW1lcj1udWxsKSx0aGlzLnRvcGljQWxpYXNSZWN2JiZ0aGlzLnRvcGljQWxpYXNSZWN2LmNsZWFyKCksdGhpcy5sb2coXCJjbG9zZSA6OiBjYWxsaW5nIF9zZXR1cFJlY29ubmVjdFwiKSx0aGlzLl9zZXR1cFJlY29ubmVjdCgpO30pLHRoaXMub3B0aW9ucy5tYW51YWxDb25uZWN0fHwodGhpcy5sb2coXCJNcXR0Q2xpZW50IDo6IHNldHRpbmcgdXAgc3RyZWFtXCIpLHRoaXMuY29ubmVjdCgpKTt9aGFuZGxlQXV0aChlLHIpe3IoKTt9aGFuZGxlTWVzc2FnZShlLHIpe3IoKTt9X25leHRJZCgpe3JldHVybiB0aGlzLm1lc3NhZ2VJZFByb3ZpZGVyLmFsbG9jYXRlKCl9Z2V0TGFzdE1lc3NhZ2VJZCgpe3JldHVybiB0aGlzLm1lc3NhZ2VJZFByb3ZpZGVyLmdldExhc3RBbGxvY2F0ZWQoKX1jb25uZWN0KCl7dmFyIGU7bGV0IHI9bmV3IEd2LldyaXRhYmxlLGk9amEuZGVmYXVsdC5wYXJzZXIodGhpcy5vcHRpb25zKSxuPW51bGwsbz1bXTt0aGlzLmxvZyhcImNvbm5lY3QgOjogY2FsbGluZyBtZXRob2QgdG8gY2xlYXIgcmVjb25uZWN0XCIpLHRoaXMuX2NsZWFyUmVjb25uZWN0KCksdGhpcy5sb2coXCJjb25uZWN0IDo6IHVzaW5nIHN0cmVhbUJ1aWxkZXIgcHJvdmlkZWQgdG8gY2xpZW50IHRvIGNyZWF0ZSBzdHJlYW1cIiksdGhpcy5zdHJlYW09dGhpcy5zdHJlYW1CdWlsZGVyKHRoaXMpLGkub24oXCJwYWNrZXRcIixoPT57dGhpcy5sb2coXCJwYXJzZXIgOjogb24gcGFja2V0IHB1c2ggdG8gcGFja2V0cyBhcnJheS5cIiksby5wdXNoKGgpO30pO2xldCBzPSgpPT57dGhpcy5sb2coXCJ3b3JrIDo6IGdldHRpbmcgbmV4dCBwYWNrZXQgaW4gcXVldWVcIik7bGV0IGg9by5zaGlmdCgpO2lmKGgpdGhpcy5sb2coXCJ3b3JrIDo6IHBhY2tldCBwdWxsZWQgZnJvbSBxdWV1ZVwiKSwoMCwgWXYuZGVmYXVsdCkodGhpcyxoLGEpO2Vsc2Uge3RoaXMubG9nKFwid29yayA6OiBubyBwYWNrZXRzIGluIHF1ZXVlXCIpO2xldCBkPW47bj1udWxsLHRoaXMubG9nKFwid29yayA6OiBkb25lIGZsYWcgaXMgJXNcIiwhIWQpLGQmJmQoKTt9fSxhPSgpPT57aWYoby5sZW5ndGgpKDAsIFdhLm5leHRUaWNrKShzKTtlbHNlIHtsZXQgaD1uO249bnVsbCxoKCk7fX07ci5fd3JpdGU9KGgsZCxnKT0+e249Zyx0aGlzLmxvZyhcIndyaXRhYmxlIHN0cmVhbSA6OiBwYXJzaW5nIGJ1ZmZlclwiKSxpLnBhcnNlKGgpLHMoKTt9O2xldCB1PWg9Pnt0aGlzLmxvZyhcInN0cmVhbUVycm9ySGFuZGxlciA6OiBlcnJvclwiLGgubWVzc2FnZSksaC5jb2RlPyh0aGlzLmxvZyhcInN0cmVhbUVycm9ySGFuZGxlciA6OiBlbWl0dGluZyBlcnJvclwiKSx0aGlzLmVtaXQoXCJlcnJvclwiLGgpKTp0aGlzLm5vb3AoaCk7fTt0aGlzLmxvZyhcImNvbm5lY3QgOjogcGlwZSBzdHJlYW0gdG8gd3JpdGFibGUgc3RyZWFtXCIpLHRoaXMuc3RyZWFtLnBpcGUociksdGhpcy5zdHJlYW0ub24oXCJlcnJvclwiLHUpLHRoaXMuc3RyZWFtLm9uKFwiY2xvc2VcIiwoKT0+e3RoaXMubG9nKFwiKCVzKXN0cmVhbSA6OiBvbiBjbG9zZVwiLHRoaXMub3B0aW9ucy5jbGllbnRJZCksdGhpcy5fZmx1c2hWb2xhdGlsZSgpLHRoaXMubG9nKFwic3RyZWFtOiBlbWl0IGNsb3NlIHRvIE1xdHRDbGllbnRcIiksdGhpcy5lbWl0KFwiY2xvc2VcIik7fSksdGhpcy5sb2coXCJjb25uZWN0OiBzZW5kaW5nIHBhY2tldCBgY29ubmVjdGBcIik7bGV0IGM9e2NtZDpcImNvbm5lY3RcIixwcm90b2NvbElkOnRoaXMub3B0aW9ucy5wcm90b2NvbElkLHByb3RvY29sVmVyc2lvbjp0aGlzLm9wdGlvbnMucHJvdG9jb2xWZXJzaW9uLGNsZWFuOnRoaXMub3B0aW9ucy5jbGVhbixjbGllbnRJZDp0aGlzLm9wdGlvbnMuY2xpZW50SWQsa2VlcGFsaXZlOnRoaXMub3B0aW9ucy5rZWVwYWxpdmUsdXNlcm5hbWU6dGhpcy5vcHRpb25zLnVzZXJuYW1lLHBhc3N3b3JkOnRoaXMub3B0aW9ucy5wYXNzd29yZCxwcm9wZXJ0aWVzOnRoaXMub3B0aW9ucy5wcm9wZXJ0aWVzfTtpZih0aGlzLm9wdGlvbnMud2lsbCYmKGMud2lsbD1PYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sdGhpcy5vcHRpb25zLndpbGwpLHtwYXlsb2FkOihlPXRoaXMub3B0aW9ucy53aWxsKT09PW51bGx8fGU9PT12b2lkIDA/dm9pZCAwOmUucGF5bG9hZH0pKSx0aGlzLnRvcGljQWxpYXNSZWN2JiYoYy5wcm9wZXJ0aWVzfHwoYy5wcm9wZXJ0aWVzPXt9KSx0aGlzLnRvcGljQWxpYXNSZWN2JiYoYy5wcm9wZXJ0aWVzLnRvcGljQWxpYXNNYXhpbXVtPXRoaXMudG9waWNBbGlhc1JlY3YubWF4KSksdGhpcy5fd3JpdGVQYWNrZXQoYyksaS5vbihcImVycm9yXCIsdGhpcy5lbWl0LmJpbmQodGhpcyxcImVycm9yXCIpKSx0aGlzLm9wdGlvbnMucHJvcGVydGllcyl7aWYoIXRoaXMub3B0aW9ucy5wcm9wZXJ0aWVzLmF1dGhlbnRpY2F0aW9uTWV0aG9kJiZ0aGlzLm9wdGlvbnMucHJvcGVydGllcy5hdXRoZW50aWNhdGlvbkRhdGEpcmV0dXJuIHRoaXMuZW5kKCgpPT50aGlzLmVtaXQoXCJlcnJvclwiLG5ldyBFcnJvcihcIlBhY2tldCBoYXMgbm8gQXV0aGVudGljYXRpb24gTWV0aG9kXCIpKSksdGhpcztpZih0aGlzLm9wdGlvbnMucHJvcGVydGllcy5hdXRoZW50aWNhdGlvbk1ldGhvZCYmdGhpcy5vcHRpb25zLmF1dGhQYWNrZXQmJnR5cGVvZiB0aGlzLm9wdGlvbnMuYXV0aFBhY2tldD09XCJvYmplY3RcIil7bGV0IGg9T2JqZWN0LmFzc2lnbih7Y21kOlwiYXV0aFwiLHJlYXNvbkNvZGU6MH0sdGhpcy5vcHRpb25zLmF1dGhQYWNrZXQpO3RoaXMuX3dyaXRlUGFja2V0KGgpO319cmV0dXJuIHRoaXMuc3RyZWFtLnNldE1heExpc3RlbmVycygxZTMpLGNsZWFyVGltZW91dCh0aGlzLmNvbm5hY2tUaW1lciksdGhpcy5jb25uYWNrVGltZXI9c2V0VGltZW91dCgoKT0+e3RoaXMubG9nKFwiISFjb25uZWN0VGltZW91dCBoaXQhISBDYWxsaW5nIF9jbGVhblVwIHdpdGggZm9yY2UgYHRydWVgXCIpLHRoaXMuZW1pdChcImVycm9yXCIsbmV3IEVycm9yKFwiY29ubmFjayB0aW1lb3V0XCIpKSx0aGlzLl9jbGVhblVwKCEwKTt9LHRoaXMub3B0aW9ucy5jb25uZWN0VGltZW91dCksdGhpc31wdWJsaXNoKGUscixpLG4pe3RoaXMubG9nKFwicHVibGlzaCA6OiBtZXNzYWdlIGAlc2AgdG8gdG9waWMgYCVzYFwiLHIsZSk7bGV0e29wdGlvbnM6b309dGhpczt0eXBlb2YgaT09XCJmdW5jdGlvblwiJiYobj1pLGk9bnVsbCksaT1pfHx7fSxpPU9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSx7cW9zOjAscmV0YWluOiExLGR1cDohMX0pLGkpO2xldHtxb3M6YSxyZXRhaW46dSxkdXA6Yyxwcm9wZXJ0aWVzOmgsY2JTdG9yZVB1dDpkfT1pO2lmKHRoaXMuX2NoZWNrRGlzY29ubmVjdGluZyhuKSlyZXR1cm4gdGhpcztsZXQgZz0oKT0+e2xldCB5PTA7aWYoKGE9PT0xfHxhPT09MikmJih5PXRoaXMuX25leHRJZCgpLHk9PT1udWxsKSlyZXR1cm4gdGhpcy5sb2coXCJObyBtZXNzYWdlSWQgbGVmdFwiKSwhMTtsZXQgdz17Y21kOlwicHVibGlzaFwiLHRvcGljOmUscGF5bG9hZDpyLHFvczphLHJldGFpbjp1LG1lc3NhZ2VJZDp5LGR1cDpjfTtzd2l0Y2goby5wcm90b2NvbFZlcnNpb249PT01JiYody5wcm9wZXJ0aWVzPWgpLHRoaXMubG9nKFwicHVibGlzaCA6OiBxb3NcIixhKSxhKXtjYXNlIDE6Y2FzZSAyOnRoaXMub3V0Z29pbmdbdy5tZXNzYWdlSWRdPXt2b2xhdGlsZTohMSxjYjpufHx0aGlzLm5vb3B9LHRoaXMubG9nKFwiTXF0dENsaWVudDpwdWJsaXNoOiBwYWNrZXQgY21kOiAlc1wiLHcuY21kKSx0aGlzLl9zZW5kUGFja2V0KHcsdm9pZCAwLGQpO2JyZWFrO2RlZmF1bHQ6dGhpcy5sb2coXCJNcXR0Q2xpZW50OnB1Ymxpc2g6IHBhY2tldCBjbWQ6ICVzXCIsdy5jbWQpLHRoaXMuX3NlbmRQYWNrZXQodyxuLGQpO2JyZWFrfXJldHVybiAhMH07cmV0dXJuICh0aGlzLl9zdG9yZVByb2Nlc3Npbmd8fHRoaXMuX3N0b3JlUHJvY2Vzc2luZ1F1ZXVlLmxlbmd0aD4wfHwhZygpKSYmdGhpcy5fc3RvcmVQcm9jZXNzaW5nUXVldWUucHVzaCh7aW52b2tlOmcsY2JTdG9yZVB1dDppLmNiU3RvcmVQdXQsY2FsbGJhY2s6bn0pLHRoaXN9cHVibGlzaEFzeW5jKGUscixpKXtyZXR1cm4gbmV3IFByb21pc2UoKG4sbyk9Pnt0aGlzLnB1Ymxpc2goZSxyLGksKHMsYSk9PntzP28ocyk6bihhKTt9KTt9KX1zdWJzY3JpYmUoZSxyLGkpe2xldCBuPXRoaXMub3B0aW9ucy5wcm90b2NvbFZlcnNpb247dHlwZW9mIHI9PVwiZnVuY3Rpb25cIiYmKGk9ciksaT1pfHx0aGlzLm5vb3A7bGV0IG89ITEscz1bXTt0eXBlb2YgZT09XCJzdHJpbmdcIj8oZT1bZV0scz1lKTpBcnJheS5pc0FycmF5KGUpP3M9ZTp0eXBlb2YgZT09XCJvYmplY3RcIiYmKG89ZS5yZXN1YnNjcmliZSxkZWxldGUgZS5yZXN1YnNjcmliZSxzPU9iamVjdC5rZXlzKGUpKTtsZXQgYT1EcC52YWxpZGF0ZVRvcGljcyhzKTtpZihhIT09bnVsbClyZXR1cm4gRmEoaSxuZXcgRXJyb3IoYEludmFsaWQgdG9waWMgJHthfWApKSx0aGlzO2lmKHRoaXMuX2NoZWNrRGlzY29ubmVjdGluZyhpKSlyZXR1cm4gdGhpcy5sb2coXCJzdWJzY3JpYmU6IGRpc2Njb25lY3RpbmcgdHJ1ZVwiKSx0aGlzO2xldCB1PXtxb3M6MH07bj09PTUmJih1Lm5sPSExLHUucmFwPSExLHUucmg9MCkscj1PYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sdSkscik7bGV0IGM9ci5wcm9wZXJ0aWVzLGg9W10sZD0oeSx3KT0+e2lmKHc9d3x8ciwhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXMuX3Jlc3Vic2NyaWJlVG9waWNzLHkpfHx0aGlzLl9yZXN1YnNjcmliZVRvcGljc1t5XS5xb3M8dy5xb3N8fG8pe2xldCBFPXt0b3BpYzp5LHFvczp3LnFvc307bj09PTUmJihFLm5sPXcubmwsRS5yYXA9dy5yYXAsRS5yaD13LnJoLEUucHJvcGVydGllcz1jKSx0aGlzLmxvZyhcInN1YnNjcmliZTogcHVzaGluZyB0b3BpYyBgJXNgIGFuZCBxb3MgYCVzYCB0byBzdWJzIGxpc3RcIixFLnRvcGljLEUucW9zKSxoLnB1c2goRSk7fX07aWYoQXJyYXkuaXNBcnJheShlKT9lLmZvckVhY2goeT0+e3RoaXMubG9nKFwic3Vic2NyaWJlOiBhcnJheSB0b3BpYyAlc1wiLHkpLGQoeSk7fSk6T2JqZWN0LmtleXMoZSkuZm9yRWFjaCh5PT57dGhpcy5sb2coXCJzdWJzY3JpYmU6IG9iamVjdCB0b3BpYyAlcywgJW9cIix5LGVbeV0pLGQoeSxlW3ldKTt9KSwhaC5sZW5ndGgpcmV0dXJuIGkobnVsbCxbXSksdGhpcztsZXQgZz0oKT0+e2xldCB5PXRoaXMuX25leHRJZCgpO2lmKHk9PT1udWxsKXJldHVybiB0aGlzLmxvZyhcIk5vIG1lc3NhZ2VJZCBsZWZ0XCIpLCExO2xldCB3PXtjbWQ6XCJzdWJzY3JpYmVcIixzdWJzY3JpcHRpb25zOmgsbWVzc2FnZUlkOnl9O2lmKGMmJih3LnByb3BlcnRpZXM9YyksdGhpcy5vcHRpb25zLnJlc3Vic2NyaWJlKXt0aGlzLmxvZyhcInN1YnNjcmliZSA6OiByZXN1YnNjcmliZSB0cnVlXCIpO2xldCBFPVtdO2guZm9yRWFjaChTPT57aWYodGhpcy5vcHRpb25zLnJlY29ubmVjdFBlcmlvZD4wKXtsZXQgST17cW9zOlMucW9zfTtuPT09NSYmKEkubmw9Uy5ubHx8ITEsSS5yYXA9Uy5yYXB8fCExLEkucmg9Uy5yaHx8MCxJLnByb3BlcnRpZXM9Uy5wcm9wZXJ0aWVzKSx0aGlzLl9yZXN1YnNjcmliZVRvcGljc1tTLnRvcGljXT1JLEUucHVzaChTLnRvcGljKTt9fSksdGhpcy5tZXNzYWdlSWRUb1RvcGljW3cubWVzc2FnZUlkXT1FO31yZXR1cm4gdGhpcy5vdXRnb2luZ1t3Lm1lc3NhZ2VJZF09e3ZvbGF0aWxlOiEwLGNiKEUsUyl7aWYoIUUpe2xldHtncmFudGVkOkl9PVM7Zm9yKGxldCBDPTA7QzxJLmxlbmd0aDtDKz0xKWhbQ10ucW9zPUlbQ107fWkoRSxoKTt9fSx0aGlzLmxvZyhcInN1YnNjcmliZSA6OiBjYWxsIF9zZW5kUGFja2V0XCIpLHRoaXMuX3NlbmRQYWNrZXQodyksITB9O3JldHVybiAodGhpcy5fc3RvcmVQcm9jZXNzaW5nfHx0aGlzLl9zdG9yZVByb2Nlc3NpbmdRdWV1ZS5sZW5ndGg+MHx8IWcoKSkmJnRoaXMuX3N0b3JlUHJvY2Vzc2luZ1F1ZXVlLnB1c2goe2ludm9rZTpnLGNhbGxiYWNrOml9KSx0aGlzfXN1YnNjcmliZUFzeW5jKGUscil7cmV0dXJuIG5ldyBQcm9taXNlKChpLG4pPT57dGhpcy5zdWJzY3JpYmUoZSxyLChvLHMpPT57bz9uKG8pOmkocyk7fSk7fSl9dW5zdWJzY3JpYmUoZSxyLGkpe3R5cGVvZiBlPT1cInN0cmluZ1wiJiYoZT1bZV0pLHR5cGVvZiByPT1cImZ1bmN0aW9uXCImJihpPXIpLGk9aXx8dGhpcy5ub29wO2xldCBuPURwLnZhbGlkYXRlVG9waWNzKGUpO2lmKG4hPT1udWxsKXJldHVybiBGYShpLG5ldyBFcnJvcihgSW52YWxpZCB0b3BpYyAke259YCkpLHRoaXM7aWYodGhpcy5fY2hlY2tEaXNjb25uZWN0aW5nKGkpKXJldHVybiB0aGlzO2xldCBvPSgpPT57bGV0IHM9dGhpcy5fbmV4dElkKCk7aWYocz09PW51bGwpcmV0dXJuIHRoaXMubG9nKFwiTm8gbWVzc2FnZUlkIGxlZnRcIiksITE7bGV0IGE9e2NtZDpcInVuc3Vic2NyaWJlXCIsbWVzc2FnZUlkOnMsdW5zdWJzY3JpcHRpb25zOltdfTtyZXR1cm4gdHlwZW9mIGU9PVwic3RyaW5nXCI/YS51bnN1YnNjcmlwdGlvbnM9W2VdOkFycmF5LmlzQXJyYXkoZSkmJihhLnVuc3Vic2NyaXB0aW9ucz1lKSx0aGlzLm9wdGlvbnMucmVzdWJzY3JpYmUmJmEudW5zdWJzY3JpcHRpb25zLmZvckVhY2godT0+e2RlbGV0ZSB0aGlzLl9yZXN1YnNjcmliZVRvcGljc1t1XTt9KSx0eXBlb2Ygcj09XCJvYmplY3RcIiYmci5wcm9wZXJ0aWVzJiYoYS5wcm9wZXJ0aWVzPXIucHJvcGVydGllcyksdGhpcy5vdXRnb2luZ1thLm1lc3NhZ2VJZF09e3ZvbGF0aWxlOiEwLGNiOml9LHRoaXMubG9nKFwidW5zdWJzY3JpYmU6IGNhbGwgX3NlbmRQYWNrZXRcIiksdGhpcy5fc2VuZFBhY2tldChhKSwhMH07cmV0dXJuICh0aGlzLl9zdG9yZVByb2Nlc3Npbmd8fHRoaXMuX3N0b3JlUHJvY2Vzc2luZ1F1ZXVlLmxlbmd0aD4wfHwhbygpKSYmdGhpcy5fc3RvcmVQcm9jZXNzaW5nUXVldWUucHVzaCh7aW52b2tlOm8sY2FsbGJhY2s6aX0pLHRoaXN9dW5zdWJzY3JpYmVBc3luYyhlLHIpe3JldHVybiBuZXcgUHJvbWlzZSgoaSxuKT0+e3RoaXMudW5zdWJzY3JpYmUoZSxyLChvLHMpPT57bz9uKG8pOmkocyk7fSk7fSl9ZW5kKGUscixpKXt0aGlzLmxvZyhcImVuZCA6OiAoJXMpXCIsdGhpcy5vcHRpb25zLmNsaWVudElkKSwoZT09bnVsbHx8dHlwZW9mIGUhPVwiYm9vbGVhblwiKSYmKGk9aXx8cixyPWUsZT0hMSksdHlwZW9mIHIhPVwib2JqZWN0XCImJihpPWl8fHIscj1udWxsKSx0aGlzLmxvZyhcImVuZCA6OiBjYj8gJXNcIiwhIWkpLCghaXx8dHlwZW9mIGkhPVwiZnVuY3Rpb25cIikmJihpPXRoaXMubm9vcCk7bGV0IG49KCk9Pnt0aGlzLmxvZyhcImVuZCA6OiBjbG9zZVN0b3JlczogY2xvc2luZyBpbmNvbWluZyBhbmQgb3V0Z29pbmcgc3RvcmVzXCIpLHRoaXMuZGlzY29ubmVjdGVkPSEwLHRoaXMuaW5jb21pbmdTdG9yZS5jbG9zZShzPT57dGhpcy5vdXRnb2luZ1N0b3JlLmNsb3NlKGE9PntpZih0aGlzLmxvZyhcImVuZCA6OiBjbG9zZVN0b3JlczogZW1pdHRpbmcgZW5kXCIpLHRoaXMuZW1pdChcImVuZFwiKSxpKXtsZXQgdT1zfHxhO3RoaXMubG9nKFwiZW5kIDo6IGNsb3NlU3RvcmVzOiBpbnZva2luZyBjYWxsYmFjayB3aXRoIGFyZ3NcIiksaSh1KTt9fSk7fSksdGhpcy5fZGVmZXJyZWRSZWNvbm5lY3QmJnRoaXMuX2RlZmVycmVkUmVjb25uZWN0KCk7fSxvPSgpPT57dGhpcy5sb2coXCJlbmQgOjogKCVzKSA6OiBmaW5pc2ggOjogY2FsbGluZyBfY2xlYW5VcCB3aXRoIGZvcmNlICVzXCIsdGhpcy5vcHRpb25zLmNsaWVudElkLGUpLHRoaXMuX2NsZWFuVXAoZSwoKT0+e3RoaXMubG9nKFwiZW5kIDo6IGZpbmlzaCA6OiBjYWxsaW5nIHByb2Nlc3MubmV4dFRpY2sgb24gY2xvc2VTdG9yZXNcIiksKDAsIFdhLm5leHRUaWNrKShuKTt9LHIpO307cmV0dXJuIHRoaXMuZGlzY29ubmVjdGluZz8oaSgpLHRoaXMpOih0aGlzLl9jbGVhclJlY29ubmVjdCgpLHRoaXMuZGlzY29ubmVjdGluZz0hMCwhZSYmT2JqZWN0LmtleXModGhpcy5vdXRnb2luZykubGVuZ3RoPjA/KHRoaXMubG9nKFwiZW5kIDo6ICglcykgOjogY2FsbGluZyBmaW5pc2ggaW4gMTBtcyBvbmNlIG91dGdvaW5nIGlzIGVtcHR5XCIsdGhpcy5vcHRpb25zLmNsaWVudElkKSx0aGlzLm9uY2UoXCJvdXRnb2luZ0VtcHR5XCIsc2V0VGltZW91dC5iaW5kKG51bGwsbywxMCkpKToodGhpcy5sb2coXCJlbmQgOjogKCVzKSA6OiBpbW1lZGlhdGVseSBjYWxsaW5nIGZpbmlzaFwiLHRoaXMub3B0aW9ucy5jbGllbnRJZCksbygpKSx0aGlzKX1lbmRBc3luYyhlLHIpe3JldHVybiBuZXcgUHJvbWlzZSgoaSxuKT0+e3RoaXMuZW5kKGUscixvPT57bz9uKG8pOmkoKTt9KTt9KX1yZW1vdmVPdXRnb2luZ01lc3NhZ2UoZSl7aWYodGhpcy5vdXRnb2luZ1tlXSl7bGV0e2NiOnJ9PXRoaXMub3V0Z29pbmdbZV07dGhpcy5fcmVtb3ZlT3V0Z29pbmdBbmRTdG9yZU1lc3NhZ2UoZSwoKT0+e3IobmV3IEVycm9yKFwiTWVzc2FnZSByZW1vdmVkXCIpKTt9KTt9cmV0dXJuIHRoaXN9cmVjb25uZWN0KGUpe3RoaXMubG9nKFwiY2xpZW50IHJlY29ubmVjdFwiKTtsZXQgcj0oKT0+e2U/KHRoaXMub3B0aW9ucy5pbmNvbWluZ1N0b3JlPWUuaW5jb21pbmdTdG9yZSx0aGlzLm9wdGlvbnMub3V0Z29pbmdTdG9yZT1lLm91dGdvaW5nU3RvcmUpOih0aGlzLm9wdGlvbnMuaW5jb21pbmdTdG9yZT1udWxsLHRoaXMub3B0aW9ucy5vdXRnb2luZ1N0b3JlPW51bGwpLHRoaXMuaW5jb21pbmdTdG9yZT10aGlzLm9wdGlvbnMuaW5jb21pbmdTdG9yZXx8bmV3IHJzLmRlZmF1bHQsdGhpcy5vdXRnb2luZ1N0b3JlPXRoaXMub3B0aW9ucy5vdXRnb2luZ1N0b3JlfHxuZXcgcnMuZGVmYXVsdCx0aGlzLmRpc2Nvbm5lY3Rpbmc9ITEsdGhpcy5kaXNjb25uZWN0ZWQ9ITEsdGhpcy5fZGVmZXJyZWRSZWNvbm5lY3Q9bnVsbCx0aGlzLl9yZWNvbm5lY3QoKTt9O3JldHVybiB0aGlzLmRpc2Nvbm5lY3RpbmcmJiF0aGlzLmRpc2Nvbm5lY3RlZD90aGlzLl9kZWZlcnJlZFJlY29ubmVjdD1yOnIoKSx0aGlzfV9mbHVzaFZvbGF0aWxlKCl7dGhpcy5vdXRnb2luZyYmKHRoaXMubG9nKFwiX2ZsdXNoVm9sYXRpbGUgOjogZGVsZXRpbmcgdm9sYXRpbGUgbWVzc2FnZXMgZnJvbSB0aGUgcXVldWUgYW5kIHNldHRpbmcgdGhlaXIgY2FsbGJhY2tzIGFzIGVycm9yIGZ1bmN0aW9uXCIpLE9iamVjdC5rZXlzKHRoaXMub3V0Z29pbmcpLmZvckVhY2goZT0+e3RoaXMub3V0Z29pbmdbZV0udm9sYXRpbGUmJnR5cGVvZiB0aGlzLm91dGdvaW5nW2VdLmNiPT1cImZ1bmN0aW9uXCImJih0aGlzLm91dGdvaW5nW2VdLmNiKG5ldyBFcnJvcihcIkNvbm5lY3Rpb24gY2xvc2VkXCIpKSxkZWxldGUgdGhpcy5vdXRnb2luZ1tlXSk7fSkpO31fZmx1c2goKXt0aGlzLm91dGdvaW5nJiYodGhpcy5sb2coXCJfZmx1c2g6IHF1ZXVlIGV4aXN0cz8gJWJcIiwhIXRoaXMub3V0Z29pbmcpLE9iamVjdC5rZXlzKHRoaXMub3V0Z29pbmcpLmZvckVhY2goZT0+e3R5cGVvZiB0aGlzLm91dGdvaW5nW2VdLmNiPT1cImZ1bmN0aW9uXCImJih0aGlzLm91dGdvaW5nW2VdLmNiKG5ldyBFcnJvcihcIkNvbm5lY3Rpb24gY2xvc2VkXCIpKSxkZWxldGUgdGhpcy5vdXRnb2luZ1tlXSk7fSkpO31fcmVtb3ZlVG9waWNBbGlhc0FuZFJlY292ZXJUb3BpY05hbWUoZSl7bGV0IHI7ZS5wcm9wZXJ0aWVzJiYocj1lLnByb3BlcnRpZXMudG9waWNBbGlhcyk7bGV0IGk9ZS50b3BpYy50b1N0cmluZygpO2lmKHRoaXMubG9nKFwiX3JlbW92ZVRvcGljQWxpYXNBbmRSZWNvdmVyVG9waWNOYW1lIDo6IGFsaWFzICVkLCB0b3BpYyAlb1wiLHIsaSksaS5sZW5ndGg9PT0wKXtpZih0eXBlb2Ygcj5cInVcIilyZXR1cm4gbmV3IEVycm9yKFwiVW5yZWdpc3RlcmVkIFRvcGljIEFsaWFzXCIpO2lmKGk9dGhpcy50b3BpY0FsaWFzU2VuZC5nZXRUb3BpY0J5QWxpYXMociksdHlwZW9mIGk+XCJ1XCIpcmV0dXJuIG5ldyBFcnJvcihcIlVucmVnaXN0ZXJlZCBUb3BpYyBBbGlhc1wiKTtlLnRvcGljPWk7fXImJmRlbGV0ZSBlLnByb3BlcnRpZXMudG9waWNBbGlhczt9X2NoZWNrRGlzY29ubmVjdGluZyhlKXtyZXR1cm4gdGhpcy5kaXNjb25uZWN0aW5nJiYoZSYmZSE9PXRoaXMubm9vcD9lKG5ldyBFcnJvcihcImNsaWVudCBkaXNjb25uZWN0aW5nXCIpKTp0aGlzLmVtaXQoXCJlcnJvclwiLG5ldyBFcnJvcihcImNsaWVudCBkaXNjb25uZWN0aW5nXCIpKSksdGhpcy5kaXNjb25uZWN0aW5nfV9yZWNvbm5lY3QoKXt0aGlzLmxvZyhcIl9yZWNvbm5lY3Q6IGVtaXR0aW5nIHJlY29ubmVjdCB0byBjbGllbnRcIiksdGhpcy5lbWl0KFwicmVjb25uZWN0XCIpLHRoaXMuY29ubmVjdGVkPyh0aGlzLmVuZCgoKT0+e3RoaXMuY29ubmVjdCgpO30pLHRoaXMubG9nKFwiY2xpZW50IGFscmVhZHkgY29ubmVjdGVkLiBkaXNjb25uZWN0aW5nIGZpcnN0LlwiKSk6KHRoaXMubG9nKFwiX3JlY29ubmVjdDogY2FsbGluZyBjb25uZWN0XCIpLHRoaXMuY29ubmVjdCgpKTt9X3NldHVwUmVjb25uZWN0KCl7IXRoaXMuZGlzY29ubmVjdGluZyYmIXRoaXMucmVjb25uZWN0VGltZXImJnRoaXMub3B0aW9ucy5yZWNvbm5lY3RQZXJpb2Q+MD8odGhpcy5yZWNvbm5lY3Rpbmd8fCh0aGlzLmxvZyhcIl9zZXR1cFJlY29ubmVjdCA6OiBlbWl0IGBvZmZsaW5lYCBzdGF0ZVwiKSx0aGlzLmVtaXQoXCJvZmZsaW5lXCIpLHRoaXMubG9nKFwiX3NldHVwUmVjb25uZWN0IDo6IHNldCBgcmVjb25uZWN0aW5nYCB0byBgdHJ1ZWBcIiksdGhpcy5yZWNvbm5lY3Rpbmc9ITApLHRoaXMubG9nKFwiX3NldHVwUmVjb25uZWN0IDo6IHNldHRpbmcgcmVjb25uZWN0VGltZXIgZm9yICVkIG1zXCIsdGhpcy5vcHRpb25zLnJlY29ubmVjdFBlcmlvZCksdGhpcy5yZWNvbm5lY3RUaW1lcj1zZXRJbnRlcnZhbCgoKT0+e3RoaXMubG9nKFwicmVjb25uZWN0VGltZXIgOjogcmVjb25uZWN0IHRyaWdnZXJlZCFcIiksdGhpcy5fcmVjb25uZWN0KCk7fSx0aGlzLm9wdGlvbnMucmVjb25uZWN0UGVyaW9kKSk6dGhpcy5sb2coXCJfc2V0dXBSZWNvbm5lY3QgOjogZG9pbmcgbm90aGluZy4uLlwiKTt9X2NsZWFyUmVjb25uZWN0KCl7dGhpcy5sb2coXCJfY2xlYXJSZWNvbm5lY3QgOiBjbGVhcmluZyByZWNvbm5lY3QgdGltZXJcIiksdGhpcy5yZWNvbm5lY3RUaW1lciYmKGNsZWFySW50ZXJ2YWwodGhpcy5yZWNvbm5lY3RUaW1lciksdGhpcy5yZWNvbm5lY3RUaW1lcj1udWxsKTt9X2NsZWFuVXAoZSxyLGk9e30pe2lmKHImJih0aGlzLmxvZyhcIl9jbGVhblVwIDo6IGRvbmUgY2FsbGJhY2sgcHJvdmlkZWQgZm9yIG9uIHN0cmVhbSBjbG9zZVwiKSx0aGlzLnN0cmVhbS5vbihcImNsb3NlXCIscikpLHRoaXMubG9nKFwiX2NsZWFuVXAgOjogZm9yY2VkPyAlc1wiLGUpLGUpdGhpcy5vcHRpb25zLnJlY29ubmVjdFBlcmlvZD09PTAmJnRoaXMub3B0aW9ucy5jbGVhbiYmdGhpcy5fZmx1c2goKSx0aGlzLmxvZyhcIl9jbGVhblVwIDo6ICglcykgOjogZGVzdHJveWluZyBzdHJlYW1cIix0aGlzLm9wdGlvbnMuY2xpZW50SWQpLHRoaXMuc3RyZWFtLmRlc3Ryb3koKTtlbHNlIHtsZXQgbj1PYmplY3QuYXNzaWduKHtjbWQ6XCJkaXNjb25uZWN0XCJ9LGkpO3RoaXMubG9nKFwiX2NsZWFuVXAgOjogKCVzKSA6OiBjYWxsIF9zZW5kUGFja2V0IHdpdGggZGlzY29ubmVjdCBwYWNrZXRcIix0aGlzLm9wdGlvbnMuY2xpZW50SWQpLHRoaXMuX3NlbmRQYWNrZXQobiwoKT0+e3RoaXMubG9nKFwiX2NsZWFuVXAgOjogKCVzKSA6OiBkZXN0cm95aW5nIHN0cmVhbVwiLHRoaXMub3B0aW9ucy5jbGllbnRJZCksRmEoKCk9Pnt0aGlzLnN0cmVhbS5lbmQoKCk9Pnt0aGlzLmxvZyhcIl9jbGVhblVwIDo6ICglcykgOjogc3RyZWFtIGRlc3Ryb3llZFwiLHRoaXMub3B0aW9ucy5jbGllbnRJZCk7fSk7fSk7fSk7fSF0aGlzLmRpc2Nvbm5lY3RpbmcmJiF0aGlzLnJlY29ubmVjdGluZyYmKHRoaXMubG9nKFwiX2NsZWFuVXAgOjogY2xpZW50IG5vdCBkaXNjb25uZWN0aW5nL3JlY29ubmVjdGluZy4gQ2xlYXJpbmcgYW5kIHJlc2V0dGluZyByZWNvbm5lY3QuXCIpLHRoaXMuX2NsZWFyUmVjb25uZWN0KCksdGhpcy5fc2V0dXBSZWNvbm5lY3QoKSksdGhpcy5waW5nVGltZXImJih0aGlzLmxvZyhcIl9jbGVhblVwIDo6IGNsZWFyaW5nIHBpbmdUaW1lclwiKSx0aGlzLnBpbmdUaW1lci5jbGVhcigpLHRoaXMucGluZ1RpbWVyPW51bGwpLHImJiF0aGlzLmNvbm5lY3RlZCYmKHRoaXMubG9nKFwiX2NsZWFuVXAgOjogKCVzKSA6OiByZW1vdmluZyBzdHJlYW0gYGRvbmVgIGNhbGxiYWNrIGBjbG9zZWAgbGlzdGVuZXJcIix0aGlzLm9wdGlvbnMuY2xpZW50SWQpLHRoaXMuc3RyZWFtLnJlbW92ZUxpc3RlbmVyKFwiY2xvc2VcIixyKSxyKCkpO31fc3RvcmVBbmRTZW5kKGUscixpKXt0aGlzLmxvZyhcInN0b3JlQW5kU2VuZCA6OiBzdG9yZSBwYWNrZXQgd2l0aCBjbWQgJXMgdG8gb3V0Z29pbmdTdG9yZVwiLGUuY21kKTtsZXQgbj1lLG87aWYobi5jbWQ9PT1cInB1Ymxpc2hcIiYmKG49KDAsIHFwLmRlZmF1bHQpKGUpLG89dGhpcy5fcmVtb3ZlVG9waWNBbGlhc0FuZFJlY292ZXJUb3BpY05hbWUobiksbykpcmV0dXJuIHImJnIobyk7dGhpcy5vdXRnb2luZ1N0b3JlLnB1dChuLHM9PntpZihzKXJldHVybiByJiZyKHMpO2koKSx0aGlzLl93cml0ZVBhY2tldChlLHIpO30pO31fYXBwbHlUb3BpY0FsaWFzKGUpe2lmKHRoaXMub3B0aW9ucy5wcm90b2NvbFZlcnNpb249PT01JiZlLmNtZD09PVwicHVibGlzaFwiKXtsZXQgcjtlLnByb3BlcnRpZXMmJihyPWUucHJvcGVydGllcy50b3BpY0FsaWFzKTtsZXQgaT1lLnRvcGljLnRvU3RyaW5nKCk7aWYodGhpcy50b3BpY0FsaWFzU2VuZClpZihyKXtpZihpLmxlbmd0aCE9PTAmJih0aGlzLmxvZyhcImFwcGx5VG9waWNBbGlhcyA6OiByZWdpc3RlciB0b3BpYzogJXMgLSBhbGlhczogJWRcIixpLHIpLCF0aGlzLnRvcGljQWxpYXNTZW5kLnB1dChpLHIpKSlyZXR1cm4gdGhpcy5sb2coXCJhcHBseVRvcGljQWxpYXMgOjogZXJyb3Igb3V0IG9mIHJhbmdlLiB0b3BpYzogJXMgLSBhbGlhczogJWRcIixpLHIpLG5ldyBFcnJvcihcIlNlbmRpbmcgVG9waWMgQWxpYXMgb3V0IG9mIHJhbmdlXCIpfWVsc2UgaS5sZW5ndGghPT0wJiYodGhpcy5vcHRpb25zLmF1dG9Bc3NpZ25Ub3BpY0FsaWFzPyhyPXRoaXMudG9waWNBbGlhc1NlbmQuZ2V0QWxpYXNCeVRvcGljKGkpLHI/KGUudG9waWM9XCJcIixlLnByb3BlcnRpZXM9T2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGUucHJvcGVydGllcykse3RvcGljQWxpYXM6cn0pLHRoaXMubG9nKFwiYXBwbHlUb3BpY0FsaWFzIDo6IGF1dG8gYXNzaWduKHVzZSkgdG9waWM6ICVzIC0gYWxpYXM6ICVkXCIsaSxyKSk6KHI9dGhpcy50b3BpY0FsaWFzU2VuZC5nZXRMcnVBbGlhcygpLHRoaXMudG9waWNBbGlhc1NlbmQucHV0KGksciksZS5wcm9wZXJ0aWVzPU9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxlLnByb3BlcnRpZXMpLHt0b3BpY0FsaWFzOnJ9KSx0aGlzLmxvZyhcImFwcGx5VG9waWNBbGlhcyA6OiBhdXRvIGFzc2lnbiB0b3BpYzogJXMgLSBhbGlhczogJWRcIixpLHIpKSk6dGhpcy5vcHRpb25zLmF1dG9Vc2VUb3BpY0FsaWFzJiYocj10aGlzLnRvcGljQWxpYXNTZW5kLmdldEFsaWFzQnlUb3BpYyhpKSxyJiYoZS50b3BpYz1cIlwiLGUucHJvcGVydGllcz1PYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sZS5wcm9wZXJ0aWVzKSx7dG9waWNBbGlhczpyfSksdGhpcy5sb2coXCJhcHBseVRvcGljQWxpYXMgOjogYXV0byB1c2UgdG9waWM6ICVzIC0gYWxpYXM6ICVkXCIsaSxyKSkpKTtlbHNlIGlmKHIpcmV0dXJuIHRoaXMubG9nKFwiYXBwbHlUb3BpY0FsaWFzIDo6IGVycm9yIG91dCBvZiByYW5nZS4gdG9waWM6ICVzIC0gYWxpYXM6ICVkXCIsaSxyKSxuZXcgRXJyb3IoXCJTZW5kaW5nIFRvcGljIEFsaWFzIG91dCBvZiByYW5nZVwiKX19X25vb3AoZSl7dGhpcy5sb2coXCJub29wIDo6XCIsZSk7fV93cml0ZVBhY2tldChlLHIpe3RoaXMubG9nKFwiX3dyaXRlUGFja2V0IDo6IHBhY2tldDogJU9cIixlKSx0aGlzLmxvZyhcIl93cml0ZVBhY2tldCA6OiBlbWl0dGluZyBgcGFja2V0c2VuZGBcIiksdGhpcy5lbWl0KFwicGFja2V0c2VuZFwiLGUpLHRoaXMuX3NoaWZ0UGluZ0ludGVydmFsKCksdGhpcy5sb2coXCJfd3JpdGVQYWNrZXQgOjogd3JpdGluZyB0byBzdHJlYW1cIik7bGV0IGk9amEuZGVmYXVsdC53cml0ZVRvU3RyZWFtKGUsdGhpcy5zdHJlYW0sdGhpcy5vcHRpb25zKTt0aGlzLmxvZyhcIl93cml0ZVBhY2tldCA6OiB3cml0ZVRvU3RyZWFtIHJlc3VsdCAlc1wiLGkpLCFpJiZyJiZyIT09dGhpcy5ub29wPyh0aGlzLmxvZyhcIl93cml0ZVBhY2tldCA6OiBoYW5kbGUgZXZlbnRzIG9uIGBkcmFpbmAgb25jZSB0aHJvdWdoIGNhbGxiYWNrLlwiKSx0aGlzLnN0cmVhbS5vbmNlKFwiZHJhaW5cIixyKSk6ciYmKHRoaXMubG9nKFwiX3dyaXRlUGFja2V0IDo6IGludm9raW5nIGNiXCIpLHIoKSk7fV9zZW5kUGFja2V0KGUscixpLG4pe3RoaXMubG9nKFwiX3NlbmRQYWNrZXQgOjogKCVzKSA6OiAgc3RhcnRcIix0aGlzLm9wdGlvbnMuY2xpZW50SWQpLGk9aXx8dGhpcy5ub29wLHI9cnx8dGhpcy5ub29wO2xldCBvPXRoaXMuX2FwcGx5VG9waWNBbGlhcyhlKTtpZihvKXtyKG8pO3JldHVybn1pZighdGhpcy5jb25uZWN0ZWQpe2lmKGUuY21kPT09XCJhdXRoXCIpe3RoaXMuX3dyaXRlUGFja2V0KGUscik7cmV0dXJufXRoaXMubG9nKFwiX3NlbmRQYWNrZXQgOjogY2xpZW50IG5vdCBjb25uZWN0ZWQuIFN0b3JpbmcgcGFja2V0IG9mZmxpbmUuXCIpLHRoaXMuX3N0b3JlUGFja2V0KGUscixpKTtyZXR1cm59aWYobil7dGhpcy5fd3JpdGVQYWNrZXQoZSxyKTtyZXR1cm59c3dpdGNoKGUuY21kKXtjYXNlXCJwdWJsaXNoXCI6YnJlYWs7Y2FzZVwicHVicmVsXCI6dGhpcy5fc3RvcmVBbmRTZW5kKGUscixpKTtyZXR1cm47ZGVmYXVsdDp0aGlzLl93cml0ZVBhY2tldChlLHIpO3JldHVybn1zd2l0Y2goZS5xb3Mpe2Nhc2UgMjpjYXNlIDE6dGhpcy5fc3RvcmVBbmRTZW5kKGUscixpKTticmVhaztjYXNlIDA6ZGVmYXVsdDp0aGlzLl93cml0ZVBhY2tldChlLHIpO2JyZWFrfXRoaXMubG9nKFwiX3NlbmRQYWNrZXQgOjogKCVzKSA6OiAgZW5kXCIsdGhpcy5vcHRpb25zLmNsaWVudElkKTt9X3N0b3JlUGFja2V0KGUscixpKXt0aGlzLmxvZyhcIl9zdG9yZVBhY2tldCA6OiBwYWNrZXQ6ICVvXCIsZSksdGhpcy5sb2coXCJfc3RvcmVQYWNrZXQgOjogY2I/ICVzXCIsISFyKSxpPWl8fHRoaXMubm9vcDtsZXQgbj1lO2lmKG4uY21kPT09XCJwdWJsaXNoXCIpe249KDAsIHFwLmRlZmF1bHQpKGUpO2xldCBzPXRoaXMuX3JlbW92ZVRvcGljQWxpYXNBbmRSZWNvdmVyVG9waWNOYW1lKG4pO2lmKHMpcmV0dXJuIHImJnIocyl9bGV0IG89bi5xb3N8fDA7bz09PTAmJnRoaXMucXVldWVRb1NaZXJvfHxuLmNtZCE9PVwicHVibGlzaFwiP3RoaXMucXVldWUucHVzaCh7cGFja2V0Om4sY2I6cn0pOm8+MD8ocj10aGlzLm91dGdvaW5nW24ubWVzc2FnZUlkXT90aGlzLm91dGdvaW5nW24ubWVzc2FnZUlkXS5jYjpudWxsLHRoaXMub3V0Z29pbmdTdG9yZS5wdXQobixzPT57aWYocylyZXR1cm4gciYmcihzKTtpKCk7fSkpOnImJnIobmV3IEVycm9yKFwiTm8gY29ubmVjdGlvbiB0byBicm9rZXJcIikpO31fc2V0dXBQaW5nVGltZXIoKXt0aGlzLmxvZyhcIl9zZXR1cFBpbmdUaW1lciA6OiBrZWVwYWxpdmUgJWQgKHNlY29uZHMpXCIsdGhpcy5vcHRpb25zLmtlZXBhbGl2ZSksIXRoaXMucGluZ1RpbWVyJiZ0aGlzLm9wdGlvbnMua2VlcGFsaXZlJiYodGhpcy5waW5nUmVzcD0hMCx0aGlzLnBpbmdUaW1lcj1uZXcgWHYuZGVmYXVsdCh0aGlzLm9wdGlvbnMua2VlcGFsaXZlLCgpPT57dGhpcy5fY2hlY2tQaW5nKCk7fSx0aGlzLm9wdGlvbnMudGltZXJWYXJpYW50KSk7fV9zaGlmdFBpbmdJbnRlcnZhbCgpe3RoaXMucGluZ1RpbWVyJiZ0aGlzLm9wdGlvbnMua2VlcGFsaXZlJiZ0aGlzLm9wdGlvbnMucmVzY2hlZHVsZVBpbmdzJiZ0aGlzLnBpbmdUaW1lci5yZXNjaGVkdWxlKCk7fV9jaGVja1BpbmcoKXt0aGlzLmxvZyhcIl9jaGVja1BpbmcgOjogY2hlY2tpbmcgcGluZy4uLlwiKSx0aGlzLnBpbmdSZXNwPyh0aGlzLmxvZyhcIl9jaGVja1BpbmcgOjogcGluZyByZXNwb25zZSByZWNlaXZlZC4gQ2xlYXJpbmcgZmxhZyBhbmQgc2VuZGluZyBgcGluZ3JlcWBcIiksdGhpcy5waW5nUmVzcD0hMSx0aGlzLl9zZW5kUGFja2V0KHtjbWQ6XCJwaW5ncmVxXCJ9KSk6KHRoaXMuZW1pdChcImVycm9yXCIsbmV3IEVycm9yKFwiS2VlcGFsaXZlIHRpbWVvdXRcIikpLHRoaXMubG9nKFwiX2NoZWNrUGluZyA6OiBjYWxsaW5nIF9jbGVhblVwIHdpdGggZm9yY2UgdHJ1ZVwiKSx0aGlzLl9jbGVhblVwKCEwKSk7fV9yZXN1YnNjcmliZSgpe3RoaXMubG9nKFwiX3Jlc3Vic2NyaWJlXCIpO2xldCBlPU9iamVjdC5rZXlzKHRoaXMuX3Jlc3Vic2NyaWJlVG9waWNzKTtpZighdGhpcy5fZmlyc3RDb25uZWN0aW9uJiYodGhpcy5vcHRpb25zLmNsZWFufHx0aGlzLm9wdGlvbnMucHJvdG9jb2xWZXJzaW9uPj00JiYhdGhpcy5jb25uYWNrUGFja2V0LnNlc3Npb25QcmVzZW50KSYmZS5sZW5ndGg+MClpZih0aGlzLm9wdGlvbnMucmVzdWJzY3JpYmUpaWYodGhpcy5vcHRpb25zLnByb3RvY29sVmVyc2lvbj09PTUpe3RoaXMubG9nKFwiX3Jlc3Vic2NyaWJlOiBwcm90b2NvbFZlcnNpb24gNVwiKTtmb3IobGV0IHI9MDtyPGUubGVuZ3RoO3IrKyl7bGV0IGk9e307aVtlW3JdXT10aGlzLl9yZXN1YnNjcmliZVRvcGljc1tlW3JdXSxpLnJlc3Vic2NyaWJlPSEwLHRoaXMuc3Vic2NyaWJlKGkse3Byb3BlcnRpZXM6aVtlW3JdXS5wcm9wZXJ0aWVzfSk7fX1lbHNlIHRoaXMuX3Jlc3Vic2NyaWJlVG9waWNzLnJlc3Vic2NyaWJlPSEwLHRoaXMuc3Vic2NyaWJlKHRoaXMuX3Jlc3Vic2NyaWJlVG9waWNzKTtlbHNlIHRoaXMuX3Jlc3Vic2NyaWJlVG9waWNzPXt9O3RoaXMuX2ZpcnN0Q29ubmVjdGlvbj0hMTt9X29uQ29ubmVjdChlKXtpZih0aGlzLmRpc2Nvbm5lY3RlZCl7dGhpcy5lbWl0KFwiY29ubmVjdFwiLGUpO3JldHVybn10aGlzLmNvbm5hY2tQYWNrZXQ9ZSx0aGlzLm1lc3NhZ2VJZFByb3ZpZGVyLmNsZWFyKCksdGhpcy5fc2V0dXBQaW5nVGltZXIoKSx0aGlzLmNvbm5lY3RlZD0hMDtsZXQgcj0oKT0+e2xldCBpPXRoaXMub3V0Z29pbmdTdG9yZS5jcmVhdGVTdHJlYW0oKSxuPSgpPT57aS5kZXN0cm95KCksaT1udWxsLHRoaXMuX2ZsdXNoU3RvcmVQcm9jZXNzaW5nUXVldWUoKSxvKCk7fSxvPSgpPT57dGhpcy5fc3RvcmVQcm9jZXNzaW5nPSExLHRoaXMuX3BhY2tldElkc0R1cmluZ1N0b3JlUHJvY2Vzc2luZz17fTt9O3RoaXMub25jZShcImNsb3NlXCIsbiksaS5vbihcImVycm9yXCIsYT0+e28oKSx0aGlzLl9mbHVzaFN0b3JlUHJvY2Vzc2luZ1F1ZXVlKCksdGhpcy5yZW1vdmVMaXN0ZW5lcihcImNsb3NlXCIsbiksdGhpcy5lbWl0KFwiZXJyb3JcIixhKTt9KTtsZXQgcz0oKT0+e2lmKCFpKXJldHVybjtsZXQgYT1pLnJlYWQoMSksdTtpZighYSl7aS5vbmNlKFwicmVhZGFibGVcIixzKTtyZXR1cm59aWYodGhpcy5fc3RvcmVQcm9jZXNzaW5nPSEwLHRoaXMuX3BhY2tldElkc0R1cmluZ1N0b3JlUHJvY2Vzc2luZ1thLm1lc3NhZ2VJZF0pe3MoKTtyZXR1cm59IXRoaXMuZGlzY29ubmVjdGluZyYmIXRoaXMucmVjb25uZWN0VGltZXI/KHU9dGhpcy5vdXRnb2luZ1thLm1lc3NhZ2VJZF0/dGhpcy5vdXRnb2luZ1thLm1lc3NhZ2VJZF0uY2I6bnVsbCx0aGlzLm91dGdvaW5nW2EubWVzc2FnZUlkXT17dm9sYXRpbGU6ITEsY2IoYyxoKXt1JiZ1KGMsaCkscygpO319LHRoaXMuX3BhY2tldElkc0R1cmluZ1N0b3JlUHJvY2Vzc2luZ1thLm1lc3NhZ2VJZF09ITAsdGhpcy5tZXNzYWdlSWRQcm92aWRlci5yZWdpc3RlcihhLm1lc3NhZ2VJZCk/dGhpcy5fc2VuZFBhY2tldChhLHZvaWQgMCx2b2lkIDAsITApOnRoaXMubG9nKFwibWVzc2FnZUlkOiAlZCBoYXMgYWxyZWFkeSB1c2VkLlwiLGEubWVzc2FnZUlkKSk6aS5kZXN0cm95JiZpLmRlc3Ryb3koKTt9O2kub24oXCJlbmRcIiwoKT0+e2xldCBhPSEwO2ZvcihsZXQgdSBpbiB0aGlzLl9wYWNrZXRJZHNEdXJpbmdTdG9yZVByb2Nlc3NpbmcpaWYoIXRoaXMuX3BhY2tldElkc0R1cmluZ1N0b3JlUHJvY2Vzc2luZ1t1XSl7YT0hMTticmVha310aGlzLnJlbW92ZUxpc3RlbmVyKFwiY2xvc2VcIixuKSxhPyhvKCksdGhpcy5faW52b2tlQWxsU3RvcmVQcm9jZXNzaW5nUXVldWUoKSx0aGlzLmVtaXQoXCJjb25uZWN0XCIsZSkpOnIoKTt9KSxzKCk7fTtyKCk7fV9pbnZva2VTdG9yZVByb2Nlc3NpbmdRdWV1ZSgpe2lmKCF0aGlzLl9zdG9yZVByb2Nlc3NpbmcmJnRoaXMuX3N0b3JlUHJvY2Vzc2luZ1F1ZXVlLmxlbmd0aD4wKXtsZXQgZT10aGlzLl9zdG9yZVByb2Nlc3NpbmdRdWV1ZVswXTtpZihlJiZlLmludm9rZSgpKXJldHVybiB0aGlzLl9zdG9yZVByb2Nlc3NpbmdRdWV1ZS5zaGlmdCgpLCEwfXJldHVybiAhMX1faW52b2tlQWxsU3RvcmVQcm9jZXNzaW5nUXVldWUoKXtmb3IoO3RoaXMuX2ludm9rZVN0b3JlUHJvY2Vzc2luZ1F1ZXVlKCk7KTt9X2ZsdXNoU3RvcmVQcm9jZXNzaW5nUXVldWUoKXtmb3IobGV0IGUgb2YgdGhpcy5fc3RvcmVQcm9jZXNzaW5nUXVldWUpZS5jYlN0b3JlUHV0JiZlLmNiU3RvcmVQdXQobmV3IEVycm9yKFwiQ29ubmVjdGlvbiBjbG9zZWRcIikpLGUuY2FsbGJhY2smJmUuY2FsbGJhY2sobmV3IEVycm9yKFwiQ29ubmVjdGlvbiBjbG9zZWRcIikpO3RoaXMuX3N0b3JlUHJvY2Vzc2luZ1F1ZXVlLnNwbGljZSgwKTt9X3JlbW92ZU91dGdvaW5nQW5kU3RvcmVNZXNzYWdlKGUscil7ZGVsZXRlIHRoaXMub3V0Z29pbmdbZV0sdGhpcy5vdXRnb2luZ1N0b3JlLmRlbCh7bWVzc2FnZUlkOmV9LChpLG4pPT57cihpLG4pLHRoaXMubWVzc2FnZUlkUHJvdmlkZXIuZGVhbGxvY2F0ZShlKSx0aGlzLl9pbnZva2VTdG9yZVByb2Nlc3NpbmdRdWV1ZSgpO30pO319O2lzLlZFUlNJT049XCI1LjUuMlwiO1FlLmRlZmF1bHQ9aXM7fSk7dmFyICRwPU0oSGE9Pnt2KCk7bSgpO18oKTtPYmplY3QuZGVmaW5lUHJvcGVydHkoSGEsXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSk7dmFyIFp2PXhhKCksJGE9Y2xhc3N7Y29uc3RydWN0b3IoKXt0aGlzLm51bWJlckFsbG9jYXRvcj1uZXcgWnYuTnVtYmVyQWxsb2NhdG9yKDEsNjU1MzUpO31hbGxvY2F0ZSgpe3JldHVybiB0aGlzLmxhc3RJZD10aGlzLm51bWJlckFsbG9jYXRvci5hbGxvYygpLHRoaXMubGFzdElkfWdldExhc3RBbGxvY2F0ZWQoKXtyZXR1cm4gdGhpcy5sYXN0SWR9cmVnaXN0ZXIoZSl7cmV0dXJuIHRoaXMubnVtYmVyQWxsb2NhdG9yLnVzZShlKX1kZWFsbG9jYXRlKGUpe3RoaXMubnVtYmVyQWxsb2NhdG9yLmZyZWUoZSk7fWNsZWFyKCl7dGhpcy5udW1iZXJBbGxvY2F0b3IuY2xlYXIoKTt9fTtIYS5kZWZhdWx0PSRhO30pO2Z1bmN0aW9uIElyKHQpe3Rocm93IG5ldyBSYW5nZUVycm9yKGlFW3RdKX1mdW5jdGlvbiBIcCh0LGUpe2xldCByPXQuc3BsaXQoXCJAXCIpLGk9XCJcIjtyLmxlbmd0aD4xJiYoaT1yWzBdK1wiQFwiLHQ9clsxXSk7bGV0IG49ZnVuY3Rpb24obyxzKXtsZXQgYT1bXSx1PW8ubGVuZ3RoO2Zvcig7dS0tOylhW3VdPXMob1t1XSk7cmV0dXJuIGF9KCh0PXQucmVwbGFjZShyRSxcIi5cIikpLnNwbGl0KFwiLlwiKSxlKS5qb2luKFwiLlwiKTtyZXR1cm4gaStufWZ1bmN0aW9uIEdwKHQpe2xldCBlPVtdLHI9MCxpPXQubGVuZ3RoO2Zvcig7cjxpOyl7bGV0IG49dC5jaGFyQ29kZUF0KHIrKyk7aWYobj49NTUyOTYmJm48PTU2MzE5JiZyPGkpe2xldCBvPXQuY2hhckNvZGVBdChyKyspOyg2NDUxMiZvKT09NTYzMjA/ZS5wdXNoKCgoMTAyMyZuKTw8MTApKygxMDIzJm8pKzY1NTM2KTooZS5wdXNoKG4pLHItLSk7fWVsc2UgZS5wdXNoKG4pO31yZXR1cm4gZX12YXIgZUUsdEUsckUsaUUsaHQsVmEsVnAsUXAsenAsS3AsenQsWXA9d2UoKCk9Pnt2KCk7bSgpO18oKTtlRT0vXnhuLS0vLHRFPS9bXlxcMC1cXHg3RV0vLHJFPS9bXFx4MkVcXHUzMDAyXFx1RkYwRVxcdUZGNjFdL2csaUU9e292ZXJmbG93OlwiT3ZlcmZsb3c6IGlucHV0IG5lZWRzIHdpZGVyIGludGVnZXJzIHRvIHByb2Nlc3NcIixcIm5vdC1iYXNpY1wiOlwiSWxsZWdhbCBpbnB1dCA+PSAweDgwIChub3QgYSBiYXNpYyBjb2RlIHBvaW50KVwiLFwiaW52YWxpZC1pbnB1dFwiOlwiSW52YWxpZCBpbnB1dFwifSxodD1NYXRoLmZsb29yLFZhPVN0cmluZy5mcm9tQ2hhckNvZGU7VnA9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdCsyMis3NSoodDwyNiktKChlIT0wKTw8NSl9LFFwPWZ1bmN0aW9uKHQsZSxyKXtsZXQgaT0wO2Zvcih0PXI/aHQodC83MDApOnQ+PjEsdCs9aHQodC9lKTt0PjQ1NTtpKz0zNil0PWh0KHQvMzUpO3JldHVybiBodChpKzM2KnQvKHQrMzgpKX0senA9ZnVuY3Rpb24odCl7bGV0IGU9W10scj10Lmxlbmd0aCxpPTAsbj0xMjgsbz03MixzPXQubGFzdEluZGV4T2YoXCItXCIpO3M8MCYmKHM9MCk7Zm9yKGxldCB1PTA7dTxzOysrdSl0LmNoYXJDb2RlQXQodSk+PTEyOCYmSXIoXCJub3QtYmFzaWNcIiksZS5wdXNoKHQuY2hhckNvZGVBdCh1KSk7Zm9yKGxldCB1PXM+MD9zKzE6MDt1PHI7KXtsZXQgYz1pO2ZvcihsZXQgZD0xLGc9MzY7O2crPTM2KXt1Pj1yJiZJcihcImludmFsaWQtaW5wdXRcIik7bGV0IHk9KGE9dC5jaGFyQ29kZUF0KHUrKykpLTQ4PDEwP2EtMjI6YS02NTwyNj9hLTY1OmEtOTc8MjY/YS05NzozNjsoeT49MzZ8fHk+aHQoKDIxNDc0ODM2NDctaSkvZCkpJiZJcihcIm92ZXJmbG93XCIpLGkrPXkqZDtsZXQgdz1nPD1vPzE6Zz49bysyNj8yNjpnLW87aWYoeTx3KWJyZWFrO2xldCBFPTM2LXc7ZD5odCgyMTQ3NDgzNjQ3L0UpJiZJcihcIm92ZXJmbG93XCIpLGQqPUU7fWxldCBoPWUubGVuZ3RoKzE7bz1RcChpLWMsaCxjPT0wKSxodChpL2gpPjIxNDc0ODM2NDctbiYmSXIoXCJvdmVyZmxvd1wiKSxuKz1odChpL2gpLGklPWgsZS5zcGxpY2UoaSsrLDAsbik7fXZhciBhO3JldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludCguLi5lKX0sS3A9ZnVuY3Rpb24odCl7bGV0IGU9W10scj0odD1HcCh0KSkubGVuZ3RoLGk9MTI4LG49MCxvPTcyO2ZvcihsZXQgdSBvZiB0KXU8MTI4JiZlLnB1c2goVmEodSkpO2xldCBzPWUubGVuZ3RoLGE9cztmb3IocyYmZS5wdXNoKFwiLVwiKTthPHI7KXtsZXQgdT0yMTQ3NDgzNjQ3O2ZvcihsZXQgaCBvZiB0KWg+PWkmJmg8dSYmKHU9aCk7bGV0IGM9YSsxO3UtaT5odCgoMjE0NzQ4MzY0Ny1uKS9jKSYmSXIoXCJvdmVyZmxvd1wiKSxuKz0odS1pKSpjLGk9dTtmb3IobGV0IGggb2YgdClpZihoPGkmJisrbj4yMTQ3NDgzNjQ3JiZJcihcIm92ZXJmbG93XCIpLGg9PWkpe2xldCBkPW47Zm9yKGxldCBnPTM2OztnKz0zNil7bGV0IHk9Zzw9bz8xOmc+PW8rMjY/MjY6Zy1vO2lmKGQ8eSlicmVhaztsZXQgdz1kLXksRT0zNi15O2UucHVzaChWYShWcCh5K3clRSwwKSkpLGQ9aHQody9FKTt9ZS5wdXNoKFZhKFZwKGQsMCkpKSxvPVFwKG4sYyxhPT1zKSxuPTAsKythO30rK24sKytpO31yZXR1cm4gZS5qb2luKFwiXCIpfSx6dD17dmVyc2lvbjpcIjIuMS4wXCIsdWNzMjp7ZGVjb2RlOkdwLGVuY29kZTp0PT5TdHJpbmcuZnJvbUNvZGVQb2ludCguLi50KX0sZGVjb2RlOnpwLGVuY29kZTpLcCx0b0FTQ0lJOmZ1bmN0aW9uKHQpe3JldHVybiBIcCh0LGZ1bmN0aW9uKGUpe3JldHVybiB0RS50ZXN0KGUpP1wieG4tLVwiK0twKGUpOmV9KX0sdG9Vbmljb2RlOmZ1bmN0aW9uKHQpe3JldHVybiBIcCh0LGZ1bmN0aW9uKGUpe3JldHVybiBlRS50ZXN0KGUpP3pwKGUuc2xpY2UoNCkudG9Mb3dlckNhc2UoKSk6ZX0pfX07enQuZGVjb2RlO3p0LmVuY29kZTt6dC50b0FTQ0lJO3p0LnRvVW5pY29kZTt6dC51Y3MyO3p0LnZlcnNpb247fSk7ZnVuY3Rpb24gbkUodCxlKXtyZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHQsZSl9dmFyIHNFLGtpLG9FLGR0LEpwPXdlKCgpPT57digpO20oKTtfKCk7c0U9ZnVuY3Rpb24odCxlLHIsaSl7ZT1lfHxcIiZcIixyPXJ8fFwiPVwiO3ZhciBuPXt9O2lmKHR5cGVvZiB0IT1cInN0cmluZ1wifHx0Lmxlbmd0aD09PTApcmV0dXJuIG47dmFyIG89L1xcKy9nO3Q9dC5zcGxpdChlKTt2YXIgcz0xZTM7aSYmdHlwZW9mIGkubWF4S2V5cz09XCJudW1iZXJcIiYmKHM9aS5tYXhLZXlzKTt2YXIgYT10Lmxlbmd0aDtzPjAmJmE+cyYmKGE9cyk7Zm9yKHZhciB1PTA7dTxhOysrdSl7dmFyIGMsaCxkLGcseT10W3VdLnJlcGxhY2UobyxcIiUyMFwiKSx3PXkuaW5kZXhPZihyKTt3Pj0wPyhjPXkuc3Vic3RyKDAsdyksaD15LnN1YnN0cih3KzEpKTooYz15LGg9XCJcIiksZD1kZWNvZGVVUklDb21wb25lbnQoYyksZz1kZWNvZGVVUklDb21wb25lbnQoaCksbkUobixkKT9BcnJheS5pc0FycmF5KG5bZF0pP25bZF0ucHVzaChnKTpuW2RdPVtuW2RdLGddOm5bZF09Zzt9cmV0dXJuIG59LGtpPWZ1bmN0aW9uKHQpe3N3aXRjaCh0eXBlb2YgdCl7Y2FzZVwic3RyaW5nXCI6cmV0dXJuIHQ7Y2FzZVwiYm9vbGVhblwiOnJldHVybiB0P1widHJ1ZVwiOlwiZmFsc2VcIjtjYXNlXCJudW1iZXJcIjpyZXR1cm4gaXNGaW5pdGUodCk/dDpcIlwiO2RlZmF1bHQ6cmV0dXJuIFwiXCJ9fSxvRT1mdW5jdGlvbih0LGUscixpKXtyZXR1cm4gZT1lfHxcIiZcIixyPXJ8fFwiPVwiLHQ9PT1udWxsJiYodD12b2lkIDApLHR5cGVvZiB0PT1cIm9iamVjdFwiP09iamVjdC5rZXlzKHQpLm1hcChmdW5jdGlvbihuKXt2YXIgbz1lbmNvZGVVUklDb21wb25lbnQoa2kobikpK3I7cmV0dXJuIEFycmF5LmlzQXJyYXkodFtuXSk/dFtuXS5tYXAoZnVuY3Rpb24ocyl7cmV0dXJuIG8rZW5jb2RlVVJJQ29tcG9uZW50KGtpKHMpKX0pLmpvaW4oZSk6bytlbmNvZGVVUklDb21wb25lbnQoa2kodFtuXSkpfSkuam9pbihlKTppP2VuY29kZVVSSUNvbXBvbmVudChraShpKSkrcitlbmNvZGVVUklDb21wb25lbnQoa2kodCkpOlwiXCJ9LGR0PXt9O2R0LmRlY29kZT1kdC5wYXJzZT1zRSxkdC5lbmNvZGU9ZHQuc3RyaW5naWZ5PW9FO2R0LmRlY29kZTtkdC5lbmNvZGU7ZHQucGFyc2U7ZHQuc3RyaW5naWZ5O30pO2Z1bmN0aW9uIHphKCl7dGhyb3cgbmV3IEVycm9yKFwic2V0VGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZFwiKX1mdW5jdGlvbiBLYSgpe3Rocm93IG5ldyBFcnJvcihcImNsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZFwiKX1mdW5jdGlvbiBlZyh0KXtpZihCdD09PXNldFRpbWVvdXQpcmV0dXJuIHNldFRpbWVvdXQodCwwKTtpZigoQnQ9PT16YXx8IUJ0KSYmc2V0VGltZW91dClyZXR1cm4gQnQ9c2V0VGltZW91dCxzZXRUaW1lb3V0KHQsMCk7dHJ5e3JldHVybiBCdCh0LDApfWNhdGNoe3RyeXtyZXR1cm4gQnQuY2FsbChudWxsLHQsMCl9Y2F0Y2h7cmV0dXJuIEJ0LmNhbGwodGhpc3x8aWksdCwwKX19fWZ1bmN0aW9uIGFFKCl7cmkmJlRyJiYocmk9ITEsVHIubGVuZ3RoP090PVRyLmNvbmNhdChPdCk6c3M9LTEsT3QubGVuZ3RoJiZ0ZygpKTt9ZnVuY3Rpb24gdGcoKXtpZighcmkpe3ZhciB0PWVnKGFFKTtyaT0hMDtmb3IodmFyIGU9T3QubGVuZ3RoO2U7KXtmb3IoVHI9T3QsT3Q9W107KytzczxlOylUciYmVHJbc3NdLnJ1bigpO3NzPS0xLGU9T3QubGVuZ3RoO31Ucj1udWxsLHJpPSExLGZ1bmN0aW9uKHIpe2lmKFB0PT09Y2xlYXJUaW1lb3V0KXJldHVybiBjbGVhclRpbWVvdXQocik7aWYoKFB0PT09S2F8fCFQdCkmJmNsZWFyVGltZW91dClyZXR1cm4gUHQ9Y2xlYXJUaW1lb3V0LGNsZWFyVGltZW91dChyKTt0cnl7UHQocik7fWNhdGNoe3RyeXtyZXR1cm4gUHQuY2FsbChudWxsLHIpfWNhdGNoe3JldHVybiBQdC5jYWxsKHRoaXN8fGlpLHIpfX19KHQpO319ZnVuY3Rpb24gWHAodCxlKXsodGhpc3x8aWkpLmZ1bj10LCh0aGlzfHxpaSkuYXJyYXk9ZTt9ZnVuY3Rpb24gQ3QoKXt9dmFyIFpwLEJ0LFB0LGlpLGZlLFRyLE90LHJpLHNzLG5lLHJnPXdlKCgpPT57digpO20oKTtfKCk7aWk9dHlwZW9mIGdsb2JhbFRoaXM8XCJ1XCI/Z2xvYmFsVGhpczp0eXBlb2Ygc2VsZjxcInVcIj9zZWxmOmdsb2JhbCxmZT1acD17fTsoZnVuY3Rpb24oKXt0cnl7QnQ9dHlwZW9mIHNldFRpbWVvdXQ9PVwiZnVuY3Rpb25cIj9zZXRUaW1lb3V0OnphO31jYXRjaHtCdD16YTt9dHJ5e1B0PXR5cGVvZiBjbGVhclRpbWVvdXQ9PVwiZnVuY3Rpb25cIj9jbGVhclRpbWVvdXQ6S2E7fWNhdGNoe1B0PUthO319KSgpO090PVtdLHJpPSExLHNzPS0xO2ZlLm5leHRUaWNrPWZ1bmN0aW9uKHQpe3ZhciBlPW5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoLTEpO2lmKGFyZ3VtZW50cy5sZW5ndGg+MSlmb3IodmFyIHI9MTtyPGFyZ3VtZW50cy5sZW5ndGg7cisrKWVbci0xXT1hcmd1bWVudHNbcl07T3QucHVzaChuZXcgWHAodCxlKSksT3QubGVuZ3RoIT09MXx8cml8fGVnKHRnKTt9LFhwLnByb3RvdHlwZS5ydW49ZnVuY3Rpb24oKXsodGhpc3x8aWkpLmZ1bi5hcHBseShudWxsLCh0aGlzfHxpaSkuYXJyYXkpO30sZmUudGl0bGU9XCJicm93c2VyXCIsZmUuYnJvd3Nlcj0hMCxmZS5lbnY9e30sZmUuYXJndj1bXSxmZS52ZXJzaW9uPVwiXCIsZmUudmVyc2lvbnM9e30sZmUub249Q3QsZmUuYWRkTGlzdGVuZXI9Q3QsZmUub25jZT1DdCxmZS5vZmY9Q3QsZmUucmVtb3ZlTGlzdGVuZXI9Q3QsZmUucmVtb3ZlQWxsTGlzdGVuZXJzPUN0LGZlLmVtaXQ9Q3QsZmUucHJlcGVuZExpc3RlbmVyPUN0LGZlLnByZXBlbmRPbmNlTGlzdGVuZXI9Q3QsZmUubGlzdGVuZXJzPWZ1bmN0aW9uKHQpe3JldHVybiBbXX0sZmUuYmluZGluZz1mdW5jdGlvbih0KXt0aHJvdyBuZXcgRXJyb3IoXCJwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZFwiKX0sZmUuY3dkPWZ1bmN0aW9uKCl7cmV0dXJuIFwiL1wifSxmZS5jaGRpcj1mdW5jdGlvbih0KXt0aHJvdyBuZXcgRXJyb3IoXCJwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWRcIil9LGZlLnVtYXNrPWZ1bmN0aW9uKCl7cmV0dXJuIDB9O25lPVpwO25lLmFkZExpc3RlbmVyO25lLmFyZ3Y7bmUuYmluZGluZztuZS5icm93c2VyO25lLmNoZGlyO25lLmN3ZDtuZS5lbWl0O25lLmVudjtuZS5saXN0ZW5lcnM7bmUubmV4dFRpY2s7bmUub2ZmO25lLm9uO25lLm9uY2U7bmUucHJlcGVuZExpc3RlbmVyO25lLnByZXBlbmRPbmNlTGlzdGVuZXI7bmUucmVtb3ZlQWxsTGlzdGVuZXJzO25lLnJlbW92ZUxpc3RlbmVyO25lLnRpdGxlO25lLnVtYXNrO25lLnZlcnNpb247bmUudmVyc2lvbnM7fSk7ZnVuY3Rpb24gbEUoKXtpZihpZylyZXR1cm4gR2E7aWc9ITA7dmFyIHQ9R2E9e30sZSxyO2Z1bmN0aW9uIGkoKXt0aHJvdyBuZXcgRXJyb3IoXCJzZXRUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkXCIpfWZ1bmN0aW9uIG4oKXt0aHJvdyBuZXcgRXJyb3IoXCJjbGVhclRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWRcIil9KGZ1bmN0aW9uKCl7dHJ5e3R5cGVvZiBzZXRUaW1lb3V0PT1cImZ1bmN0aW9uXCI/ZT1zZXRUaW1lb3V0OmU9aTt9Y2F0Y2h7ZT1pO310cnl7dHlwZW9mIGNsZWFyVGltZW91dD09XCJmdW5jdGlvblwiP3I9Y2xlYXJUaW1lb3V0OnI9bjt9Y2F0Y2h7cj1uO319KSgpO2Z1bmN0aW9uIG8oRSl7aWYoZT09PXNldFRpbWVvdXQpcmV0dXJuIHNldFRpbWVvdXQoRSwwKTtpZigoZT09PWl8fCFlKSYmc2V0VGltZW91dClyZXR1cm4gZT1zZXRUaW1lb3V0LHNldFRpbWVvdXQoRSwwKTt0cnl7cmV0dXJuIGUoRSwwKX1jYXRjaHt0cnl7cmV0dXJuIGUuY2FsbChudWxsLEUsMCl9Y2F0Y2h7cmV0dXJuIGUuY2FsbCh0aGlzfHxuaSxFLDApfX19ZnVuY3Rpb24gcyhFKXtpZihyPT09Y2xlYXJUaW1lb3V0KXJldHVybiBjbGVhclRpbWVvdXQoRSk7aWYoKHI9PT1ufHwhcikmJmNsZWFyVGltZW91dClyZXR1cm4gcj1jbGVhclRpbWVvdXQsY2xlYXJUaW1lb3V0KEUpO3RyeXtyZXR1cm4gcihFKX1jYXRjaHt0cnl7cmV0dXJuIHIuY2FsbChudWxsLEUpfWNhdGNoe3JldHVybiByLmNhbGwodGhpc3x8bmksRSl9fX12YXIgYT1bXSx1PSExLGMsaD0tMTtmdW5jdGlvbiBkKCl7IXV8fCFjfHwodT0hMSxjLmxlbmd0aD9hPWMuY29uY2F0KGEpOmg9LTEsYS5sZW5ndGgmJmcoKSk7fWZ1bmN0aW9uIGcoKXtpZighdSl7dmFyIEU9byhkKTt1PSEwO2Zvcih2YXIgUz1hLmxlbmd0aDtTOyl7Zm9yKGM9YSxhPVtdOysraDxTOyljJiZjW2hdLnJ1bigpO2g9LTEsUz1hLmxlbmd0aDt9Yz1udWxsLHU9ITEscyhFKTt9fXQubmV4dFRpY2s9ZnVuY3Rpb24oRSl7dmFyIFM9bmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgtMSk7aWYoYXJndW1lbnRzLmxlbmd0aD4xKWZvcih2YXIgST0xO0k8YXJndW1lbnRzLmxlbmd0aDtJKyspU1tJLTFdPWFyZ3VtZW50c1tJXTthLnB1c2gobmV3IHkoRSxTKSksYS5sZW5ndGg9PT0xJiYhdSYmbyhnKTt9O2Z1bmN0aW9uIHkoRSxTKXsodGhpc3x8bmkpLmZ1bj1FLCh0aGlzfHxuaSkuYXJyYXk9Uzt9eS5wcm90b3R5cGUucnVuPWZ1bmN0aW9uKCl7KHRoaXN8fG5pKS5mdW4uYXBwbHkobnVsbCwodGhpc3x8bmkpLmFycmF5KTt9LHQudGl0bGU9XCJicm93c2VyXCIsdC5icm93c2VyPSEwLHQuZW52PXt9LHQuYXJndj1bXSx0LnZlcnNpb249XCJcIix0LnZlcnNpb25zPXt9O2Z1bmN0aW9uIHcoKXt9cmV0dXJuIHQub249dyx0LmFkZExpc3RlbmVyPXcsdC5vbmNlPXcsdC5vZmY9dyx0LnJlbW92ZUxpc3RlbmVyPXcsdC5yZW1vdmVBbGxMaXN0ZW5lcnM9dyx0LmVtaXQ9dyx0LnByZXBlbmRMaXN0ZW5lcj13LHQucHJlcGVuZE9uY2VMaXN0ZW5lcj13LHQubGlzdGVuZXJzPWZ1bmN0aW9uKEUpe3JldHVybiBbXX0sdC5iaW5kaW5nPWZ1bmN0aW9uKEUpe3Rocm93IG5ldyBFcnJvcihcInByb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkXCIpfSx0LmN3ZD1mdW5jdGlvbigpe3JldHVybiBcIi9cIn0sdC5jaGRpcj1mdW5jdGlvbihFKXt0aHJvdyBuZXcgRXJyb3IoXCJwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWRcIil9LHQudW1hc2s9ZnVuY3Rpb24oKXtyZXR1cm4gMH0sR2F9dmFyIEdhLGlnLG5pLHJlLFFhPXdlKCgpPT57digpO20oKTtfKCk7R2E9e30saWc9ITEsbmk9dHlwZW9mIGdsb2JhbFRoaXM8XCJ1XCI/Z2xvYmFsVGhpczp0eXBlb2Ygc2VsZjxcInVcIj9zZWxmOmdsb2JhbDtyZT1sRSgpO3JlLnBsYXRmb3JtPVwiYnJvd3NlclwiO3JlLmFkZExpc3RlbmVyO3JlLmFyZ3Y7cmUuYmluZGluZztyZS5icm93c2VyO3JlLmNoZGlyO3JlLmN3ZDtyZS5lbWl0O3JlLmVudjtyZS5saXN0ZW5lcnM7cmUubmV4dFRpY2s7cmUub2ZmO3JlLm9uO3JlLm9uY2U7cmUucHJlcGVuZExpc3RlbmVyO3JlLnByZXBlbmRPbmNlTGlzdGVuZXI7cmUucmVtb3ZlQWxsTGlzdGVuZXJzO3JlLnJlbW92ZUxpc3RlbmVyO3JlLnRpdGxlO3JlLnVtYXNrO3JlLnZlcnNpb247cmUudmVyc2lvbnM7fSk7ZnVuY3Rpb24gdUUoKXtpZihuZylyZXR1cm4gWWE7bmc9ITA7dmFyIHQ9cmU7ZnVuY3Rpb24gZShvKXtpZih0eXBlb2YgbyE9XCJzdHJpbmdcIil0aHJvdyBuZXcgVHlwZUVycm9yKFwiUGF0aCBtdXN0IGJlIGEgc3RyaW5nLiBSZWNlaXZlZCBcIitKU09OLnN0cmluZ2lmeShvKSl9ZnVuY3Rpb24gcihvLHMpe2Zvcih2YXIgYT1cIlwiLHU9MCxjPS0xLGg9MCxkLGc9MDtnPD1vLmxlbmd0aDsrK2cpe2lmKGc8by5sZW5ndGgpZD1vLmNoYXJDb2RlQXQoZyk7ZWxzZSB7aWYoZD09PTQ3KWJyZWFrO2Q9NDc7fWlmKGQ9PT00Nyl7aWYoIShjPT09Zy0xfHxoPT09MSkpaWYoYyE9PWctMSYmaD09PTIpe2lmKGEubGVuZ3RoPDJ8fHUhPT0yfHxhLmNoYXJDb2RlQXQoYS5sZW5ndGgtMSkhPT00Nnx8YS5jaGFyQ29kZUF0KGEubGVuZ3RoLTIpIT09NDYpe2lmKGEubGVuZ3RoPjIpe3ZhciB5PWEubGFzdEluZGV4T2YoXCIvXCIpO2lmKHkhPT1hLmxlbmd0aC0xKXt5PT09LTE/KGE9XCJcIix1PTApOihhPWEuc2xpY2UoMCx5KSx1PWEubGVuZ3RoLTEtYS5sYXN0SW5kZXhPZihcIi9cIikpLGM9ZyxoPTA7Y29udGludWV9fWVsc2UgaWYoYS5sZW5ndGg9PT0yfHxhLmxlbmd0aD09PTEpe2E9XCJcIix1PTAsYz1nLGg9MDtjb250aW51ZX19cyYmKGEubGVuZ3RoPjA/YSs9XCIvLi5cIjphPVwiLi5cIix1PTIpO31lbHNlIGEubGVuZ3RoPjA/YSs9XCIvXCIrby5zbGljZShjKzEsZyk6YT1vLnNsaWNlKGMrMSxnKSx1PWctYy0xO2M9ZyxoPTA7fWVsc2UgZD09PTQ2JiZoIT09LTE/KytoOmg9LTE7fXJldHVybiBhfWZ1bmN0aW9uIGkobyxzKXt2YXIgYT1zLmRpcnx8cy5yb290LHU9cy5iYXNlfHwocy5uYW1lfHxcIlwiKSsocy5leHR8fFwiXCIpO3JldHVybiBhP2E9PT1zLnJvb3Q/YSt1OmErbyt1OnV9dmFyIG49e3Jlc29sdmU6ZnVuY3Rpb24oKXtmb3IodmFyIHM9XCJcIixhPSExLHUsYz1hcmd1bWVudHMubGVuZ3RoLTE7Yz49LTEmJiFhO2MtLSl7dmFyIGg7Yz49MD9oPWFyZ3VtZW50c1tjXToodT09PXZvaWQgMCYmKHU9dC5jd2QoKSksaD11KSxlKGgpLGgubGVuZ3RoIT09MCYmKHM9aCtcIi9cIitzLGE9aC5jaGFyQ29kZUF0KDApPT09NDcpO31yZXR1cm4gcz1yKHMsIWEpLGE/cy5sZW5ndGg+MD9cIi9cIitzOlwiL1wiOnMubGVuZ3RoPjA/czpcIi5cIn0sbm9ybWFsaXplOmZ1bmN0aW9uKHMpe2lmKGUocykscy5sZW5ndGg9PT0wKXJldHVybiBcIi5cIjt2YXIgYT1zLmNoYXJDb2RlQXQoMCk9PT00Nyx1PXMuY2hhckNvZGVBdChzLmxlbmd0aC0xKT09PTQ3O3JldHVybiBzPXIocywhYSkscy5sZW5ndGg9PT0wJiYhYSYmKHM9XCIuXCIpLHMubGVuZ3RoPjAmJnUmJihzKz1cIi9cIiksYT9cIi9cIitzOnN9LGlzQWJzb2x1dGU6ZnVuY3Rpb24ocyl7cmV0dXJuIGUocykscy5sZW5ndGg+MCYmcy5jaGFyQ29kZUF0KDApPT09NDd9LGpvaW46ZnVuY3Rpb24oKXtpZihhcmd1bWVudHMubGVuZ3RoPT09MClyZXR1cm4gXCIuXCI7Zm9yKHZhciBzLGE9MDthPGFyZ3VtZW50cy5sZW5ndGg7KythKXt2YXIgdT1hcmd1bWVudHNbYV07ZSh1KSx1Lmxlbmd0aD4wJiYocz09PXZvaWQgMD9zPXU6cys9XCIvXCIrdSk7fXJldHVybiBzPT09dm9pZCAwP1wiLlwiOm4ubm9ybWFsaXplKHMpfSxyZWxhdGl2ZTpmdW5jdGlvbihzLGEpe2lmKGUocyksZShhKSxzPT09YXx8KHM9bi5yZXNvbHZlKHMpLGE9bi5yZXNvbHZlKGEpLHM9PT1hKSlyZXR1cm4gXCJcIjtmb3IodmFyIHU9MTt1PHMubGVuZ3RoJiZzLmNoYXJDb2RlQXQodSk9PT00NzsrK3UpO2Zvcih2YXIgYz1zLmxlbmd0aCxoPWMtdSxkPTE7ZDxhLmxlbmd0aCYmYS5jaGFyQ29kZUF0KGQpPT09NDc7KytkKTtmb3IodmFyIGc9YS5sZW5ndGgseT1nLWQsdz1oPHk/aDp5LEU9LTEsUz0wO1M8PXc7KytTKXtpZihTPT09dyl7aWYoeT53KXtpZihhLmNoYXJDb2RlQXQoZCtTKT09PTQ3KXJldHVybiBhLnNsaWNlKGQrUysxKTtpZihTPT09MClyZXR1cm4gYS5zbGljZShkK1MpfWVsc2UgaD53JiYocy5jaGFyQ29kZUF0KHUrUyk9PT00Nz9FPVM6Uz09PTAmJihFPTApKTticmVha312YXIgST1zLmNoYXJDb2RlQXQodStTKSxDPWEuY2hhckNvZGVBdChkK1MpO2lmKEkhPT1DKWJyZWFrO0k9PT00NyYmKEU9Uyk7fXZhciBSPVwiXCI7Zm9yKFM9dStFKzE7Uzw9YzsrK1MpKFM9PT1jfHxzLmNoYXJDb2RlQXQoUyk9PT00NykmJihSLmxlbmd0aD09PTA/Uis9XCIuLlwiOlIrPVwiLy4uXCIpO3JldHVybiBSLmxlbmd0aD4wP1IrYS5zbGljZShkK0UpOihkKz1FLGEuY2hhckNvZGVBdChkKT09PTQ3JiYrK2QsYS5zbGljZShkKSl9LF9tYWtlTG9uZzpmdW5jdGlvbihzKXtyZXR1cm4gc30sZGlybmFtZTpmdW5jdGlvbihzKXtpZihlKHMpLHMubGVuZ3RoPT09MClyZXR1cm4gXCIuXCI7Zm9yKHZhciBhPXMuY2hhckNvZGVBdCgwKSx1PWE9PT00NyxjPS0xLGg9ITAsZD1zLmxlbmd0aC0xO2Q+PTE7LS1kKWlmKGE9cy5jaGFyQ29kZUF0KGQpLGE9PT00Nyl7aWYoIWgpe2M9ZDticmVha319ZWxzZSBoPSExO3JldHVybiBjPT09LTE/dT9cIi9cIjpcIi5cIjp1JiZjPT09MT9cIi8vXCI6cy5zbGljZSgwLGMpfSxiYXNlbmFtZTpmdW5jdGlvbihzLGEpe2lmKGEhPT12b2lkIDAmJnR5cGVvZiBhIT1cInN0cmluZ1wiKXRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZXh0XCIgYXJndW1lbnQgbXVzdCBiZSBhIHN0cmluZycpO2Uocyk7dmFyIHU9MCxjPS0xLGg9ITAsZDtpZihhIT09dm9pZCAwJiZhLmxlbmd0aD4wJiZhLmxlbmd0aDw9cy5sZW5ndGgpe2lmKGEubGVuZ3RoPT09cy5sZW5ndGgmJmE9PT1zKXJldHVybiBcIlwiO3ZhciBnPWEubGVuZ3RoLTEseT0tMTtmb3IoZD1zLmxlbmd0aC0xO2Q+PTA7LS1kKXt2YXIgdz1zLmNoYXJDb2RlQXQoZCk7aWYodz09PTQ3KXtpZighaCl7dT1kKzE7YnJlYWt9fWVsc2UgeT09PS0xJiYoaD0hMSx5PWQrMSksZz49MCYmKHc9PT1hLmNoYXJDb2RlQXQoZyk/LS1nPT09LTEmJihjPWQpOihnPS0xLGM9eSkpO31yZXR1cm4gdT09PWM/Yz15OmM9PT0tMSYmKGM9cy5sZW5ndGgpLHMuc2xpY2UodSxjKX1lbHNlIHtmb3IoZD1zLmxlbmd0aC0xO2Q+PTA7LS1kKWlmKHMuY2hhckNvZGVBdChkKT09PTQ3KXtpZighaCl7dT1kKzE7YnJlYWt9fWVsc2UgYz09PS0xJiYoaD0hMSxjPWQrMSk7cmV0dXJuIGM9PT0tMT9cIlwiOnMuc2xpY2UodSxjKX19LGV4dG5hbWU6ZnVuY3Rpb24ocyl7ZShzKTtmb3IodmFyIGE9LTEsdT0wLGM9LTEsaD0hMCxkPTAsZz1zLmxlbmd0aC0xO2c+PTA7LS1nKXt2YXIgeT1zLmNoYXJDb2RlQXQoZyk7aWYoeT09PTQ3KXtpZighaCl7dT1nKzE7YnJlYWt9Y29udGludWV9Yz09PS0xJiYoaD0hMSxjPWcrMSkseT09PTQ2P2E9PT0tMT9hPWc6ZCE9PTEmJihkPTEpOmEhPT0tMSYmKGQ9LTEpO31yZXR1cm4gYT09PS0xfHxjPT09LTF8fGQ9PT0wfHxkPT09MSYmYT09PWMtMSYmYT09PXUrMT9cIlwiOnMuc2xpY2UoYSxjKX0sZm9ybWF0OmZ1bmN0aW9uKHMpe2lmKHM9PT1udWxsfHx0eXBlb2YgcyE9XCJvYmplY3RcIil0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgXCJwYXRoT2JqZWN0XCIgYXJndW1lbnQgbXVzdCBiZSBvZiB0eXBlIE9iamVjdC4gUmVjZWl2ZWQgdHlwZSAnK3R5cGVvZiBzKTtyZXR1cm4gaShcIi9cIixzKX0scGFyc2U6ZnVuY3Rpb24ocyl7ZShzKTt2YXIgYT17cm9vdDpcIlwiLGRpcjpcIlwiLGJhc2U6XCJcIixleHQ6XCJcIixuYW1lOlwiXCJ9O2lmKHMubGVuZ3RoPT09MClyZXR1cm4gYTt2YXIgdT1zLmNoYXJDb2RlQXQoMCksYz11PT09NDcsaDtjPyhhLnJvb3Q9XCIvXCIsaD0xKTpoPTA7Zm9yKHZhciBkPS0xLGc9MCx5PS0xLHc9ITAsRT1zLmxlbmd0aC0xLFM9MDtFPj1oOy0tRSl7aWYodT1zLmNoYXJDb2RlQXQoRSksdT09PTQ3KXtpZighdyl7Zz1FKzE7YnJlYWt9Y29udGludWV9eT09PS0xJiYodz0hMSx5PUUrMSksdT09PTQ2P2Q9PT0tMT9kPUU6UyE9PTEmJihTPTEpOmQhPT0tMSYmKFM9LTEpO31yZXR1cm4gZD09PS0xfHx5PT09LTF8fFM9PT0wfHxTPT09MSYmZD09PXktMSYmZD09PWcrMT95IT09LTEmJihnPT09MCYmYz9hLmJhc2U9YS5uYW1lPXMuc2xpY2UoMSx5KTphLmJhc2U9YS5uYW1lPXMuc2xpY2UoZyx5KSk6KGc9PT0wJiZjPyhhLm5hbWU9cy5zbGljZSgxLGQpLGEuYmFzZT1zLnNsaWNlKDEseSkpOihhLm5hbWU9cy5zbGljZShnLGQpLGEuYmFzZT1zLnNsaWNlKGcseSkpLGEuZXh0PXMuc2xpY2UoZCx5KSksZz4wP2EuZGlyPXMuc2xpY2UoMCxnLTEpOmMmJihhLmRpcj1cIi9cIiksYX0sc2VwOlwiL1wiLGRlbGltaXRlcjpcIjpcIix3aW4zMjpudWxsLHBvc2l4Om51bGx9O3JldHVybiBuLnBvc2l4PW4sWWE9bixZYX12YXIgWWEsbmcsSmEsc2c9d2UoKCk9Pnt2KCk7bSgpO18oKTtRYSgpO1lhPXt9LG5nPSExO0phPXVFKCk7fSk7dmFyIGRnPXt9O1F0KGRnLHtVUkw6KCk9PkRFLFVybDooKT0+TUUsZGVmYXVsdDooKT0+WixmaWxlVVJMVG9QYXRoOigpPT5jZyxmb3JtYXQ6KCk9PkxFLHBhcnNlOigpPT5xRSxwYXRoVG9GaWxlVVJMOigpPT5oZyxyZXNvbHZlOigpPT5VRSxyZXNvbHZlT2JqZWN0OigpPT5ORX0pO2Z1bmN0aW9uIEZlKCl7dGhpcy5wcm90b2NvbD1udWxsLHRoaXMuc2xhc2hlcz1udWxsLHRoaXMuYXV0aD1udWxsLHRoaXMuaG9zdD1udWxsLHRoaXMucG9ydD1udWxsLHRoaXMuaG9zdG5hbWU9bnVsbCx0aGlzLmhhc2g9bnVsbCx0aGlzLnNlYXJjaD1udWxsLHRoaXMucXVlcnk9bnVsbCx0aGlzLnBhdGhuYW1lPW51bGwsdGhpcy5wYXRoPW51bGwsdGhpcy5ocmVmPW51bGw7fWZ1bmN0aW9uIHhpKHQsZSxyKXtpZih0JiZwdC5pc09iamVjdCh0KSYmdCBpbnN0YW5jZW9mIEZlKXJldHVybiB0O3ZhciBpPW5ldyBGZTtyZXR1cm4gaS5wYXJzZSh0LGUsciksaX1mdW5jdGlvbiBiRSgpe2lmKHVnKXJldHVybiBlbDt1Zz0hMDt2YXIgdD1uZTtmdW5jdGlvbiBlKG8pe2lmKHR5cGVvZiBvIT1cInN0cmluZ1wiKXRocm93IG5ldyBUeXBlRXJyb3IoXCJQYXRoIG11c3QgYmUgYSBzdHJpbmcuIFJlY2VpdmVkIFwiK0pTT04uc3RyaW5naWZ5KG8pKX1mdW5jdGlvbiByKG8scyl7Zm9yKHZhciBhPVwiXCIsdT0wLGM9LTEsaD0wLGQsZz0wO2c8PW8ubGVuZ3RoOysrZyl7aWYoZzxvLmxlbmd0aClkPW8uY2hhckNvZGVBdChnKTtlbHNlIHtpZihkPT09NDcpYnJlYWs7ZD00Nzt9aWYoZD09PTQ3KXtpZighKGM9PT1nLTF8fGg9PT0xKSlpZihjIT09Zy0xJiZoPT09Mil7aWYoYS5sZW5ndGg8Mnx8dSE9PTJ8fGEuY2hhckNvZGVBdChhLmxlbmd0aC0xKSE9PTQ2fHxhLmNoYXJDb2RlQXQoYS5sZW5ndGgtMikhPT00Nil7aWYoYS5sZW5ndGg+Mil7dmFyIHk9YS5sYXN0SW5kZXhPZihcIi9cIik7aWYoeSE9PWEubGVuZ3RoLTEpe3k9PT0tMT8oYT1cIlwiLHU9MCk6KGE9YS5zbGljZSgwLHkpLHU9YS5sZW5ndGgtMS1hLmxhc3RJbmRleE9mKFwiL1wiKSksYz1nLGg9MDtjb250aW51ZX19ZWxzZSBpZihhLmxlbmd0aD09PTJ8fGEubGVuZ3RoPT09MSl7YT1cIlwiLHU9MCxjPWcsaD0wO2NvbnRpbnVlfX1zJiYoYS5sZW5ndGg+MD9hKz1cIi8uLlwiOmE9XCIuLlwiLHU9Mik7fWVsc2UgYS5sZW5ndGg+MD9hKz1cIi9cIitvLnNsaWNlKGMrMSxnKTphPW8uc2xpY2UoYysxLGcpLHU9Zy1jLTE7Yz1nLGg9MDt9ZWxzZSBkPT09NDYmJmghPT0tMT8rK2g6aD0tMTt9cmV0dXJuIGF9ZnVuY3Rpb24gaShvLHMpe3ZhciBhPXMuZGlyfHxzLnJvb3QsdT1zLmJhc2V8fChzLm5hbWV8fFwiXCIpKyhzLmV4dHx8XCJcIik7cmV0dXJuIGE/YT09PXMucm9vdD9hK3U6YStvK3U6dX12YXIgbj17cmVzb2x2ZTpmdW5jdGlvbigpe2Zvcih2YXIgcz1cIlwiLGE9ITEsdSxjPWFyZ3VtZW50cy5sZW5ndGgtMTtjPj0tMSYmIWE7Yy0tKXt2YXIgaDtjPj0wP2g9YXJndW1lbnRzW2NdOih1PT09dm9pZCAwJiYodT10LmN3ZCgpKSxoPXUpLGUoaCksaC5sZW5ndGghPT0wJiYocz1oK1wiL1wiK3MsYT1oLmNoYXJDb2RlQXQoMCk9PT00Nyk7fXJldHVybiBzPXIocywhYSksYT9zLmxlbmd0aD4wP1wiL1wiK3M6XCIvXCI6cy5sZW5ndGg+MD9zOlwiLlwifSxub3JtYWxpemU6ZnVuY3Rpb24ocyl7aWYoZShzKSxzLmxlbmd0aD09PTApcmV0dXJuIFwiLlwiO3ZhciBhPXMuY2hhckNvZGVBdCgwKT09PTQ3LHU9cy5jaGFyQ29kZUF0KHMubGVuZ3RoLTEpPT09NDc7cmV0dXJuIHM9cihzLCFhKSxzLmxlbmd0aD09PTAmJiFhJiYocz1cIi5cIikscy5sZW5ndGg+MCYmdSYmKHMrPVwiL1wiKSxhP1wiL1wiK3M6c30saXNBYnNvbHV0ZTpmdW5jdGlvbihzKXtyZXR1cm4gZShzKSxzLmxlbmd0aD4wJiZzLmNoYXJDb2RlQXQoMCk9PT00N30sam9pbjpmdW5jdGlvbigpe2lmKGFyZ3VtZW50cy5sZW5ndGg9PT0wKXJldHVybiBcIi5cIjtmb3IodmFyIHMsYT0wO2E8YXJndW1lbnRzLmxlbmd0aDsrK2Epe3ZhciB1PWFyZ3VtZW50c1thXTtlKHUpLHUubGVuZ3RoPjAmJihzPT09dm9pZCAwP3M9dTpzKz1cIi9cIit1KTt9cmV0dXJuIHM9PT12b2lkIDA/XCIuXCI6bi5ub3JtYWxpemUocyl9LHJlbGF0aXZlOmZ1bmN0aW9uKHMsYSl7aWYoZShzKSxlKGEpLHM9PT1hfHwocz1uLnJlc29sdmUocyksYT1uLnJlc29sdmUoYSkscz09PWEpKXJldHVybiBcIlwiO2Zvcih2YXIgdT0xO3U8cy5sZW5ndGgmJnMuY2hhckNvZGVBdCh1KT09PTQ3OysrdSk7Zm9yKHZhciBjPXMubGVuZ3RoLGg9Yy11LGQ9MTtkPGEubGVuZ3RoJiZhLmNoYXJDb2RlQXQoZCk9PT00NzsrK2QpO2Zvcih2YXIgZz1hLmxlbmd0aCx5PWctZCx3PWg8eT9oOnksRT0tMSxTPTA7Uzw9dzsrK1Mpe2lmKFM9PT13KXtpZih5Pncpe2lmKGEuY2hhckNvZGVBdChkK1MpPT09NDcpcmV0dXJuIGEuc2xpY2UoZCtTKzEpO2lmKFM9PT0wKXJldHVybiBhLnNsaWNlKGQrUyl9ZWxzZSBoPncmJihzLmNoYXJDb2RlQXQodStTKT09PTQ3P0U9UzpTPT09MCYmKEU9MCkpO2JyZWFrfXZhciBJPXMuY2hhckNvZGVBdCh1K1MpLEM9YS5jaGFyQ29kZUF0KGQrUyk7aWYoSSE9PUMpYnJlYWs7ST09PTQ3JiYoRT1TKTt9dmFyIFI9XCJcIjtmb3IoUz11K0UrMTtTPD1jOysrUykoUz09PWN8fHMuY2hhckNvZGVBdChTKT09PTQ3KSYmKFIubGVuZ3RoPT09MD9SKz1cIi4uXCI6Uis9XCIvLi5cIik7cmV0dXJuIFIubGVuZ3RoPjA/UithLnNsaWNlKGQrRSk6KGQrPUUsYS5jaGFyQ29kZUF0KGQpPT09NDcmJisrZCxhLnNsaWNlKGQpKX0sX21ha2VMb25nOmZ1bmN0aW9uKHMpe3JldHVybiBzfSxkaXJuYW1lOmZ1bmN0aW9uKHMpe2lmKGUocykscy5sZW5ndGg9PT0wKXJldHVybiBcIi5cIjtmb3IodmFyIGE9cy5jaGFyQ29kZUF0KDApLHU9YT09PTQ3LGM9LTEsaD0hMCxkPXMubGVuZ3RoLTE7ZD49MTstLWQpaWYoYT1zLmNoYXJDb2RlQXQoZCksYT09PTQ3KXtpZighaCl7Yz1kO2JyZWFrfX1lbHNlIGg9ITE7cmV0dXJuIGM9PT0tMT91P1wiL1wiOlwiLlwiOnUmJmM9PT0xP1wiLy9cIjpzLnNsaWNlKDAsYyl9LGJhc2VuYW1lOmZ1bmN0aW9uKHMsYSl7aWYoYSE9PXZvaWQgMCYmdHlwZW9mIGEhPVwic3RyaW5nXCIpdGhyb3cgbmV3IFR5cGVFcnJvcignXCJleHRcIiBhcmd1bWVudCBtdXN0IGJlIGEgc3RyaW5nJyk7ZShzKTt2YXIgdT0wLGM9LTEsaD0hMCxkO2lmKGEhPT12b2lkIDAmJmEubGVuZ3RoPjAmJmEubGVuZ3RoPD1zLmxlbmd0aCl7aWYoYS5sZW5ndGg9PT1zLmxlbmd0aCYmYT09PXMpcmV0dXJuIFwiXCI7dmFyIGc9YS5sZW5ndGgtMSx5PS0xO2ZvcihkPXMubGVuZ3RoLTE7ZD49MDstLWQpe3ZhciB3PXMuY2hhckNvZGVBdChkKTtpZih3PT09NDcpe2lmKCFoKXt1PWQrMTticmVha319ZWxzZSB5PT09LTEmJihoPSExLHk9ZCsxKSxnPj0wJiYodz09PWEuY2hhckNvZGVBdChnKT8tLWc9PT0tMSYmKGM9ZCk6KGc9LTEsYz15KSk7fXJldHVybiB1PT09Yz9jPXk6Yz09PS0xJiYoYz1zLmxlbmd0aCkscy5zbGljZSh1LGMpfWVsc2Uge2ZvcihkPXMubGVuZ3RoLTE7ZD49MDstLWQpaWYocy5jaGFyQ29kZUF0KGQpPT09NDcpe2lmKCFoKXt1PWQrMTticmVha319ZWxzZSBjPT09LTEmJihoPSExLGM9ZCsxKTtyZXR1cm4gYz09PS0xP1wiXCI6cy5zbGljZSh1LGMpfX0sZXh0bmFtZTpmdW5jdGlvbihzKXtlKHMpO2Zvcih2YXIgYT0tMSx1PTAsYz0tMSxoPSEwLGQ9MCxnPXMubGVuZ3RoLTE7Zz49MDstLWcpe3ZhciB5PXMuY2hhckNvZGVBdChnKTtpZih5PT09NDcpe2lmKCFoKXt1PWcrMTticmVha31jb250aW51ZX1jPT09LTEmJihoPSExLGM9ZysxKSx5PT09NDY/YT09PS0xP2E9ZzpkIT09MSYmKGQ9MSk6YSE9PS0xJiYoZD0tMSk7fXJldHVybiBhPT09LTF8fGM9PT0tMXx8ZD09PTB8fGQ9PT0xJiZhPT09Yy0xJiZhPT09dSsxP1wiXCI6cy5zbGljZShhLGMpfSxmb3JtYXQ6ZnVuY3Rpb24ocyl7aWYocz09PW51bGx8fHR5cGVvZiBzIT1cIm9iamVjdFwiKXRocm93IG5ldyBUeXBlRXJyb3IoJ1RoZSBcInBhdGhPYmplY3RcIiBhcmd1bWVudCBtdXN0IGJlIG9mIHR5cGUgT2JqZWN0LiBSZWNlaXZlZCB0eXBlICcrdHlwZW9mIHMpO3JldHVybiBpKFwiL1wiLHMpfSxwYXJzZTpmdW5jdGlvbihzKXtlKHMpO3ZhciBhPXtyb290OlwiXCIsZGlyOlwiXCIsYmFzZTpcIlwiLGV4dDpcIlwiLG5hbWU6XCJcIn07aWYocy5sZW5ndGg9PT0wKXJldHVybiBhO3ZhciB1PXMuY2hhckNvZGVBdCgwKSxjPXU9PT00NyxoO2M/KGEucm9vdD1cIi9cIixoPTEpOmg9MDtmb3IodmFyIGQ9LTEsZz0wLHk9LTEsdz0hMCxFPXMubGVuZ3RoLTEsUz0wO0U+PWg7LS1FKXtpZih1PXMuY2hhckNvZGVBdChFKSx1PT09NDcpe2lmKCF3KXtnPUUrMTticmVha31jb250aW51ZX15PT09LTEmJih3PSExLHk9RSsxKSx1PT09NDY/ZD09PS0xP2Q9RTpTIT09MSYmKFM9MSk6ZCE9PS0xJiYoUz0tMSk7fXJldHVybiBkPT09LTF8fHk9PT0tMXx8Uz09PTB8fFM9PT0xJiZkPT09eS0xJiZkPT09ZysxP3khPT0tMSYmKGc9PT0wJiZjP2EuYmFzZT1hLm5hbWU9cy5zbGljZSgxLHkpOmEuYmFzZT1hLm5hbWU9cy5zbGljZShnLHkpKTooZz09PTAmJmM/KGEubmFtZT1zLnNsaWNlKDEsZCksYS5iYXNlPXMuc2xpY2UoMSx5KSk6KGEubmFtZT1zLnNsaWNlKGcsZCksYS5iYXNlPXMuc2xpY2UoZyx5KSksYS5leHQ9cy5zbGljZShkLHkpKSxnPjA/YS5kaXI9cy5zbGljZSgwLGctMSk6YyYmKGEuZGlyPVwiL1wiKSxhfSxzZXA6XCIvXCIsZGVsaW1pdGVyOlwiOlwiLHdpbjMyOm51bGwscG9zaXg6bnVsbH07cmV0dXJuIG4ucG9zaXg9bixlbD1uLGVsfWZ1bmN0aW9uIEJFKHQpe2lmKHR5cGVvZiB0PT1cInN0cmluZ1wiKXQ9bmV3IFVSTCh0KTtlbHNlIGlmKCEodCBpbnN0YW5jZW9mIFVSTCkpdGhyb3cgbmV3IERlbm8uZXJyb3JzLkludmFsaWREYXRhKFwiaW52YWxpZCBhcmd1bWVudCBwYXRoICwgbXVzdCBiZSBhIHN0cmluZyBvciBVUkxcIik7aWYodC5wcm90b2NvbCE9PVwiZmlsZTpcIil0aHJvdyBuZXcgRGVuby5lcnJvcnMuSW52YWxpZERhdGEoXCJpbnZhbGlkIHVybCBzY2hlbWVcIik7cmV0dXJuIHJsP1BFKHQpOk9FKHQpfWZ1bmN0aW9uIFBFKHQpe2xldCBlPXQuaG9zdG5hbWUscj10LnBhdGhuYW1lO2ZvcihsZXQgaT0wO2k8ci5sZW5ndGg7aSsrKWlmKHJbaV09PT1cIiVcIil7bGV0IG49ci5jb2RlUG9pbnRBdChpKzIpfHwzMjtpZihyW2krMV09PT1cIjJcIiYmbj09PTEwMnx8cltpKzFdPT09XCI1XCImJm49PT05OSl0aHJvdyBuZXcgRGVuby5lcnJvcnMuSW52YWxpZERhdGEoXCJtdXN0IG5vdCBpbmNsdWRlIGVuY29kZWQgXFxcXCBvciAvIGNoYXJhY3RlcnNcIil9aWYocj1yLnJlcGxhY2UoU0UsXCJcXFxcXCIpLHI9ZGVjb2RlVVJJQ29tcG9uZW50KHIpLGUhPT1cIlwiKXJldHVybiBgXFxcXFxcXFwke2V9JHtyfWA7e2xldCBpPXIuY29kZVBvaW50QXQoMSl8MzIsbj1yWzJdO2lmKGk8dkV8fGk+RUV8fG4hPT1cIjpcIil0aHJvdyBuZXcgRGVuby5lcnJvcnMuSW52YWxpZERhdGEoXCJmaWxlIHVybCBwYXRoIG11c3QgYmUgYWJzb2x1dGVcIik7cmV0dXJuIHIuc2xpY2UoMSl9fWZ1bmN0aW9uIE9FKHQpe2lmKHQuaG9zdG5hbWUhPT1cIlwiKXRocm93IG5ldyBEZW5vLmVycm9ycy5JbnZhbGlkRGF0YShcImludmFsaWQgZmlsZSB1cmwgaG9zdG5hbWVcIik7bGV0IGU9dC5wYXRobmFtZTtmb3IobGV0IHI9MDtyPGUubGVuZ3RoO3IrKylpZihlW3JdPT09XCIlXCIpe2xldCBpPWUuY29kZVBvaW50QXQocisyKXx8MzI7aWYoZVtyKzFdPT09XCIyXCImJmk9PT0xMDIpdGhyb3cgbmV3IERlbm8uZXJyb3JzLkludmFsaWREYXRhKFwibXVzdCBub3QgaW5jbHVkZSBlbmNvZGVkIC8gY2hhcmFjdGVyc1wiKX1yZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KGUpfWZ1bmN0aW9uIGtFKHQpe2xldCBlPWZnLnJlc29sdmUodCkscj10LmNoYXJDb2RlQXQodC5sZW5ndGgtMSk7KHI9PT1tRXx8cmwmJnI9PT1fRSkmJmVbZS5sZW5ndGgtMV0hPT1mZy5zZXAmJihlKz1cIi9cIik7bGV0IGk9bmV3IFVSTChcImZpbGU6Ly9cIik7cmV0dXJuIGUuaW5jbHVkZXMoXCIlXCIpJiYoZT1lLnJlcGxhY2UoQUUsXCIlMjVcIikpLCFybCYmZS5pbmNsdWRlcyhcIlxcXFxcIikmJihlPWUucmVwbGFjZShJRSxcIiU1Q1wiKSksZS5pbmNsdWRlcyhgXG5gKSYmKGU9ZS5yZXBsYWNlKFRFLFwiJTBBXCIpKSxlLmluY2x1ZGVzKFwiXFxyXCIpJiYoZT1lLnJlcGxhY2UoUkUsXCIlMERcIikpLGUuaW5jbHVkZXMoXCJcdFwiKSYmKGU9ZS5yZXBsYWNlKENFLFwiJTA5XCIpKSxpLnBhdGhuYW1lPWUsaX1mdW5jdGlvbiBjZyh0KXtpZih0eXBlb2YgdD09XCJzdHJpbmdcIil0PW5ldyBVUkwodCk7ZWxzZSBpZighKHQgaW5zdGFuY2VvZiBVUkwpKXRocm93IG5ldyBEZW5vLmVycm9ycy5JbnZhbGlkRGF0YShcImludmFsaWQgYXJndW1lbnQgcGF0aCAsIG11c3QgYmUgYSBzdHJpbmcgb3IgVVJMXCIpO2lmKHQucHJvdG9jb2whPT1cImZpbGU6XCIpdGhyb3cgbmV3IERlbm8uZXJyb3JzLkludmFsaWREYXRhKFwiaW52YWxpZCB1cmwgc2NoZW1lXCIpO3JldHVybiBpbD9ZRSh0KTpKRSh0KX1mdW5jdGlvbiBZRSh0KXtsZXQgZT10Lmhvc3RuYW1lLHI9dC5wYXRobmFtZTtmb3IobGV0IGk9MDtpPHIubGVuZ3RoO2krKylpZihyW2ldPT09XCIlXCIpe2xldCBuPXIuY29kZVBvaW50QXQoaSsyKXx8MzI7aWYocltpKzFdPT09XCIyXCImJm49PT0xMDJ8fHJbaSsxXT09PVwiNVwiJiZuPT09OTkpdGhyb3cgbmV3IERlbm8uZXJyb3JzLkludmFsaWREYXRhKFwibXVzdCBub3QgaW5jbHVkZSBlbmNvZGVkIFxcXFwgb3IgLyBjaGFyYWN0ZXJzXCIpfWlmKHI9ci5yZXBsYWNlKEhFLFwiXFxcXFwiKSxyPWRlY29kZVVSSUNvbXBvbmVudChyKSxlIT09XCJcIilyZXR1cm4gYFxcXFxcXFxcJHtlfSR7cn1gO3tsZXQgaT1yLmNvZGVQb2ludEF0KDEpfDMyLG49clsyXTtpZihpPFdFfHxpPiRFfHxuIT09XCI6XCIpdGhyb3cgbmV3IERlbm8uZXJyb3JzLkludmFsaWREYXRhKFwiZmlsZSB1cmwgcGF0aCBtdXN0IGJlIGFic29sdXRlXCIpO3JldHVybiByLnNsaWNlKDEpfX1mdW5jdGlvbiBKRSh0KXtpZih0Lmhvc3RuYW1lIT09XCJcIil0aHJvdyBuZXcgRGVuby5lcnJvcnMuSW52YWxpZERhdGEoXCJpbnZhbGlkIGZpbGUgdXJsIGhvc3RuYW1lXCIpO2xldCBlPXQucGF0aG5hbWU7Zm9yKGxldCByPTA7cjxlLmxlbmd0aDtyKyspaWYoZVtyXT09PVwiJVwiKXtsZXQgaT1lLmNvZGVQb2ludEF0KHIrMil8fDMyO2lmKGVbcisxXT09PVwiMlwiJiZpPT09MTAyKXRocm93IG5ldyBEZW5vLmVycm9ycy5JbnZhbGlkRGF0YShcIm11c3Qgbm90IGluY2x1ZGUgZW5jb2RlZCAvIGNoYXJhY3RlcnNcIil9cmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChlKX1mdW5jdGlvbiBoZyh0KXtsZXQgZT1KYS5yZXNvbHZlKHQpLHI9dC5jaGFyQ29kZUF0KHQubGVuZ3RoLTEpOyhyPT09RkV8fGlsJiZyPT09akUpJiZlW2UubGVuZ3RoLTFdIT09SmEuc2VwJiYoZSs9XCIvXCIpO2xldCBpPW5ldyBVUkwoXCJmaWxlOi8vXCIpO3JldHVybiBlLmluY2x1ZGVzKFwiJVwiKSYmKGU9ZS5yZXBsYWNlKFZFLFwiJTI1XCIpKSwhaWwmJmUuaW5jbHVkZXMoXCJcXFxcXCIpJiYoZT1lLnJlcGxhY2UoekUsXCIlNUNcIikpLGUuaW5jbHVkZXMoYFxuYCkmJihlPWUucmVwbGFjZShLRSxcIiUwQVwiKSksZS5pbmNsdWRlcyhcIlxcclwiKSYmKGU9ZS5yZXBsYWNlKEdFLFwiJTBEXCIpKSxlLmluY2x1ZGVzKFwiXHRcIikmJihlPWUucmVwbGFjZShRRSxcIiUwOVwiKSksaS5wYXRobmFtZT1lLGl9dmFyIFosZkUscHQsY0UsaEUsZEUscEUsdGwsb2csYWcsbGcsZ0UseUUsWGEsc2ksWmEsZWwsdWcsZmcsd0UsX0UsbUUsdkUsRUUscmwsU0UsQUUsSUUsVEUsUkUsQ0UseEUsTUUsTEUsVUUsTkUscUUsREUsakUsRkUsV0UsJEUsaWwsSEUsVkUsekUsS0UsR0UsUUUscGc9d2UoKCk9Pnt2KCk7bSgpO18oKTtZcCgpO0pwKCk7cmcoKTtzZygpO1FhKCk7Wj17fSxmRT16dCxwdD17aXNTdHJpbmc6ZnVuY3Rpb24odCl7cmV0dXJuIHR5cGVvZiB0PT1cInN0cmluZ1wifSxpc09iamVjdDpmdW5jdGlvbih0KXtyZXR1cm4gdHlwZW9mIHQ9PVwib2JqZWN0XCImJnQhPT1udWxsfSxpc051bGw6ZnVuY3Rpb24odCl7cmV0dXJuIHQ9PT1udWxsfSxpc051bGxPclVuZGVmaW5lZDpmdW5jdGlvbih0KXtyZXR1cm4gdD09bnVsbH19O1oucGFyc2U9eGksWi5yZXNvbHZlPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHhpKHQsITEsITApLnJlc29sdmUoZSl9LFoucmVzb2x2ZU9iamVjdD1mdW5jdGlvbih0LGUpe3JldHVybiB0P3hpKHQsITEsITApLnJlc29sdmVPYmplY3QoZSk6ZX0sWi5mb3JtYXQ9ZnVuY3Rpb24odCl7cmV0dXJuIHB0LmlzU3RyaW5nKHQpJiYodD14aSh0KSksdCBpbnN0YW5jZW9mIEZlP3QuZm9ybWF0KCk6RmUucHJvdG90eXBlLmZvcm1hdC5jYWxsKHQpfSxaLlVybD1GZTtjRT0vXihbYS16MC05ListXSs6KS9pLGhFPS86WzAtOV0qJC8sZEU9L14oXFwvXFwvPyg/IVxcLylbXlxcP1xcc10qKShcXD9bXlxcc10qKT8kLyxwRT1bXCJ7XCIsXCJ9XCIsXCJ8XCIsXCJcXFxcXCIsXCJeXCIsXCJgXCJdLmNvbmNhdChbXCI8XCIsXCI+XCIsJ1wiJyxcImBcIixcIiBcIixcIlxcclwiLGBcbmAsXCJcdFwiXSksdGw9W1wiJ1wiXS5jb25jYXQocEUpLG9nPVtcIiVcIixcIi9cIixcIj9cIixcIjtcIixcIiNcIl0uY29uY2F0KHRsKSxhZz1bXCIvXCIsXCI/XCIsXCIjXCJdLGxnPS9eWythLXowLTlBLVpfLV17MCw2M30kLyxnRT0vXihbK2EtejAtOUEtWl8tXXswLDYzfSkoLiopJC8seUU9e2phdmFzY3JpcHQ6ITAsXCJqYXZhc2NyaXB0OlwiOiEwfSxYYT17amF2YXNjcmlwdDohMCxcImphdmFzY3JpcHQ6XCI6ITB9LHNpPXtodHRwOiEwLGh0dHBzOiEwLGZ0cDohMCxnb3BoZXI6ITAsZmlsZTohMCxcImh0dHA6XCI6ITAsXCJodHRwczpcIjohMCxcImZ0cDpcIjohMCxcImdvcGhlcjpcIjohMCxcImZpbGU6XCI6ITB9LFphPWR0O0ZlLnByb3RvdHlwZS5wYXJzZT1mdW5jdGlvbih0LGUscil7aWYoIXB0LmlzU3RyaW5nKHQpKXRocm93IG5ldyBUeXBlRXJyb3IoXCJQYXJhbWV0ZXIgJ3VybCcgbXVzdCBiZSBhIHN0cmluZywgbm90IFwiK3R5cGVvZiB0KTt2YXIgaT10LmluZGV4T2YoXCI/XCIpLG49aSE9PS0xJiZpPHQuaW5kZXhPZihcIiNcIik/XCI/XCI6XCIjXCIsbz10LnNwbGl0KG4pO29bMF09b1swXS5yZXBsYWNlKC9cXFxcL2csXCIvXCIpO3ZhciBzPXQ9by5qb2luKG4pO2lmKHM9cy50cmltKCksIXImJnQuc3BsaXQoXCIjXCIpLmxlbmd0aD09PTEpe3ZhciBhPWRFLmV4ZWMocyk7aWYoYSlyZXR1cm4gdGhpcy5wYXRoPXMsdGhpcy5ocmVmPXMsdGhpcy5wYXRobmFtZT1hWzFdLGFbMl0/KHRoaXMuc2VhcmNoPWFbMl0sdGhpcy5xdWVyeT1lP1phLnBhcnNlKHRoaXMuc2VhcmNoLnN1YnN0cigxKSk6dGhpcy5zZWFyY2guc3Vic3RyKDEpKTplJiYodGhpcy5zZWFyY2g9XCJcIix0aGlzLnF1ZXJ5PXt9KSx0aGlzfXZhciB1PWNFLmV4ZWMocyk7aWYodSl7dmFyIGM9KHU9dVswXSkudG9Mb3dlckNhc2UoKTt0aGlzLnByb3RvY29sPWMscz1zLnN1YnN0cih1Lmxlbmd0aCk7fWlmKHJ8fHV8fHMubWF0Y2goL15cXC9cXC9bXkBcXC9dK0BbXkBcXC9dKy8pKXt2YXIgaD1zLnN1YnN0cigwLDIpPT09XCIvL1wiOyFofHx1JiZYYVt1XXx8KHM9cy5zdWJzdHIoMiksdGhpcy5zbGFzaGVzPSEwKTt9aWYoIVhhW3VdJiYoaHx8dSYmIXNpW3VdKSl7Zm9yKHZhciBkLGcseT0tMSx3PTA7dzxhZy5sZW5ndGg7dysrKShFPXMuaW5kZXhPZihhZ1t3XSkpIT09LTEmJih5PT09LTF8fEU8eSkmJih5PUUpO2ZvcigoZz15PT09LTE/cy5sYXN0SW5kZXhPZihcIkBcIik6cy5sYXN0SW5kZXhPZihcIkBcIix5KSkhPT0tMSYmKGQ9cy5zbGljZSgwLGcpLHM9cy5zbGljZShnKzEpLHRoaXMuYXV0aD1kZWNvZGVVUklDb21wb25lbnQoZCkpLHk9LTEsdz0wO3c8b2cubGVuZ3RoO3crKyl7dmFyIEU7KEU9cy5pbmRleE9mKG9nW3ddKSkhPT0tMSYmKHk9PT0tMXx8RTx5KSYmKHk9RSk7fXk9PT0tMSYmKHk9cy5sZW5ndGgpLHRoaXMuaG9zdD1zLnNsaWNlKDAseSkscz1zLnNsaWNlKHkpLHRoaXMucGFyc2VIb3N0KCksdGhpcy5ob3N0bmFtZT10aGlzLmhvc3RuYW1lfHxcIlwiO3ZhciBTPXRoaXMuaG9zdG5hbWVbMF09PT1cIltcIiYmdGhpcy5ob3N0bmFtZVt0aGlzLmhvc3RuYW1lLmxlbmd0aC0xXT09PVwiXVwiO2lmKCFTKWZvcih2YXIgST10aGlzLmhvc3RuYW1lLnNwbGl0KC9cXC4vKSxDPSh3PTAsSS5sZW5ndGgpO3c8Qzt3Kyspe3ZhciBSPUlbd107aWYoUiYmIVIubWF0Y2gobGcpKXtmb3IodmFyIFU9XCJcIixOPTAsVz1SLmxlbmd0aDtOPFc7TisrKVIuY2hhckNvZGVBdChOKT4xMjc/VSs9XCJ4XCI6VSs9UltOXTtpZighVS5tYXRjaChsZykpe3ZhciBLPUkuc2xpY2UoMCx3KSx6PUkuc2xpY2UodysxKSxRPVIubWF0Y2goZ0UpO1EmJihLLnB1c2goUVsxXSksei51bnNoaWZ0KFFbMl0pKSx6Lmxlbmd0aCYmKHM9XCIvXCIrei5qb2luKFwiLlwiKStzKSx0aGlzLmhvc3RuYW1lPUsuam9pbihcIi5cIik7YnJlYWt9fX10aGlzLmhvc3RuYW1lLmxlbmd0aD4yNTU/dGhpcy5ob3N0bmFtZT1cIlwiOnRoaXMuaG9zdG5hbWU9dGhpcy5ob3N0bmFtZS50b0xvd2VyQ2FzZSgpLFN8fCh0aGlzLmhvc3RuYW1lPWZFLnRvQVNDSUkodGhpcy5ob3N0bmFtZSkpO3ZhciBkZT10aGlzLnBvcnQ/XCI6XCIrdGhpcy5wb3J0OlwiXCIsR3Q9dGhpcy5ob3N0bmFtZXx8XCJcIjt0aGlzLmhvc3Q9R3QrZGUsdGhpcy5ocmVmKz10aGlzLmhvc3QsUyYmKHRoaXMuaG9zdG5hbWU9dGhpcy5ob3N0bmFtZS5zdWJzdHIoMSx0aGlzLmhvc3RuYW1lLmxlbmd0aC0yKSxzWzBdIT09XCIvXCImJihzPVwiL1wiK3MpKTt9aWYoIXlFW2NdKWZvcih3PTAsQz10bC5sZW5ndGg7dzxDO3crKyl7dmFyIHBlPXRsW3ddO2lmKHMuaW5kZXhPZihwZSkhPT0tMSl7dmFyIENyPWVuY29kZVVSSUNvbXBvbmVudChwZSk7Q3I9PT1wZSYmKENyPWVzY2FwZShwZSkpLHM9cy5zcGxpdChwZSkuam9pbihDcik7fX12YXIgQnI9cy5pbmRleE9mKFwiI1wiKTtCciE9PS0xJiYodGhpcy5oYXNoPXMuc3Vic3RyKEJyKSxzPXMuc2xpY2UoMCxCcikpO3ZhciBQcj1zLmluZGV4T2YoXCI/XCIpO2lmKFByIT09LTE/KHRoaXMuc2VhcmNoPXMuc3Vic3RyKFByKSx0aGlzLnF1ZXJ5PXMuc3Vic3RyKFByKzEpLGUmJih0aGlzLnF1ZXJ5PVphLnBhcnNlKHRoaXMucXVlcnkpKSxzPXMuc2xpY2UoMCxQcikpOmUmJih0aGlzLnNlYXJjaD1cIlwiLHRoaXMucXVlcnk9e30pLHMmJih0aGlzLnBhdGhuYW1lPXMpLHNpW2NdJiZ0aGlzLmhvc3RuYW1lJiYhdGhpcy5wYXRobmFtZSYmKHRoaXMucGF0aG5hbWU9XCIvXCIpLHRoaXMucGF0aG5hbWV8fHRoaXMuc2VhcmNoKXtkZT10aGlzLnBhdGhuYW1lfHxcIlwiO3ZhciB1cz10aGlzLnNlYXJjaHx8XCJcIjt0aGlzLnBhdGg9ZGUrdXM7fXJldHVybiB0aGlzLmhyZWY9dGhpcy5mb3JtYXQoKSx0aGlzfSxGZS5wcm90b3R5cGUuZm9ybWF0PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5hdXRofHxcIlwiO3QmJih0PSh0PWVuY29kZVVSSUNvbXBvbmVudCh0KSkucmVwbGFjZSgvJTNBL2ksXCI6XCIpLHQrPVwiQFwiKTt2YXIgZT10aGlzLnByb3RvY29sfHxcIlwiLHI9dGhpcy5wYXRobmFtZXx8XCJcIixpPXRoaXMuaGFzaHx8XCJcIixuPSExLG89XCJcIjt0aGlzLmhvc3Q/bj10K3RoaXMuaG9zdDp0aGlzLmhvc3RuYW1lJiYobj10Kyh0aGlzLmhvc3RuYW1lLmluZGV4T2YoXCI6XCIpPT09LTE/dGhpcy5ob3N0bmFtZTpcIltcIit0aGlzLmhvc3RuYW1lK1wiXVwiKSx0aGlzLnBvcnQmJihuKz1cIjpcIit0aGlzLnBvcnQpKSx0aGlzLnF1ZXJ5JiZwdC5pc09iamVjdCh0aGlzLnF1ZXJ5KSYmT2JqZWN0LmtleXModGhpcy5xdWVyeSkubGVuZ3RoJiYobz1aYS5zdHJpbmdpZnkodGhpcy5xdWVyeSkpO3ZhciBzPXRoaXMuc2VhcmNofHxvJiZcIj9cIitvfHxcIlwiO3JldHVybiBlJiZlLnN1YnN0cigtMSkhPT1cIjpcIiYmKGUrPVwiOlwiKSx0aGlzLnNsYXNoZXN8fCghZXx8c2lbZV0pJiZuIT09ITE/KG49XCIvL1wiKyhufHxcIlwiKSxyJiZyLmNoYXJBdCgwKSE9PVwiL1wiJiYocj1cIi9cIityKSk6bnx8KG49XCJcIiksaSYmaS5jaGFyQXQoMCkhPT1cIiNcIiYmKGk9XCIjXCIraSkscyYmcy5jaGFyQXQoMCkhPT1cIj9cIiYmKHM9XCI/XCIrcyksZStuKyhyPXIucmVwbGFjZSgvWz8jXS9nLGZ1bmN0aW9uKGEpe3JldHVybiBlbmNvZGVVUklDb21wb25lbnQoYSl9KSkrKHM9cy5yZXBsYWNlKFwiI1wiLFwiJTIzXCIpKStpfSxGZS5wcm90b3R5cGUucmVzb2x2ZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5yZXNvbHZlT2JqZWN0KHhpKHQsITEsITApKS5mb3JtYXQoKX0sRmUucHJvdG90eXBlLnJlc29sdmVPYmplY3Q9ZnVuY3Rpb24odCl7aWYocHQuaXNTdHJpbmcodCkpe3ZhciBlPW5ldyBGZTtlLnBhcnNlKHQsITEsITApLHQ9ZTt9Zm9yKHZhciByPW5ldyBGZSxpPU9iamVjdC5rZXlzKHRoaXMpLG49MDtuPGkubGVuZ3RoO24rKyl7dmFyIG89aVtuXTtyW29dPXRoaXNbb107fWlmKHIuaGFzaD10Lmhhc2gsdC5ocmVmPT09XCJcIilyZXR1cm4gci5ocmVmPXIuZm9ybWF0KCkscjtpZih0LnNsYXNoZXMmJiF0LnByb3RvY29sKXtmb3IodmFyIHM9T2JqZWN0LmtleXModCksYT0wO2E8cy5sZW5ndGg7YSsrKXt2YXIgdT1zW2FdO3UhPT1cInByb3RvY29sXCImJihyW3VdPXRbdV0pO31yZXR1cm4gc2lbci5wcm90b2NvbF0mJnIuaG9zdG5hbWUmJiFyLnBhdGhuYW1lJiYoci5wYXRoPXIucGF0aG5hbWU9XCIvXCIpLHIuaHJlZj1yLmZvcm1hdCgpLHJ9aWYodC5wcm90b2NvbCYmdC5wcm90b2NvbCE9PXIucHJvdG9jb2wpe2lmKCFzaVt0LnByb3RvY29sXSl7Zm9yKHZhciBjPU9iamVjdC5rZXlzKHQpLGg9MDtoPGMubGVuZ3RoO2grKyl7dmFyIGQ9Y1toXTtyW2RdPXRbZF07fXJldHVybiByLmhyZWY9ci5mb3JtYXQoKSxyfWlmKHIucHJvdG9jb2w9dC5wcm90b2NvbCx0Lmhvc3R8fFhhW3QucHJvdG9jb2xdKXIucGF0aG5hbWU9dC5wYXRobmFtZTtlbHNlIHtmb3IodmFyIGc9KHQucGF0aG5hbWV8fFwiXCIpLnNwbGl0KFwiL1wiKTtnLmxlbmd0aCYmISh0Lmhvc3Q9Zy5zaGlmdCgpKTspO3QuaG9zdHx8KHQuaG9zdD1cIlwiKSx0Lmhvc3RuYW1lfHwodC5ob3N0bmFtZT1cIlwiKSxnWzBdIT09XCJcIiYmZy51bnNoaWZ0KFwiXCIpLGcubGVuZ3RoPDImJmcudW5zaGlmdChcIlwiKSxyLnBhdGhuYW1lPWcuam9pbihcIi9cIik7fWlmKHIuc2VhcmNoPXQuc2VhcmNoLHIucXVlcnk9dC5xdWVyeSxyLmhvc3Q9dC5ob3N0fHxcIlwiLHIuYXV0aD10LmF1dGgsci5ob3N0bmFtZT10Lmhvc3RuYW1lfHx0Lmhvc3Qsci5wb3J0PXQucG9ydCxyLnBhdGhuYW1lfHxyLnNlYXJjaCl7dmFyIHk9ci5wYXRobmFtZXx8XCJcIix3PXIuc2VhcmNofHxcIlwiO3IucGF0aD15K3c7fXJldHVybiByLnNsYXNoZXM9ci5zbGFzaGVzfHx0LnNsYXNoZXMsci5ocmVmPXIuZm9ybWF0KCkscn12YXIgRT1yLnBhdGhuYW1lJiZyLnBhdGhuYW1lLmNoYXJBdCgwKT09PVwiL1wiLFM9dC5ob3N0fHx0LnBhdGhuYW1lJiZ0LnBhdGhuYW1lLmNoYXJBdCgwKT09PVwiL1wiLEk9U3x8RXx8ci5ob3N0JiZ0LnBhdGhuYW1lLEM9SSxSPXIucGF0aG5hbWUmJnIucGF0aG5hbWUuc3BsaXQoXCIvXCIpfHxbXSxVPShnPXQucGF0aG5hbWUmJnQucGF0aG5hbWUuc3BsaXQoXCIvXCIpfHxbXSxyLnByb3RvY29sJiYhc2lbci5wcm90b2NvbF0pO2lmKFUmJihyLmhvc3RuYW1lPVwiXCIsci5wb3J0PW51bGwsci5ob3N0JiYoUlswXT09PVwiXCI/UlswXT1yLmhvc3Q6Ui51bnNoaWZ0KHIuaG9zdCkpLHIuaG9zdD1cIlwiLHQucHJvdG9jb2wmJih0Lmhvc3RuYW1lPW51bGwsdC5wb3J0PW51bGwsdC5ob3N0JiYoZ1swXT09PVwiXCI/Z1swXT10Lmhvc3Q6Zy51bnNoaWZ0KHQuaG9zdCkpLHQuaG9zdD1udWxsKSxJPUkmJihnWzBdPT09XCJcInx8UlswXT09PVwiXCIpKSxTKXIuaG9zdD10Lmhvc3R8fHQuaG9zdD09PVwiXCI/dC5ob3N0OnIuaG9zdCxyLmhvc3RuYW1lPXQuaG9zdG5hbWV8fHQuaG9zdG5hbWU9PT1cIlwiP3QuaG9zdG5hbWU6ci5ob3N0bmFtZSxyLnNlYXJjaD10LnNlYXJjaCxyLnF1ZXJ5PXQucXVlcnksUj1nO2Vsc2UgaWYoZy5sZW5ndGgpUnx8KFI9W10pLFIucG9wKCksUj1SLmNvbmNhdChnKSxyLnNlYXJjaD10LnNlYXJjaCxyLnF1ZXJ5PXQucXVlcnk7ZWxzZSBpZighcHQuaXNOdWxsT3JVbmRlZmluZWQodC5zZWFyY2gpKXJldHVybiBVJiYoci5ob3N0bmFtZT1yLmhvc3Q9Ui5zaGlmdCgpLChRPSEhKHIuaG9zdCYmci5ob3N0LmluZGV4T2YoXCJAXCIpPjApJiZyLmhvc3Quc3BsaXQoXCJAXCIpKSYmKHIuYXV0aD1RLnNoaWZ0KCksci5ob3N0PXIuaG9zdG5hbWU9US5zaGlmdCgpKSksci5zZWFyY2g9dC5zZWFyY2gsci5xdWVyeT10LnF1ZXJ5LHB0LmlzTnVsbChyLnBhdGhuYW1lKSYmcHQuaXNOdWxsKHIuc2VhcmNoKXx8KHIucGF0aD0oci5wYXRobmFtZT9yLnBhdGhuYW1lOlwiXCIpKyhyLnNlYXJjaD9yLnNlYXJjaDpcIlwiKSksci5ocmVmPXIuZm9ybWF0KCkscjtpZighUi5sZW5ndGgpcmV0dXJuIHIucGF0aG5hbWU9bnVsbCxyLnNlYXJjaD9yLnBhdGg9XCIvXCIrci5zZWFyY2g6ci5wYXRoPW51bGwsci5ocmVmPXIuZm9ybWF0KCkscjtmb3IodmFyIE49Ui5zbGljZSgtMSlbMF0sVz0oci5ob3N0fHx0Lmhvc3R8fFIubGVuZ3RoPjEpJiYoTj09PVwiLlwifHxOPT09XCIuLlwiKXx8Tj09PVwiXCIsSz0wLHo9Ui5sZW5ndGg7ej49MDt6LS0pKE49Ult6XSk9PT1cIi5cIj9SLnNwbGljZSh6LDEpOk49PT1cIi4uXCI/KFIuc3BsaWNlKHosMSksSysrKTpLJiYoUi5zcGxpY2UoeiwxKSxLLS0pO2lmKCFJJiYhQylmb3IoO0stLTtLKVIudW5zaGlmdChcIi4uXCIpOyFJfHxSWzBdPT09XCJcInx8UlswXSYmUlswXS5jaGFyQXQoMCk9PT1cIi9cInx8Ui51bnNoaWZ0KFwiXCIpLFcmJlIuam9pbihcIi9cIikuc3Vic3RyKC0xKSE9PVwiL1wiJiZSLnB1c2goXCJcIik7dmFyIFEsZGU9UlswXT09PVwiXCJ8fFJbMF0mJlJbMF0uY2hhckF0KDApPT09XCIvXCI7cmV0dXJuIFUmJihyLmhvc3RuYW1lPXIuaG9zdD1kZT9cIlwiOlIubGVuZ3RoP1Iuc2hpZnQoKTpcIlwiLChRPSEhKHIuaG9zdCYmci5ob3N0LmluZGV4T2YoXCJAXCIpPjApJiZyLmhvc3Quc3BsaXQoXCJAXCIpKSYmKHIuYXV0aD1RLnNoaWZ0KCksci5ob3N0PXIuaG9zdG5hbWU9US5zaGlmdCgpKSksKEk9SXx8ci5ob3N0JiZSLmxlbmd0aCkmJiFkZSYmUi51bnNoaWZ0KFwiXCIpLFIubGVuZ3RoP3IucGF0aG5hbWU9Ui5qb2luKFwiL1wiKTooci5wYXRobmFtZT1udWxsLHIucGF0aD1udWxsKSxwdC5pc051bGwoci5wYXRobmFtZSkmJnB0LmlzTnVsbChyLnNlYXJjaCl8fChyLnBhdGg9KHIucGF0aG5hbWU/ci5wYXRobmFtZTpcIlwiKSsoci5zZWFyY2g/ci5zZWFyY2g6XCJcIikpLHIuYXV0aD10LmF1dGh8fHIuYXV0aCxyLnNsYXNoZXM9ci5zbGFzaGVzfHx0LnNsYXNoZXMsci5ocmVmPXIuZm9ybWF0KCkscn0sRmUucHJvdG90eXBlLnBhcnNlSG9zdD1mdW5jdGlvbigpe3ZhciB0PXRoaXMuaG9zdCxlPWhFLmV4ZWModCk7ZSYmKChlPWVbMF0pIT09XCI6XCImJih0aGlzLnBvcnQ9ZS5zdWJzdHIoMSkpLHQ9dC5zdWJzdHIoMCx0Lmxlbmd0aC1lLmxlbmd0aCkpLHQmJih0aGlzLmhvc3RuYW1lPXQpO307Wi5Vcmw7Wi5mb3JtYXQ7Wi5yZXNvbHZlO1oucmVzb2x2ZU9iamVjdDtlbD17fSx1Zz0hMTtmZz1iRSgpLHdFPXR5cGVvZiBEZW5vPFwidVwiP0Rlbm8uYnVpbGQub3M9PT1cIndpbmRvd3NcIj9cIndpbjMyXCI6RGVuby5idWlsZC5vczp2b2lkIDA7Wi5VUkw9dHlwZW9mIFVSTDxcInVcIj9VUkw6bnVsbDtaLnBhdGhUb0ZpbGVVUkw9a0U7Wi5maWxlVVJMVG9QYXRoPUJFO1ouVXJsO1ouZm9ybWF0O1oucmVzb2x2ZTtaLnJlc29sdmVPYmplY3Q7Wi5VUkw7X0U9OTIsbUU9NDcsdkU9OTcsRUU9MTIyLHJsPXdFPT09XCJ3aW4zMlwiLFNFPS9cXC8vZyxBRT0vJS9nLElFPS9cXFxcL2csVEU9L1xcbi9nLFJFPS9cXHIvZyxDRT0vXFx0L2c7eEU9dHlwZW9mIERlbm88XCJ1XCI/RGVuby5idWlsZC5vcz09PVwid2luZG93c1wiP1wid2luMzJcIjpEZW5vLmJ1aWxkLm9zOnZvaWQgMDtaLlVSTD10eXBlb2YgVVJMPFwidVwiP1VSTDpudWxsO1oucGF0aFRvRmlsZVVSTD1oZztaLmZpbGVVUkxUb1BhdGg9Y2c7TUU9Wi5VcmwsTEU9Wi5mb3JtYXQsVUU9Wi5yZXNvbHZlLE5FPVoucmVzb2x2ZU9iamVjdCxxRT1aLnBhcnNlLERFPVouVVJMLGpFPTkyLEZFPTQ3LFdFPTk3LCRFPTEyMixpbD14RT09PVwid2luMzJcIixIRT0vXFwvL2csVkU9LyUvZyx6RT0vXFxcXC9nLEtFPS9cXG4vZyxHRT0vXFxyL2csUUU9L1xcdC9nO30pO3ZhciBubD17fTtRdChubCx7U2VydmVyOigpPT5NZSxTb2NrZXQ6KCk9Pk1lLFN0cmVhbTooKT0+TWUsX2NyZWF0ZVNlcnZlckhhbmRsZTooKT0+TWUsX25vcm1hbGl6ZUFyZ3M6KCk9Pk1lLF9zZXRTaW11bHRhbmVvdXNBY2NlcHRzOigpPT5NZSxjb25uZWN0OigpPT5NZSxjcmVhdGVDb25uZWN0aW9uOigpPT5NZSxjcmVhdGVTZXJ2ZXI6KCk9Pk1lLGRlZmF1bHQ6KCk9PlhFLGlzSVA6KCk9Pk1lLGlzSVB2NDooKT0+TWUsaXNJUHY2OigpPT5NZX0pO2Z1bmN0aW9uIE1lKCl7dGhyb3cgbmV3IEVycm9yKFwiTm9kZS5qcyBuZXQgbW9kdWxlIGlzIG5vdCBzdXBwb3J0ZWQgYnkgSlNQTSBjb3JlIG91dHNpZGUgb2YgTm9kZS5qc1wiKX12YXIgWEUsc2w9d2UoKCk9Pnt2KCk7bSgpO18oKTtYRT17X2NyZWF0ZVNlcnZlckhhbmRsZTpNZSxfbm9ybWFsaXplQXJnczpNZSxfc2V0U2ltdWx0YW5lb3VzQWNjZXB0czpNZSxjb25uZWN0Ok1lLGNyZWF0ZUNvbm5lY3Rpb246TWUsY3JlYXRlU2VydmVyOk1lLGlzSVA6TWUsaXNJUHY0Ok1lLGlzSVB2NjpNZSxTZXJ2ZXI6TWUsU29ja2V0Ok1lLFN0cmVhbTpNZX07fSk7dmFyIG9sPU0oTWk9Pnt2KCk7bSgpO18oKTt2YXIgZ2c9TWkmJk1pLl9faW1wb3J0RGVmYXVsdHx8ZnVuY3Rpb24odCl7cmV0dXJuIHQmJnQuX19lc01vZHVsZT90OntkZWZhdWx0OnR9fTtPYmplY3QuZGVmaW5lUHJvcGVydHkoTWksXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSk7dmFyIFpFPWdnKChzbCgpLFgobmwpKSksZVM9Z2cob3QoKSksdFM9KDAsIGVTLmRlZmF1bHQpKFwibXF0dGpzOnRjcFwiKSxyUz0odCxlKT0+e2UucG9ydD1lLnBvcnR8fDE4ODMsZS5ob3N0bmFtZT1lLmhvc3RuYW1lfHxlLmhvc3R8fFwibG9jYWxob3N0XCI7bGV0e3BvcnQ6cn09ZSxpPWUuaG9zdG5hbWU7cmV0dXJuIHRTKFwicG9ydCAlZCBhbmQgaG9zdCAlc1wiLHIsaSksWkUuZGVmYXVsdC5jcmVhdGVDb25uZWN0aW9uKHIsaSl9O01pLmRlZmF1bHQ9clM7fSk7dmFyIHlnPXt9O1F0KHlnLHtkZWZhdWx0OigpPT5pU30pO3ZhciBpUyxiZz13ZSgoKT0+e3YoKTttKCk7XygpO2lTPXt9O30pO3ZhciBsbD1NKExpPT57digpO20oKTtfKCk7dmFyIGFsPUxpJiZMaS5fX2ltcG9ydERlZmF1bHR8fGZ1bmN0aW9uKHQpe3JldHVybiB0JiZ0Ll9fZXNNb2R1bGU/dDp7ZGVmYXVsdDp0fX07T2JqZWN0LmRlZmluZVByb3BlcnR5KExpLFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO3ZhciBuUz1hbCgoYmcoKSxYKHlnKSkpLHNTPWFsKChzbCgpLFgobmwpKSksb1M9YWwob3QoKSksYVM9KDAsIG9TLmRlZmF1bHQpKFwibXF0dGpzOnRsc1wiKSxsUz0odCxlKT0+e2UucG9ydD1lLnBvcnR8fDg4ODMsZS5ob3N0PWUuaG9zdG5hbWV8fGUuaG9zdHx8XCJsb2NhbGhvc3RcIixzUy5kZWZhdWx0LmlzSVAoZS5ob3N0KT09PTAmJihlLnNlcnZlcm5hbWU9ZS5ob3N0KSxlLnJlamVjdFVuYXV0aG9yaXplZD1lLnJlamVjdFVuYXV0aG9yaXplZCE9PSExLGRlbGV0ZSBlLnBhdGgsYVMoXCJwb3J0ICVkIGhvc3QgJXMgcmVqZWN0VW5hdXRob3JpemVkICViXCIsZS5wb3J0LGUuaG9zdCxlLnJlamVjdFVuYXV0aG9yaXplZCk7bGV0IHI9blMuZGVmYXVsdC5jb25uZWN0KGUpO3Iub24oXCJzZWN1cmVDb25uZWN0XCIsKCk9PntlLnJlamVjdFVuYXV0aG9yaXplZCYmIXIuYXV0aG9yaXplZD9yLmVtaXQoXCJlcnJvclwiLG5ldyBFcnJvcihcIlRMUyBub3QgYXV0aG9yaXplZFwiKSk6ci5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsaSk7fSk7ZnVuY3Rpb24gaShuKXtlLnJlamVjdFVuYXV0aG9yaXplZCYmdC5lbWl0KFwiZXJyb3JcIixuKSxyLmVuZCgpO31yZXR1cm4gci5vbihcImVycm9yXCIsaSkscn07TGkuZGVmYXVsdD1sUzt9KTt2YXIgb3M9TShvaT0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShvaSxcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTtvaS5CdWZmZXJlZER1cGxleD1vaS53cml0ZXY9dm9pZCAwO3ZhciB1Uz1EdCgpLHdnPSh5ZSgpLFgoX2UpKTtmdW5jdGlvbiBfZyh0LGUpe2xldCByPW5ldyBBcnJheSh0Lmxlbmd0aCk7Zm9yKGxldCBpPTA7aTx0Lmxlbmd0aDtpKyspdHlwZW9mIHRbaV0uY2h1bms9PVwic3RyaW5nXCI/cltpXT13Zy5CdWZmZXIuZnJvbSh0W2ldLmNodW5rLFwidXRmOFwiKTpyW2ldPXRbaV0uY2h1bms7dGhpcy5fd3JpdGUod2cuQnVmZmVyLmNvbmNhdChyKSxcImJpbmFyeVwiLGUpO31vaS53cml0ZXY9X2c7dmFyIHVsPWNsYXNzIGV4dGVuZHMgdVMuRHVwbGV4e2NvbnN0cnVjdG9yKGUscixpKXtzdXBlcih7b2JqZWN0TW9kZTohMH0pLHRoaXMucHJveHk9cix0aGlzLnNvY2tldD1pLHRoaXMud3JpdGVRdWV1ZT1bXSxlLm9iamVjdE1vZGV8fCh0aGlzLl93cml0ZXY9X2cuYmluZCh0aGlzKSksdGhpcy5pc1NvY2tldE9wZW49ITEsdGhpcy5wcm94eS5vbihcImRhdGFcIixuPT57dGhpcy5wdXNoKG4pO30pO31fcmVhZChlKXt0aGlzLnByb3h5LnJlYWQoZSk7fV93cml0ZShlLHIsaSl7dGhpcy5pc1NvY2tldE9wZW4/dGhpcy53cml0ZVRvUHJveHkoZSxyLGkpOnRoaXMud3JpdGVRdWV1ZS5wdXNoKHtjaHVuazplLGVuY29kaW5nOnIsY2I6aX0pO31fZmluYWwoZSl7dGhpcy53cml0ZVF1ZXVlPVtdLHRoaXMucHJveHkuZW5kKGUpO31fZGVzdHJveShlLHIpe3RoaXMud3JpdGVRdWV1ZT1bXSx0aGlzLnByb3h5LmRlc3Ryb3koKSxyKGUpO31zb2NrZXRSZWFkeSgpe3RoaXMuZW1pdChcImNvbm5lY3RcIiksdGhpcy5pc1NvY2tldE9wZW49ITAsdGhpcy5wcm9jZXNzV3JpdGVRdWV1ZSgpO313cml0ZVRvUHJveHkoZSxyLGkpe3RoaXMucHJveHkud3JpdGUoZSxyKT09PSExP3RoaXMucHJveHkub25jZShcImRyYWluXCIsaSk6aSgpO31wcm9jZXNzV3JpdGVRdWV1ZSgpe2Zvcig7dGhpcy53cml0ZVF1ZXVlLmxlbmd0aD4wOyl7bGV0e2NodW5rOmUsZW5jb2Rpbmc6cixjYjppfT10aGlzLndyaXRlUXVldWUuc2hpZnQoKTt0aGlzLndyaXRlVG9Qcm94eShlLHIsaSk7fX19O29pLkJ1ZmZlcmVkRHVwbGV4PXVsO30pO3ZhciBobD1NKGNsPT57digpO20oKTtfKCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGNsLFwiX19lc01vZHVsZVwiLHt2YWx1ZTohMH0pO3ZhciBtZz0oeWUoKSxYKF9lKSksZlM9RHQoKSxjUz1vcygpLGd0LGZsLExlO2Z1bmN0aW9uIGhTKCl7bGV0IHQ9bmV3IGZTLlRyYW5zZm9ybTtyZXR1cm4gdC5fd3JpdGU9KGUscixpKT0+e2d0LnNlbmQoe2RhdGE6ZS5idWZmZXIsc3VjY2Vzcygpe2koKTt9LGZhaWwobil7aShuZXcgRXJyb3IobikpO319KTt9LHQuX2ZsdXNoPWU9PntndC5jbG9zZSh7c3VjY2Vzcygpe2UoKTt9fSk7fSx0fWZ1bmN0aW9uIGRTKHQpe3QuaG9zdG5hbWV8fCh0Lmhvc3RuYW1lPVwibG9jYWxob3N0XCIpLHQucGF0aHx8KHQucGF0aD1cIi9cIiksdC53c09wdGlvbnN8fCh0LndzT3B0aW9ucz17fSk7fWZ1bmN0aW9uIHBTKHQsZSl7bGV0IHI9dC5wcm90b2NvbD09PVwid3hzXCI/XCJ3c3NcIjpcIndzXCIsaT1gJHtyfTovLyR7dC5ob3N0bmFtZX0ke3QucGF0aH1gO3JldHVybiB0LnBvcnQmJnQucG9ydCE9PTgwJiZ0LnBvcnQhPT00NDMmJihpPWAke3J9Oi8vJHt0Lmhvc3RuYW1lfToke3QucG9ydH0ke3QucGF0aH1gKSx0eXBlb2YgdC50cmFuc2Zvcm1Xc1VybD09XCJmdW5jdGlvblwiJiYoaT10LnRyYW5zZm9ybVdzVXJsKGksdCxlKSksaX1mdW5jdGlvbiBnUygpe2d0Lm9uT3BlbigoKT0+e0xlLnNvY2tldFJlYWR5KCk7fSksZ3Qub25NZXNzYWdlKHQ9PntsZXR7ZGF0YTplfT10O2UgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcj9lPW1nLkJ1ZmZlci5mcm9tKGUpOmU9bWcuQnVmZmVyLmZyb20oZSxcInV0ZjhcIiksZmwucHVzaChlKTt9KSxndC5vbkNsb3NlKCgpPT57TGUuZW1pdChcImNsb3NlXCIpLExlLmVuZCgpLExlLmRlc3Ryb3koKTt9KSxndC5vbkVycm9yKHQ9PntsZXQgZT1uZXcgRXJyb3IodC5lcnJNc2cpO0xlLmRlc3Ryb3koZSk7fSk7fXZhciB5Uz0odCxlKT0+e2lmKGUuaG9zdG5hbWU9ZS5ob3N0bmFtZXx8ZS5ob3N0LCFlLmhvc3RuYW1lKXRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBkZXRlcm1pbmUgaG9zdC4gU3BlY2lmeSBob3N0IG1hbnVhbGx5LlwiKTtsZXQgcj1lLnByb3RvY29sSWQ9PT1cIk1RSXNkcFwiJiZlLnByb3RvY29sVmVyc2lvbj09PTM/XCJtcXR0djMuMVwiOlwibXF0dFwiO2RTKGUpO2xldCBpPXBTKGUsdCk7Z3Q9d3guY29ubmVjdFNvY2tldCh7dXJsOmkscHJvdG9jb2xzOltyXX0pLGZsPWhTKCksTGU9bmV3IGNTLkJ1ZmZlcmVkRHVwbGV4KGUsZmwsZ3QpLExlLl9kZXN0cm95PShvLHMpPT57Z3QuY2xvc2Uoe3N1Y2Nlc3MoKXtzJiZzKG8pO319KTt9O2xldCBuPUxlLmRlc3Ryb3k7cmV0dXJuIExlLmRlc3Ryb3k9KG8scyk9PihMZS5kZXN0cm95PW4sc2V0VGltZW91dCgoKT0+e2d0LmNsb3NlKHtmYWlsKCl7TGUuX2Rlc3Ryb3kobyxzKTt9fSk7fSwwKSxMZSksZ1MoKSxMZX07Y2wuZGVmYXVsdD15Uzt9KTt2YXIgZ2w9TShwbD0+e3YoKTttKCk7XygpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShwbCxcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTt2YXIgZGw9KHllKCksWChfZSkpLGJTPUR0KCksd1M9b3MoKSxrdCxhcyxhaSx2Zz0hMTtmdW5jdGlvbiBfUygpe2xldCB0PW5ldyBiUy5UcmFuc2Zvcm07cmV0dXJuIHQuX3dyaXRlPShlLHIsaSk9PntrdC5zZW5kU29ja2V0TWVzc2FnZSh7ZGF0YTplLmJ1ZmZlcixzdWNjZXNzKCl7aSgpO30sZmFpbCgpe2kobmV3IEVycm9yKTt9fSk7fSx0Ll9mbHVzaD1lPT57a3QuY2xvc2VTb2NrZXQoe3N1Y2Nlc3MoKXtlKCk7fX0pO30sdH1mdW5jdGlvbiBtUyh0KXt0Lmhvc3RuYW1lfHwodC5ob3N0bmFtZT1cImxvY2FsaG9zdFwiKSx0LnBhdGh8fCh0LnBhdGg9XCIvXCIpLHQud3NPcHRpb25zfHwodC53c09wdGlvbnM9e30pO31mdW5jdGlvbiB2Uyh0LGUpe2xldCByPXQucHJvdG9jb2w9PT1cImFsaXNcIj9cIndzc1wiOlwid3NcIixpPWAke3J9Oi8vJHt0Lmhvc3RuYW1lfSR7dC5wYXRofWA7cmV0dXJuIHQucG9ydCYmdC5wb3J0IT09ODAmJnQucG9ydCE9PTQ0MyYmKGk9YCR7cn06Ly8ke3QuaG9zdG5hbWV9OiR7dC5wb3J0fSR7dC5wYXRofWApLHR5cGVvZiB0LnRyYW5zZm9ybVdzVXJsPT1cImZ1bmN0aW9uXCImJihpPXQudHJhbnNmb3JtV3NVcmwoaSx0LGUpKSxpfWZ1bmN0aW9uIEVTKCl7dmd8fCh2Zz0hMCxrdC5vblNvY2tldE9wZW4oKCk9PnthaS5zb2NrZXRSZWFkeSgpO30pLGt0Lm9uU29ja2V0TWVzc2FnZSh0PT57aWYodHlwZW9mIHQuZGF0YT09XCJzdHJpbmdcIil7bGV0IGU9ZGwuQnVmZmVyLmZyb20odC5kYXRhLFwiYmFzZTY0XCIpO2FzLnB1c2goZSk7fWVsc2Uge2xldCBlPW5ldyBGaWxlUmVhZGVyO2UuYWRkRXZlbnRMaXN0ZW5lcihcImxvYWRcIiwoKT0+e2xldCByPWUucmVzdWx0O3IgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcj9yPWRsLkJ1ZmZlci5mcm9tKHIpOnI9ZGwuQnVmZmVyLmZyb20ocixcInV0ZjhcIiksYXMucHVzaChyKTt9KSxlLnJlYWRBc0FycmF5QnVmZmVyKHQuZGF0YSk7fX0pLGt0Lm9uU29ja2V0Q2xvc2UoKCk9PnthaS5lbmQoKSxhaS5kZXN0cm95KCk7fSksa3Qub25Tb2NrZXRFcnJvcih0PT57YWkuZGVzdHJveSh0KTt9KSk7fXZhciBTUz0odCxlKT0+e2lmKGUuaG9zdG5hbWU9ZS5ob3N0bmFtZXx8ZS5ob3N0LCFlLmhvc3RuYW1lKXRocm93IG5ldyBFcnJvcihcIkNvdWxkIG5vdCBkZXRlcm1pbmUgaG9zdC4gU3BlY2lmeSBob3N0IG1hbnVhbGx5LlwiKTtsZXQgcj1lLnByb3RvY29sSWQ9PT1cIk1RSXNkcFwiJiZlLnByb3RvY29sVmVyc2lvbj09PTM/XCJtcXR0djMuMVwiOlwibXF0dFwiO21TKGUpO2xldCBpPXZTKGUsdCk7cmV0dXJuIGt0PWUubXksa3QuY29ubmVjdFNvY2tldCh7dXJsOmkscHJvdG9jb2xzOnJ9KSxhcz1fUygpLGFpPW5ldyB3Uy5CdWZmZXJlZER1cGxleChlLGFzLGt0KSxFUygpLGFpfTtwbC5kZWZhdWx0PVNTO30pO3ZhciBTZz1NKChQRCxFZyk9Pnt2KCk7bSgpO18oKTtFZy5leHBvcnRzPWZ1bmN0aW9uKCl7dGhyb3cgbmV3IEVycm9yKFwid3MgZG9lcyBub3Qgd29yayBpbiB0aGUgYnJvd3Nlci4gQnJvd3NlciBjbGllbnRzIG11c3QgdXNlIHRoZSBuYXRpdmUgV2ViU29ja2V0IG9iamVjdFwiKX07fSk7dmFyIF9sPU0oVWk9Pnt2KCk7bSgpO18oKTt2YXIgd2w9VWkmJlVpLl9faW1wb3J0RGVmYXVsdHx8ZnVuY3Rpb24odCl7cmV0dXJuIHQmJnQuX19lc01vZHVsZT90OntkZWZhdWx0OnR9fTtPYmplY3QuZGVmaW5lUHJvcGVydHkoVWksXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSk7dmFyIHlsPSh5ZSgpLFgoX2UpKSxBZz13bChTZygpKSxBUz13bChvdCgpKSxJUz1EdCgpLElnPXdsKFBpKCkpLGJsPW9zKCksS3Q9KDAsIEFTLmRlZmF1bHQpKFwibXF0dGpzOndzXCIpLFRTPVtcInJlamVjdFVuYXV0aG9yaXplZFwiLFwiY2FcIixcImNlcnRcIixcImtleVwiLFwicGZ4XCIsXCJwYXNzcGhyYXNlXCJdO2Z1bmN0aW9uIFRnKHQsZSl7bGV0IHI9YCR7dC5wcm90b2NvbH06Ly8ke3QuaG9zdG5hbWV9OiR7dC5wb3J0fSR7dC5wYXRofWA7cmV0dXJuIHR5cGVvZiB0LnRyYW5zZm9ybVdzVXJsPT1cImZ1bmN0aW9uXCImJihyPXQudHJhbnNmb3JtV3NVcmwocix0LGUpKSxyfWZ1bmN0aW9uIFJnKHQpe2xldCBlPXQ7cmV0dXJuIHQuaG9zdG5hbWV8fChlLmhvc3RuYW1lPVwibG9jYWxob3N0XCIpLHQucG9ydHx8KHQucHJvdG9jb2w9PT1cIndzc1wiP2UucG9ydD00NDM6ZS5wb3J0PTgwKSx0LnBhdGh8fChlLnBhdGg9XCIvXCIpLHQud3NPcHRpb25zfHwoZS53c09wdGlvbnM9e30pLCFJZy5kZWZhdWx0JiZ0LnByb3RvY29sPT09XCJ3c3NcIiYmVFMuZm9yRWFjaChyPT57T2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHQscikmJiFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodC53c09wdGlvbnMscikmJihlLndzT3B0aW9uc1tyXT10W3JdKTt9KSxlfWZ1bmN0aW9uIFJTKHQpe2xldCBlPVJnKHQpO2lmKGUuaG9zdG5hbWV8fChlLmhvc3RuYW1lPWUuaG9zdCksIWUuaG9zdG5hbWUpe2lmKHR5cGVvZiBkb2N1bWVudD5cInVcIil0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgZGV0ZXJtaW5lIGhvc3QuIFNwZWNpZnkgaG9zdCBtYW51YWxseS5cIik7bGV0IHI9bmV3IFVSTChkb2N1bWVudC5VUkwpO2UuaG9zdG5hbWU9ci5ob3N0bmFtZSxlLnBvcnR8fChlLnBvcnQ9TnVtYmVyKHIucG9ydCkpO31yZXR1cm4gZS5vYmplY3RNb2RlPT09dm9pZCAwJiYoZS5vYmplY3RNb2RlPSEoZS5iaW5hcnk9PT0hMHx8ZS5iaW5hcnk9PT12b2lkIDApKSxlfWZ1bmN0aW9uIENTKHQsZSxyKXtLdChcImNyZWF0ZVdlYlNvY2tldFwiKSxLdChgcHJvdG9jb2w6ICR7ci5wcm90b2NvbElkfSAke3IucHJvdG9jb2xWZXJzaW9ufWApO2xldCBpPXIucHJvdG9jb2xJZD09PVwiTVFJc2RwXCImJnIucHJvdG9jb2xWZXJzaW9uPT09Mz9cIm1xdHR2My4xXCI6XCJtcXR0XCI7S3QoYGNyZWF0aW5nIG5ldyBXZWJzb2NrZXQgZm9yIHVybDogJHtlfSBhbmQgcHJvdG9jb2w6ICR7aX1gKTtsZXQgbjtyZXR1cm4gci5jcmVhdGVXZWJzb2NrZXQ/bj1yLmNyZWF0ZVdlYnNvY2tldChlLFtpXSxyKTpuPW5ldyBBZy5kZWZhdWx0KGUsW2ldLHIud3NPcHRpb25zKSxufWZ1bmN0aW9uIEJTKHQsZSl7bGV0IHI9ZS5wcm90b2NvbElkPT09XCJNUUlzZHBcIiYmZS5wcm90b2NvbFZlcnNpb249PT0zP1wibXF0dHYzLjFcIjpcIm1xdHRcIixpPVRnKGUsdCksbjtyZXR1cm4gZS5jcmVhdGVXZWJzb2NrZXQ/bj1lLmNyZWF0ZVdlYnNvY2tldChpLFtyXSxlKTpuPW5ldyBXZWJTb2NrZXQoaSxbcl0pLG4uYmluYXJ5VHlwZT1cImFycmF5YnVmZmVyXCIsbn12YXIgUFM9KHQsZSk9PntLdChcInN0cmVhbUJ1aWxkZXJcIik7bGV0IHI9UmcoZSksaT1UZyhyLHQpLG49Q1ModCxpLHIpLG89QWcuZGVmYXVsdC5jcmVhdGVXZWJTb2NrZXRTdHJlYW0obixyLndzT3B0aW9ucyk7cmV0dXJuIG8udXJsPWksbi5vbihcImNsb3NlXCIsKCk9PntvLmRlc3Ryb3koKTt9KSxvfSxPUz0odCxlKT0+e0t0KFwiYnJvd3NlclN0cmVhbUJ1aWxkZXJcIik7bGV0IHIsbj1SUyhlKS5icm93c2VyQnVmZmVyU2l6ZXx8MTAyNCo1MTIsbz1lLmJyb3dzZXJCdWZmZXJUaW1lb3V0fHwxZTMscz0hZS5vYmplY3RNb2RlLGE9QlModCxlKSx1PWgoZSxFLFMpO2Uub2JqZWN0TW9kZXx8KHUuX3dyaXRldj1ibC53cml0ZXYuYmluZCh1KSksdS5vbihcImNsb3NlXCIsKCk9PnthLmNsb3NlKCk7fSk7bGV0IGM9dHlwZW9mIGEuYWRkRXZlbnRMaXN0ZW5lcjxcInVcIjthLnJlYWR5U3RhdGU9PT1hLk9QRU4/KHI9dSxyLnNvY2tldD1hKToocj1uZXcgYmwuQnVmZmVyZWREdXBsZXgoZSx1LGEpLGM/YS5hZGRFdmVudExpc3RlbmVyKFwib3BlblwiLGQpOmEub25vcGVuPWQpLGM/KGEuYWRkRXZlbnRMaXN0ZW5lcihcImNsb3NlXCIsZyksYS5hZGRFdmVudExpc3RlbmVyKFwiZXJyb3JcIix5KSxhLmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsdykpOihhLm9uY2xvc2U9ZyxhLm9uZXJyb3I9eSxhLm9ubWVzc2FnZT13KTtmdW5jdGlvbiBoKEksQyxSKXtsZXQgVT1uZXcgSVMuVHJhbnNmb3JtKHtvYmplY3RNb2RlOkkub2JqZWN0TW9kZX0pO3JldHVybiBVLl93cml0ZT1DLFUuX2ZsdXNoPVIsVX1mdW5jdGlvbiBkKCl7S3QoXCJXZWJTb2NrZXQgb25PcGVuXCIpLHIgaW5zdGFuY2VvZiBibC5CdWZmZXJlZER1cGxleCYmci5zb2NrZXRSZWFkeSgpO31mdW5jdGlvbiBnKEkpe0t0KFwiV2ViU29ja2V0IG9uQ2xvc2VcIixJKSxyLmVuZCgpLHIuZGVzdHJveSgpO31mdW5jdGlvbiB5KEkpe0t0KFwiV2ViU29ja2V0IG9uRXJyb3JcIixJKTtsZXQgQz1uZXcgRXJyb3IoXCJXZWJTb2NrZXQgZXJyb3JcIik7Qy5ldmVudD1JLHIuZGVzdHJveShDKTt9ZnVuY3Rpb24gdyhJKXtsZXR7ZGF0YTpDfT1JO0MgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcj9DPXlsLkJ1ZmZlci5mcm9tKEMpOkM9eWwuQnVmZmVyLmZyb20oQyxcInV0ZjhcIiksdS5wdXNoKEMpO31mdW5jdGlvbiBFKEksQyxSKXtpZihhLmJ1ZmZlcmVkQW1vdW50Pm4pe3NldFRpbWVvdXQoRSxvLEksQyxSKTtyZXR1cm59cyYmdHlwZW9mIEk9PVwic3RyaW5nXCImJihJPXlsLkJ1ZmZlci5mcm9tKEksXCJ1dGY4XCIpKTt0cnl7YS5zZW5kKEkpO31jYXRjaChVKXtyZXR1cm4gUihVKX1SKCk7fWZ1bmN0aW9uIFMoSSl7YS5jbG9zZSgpLEkoKTt9cmV0dXJuIHJ9O1VpLmRlZmF1bHQ9SWcuZGVmYXVsdD9PUzpQUzt9KTt2YXIgUGc9TShScj0+e3YoKTttKCk7XygpO3ZhciBscz1SciYmUnIuX19pbXBvcnREZWZhdWx0fHxmdW5jdGlvbih0KXtyZXR1cm4gdCYmdC5fX2VzTW9kdWxlP3Q6e2RlZmF1bHQ6dH19O09iamVjdC5kZWZpbmVQcm9wZXJ0eShScixcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTtSci5jb25uZWN0QXN5bmM9dm9pZCAwO3ZhciBrUz1scyhvdCgpKSx4Uz1scygocGcoKSxYKGRnKSkpLE1TPWxzKG5zKCkpLExTPWxzKFBpKCkpLENnPSgwLCBrUy5kZWZhdWx0KShcIm1xdHRqc1wiKSxSZT17fTtMUy5kZWZhdWx0PyhSZS53eD1obCgpLmRlZmF1bHQsUmUud3hzPWhsKCkuZGVmYXVsdCxSZS5hbGk9Z2woKS5kZWZhdWx0LFJlLmFsaXM9Z2woKS5kZWZhdWx0KTooUmUubXF0dD1vbCgpLmRlZmF1bHQsUmUudGNwPW9sKCkuZGVmYXVsdCxSZS5zc2w9bGwoKS5kZWZhdWx0LFJlLnRscz1SZS5zc2wsUmUubXF0dHM9bGwoKS5kZWZhdWx0KTtSZS53cz1fbCgpLmRlZmF1bHQ7UmUud3NzPV9sKCkuZGVmYXVsdDtmdW5jdGlvbiBVUyh0KXtsZXQgZTt0LmF1dGgmJihlPXQuYXV0aC5tYXRjaCgvXiguKyk6KC4rKSQvKSxlPyh0LnVzZXJuYW1lPWVbMV0sdC5wYXNzd29yZD1lWzJdKTp0LnVzZXJuYW1lPXQuYXV0aCk7fWZ1bmN0aW9uIEJnKHQsZSl7aWYoQ2coXCJjb25uZWN0aW5nIHRvIGFuIE1RVFQgYnJva2VyLi4uXCIpLHR5cGVvZiB0PT1cIm9iamVjdFwiJiYhZSYmKGU9dCx0PVwiXCIpLGU9ZXx8e30sdCYmdHlwZW9mIHQ9PVwic3RyaW5nXCIpe2xldCBuPXhTLmRlZmF1bHQucGFyc2UodCwhMCk7aWYobi5wb3J0IT1udWxsJiYobi5wb3J0PU51bWJlcihuLnBvcnQpKSxlPU9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxuKSxlKSxlLnByb3RvY29sPT09bnVsbCl0aHJvdyBuZXcgRXJyb3IoXCJNaXNzaW5nIHByb3RvY29sXCIpO2UucHJvdG9jb2w9ZS5wcm90b2NvbC5yZXBsYWNlKC86JC8sXCJcIik7fWlmKFVTKGUpLGUucXVlcnkmJnR5cGVvZiBlLnF1ZXJ5LmNsaWVudElkPT1cInN0cmluZ1wiJiYoZS5jbGllbnRJZD1lLnF1ZXJ5LmNsaWVudElkKSxlLmNlcnQmJmUua2V5KWlmKGUucHJvdG9jb2wpe2lmKFtcIm1xdHRzXCIsXCJ3c3NcIixcInd4c1wiLFwiYWxpc1wiXS5pbmRleE9mKGUucHJvdG9jb2wpPT09LTEpc3dpdGNoKGUucHJvdG9jb2wpe2Nhc2VcIm1xdHRcIjplLnByb3RvY29sPVwibXF0dHNcIjticmVhaztjYXNlXCJ3c1wiOmUucHJvdG9jb2w9XCJ3c3NcIjticmVhaztjYXNlXCJ3eFwiOmUucHJvdG9jb2w9XCJ3eHNcIjticmVhaztjYXNlXCJhbGlcIjplLnByb3RvY29sPVwiYWxpc1wiO2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHByb3RvY29sIGZvciBzZWN1cmUgY29ubmVjdGlvbjogXCIke2UucHJvdG9jb2x9XCIhYCl9fWVsc2UgdGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyBzZWN1cmUgcHJvdG9jb2wga2V5XCIpO2lmKCFSZVtlLnByb3RvY29sXSl7bGV0IG49W1wibXF0dHNcIixcIndzc1wiXS5pbmRleE9mKGUucHJvdG9jb2wpIT09LTE7ZS5wcm90b2NvbD1bXCJtcXR0XCIsXCJtcXR0c1wiLFwid3NcIixcIndzc1wiLFwid3hcIixcInd4c1wiLFwiYWxpXCIsXCJhbGlzXCJdLmZpbHRlcigobyxzKT0+biYmcyUyPT09MD8hMTp0eXBlb2YgUmVbb109PVwiZnVuY3Rpb25cIilbMF07fWlmKGUuY2xlYW49PT0hMSYmIWUuY2xpZW50SWQpdGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyBjbGllbnRJZCBmb3IgdW5jbGVhbiBjbGllbnRzXCIpO2UucHJvdG9jb2wmJihlLmRlZmF1bHRQcm90b2NvbD1lLnByb3RvY29sKTtmdW5jdGlvbiByKG4pe3JldHVybiBlLnNlcnZlcnMmJigoIW4uX3JlY29ubmVjdENvdW50fHxuLl9yZWNvbm5lY3RDb3VudD09PWUuc2VydmVycy5sZW5ndGgpJiYobi5fcmVjb25uZWN0Q291bnQ9MCksZS5ob3N0PWUuc2VydmVyc1tuLl9yZWNvbm5lY3RDb3VudF0uaG9zdCxlLnBvcnQ9ZS5zZXJ2ZXJzW24uX3JlY29ubmVjdENvdW50XS5wb3J0LGUucHJvdG9jb2w9ZS5zZXJ2ZXJzW24uX3JlY29ubmVjdENvdW50XS5wcm90b2NvbD9lLnNlcnZlcnNbbi5fcmVjb25uZWN0Q291bnRdLnByb3RvY29sOmUuZGVmYXVsdFByb3RvY29sLGUuaG9zdG5hbWU9ZS5ob3N0LG4uX3JlY29ubmVjdENvdW50KyspLENnKFwiY2FsbGluZyBzdHJlYW1idWlsZGVyIGZvclwiLGUucHJvdG9jb2wpLFJlW2UucHJvdG9jb2xdKG4sZSl9bGV0IGk9bmV3IE1TLmRlZmF1bHQocixlKTtyZXR1cm4gaS5vbihcImVycm9yXCIsKCk9Pnt9KSxpfWZ1bmN0aW9uIE5TKHQsZSxyPSEwKXtyZXR1cm4gbmV3IFByb21pc2UoKGksbik9PntsZXQgbz1CZyh0LGUpLHM9e2Nvbm5lY3Q6dT0+e2EoKSxpKG8pO30sZW5kOigpPT57YSgpLGkobyk7fSxlcnJvcjp1PT57YSgpLG8uZW5kKCksbih1KTt9fTtyPT09ITEmJihzLmNsb3NlPSgpPT57cy5lcnJvcihuZXcgRXJyb3IoXCJDb3VsZG4ndCBjb25uZWN0IHRvIHNlcnZlclwiKSk7fSk7ZnVuY3Rpb24gYSgpe09iamVjdC5rZXlzKHMpLmZvckVhY2godT0+e28ub2ZmKHUsc1t1XSk7fSk7fU9iamVjdC5rZXlzKHMpLmZvckVhY2godT0+e28ub24odSxzW3VdKTt9KTt9KX1Sci5jb25uZWN0QXN5bmM9TlM7UnIuZGVmYXVsdD1CZzt9KTt2YXIgbWw9TShHPT57digpO20oKTtfKCk7dmFyIE9nPUcmJkcuX19jcmVhdGVCaW5kaW5nfHwoT2JqZWN0LmNyZWF0ZT9mdW5jdGlvbih0LGUscixpKXtpPT09dm9pZCAwJiYoaT1yKTt2YXIgbj1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGUscik7KCFufHwoXCJnZXRcImluIG4/IWUuX19lc01vZHVsZTpuLndyaXRhYmxlfHxuLmNvbmZpZ3VyYWJsZSkpJiYobj17ZW51bWVyYWJsZTohMCxnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gZVtyXX19KSxPYmplY3QuZGVmaW5lUHJvcGVydHkodCxpLG4pO306ZnVuY3Rpb24odCxlLHIsaSl7aT09PXZvaWQgMCYmKGk9ciksdFtpXT1lW3JdO30pLHFTPUcmJkcuX19zZXRNb2R1bGVEZWZhdWx0fHwoT2JqZWN0LmNyZWF0ZT9mdW5jdGlvbih0LGUpe09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LFwiZGVmYXVsdFwiLHtlbnVtZXJhYmxlOiEwLHZhbHVlOmV9KTt9OmZ1bmN0aW9uKHQsZSl7dC5kZWZhdWx0PWU7fSksRFM9RyYmRy5fX2ltcG9ydFN0YXJ8fGZ1bmN0aW9uKHQpe2lmKHQmJnQuX19lc01vZHVsZSlyZXR1cm4gdDt2YXIgZT17fTtpZih0IT1udWxsKWZvcih2YXIgciBpbiB0KXIhPT1cImRlZmF1bHRcIiYmT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHQscikmJk9nKGUsdCxyKTtyZXR1cm4gcVMoZSx0KSxlfSxrZz1HJiZHLl9fZXhwb3J0U3Rhcnx8ZnVuY3Rpb24odCxlKXtmb3IodmFyIHIgaW4gdClyIT09XCJkZWZhdWx0XCImJiFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZSxyKSYmT2coZSx0LHIpO30sTmk9RyYmRy5fX2ltcG9ydERlZmF1bHR8fGZ1bmN0aW9uKHQpe3JldHVybiB0JiZ0Ll9fZXNNb2R1bGU/dDp7ZGVmYXVsdDp0fX07T2JqZWN0LmRlZmluZVByb3BlcnR5KEcsXCJfX2VzTW9kdWxlXCIse3ZhbHVlOiEwfSk7Ry5SZWFzb25Db2Rlcz1HLlBpbmdUaW1lcj1HLlVuaXF1ZU1lc3NhZ2VJZFByb3ZpZGVyPUcuRGVmYXVsdE1lc3NhZ2VJZFByb3ZpZGVyPUcuU3RvcmU9Ry5NcXR0Q2xpZW50PUcuY29ubmVjdEFzeW5jPUcuY29ubmVjdD1HLkNsaWVudD12b2lkIDA7dmFyIHhnPU5pKG5zKCkpO0cuTXF0dENsaWVudD14Zy5kZWZhdWx0O3ZhciBqUz1OaShZbygpKTtHLkRlZmF1bHRNZXNzYWdlSWRQcm92aWRlcj1qUy5kZWZhdWx0O3ZhciBGUz1OaSgkcCgpKTtHLlVuaXF1ZU1lc3NhZ2VJZFByb3ZpZGVyPUZTLmRlZmF1bHQ7dmFyIFdTPU5pKFpvKCkpO0cuU3RvcmU9V1MuZGVmYXVsdDt2YXIgTWc9RFMoUGcoKSk7Ry5jb25uZWN0PU1nLmRlZmF1bHQ7T2JqZWN0LmRlZmluZVByb3BlcnR5KEcsXCJjb25uZWN0QXN5bmNcIix7ZW51bWVyYWJsZTohMCxnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gTWcuY29ubmVjdEFzeW5jfX0pO3ZhciAkUz1OaShEYSgpKTtHLlBpbmdUaW1lcj0kUy5kZWZhdWx0O0cuQ2xpZW50PXhnLmRlZmF1bHQ7a2cobnMoKSxHKTtrZyhKcigpLEcpO3ZhciBIUz1BaSgpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShHLFwiUmVhc29uQ29kZXNcIix7ZW51bWVyYWJsZTohMCxnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gSFMuUmVhc29uQ29kZXN9fSk7fSk7dmFyIFFTPU0oV2U9Pnt2KCk7bSgpO18oKTt2YXIgTGc9V2UmJldlLl9fY3JlYXRlQmluZGluZ3x8KE9iamVjdC5jcmVhdGU/ZnVuY3Rpb24odCxlLHIsaSl7aT09PXZvaWQgMCYmKGk9cik7dmFyIG49T2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihlLHIpOyghbnx8KFwiZ2V0XCJpbiBuPyFlLl9fZXNNb2R1bGU6bi53cml0YWJsZXx8bi5jb25maWd1cmFibGUpKSYmKG49e2VudW1lcmFibGU6ITAsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIGVbcl19fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KHQsaSxuKTt9OmZ1bmN0aW9uKHQsZSxyLGkpe2k9PT12b2lkIDAmJihpPXIpLHRbaV09ZVtyXTt9KSxWUz1XZSYmV2UuX19zZXRNb2R1bGVEZWZhdWx0fHwoT2JqZWN0LmNyZWF0ZT9mdW5jdGlvbih0LGUpe09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LFwiZGVmYXVsdFwiLHtlbnVtZXJhYmxlOiEwLHZhbHVlOmV9KTt9OmZ1bmN0aW9uKHQsZSl7dC5kZWZhdWx0PWU7fSkselM9V2UmJldlLl9faW1wb3J0U3Rhcnx8ZnVuY3Rpb24odCl7aWYodCYmdC5fX2VzTW9kdWxlKXJldHVybiB0O3ZhciBlPXt9O2lmKHQhPW51bGwpZm9yKHZhciByIGluIHQpciE9PVwiZGVmYXVsdFwiJiZPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCxyKSYmTGcoZSx0LHIpO3JldHVybiBWUyhlLHQpLGV9LEtTPVdlJiZXZS5fX2V4cG9ydFN0YXJ8fGZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByIGluIHQpciE9PVwiZGVmYXVsdFwiJiYhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGUscikmJkxnKGUsdCxyKTt9O09iamVjdC5kZWZpbmVQcm9wZXJ0eShXZSxcIl9fZXNNb2R1bGVcIix7dmFsdWU6ITB9KTt2YXIgR1M9elMobWwoKSk7V2UuZGVmYXVsdD1HUztLUyhtbCgpLFdlKTt9KTt2YXIgbXF0dCA9IFFTKCk7XG4vKiEgQnVuZGxlZCBsaWNlbnNlIGluZm9ybWF0aW9uOlxuXG5AanNwbS9jb3JlL25vZGVsaWJzL2Jyb3dzZXIvYnVmZmVyLmpzOlxuICAoKiEgaWVlZTc1NC4gQlNELTMtQ2xhdXNlIExpY2Vuc2UuIEZlcm9zcyBBYm91a2hhZGlqZWggPGh0dHBzOi8vZmVyb3NzLm9yZy9vcGVuc291cmNlPiAqKVxuKi9cblxuY2xhc3MgQ2xvdWRJbnRlcm9wQVBJIHtcbiAgICBjb25uZWN0UGFyYW1zO1xuICAgIF9zZXNzaW9uRGV0YWlscztcbiAgICBfbXF0dENsaWVudDtcbiAgICByZWNvbm5lY3RSZXRyeUxpbWl0ID0gMzA7XG4gICAgcmVjb25uZWN0UmV0cmllcyA9IDA7XG4gICAgY29udGV4dExpc3RlbmVyO1xuICAgIGNvbnN0cnVjdG9yKGNvbm5lY3RQYXJhbXMpIHtcbiAgICAgICAgdGhpcy5jb25uZWN0UGFyYW1zID0gY29ubmVjdFBhcmFtcztcbiAgICB9XG4gICAgZ2V0IHNlc3Npb25EZXRhaWxzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2Vzc2lvbkRldGFpbHM7XG4gICAgfVxuICAgIGdldCBtcXR0Q2xpZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbXF0dENsaWVudDtcbiAgICB9XG4gICAgYXN5bmMgY29ubmVjdChwYXJhbXMpIHtcbiAgICAgICAgY29uc3QgeyB1c2VySWQsIHBhc3N3b3JkLCBzb3VyY2VJZCwgcGxhdGZvcm1JZCB9ID0gcGFyYW1zO1xuICAgICAgICBsZXQgY29ubmVjdFJlc3BvbnNlO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29ubmVjdFJlc3BvbnNlID0gYXdhaXQgYXhpb3MucG9zdChgJHt0aGlzLmNvbm5lY3RQYXJhbXMudXJsfS9zZXNzaW9uc2AsIHtcbiAgICAgICAgICAgICAgICB1c2VySWQsXG4gICAgICAgICAgICAgICAgc291cmNlSWQsXG4gICAgICAgICAgICAgICAgcGxhdGZvcm1JZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoY29ubmVjdFJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gY29ubmVjdCB0byBDbG91ZCBJbnRlcm9wIHVybDogJHt0aGlzLmNvbm5lY3RQYXJhbXMudXJsfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgeyBzZXNzaW9uUm9vdFRvcGljIH0gPSBjb25uZWN0UmVzcG9uc2UuZGF0YTtcbiAgICAgICAgICAgIGNvbnN0IGxhc3RXaWxsUGF5bG9hZCA9IHtcbiAgICAgICAgICAgICAgICB1c2VySWQsXG4gICAgICAgICAgICAgICAgc291cmNlSWQsXG4gICAgICAgICAgICAgICAgcGxhdGZvcm1JZCxcbiAgICAgICAgICAgICAgICBzZXNzaW9uSWQ6IGNvbm5lY3RSZXNwb25zZS5kYXRhLnNlc3Npb25JZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IGNsaWVudE9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgY2xpZW50SWQ6IGNvbm5lY3RSZXNwb25zZS5kYXRhLnNlc3Npb25JZCxcbiAgICAgICAgICAgICAgICBjbGVhbjogdHJ1ZSxcbiAgICAgICAgICAgICAgICBwcm90b2NvbFZlcnNpb246IDUsXG4gICAgICAgICAgICAgICAgd2lsbDoge1xuICAgICAgICAgICAgICAgICAgICB0b3BpYzogJ2ludGVyb3AvbGFzdHdpbGwnLFxuICAgICAgICAgICAgICAgICAgICBwYXlsb2FkOiBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShsYXN0V2lsbFBheWxvYWQpKSxcbiAgICAgICAgICAgICAgICAgICAgcW9zOiAwLFxuICAgICAgICAgICAgICAgICAgICByZXRhaW46IGZhbHNlXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB1c2VybmFtZTogdXNlcklkLFxuICAgICAgICAgICAgICAgIHBhc3N3b3JkXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5fbXF0dENsaWVudCA9IGF3YWl0IG1xdHQuY29ubmVjdEFzeW5jKGNvbm5lY3RSZXNwb25zZS5kYXRhLm1xdHRVcmwsIGNsaWVudE9wdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5fc2Vzc2lvbkRldGFpbHMgPSBjb25uZWN0UmVzcG9uc2UuZGF0YTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBDbG91ZCBJbnRlcm9wIHN1Y2Nlc3NmdWxseSBjb25uZWN0ZWQgdG8gJHt0aGlzLmNvbm5lY3RQYXJhbXMudXJsfWApO1xuICAgICAgICAgICAgdGhpcy5fbXF0dENsaWVudC5vbignZXJyb3InLCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBDbG91ZCBJbnRlcm9wIEVycm9yOiAke2Vycm9yfWApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLl9tcXR0Q2xpZW50LnN0cmVhbS5vbignZXJyb3InLCAoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBDbG91ZCBJbnRlcm9wIENvbm5lY3Rpb24gRXJyb3I6ICR7ZXJyb3J9YCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuX21xdHRDbGllbnQub24oJ3JlY29ubmVjdCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYENsb3VkIEludGVyb3AgYXR0ZW1wdGluZyByZWNvbm5lY3Rpb24uLi5gKTtcbiAgICAgICAgICAgICAgICAvLyBEZWZhdWx0IHJlY29ubmVjdFBlcmlvZCA9IDMwIHNlY29uZHNcbiAgICAgICAgICAgICAgICAvLyBBdHRlbXB0IHJlY29ubmVjdGlvbiAzMCB0aW1lcyBiZWZvcmUgZW5kaW5nIHNlc3Npb25cbiAgICAgICAgICAgICAgICB0aGlzLnJlY29ubmVjdFJldHJpZXMgKz0gMTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZWNvbm5lY3RSZXRyaWVzID09PSB0aGlzLnJlY29ubmVjdFJldHJ5TGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBDbG91ZCBJbnRlcm9wIHJlYWNoZWQgbWF4IHJlY29ubmVjdGlvbiBhdHRlbXB0cy4uLmApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIERvZXMgbm90IGZpcmUgb24gaW5pdGlhbCBjb25uZWN0aW9uLCBvbmx5IHN1Y2Nlc3NmdWwgcmVjb25uZWN0aW9uIGF0dGVtcHRzXG4gICAgICAgICAgICB0aGlzLl9tcXR0Q2xpZW50Lm9uKCdjb25uZWN0JywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBDbG91ZCBJbnRlcm9wIHN1Y2Nlc3NmdWxseSByZWNvbm5lY3RlZGApO1xuICAgICAgICAgICAgICAgIHRoaXMucmVjb25uZWN0UmV0cmllcyA9IDA7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuX21xdHRDbGllbnQub24oJ21lc3NhZ2UnLCAodG9waWMsIG1lc3NhZ2UpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZUNvbW1hbmQodG9waWMsIG1lc3NhZ2UsIHRoaXMuX3Nlc3Npb25EZXRhaWxzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gU3Vic2NyaWJlIHRvIGFsbCBjb250ZXh0IGdyb3Vwc1xuICAgICAgICAgICAgdGhpcy5fbXF0dENsaWVudC5zdWJzY3JpYmUoYCR7c2Vzc2lvblJvb3RUb3BpY30vY29udGV4dC1ncm91cHMvI2ApO1xuICAgICAgICAgICAgLy8gTGlzdGVuIG91dCBmb3IgZ2xvYmFsIGNvbW1hbmRzXG4gICAgICAgICAgICB0aGlzLl9tcXR0Q2xpZW50LnN1YnNjcmliZShgJHtzZXNzaW9uUm9vdFRvcGljfS9jb21tYW5kc2ApO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBGYWlsZWQgdG8gY29ubmVjdCB0byBDbG91ZCBJbnRlcm9wIGF0ICR7dGhpcy5jb25uZWN0UGFyYW1zLnVybH1gLCBlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYXN5bmMgZGlzY29ubmVjdCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9zZXNzaW9uRGV0YWlscykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBkaXNjb25uZWN0UmVzcG9uc2UgPSBhd2FpdCBheGlvcy5kZWxldGUoYCR7dGhpcy5jb25uZWN0UGFyYW1zLnVybH0vc2Vzc2lvbnMvJHt0aGlzLl9zZXNzaW9uRGV0YWlscy5zZXNzaW9uSWR9YCk7XG4gICAgICAgICAgICBpZiAoZGlzY29ubmVjdFJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBDbG91ZCBJbnRlcm9wIGRpc2Nvbm5lY3Rpb24gZmFpbGVkYCwgZGlzY29ubmVjdFJlc3BvbnNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgQ2xvdWQgSW50ZXJvcCBlcnJvciBkdXJpbmcgZGlzY29ubmVjdGlvbmAsIGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRoaXMuX21xdHRDbGllbnQ/LnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgICAgICAgICAgdGhpcy5fbXF0dENsaWVudD8uZW5kKHRydWUpO1xuICAgICAgICAgICAgdGhpcy5fc2Vzc2lvbkRldGFpbHMgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLl9tcXR0Q2xpZW50ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3RSZXRyaWVzID0gMDtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhc3luYyBzZXRDb250ZXh0KGNvbnRleHRHcm91cCwgY29udGV4dCkge1xuICAgICAgICBpZiAoIXRoaXMuX3Nlc3Npb25EZXRhaWxzKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyB1c2VySWQsIHNvdXJjZUlkIH0gPSB0aGlzLmNvbm5lY3RQYXJhbXM7XG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICB1c2VySWQsXG4gICAgICAgICAgICBzb3VyY2VJZCxcbiAgICAgICAgICAgIGNvbnRleHRcbiAgICAgICAgfTtcbiAgICAgICAgYXdhaXQgYXhpb3MucG9zdChgJHt0aGlzLmNvbm5lY3RQYXJhbXMudXJsfS9jb250ZXh0LWdyb3Vwcy8ke3RoaXMuX3Nlc3Npb25EZXRhaWxzLnNlc3Npb25JZH0vJHtjb250ZXh0R3JvdXB9YCwgcGF5bG9hZCk7XG4gICAgfVxuICAgIGFkZENvbnRleHRMaXN0ZW5lcihjYWxsYmFjaykge1xuICAgICAgICB0aGlzLmNvbnRleHRMaXN0ZW5lciA9IGNhbGxiYWNrO1xuICAgIH1cbiAgICBzdGFydEludGVudERpc2NvdmVyeShpbnRlbnROYW1lLCBjb250ZXh0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgICB9XG4gICAgZW5kSW50ZW50RGlzY292ZXJ5KGRpc2NvdmVyeUlkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgICB9XG4gICAgc2VuZEludGVudERldGFpbChkaXNjb3ZlcnlJZCwgaW50ZW50RGV0YWlsKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgICB9XG4gICAgcmFpc2VJbnRlbnQodGFyZ2V0U2Vzc2lvbiwgaW50ZW50SW5zdGFuY2VJZCwgY29udGV4dCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQuJyk7XG4gICAgfVxuICAgIGFkZEludGVudERldGFpbExpc3RlbmVyKGNhbGxiYWNrKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgICB9XG4gICAgaGFuZGxlQ29tbWFuZCh0b3BpYywgbWVzc2FnZSwgc2Vzc2lvbkRldGFpbHMpIHtcbiAgICAgICAgaWYgKG1lc3NhZ2UubGVuZ3RoID09PSAwIHx8ICFzZXNzaW9uRGV0YWlscykge1xuICAgICAgICAgICAgLy8gSWdub3JlIGNsZWFuIHVwIG1lc3NhZ2VzXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbWVzc2FnZUVudmVsb3BlID0gSlNPTi5wYXJzZShtZXNzYWdlLnRvU3RyaW5nKCkpO1xuICAgICAgICBpZiAodG9waWMuc3RhcnRzV2l0aChgJHtzZXNzaW9uRGV0YWlscy5zZXNzaW9uUm9vdFRvcGljfS9jb250ZXh0LWdyb3Vwcy9gKSkge1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2VFbnZlbG9wZS5zb3VyY2Uuc2Vzc2lvbklkID09PSBzZXNzaW9uRGV0YWlscy5zZXNzaW9uSWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5jb250ZXh0TGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB7IGNoYW5uZWxOYW1lOiBjb250ZXh0R3JvdXAsIHBheWxvYWQ6IGNvbnRleHQsIHNvdXJjZSB9ID0gbWVzc2FnZUVudmVsb3BlO1xuICAgICAgICAgICAgICAgIHRoaXMuY29udGV4dExpc3RlbmVyKGNvbnRleHRHcm91cCwgY29udGV4dCwgc291cmNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gY2xvdWRJbnRlcm9wT3ZlcnJpZGUoY29uZmlnKSB7XG4gICAgY29uc3QgY2xpZW50ID0gbmV3IENsb3VkSW50ZXJvcEFQSShjb25maWcpO1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGNsaWVudC5jb25uZWN0KGNvbmZpZyk7XG4gICAgfVxuICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGVycik7XG4gICAgICAgIHJldHVybiAoQmFzZSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGNsYXNzIE5vT3BPdmVycmlkZSBleHRlbmRzIEJhc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgICAgICAgICBzdXBlcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiAoQmFzZSkgPT4ge1xuICAgICAgICByZXR1cm4gY2xhc3MgQ2xvdWRJbnRlcm9wT3ZlcnJpZGUgZXh0ZW5kcyBCYXNlIHtcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAgICAgICAgIHN1cGVyKCk7XG4gICAgICAgICAgICAgICAgY2xpZW50LmFkZENvbnRleHRMaXN0ZW5lcigoY29udGV4dEdyb3VwLCBjb250ZXh0LCBzb3VyY2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZ2V0Q29udGV4dEdyb3VwcygpXG4gICAgICAgICAgICAgICAgICAgICAgICAubWFwKCh7IGlkIH0pID0+IGlkKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmluY2x1ZGVzKGNvbnRleHRHcm91cCkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsaWVudC5zZXNzaW9uRGV0YWlscz8uc2Vzc2lvbklkICE9PSBzb3VyY2Uuc2Vzc2lvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdXBlci5zZXRDb250ZXh0Rm9yR3JvdXAoeyBjb250ZXh0OiBjb250ZXh0IH0sIGNvbnRleHRHcm91cCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzeW5jIHNldENvbnRleHRGb3JHcm91cCh7IGNvbnRleHQgfSwgY29udGV4dEdyb3VwSWQpIHtcbiAgICAgICAgICAgICAgICBjbGllbnQuc2V0Q29udGV4dChjb250ZXh0R3JvdXBJZCwgY29udGV4dCk7XG4gICAgICAgICAgICAgICAgc3VwZXIuc2V0Q29udGV4dEZvckdyb3VwKHsgY29udGV4dCB9LCBjb250ZXh0R3JvdXBJZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhc3luYyBjbG91ZFJlY29ubmVjdCgpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBjbGllbnQuY29ubmVjdChjb25maWcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ2V0IGNsb3VkQ29ubmVjdGlvblN0YXRlKCkge1xuICAgICAgICAgICAgICAgIGlmIChjbGllbnQubXF0dENsaWVudD8uY29ubmVjdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnY29ubmVjdGVkJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGNsaWVudC5tcXR0Q2xpZW50Py5yZWNvbm5lY3RpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdyZWNvbm5lY3RpbmcnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gJ2Rpc2Nvbm5lY3RlZCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfTtcbn1cblxuZXhwb3J0IHsgY2xvdWRJbnRlcm9wT3ZlcnJpZGUgfTtcbiIsIid1c2Ugc3RyaWN0J1xuXG5leHBvcnRzLmJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoXG5leHBvcnRzLnRvQnl0ZUFycmF5ID0gdG9CeXRlQXJyYXlcbmV4cG9ydHMuZnJvbUJ5dGVBcnJheSA9IGZyb21CeXRlQXJyYXlcblxudmFyIGxvb2t1cCA9IFtdXG52YXIgcmV2TG9va3VwID0gW11cbnZhciBBcnIgPSB0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcgPyBVaW50OEFycmF5IDogQXJyYXlcblxudmFyIGNvZGUgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLydcbmZvciAodmFyIGkgPSAwLCBsZW4gPSBjb2RlLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XG4gIGxvb2t1cFtpXSA9IGNvZGVbaV1cbiAgcmV2TG9va3VwW2NvZGUuY2hhckNvZGVBdChpKV0gPSBpXG59XG5cbi8vIFN1cHBvcnQgZGVjb2RpbmcgVVJMLXNhZmUgYmFzZTY0IHN0cmluZ3MsIGFzIE5vZGUuanMgZG9lcy5cbi8vIFNlZTogaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQmFzZTY0I1VSTF9hcHBsaWNhdGlvbnNcbnJldkxvb2t1cFsnLScuY2hhckNvZGVBdCgwKV0gPSA2MlxucmV2TG9va3VwWydfJy5jaGFyQ29kZUF0KDApXSA9IDYzXG5cbmZ1bmN0aW9uIGdldExlbnMgKGI2NCkge1xuICB2YXIgbGVuID0gYjY0Lmxlbmd0aFxuXG4gIGlmIChsZW4gJSA0ID4gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzdHJpbmcuIExlbmd0aCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNCcpXG4gIH1cblxuICAvLyBUcmltIG9mZiBleHRyYSBieXRlcyBhZnRlciBwbGFjZWhvbGRlciBieXRlcyBhcmUgZm91bmRcbiAgLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vYmVhdGdhbW1pdC9iYXNlNjQtanMvaXNzdWVzLzQyXG4gIHZhciB2YWxpZExlbiA9IGI2NC5pbmRleE9mKCc9JylcbiAgaWYgKHZhbGlkTGVuID09PSAtMSkgdmFsaWRMZW4gPSBsZW5cblxuICB2YXIgcGxhY2VIb2xkZXJzTGVuID0gdmFsaWRMZW4gPT09IGxlblxuICAgID8gMFxuICAgIDogNCAtICh2YWxpZExlbiAlIDQpXG5cbiAgcmV0dXJuIFt2YWxpZExlbiwgcGxhY2VIb2xkZXJzTGVuXVxufVxuXG4vLyBiYXNlNjQgaXMgNC8zICsgdXAgdG8gdHdvIGNoYXJhY3RlcnMgb2YgdGhlIG9yaWdpbmFsIGRhdGFcbmZ1bmN0aW9uIGJ5dGVMZW5ndGggKGI2NCkge1xuICB2YXIgbGVucyA9IGdldExlbnMoYjY0KVxuICB2YXIgdmFsaWRMZW4gPSBsZW5zWzBdXG4gIHZhciBwbGFjZUhvbGRlcnNMZW4gPSBsZW5zWzFdXG4gIHJldHVybiAoKHZhbGlkTGVuICsgcGxhY2VIb2xkZXJzTGVuKSAqIDMgLyA0KSAtIHBsYWNlSG9sZGVyc0xlblxufVxuXG5mdW5jdGlvbiBfYnl0ZUxlbmd0aCAoYjY0LCB2YWxpZExlbiwgcGxhY2VIb2xkZXJzTGVuKSB7XG4gIHJldHVybiAoKHZhbGlkTGVuICsgcGxhY2VIb2xkZXJzTGVuKSAqIDMgLyA0KSAtIHBsYWNlSG9sZGVyc0xlblxufVxuXG5mdW5jdGlvbiB0b0J5dGVBcnJheSAoYjY0KSB7XG4gIHZhciB0bXBcbiAgdmFyIGxlbnMgPSBnZXRMZW5zKGI2NClcbiAgdmFyIHZhbGlkTGVuID0gbGVuc1swXVxuICB2YXIgcGxhY2VIb2xkZXJzTGVuID0gbGVuc1sxXVxuXG4gIHZhciBhcnIgPSBuZXcgQXJyKF9ieXRlTGVuZ3RoKGI2NCwgdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbikpXG5cbiAgdmFyIGN1ckJ5dGUgPSAwXG5cbiAgLy8gaWYgdGhlcmUgYXJlIHBsYWNlaG9sZGVycywgb25seSBnZXQgdXAgdG8gdGhlIGxhc3QgY29tcGxldGUgNCBjaGFyc1xuICB2YXIgbGVuID0gcGxhY2VIb2xkZXJzTGVuID4gMFxuICAgID8gdmFsaWRMZW4gLSA0XG4gICAgOiB2YWxpZExlblxuXG4gIHZhciBpXG4gIGZvciAoaSA9IDA7IGkgPCBsZW47IGkgKz0gNCkge1xuICAgIHRtcCA9XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxOCkgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldIDw8IDEyKSB8XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAyKV0gPDwgNikgfFxuICAgICAgcmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAzKV1cbiAgICBhcnJbY3VyQnl0ZSsrXSA9ICh0bXAgPj4gMTYpICYgMHhGRlxuICAgIGFycltjdXJCeXRlKytdID0gKHRtcCA+PiA4KSAmIDB4RkZcbiAgICBhcnJbY3VyQnl0ZSsrXSA9IHRtcCAmIDB4RkZcbiAgfVxuXG4gIGlmIChwbGFjZUhvbGRlcnNMZW4gPT09IDIpIHtcbiAgICB0bXAgPVxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMikgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldID4+IDQpXG4gICAgYXJyW2N1ckJ5dGUrK10gPSB0bXAgJiAweEZGXG4gIH1cblxuICBpZiAocGxhY2VIb2xkZXJzTGVuID09PSAxKSB7XG4gICAgdG1wID1cbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSldIDw8IDEwKSB8XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAxKV0gPDwgNCkgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMildID4+IDIpXG4gICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDgpICYgMHhGRlxuICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIGFyclxufVxuXG5mdW5jdGlvbiB0cmlwbGV0VG9CYXNlNjQgKG51bSkge1xuICByZXR1cm4gbG9va3VwW251bSA+PiAxOCAmIDB4M0ZdICtcbiAgICBsb29rdXBbbnVtID4+IDEyICYgMHgzRl0gK1xuICAgIGxvb2t1cFtudW0gPj4gNiAmIDB4M0ZdICtcbiAgICBsb29rdXBbbnVtICYgMHgzRl1cbn1cblxuZnVuY3Rpb24gZW5jb2RlQ2h1bmsgKHVpbnQ4LCBzdGFydCwgZW5kKSB7XG4gIHZhciB0bXBcbiAgdmFyIG91dHB1dCA9IFtdXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSArPSAzKSB7XG4gICAgdG1wID1cbiAgICAgICgodWludDhbaV0gPDwgMTYpICYgMHhGRjAwMDApICtcbiAgICAgICgodWludDhbaSArIDFdIDw8IDgpICYgMHhGRjAwKSArXG4gICAgICAodWludDhbaSArIDJdICYgMHhGRilcbiAgICBvdXRwdXQucHVzaCh0cmlwbGV0VG9CYXNlNjQodG1wKSlcbiAgfVxuICByZXR1cm4gb3V0cHV0LmpvaW4oJycpXG59XG5cbmZ1bmN0aW9uIGZyb21CeXRlQXJyYXkgKHVpbnQ4KSB7XG4gIHZhciB0bXBcbiAgdmFyIGxlbiA9IHVpbnQ4Lmxlbmd0aFxuICB2YXIgZXh0cmFCeXRlcyA9IGxlbiAlIDMgLy8gaWYgd2UgaGF2ZSAxIGJ5dGUgbGVmdCwgcGFkIDIgYnl0ZXNcbiAgdmFyIHBhcnRzID0gW11cbiAgdmFyIG1heENodW5rTGVuZ3RoID0gMTYzODMgLy8gbXVzdCBiZSBtdWx0aXBsZSBvZiAzXG5cbiAgLy8gZ28gdGhyb3VnaCB0aGUgYXJyYXkgZXZlcnkgdGhyZWUgYnl0ZXMsIHdlJ2xsIGRlYWwgd2l0aCB0cmFpbGluZyBzdHVmZiBsYXRlclxuICBmb3IgKHZhciBpID0gMCwgbGVuMiA9IGxlbiAtIGV4dHJhQnl0ZXM7IGkgPCBsZW4yOyBpICs9IG1heENodW5rTGVuZ3RoKSB7XG4gICAgcGFydHMucHVzaChlbmNvZGVDaHVuayh1aW50OCwgaSwgKGkgKyBtYXhDaHVua0xlbmd0aCkgPiBsZW4yID8gbGVuMiA6IChpICsgbWF4Q2h1bmtMZW5ndGgpKSlcbiAgfVxuXG4gIC8vIHBhZCB0aGUgZW5kIHdpdGggemVyb3MsIGJ1dCBtYWtlIHN1cmUgdG8gbm90IGZvcmdldCB0aGUgZXh0cmEgYnl0ZXNcbiAgaWYgKGV4dHJhQnl0ZXMgPT09IDEpIHtcbiAgICB0bXAgPSB1aW50OFtsZW4gLSAxXVxuICAgIHBhcnRzLnB1c2goXG4gICAgICBsb29rdXBbdG1wID4+IDJdICtcbiAgICAgIGxvb2t1cFsodG1wIDw8IDQpICYgMHgzRl0gK1xuICAgICAgJz09J1xuICAgIClcbiAgfSBlbHNlIGlmIChleHRyYUJ5dGVzID09PSAyKSB7XG4gICAgdG1wID0gKHVpbnQ4W2xlbiAtIDJdIDw8IDgpICsgdWludDhbbGVuIC0gMV1cbiAgICBwYXJ0cy5wdXNoKFxuICAgICAgbG9va3VwW3RtcCA+PiAxMF0gK1xuICAgICAgbG9va3VwWyh0bXAgPj4gNCkgJiAweDNGXSArXG4gICAgICBsb29rdXBbKHRtcCA8PCAyKSAmIDB4M0ZdICtcbiAgICAgICc9J1xuICAgIClcbiAgfVxuXG4gIHJldHVybiBwYXJ0cy5qb2luKCcnKVxufVxuIiwiLyohXG4gKiBUaGUgYnVmZmVyIG1vZHVsZSBmcm9tIG5vZGUuanMsIGZvciB0aGUgYnJvd3Nlci5cbiAqXG4gKiBAYXV0aG9yICAgRmVyb3NzIEFib3VraGFkaWplaCA8aHR0cHM6Ly9mZXJvc3Mub3JnPlxuICogQGxpY2Vuc2UgIE1JVFxuICovXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90byAqL1xuXG4ndXNlIHN0cmljdCdcblxuY29uc3QgYmFzZTY0ID0gcmVxdWlyZSgnYmFzZTY0LWpzJylcbmNvbnN0IGllZWU3NTQgPSByZXF1aXJlKCdpZWVlNzU0JylcbmNvbnN0IGN1c3RvbUluc3BlY3RTeW1ib2wgPVxuICAodHlwZW9mIFN5bWJvbCA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgU3ltYm9sWydmb3InXSA9PT0gJ2Z1bmN0aW9uJykgLy8gZXNsaW50LWRpc2FibGUtbGluZSBkb3Qtbm90YXRpb25cbiAgICA/IFN5bWJvbFsnZm9yJ10oJ25vZGVqcy51dGlsLmluc3BlY3QuY3VzdG9tJykgLy8gZXNsaW50LWRpc2FibGUtbGluZSBkb3Qtbm90YXRpb25cbiAgICA6IG51bGxcblxuZXhwb3J0cy5CdWZmZXIgPSBCdWZmZXJcbmV4cG9ydHMuU2xvd0J1ZmZlciA9IFNsb3dCdWZmZXJcbmV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVMgPSA1MFxuXG5jb25zdCBLX01BWF9MRU5HVEggPSAweDdmZmZmZmZmXG5leHBvcnRzLmtNYXhMZW5ndGggPSBLX01BWF9MRU5HVEhcblxuLyoqXG4gKiBJZiBgQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRgOlxuICogICA9PT0gdHJ1ZSAgICBVc2UgVWludDhBcnJheSBpbXBsZW1lbnRhdGlvbiAoZmFzdGVzdClcbiAqICAgPT09IGZhbHNlICAgUHJpbnQgd2FybmluZyBhbmQgcmVjb21tZW5kIHVzaW5nIGBidWZmZXJgIHY0Lnggd2hpY2ggaGFzIGFuIE9iamVjdFxuICogICAgICAgICAgICAgICBpbXBsZW1lbnRhdGlvbiAobW9zdCBjb21wYXRpYmxlLCBldmVuIElFNilcbiAqXG4gKiBCcm93c2VycyB0aGF0IHN1cHBvcnQgdHlwZWQgYXJyYXlzIGFyZSBJRSAxMCssIEZpcmVmb3ggNCssIENocm9tZSA3KywgU2FmYXJpIDUuMSssXG4gKiBPcGVyYSAxMS42KywgaU9TIDQuMisuXG4gKlxuICogV2UgcmVwb3J0IHRoYXQgdGhlIGJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCB0eXBlZCBhcnJheXMgaWYgdGhlIGFyZSBub3Qgc3ViY2xhc3NhYmxlXG4gKiB1c2luZyBfX3Byb3RvX18uIEZpcmVmb3ggNC0yOSBsYWNrcyBzdXBwb3J0IGZvciBhZGRpbmcgbmV3IHByb3BlcnRpZXMgdG8gYFVpbnQ4QXJyYXlgXG4gKiAoU2VlOiBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD02OTU0MzgpLiBJRSAxMCBsYWNrcyBzdXBwb3J0XG4gKiBmb3IgX19wcm90b19fIGFuZCBoYXMgYSBidWdneSB0eXBlZCBhcnJheSBpbXBsZW1lbnRhdGlvbi5cbiAqL1xuQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgPSB0eXBlZEFycmF5U3VwcG9ydCgpXG5cbmlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgJiYgdHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnICYmXG4gICAgdHlwZW9mIGNvbnNvbGUuZXJyb3IgPT09ICdmdW5jdGlvbicpIHtcbiAgY29uc29sZS5lcnJvcihcbiAgICAnVGhpcyBicm93c2VyIGxhY2tzIHR5cGVkIGFycmF5IChVaW50OEFycmF5KSBzdXBwb3J0IHdoaWNoIGlzIHJlcXVpcmVkIGJ5ICcgK1xuICAgICdgYnVmZmVyYCB2NS54LiBVc2UgYGJ1ZmZlcmAgdjQueCBpZiB5b3UgcmVxdWlyZSBvbGQgYnJvd3NlciBzdXBwb3J0LidcbiAgKVxufVxuXG5mdW5jdGlvbiB0eXBlZEFycmF5U3VwcG9ydCAoKSB7XG4gIC8vIENhbiB0eXBlZCBhcnJheSBpbnN0YW5jZXMgY2FuIGJlIGF1Z21lbnRlZD9cbiAgdHJ5IHtcbiAgICBjb25zdCBhcnIgPSBuZXcgVWludDhBcnJheSgxKVxuICAgIGNvbnN0IHByb3RvID0geyBmb286IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDQyIH0gfVxuICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZihwcm90bywgVWludDhBcnJheS5wcm90b3R5cGUpXG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKGFyciwgcHJvdG8pXG4gICAgcmV0dXJuIGFyci5mb28oKSA9PT0gNDJcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShCdWZmZXIucHJvdG90eXBlLCAncGFyZW50Jywge1xuICBlbnVtZXJhYmxlOiB0cnVlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcih0aGlzKSkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIHJldHVybiB0aGlzLmJ1ZmZlclxuICB9XG59KVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQnVmZmVyLnByb3RvdHlwZSwgJ29mZnNldCcsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIodGhpcykpIHJldHVybiB1bmRlZmluZWRcbiAgICByZXR1cm4gdGhpcy5ieXRlT2Zmc2V0XG4gIH1cbn0pXG5cbmZ1bmN0aW9uIGNyZWF0ZUJ1ZmZlciAobGVuZ3RoKSB7XG4gIGlmIChsZW5ndGggPiBLX01BWF9MRU5HVEgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVGhlIHZhbHVlIFwiJyArIGxlbmd0aCArICdcIiBpcyBpbnZhbGlkIGZvciBvcHRpb24gXCJzaXplXCInKVxuICB9XG4gIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlXG4gIGNvbnN0IGJ1ZiA9IG5ldyBVaW50OEFycmF5KGxlbmd0aClcbiAgT2JqZWN0LnNldFByb3RvdHlwZU9mKGJ1ZiwgQnVmZmVyLnByb3RvdHlwZSlcbiAgcmV0dXJuIGJ1ZlxufVxuXG4vKipcbiAqIFRoZSBCdWZmZXIgY29uc3RydWN0b3IgcmV0dXJucyBpbnN0YW5jZXMgb2YgYFVpbnQ4QXJyYXlgIHRoYXQgaGF2ZSB0aGVpclxuICogcHJvdG90eXBlIGNoYW5nZWQgdG8gYEJ1ZmZlci5wcm90b3R5cGVgLiBGdXJ0aGVybW9yZSwgYEJ1ZmZlcmAgaXMgYSBzdWJjbGFzcyBvZlxuICogYFVpbnQ4QXJyYXlgLCBzbyB0aGUgcmV0dXJuZWQgaW5zdGFuY2VzIHdpbGwgaGF2ZSBhbGwgdGhlIG5vZGUgYEJ1ZmZlcmAgbWV0aG9kc1xuICogYW5kIHRoZSBgVWludDhBcnJheWAgbWV0aG9kcy4gU3F1YXJlIGJyYWNrZXQgbm90YXRpb24gd29ya3MgYXMgZXhwZWN0ZWQgLS0gaXRcbiAqIHJldHVybnMgYSBzaW5nbGUgb2N0ZXQuXG4gKlxuICogVGhlIGBVaW50OEFycmF5YCBwcm90b3R5cGUgcmVtYWlucyB1bm1vZGlmaWVkLlxuICovXG5cbmZ1bmN0aW9uIEJ1ZmZlciAoYXJnLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgLy8gQ29tbW9uIGNhc2UuXG4gIGlmICh0eXBlb2YgYXJnID09PSAnbnVtYmVyJykge1xuICAgIGlmICh0eXBlb2YgZW5jb2RpbmdPck9mZnNldCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICdUaGUgXCJzdHJpbmdcIiBhcmd1bWVudCBtdXN0IGJlIG9mIHR5cGUgc3RyaW5nLiBSZWNlaXZlZCB0eXBlIG51bWJlcidcbiAgICAgIClcbiAgICB9XG4gICAgcmV0dXJuIGFsbG9jVW5zYWZlKGFyZylcbiAgfVxuICByZXR1cm4gZnJvbShhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbn1cblxuQnVmZmVyLnBvb2xTaXplID0gODE5MiAvLyBub3QgdXNlZCBieSB0aGlzIGltcGxlbWVudGF0aW9uXG5cbmZ1bmN0aW9uIGZyb20gKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZnJvbVN0cmluZyh2YWx1ZSwgZW5jb2RpbmdPck9mZnNldClcbiAgfVxuXG4gIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcodmFsdWUpKSB7XG4gICAgcmV0dXJuIGZyb21BcnJheVZpZXcodmFsdWUpXG4gIH1cblxuICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnVGhlIGZpcnN0IGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgc3RyaW5nLCBCdWZmZXIsIEFycmF5QnVmZmVyLCBBcnJheSwgJyArXG4gICAgICAnb3IgQXJyYXktbGlrZSBPYmplY3QuIFJlY2VpdmVkIHR5cGUgJyArICh0eXBlb2YgdmFsdWUpXG4gICAgKVxuICB9XG5cbiAgaWYgKGlzSW5zdGFuY2UodmFsdWUsIEFycmF5QnVmZmVyKSB8fFxuICAgICAgKHZhbHVlICYmIGlzSW5zdGFuY2UodmFsdWUuYnVmZmVyLCBBcnJheUJ1ZmZlcikpKSB7XG4gICAgcmV0dXJuIGZyb21BcnJheUJ1ZmZlcih2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxuICB9XG5cbiAgaWYgKHR5cGVvZiBTaGFyZWRBcnJheUJ1ZmZlciAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIChpc0luc3RhbmNlKHZhbHVlLCBTaGFyZWRBcnJheUJ1ZmZlcikgfHxcbiAgICAgICh2YWx1ZSAmJiBpc0luc3RhbmNlKHZhbHVlLmJ1ZmZlciwgU2hhcmVkQXJyYXlCdWZmZXIpKSkpIHtcbiAgICByZXR1cm4gZnJvbUFycmF5QnVmZmVyKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAnVGhlIFwidmFsdWVcIiBhcmd1bWVudCBtdXN0IG5vdCBiZSBvZiB0eXBlIG51bWJlci4gUmVjZWl2ZWQgdHlwZSBudW1iZXInXG4gICAgKVxuICB9XG5cbiAgY29uc3QgdmFsdWVPZiA9IHZhbHVlLnZhbHVlT2YgJiYgdmFsdWUudmFsdWVPZigpXG4gIGlmICh2YWx1ZU9mICE9IG51bGwgJiYgdmFsdWVPZiAhPT0gdmFsdWUpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20odmFsdWVPZiwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxuICB9XG5cbiAgY29uc3QgYiA9IGZyb21PYmplY3QodmFsdWUpXG4gIGlmIChiKSByZXR1cm4gYlxuXG4gIGlmICh0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9QcmltaXRpdmUgIT0gbnVsbCAmJlxuICAgICAgdHlwZW9mIHZhbHVlW1N5bWJvbC50b1ByaW1pdGl2ZV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20odmFsdWVbU3ltYm9sLnRvUHJpbWl0aXZlXSgnc3RyaW5nJyksIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgJ1RoZSBmaXJzdCBhcmd1bWVudCBtdXN0IGJlIG9uZSBvZiB0eXBlIHN0cmluZywgQnVmZmVyLCBBcnJheUJ1ZmZlciwgQXJyYXksICcgK1xuICAgICdvciBBcnJheS1saWtlIE9iamVjdC4gUmVjZWl2ZWQgdHlwZSAnICsgKHR5cGVvZiB2YWx1ZSlcbiAgKVxufVxuXG4vKipcbiAqIEZ1bmN0aW9uYWxseSBlcXVpdmFsZW50IHRvIEJ1ZmZlcihhcmcsIGVuY29kaW5nKSBidXQgdGhyb3dzIGEgVHlwZUVycm9yXG4gKiBpZiB2YWx1ZSBpcyBhIG51bWJlci5cbiAqIEJ1ZmZlci5mcm9tKHN0clssIGVuY29kaW5nXSlcbiAqIEJ1ZmZlci5mcm9tKGFycmF5KVxuICogQnVmZmVyLmZyb20oYnVmZmVyKVxuICogQnVmZmVyLmZyb20oYXJyYXlCdWZmZXJbLCBieXRlT2Zmc2V0WywgbGVuZ3RoXV0pXG4gKiovXG5CdWZmZXIuZnJvbSA9IGZ1bmN0aW9uICh2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBmcm9tKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG59XG5cbi8vIE5vdGU6IENoYW5nZSBwcm90b3R5cGUgKmFmdGVyKiBCdWZmZXIuZnJvbSBpcyBkZWZpbmVkIHRvIHdvcmthcm91bmQgQ2hyb21lIGJ1Zzpcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL3B1bGwvMTQ4XG5PYmplY3Quc2V0UHJvdG90eXBlT2YoQnVmZmVyLnByb3RvdHlwZSwgVWludDhBcnJheS5wcm90b3R5cGUpXG5PYmplY3Quc2V0UHJvdG90eXBlT2YoQnVmZmVyLCBVaW50OEFycmF5KVxuXG5mdW5jdGlvbiBhc3NlcnRTaXplIChzaXplKSB7XG4gIGlmICh0eXBlb2Ygc2l6ZSAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcInNpemVcIiBhcmd1bWVudCBtdXN0IGJlIG9mIHR5cGUgbnVtYmVyJylcbiAgfSBlbHNlIGlmIChzaXplIDwgMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdUaGUgdmFsdWUgXCInICsgc2l6ZSArICdcIiBpcyBpbnZhbGlkIGZvciBvcHRpb24gXCJzaXplXCInKVxuICB9XG59XG5cbmZ1bmN0aW9uIGFsbG9jIChzaXplLCBmaWxsLCBlbmNvZGluZykge1xuICBhc3NlcnRTaXplKHNpemUpXG4gIGlmIChzaXplIDw9IDApIHtcbiAgICByZXR1cm4gY3JlYXRlQnVmZmVyKHNpemUpXG4gIH1cbiAgaWYgKGZpbGwgIT09IHVuZGVmaW5lZCkge1xuICAgIC8vIE9ubHkgcGF5IGF0dGVudGlvbiB0byBlbmNvZGluZyBpZiBpdCdzIGEgc3RyaW5nLiBUaGlzXG4gICAgLy8gcHJldmVudHMgYWNjaWRlbnRhbGx5IHNlbmRpbmcgaW4gYSBudW1iZXIgdGhhdCB3b3VsZFxuICAgIC8vIGJlIGludGVycHJldGVkIGFzIGEgc3RhcnQgb2Zmc2V0LlxuICAgIHJldHVybiB0eXBlb2YgZW5jb2RpbmcgPT09ICdzdHJpbmcnXG4gICAgICA/IGNyZWF0ZUJ1ZmZlcihzaXplKS5maWxsKGZpbGwsIGVuY29kaW5nKVxuICAgICAgOiBjcmVhdGVCdWZmZXIoc2l6ZSkuZmlsbChmaWxsKVxuICB9XG4gIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSlcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGZpbGxlZCBCdWZmZXIgaW5zdGFuY2UuXG4gKiBhbGxvYyhzaXplWywgZmlsbFssIGVuY29kaW5nXV0pXG4gKiovXG5CdWZmZXIuYWxsb2MgPSBmdW5jdGlvbiAoc2l6ZSwgZmlsbCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIGFsbG9jKHNpemUsIGZpbGwsIGVuY29kaW5nKVxufVxuXG5mdW5jdGlvbiBhbGxvY1Vuc2FmZSAoc2l6ZSkge1xuICBhc3NlcnRTaXplKHNpemUpXG4gIHJldHVybiBjcmVhdGVCdWZmZXIoc2l6ZSA8IDAgPyAwIDogY2hlY2tlZChzaXplKSB8IDApXG59XG5cbi8qKlxuICogRXF1aXZhbGVudCB0byBCdWZmZXIobnVtKSwgYnkgZGVmYXVsdCBjcmVhdGVzIGEgbm9uLXplcm8tZmlsbGVkIEJ1ZmZlciBpbnN0YW5jZS5cbiAqICovXG5CdWZmZXIuYWxsb2NVbnNhZmUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICByZXR1cm4gYWxsb2NVbnNhZmUoc2l6ZSlcbn1cbi8qKlxuICogRXF1aXZhbGVudCB0byBTbG93QnVmZmVyKG51bSksIGJ5IGRlZmF1bHQgY3JlYXRlcyBhIG5vbi16ZXJvLWZpbGxlZCBCdWZmZXIgaW5zdGFuY2UuXG4gKi9cbkJ1ZmZlci5hbGxvY1Vuc2FmZVNsb3cgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICByZXR1cm4gYWxsb2NVbnNhZmUoc2l6ZSlcbn1cblxuZnVuY3Rpb24gZnJvbVN0cmluZyAoc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAodHlwZW9mIGVuY29kaW5nICE9PSAnc3RyaW5nJyB8fCBlbmNvZGluZyA9PT0gJycpIHtcbiAgICBlbmNvZGluZyA9ICd1dGY4J1xuICB9XG5cbiAgaWYgKCFCdWZmZXIuaXNFbmNvZGluZyhlbmNvZGluZykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gIH1cblxuICBjb25zdCBsZW5ndGggPSBieXRlTGVuZ3RoKHN0cmluZywgZW5jb2RpbmcpIHwgMFxuICBsZXQgYnVmID0gY3JlYXRlQnVmZmVyKGxlbmd0aClcblxuICBjb25zdCBhY3R1YWwgPSBidWYud3JpdGUoc3RyaW5nLCBlbmNvZGluZylcblxuICBpZiAoYWN0dWFsICE9PSBsZW5ndGgpIHtcbiAgICAvLyBXcml0aW5nIGEgaGV4IHN0cmluZywgZm9yIGV4YW1wbGUsIHRoYXQgY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzIHdpbGxcbiAgICAvLyBjYXVzZSBldmVyeXRoaW5nIGFmdGVyIHRoZSBmaXJzdCBpbnZhbGlkIGNoYXJhY3RlciB0byBiZSBpZ25vcmVkLiAoZS5nLlxuICAgIC8vICdhYnh4Y2QnIHdpbGwgYmUgdHJlYXRlZCBhcyAnYWInKVxuICAgIGJ1ZiA9IGJ1Zi5zbGljZSgwLCBhY3R1YWwpXG4gIH1cblxuICByZXR1cm4gYnVmXG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUxpa2UgKGFycmF5KSB7XG4gIGNvbnN0IGxlbmd0aCA9IGFycmF5Lmxlbmd0aCA8IDAgPyAwIDogY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICBjb25zdCBidWYgPSBjcmVhdGVCdWZmZXIobGVuZ3RoKVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgYnVmW2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gYnVmXG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheVZpZXcgKGFycmF5Vmlldykge1xuICBpZiAoaXNJbnN0YW5jZShhcnJheVZpZXcsIFVpbnQ4QXJyYXkpKSB7XG4gICAgY29uc3QgY29weSA9IG5ldyBVaW50OEFycmF5KGFycmF5VmlldylcbiAgICByZXR1cm4gZnJvbUFycmF5QnVmZmVyKGNvcHkuYnVmZmVyLCBjb3B5LmJ5dGVPZmZzZXQsIGNvcHkuYnl0ZUxlbmd0aClcbiAgfVxuICByZXR1cm4gZnJvbUFycmF5TGlrZShhcnJheVZpZXcpXG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUJ1ZmZlciAoYXJyYXksIGJ5dGVPZmZzZXQsIGxlbmd0aCkge1xuICBpZiAoYnl0ZU9mZnNldCA8IDAgfHwgYXJyYXkuYnl0ZUxlbmd0aCA8IGJ5dGVPZmZzZXQpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJvZmZzZXRcIiBpcyBvdXRzaWRlIG9mIGJ1ZmZlciBib3VuZHMnKVxuICB9XG5cbiAgaWYgKGFycmF5LmJ5dGVMZW5ndGggPCBieXRlT2Zmc2V0ICsgKGxlbmd0aCB8fCAwKSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdcImxlbmd0aFwiIGlzIG91dHNpZGUgb2YgYnVmZmVyIGJvdW5kcycpXG4gIH1cblxuICBsZXQgYnVmXG4gIGlmIChieXRlT2Zmc2V0ID09PSB1bmRlZmluZWQgJiYgbGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBidWYgPSBuZXcgVWludDhBcnJheShhcnJheSlcbiAgfSBlbHNlIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGFycmF5LCBieXRlT2Zmc2V0KVxuICB9IGVsc2Uge1xuICAgIGJ1ZiA9IG5ldyBVaW50OEFycmF5KGFycmF5LCBieXRlT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICAvLyBSZXR1cm4gYW4gYXVnbWVudGVkIGBVaW50OEFycmF5YCBpbnN0YW5jZVxuICBPYmplY3Quc2V0UHJvdG90eXBlT2YoYnVmLCBCdWZmZXIucHJvdG90eXBlKVxuXG4gIHJldHVybiBidWZcbn1cblxuZnVuY3Rpb24gZnJvbU9iamVjdCAob2JqKSB7XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIob2JqKSkge1xuICAgIGNvbnN0IGxlbiA9IGNoZWNrZWQob2JqLmxlbmd0aCkgfCAwXG4gICAgY29uc3QgYnVmID0gY3JlYXRlQnVmZmVyKGxlbilcblxuICAgIGlmIChidWYubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gYnVmXG4gICAgfVxuXG4gICAgb2JqLmNvcHkoYnVmLCAwLCAwLCBsZW4pXG4gICAgcmV0dXJuIGJ1ZlxuICB9XG5cbiAgaWYgKG9iai5sZW5ndGggIT09IHVuZGVmaW5lZCkge1xuICAgIGlmICh0eXBlb2Ygb2JqLmxlbmd0aCAhPT0gJ251bWJlcicgfHwgbnVtYmVySXNOYU4ob2JqLmxlbmd0aCkpIHtcbiAgICAgIHJldHVybiBjcmVhdGVCdWZmZXIoMClcbiAgICB9XG4gICAgcmV0dXJuIGZyb21BcnJheUxpa2Uob2JqKVxuICB9XG5cbiAgaWYgKG9iai50eXBlID09PSAnQnVmZmVyJyAmJiBBcnJheS5pc0FycmF5KG9iai5kYXRhKSkge1xuICAgIHJldHVybiBmcm9tQXJyYXlMaWtlKG9iai5kYXRhKVxuICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrZWQgKGxlbmd0aCkge1xuICAvLyBOb3RlOiBjYW5ub3QgdXNlIGBsZW5ndGggPCBLX01BWF9MRU5HVEhgIGhlcmUgYmVjYXVzZSB0aGF0IGZhaWxzIHdoZW5cbiAgLy8gbGVuZ3RoIGlzIE5hTiAod2hpY2ggaXMgb3RoZXJ3aXNlIGNvZXJjZWQgdG8gemVyby4pXG4gIGlmIChsZW5ndGggPj0gS19NQVhfTEVOR1RIKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0F0dGVtcHQgdG8gYWxsb2NhdGUgQnVmZmVyIGxhcmdlciB0aGFuIG1heGltdW0gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgJ3NpemU6IDB4JyArIEtfTUFYX0xFTkdUSC50b1N0cmluZygxNikgKyAnIGJ5dGVzJylcbiAgfVxuICByZXR1cm4gbGVuZ3RoIHwgMFxufVxuXG5mdW5jdGlvbiBTbG93QnVmZmVyIChsZW5ndGgpIHtcbiAgaWYgKCtsZW5ndGggIT0gbGVuZ3RoKSB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgZXFlcWVxXG4gICAgbGVuZ3RoID0gMFxuICB9XG4gIHJldHVybiBCdWZmZXIuYWxsb2MoK2xlbmd0aClcbn1cblxuQnVmZmVyLmlzQnVmZmVyID0gZnVuY3Rpb24gaXNCdWZmZXIgKGIpIHtcbiAgcmV0dXJuIGIgIT0gbnVsbCAmJiBiLl9pc0J1ZmZlciA9PT0gdHJ1ZSAmJlxuICAgIGIgIT09IEJ1ZmZlci5wcm90b3R5cGUgLy8gc28gQnVmZmVyLmlzQnVmZmVyKEJ1ZmZlci5wcm90b3R5cGUpIHdpbGwgYmUgZmFsc2Vcbn1cblxuQnVmZmVyLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlIChhLCBiKSB7XG4gIGlmIChpc0luc3RhbmNlKGEsIFVpbnQ4QXJyYXkpKSBhID0gQnVmZmVyLmZyb20oYSwgYS5vZmZzZXQsIGEuYnl0ZUxlbmd0aClcbiAgaWYgKGlzSW5zdGFuY2UoYiwgVWludDhBcnJheSkpIGIgPSBCdWZmZXIuZnJvbShiLCBiLm9mZnNldCwgYi5ieXRlTGVuZ3RoKVxuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihhKSB8fCAhQnVmZmVyLmlzQnVmZmVyKGIpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdUaGUgXCJidWYxXCIsIFwiYnVmMlwiIGFyZ3VtZW50cyBtdXN0IGJlIG9uZSBvZiB0eXBlIEJ1ZmZlciBvciBVaW50OEFycmF5J1xuICAgIClcbiAgfVxuXG4gIGlmIChhID09PSBiKSByZXR1cm4gMFxuXG4gIGxldCB4ID0gYS5sZW5ndGhcbiAgbGV0IHkgPSBiLmxlbmd0aFxuXG4gIGZvciAobGV0IGkgPSAwLCBsZW4gPSBNYXRoLm1pbih4LCB5KTsgaSA8IGxlbjsgKytpKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIHtcbiAgICAgIHggPSBhW2ldXG4gICAgICB5ID0gYltpXVxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICBpZiAoeCA8IHkpIHJldHVybiAtMVxuICBpZiAoeSA8IHgpIHJldHVybiAxXG4gIHJldHVybiAwXG59XG5cbkJ1ZmZlci5pc0VuY29kaW5nID0gZnVuY3Rpb24gaXNFbmNvZGluZyAoZW5jb2RpbmcpIHtcbiAgc3dpdGNoIChTdHJpbmcoZW5jb2RpbmcpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnbGF0aW4xJzpcbiAgICBjYXNlICdiaW5hcnknOlxuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldHVybiB0cnVlXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbkJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiBjb25jYXQgKGxpc3QsIGxlbmd0aCkge1xuICBpZiAoIUFycmF5LmlzQXJyYXkobGlzdCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RcIiBhcmd1bWVudCBtdXN0IGJlIGFuIEFycmF5IG9mIEJ1ZmZlcnMnKVxuICB9XG5cbiAgaWYgKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIEJ1ZmZlci5hbGxvYygwKVxuICB9XG5cbiAgbGV0IGlcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbGVuZ3RoID0gMFxuICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgICBsZW5ndGggKz0gbGlzdFtpXS5sZW5ndGhcbiAgICB9XG4gIH1cblxuICBjb25zdCBidWZmZXIgPSBCdWZmZXIuYWxsb2NVbnNhZmUobGVuZ3RoKVxuICBsZXQgcG9zID0gMFxuICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7ICsraSkge1xuICAgIGxldCBidWYgPSBsaXN0W2ldXG4gICAgaWYgKGlzSW5zdGFuY2UoYnVmLCBVaW50OEFycmF5KSkge1xuICAgICAgaWYgKHBvcyArIGJ1Zi5sZW5ndGggPiBidWZmZXIubGVuZ3RoKSB7XG4gICAgICAgIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIGJ1ZiA9IEJ1ZmZlci5mcm9tKGJ1ZilcbiAgICAgICAgYnVmLmNvcHkoYnVmZmVyLCBwb3MpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBVaW50OEFycmF5LnByb3RvdHlwZS5zZXQuY2FsbChcbiAgICAgICAgICBidWZmZXIsXG4gICAgICAgICAgYnVmLFxuICAgICAgICAgIHBvc1xuICAgICAgICApXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdFwiIGFyZ3VtZW50IG11c3QgYmUgYW4gQXJyYXkgb2YgQnVmZmVycycpXG4gICAgfSBlbHNlIHtcbiAgICAgIGJ1Zi5jb3B5KGJ1ZmZlciwgcG9zKVxuICAgIH1cbiAgICBwb3MgKz0gYnVmLmxlbmd0aFxuICB9XG4gIHJldHVybiBidWZmZXJcbn1cblxuZnVuY3Rpb24gYnl0ZUxlbmd0aCAoc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAoQnVmZmVyLmlzQnVmZmVyKHN0cmluZykpIHtcbiAgICByZXR1cm4gc3RyaW5nLmxlbmd0aFxuICB9XG4gIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcoc3RyaW5nKSB8fCBpc0luc3RhbmNlKHN0cmluZywgQXJyYXlCdWZmZXIpKSB7XG4gICAgcmV0dXJuIHN0cmluZy5ieXRlTGVuZ3RoXG4gIH1cbiAgaWYgKHR5cGVvZiBzdHJpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICdUaGUgXCJzdHJpbmdcIiBhcmd1bWVudCBtdXN0IGJlIG9uZSBvZiB0eXBlIHN0cmluZywgQnVmZmVyLCBvciBBcnJheUJ1ZmZlci4gJyArXG4gICAgICAnUmVjZWl2ZWQgdHlwZSAnICsgdHlwZW9mIHN0cmluZ1xuICAgIClcbiAgfVxuXG4gIGNvbnN0IGxlbiA9IHN0cmluZy5sZW5ndGhcbiAgY29uc3QgbXVzdE1hdGNoID0gKGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSA9PT0gdHJ1ZSlcbiAgaWYgKCFtdXN0TWF0Y2ggJiYgbGVuID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIFVzZSBhIGZvciBsb29wIHRvIGF2b2lkIHJlY3Vyc2lvblxuICBsZXQgbG93ZXJlZENhc2UgPSBmYWxzZVxuICBmb3IgKDs7KSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgY2FzZSAnbGF0aW4xJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBsZW5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiBsZW4gKiAyXG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gbGVuID4+PiAxXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0VG9CeXRlcyhzdHJpbmcpLmxlbmd0aFxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB7XG4gICAgICAgICAgcmV0dXJuIG11c3RNYXRjaCA/IC0xIDogdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGggLy8gYXNzdW1lIHV0ZjhcbiAgICAgICAgfVxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuQnVmZmVyLmJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoXG5cbmZ1bmN0aW9uIHNsb3dUb1N0cmluZyAoZW5jb2RpbmcsIHN0YXJ0LCBlbmQpIHtcbiAgbGV0IGxvd2VyZWRDYXNlID0gZmFsc2VcblxuICAvLyBObyBuZWVkIHRvIHZlcmlmeSB0aGF0IFwidGhpcy5sZW5ndGggPD0gTUFYX1VJTlQzMlwiIHNpbmNlIGl0J3MgYSByZWFkLW9ubHlcbiAgLy8gcHJvcGVydHkgb2YgYSB0eXBlZCBhcnJheS5cblxuICAvLyBUaGlzIGJlaGF2ZXMgbmVpdGhlciBsaWtlIFN0cmluZyBub3IgVWludDhBcnJheSBpbiB0aGF0IHdlIHNldCBzdGFydC9lbmRcbiAgLy8gdG8gdGhlaXIgdXBwZXIvbG93ZXIgYm91bmRzIGlmIHRoZSB2YWx1ZSBwYXNzZWQgaXMgb3V0IG9mIHJhbmdlLlxuICAvLyB1bmRlZmluZWQgaXMgaGFuZGxlZCBzcGVjaWFsbHkgYXMgcGVyIEVDTUEtMjYyIDZ0aCBFZGl0aW9uLFxuICAvLyBTZWN0aW9uIDEzLjMuMy43IFJ1bnRpbWUgU2VtYW50aWNzOiBLZXllZEJpbmRpbmdJbml0aWFsaXphdGlvbi5cbiAgaWYgKHN0YXJ0ID09PSB1bmRlZmluZWQgfHwgc3RhcnQgPCAwKSB7XG4gICAgc3RhcnQgPSAwXG4gIH1cbiAgLy8gUmV0dXJuIGVhcmx5IGlmIHN0YXJ0ID4gdGhpcy5sZW5ndGguIERvbmUgaGVyZSB0byBwcmV2ZW50IHBvdGVudGlhbCB1aW50MzJcbiAgLy8gY29lcmNpb24gZmFpbCBiZWxvdy5cbiAgaWYgKHN0YXJ0ID4gdGhpcy5sZW5ndGgpIHtcbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIGlmIChlbmQgPT09IHVuZGVmaW5lZCB8fCBlbmQgPiB0aGlzLmxlbmd0aCkge1xuICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gIH1cblxuICBpZiAoZW5kIDw9IDApIHtcbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIC8vIEZvcmNlIGNvZXJjaW9uIHRvIHVpbnQzMi4gVGhpcyB3aWxsIGFsc28gY29lcmNlIGZhbHNleS9OYU4gdmFsdWVzIHRvIDAuXG4gIGVuZCA+Pj49IDBcbiAgc3RhcnQgPj4+PSAwXG5cbiAgaWYgKGVuZCA8PSBzdGFydCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcblxuICB3aGlsZSAodHJ1ZSkge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBoZXhTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICAgIHJldHVybiBhc2NpaVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2xhdGluMSc6XG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gbGF0aW4xU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1dGYxNmxlU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKGVuY29kaW5nICsgJycpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbi8vIFRoaXMgcHJvcGVydHkgaXMgdXNlZCBieSBgQnVmZmVyLmlzQnVmZmVyYCAoYW5kIHRoZSBgaXMtYnVmZmVyYCBucG0gcGFja2FnZSlcbi8vIHRvIGRldGVjdCBhIEJ1ZmZlciBpbnN0YW5jZS4gSXQncyBub3QgcG9zc2libGUgdG8gdXNlIGBpbnN0YW5jZW9mIEJ1ZmZlcmBcbi8vIHJlbGlhYmx5IGluIGEgYnJvd3NlcmlmeSBjb250ZXh0IGJlY2F1c2UgdGhlcmUgY291bGQgYmUgbXVsdGlwbGUgZGlmZmVyZW50XG4vLyBjb3BpZXMgb2YgdGhlICdidWZmZXInIHBhY2thZ2UgaW4gdXNlLiBUaGlzIG1ldGhvZCB3b3JrcyBldmVuIGZvciBCdWZmZXJcbi8vIGluc3RhbmNlcyB0aGF0IHdlcmUgY3JlYXRlZCBmcm9tIGFub3RoZXIgY29weSBvZiB0aGUgYGJ1ZmZlcmAgcGFja2FnZS5cbi8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXIvaXNzdWVzLzE1NFxuQnVmZmVyLnByb3RvdHlwZS5faXNCdWZmZXIgPSB0cnVlXG5cbmZ1bmN0aW9uIHN3YXAgKGIsIG4sIG0pIHtcbiAgY29uc3QgaSA9IGJbbl1cbiAgYltuXSA9IGJbbV1cbiAgYlttXSA9IGlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwMTYgPSBmdW5jdGlvbiBzd2FwMTYgKCkge1xuICBjb25zdCBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgMiAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMTYtYml0cycpXG4gIH1cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkgKz0gMikge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDEpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwMzIgPSBmdW5jdGlvbiBzd2FwMzIgKCkge1xuICBjb25zdCBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgNCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMzItYml0cycpXG4gIH1cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkgKz0gNCkge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDMpXG4gICAgc3dhcCh0aGlzLCBpICsgMSwgaSArIDIpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwNjQgPSBmdW5jdGlvbiBzd2FwNjQgKCkge1xuICBjb25zdCBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgOCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNjQtYml0cycpXG4gIH1cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkgKz0gOCkge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDcpXG4gICAgc3dhcCh0aGlzLCBpICsgMSwgaSArIDYpXG4gICAgc3dhcCh0aGlzLCBpICsgMiwgaSArIDUpXG4gICAgc3dhcCh0aGlzLCBpICsgMywgaSArIDQpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nICgpIHtcbiAgY29uc3QgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgaWYgKGxlbmd0aCA9PT0gMCkgcmV0dXJuICcnXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIDAsIGxlbmd0aClcbiAgcmV0dXJuIHNsb3dUb1N0cmluZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9Mb2NhbGVTdHJpbmcgPSBCdWZmZXIucHJvdG90eXBlLnRvU3RyaW5nXG5cbkJ1ZmZlci5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24gZXF1YWxzIChiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyJylcbiAgaWYgKHRoaXMgPT09IGIpIHJldHVybiB0cnVlXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKSA9PT0gMFxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbiBpbnNwZWN0ICgpIHtcbiAgbGV0IHN0ciA9ICcnXG4gIGNvbnN0IG1heCA9IGV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVNcbiAgc3RyID0gdGhpcy50b1N0cmluZygnaGV4JywgMCwgbWF4KS5yZXBsYWNlKC8oLnsyfSkvZywgJyQxICcpLnRyaW0oKVxuICBpZiAodGhpcy5sZW5ndGggPiBtYXgpIHN0ciArPSAnIC4uLiAnXG4gIHJldHVybiAnPEJ1ZmZlciAnICsgc3RyICsgJz4nXG59XG5pZiAoY3VzdG9tSW5zcGVjdFN5bWJvbCkge1xuICBCdWZmZXIucHJvdG90eXBlW2N1c3RvbUluc3BlY3RTeW1ib2xdID0gQnVmZmVyLnByb3RvdHlwZS5pbnNwZWN0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuY29tcGFyZSA9IGZ1bmN0aW9uIGNvbXBhcmUgKHRhcmdldCwgc3RhcnQsIGVuZCwgdGhpc1N0YXJ0LCB0aGlzRW5kKSB7XG4gIGlmIChpc0luc3RhbmNlKHRhcmdldCwgVWludDhBcnJheSkpIHtcbiAgICB0YXJnZXQgPSBCdWZmZXIuZnJvbSh0YXJnZXQsIHRhcmdldC5vZmZzZXQsIHRhcmdldC5ieXRlTGVuZ3RoKVxuICB9XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKHRhcmdldCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgJ1RoZSBcInRhcmdldFwiIGFyZ3VtZW50IG11c3QgYmUgb25lIG9mIHR5cGUgQnVmZmVyIG9yIFVpbnQ4QXJyYXkuICcgK1xuICAgICAgJ1JlY2VpdmVkIHR5cGUgJyArICh0eXBlb2YgdGFyZ2V0KVxuICAgIClcbiAgfVxuXG4gIGlmIChzdGFydCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgc3RhcnQgPSAwXG4gIH1cbiAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgZW5kID0gdGFyZ2V0ID8gdGFyZ2V0Lmxlbmd0aCA6IDBcbiAgfVxuICBpZiAodGhpc1N0YXJ0ID09PSB1bmRlZmluZWQpIHtcbiAgICB0aGlzU3RhcnQgPSAwXG4gIH1cbiAgaWYgKHRoaXNFbmQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRoaXNFbmQgPSB0aGlzLmxlbmd0aFxuICB9XG5cbiAgaWYgKHN0YXJ0IDwgMCB8fCBlbmQgPiB0YXJnZXQubGVuZ3RoIHx8IHRoaXNTdGFydCA8IDAgfHwgdGhpc0VuZCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ291dCBvZiByYW5nZSBpbmRleCcpXG4gIH1cblxuICBpZiAodGhpc1N0YXJ0ID49IHRoaXNFbmQgJiYgc3RhcnQgPj0gZW5kKSB7XG4gICAgcmV0dXJuIDBcbiAgfVxuICBpZiAodGhpc1N0YXJ0ID49IHRoaXNFbmQpIHtcbiAgICByZXR1cm4gLTFcbiAgfVxuICBpZiAoc3RhcnQgPj0gZW5kKSB7XG4gICAgcmV0dXJuIDFcbiAgfVxuXG4gIHN0YXJ0ID4+Pj0gMFxuICBlbmQgPj4+PSAwXG4gIHRoaXNTdGFydCA+Pj49IDBcbiAgdGhpc0VuZCA+Pj49IDBcblxuICBpZiAodGhpcyA9PT0gdGFyZ2V0KSByZXR1cm4gMFxuXG4gIGxldCB4ID0gdGhpc0VuZCAtIHRoaXNTdGFydFxuICBsZXQgeSA9IGVuZCAtIHN0YXJ0XG4gIGNvbnN0IGxlbiA9IE1hdGgubWluKHgsIHkpXG5cbiAgY29uc3QgdGhpc0NvcHkgPSB0aGlzLnNsaWNlKHRoaXNTdGFydCwgdGhpc0VuZClcbiAgY29uc3QgdGFyZ2V0Q29weSA9IHRhcmdldC5zbGljZShzdGFydCwgZW5kKVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyArK2kpIHtcbiAgICBpZiAodGhpc0NvcHlbaV0gIT09IHRhcmdldENvcHlbaV0pIHtcbiAgICAgIHggPSB0aGlzQ29weVtpXVxuICAgICAgeSA9IHRhcmdldENvcHlbaV1cbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgaWYgKHggPCB5KSByZXR1cm4gLTFcbiAgaWYgKHkgPCB4KSByZXR1cm4gMVxuICByZXR1cm4gMFxufVxuXG4vLyBGaW5kcyBlaXRoZXIgdGhlIGZpcnN0IGluZGV4IG9mIGB2YWxgIGluIGBidWZmZXJgIGF0IG9mZnNldCA+PSBgYnl0ZU9mZnNldGAsXG4vLyBPUiB0aGUgbGFzdCBpbmRleCBvZiBgdmFsYCBpbiBgYnVmZmVyYCBhdCBvZmZzZXQgPD0gYGJ5dGVPZmZzZXRgLlxuLy9cbi8vIEFyZ3VtZW50czpcbi8vIC0gYnVmZmVyIC0gYSBCdWZmZXIgdG8gc2VhcmNoXG4vLyAtIHZhbCAtIGEgc3RyaW5nLCBCdWZmZXIsIG9yIG51bWJlclxuLy8gLSBieXRlT2Zmc2V0IC0gYW4gaW5kZXggaW50byBgYnVmZmVyYDsgd2lsbCBiZSBjbGFtcGVkIHRvIGFuIGludDMyXG4vLyAtIGVuY29kaW5nIC0gYW4gb3B0aW9uYWwgZW5jb2RpbmcsIHJlbGV2YW50IGlzIHZhbCBpcyBhIHN0cmluZ1xuLy8gLSBkaXIgLSB0cnVlIGZvciBpbmRleE9mLCBmYWxzZSBmb3IgbGFzdEluZGV4T2ZcbmZ1bmN0aW9uIGJpZGlyZWN0aW9uYWxJbmRleE9mIChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGRpcikge1xuICAvLyBFbXB0eSBidWZmZXIgbWVhbnMgbm8gbWF0Y2hcbiAgaWYgKGJ1ZmZlci5sZW5ndGggPT09IDApIHJldHVybiAtMVxuXG4gIC8vIE5vcm1hbGl6ZSBieXRlT2Zmc2V0XG4gIGlmICh0eXBlb2YgYnl0ZU9mZnNldCA9PT0gJ3N0cmluZycpIHtcbiAgICBlbmNvZGluZyA9IGJ5dGVPZmZzZXRcbiAgICBieXRlT2Zmc2V0ID0gMFxuICB9IGVsc2UgaWYgKGJ5dGVPZmZzZXQgPiAweDdmZmZmZmZmKSB7XG4gICAgYnl0ZU9mZnNldCA9IDB4N2ZmZmZmZmZcbiAgfSBlbHNlIGlmIChieXRlT2Zmc2V0IDwgLTB4ODAwMDAwMDApIHtcbiAgICBieXRlT2Zmc2V0ID0gLTB4ODAwMDAwMDBcbiAgfVxuICBieXRlT2Zmc2V0ID0gK2J5dGVPZmZzZXQgLy8gQ29lcmNlIHRvIE51bWJlci5cbiAgaWYgKG51bWJlcklzTmFOKGJ5dGVPZmZzZXQpKSB7XG4gICAgLy8gYnl0ZU9mZnNldDogaXQgaXQncyB1bmRlZmluZWQsIG51bGwsIE5hTiwgXCJmb29cIiwgZXRjLCBzZWFyY2ggd2hvbGUgYnVmZmVyXG4gICAgYnl0ZU9mZnNldCA9IGRpciA/IDAgOiAoYnVmZmVyLmxlbmd0aCAtIDEpXG4gIH1cblxuICAvLyBOb3JtYWxpemUgYnl0ZU9mZnNldDogbmVnYXRpdmUgb2Zmc2V0cyBzdGFydCBmcm9tIHRoZSBlbmQgb2YgdGhlIGJ1ZmZlclxuICBpZiAoYnl0ZU9mZnNldCA8IDApIGJ5dGVPZmZzZXQgPSBidWZmZXIubGVuZ3RoICsgYnl0ZU9mZnNldFxuICBpZiAoYnl0ZU9mZnNldCA+PSBidWZmZXIubGVuZ3RoKSB7XG4gICAgaWYgKGRpcikgcmV0dXJuIC0xXG4gICAgZWxzZSBieXRlT2Zmc2V0ID0gYnVmZmVyLmxlbmd0aCAtIDFcbiAgfSBlbHNlIGlmIChieXRlT2Zmc2V0IDwgMCkge1xuICAgIGlmIChkaXIpIGJ5dGVPZmZzZXQgPSAwXG4gICAgZWxzZSByZXR1cm4gLTFcbiAgfVxuXG4gIC8vIE5vcm1hbGl6ZSB2YWxcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgdmFsID0gQnVmZmVyLmZyb20odmFsLCBlbmNvZGluZylcbiAgfVxuXG4gIC8vIEZpbmFsbHksIHNlYXJjaCBlaXRoZXIgaW5kZXhPZiAoaWYgZGlyIGlzIHRydWUpIG9yIGxhc3RJbmRleE9mXG4gIGlmIChCdWZmZXIuaXNCdWZmZXIodmFsKSkge1xuICAgIC8vIFNwZWNpYWwgY2FzZTogbG9va2luZyBmb3IgZW1wdHkgc3RyaW5nL2J1ZmZlciBhbHdheXMgZmFpbHNcbiAgICBpZiAodmFsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIC0xXG4gICAgfVxuICAgIHJldHVybiBhcnJheUluZGV4T2YoYnVmZmVyLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpXG4gIH0gZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICB2YWwgPSB2YWwgJiAweEZGIC8vIFNlYXJjaCBmb3IgYSBieXRlIHZhbHVlIFswLTI1NV1cbiAgICBpZiAodHlwZW9mIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGlmIChkaXIpIHtcbiAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBVaW50OEFycmF5LnByb3RvdHlwZS5sYXN0SW5kZXhPZi5jYWxsKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0KVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKGJ1ZmZlciwgW3ZhbF0sIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpXG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2YWwgbXVzdCBiZSBzdHJpbmcsIG51bWJlciBvciBCdWZmZXInKVxufVxuXG5mdW5jdGlvbiBhcnJheUluZGV4T2YgKGFyciwgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgZGlyKSB7XG4gIGxldCBpbmRleFNpemUgPSAxXG4gIGxldCBhcnJMZW5ndGggPSBhcnIubGVuZ3RoXG4gIGxldCB2YWxMZW5ndGggPSB2YWwubGVuZ3RoXG5cbiAgaWYgKGVuY29kaW5nICE9PSB1bmRlZmluZWQpIHtcbiAgICBlbmNvZGluZyA9IFN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKVxuICAgIGlmIChlbmNvZGluZyA9PT0gJ3VjczInIHx8IGVuY29kaW5nID09PSAndWNzLTInIHx8XG4gICAgICAgIGVuY29kaW5nID09PSAndXRmMTZsZScgfHwgZW5jb2RpbmcgPT09ICd1dGYtMTZsZScpIHtcbiAgICAgIGlmIChhcnIubGVuZ3RoIDwgMiB8fCB2YWwubGVuZ3RoIDwgMikge1xuICAgICAgICByZXR1cm4gLTFcbiAgICAgIH1cbiAgICAgIGluZGV4U2l6ZSA9IDJcbiAgICAgIGFyckxlbmd0aCAvPSAyXG4gICAgICB2YWxMZW5ndGggLz0gMlxuICAgICAgYnl0ZU9mZnNldCAvPSAyXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcmVhZCAoYnVmLCBpKSB7XG4gICAgaWYgKGluZGV4U2l6ZSA9PT0gMSkge1xuICAgICAgcmV0dXJuIGJ1ZltpXVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYnVmLnJlYWRVSW50MTZCRShpICogaW5kZXhTaXplKVxuICAgIH1cbiAgfVxuXG4gIGxldCBpXG4gIGlmIChkaXIpIHtcbiAgICBsZXQgZm91bmRJbmRleCA9IC0xXG4gICAgZm9yIChpID0gYnl0ZU9mZnNldDsgaSA8IGFyckxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocmVhZChhcnIsIGkpID09PSByZWFkKHZhbCwgZm91bmRJbmRleCA9PT0gLTEgPyAwIDogaSAtIGZvdW5kSW5kZXgpKSB7XG4gICAgICAgIGlmIChmb3VuZEluZGV4ID09PSAtMSkgZm91bmRJbmRleCA9IGlcbiAgICAgICAgaWYgKGkgLSBmb3VuZEluZGV4ICsgMSA9PT0gdmFsTGVuZ3RoKSByZXR1cm4gZm91bmRJbmRleCAqIGluZGV4U2l6ZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGZvdW5kSW5kZXggIT09IC0xKSBpIC09IGkgLSBmb3VuZEluZGV4XG4gICAgICAgIGZvdW5kSW5kZXggPSAtMVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAoYnl0ZU9mZnNldCArIHZhbExlbmd0aCA+IGFyckxlbmd0aCkgYnl0ZU9mZnNldCA9IGFyckxlbmd0aCAtIHZhbExlbmd0aFxuICAgIGZvciAoaSA9IGJ5dGVPZmZzZXQ7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBsZXQgZm91bmQgPSB0cnVlXG4gICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHZhbExlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmIChyZWFkKGFyciwgaSArIGopICE9PSByZWFkKHZhbCwgaikpIHtcbiAgICAgICAgICBmb3VuZCA9IGZhbHNlXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGZvdW5kKSByZXR1cm4gaVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiAtMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluY2x1ZGVzID0gZnVuY3Rpb24gaW5jbHVkZXMgKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIHRoaXMuaW5kZXhPZih2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSAhPT0gLTFcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbmRleE9mID0gZnVuY3Rpb24gaW5kZXhPZiAodmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZykge1xuICByZXR1cm4gYmlkaXJlY3Rpb25hbEluZGV4T2YodGhpcywgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgdHJ1ZSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5sYXN0SW5kZXhPZiA9IGZ1bmN0aW9uIGxhc3RJbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSB7XG4gIHJldHVybiBiaWRpcmVjdGlvbmFsSW5kZXhPZih0aGlzLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBmYWxzZSlcbn1cblxuZnVuY3Rpb24gaGV4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICBvZmZzZXQgPSBOdW1iZXIob2Zmc2V0KSB8fCAwXG4gIGNvbnN0IHJlbWFpbmluZyA9IGJ1Zi5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKCFsZW5ndGgpIHtcbiAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgfSBlbHNlIHtcbiAgICBsZW5ndGggPSBOdW1iZXIobGVuZ3RoKVxuICAgIGlmIChsZW5ndGggPiByZW1haW5pbmcpIHtcbiAgICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHN0ckxlbiA9IHN0cmluZy5sZW5ndGhcblxuICBpZiAobGVuZ3RoID4gc3RyTGVuIC8gMikge1xuICAgIGxlbmd0aCA9IHN0ckxlbiAvIDJcbiAgfVxuICBsZXQgaVxuICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUludChzdHJpbmcuc3Vic3RyKGkgKiAyLCAyKSwgMTYpXG4gICAgaWYgKG51bWJlcklzTmFOKHBhcnNlZCkpIHJldHVybiBpXG4gICAgYnVmW29mZnNldCArIGldID0gcGFyc2VkXG4gIH1cbiAgcmV0dXJuIGlcbn1cblxuZnVuY3Rpb24gdXRmOFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIodXRmOFRvQnl0ZXMoc3RyaW5nLCBidWYubGVuZ3RoIC0gb2Zmc2V0KSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYXNjaWlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKGFzY2lpVG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBiYXNlNjRXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKGJhc2U2NFRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gdWNzMldyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIodXRmMTZsZVRvQnl0ZXMoc3RyaW5nLCBidWYubGVuZ3RoIC0gb2Zmc2V0KSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uIHdyaXRlIChzdHJpbmcsIG9mZnNldCwgbGVuZ3RoLCBlbmNvZGluZykge1xuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nKVxuICBpZiAob2Zmc2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICBlbmNvZGluZyA9ICd1dGY4J1xuICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoXG4gICAgb2Zmc2V0ID0gMFxuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nLCBlbmNvZGluZylcbiAgfSBlbHNlIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygb2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgIGVuY29kaW5nID0gb2Zmc2V0XG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIG9mZnNldFssIGxlbmd0aF1bLCBlbmNvZGluZ10pXG4gIH0gZWxzZSBpZiAoaXNGaW5pdGUob2Zmc2V0KSkge1xuICAgIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICAgIGlmIChpc0Zpbml0ZShsZW5ndGgpKSB7XG4gICAgICBsZW5ndGggPSBsZW5ndGggPj4+IDBcbiAgICAgIGlmIChlbmNvZGluZyA9PT0gdW5kZWZpbmVkKSBlbmNvZGluZyA9ICd1dGY4J1xuICAgIH0gZWxzZSB7XG4gICAgICBlbmNvZGluZyA9IGxlbmd0aFxuICAgICAgbGVuZ3RoID0gdW5kZWZpbmVkXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICdCdWZmZXIud3JpdGUoc3RyaW5nLCBlbmNvZGluZywgb2Zmc2V0WywgbGVuZ3RoXSkgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZCdcbiAgICApXG4gIH1cblxuICBjb25zdCByZW1haW5pbmcgPSB0aGlzLmxlbmd0aCAtIG9mZnNldFxuICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQgfHwgbGVuZ3RoID4gcmVtYWluaW5nKSBsZW5ndGggPSByZW1haW5pbmdcblxuICBpZiAoKHN0cmluZy5sZW5ndGggPiAwICYmIChsZW5ndGggPCAwIHx8IG9mZnNldCA8IDApKSB8fCBvZmZzZXQgPiB0aGlzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIHdyaXRlIG91dHNpZGUgYnVmZmVyIGJvdW5kcycpXG4gIH1cblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIGxldCBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgY2FzZSAnbGF0aW4xJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBhc2NpaVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIC8vIFdhcm5pbmc6IG1heExlbmd0aCBub3QgdGFrZW4gaW50byBhY2NvdW50IGluIGJhc2U2NFdyaXRlXG4gICAgICAgIHJldHVybiBiYXNlNjRXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdWNzMldyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuZnVuY3Rpb24gYmFzZTY0U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBpZiAoc3RhcnQgPT09IDAgJiYgZW5kID09PSBidWYubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1ZilcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmLnNsaWNlKHN0YXJ0LCBlbmQpKVxuICB9XG59XG5cbmZ1bmN0aW9uIHV0ZjhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcbiAgY29uc3QgcmVzID0gW11cblxuICBsZXQgaSA9IHN0YXJ0XG4gIHdoaWxlIChpIDwgZW5kKSB7XG4gICAgY29uc3QgZmlyc3RCeXRlID0gYnVmW2ldXG4gICAgbGV0IGNvZGVQb2ludCA9IG51bGxcbiAgICBsZXQgYnl0ZXNQZXJTZXF1ZW5jZSA9IChmaXJzdEJ5dGUgPiAweEVGKVxuICAgICAgPyA0XG4gICAgICA6IChmaXJzdEJ5dGUgPiAweERGKVxuICAgICAgICAgID8gM1xuICAgICAgICAgIDogKGZpcnN0Qnl0ZSA+IDB4QkYpXG4gICAgICAgICAgICAgID8gMlxuICAgICAgICAgICAgICA6IDFcblxuICAgIGlmIChpICsgYnl0ZXNQZXJTZXF1ZW5jZSA8PSBlbmQpIHtcbiAgICAgIGxldCBzZWNvbmRCeXRlLCB0aGlyZEJ5dGUsIGZvdXJ0aEJ5dGUsIHRlbXBDb2RlUG9pbnRcblxuICAgICAgc3dpdGNoIChieXRlc1BlclNlcXVlbmNlKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICBpZiAoZmlyc3RCeXRlIDwgMHg4MCkge1xuICAgICAgICAgICAgY29kZVBvaW50ID0gZmlyc3RCeXRlXG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4MUYpIDw8IDB4NiB8IChzZWNvbmRCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHg3Rikge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIHRoaXJkQnl0ZSA9IGJ1ZltpICsgMl1cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAodGhpcmRCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHhGKSA8PCAweEMgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpIDw8IDB4NiB8ICh0aGlyZEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweDdGRiAmJiAodGVtcENvZGVQb2ludCA8IDB4RDgwMCB8fCB0ZW1wQ29kZVBvaW50ID4gMHhERkZGKSkge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIHRoaXJkQnl0ZSA9IGJ1ZltpICsgMl1cbiAgICAgICAgICBmb3VydGhCeXRlID0gYnVmW2kgKyAzXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwICYmICh0aGlyZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAoZm91cnRoQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4RikgPDwgMHgxMiB8IChzZWNvbmRCeXRlICYgMHgzRikgPDwgMHhDIHwgKHRoaXJkQnl0ZSAmIDB4M0YpIDw8IDB4NiB8IChmb3VydGhCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHhGRkZGICYmIHRlbXBDb2RlUG9pbnQgPCAweDExMDAwMCkge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjb2RlUG9pbnQgPT09IG51bGwpIHtcbiAgICAgIC8vIHdlIGRpZCBub3QgZ2VuZXJhdGUgYSB2YWxpZCBjb2RlUG9pbnQgc28gaW5zZXJ0IGFcbiAgICAgIC8vIHJlcGxhY2VtZW50IGNoYXIgKFUrRkZGRCkgYW5kIGFkdmFuY2Ugb25seSAxIGJ5dGVcbiAgICAgIGNvZGVQb2ludCA9IDB4RkZGRFxuICAgICAgYnl0ZXNQZXJTZXF1ZW5jZSA9IDFcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA+IDB4RkZGRikge1xuICAgICAgLy8gZW5jb2RlIHRvIHV0ZjE2IChzdXJyb2dhdGUgcGFpciBkYW5jZSlcbiAgICAgIGNvZGVQb2ludCAtPSAweDEwMDAwXG4gICAgICByZXMucHVzaChjb2RlUG9pbnQgPj4+IDEwICYgMHgzRkYgfCAweEQ4MDApXG4gICAgICBjb2RlUG9pbnQgPSAweERDMDAgfCBjb2RlUG9pbnQgJiAweDNGRlxuICAgIH1cblxuICAgIHJlcy5wdXNoKGNvZGVQb2ludClcbiAgICBpICs9IGJ5dGVzUGVyU2VxdWVuY2VcbiAgfVxuXG4gIHJldHVybiBkZWNvZGVDb2RlUG9pbnRzQXJyYXkocmVzKVxufVxuXG4vLyBCYXNlZCBvbiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMjc0NzI3Mi82ODA3NDIsIHRoZSBicm93c2VyIHdpdGhcbi8vIHRoZSBsb3dlc3QgbGltaXQgaXMgQ2hyb21lLCB3aXRoIDB4MTAwMDAgYXJncy5cbi8vIFdlIGdvIDEgbWFnbml0dWRlIGxlc3MsIGZvciBzYWZldHlcbmNvbnN0IE1BWF9BUkdVTUVOVFNfTEVOR1RIID0gMHgxMDAwXG5cbmZ1bmN0aW9uIGRlY29kZUNvZGVQb2ludHNBcnJheSAoY29kZVBvaW50cykge1xuICBjb25zdCBsZW4gPSBjb2RlUG9pbnRzLmxlbmd0aFxuICBpZiAobGVuIDw9IE1BWF9BUkdVTUVOVFNfTEVOR1RIKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjb2RlUG9pbnRzKSAvLyBhdm9pZCBleHRyYSBzbGljZSgpXG4gIH1cblxuICAvLyBEZWNvZGUgaW4gY2h1bmtzIHRvIGF2b2lkIFwiY2FsbCBzdGFjayBzaXplIGV4Y2VlZGVkXCIuXG4gIGxldCByZXMgPSAnJ1xuICBsZXQgaSA9IDBcbiAgd2hpbGUgKGkgPCBsZW4pIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShcbiAgICAgIFN0cmluZyxcbiAgICAgIGNvZGVQb2ludHMuc2xpY2UoaSwgaSArPSBNQVhfQVJHVU1FTlRTX0xFTkdUSClcbiAgICApXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgbGV0IHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSAmIDB4N0YpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBsYXRpbjFTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGxldCByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBoZXhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGNvbnN0IGxlbiA9IGJ1Zi5sZW5ndGhcblxuICBpZiAoIXN0YXJ0IHx8IHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIGlmICghZW5kIHx8IGVuZCA8IDAgfHwgZW5kID4gbGVuKSBlbmQgPSBsZW5cblxuICBsZXQgb3V0ID0gJydcbiAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICBvdXQgKz0gaGV4U2xpY2VMb29rdXBUYWJsZVtidWZbaV1dXG4gIH1cbiAgcmV0dXJuIG91dFxufVxuXG5mdW5jdGlvbiB1dGYxNmxlU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBjb25zdCBieXRlcyA9IGJ1Zi5zbGljZShzdGFydCwgZW5kKVxuICBsZXQgcmVzID0gJydcbiAgLy8gSWYgYnl0ZXMubGVuZ3RoIGlzIG9kZCwgdGhlIGxhc3QgOCBiaXRzIG11c3QgYmUgaWdub3JlZCAoc2FtZSBhcyBub2RlLmpzKVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aCAtIDE7IGkgKz0gMikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGVzW2ldICsgKGJ5dGVzW2kgKyAxXSAqIDI1NikpXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24gc2xpY2UgKHN0YXJ0LCBlbmQpIHtcbiAgY29uc3QgbGVuID0gdGhpcy5sZW5ndGhcbiAgc3RhcnQgPSB+fnN0YXJ0XG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkID8gbGVuIDogfn5lbmRcblxuICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgc3RhcnQgKz0gbGVuXG4gICAgaWYgKHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIH0gZWxzZSBpZiAoc3RhcnQgPiBsZW4pIHtcbiAgICBzdGFydCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IDApIHtcbiAgICBlbmQgKz0gbGVuXG4gICAgaWYgKGVuZCA8IDApIGVuZCA9IDBcbiAgfSBlbHNlIGlmIChlbmQgPiBsZW4pIHtcbiAgICBlbmQgPSBsZW5cbiAgfVxuXG4gIGlmIChlbmQgPCBzdGFydCkgZW5kID0gc3RhcnRcblxuICBjb25zdCBuZXdCdWYgPSB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpXG4gIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlXG4gIE9iamVjdC5zZXRQcm90b3R5cGVPZihuZXdCdWYsIEJ1ZmZlci5wcm90b3R5cGUpXG5cbiAgcmV0dXJuIG5ld0J1ZlxufVxuXG4vKlxuICogTmVlZCB0byBtYWtlIHN1cmUgdGhhdCBidWZmZXIgaXNuJ3QgdHJ5aW5nIHRvIHdyaXRlIG91dCBvZiBib3VuZHMuXG4gKi9cbmZ1bmN0aW9uIGNoZWNrT2Zmc2V0IChvZmZzZXQsIGV4dCwgbGVuZ3RoKSB7XG4gIGlmICgob2Zmc2V0ICUgMSkgIT09IDAgfHwgb2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ29mZnNldCBpcyBub3QgdWludCcpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBsZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdUcnlpbmcgdG8gYWNjZXNzIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludExFID1cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRMRSA9IGZ1bmN0aW9uIHJlYWRVSW50TEUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgbGV0IHZhbCA9IHRoaXNbb2Zmc2V0XVxuICBsZXQgbXVsID0gMVxuICBsZXQgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVaW50QkUgPVxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludEJFID0gZnVuY3Rpb24gcmVhZFVJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG4gIH1cblxuICBsZXQgdmFsID0gdGhpc1tvZmZzZXQgKyAtLWJ5dGVMZW5ndGhdXG4gIGxldCBtdWwgPSAxXG4gIHdoaWxlIChieXRlTGVuZ3RoID4gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIC0tYnl0ZUxlbmd0aF0gKiBtdWxcbiAgfVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludDggPVxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDggPSBmdW5jdGlvbiByZWFkVUludDggKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMSwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiB0aGlzW29mZnNldF1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludDE2TEUgPVxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2TEUgPSBmdW5jdGlvbiByZWFkVUludDE2TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiB0aGlzW29mZnNldF0gfCAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVaW50MTZCRSA9XG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZCRSA9IGZ1bmN0aW9uIHJlYWRVSW50MTZCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgOCkgfCB0aGlzW29mZnNldCArIDFdXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVpbnQzMkxFID1cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkxFID0gZnVuY3Rpb24gcmVhZFVJbnQzMkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAoKHRoaXNbb2Zmc2V0XSkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOCkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgMTYpKSArXG4gICAgICAodGhpc1tvZmZzZXQgKyAzXSAqIDB4MTAwMDAwMClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludDMyQkUgPVxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyQkUgPSBmdW5jdGlvbiByZWFkVUludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gKiAweDEwMDAwMDApICtcbiAgICAoKHRoaXNbb2Zmc2V0ICsgMV0gPDwgMTYpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCA4KSB8XG4gICAgdGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkQmlnVUludDY0TEUgPSBkZWZpbmVCaWdJbnRNZXRob2QoZnVuY3Rpb24gcmVhZEJpZ1VJbnQ2NExFIChvZmZzZXQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIHZhbGlkYXRlTnVtYmVyKG9mZnNldCwgJ29mZnNldCcpXG4gIGNvbnN0IGZpcnN0ID0gdGhpc1tvZmZzZXRdXG4gIGNvbnN0IGxhc3QgPSB0aGlzW29mZnNldCArIDddXG4gIGlmIChmaXJzdCA9PT0gdW5kZWZpbmVkIHx8IGxhc3QgPT09IHVuZGVmaW5lZCkge1xuICAgIGJvdW5kc0Vycm9yKG9mZnNldCwgdGhpcy5sZW5ndGggLSA4KVxuICB9XG5cbiAgY29uc3QgbG8gPSBmaXJzdCArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDggK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiAxNiArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDI0XG5cbiAgY29uc3QgaGkgPSB0aGlzWysrb2Zmc2V0XSArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDggK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiAxNiArXG4gICAgbGFzdCAqIDIgKiogMjRcblxuICByZXR1cm4gQmlnSW50KGxvKSArIChCaWdJbnQoaGkpIDw8IEJpZ0ludCgzMikpXG59KVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRCaWdVSW50NjRCRSA9IGRlZmluZUJpZ0ludE1ldGhvZChmdW5jdGlvbiByZWFkQmlnVUludDY0QkUgKG9mZnNldCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgdmFsaWRhdGVOdW1iZXIob2Zmc2V0LCAnb2Zmc2V0JylcbiAgY29uc3QgZmlyc3QgPSB0aGlzW29mZnNldF1cbiAgY29uc3QgbGFzdCA9IHRoaXNbb2Zmc2V0ICsgN11cbiAgaWYgKGZpcnN0ID09PSB1bmRlZmluZWQgfHwgbGFzdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYm91bmRzRXJyb3Iob2Zmc2V0LCB0aGlzLmxlbmd0aCAtIDgpXG4gIH1cblxuICBjb25zdCBoaSA9IGZpcnN0ICogMiAqKiAyNCArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDE2ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogOCArXG4gICAgdGhpc1srK29mZnNldF1cblxuICBjb25zdCBsbyA9IHRoaXNbKytvZmZzZXRdICogMiAqKiAyNCArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDE2ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogOCArXG4gICAgbGFzdFxuXG4gIHJldHVybiAoQmlnSW50KGhpKSA8PCBCaWdJbnQoMzIpKSArIEJpZ0ludChsbylcbn0pXG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludExFID0gZnVuY3Rpb24gcmVhZEludExFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIGxldCB2YWwgPSB0aGlzW29mZnNldF1cbiAgbGV0IG11bCA9IDFcbiAgbGV0IGkgPSAwXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcbiAgfVxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKSB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRCRSA9IGZ1bmN0aW9uIHJlYWRJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICBsZXQgaSA9IGJ5dGVMZW5ndGhcbiAgbGV0IG11bCA9IDFcbiAgbGV0IHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1pXVxuICB3aGlsZSAoaSA+IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uIHJlYWRJbnQ4IChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICBpZiAoISh0aGlzW29mZnNldF0gJiAweDgwKSkgcmV0dXJuICh0aGlzW29mZnNldF0pXG4gIHJldHVybiAoKDB4ZmYgLSB0aGlzW29mZnNldF0gKyAxKSAqIC0xKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkxFID0gZnVuY3Rpb24gcmVhZEludDE2TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIGNvbnN0IHZhbCA9IHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZCRSA9IGZ1bmN0aW9uIHJlYWRJbnQxNkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICBjb25zdCB2YWwgPSB0aGlzW29mZnNldCArIDFdIHwgKHRoaXNbb2Zmc2V0XSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyTEUgPSBmdW5jdGlvbiByZWFkSW50MzJMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDNdIDw8IDI0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkJFID0gZnVuY3Rpb24gcmVhZEludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgMjQpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkQmlnSW50NjRMRSA9IGRlZmluZUJpZ0ludE1ldGhvZChmdW5jdGlvbiByZWFkQmlnSW50NjRMRSAob2Zmc2V0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICB2YWxpZGF0ZU51bWJlcihvZmZzZXQsICdvZmZzZXQnKVxuICBjb25zdCBmaXJzdCA9IHRoaXNbb2Zmc2V0XVxuICBjb25zdCBsYXN0ID0gdGhpc1tvZmZzZXQgKyA3XVxuICBpZiAoZmlyc3QgPT09IHVuZGVmaW5lZCB8fCBsYXN0ID09PSB1bmRlZmluZWQpIHtcbiAgICBib3VuZHNFcnJvcihvZmZzZXQsIHRoaXMubGVuZ3RoIC0gOClcbiAgfVxuXG4gIGNvbnN0IHZhbCA9IHRoaXNbb2Zmc2V0ICsgNF0gK1xuICAgIHRoaXNbb2Zmc2V0ICsgNV0gKiAyICoqIDggK1xuICAgIHRoaXNbb2Zmc2V0ICsgNl0gKiAyICoqIDE2ICtcbiAgICAobGFzdCA8PCAyNCkgLy8gT3ZlcmZsb3dcblxuICByZXR1cm4gKEJpZ0ludCh2YWwpIDw8IEJpZ0ludCgzMikpICtcbiAgICBCaWdJbnQoZmlyc3QgK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiA4ICtcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogMTYgK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiAyNClcbn0pXG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEJpZ0ludDY0QkUgPSBkZWZpbmVCaWdJbnRNZXRob2QoZnVuY3Rpb24gcmVhZEJpZ0ludDY0QkUgKG9mZnNldCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgdmFsaWRhdGVOdW1iZXIob2Zmc2V0LCAnb2Zmc2V0JylcbiAgY29uc3QgZmlyc3QgPSB0aGlzW29mZnNldF1cbiAgY29uc3QgbGFzdCA9IHRoaXNbb2Zmc2V0ICsgN11cbiAgaWYgKGZpcnN0ID09PSB1bmRlZmluZWQgfHwgbGFzdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYm91bmRzRXJyb3Iob2Zmc2V0LCB0aGlzLmxlbmd0aCAtIDgpXG4gIH1cblxuICBjb25zdCB2YWwgPSAoZmlyc3QgPDwgMjQpICsgLy8gT3ZlcmZsb3dcbiAgICB0aGlzWysrb2Zmc2V0XSAqIDIgKiogMTYgK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiA4ICtcbiAgICB0aGlzWysrb2Zmc2V0XVxuXG4gIHJldHVybiAoQmlnSW50KHZhbCkgPDwgQmlnSW50KDMyKSkgK1xuICAgIEJpZ0ludCh0aGlzWysrb2Zmc2V0XSAqIDIgKiogMjQgK1xuICAgIHRoaXNbKytvZmZzZXRdICogMiAqKiAxNiArXG4gICAgdGhpc1srK29mZnNldF0gKiAyICoqIDggK1xuICAgIGxhc3QpXG59KVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdExFID0gZnVuY3Rpb24gcmVhZEZsb2F0TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRCRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdEJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgZmFsc2UsIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVMRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIHRydWUsIDUyLCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVCRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCA1MiwgOClcbn1cblxuZnVuY3Rpb24gY2hlY2tJbnQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihidWYpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImJ1ZmZlclwiIGFyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXIgaW5zdGFuY2UnKVxuICBpZiAodmFsdWUgPiBtYXggfHwgdmFsdWUgPCBtaW4pIHRocm93IG5ldyBSYW5nZUVycm9yKCdcInZhbHVlXCIgYXJndW1lbnQgaXMgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5kZXggb3V0IG9mIHJhbmdlJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVpbnRMRSA9XG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludExFID0gZnVuY3Rpb24gd3JpdGVVSW50TEUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY29uc3QgbWF4Qnl0ZXMgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCkgLSAxXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbWF4Qnl0ZXMsIDApXG4gIH1cblxuICBsZXQgbXVsID0gMVxuICBsZXQgaSA9IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICh2YWx1ZSAvIG11bCkgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVWludEJFID1cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjb25zdCBtYXhCeXRlcyA9IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKSAtIDFcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBtYXhCeXRlcywgMClcbiAgfVxuXG4gIGxldCBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgbGV0IG11bCA9IDFcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVaW50OCA9XG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDggPSBmdW5jdGlvbiB3cml0ZVVJbnQ4ICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHhmZiwgMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDFcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVpbnQxNkxFID1cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVaW50MTZCRSA9XG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDE2QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnQxNkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHhmZmZmLCAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDgpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVWludDMyTEUgPVxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVpbnQzMkJFID1cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDMyQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDI0KVxuICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbmZ1bmN0aW9uIHdydEJpZ1VJbnQ2NExFIChidWYsIHZhbHVlLCBvZmZzZXQsIG1pbiwgbWF4KSB7XG4gIGNoZWNrSW50QkkodmFsdWUsIG1pbiwgbWF4LCBidWYsIG9mZnNldCwgNylcblxuICBsZXQgbG8gPSBOdW1iZXIodmFsdWUgJiBCaWdJbnQoMHhmZmZmZmZmZikpXG4gIGJ1ZltvZmZzZXQrK10gPSBsb1xuICBsbyA9IGxvID4+IDhcbiAgYnVmW29mZnNldCsrXSA9IGxvXG4gIGxvID0gbG8gPj4gOFxuICBidWZbb2Zmc2V0KytdID0gbG9cbiAgbG8gPSBsbyA+PiA4XG4gIGJ1ZltvZmZzZXQrK10gPSBsb1xuICBsZXQgaGkgPSBOdW1iZXIodmFsdWUgPj4gQmlnSW50KDMyKSAmIEJpZ0ludCgweGZmZmZmZmZmKSlcbiAgYnVmW29mZnNldCsrXSA9IGhpXG4gIGhpID0gaGkgPj4gOFxuICBidWZbb2Zmc2V0KytdID0gaGlcbiAgaGkgPSBoaSA+PiA4XG4gIGJ1ZltvZmZzZXQrK10gPSBoaVxuICBoaSA9IGhpID4+IDhcbiAgYnVmW29mZnNldCsrXSA9IGhpXG4gIHJldHVybiBvZmZzZXRcbn1cblxuZnVuY3Rpb24gd3J0QmlnVUludDY0QkUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbWluLCBtYXgpIHtcbiAgY2hlY2tJbnRCSSh2YWx1ZSwgbWluLCBtYXgsIGJ1Ziwgb2Zmc2V0LCA3KVxuXG4gIGxldCBsbyA9IE51bWJlcih2YWx1ZSAmIEJpZ0ludCgweGZmZmZmZmZmKSlcbiAgYnVmW29mZnNldCArIDddID0gbG9cbiAgbG8gPSBsbyA+PiA4XG4gIGJ1ZltvZmZzZXQgKyA2XSA9IGxvXG4gIGxvID0gbG8gPj4gOFxuICBidWZbb2Zmc2V0ICsgNV0gPSBsb1xuICBsbyA9IGxvID4+IDhcbiAgYnVmW29mZnNldCArIDRdID0gbG9cbiAgbGV0IGhpID0gTnVtYmVyKHZhbHVlID4+IEJpZ0ludCgzMikgJiBCaWdJbnQoMHhmZmZmZmZmZikpXG4gIGJ1ZltvZmZzZXQgKyAzXSA9IGhpXG4gIGhpID0gaGkgPj4gOFxuICBidWZbb2Zmc2V0ICsgMl0gPSBoaVxuICBoaSA9IGhpID4+IDhcbiAgYnVmW29mZnNldCArIDFdID0gaGlcbiAgaGkgPSBoaSA+PiA4XG4gIGJ1ZltvZmZzZXRdID0gaGlcbiAgcmV0dXJuIG9mZnNldCArIDhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUJpZ1VJbnQ2NExFID0gZGVmaW5lQmlnSW50TWV0aG9kKGZ1bmN0aW9uIHdyaXRlQmlnVUludDY0TEUgKHZhbHVlLCBvZmZzZXQgPSAwKSB7XG4gIHJldHVybiB3cnRCaWdVSW50NjRMRSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBCaWdJbnQoMCksIEJpZ0ludCgnMHhmZmZmZmZmZmZmZmZmZmZmJykpXG59KVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlQmlnVUludDY0QkUgPSBkZWZpbmVCaWdJbnRNZXRob2QoZnVuY3Rpb24gd3JpdGVCaWdVSW50NjRCRSAodmFsdWUsIG9mZnNldCA9IDApIHtcbiAgcmV0dXJuIHdydEJpZ1VJbnQ2NEJFKHRoaXMsIHZhbHVlLCBvZmZzZXQsIEJpZ0ludCgwKSwgQmlnSW50KCcweGZmZmZmZmZmZmZmZmZmZmYnKSlcbn0pXG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRMRSA9IGZ1bmN0aW9uIHdyaXRlSW50TEUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY29uc3QgbGltaXQgPSBNYXRoLnBvdygyLCAoOCAqIGJ5dGVMZW5ndGgpIC0gMSlcblxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIGxpbWl0IC0gMSwgLWxpbWl0KVxuICB9XG5cbiAgbGV0IGkgPSAwXG4gIGxldCBtdWwgPSAxXG4gIGxldCBzdWIgPSAwXG4gIHRoaXNbb2Zmc2V0XSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIGlmICh2YWx1ZSA8IDAgJiYgc3ViID09PSAwICYmIHRoaXNbb2Zmc2V0ICsgaSAtIDFdICE9PSAwKSB7XG4gICAgICBzdWIgPSAxXG4gICAgfVxuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAoKHZhbHVlIC8gbXVsKSA+PiAwKSAtIHN1YiAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRCRSA9IGZ1bmN0aW9uIHdyaXRlSW50QkUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY29uc3QgbGltaXQgPSBNYXRoLnBvdygyLCAoOCAqIGJ5dGVMZW5ndGgpIC0gMSlcblxuICAgIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIGxpbWl0IC0gMSwgLWxpbWl0KVxuICB9XG5cbiAgbGV0IGkgPSBieXRlTGVuZ3RoIC0gMVxuICBsZXQgbXVsID0gMVxuICBsZXQgc3ViID0gMFxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIGlmICh2YWx1ZSA8IDAgJiYgc3ViID09PSAwICYmIHRoaXNbb2Zmc2V0ICsgaSArIDFdICE9PSAwKSB7XG4gICAgICBzdWIgPSAxXG4gICAgfVxuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAoKHZhbHVlIC8gbXVsKSA+PiAwKSAtIHN1YiAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQ4ID0gZnVuY3Rpb24gd3JpdGVJbnQ4ICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHg3ZiwgLTB4ODApXG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZiArIHZhbHVlICsgMVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlSW50MTZMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2QkUgPSBmdW5jdGlvbiB3cml0ZUludDE2QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweDdmZmYsIC0weDgwMDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVJbnQzMkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgPj4+IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHg3ZmZmZmZmZiwgLTB4ODAwMDAwMDApXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDE2KVxuICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyQkUgPSBmdW5jdGlvbiB3cml0ZUludDMyQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDE2KVxuICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiA4KVxuICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUJpZ0ludDY0TEUgPSBkZWZpbmVCaWdJbnRNZXRob2QoZnVuY3Rpb24gd3JpdGVCaWdJbnQ2NExFICh2YWx1ZSwgb2Zmc2V0ID0gMCkge1xuICByZXR1cm4gd3J0QmlnVUludDY0TEUodGhpcywgdmFsdWUsIG9mZnNldCwgLUJpZ0ludCgnMHg4MDAwMDAwMDAwMDAwMDAwJyksIEJpZ0ludCgnMHg3ZmZmZmZmZmZmZmZmZmZmJykpXG59KVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlQmlnSW50NjRCRSA9IGRlZmluZUJpZ0ludE1ldGhvZChmdW5jdGlvbiB3cml0ZUJpZ0ludDY0QkUgKHZhbHVlLCBvZmZzZXQgPSAwKSB7XG4gIHJldHVybiB3cnRCaWdVSW50NjRCRSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAtQmlnSW50KCcweDgwMDAwMDAwMDAwMDAwMDAnKSwgQmlnSW50KCcweDdmZmZmZmZmZmZmZmZmZmYnKSlcbn0pXG5cbmZ1bmN0aW9uIGNoZWNrSUVFRTc1NCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5kZXggb3V0IG9mIHJhbmdlJylcbiAgaWYgKG9mZnNldCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxufVxuXG5mdW5jdGlvbiB3cml0ZUZsb2F0IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0ID4+PiAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja0lFRUU3NTQoYnVmLCB2YWx1ZSwgb2Zmc2V0LCA0LCAzLjQwMjgyMzQ2NjM4NTI4ODZlKzM4LCAtMy40MDI4MjM0NjYzODUyODg2ZSszOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCAyMywgNClcbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0TEUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRCRSA9IGZ1bmN0aW9uIHdyaXRlRmxvYXRCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiB3cml0ZURvdWJsZSAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCA+Pj4gMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgOCwgMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgsIC0xLjc5NzY5MzEzNDg2MjMxNTdFKzMwOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCA1MiwgOClcbiAgcmV0dXJuIG9mZnNldCArIDhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUxFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiB3cml0ZURvdWJsZUJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG4vLyBjb3B5KHRhcmdldEJ1ZmZlciwgdGFyZ2V0U3RhcnQ9MCwgc291cmNlU3RhcnQ9MCwgc291cmNlRW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiBjb3B5ICh0YXJnZXQsIHRhcmdldFN0YXJ0LCBzdGFydCwgZW5kKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKHRhcmdldCkpIHRocm93IG5ldyBUeXBlRXJyb3IoJ2FyZ3VtZW50IHNob3VsZCBiZSBhIEJ1ZmZlcicpXG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCAmJiBlbmQgIT09IDApIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXRTdGFydCA+PSB0YXJnZXQubGVuZ3RoKSB0YXJnZXRTdGFydCA9IHRhcmdldC5sZW5ndGhcbiAgaWYgKCF0YXJnZXRTdGFydCkgdGFyZ2V0U3RhcnQgPSAwXG4gIGlmIChlbmQgPiAwICYmIGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIC8vIENvcHkgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuIDBcbiAgaWYgKHRhcmdldC5sZW5ndGggPT09IDAgfHwgdGhpcy5sZW5ndGggPT09IDApIHJldHVybiAwXG5cbiAgLy8gRmF0YWwgZXJyb3IgY29uZGl0aW9uc1xuICBpZiAodGFyZ2V0U3RhcnQgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3RhcmdldFN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICB9XG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxuICBpZiAoZW5kIDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3NvdXJjZUVuZCBvdXQgb2YgYm91bmRzJylcblxuICAvLyBBcmUgd2Ugb29iP1xuICBpZiAoZW5kID4gdGhpcy5sZW5ndGgpIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0U3RhcnQgPCBlbmQgLSBzdGFydCkge1xuICAgIGVuZCA9IHRhcmdldC5sZW5ndGggLSB0YXJnZXRTdGFydCArIHN0YXJ0XG4gIH1cblxuICBjb25zdCBsZW4gPSBlbmQgLSBzdGFydFxuXG4gIGlmICh0aGlzID09PSB0YXJnZXQgJiYgdHlwZW9mIFVpbnQ4QXJyYXkucHJvdG90eXBlLmNvcHlXaXRoaW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAvLyBVc2UgYnVpbHQtaW4gd2hlbiBhdmFpbGFibGUsIG1pc3NpbmcgZnJvbSBJRTExXG4gICAgdGhpcy5jb3B5V2l0aGluKHRhcmdldFN0YXJ0LCBzdGFydCwgZW5kKVxuICB9IGVsc2Uge1xuICAgIFVpbnQ4QXJyYXkucHJvdG90eXBlLnNldC5jYWxsKFxuICAgICAgdGFyZ2V0LFxuICAgICAgdGhpcy5zdWJhcnJheShzdGFydCwgZW5kKSxcbiAgICAgIHRhcmdldFN0YXJ0XG4gICAgKVxuICB9XG5cbiAgcmV0dXJuIGxlblxufVxuXG4vLyBVc2FnZTpcbi8vICAgIGJ1ZmZlci5maWxsKG51bWJlclssIG9mZnNldFssIGVuZF1dKVxuLy8gICAgYnVmZmVyLmZpbGwoYnVmZmVyWywgb2Zmc2V0WywgZW5kXV0pXG4vLyAgICBidWZmZXIuZmlsbChzdHJpbmdbLCBvZmZzZXRbLCBlbmRdXVssIGVuY29kaW5nXSlcbkJ1ZmZlci5wcm90b3R5cGUuZmlsbCA9IGZ1bmN0aW9uIGZpbGwgKHZhbCwgc3RhcnQsIGVuZCwgZW5jb2RpbmcpIHtcbiAgLy8gSGFuZGxlIHN0cmluZyBjYXNlczpcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKHR5cGVvZiBzdGFydCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVuY29kaW5nID0gc3RhcnRcbiAgICAgIHN0YXJ0ID0gMFxuICAgICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBlbmQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBlbmNvZGluZyA9IGVuZFxuICAgICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgICB9XG4gICAgaWYgKGVuY29kaW5nICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIGVuY29kaW5nICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZW5jb2RpbmcgbXVzdCBiZSBhIHN0cmluZycpXG4gICAgfVxuICAgIGlmICh0eXBlb2YgZW5jb2RpbmcgPT09ICdzdHJpbmcnICYmICFCdWZmZXIuaXNFbmNvZGluZyhlbmNvZGluZykpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICB9XG4gICAgaWYgKHZhbC5sZW5ndGggPT09IDEpIHtcbiAgICAgIGNvbnN0IGNvZGUgPSB2YWwuY2hhckNvZGVBdCgwKVxuICAgICAgaWYgKChlbmNvZGluZyA9PT0gJ3V0ZjgnICYmIGNvZGUgPCAxMjgpIHx8XG4gICAgICAgICAgZW5jb2RpbmcgPT09ICdsYXRpbjEnKSB7XG4gICAgICAgIC8vIEZhc3QgcGF0aDogSWYgYHZhbGAgZml0cyBpbnRvIGEgc2luZ2xlIGJ5dGUsIHVzZSB0aGF0IG51bWVyaWMgdmFsdWUuXG4gICAgICAgIHZhbCA9IGNvZGVcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICB2YWwgPSB2YWwgJiAyNTVcbiAgfSBlbHNlIGlmICh0eXBlb2YgdmFsID09PSAnYm9vbGVhbicpIHtcbiAgICB2YWwgPSBOdW1iZXIodmFsKVxuICB9XG5cbiAgLy8gSW52YWxpZCByYW5nZXMgYXJlIG5vdCBzZXQgdG8gYSBkZWZhdWx0LCBzbyBjYW4gcmFuZ2UgY2hlY2sgZWFybHkuXG4gIGlmIChzdGFydCA8IDAgfHwgdGhpcy5sZW5ndGggPCBzdGFydCB8fCB0aGlzLmxlbmd0aCA8IGVuZCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdPdXQgb2YgcmFuZ2UgaW5kZXgnKVxuICB9XG5cbiAgaWYgKGVuZCA8PSBzdGFydCkge1xuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBzdGFydCA9IHN0YXJ0ID4+PiAwXG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkID8gdGhpcy5sZW5ndGggOiBlbmQgPj4+IDBcblxuICBpZiAoIXZhbCkgdmFsID0gMFxuXG4gIGxldCBpXG4gIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICAgIHRoaXNbaV0gPSB2YWxcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgYnl0ZXMgPSBCdWZmZXIuaXNCdWZmZXIodmFsKVxuICAgICAgPyB2YWxcbiAgICAgIDogQnVmZmVyLmZyb20odmFsLCBlbmNvZGluZylcbiAgICBjb25zdCBsZW4gPSBieXRlcy5sZW5ndGhcbiAgICBpZiAobGVuID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgdmFsdWUgXCInICsgdmFsICtcbiAgICAgICAgJ1wiIGlzIGludmFsaWQgZm9yIGFyZ3VtZW50IFwidmFsdWVcIicpXG4gICAgfVxuICAgIGZvciAoaSA9IDA7IGkgPCBlbmQgLSBzdGFydDsgKytpKSB7XG4gICAgICB0aGlzW2kgKyBzdGFydF0gPSBieXRlc1tpICUgbGVuXVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzXG59XG5cbi8vIENVU1RPTSBFUlJPUlNcbi8vID09PT09PT09PT09PT1cblxuLy8gU2ltcGxpZmllZCB2ZXJzaW9ucyBmcm9tIE5vZGUsIGNoYW5nZWQgZm9yIEJ1ZmZlci1vbmx5IHVzYWdlXG5jb25zdCBlcnJvcnMgPSB7fVxuZnVuY3Rpb24gRSAoc3ltLCBnZXRNZXNzYWdlLCBCYXNlKSB7XG4gIGVycm9yc1tzeW1dID0gY2xhc3MgTm9kZUVycm9yIGV4dGVuZHMgQmFzZSB7XG4gICAgY29uc3RydWN0b3IgKCkge1xuICAgICAgc3VwZXIoKVxuXG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ21lc3NhZ2UnLCB7XG4gICAgICAgIHZhbHVlOiBnZXRNZXNzYWdlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH0pXG5cbiAgICAgIC8vIEFkZCB0aGUgZXJyb3IgY29kZSB0byB0aGUgbmFtZSB0byBpbmNsdWRlIGl0IGluIHRoZSBzdGFjayB0cmFjZS5cbiAgICAgIHRoaXMubmFtZSA9IGAke3RoaXMubmFtZX0gWyR7c3ltfV1gXG4gICAgICAvLyBBY2Nlc3MgdGhlIHN0YWNrIHRvIGdlbmVyYXRlIHRoZSBlcnJvciBtZXNzYWdlIGluY2x1ZGluZyB0aGUgZXJyb3IgY29kZVxuICAgICAgLy8gZnJvbSB0aGUgbmFtZS5cbiAgICAgIHRoaXMuc3RhY2sgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtZXhwcmVzc2lvbnNcbiAgICAgIC8vIFJlc2V0IHRoZSBuYW1lIHRvIHRoZSBhY3R1YWwgbmFtZS5cbiAgICAgIGRlbGV0ZSB0aGlzLm5hbWVcbiAgICB9XG5cbiAgICBnZXQgY29kZSAoKSB7XG4gICAgICByZXR1cm4gc3ltXG4gICAgfVxuXG4gICAgc2V0IGNvZGUgKHZhbHVlKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgJ2NvZGUnLCB7XG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgICB9KVxuICAgIH1cblxuICAgIHRvU3RyaW5nICgpIHtcbiAgICAgIHJldHVybiBgJHt0aGlzLm5hbWV9IFske3N5bX1dOiAke3RoaXMubWVzc2FnZX1gXG4gICAgfVxuICB9XG59XG5cbkUoJ0VSUl9CVUZGRVJfT1VUX09GX0JPVU5EUycsXG4gIGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgaWYgKG5hbWUpIHtcbiAgICAgIHJldHVybiBgJHtuYW1lfSBpcyBvdXRzaWRlIG9mIGJ1ZmZlciBib3VuZHNgXG4gICAgfVxuXG4gICAgcmV0dXJuICdBdHRlbXB0IHRvIGFjY2VzcyBtZW1vcnkgb3V0c2lkZSBidWZmZXIgYm91bmRzJ1xuICB9LCBSYW5nZUVycm9yKVxuRSgnRVJSX0lOVkFMSURfQVJHX1RZUEUnLFxuICBmdW5jdGlvbiAobmFtZSwgYWN0dWFsKSB7XG4gICAgcmV0dXJuIGBUaGUgXCIke25hbWV9XCIgYXJndW1lbnQgbXVzdCBiZSBvZiB0eXBlIG51bWJlci4gUmVjZWl2ZWQgdHlwZSAke3R5cGVvZiBhY3R1YWx9YFxuICB9LCBUeXBlRXJyb3IpXG5FKCdFUlJfT1VUX09GX1JBTkdFJyxcbiAgZnVuY3Rpb24gKHN0ciwgcmFuZ2UsIGlucHV0KSB7XG4gICAgbGV0IG1zZyA9IGBUaGUgdmFsdWUgb2YgXCIke3N0cn1cIiBpcyBvdXQgb2YgcmFuZ2UuYFxuICAgIGxldCByZWNlaXZlZCA9IGlucHV0XG4gICAgaWYgKE51bWJlci5pc0ludGVnZXIoaW5wdXQpICYmIE1hdGguYWJzKGlucHV0KSA+IDIgKiogMzIpIHtcbiAgICAgIHJlY2VpdmVkID0gYWRkTnVtZXJpY2FsU2VwYXJhdG9yKFN0cmluZyhpbnB1dCkpXG4gICAgfSBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdiaWdpbnQnKSB7XG4gICAgICByZWNlaXZlZCA9IFN0cmluZyhpbnB1dClcbiAgICAgIGlmIChpbnB1dCA+IEJpZ0ludCgyKSAqKiBCaWdJbnQoMzIpIHx8IGlucHV0IDwgLShCaWdJbnQoMikgKiogQmlnSW50KDMyKSkpIHtcbiAgICAgICAgcmVjZWl2ZWQgPSBhZGROdW1lcmljYWxTZXBhcmF0b3IocmVjZWl2ZWQpXG4gICAgICB9XG4gICAgICByZWNlaXZlZCArPSAnbidcbiAgICB9XG4gICAgbXNnICs9IGAgSXQgbXVzdCBiZSAke3JhbmdlfS4gUmVjZWl2ZWQgJHtyZWNlaXZlZH1gXG4gICAgcmV0dXJuIG1zZ1xuICB9LCBSYW5nZUVycm9yKVxuXG5mdW5jdGlvbiBhZGROdW1lcmljYWxTZXBhcmF0b3IgKHZhbCkge1xuICBsZXQgcmVzID0gJydcbiAgbGV0IGkgPSB2YWwubGVuZ3RoXG4gIGNvbnN0IHN0YXJ0ID0gdmFsWzBdID09PSAnLScgPyAxIDogMFxuICBmb3IgKDsgaSA+PSBzdGFydCArIDQ7IGkgLT0gMykge1xuICAgIHJlcyA9IGBfJHt2YWwuc2xpY2UoaSAtIDMsIGkpfSR7cmVzfWBcbiAgfVxuICByZXR1cm4gYCR7dmFsLnNsaWNlKDAsIGkpfSR7cmVzfWBcbn1cblxuLy8gQ0hFQ0sgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT1cblxuZnVuY3Rpb24gY2hlY2tCb3VuZHMgKGJ1Ziwgb2Zmc2V0LCBieXRlTGVuZ3RoKSB7XG4gIHZhbGlkYXRlTnVtYmVyKG9mZnNldCwgJ29mZnNldCcpXG4gIGlmIChidWZbb2Zmc2V0XSA9PT0gdW5kZWZpbmVkIHx8IGJ1ZltvZmZzZXQgKyBieXRlTGVuZ3RoXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYm91bmRzRXJyb3Iob2Zmc2V0LCBidWYubGVuZ3RoIC0gKGJ5dGVMZW5ndGggKyAxKSlcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGVja0ludEJJICh2YWx1ZSwgbWluLCBtYXgsIGJ1Ziwgb2Zmc2V0LCBieXRlTGVuZ3RoKSB7XG4gIGlmICh2YWx1ZSA+IG1heCB8fCB2YWx1ZSA8IG1pbikge1xuICAgIGNvbnN0IG4gPSB0eXBlb2YgbWluID09PSAnYmlnaW50JyA/ICduJyA6ICcnXG4gICAgbGV0IHJhbmdlXG4gICAgaWYgKGJ5dGVMZW5ndGggPiAzKSB7XG4gICAgICBpZiAobWluID09PSAwIHx8IG1pbiA9PT0gQmlnSW50KDApKSB7XG4gICAgICAgIHJhbmdlID0gYD49IDAke259IGFuZCA8IDIke259ICoqICR7KGJ5dGVMZW5ndGggKyAxKSAqIDh9JHtufWBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJhbmdlID0gYD49IC0oMiR7bn0gKiogJHsoYnl0ZUxlbmd0aCArIDEpICogOCAtIDF9JHtufSkgYW5kIDwgMiAqKiBgICtcbiAgICAgICAgICAgICAgICBgJHsoYnl0ZUxlbmd0aCArIDEpICogOCAtIDF9JHtufWBcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmFuZ2UgPSBgPj0gJHttaW59JHtufSBhbmQgPD0gJHttYXh9JHtufWBcbiAgICB9XG4gICAgdGhyb3cgbmV3IGVycm9ycy5FUlJfT1VUX09GX1JBTkdFKCd2YWx1ZScsIHJhbmdlLCB2YWx1ZSlcbiAgfVxuICBjaGVja0JvdW5kcyhidWYsIG9mZnNldCwgYnl0ZUxlbmd0aClcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVOdW1iZXIgKHZhbHVlLCBuYW1lKSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInKSB7XG4gICAgdGhyb3cgbmV3IGVycm9ycy5FUlJfSU5WQUxJRF9BUkdfVFlQRShuYW1lLCAnbnVtYmVyJywgdmFsdWUpXG4gIH1cbn1cblxuZnVuY3Rpb24gYm91bmRzRXJyb3IgKHZhbHVlLCBsZW5ndGgsIHR5cGUpIHtcbiAgaWYgKE1hdGguZmxvb3IodmFsdWUpICE9PSB2YWx1ZSkge1xuICAgIHZhbGlkYXRlTnVtYmVyKHZhbHVlLCB0eXBlKVxuICAgIHRocm93IG5ldyBlcnJvcnMuRVJSX09VVF9PRl9SQU5HRSh0eXBlIHx8ICdvZmZzZXQnLCAnYW4gaW50ZWdlcicsIHZhbHVlKVxuICB9XG5cbiAgaWYgKGxlbmd0aCA8IDApIHtcbiAgICB0aHJvdyBuZXcgZXJyb3JzLkVSUl9CVUZGRVJfT1VUX09GX0JPVU5EUygpXG4gIH1cblxuICB0aHJvdyBuZXcgZXJyb3JzLkVSUl9PVVRfT0ZfUkFOR0UodHlwZSB8fCAnb2Zmc2V0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGA+PSAke3R5cGUgPyAxIDogMH0gYW5kIDw9ICR7bGVuZ3RofWAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSlcbn1cblxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PVxuXG5jb25zdCBJTlZBTElEX0JBU0U2NF9SRSA9IC9bXisvMC05QS1aYS16LV9dL2dcblxuZnVuY3Rpb24gYmFzZTY0Y2xlYW4gKHN0cikge1xuICAvLyBOb2RlIHRha2VzIGVxdWFsIHNpZ25zIGFzIGVuZCBvZiB0aGUgQmFzZTY0IGVuY29kaW5nXG4gIHN0ciA9IHN0ci5zcGxpdCgnPScpWzBdXG4gIC8vIE5vZGUgc3RyaXBzIG91dCBpbnZhbGlkIGNoYXJhY3RlcnMgbGlrZSBcXG4gYW5kIFxcdCBmcm9tIHRoZSBzdHJpbmcsIGJhc2U2NC1qcyBkb2VzIG5vdFxuICBzdHIgPSBzdHIudHJpbSgpLnJlcGxhY2UoSU5WQUxJRF9CQVNFNjRfUkUsICcnKVxuICAvLyBOb2RlIGNvbnZlcnRzIHN0cmluZ3Mgd2l0aCBsZW5ndGggPCAyIHRvICcnXG4gIGlmIChzdHIubGVuZ3RoIDwgMikgcmV0dXJuICcnXG4gIC8vIE5vZGUgYWxsb3dzIGZvciBub24tcGFkZGVkIGJhc2U2NCBzdHJpbmdzIChtaXNzaW5nIHRyYWlsaW5nID09PSksIGJhc2U2NC1qcyBkb2VzIG5vdFxuICB3aGlsZSAoc3RyLmxlbmd0aCAlIDQgIT09IDApIHtcbiAgICBzdHIgPSBzdHIgKyAnPSdcbiAgfVxuICByZXR1cm4gc3RyXG59XG5cbmZ1bmN0aW9uIHV0ZjhUb0J5dGVzIChzdHJpbmcsIHVuaXRzKSB7XG4gIHVuaXRzID0gdW5pdHMgfHwgSW5maW5pdHlcbiAgbGV0IGNvZGVQb2ludFxuICBjb25zdCBsZW5ndGggPSBzdHJpbmcubGVuZ3RoXG4gIGxldCBsZWFkU3Vycm9nYXRlID0gbnVsbFxuICBjb25zdCBieXRlcyA9IFtdXG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGNvZGVQb2ludCA9IHN0cmluZy5jaGFyQ29kZUF0KGkpXG5cbiAgICAvLyBpcyBzdXJyb2dhdGUgY29tcG9uZW50XG4gICAgaWYgKGNvZGVQb2ludCA+IDB4RDdGRiAmJiBjb2RlUG9pbnQgPCAweEUwMDApIHtcbiAgICAgIC8vIGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoIWxlYWRTdXJyb2dhdGUpIHtcbiAgICAgICAgLy8gbm8gbGVhZCB5ZXRcbiAgICAgICAgaWYgKGNvZGVQb2ludCA+IDB4REJGRikge1xuICAgICAgICAgIC8vIHVuZXhwZWN0ZWQgdHJhaWxcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9IGVsc2UgaWYgKGkgKyAxID09PSBsZW5ndGgpIHtcbiAgICAgICAgICAvLyB1bnBhaXJlZCBsZWFkXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHZhbGlkIGxlYWRcbiAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIDIgbGVhZHMgaW4gYSByb3dcbiAgICAgIGlmIChjb2RlUG9pbnQgPCAweERDMDApIHtcbiAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy8gdmFsaWQgc3Vycm9nYXRlIHBhaXJcbiAgICAgIGNvZGVQb2ludCA9IChsZWFkU3Vycm9nYXRlIC0gMHhEODAwIDw8IDEwIHwgY29kZVBvaW50IC0gMHhEQzAwKSArIDB4MTAwMDBcbiAgICB9IGVsc2UgaWYgKGxlYWRTdXJyb2dhdGUpIHtcbiAgICAgIC8vIHZhbGlkIGJtcCBjaGFyLCBidXQgbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgIH1cblxuICAgIGxlYWRTdXJyb2dhdGUgPSBudWxsXG5cbiAgICAvLyBlbmNvZGUgdXRmOFxuICAgIGlmIChjb2RlUG9pbnQgPCAweDgwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDEpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goY29kZVBvaW50KVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHg4MDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiB8IDB4QzAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDMpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgfCAweEUwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDExMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSA0KSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHgxMiB8IDB4RjAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29kZSBwb2ludCcpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVzXG59XG5cbmZ1bmN0aW9uIGFzY2lpVG9CeXRlcyAoc3RyKSB7XG4gIGNvbnN0IGJ5dGVBcnJheSA9IFtdXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7XG4gICAgLy8gTm9kZSdzIGNvZGUgc2VlbXMgdG8gYmUgZG9pbmcgdGhpcyBhbmQgbm90ICYgMHg3Ri4uXG4gICAgYnl0ZUFycmF5LnB1c2goc3RyLmNoYXJDb2RlQXQoaSkgJiAweEZGKVxuICB9XG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gdXRmMTZsZVRvQnl0ZXMgKHN0ciwgdW5pdHMpIHtcbiAgbGV0IGMsIGhpLCBsb1xuICBjb25zdCBieXRlQXJyYXkgPSBbXVxuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkge1xuICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuXG4gICAgYyA9IHN0ci5jaGFyQ29kZUF0KGkpXG4gICAgaGkgPSBjID4+IDhcbiAgICBsbyA9IGMgJSAyNTZcbiAgICBieXRlQXJyYXkucHVzaChsbylcbiAgICBieXRlQXJyYXkucHVzaChoaSlcbiAgfVxuXG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gYmFzZTY0VG9CeXRlcyAoc3RyKSB7XG4gIHJldHVybiBiYXNlNjQudG9CeXRlQXJyYXkoYmFzZTY0Y2xlYW4oc3RyKSlcbn1cblxuZnVuY3Rpb24gYmxpdEJ1ZmZlciAoc3JjLCBkc3QsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIGxldCBpXG4gIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGlmICgoaSArIG9mZnNldCA+PSBkc3QubGVuZ3RoKSB8fCAoaSA+PSBzcmMubGVuZ3RoKSkgYnJlYWtcbiAgICBkc3RbaSArIG9mZnNldF0gPSBzcmNbaV1cbiAgfVxuICByZXR1cm4gaVxufVxuXG4vLyBBcnJheUJ1ZmZlciBvciBVaW50OEFycmF5IG9iamVjdHMgZnJvbSBvdGhlciBjb250ZXh0cyAoaS5lLiBpZnJhbWVzKSBkbyBub3QgcGFzc1xuLy8gdGhlIGBpbnN0YW5jZW9mYCBjaGVjayBidXQgdGhleSBzaG91bGQgYmUgdHJlYXRlZCBhcyBvZiB0aGF0IHR5cGUuXG4vLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyL2lzc3Vlcy8xNjZcbmZ1bmN0aW9uIGlzSW5zdGFuY2UgKG9iaiwgdHlwZSkge1xuICByZXR1cm4gb2JqIGluc3RhbmNlb2YgdHlwZSB8fFxuICAgIChvYmogIT0gbnVsbCAmJiBvYmouY29uc3RydWN0b3IgIT0gbnVsbCAmJiBvYmouY29uc3RydWN0b3IubmFtZSAhPSBudWxsICYmXG4gICAgICBvYmouY29uc3RydWN0b3IubmFtZSA9PT0gdHlwZS5uYW1lKVxufVxuZnVuY3Rpb24gbnVtYmVySXNOYU4gKG9iaikge1xuICAvLyBGb3IgSUUxMSBzdXBwb3J0XG4gIHJldHVybiBvYmogIT09IG9iaiAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXNlbGYtY29tcGFyZVxufVxuXG4vLyBDcmVhdGUgbG9va3VwIHRhYmxlIGZvciBgdG9TdHJpbmcoJ2hleCcpYFxuLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlci9pc3N1ZXMvMjE5XG5jb25zdCBoZXhTbGljZUxvb2t1cFRhYmxlID0gKGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgYWxwaGFiZXQgPSAnMDEyMzQ1Njc4OWFiY2RlZidcbiAgY29uc3QgdGFibGUgPSBuZXcgQXJyYXkoMjU2KVxuICBmb3IgKGxldCBpID0gMDsgaSA8IDE2OyArK2kpIHtcbiAgICBjb25zdCBpMTYgPSBpICogMTZcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IDE2OyArK2opIHtcbiAgICAgIHRhYmxlW2kxNiArIGpdID0gYWxwaGFiZXRbaV0gKyBhbHBoYWJldFtqXVxuICAgIH1cbiAgfVxuICByZXR1cm4gdGFibGVcbn0pKClcblxuLy8gUmV0dXJuIG5vdCBmdW5jdGlvbiB3aXRoIEVycm9yIGlmIEJpZ0ludCBub3Qgc3VwcG9ydGVkXG5mdW5jdGlvbiBkZWZpbmVCaWdJbnRNZXRob2QgKGZuKSB7XG4gIHJldHVybiB0eXBlb2YgQmlnSW50ID09PSAndW5kZWZpbmVkJyA/IEJ1ZmZlckJpZ0ludE5vdERlZmluZWQgOiBmblxufVxuXG5mdW5jdGlvbiBCdWZmZXJCaWdJbnROb3REZWZpbmVkICgpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdCaWdJbnQgbm90IHN1cHBvcnRlZCcpXG59XG4iLCIvKiEgaWVlZTc1NC4gQlNELTMtQ2xhdXNlIExpY2Vuc2UuIEZlcm9zcyBBYm91a2hhZGlqZWggPGh0dHBzOi8vZmVyb3NzLm9yZy9vcGVuc291cmNlPiAqL1xuZXhwb3J0cy5yZWFkID0gZnVuY3Rpb24gKGJ1ZmZlciwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG1cbiAgdmFyIGVMZW4gPSAobkJ5dGVzICogOCkgLSBtTGVuIC0gMVxuICB2YXIgZU1heCA9ICgxIDw8IGVMZW4pIC0gMVxuICB2YXIgZUJpYXMgPSBlTWF4ID4+IDFcbiAgdmFyIG5CaXRzID0gLTdcbiAgdmFyIGkgPSBpc0xFID8gKG5CeXRlcyAtIDEpIDogMFxuICB2YXIgZCA9IGlzTEUgPyAtMSA6IDFcbiAgdmFyIHMgPSBidWZmZXJbb2Zmc2V0ICsgaV1cblxuICBpICs9IGRcblxuICBlID0gcyAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKVxuICBzID4+PSAoLW5CaXRzKVxuICBuQml0cyArPSBlTGVuXG4gIGZvciAoOyBuQml0cyA+IDA7IGUgPSAoZSAqIDI1NikgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBtID0gZSAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKVxuICBlID4+PSAoLW5CaXRzKVxuICBuQml0cyArPSBtTGVuXG4gIGZvciAoOyBuQml0cyA+IDA7IG0gPSAobSAqIDI1NikgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXNcbiAgfSBlbHNlIGlmIChlID09PSBlTWF4KSB7XG4gICAgcmV0dXJuIG0gPyBOYU4gOiAoKHMgPyAtMSA6IDEpICogSW5maW5pdHkpXG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKVxuICAgIGUgPSBlIC0gZUJpYXNcbiAgfVxuICByZXR1cm4gKHMgPyAtMSA6IDEpICogbSAqIE1hdGgucG93KDIsIGUgLSBtTGVuKVxufVxuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24gKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjXG4gIHZhciBlTGVuID0gKG5CeXRlcyAqIDgpIC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBydCA9IChtTGVuID09PSAyMyA/IE1hdGgucG93KDIsIC0yNCkgLSBNYXRoLnBvdygyLCAtNzcpIDogMClcbiAgdmFyIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKVxuICB2YXIgZCA9IGlzTEUgPyAxIDogLTFcbiAgdmFyIHMgPSB2YWx1ZSA8IDAgfHwgKHZhbHVlID09PSAwICYmIDEgLyB2YWx1ZSA8IDApID8gMSA6IDBcblxuICB2YWx1ZSA9IE1hdGguYWJzKHZhbHVlKVxuXG4gIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPT09IEluZmluaXR5KSB7XG4gICAgbSA9IGlzTmFOKHZhbHVlKSA/IDEgOiAwXG4gICAgZSA9IGVNYXhcbiAgfSBlbHNlIHtcbiAgICBlID0gTWF0aC5mbG9vcihNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMilcbiAgICBpZiAodmFsdWUgKiAoYyA9IE1hdGgucG93KDIsIC1lKSkgPCAxKSB7XG4gICAgICBlLS1cbiAgICAgIGMgKj0gMlxuICAgIH1cbiAgICBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIHZhbHVlICs9IHJ0IC8gY1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZSArPSBydCAqIE1hdGgucG93KDIsIDEgLSBlQmlhcylcbiAgICB9XG4gICAgaWYgKHZhbHVlICogYyA+PSAyKSB7XG4gICAgICBlKytcbiAgICAgIGMgLz0gMlxuICAgIH1cblxuICAgIGlmIChlICsgZUJpYXMgPj0gZU1heCkge1xuICAgICAgbSA9IDBcbiAgICAgIGUgPSBlTWF4XG4gICAgfSBlbHNlIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgbSA9ICgodmFsdWUgKiBjKSAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSBlICsgZUJpYXNcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IHZhbHVlICogTWF0aC5wb3coMiwgZUJpYXMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gMFxuICAgIH1cbiAgfVxuXG4gIGZvciAoOyBtTGVuID49IDg7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IG0gJiAweGZmLCBpICs9IGQsIG0gLz0gMjU2LCBtTGVuIC09IDgpIHt9XG5cbiAgZSA9IChlIDw8IG1MZW4pIHwgbVxuICBlTGVuICs9IG1MZW5cbiAgZm9yICg7IGVMZW4gPiAwOyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBlICYgMHhmZiwgaSArPSBkLCBlIC89IDI1NiwgZUxlbiAtPSA4KSB7fVxuXG4gIGJ1ZmZlcltvZmZzZXQgKyBpIC0gZF0gfD0gcyAqIDEyOFxufVxuIiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBDdXN0b21TZXR0aW5ncyB9IGZyb20gXCIuL3NoYXBlc1wiO1xuXG4vKipcbiAqIExvYWQgdGhlIGN1c3RvbVNldHRpbmdzIHNlY3Rpb24gZnJvbSB0aGUgYXBwbGljYXRpb24gbWFuaWZlc3QuXG4gKiBAcmV0dXJucyBUaGUgY3VzdG9tIHNldHRpbmdzIGZyb20gdGhlIG1hbmlmZXN0LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0TWFuaWZlc3RDdXN0b21TZXR0aW5ncygpOiBQcm9taXNlPEN1c3RvbVNldHRpbmdzIHwgdW5kZWZpbmVkPiB7XG5cdGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdGNvbnN0IG1hbmlmZXN0OiBPcGVuRmluLk1hbmlmZXN0ICYgeyBjdXN0b21TZXR0aW5ncz86IEN1c3RvbVNldHRpbmdzIH0gPSBhd2FpdCBhcHAuZ2V0TWFuaWZlc3QoKTtcblx0cmV0dXJuIG1hbmlmZXN0LmN1c3RvbVNldHRpbmdzO1xufVxuIiwiLy8gVGhlIG1vZHVsZSBjYWNoZVxudmFyIF9fd2VicGFja19tb2R1bGVfY2FjaGVfXyA9IHt9O1xuXG4vLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcblx0dmFyIGNhY2hlZE1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF07XG5cdGlmIChjYWNoZWRNb2R1bGUgIT09IHVuZGVmaW5lZCkge1xuXHRcdHJldHVybiBjYWNoZWRNb2R1bGUuZXhwb3J0cztcblx0fVxuXHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuXHR2YXIgbW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXSA9IHtcblx0XHQvLyBubyBtb2R1bGUuaWQgbmVlZGVkXG5cdFx0Ly8gbm8gbW9kdWxlLmxvYWRlZCBuZWVkZWRcblx0XHRleHBvcnRzOiB7fVxuXHR9O1xuXG5cdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuXHRfX3dlYnBhY2tfbW9kdWxlc19fW21vZHVsZUlkXShtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuXHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuXHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG59XG5cbiIsIl9fd2VicGFja19yZXF1aXJlX18uYW1kTyA9IHt9OyIsIi8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18uZyA9IChmdW5jdGlvbigpIHtcblx0aWYgKHR5cGVvZiBnbG9iYWxUaGlzID09PSAnb2JqZWN0JykgcmV0dXJuIGdsb2JhbFRoaXM7XG5cdHRyeSB7XG5cdFx0cmV0dXJuIHRoaXMgfHwgbmV3IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcpIHJldHVybiB3aW5kb3c7XG5cdH1cbn0pKCk7IiwiX193ZWJwYWNrX3JlcXVpcmVfXy5vID0gKG9iaiwgcHJvcCkgPT4gKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKSIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsImltcG9ydCB7IGNsb3VkSW50ZXJvcE92ZXJyaWRlIH0gZnJvbSBcIkBvcGVuZmluL2Nsb3VkLWludGVyb3BcIjtcbmltcG9ydCB0eXBlIE9wZW5GaW4gZnJvbSBcIkBvcGVuZmluL2NvcmVcIjtcbmltcG9ydCB7IGdldE1hbmlmZXN0Q3VzdG9tU2V0dGluZ3MgfSBmcm9tIFwiLi9zZXR0aW5nc1wiO1xuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgYXN5bmMgKCkgPT4ge1xuXHRjb25zdCBjdXN0b21TZXR0aW5ncyA9IGF3YWl0IGdldE1hbmlmZXN0Q3VzdG9tU2V0dGluZ3MoKTtcblx0Y29uc3QgaW50ZXJvcE92ZXJyaWRlcyA9IFtdO1xuXG5cdGlmIChjdXN0b21TZXR0aW5ncz8uY2xvdWRJbnRlcm9wUHJvdmlkZXI/LmVuYWJsZWQpIHtcblx0XHRjb25zdCBpbml0aWFsaXplZENsb3VkSW50ZXJvcE92ZXJyaWRlID0gKGF3YWl0IGNsb3VkSW50ZXJvcE92ZXJyaWRlKFxuXHRcdFx0Y3VzdG9tU2V0dGluZ3M/LmNsb3VkSW50ZXJvcFByb3ZpZGVyPy5jb25uZWN0UGFyYW1zXG5cdFx0KSkgYXMgdW5rbm93biBhcyBPcGVuRmluLkNvbnN0cnVjdG9yT3ZlcnJpZGU8T3BlbkZpbi5JbnRlcm9wQnJva2VyPjtcblx0XHRpbnRlcm9wT3ZlcnJpZGVzLnB1c2goaW5pdGlhbGl6ZWRDbG91ZEludGVyb3BPdmVycmlkZSk7XG5cdH1cblx0ZmluLlBsYXRmb3JtLmluaXQoeyBpbnRlcm9wT3ZlcnJpZGU6IGludGVyb3BPdmVycmlkZXMgfSkuY2F0Y2goKGVycm9yKSA9PiBjb25zb2xlLmVycm9yKGVycm9yKSk7XG59KTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-interop-cloud-interop/js/window.bundle.js b/dev/john/update-logging-example/use-interop-cloud-interop/js/window.bundle.js new file mode 100644 index 00000000..a12b0068 --- /dev/null +++ b/dev/john/update-logging-example/use-interop-cloud-interop/js/window.bundle.js @@ -0,0 +1,146 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!******************************!*\ + !*** ./client/src/window.ts ***! + \******************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ CONTAINER_ID: () => (/* binding */ CONTAINER_ID) +/* harmony export */ }); +const CONTAINER_ID = "layout-container"; +const openfinWindow = fin.Window.getCurrentSync(); +const openfinApplication = fin.Application.getCurrentSync(); +let lastFocusedView; +openfinApplication + .on("view-focused", (viewEvent) => { + lastFocusedView = viewEvent.viewIdentity; +}) + .catch((error) => console.error(error)); +window.addEventListener("DOMContentLoaded", async () => { + await fin.Platform.Layout.init({ containerId: CONTAINER_ID }); + await setupTitleBar(); +}); +/** + * Setup the content for the title bar. + */ +async function setupTitleBar() { + const title = document.querySelector("#title"); + const minBtn = document.querySelector("#minimize-button"); + const maxBtn = document.querySelector("#expand-button"); + const closeBtn = document.querySelector("#close-button"); + if (title && minBtn && maxBtn && closeBtn) { + title.innerHTML = fin.me.identity.uuid; + minBtn.addEventListener("click", minimizeWindow); + maxBtn.addEventListener("click", maxOrRestore); + closeBtn.addEventListener("click", closeWindow); + } + await addContextGroupButtons(); +} +/** + * Joins a context group by passing in the top-level variable `lastFocusedView` as the `target` parameter of the `joinContextGroup` function. + * @param event - DOM click event that is passed in to the button click event from `addContextGroupButtons` local `newButton` variable + */ +async function changeContextGroup(event) { + const selectedColorElement = event.target; + const color = selectedColorElement.title; + await fin.me.interop.joinContextGroup(color, lastFocusedView); + const contextGroups = await fin.me.interop.getContextGroups(); + const focusedTab = document.querySelector(`#tab-${lastFocusedView.name}`); + if (focusedTab) { + focusedTab.classList.remove(...contextGroups.map(({ displayMetadata }) => `${displayMetadata?.name}-channel`)); + } + const focusedView = document.querySelector(`#tab-${lastFocusedView.name}`); + if (focusedView) { + focusedView.classList.add(`${color}-channel`); + } +} +/** + * Add the context group buttons. + * 1. Retrieves a Platform's interop context groups. + * 2. Iterates all context groups and creates a corresponding button per context group (color channel). + * 3. Adds a click listener to each button with the `changeContextGroup` function as the listener callback. + */ +async function addContextGroupButtons() { + const contextGroups = await fin.me.interop.getContextGroups(); + const windowFrameStyleSheet = document.styleSheets[0]; + const buttonsWrapper = document.querySelector("#buttons-wrapper"); + if (buttonsWrapper) { + for (const systemChannel of contextGroups) { + const nm = systemChannel.displayMetadata?.name; + const col = systemChannel.displayMetadata?.color; + if (nm && col) { + windowFrameStyleSheet.insertRule(`.${nm}-channel { border-left: 2px solid ${col} !important;}`); + windowFrameStyleSheet.insertRule(`#${nm}-button:after { background-color: ${col}}`); + const newButton = document.createElement("div"); + newButton.classList.add("button"); + newButton.classList.add("channel-button"); + newButton.id = `${nm}-button`; + newButton.title = nm; + newButton.addEventListener("click", changeContextGroup); + buttonsWrapper.prepend(newButton); + } + } + } +} +/** + * Maximize or restore the window. + * @returns Nothing. + */ +async function maxOrRestore() { + if ((await openfinWindow.getState()) === "normal") { + return openfinWindow.maximize(); + } + return openfinWindow.restore(); +} +/** + * Close the window. + * @returns Nothing. + */ +async function closeWindow() { + return openfinWindow.close(); +} +/** + * Minimize the window. + * @returns Nothing. + */ +async function minimizeWindow() { + return openfinWindow.minimize(); +} + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDbEMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztnQkFDMUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxHQUFHLEVBQUUsU0FBUyxDQUFDO2dCQUM5QixTQUFTLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztnQkFDckIsU0FBUyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO2dCQUN4RCxjQUFjLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ25DLENBQUM7UUFDRixDQUFDO0lBQ0YsQ0FBQztBQUNGLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxLQUFLLFVBQVUsWUFBWTtJQUMxQixJQUFJLENBQUMsTUFBTSxhQUFhLENBQUMsUUFBUSxFQUFFLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNuRCxPQUFPLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNqQyxDQUFDO0lBRUQsT0FBTyxhQUFhLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDaEMsQ0FBQztBQUVEOzs7R0FHRztBQUNILEtBQUssVUFBVSxXQUFXO0lBQ3pCLE9BQU8sYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQzlCLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxLQUFLLFVBQVUsY0FBYztJQUM1QixPQUFPLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUNqQyxDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vY29udGFpbmVyLXN0YXJ0ZXItdXNlLWludGVyb3AtLWNsb3VkLWludGVyb3Avd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vY29udGFpbmVyLXN0YXJ0ZXItdXNlLWludGVyb3AtLWNsb3VkLWludGVyb3Avd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzIiwid2VicGFjazovL2NvbnRhaW5lci1zdGFydGVyLXVzZS1pbnRlcm9wLS1jbG91ZC1pbnRlcm9wL3dlYnBhY2svcnVudGltZS9oYXNPd25Qcm9wZXJ0eSBzaG9ydGhhbmQiLCJ3ZWJwYWNrOi8vY29udGFpbmVyLXN0YXJ0ZXItdXNlLWludGVyb3AtLWNsb3VkLWludGVyb3Avd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9jb250YWluZXItc3RhcnRlci11c2UtaW50ZXJvcC0tY2xvdWQtaW50ZXJvcC8uL2NsaWVudC9zcmMvd2luZG93LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSByZXF1aXJlIHNjb3BlXG52YXIgX193ZWJwYWNrX3JlcXVpcmVfXyA9IHt9O1xuXG4iLCIvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9ucyBmb3IgaGFybW9ueSBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSAoZXhwb3J0cywgZGVmaW5pdGlvbikgPT4ge1xuXHRmb3IodmFyIGtleSBpbiBkZWZpbml0aW9uKSB7XG5cdFx0aWYoX193ZWJwYWNrX3JlcXVpcmVfXy5vKGRlZmluaXRpb24sIGtleSkgJiYgIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBrZXkpKSB7XG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywga2V5LCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZGVmaW5pdGlvbltrZXldIH0pO1xuXHRcdH1cblx0fVxufTsiLCJfX3dlYnBhY2tfcmVxdWlyZV9fLm8gPSAob2JqLCBwcm9wKSA9PiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCkpIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuXG5leHBvcnQgY29uc3QgQ09OVEFJTkVSX0lEID0gXCJsYXlvdXQtY29udGFpbmVyXCI7XG5jb25zdCBvcGVuZmluV2luZG93OiBPcGVuRmluLldpbmRvdyA9IGZpbi5XaW5kb3cuZ2V0Q3VycmVudFN5bmMoKTtcbmNvbnN0IG9wZW5maW5BcHBsaWNhdGlvbjogT3BlbkZpbi5BcHBsaWNhdGlvbiA9IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50U3luYygpO1xuXG5sZXQgbGFzdEZvY3VzZWRWaWV3OiBPcGVuRmluLklkZW50aXR5O1xuXG5vcGVuZmluQXBwbGljYXRpb25cblx0Lm9uKFwidmlldy1mb2N1c2VkXCIsICh2aWV3RXZlbnQpOiB2b2lkID0+IHtcblx0XHRsYXN0Rm9jdXNlZFZpZXcgPSB2aWV3RXZlbnQudmlld0lkZW50aXR5O1xuXHR9KVxuXHQuY2F0Y2goKGVycm9yKSA9PiBjb25zb2xlLmVycm9yKGVycm9yKSk7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBhc3luYyAoKSA9PiB7XG5cdGF3YWl0IGZpbi5QbGF0Zm9ybS5MYXlvdXQuaW5pdCh7IGNvbnRhaW5lcklkOiBDT05UQUlORVJfSUQgfSk7XG5cdGF3YWl0IHNldHVwVGl0bGVCYXIoKTtcbn0pO1xuXG4vKipcbiAqIFNldHVwIHRoZSBjb250ZW50IGZvciB0aGUgdGl0bGUgYmFyLlxuICovXG5hc3luYyBmdW5jdGlvbiBzZXR1cFRpdGxlQmFyKCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCB0aXRsZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjdGl0bGVcIik7XG5cdGNvbnN0IG1pbkJ0biA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjbWluaW1pemUtYnV0dG9uXCIpO1xuXHRjb25zdCBtYXhCdG4gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2V4cGFuZC1idXR0b25cIik7XG5cdGNvbnN0IGNsb3NlQnRuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNjbG9zZS1idXR0b25cIik7XG5cblx0aWYgKHRpdGxlICYmIG1pbkJ0biAmJiBtYXhCdG4gJiYgY2xvc2VCdG4pIHtcblx0XHR0aXRsZS5pbm5lckhUTUwgPSBmaW4ubWUuaWRlbnRpdHkudXVpZDtcblxuXHRcdG1pbkJ0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgbWluaW1pemVXaW5kb3cpO1xuXHRcdG1heEJ0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgbWF4T3JSZXN0b3JlKTtcblx0XHRjbG9zZUJ0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgY2xvc2VXaW5kb3cpO1xuXHR9XG5cblx0YXdhaXQgYWRkQ29udGV4dEdyb3VwQnV0dG9ucygpO1xufVxuXG4vKipcbiAqIEpvaW5zIGEgY29udGV4dCBncm91cCBieSBwYXNzaW5nIGluIHRoZSB0b3AtbGV2ZWwgdmFyaWFibGUgYGxhc3RGb2N1c2VkVmlld2AgYXMgdGhlIGB0YXJnZXRgIHBhcmFtZXRlciBvZiB0aGUgYGpvaW5Db250ZXh0R3JvdXBgIGZ1bmN0aW9uLlxuICogQHBhcmFtIGV2ZW50IC0gRE9NIGNsaWNrIGV2ZW50IHRoYXQgaXMgcGFzc2VkIGluIHRvIHRoZSBidXR0b24gY2xpY2sgZXZlbnQgZnJvbSBgYWRkQ29udGV4dEdyb3VwQnV0dG9uc2AgbG9jYWwgYG5ld0J1dHRvbmAgdmFyaWFibGVcbiAqL1xuYXN5bmMgZnVuY3Rpb24gY2hhbmdlQ29udGV4dEdyb3VwKGV2ZW50OiBFdmVudCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBzZWxlY3RlZENvbG9yRWxlbWVudDogSFRNTEVsZW1lbnQgPSBldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQ7XG5cdGNvbnN0IGNvbG9yOiBzdHJpbmcgPSBzZWxlY3RlZENvbG9yRWxlbWVudC50aXRsZTtcblx0YXdhaXQgZmluLm1lLmludGVyb3Auam9pbkNvbnRleHRHcm91cChjb2xvciwgbGFzdEZvY3VzZWRWaWV3KTtcblx0Y29uc3QgY29udGV4dEdyb3VwczogT3BlbkZpbi5Db250ZXh0R3JvdXBJbmZvW10gPSBhd2FpdCBmaW4ubWUuaW50ZXJvcC5nZXRDb250ZXh0R3JvdXBzKCk7XG5cdGNvbnN0IGZvY3VzZWRUYWIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGAjdGFiLSR7bGFzdEZvY3VzZWRWaWV3Lm5hbWV9YCk7XG5cdGlmIChmb2N1c2VkVGFiKSB7XG5cdFx0Zm9jdXNlZFRhYi5jbGFzc0xpc3QucmVtb3ZlKFxuXHRcdFx0Li4uY29udGV4dEdyb3Vwcy5tYXAoXG5cdFx0XHRcdCh7IGRpc3BsYXlNZXRhZGF0YSB9OiBPcGVuRmluLkNvbnRleHRHcm91cEluZm8pID0+IGAke2Rpc3BsYXlNZXRhZGF0YT8ubmFtZX0tY2hhbm5lbGBcblx0XHRcdClcblx0XHQpO1xuXHR9XG5cdGNvbnN0IGZvY3VzZWRWaWV3ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihgI3RhYi0ke2xhc3RGb2N1c2VkVmlldy5uYW1lfWApO1xuXHRpZiAoZm9jdXNlZFZpZXcpIHtcblx0XHRmb2N1c2VkVmlldy5jbGFzc0xpc3QuYWRkKGAke2NvbG9yfS1jaGFubmVsYCk7XG5cdH1cbn1cblxuLyoqXG4gKiBBZGQgdGhlIGNvbnRleHQgZ3JvdXAgYnV0dG9ucy5cbiAqIDEuIFJldHJpZXZlcyBhIFBsYXRmb3JtJ3MgaW50ZXJvcCBjb250ZXh0IGdyb3Vwcy5cbiAqIDIuIEl0ZXJhdGVzIGFsbCBjb250ZXh0IGdyb3VwcyBhbmQgY3JlYXRlcyBhIGNvcnJlc3BvbmRpbmcgYnV0dG9uIHBlciBjb250ZXh0IGdyb3VwIChjb2xvciBjaGFubmVsKS5cbiAqIDMuIEFkZHMgYSBjbGljayBsaXN0ZW5lciB0byBlYWNoIGJ1dHRvbiB3aXRoIHRoZSBgY2hhbmdlQ29udGV4dEdyb3VwYCBmdW5jdGlvbiBhcyB0aGUgbGlzdGVuZXIgY2FsbGJhY2suXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGFkZENvbnRleHRHcm91cEJ1dHRvbnMoKTogUHJvbWlzZTx2b2lkPiB7XG5cdGNvbnN0IGNvbnRleHRHcm91cHM6IE9wZW5GaW4uQ29udGV4dEdyb3VwSW5mb1tdID0gYXdhaXQgZmluLm1lLmludGVyb3AuZ2V0Q29udGV4dEdyb3VwcygpO1xuXHRjb25zdCB3aW5kb3dGcmFtZVN0eWxlU2hlZXQ6IENTU1N0eWxlU2hlZXQgPSBkb2N1bWVudC5zdHlsZVNoZWV0c1swXTtcblx0Y29uc3QgYnV0dG9uc1dyYXBwZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxFbGVtZW50PihcIiNidXR0b25zLXdyYXBwZXJcIik7XG5cdGlmIChidXR0b25zV3JhcHBlcikge1xuXHRcdGZvciAoY29uc3Qgc3lzdGVtQ2hhbm5lbCBvZiBjb250ZXh0R3JvdXBzKSB7XG5cdFx0XHRjb25zdCBubSA9IHN5c3RlbUNoYW5uZWwuZGlzcGxheU1ldGFkYXRhPy5uYW1lO1xuXHRcdFx0Y29uc3QgY29sID0gc3lzdGVtQ2hhbm5lbC5kaXNwbGF5TWV0YWRhdGE/LmNvbG9yO1xuXHRcdFx0aWYgKG5tICYmIGNvbCkge1xuXHRcdFx0XHR3aW5kb3dGcmFtZVN0eWxlU2hlZXQuaW5zZXJ0UnVsZShgLiR7bm19LWNoYW5uZWwgeyBib3JkZXItbGVmdDogMnB4IHNvbGlkICR7Y29sfSAhaW1wb3J0YW50O31gKTtcblx0XHRcdFx0d2luZG93RnJhbWVTdHlsZVNoZWV0Lmluc2VydFJ1bGUoYCMke25tfS1idXR0b246YWZ0ZXIgeyBiYWNrZ3JvdW5kLWNvbG9yOiAke2NvbH19YCk7XG5cdFx0XHRcdGNvbnN0IG5ld0J1dHRvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG5cdFx0XHRcdG5ld0J1dHRvbi5jbGFzc0xpc3QuYWRkKFwiYnV0dG9uXCIpO1xuXHRcdFx0XHRuZXdCdXR0b24uY2xhc3NMaXN0LmFkZChcImNoYW5uZWwtYnV0dG9uXCIpO1xuXHRcdFx0XHRuZXdCdXR0b24uaWQgPSBgJHtubX0tYnV0dG9uYDtcblx0XHRcdFx0bmV3QnV0dG9uLnRpdGxlID0gbm07XG5cdFx0XHRcdG5ld0J1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgY2hhbmdlQ29udGV4dEdyb3VwKTtcblx0XHRcdFx0YnV0dG9uc1dyYXBwZXIucHJlcGVuZChuZXdCdXR0b24pO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIE1heGltaXplIG9yIHJlc3RvcmUgdGhlIHdpbmRvdy5cbiAqIEByZXR1cm5zIE5vdGhpbmcuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIG1heE9yUmVzdG9yZSgpOiBQcm9taXNlPHZvaWQ+IHtcblx0aWYgKChhd2FpdCBvcGVuZmluV2luZG93LmdldFN0YXRlKCkpID09PSBcIm5vcm1hbFwiKSB7XG5cdFx0cmV0dXJuIG9wZW5maW5XaW5kb3cubWF4aW1pemUoKTtcblx0fVxuXG5cdHJldHVybiBvcGVuZmluV2luZG93LnJlc3RvcmUoKTtcbn1cblxuLyoqXG4gKiBDbG9zZSB0aGUgd2luZG93LlxuICogQHJldHVybnMgTm90aGluZy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gY2xvc2VXaW5kb3coKTogUHJvbWlzZTx2b2lkPiB7XG5cdHJldHVybiBvcGVuZmluV2luZG93LmNsb3NlKCk7XG59XG5cbi8qKlxuICogTWluaW1pemUgdGhlIHdpbmRvdy5cbiAqIEByZXR1cm5zIE5vdGhpbmcuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIG1pbmltaXplV2luZG93KCk6IFByb21pc2U8dm9pZD4ge1xuXHRyZXR1cm4gb3BlbmZpbldpbmRvdy5taW5pbWl6ZSgpO1xufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dev/john/update-logging-example/use-interop-cloud-interop/manifest.fin.json b/dev/john/update-logging-example/use-interop-cloud-interop/manifest.fin.json new file mode 100644 index 00000000..7d39a97d --- /dev/null +++ b/dev/john/update-logging-example/use-interop-cloud-interop/manifest.fin.json @@ -0,0 +1,65 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect --enable-mesh --security-realm=container-interop-use-cloud-platform1", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "platform-1", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-interop-cloud-interop/favicon.ico", + "autoShow": false, + "providerUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-interop-cloud-interop/html/provider.html", + "defaultWindowOptions": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-interop-cloud-interop/html/window.html", + "contextMenu": true, + "defaultWidth": 1100, + "defaultHeight": 700, + "minHeight": 700, + "minWidth": 900, + "height": 700, + "width": 1100 + } + }, + "snapshot": { + "windows": [ + { + "name": "window1", + "layout": { + "content": [ + { + "type": "row", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/interop-api/context/interop-broadcast-view.html" + } + }, + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/interop-api/context/interop-broadcast-view.html" + } + } + ] + } + ] + } + } + ] + }, + "customSettings": { + "cloudInteropProvider": { + "enabled": false, + "connectParams": { + "url": "", + "userId": "", + "password": "", + "platformId": "cloud-interop", + "sourceId": "platform1", + "sourceDisplayName": "Platform 1" + } + } + } +} diff --git a/dev/john/update-logging-example/use-interop-cloud-interop/second.manifest.fin.json b/dev/john/update-logging-example/use-interop-cloud-interop/second.manifest.fin.json new file mode 100644 index 00000000..feac44fd --- /dev/null +++ b/dev/john/update-logging-example/use-interop-cloud-interop/second.manifest.fin.json @@ -0,0 +1,68 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect --enable-mesh --security-realm=container-interop-use-cloud-platform2", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "platform-2", + "icon": "https://openfin.github.io/golden-prototype/favicon.ico", + "autoShow": false, + "providerUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-interop-cloud-interop/html/provider.html", + "defaultWindowOptions": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-interop-cloud-interop/html/window.html", + "contextMenu": true, + "defaultWidth": 1100, + "defaultHeight": 700, + "minHeight": 700, + "minWidth": 700, + "height": 700, + "width": 1100 + }, + "defaultViewOptions": { + "fdc3InteropApi": "2.0" + } + }, + "snapshot": { + "windows": [ + { + "name": "view", + "layout": { + "content": [ + { + "type": "row", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/fdc3/context/fdc3-broadcast-view.html" + } + }, + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/interop-api/context/interop-broadcast-view.html" + } + } + ] + } + ] + } + } + ] + }, + "customSettings": { + "cloudInteropProvider": { + "enabled": false, + "connectParams": { + "url": "", + "userId": "", + "password": "", + "platformId": "cloud-interop", + "sourceId": "platform2", + "sourceDisplayName": "Platform 2" + } + } + } +} diff --git a/dev/john/update-logging-example/use-interop-cloud-interop/styles/frame-styles.css b/dev/john/update-logging-example/use-interop-cloud-interop/styles/frame-styles.css new file mode 100644 index 00000000..14b7200b --- /dev/null +++ b/dev/john/update-logging-example/use-interop-cloud-interop/styles/frame-styles.css @@ -0,0 +1,30 @@ +#body-container { + display: flex; + transition: 0.8s; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; + height: 96%; + width: 100%; +} + +.face { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + z-index: 1; +} + +.channel-button:after { + content: ''; + padding: 5px; + display: inline-block; + margin-left: 10px; + margin-top: 10px; +} + +#title { + color: var(--body-font-color); + margin: 0px; +} diff --git a/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/common/images/icon-blue.png b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/common/style/app.css b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/favicon.ico b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/favicon.ico differ diff --git a/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/html/provider.html b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/html/provider.html new file mode 100644 index 00000000..91029415 --- /dev/null +++ b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/html/provider.html @@ -0,0 +1,17 @@ + + + + + + OpenFin Template + + + + + + +
+

Platform Provider

+
+ + diff --git a/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/html/window.html b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/html/window.html new file mode 100644 index 00000000..4a3e7430 --- /dev/null +++ b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/html/window.html @@ -0,0 +1,29 @@ + + + + + + + Interop + + + + + +
+ +
+

+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/js/provider.bundle.js b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/js/provider.bundle.js new file mode 100644 index 00000000..259827ae --- /dev/null +++ b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/js/provider.bundle.js @@ -0,0 +1,164 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!********************************!*\ + !*** ./client/src/provider.ts ***! + \********************************/ +__webpack_require__.r(__webpack_exports__); +/** + * Override the interop broker. + * @param InteropBroker class used to extend the custom override subclass. + * @returns The override. + */ +function interopOverride(InteropBroker) { + /** + * Class that inherits the public InteropBroker methods that allows you to override existing + * InteropBroker methods and add any custom logic to the returned InteropBroker instance used by your platform. + */ + class Override extends InteropBroker { + /** + * Initialize and connect to external broker. + */ + constructor() { + super(); + this.externalBroker = "platform-2"; + this.externalClients = new Map(); + this.initializeBrokers().catch((error) => console.error(error)); + } + /** + * Initialize the brokers. + * 1. Gets the instance of the specified external platform. + * 2. Ensure the external platform application is running. + * 3. Ensure that the platform api is finished initializing. + * 4. Reset the map tracking the externalClient connections. + */ + async initializeBrokers() { + const platform = fin.Platform.wrapSync({ uuid: this.externalBroker }); + if (await platform.Application.isRunning()) { + await this.setupContextGroups(); + } + await platform.on("platform-api-ready", async () => { + await this.setupContextGroups(); + }); + await platform.Application.once("closed", () => { + this.externalClients = new Map(); + }); + } + /** + * Setup the context groups + * 1. Create a InteropClient instance by connecting to a member of Override.externalBrokers. + * 2. externalContextGroups: using the created client instance, retrieve the externalBroker's context groups. + * 3. Create a InteropClient instance by connecting to the current platforms interop broker. + * 4. PlatformContextGroups: using the created client instance, retrieve the current platform context groups. + * 5. Check to which externalContextGroups and platformContextGroups are the same. + * 6. If the platformContextGroup is shared with an externalContextGroup create a colorClient and join the shared context group from the colorClient. + * 7. Create a context handler for the colorClient. + */ + async setupContextGroups() { + const externalInteropClient = fin.Interop.connectSync(this.externalBroker, {}); + const externalContextGroups = await externalInteropClient.getContextGroups(); + const platformInteropClient = fin.Interop.connectSync(fin.me.uuid, {}); + const platformContextGroups = await platformInteropClient.getContextGroups(); + // Array of ExternalClientMap Promises + const externalContextGroupPromises = externalContextGroups.map(async (externalContextGroupInfo) => { + // check to see if a Platform Client's context group has any of the channels as a externalContextGroup + const hasPlatformContextGroup = platformContextGroups.some(({ id }) => id === externalContextGroupInfo.id); + if (hasPlatformContextGroup) { + const colorClient = fin.Interop.connectSync(this.externalBroker, {}); + await colorClient.joinContextGroup(externalContextGroupInfo.id); + /** + * Handle a context. + * @param context object passed from the setContext method. + * If the newContext variable has a _clientInfo object with a uuid return the context as is + * because it is initially set on the platformInteropClient's broker. + * otherwise copy the context attributes and values to a new object containing + * a _clientInfo attribute with the uuid of the connected externalBroker. + */ + const contextHandler = async (context) => { + await platformInteropClient.joinContextGroup(externalContextGroupInfo.id); + const newContext = context._clientInfo?.uuid + ? context + : { ...context, _clientInfo: { uuid: this.externalBroker } }; + await platformInteropClient.setContext(newContext); + }; + await colorClient.addContextHandler(contextHandler); + // return the connected context group and corresponded color client. + return this.externalClients.set(externalContextGroupInfo.id, colorClient); + } + }); + try { + await Promise.all(externalContextGroupPromises); + } + catch (error) { + throw new Error(`Not able to setup handlers for external brokers: ${error}`); + } + } + /** + * Set the context on an external client. + * if the externalClientsMap has previously derived contextGroup get the corresponding + * colorClient and set the context on the matching colorClient. + * @param context context object passed in from the @setContext method. + * @param clientIdentity clientIdentity object passed in from the @setContext method. + */ + async setContextOnExternalClient(context, clientIdentity) { + // use accessor syntax for this.getClientState as it is not a public inherited method from InteropBroker + // eslint-disable-next-line @typescript-eslint/dot-notation + const state = this["getClientState"](clientIdentity); + const ctxGroupId = state.contextGroupId; + if (this.externalClients.has(ctxGroupId)) { + const colorClient = this.externalClients.get(ctxGroupId); + if (colorClient) { + await colorClient.setContext(context); + } + } + } + /** + * Set the context. + * @param payload object that is passed in when set context is called from an OpenFin entity using the interop api. + * @param payload.context The context for the payload. + * @param clientIdentity object containing the clientIdentity of the sender. + */ + async setContext(payload, clientIdentity) { + // create a new context object for interop setContext calls from the interop object within the Platform Client's windows or views. + const { context } = payload; + if (context._clientInfo) { + const { _clientInfo: { uuid } } = context; + // set context on external broker + if ((uuid !== fin.me.uuid && uuid !== this.externalBroker) || uuid === this.externalBroker) { + const newContext = context; + delete newContext._clientInfo; + super.setContext({ ...payload, context: newContext }, clientIdentity); + } + } + else { + // If there is no _clientInfo object present on the context object we treat it as a brand new object and set it on both the platform and external clients. + const newContext = { ...context, _clientInfo: { uuid: fin.me.uuid } }; + await this.setContextOnExternalClient(newContext, clientIdentity); + super.setContext(payload, clientIdentity); + } + } + } + return new Override(); +} +fin.Platform.init({ interopOverride }).catch((error) => console.error(error)); + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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Q0YsQ0FBQztLQUNEO0lBQ0QsT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO0FBQ3ZCLENBQUM7QUFFRCxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLGVBQWUsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9zZXR1cC1jcm9zcy1wbGF0Zm9ybS1pbnRlcm9wL3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL3NldHVwLWNyb3NzLXBsYXRmb3JtLWludGVyb3Avd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9zZXR1cC1jcm9zcy1wbGF0Zm9ybS1pbnRlcm9wLy4vY2xpZW50L3NyYy9wcm92aWRlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBFeHRlcm5hbENsaWVudE1hcCwgRXh0ZXJuYWxDb250ZXh0IH0gZnJvbSBcIi4vc2hhcGVzXCI7XG5cbi8qKlxuICogT3ZlcnJpZGUgdGhlIGludGVyb3AgYnJva2VyLlxuICogQHBhcmFtIEludGVyb3BCcm9rZXIgY2xhc3MgdXNlZCB0byBleHRlbmQgdGhlIGN1c3RvbSBvdmVycmlkZSBzdWJjbGFzcy5cbiAqIEByZXR1cm5zIFRoZSBvdmVycmlkZS5cbiAqL1xuZnVuY3Rpb24gaW50ZXJvcE92ZXJyaWRlKEludGVyb3BCcm9rZXI6IE9wZW5GaW4uQ29uc3RydWN0b3I8T3BlbkZpbi5JbnRlcm9wQnJva2VyPik6IE9wZW5GaW4uSW50ZXJvcEJyb2tlciB7XG5cdC8qKlxuXHQgKiBDbGFzcyB0aGF0IGluaGVyaXRzIHRoZSBwdWJsaWMgSW50ZXJvcEJyb2tlciBtZXRob2RzIHRoYXQgYWxsb3dzIHlvdSB0byBvdmVycmlkZSBleGlzdGluZ1xuXHQgKiBJbnRlcm9wQnJva2VyIG1ldGhvZHMgYW5kIGFkZCBhbnkgY3VzdG9tIGxvZ2ljIHRvIHRoZSByZXR1cm5lZCBJbnRlcm9wQnJva2VyIGluc3RhbmNlIHVzZWQgYnkgeW91ciBwbGF0Zm9ybS5cblx0ICovXG5cdGNsYXNzIE92ZXJyaWRlIGV4dGVuZHMgSW50ZXJvcEJyb2tlciB7XG5cdFx0cHVibGljIGV4dGVybmFsQnJva2VyOiBzdHJpbmc7XG5cblx0XHRwdWJsaWMgZXh0ZXJuYWxDbGllbnRzOiBFeHRlcm5hbENsaWVudE1hcDtcblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemUgYW5kIGNvbm5lY3QgdG8gZXh0ZXJuYWwgYnJva2VyLlxuXHRcdCAqL1xuXHRcdGNvbnN0cnVjdG9yKCkge1xuXHRcdFx0c3VwZXIoKTtcblx0XHRcdHRoaXMuZXh0ZXJuYWxCcm9rZXIgPSBcInBsYXRmb3JtLTJcIjtcblx0XHRcdHRoaXMuZXh0ZXJuYWxDbGllbnRzID0gbmV3IE1hcCgpO1xuXHRcdFx0dGhpcy5pbml0aWFsaXplQnJva2VycygpLmNhdGNoKChlcnJvcikgPT4gY29uc29sZS5lcnJvcihlcnJvcikpO1xuXHRcdH1cblxuXHRcdC8qKlxuXHRcdCAqIEluaXRpYWxpemUgdGhlIGJyb2tlcnMuXG5cdFx0ICogMS4gR2V0cyB0aGUgaW5zdGFuY2Ugb2YgdGhlIHNwZWNpZmllZCBleHRlcm5hbCBwbGF0Zm9ybS5cblx0XHQgKiAyLiBFbnN1cmUgdGhlIGV4dGVybmFsIHBsYXRmb3JtIGFwcGxpY2F0aW9uIGlzIHJ1bm5pbmcuXG5cdFx0ICogMy4gRW5zdXJlIHRoYXQgdGhlIHBsYXRmb3JtIGFwaSBpcyBmaW5pc2hlZCBpbml0aWFsaXppbmcuXG5cdFx0ICogNC4gUmVzZXQgdGhlIG1hcCB0cmFja2luZyB0aGUgZXh0ZXJuYWxDbGllbnQgY29ubmVjdGlvbnMuXG5cdFx0ICovXG5cdFx0cHVibGljIGFzeW5jIGluaXRpYWxpemVCcm9rZXJzKCk6IFByb21pc2U8dm9pZD4ge1xuXHRcdFx0Y29uc3QgcGxhdGZvcm06IE9wZW5GaW4uUGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0ud3JhcFN5bmMoeyB1dWlkOiB0aGlzLmV4dGVybmFsQnJva2VyIH0pO1xuXG5cdFx0XHRpZiAoYXdhaXQgcGxhdGZvcm0uQXBwbGljYXRpb24uaXNSdW5uaW5nKCkpIHtcblx0XHRcdFx0YXdhaXQgdGhpcy5zZXR1cENvbnRleHRHcm91cHMoKTtcblx0XHRcdH1cblxuXHRcdFx0YXdhaXQgcGxhdGZvcm0ub24oXCJwbGF0Zm9ybS1hcGktcmVhZHlcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRhd2FpdCB0aGlzLnNldHVwQ29udGV4dEdyb3VwcygpO1xuXHRcdFx0fSk7XG5cblx0XHRcdGF3YWl0IHBsYXRmb3JtLkFwcGxpY2F0aW9uLm9uY2UoXCJjbG9zZWRcIiwgKCkgPT4ge1xuXHRcdFx0XHR0aGlzLmV4dGVybmFsQ2xpZW50cyA9IG5ldyBNYXAoKTtcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdC8qKlxuXHRcdCAqIFNldHVwIHRoZSBjb250ZXh0IGdyb3Vwc1xuXHRcdCAqIDEuIENyZWF0ZSBhIEludGVyb3BDbGllbnQgaW5zdGFuY2UgYnkgY29ubmVjdGluZyB0byBhIG1lbWJlciBvZiBPdmVycmlkZS5leHRlcm5hbEJyb2tlcnMuXG5cdFx0ICogMi4gZXh0ZXJuYWxDb250ZXh0R3JvdXBzOiB1c2luZyB0aGUgY3JlYXRlZCBjbGllbnQgaW5zdGFuY2UsIHJldHJpZXZlIHRoZSBleHRlcm5hbEJyb2tlcidzIGNvbnRleHQgZ3JvdXBzLlxuXHRcdCAqIDMuIENyZWF0ZSBhIEludGVyb3BDbGllbnQgaW5zdGFuY2UgYnkgY29ubmVjdGluZyB0byB0aGUgY3VycmVudCBwbGF0Zm9ybXMgaW50ZXJvcCBicm9rZXIuXG5cdFx0ICogNC4gUGxhdGZvcm1Db250ZXh0R3JvdXBzOiB1c2luZyB0aGUgY3JlYXRlZCBjbGllbnQgaW5zdGFuY2UsIHJldHJpZXZlIHRoZSBjdXJyZW50IHBsYXRmb3JtIGNvbnRleHQgZ3JvdXBzLlxuXHRcdCAqIDUuIENoZWNrIHRvIHdoaWNoIGV4dGVybmFsQ29udGV4dEdyb3VwcyBhbmQgcGxhdGZvcm1Db250ZXh0R3JvdXBzIGFyZSB0aGUgc2FtZS5cblx0XHQgKiA2LiBJZiB0aGUgcGxhdGZvcm1Db250ZXh0R3JvdXAgaXMgc2hhcmVkIHdpdGggYW4gZXh0ZXJuYWxDb250ZXh0R3JvdXAgY3JlYXRlIGEgY29sb3JDbGllbnQgYW5kIGpvaW4gdGhlIHNoYXJlZCBjb250ZXh0IGdyb3VwIGZyb20gdGhlIGNvbG9yQ2xpZW50LlxuXHRcdCAqIDcuIENyZWF0ZSBhIGNvbnRleHQgaGFuZGxlciBmb3IgdGhlIGNvbG9yQ2xpZW50LlxuXHRcdCAqL1xuXHRcdHB1YmxpYyBhc3luYyBzZXR1cENvbnRleHRHcm91cHMoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0XHRjb25zdCBleHRlcm5hbEludGVyb3BDbGllbnQ6IE9wZW5GaW4uSW50ZXJvcENsaWVudCA9IGZpbi5JbnRlcm9wLmNvbm5lY3RTeW5jKHRoaXMuZXh0ZXJuYWxCcm9rZXIsIHt9KTtcblx0XHRcdGNvbnN0IGV4dGVybmFsQ29udGV4dEdyb3VwczogT3BlbkZpbi5Db250ZXh0R3JvdXBJbmZvW10gPVxuXHRcdFx0XHRhd2FpdCBleHRlcm5hbEludGVyb3BDbGllbnQuZ2V0Q29udGV4dEdyb3VwcygpO1xuXG5cdFx0XHRjb25zdCBwbGF0Zm9ybUludGVyb3BDbGllbnQ6IE9wZW5GaW4uSW50ZXJvcENsaWVudCA9IGZpbi5JbnRlcm9wLmNvbm5lY3RTeW5jKGZpbi5tZS51dWlkLCB7fSk7XG5cdFx0XHRjb25zdCBwbGF0Zm9ybUNvbnRleHRHcm91cHM6IE9wZW5GaW4uQ29udGV4dEdyb3VwSW5mb1tdID1cblx0XHRcdFx0YXdhaXQgcGxhdGZvcm1JbnRlcm9wQ2xpZW50LmdldENvbnRleHRHcm91cHMoKTtcblxuXHRcdFx0Ly8gQXJyYXkgb2YgRXh0ZXJuYWxDbGllbnRNYXAgUHJvbWlzZXNcblx0XHRcdGNvbnN0IGV4dGVybmFsQ29udGV4dEdyb3VwUHJvbWlzZXM6IFByb21pc2U8RXh0ZXJuYWxDbGllbnRNYXAgfCB1bmRlZmluZWQ+W10gPVxuXHRcdFx0XHRleHRlcm5hbENvbnRleHRHcm91cHMubWFwKFxuXHRcdFx0XHRcdGFzeW5jIChcblx0XHRcdFx0XHRcdGV4dGVybmFsQ29udGV4dEdyb3VwSW5mbzogT3BlbkZpbi5Db250ZXh0R3JvdXBJbmZvXG5cdFx0XHRcdFx0KTogUHJvbWlzZTxFeHRlcm5hbENsaWVudE1hcCB8IHVuZGVmaW5lZD4gPT4ge1xuXHRcdFx0XHRcdFx0Ly8gY2hlY2sgdG8gc2VlIGlmIGEgUGxhdGZvcm0gQ2xpZW50J3MgY29udGV4dCBncm91cCBoYXMgYW55IG9mIHRoZSBjaGFubmVscyBhcyBhIGV4dGVybmFsQ29udGV4dEdyb3VwXG5cdFx0XHRcdFx0XHRjb25zdCBoYXNQbGF0Zm9ybUNvbnRleHRHcm91cDogYm9vbGVhbiA9IHBsYXRmb3JtQ29udGV4dEdyb3Vwcy5zb21lKFxuXHRcdFx0XHRcdFx0XHQoeyBpZCB9OiBPcGVuRmluLkNvbnRleHRHcm91cEluZm8pID0+IGlkID09PSBleHRlcm5hbENvbnRleHRHcm91cEluZm8uaWRcblx0XHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHRcdGlmIChoYXNQbGF0Zm9ybUNvbnRleHRHcm91cCkge1xuXHRcdFx0XHRcdFx0XHRjb25zdCBjb2xvckNsaWVudDogT3BlbkZpbi5JbnRlcm9wQ2xpZW50ID0gZmluLkludGVyb3AuY29ubmVjdFN5bmModGhpcy5leHRlcm5hbEJyb2tlciwge30pO1xuXHRcdFx0XHRcdFx0XHRhd2FpdCBjb2xvckNsaWVudC5qb2luQ29udGV4dEdyb3VwKGV4dGVybmFsQ29udGV4dEdyb3VwSW5mby5pZCk7XG5cdFx0XHRcdFx0XHRcdC8qKlxuXHRcdFx0XHRcdFx0XHQgKiBIYW5kbGUgYSBjb250ZXh0LlxuXHRcdFx0XHRcdFx0XHQgKiBAcGFyYW0gY29udGV4dCBvYmplY3QgcGFzc2VkIGZyb20gdGhlIHNldENvbnRleHQgbWV0aG9kLlxuXHRcdFx0XHRcdFx0XHQgKiBJZiB0aGUgbmV3Q29udGV4dCB2YXJpYWJsZSBoYXMgYSBfY2xpZW50SW5mbyBvYmplY3Qgd2l0aCBhIHV1aWQgcmV0dXJuIHRoZSBjb250ZXh0IGFzIGlzXG5cdFx0XHRcdFx0XHRcdCAqIGJlY2F1c2UgaXQgaXMgaW5pdGlhbGx5IHNldCBvbiB0aGUgcGxhdGZvcm1JbnRlcm9wQ2xpZW50J3MgYnJva2VyLlxuXHRcdFx0XHRcdFx0XHQgKiBvdGhlcndpc2UgY29weSB0aGUgY29udGV4dCBhdHRyaWJ1dGVzIGFuZCB2YWx1ZXMgdG8gYSBuZXcgb2JqZWN0IGNvbnRhaW5pbmdcblx0XHRcdFx0XHRcdFx0ICogYSBfY2xpZW50SW5mbyBhdHRyaWJ1dGUgd2l0aCB0aGUgdXVpZCBvZiB0aGUgY29ubmVjdGVkIGV4dGVybmFsQnJva2VyLlxuXHRcdFx0XHRcdFx0XHQgKi9cblx0XHRcdFx0XHRcdFx0Y29uc3QgY29udGV4dEhhbmRsZXIgPSBhc3luYyAoY29udGV4dDogRXh0ZXJuYWxDb250ZXh0KTogUHJvbWlzZTx2b2lkPiA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgcGxhdGZvcm1JbnRlcm9wQ2xpZW50LmpvaW5Db250ZXh0R3JvdXAoZXh0ZXJuYWxDb250ZXh0R3JvdXBJbmZvLmlkKTtcblx0XHRcdFx0XHRcdFx0XHRjb25zdCBuZXdDb250ZXh0ID0gY29udGV4dC5fY2xpZW50SW5mbz8udXVpZFxuXHRcdFx0XHRcdFx0XHRcdFx0PyBjb250ZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHQ6IHsgLi4uY29udGV4dCwgX2NsaWVudEluZm86IHsgdXVpZDogdGhpcy5leHRlcm5hbEJyb2tlciB9IH07XG5cdFx0XHRcdFx0XHRcdFx0YXdhaXQgcGxhdGZvcm1JbnRlcm9wQ2xpZW50LnNldENvbnRleHQobmV3Q29udGV4dCk7XG5cdFx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0XHRcdGF3YWl0IGNvbG9yQ2xpZW50LmFkZENvbnRleHRIYW5kbGVyKGNvbnRleHRIYW5kbGVyKTtcblx0XHRcdFx0XHRcdFx0Ly8gcmV0dXJuIHRoZSBjb25uZWN0ZWQgY29udGV4dCBncm91cCBhbmQgY29ycmVzcG9uZGVkIGNvbG9yIGNsaWVudC5cblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRoaXMuZXh0ZXJuYWxDbGllbnRzLnNldChleHRlcm5hbENvbnRleHRHcm91cEluZm8uaWQsIGNvbG9yQ2xpZW50KTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdCk7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRhd2FpdCBQcm9taXNlLmFsbChleHRlcm5hbENvbnRleHRHcm91cFByb21pc2VzKTtcblx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihgTm90IGFibGUgdG8gc2V0dXAgaGFuZGxlcnMgZm9yIGV4dGVybmFsIGJyb2tlcnM6ICR7ZXJyb3J9YCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0LyoqXG5cdFx0ICogU2V0IHRoZSBjb250ZXh0IG9uIGFuIGV4dGVybmFsIGNsaWVudC5cblx0XHQgKiBpZiB0aGUgZXh0ZXJuYWxDbGllbnRzTWFwIGhhcyBwcmV2aW91c2x5IGRlcml2ZWQgY29udGV4dEdyb3VwIGdldCB0aGUgY29ycmVzcG9uZGluZ1xuXHRcdCAqIGNvbG9yQ2xpZW50IGFuZCBzZXQgdGhlIGNvbnRleHQgb24gdGhlIG1hdGNoaW5nIGNvbG9yQ2xpZW50LlxuXHRcdCAqIEBwYXJhbSBjb250ZXh0IGNvbnRleHQgb2JqZWN0IHBhc3NlZCBpbiBmcm9tIHRoZSBAc2V0Q29udGV4dCBtZXRob2QuXG5cdFx0ICogQHBhcmFtIGNsaWVudElkZW50aXR5IGNsaWVudElkZW50aXR5IG9iamVjdCBwYXNzZWQgaW4gZnJvbSB0aGUgQHNldENvbnRleHQgbWV0aG9kLlxuXHRcdCAqL1xuXHRcdHB1YmxpYyBhc3luYyBzZXRDb250ZXh0T25FeHRlcm5hbENsaWVudChcblx0XHRcdGNvbnRleHQ6IEV4dGVybmFsQ29udGV4dCxcblx0XHRcdGNsaWVudElkZW50aXR5OiBPcGVuRmluLkNsaWVudElkZW50aXR5XG5cdFx0KTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0XHQvLyB1c2UgYWNjZXNzb3Igc3ludGF4IGZvciB0aGlzLmdldENsaWVudFN0YXRlIGFzIGl0IGlzIG5vdCBhIHB1YmxpYyBpbmhlcml0ZWQgbWV0aG9kIGZyb20gSW50ZXJvcEJyb2tlclxuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9kb3Qtbm90YXRpb25cblx0XHRcdGNvbnN0IHN0YXRlID0gdGhpc1tcImdldENsaWVudFN0YXRlXCJdKGNsaWVudElkZW50aXR5KTtcblx0XHRcdGNvbnN0IGN0eEdyb3VwSWQgPSBzdGF0ZS5jb250ZXh0R3JvdXBJZCBhcyBzdHJpbmc7XG5cdFx0XHRpZiAodGhpcy5leHRlcm5hbENsaWVudHMuaGFzKGN0eEdyb3VwSWQpKSB7XG5cdFx0XHRcdGNvbnN0IGNvbG9yQ2xpZW50ID0gdGhpcy5leHRlcm5hbENsaWVudHMuZ2V0KGN0eEdyb3VwSWQpO1xuXHRcdFx0XHRpZiAoY29sb3JDbGllbnQpIHtcblx0XHRcdFx0XHRhd2FpdCBjb2xvckNsaWVudC5zZXRDb250ZXh0KGNvbnRleHQpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0LyoqXG5cdFx0ICogU2V0IHRoZSBjb250ZXh0LlxuXHRcdCAqIEBwYXJhbSBwYXlsb2FkIG9iamVjdCB0aGF0IGlzIHBhc3NlZCBpbiB3aGVuIHNldCBjb250ZXh0IGlzIGNhbGxlZCBmcm9tIGFuIE9wZW5GaW4gZW50aXR5IHVzaW5nIHRoZSBpbnRlcm9wIGFwaS5cblx0XHQgKiBAcGFyYW0gcGF5bG9hZC5jb250ZXh0IFRoZSBjb250ZXh0IGZvciB0aGUgcGF5bG9hZC5cblx0XHQgKiBAcGFyYW0gY2xpZW50SWRlbnRpdHkgb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNsaWVudElkZW50aXR5IG9mIHRoZSBzZW5kZXIuXG5cdFx0ICovXG5cdFx0cHVibGljIGFzeW5jIHNldENvbnRleHQoXG5cdFx0XHRwYXlsb2FkOiB7IGNvbnRleHQ6IEV4dGVybmFsQ29udGV4dCB9LFxuXHRcdFx0Y2xpZW50SWRlbnRpdHk6IE9wZW5GaW4uQ2xpZW50SWRlbnRpdHlcblx0XHQpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRcdC8vIGNyZWF0ZSBhIG5ldyBjb250ZXh0IG9iamVjdCBmb3IgaW50ZXJvcCBzZXRDb250ZXh0IGNhbGxzIGZyb20gdGhlIGludGVyb3Agb2JqZWN0IHdpdGhpbiB0aGUgUGxhdGZvcm0gQ2xpZW50J3Mgd2luZG93cyBvciB2aWV3cy5cblx0XHRcdGNvbnN0IHsgY29udGV4dCB9ID0gcGF5bG9hZDtcblx0XHRcdGlmIChjb250ZXh0Ll9jbGllbnRJbmZvKSB7XG5cdFx0XHRcdGNvbnN0IHtcblx0XHRcdFx0XHRfY2xpZW50SW5mbzogeyB1dWlkIH1cblx0XHRcdFx0fSA9IGNvbnRleHQ7XG5cdFx0XHRcdC8vIHNldCBjb250ZXh0IG9uIGV4dGVybmFsIGJyb2tlclxuXHRcdFx0XHRpZiAoKHV1aWQgIT09IGZpbi5tZS51dWlkICYmIHV1aWQgIT09IHRoaXMuZXh0ZXJuYWxCcm9rZXIpIHx8IHV1aWQgPT09IHRoaXMuZXh0ZXJuYWxCcm9rZXIpIHtcblx0XHRcdFx0XHRjb25zdCBuZXdDb250ZXh0ID0gY29udGV4dDtcblx0XHRcdFx0XHRkZWxldGUgbmV3Q29udGV4dC5fY2xpZW50SW5mbztcblx0XHRcdFx0XHRzdXBlci5zZXRDb250ZXh0KHsgLi4ucGF5bG9hZCwgY29udGV4dDogbmV3Q29udGV4dCB9LCBjbGllbnRJZGVudGl0eSk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIElmIHRoZXJlIGlzIG5vIF9jbGllbnRJbmZvIG9iamVjdCBwcmVzZW50IG9uIHRoZSBjb250ZXh0IG9iamVjdCB3ZSB0cmVhdCBpdCBhcyBhIGJyYW5kIG5ldyBvYmplY3QgYW5kIHNldCBpdCBvbiBib3RoIHRoZSBwbGF0Zm9ybSBhbmQgZXh0ZXJuYWwgY2xpZW50cy5cblx0XHRcdFx0Y29uc3QgbmV3Q29udGV4dCA9IHsgLi4uY29udGV4dCwgX2NsaWVudEluZm86IHsgdXVpZDogZmluLm1lLnV1aWQgfSB9O1xuXHRcdFx0XHRhd2FpdCB0aGlzLnNldENvbnRleHRPbkV4dGVybmFsQ2xpZW50KG5ld0NvbnRleHQsIGNsaWVudElkZW50aXR5KTtcblx0XHRcdFx0c3VwZXIuc2V0Q29udGV4dChwYXlsb2FkLCBjbGllbnRJZGVudGl0eSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdHJldHVybiBuZXcgT3ZlcnJpZGUoKTtcbn1cblxuZmluLlBsYXRmb3JtLmluaXQoeyBpbnRlcm9wT3ZlcnJpZGUgfSkuY2F0Y2goKGVycm9yKSA9PiBjb25zb2xlLmVycm9yKGVycm9yKSk7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/js/window.bundle.js b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/js/window.bundle.js new file mode 100644 index 00000000..22018dfb --- /dev/null +++ b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/js/window.bundle.js @@ -0,0 +1,146 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!******************************!*\ + !*** ./client/src/window.ts ***! + \******************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ CONTAINER_ID: () => (/* binding */ CONTAINER_ID) +/* harmony export */ }); +const CONTAINER_ID = "layout-container"; +const openfinWindow = fin.Window.getCurrentSync(); +const openfinApplication = fin.Application.getCurrentSync(); +let lastFocusedView; +openfinApplication + .on("view-focused", (viewEvent) => { + lastFocusedView = viewEvent.viewIdentity; +}) + .catch((error) => console.error(error)); +window.addEventListener("DOMContentLoaded", async () => { + await fin.Platform.Layout.init({ containerId: CONTAINER_ID }); + await setupTitleBar(); +}); +/** + * Setup the content for the title bar. + */ +async function setupTitleBar() { + const title = document.querySelector("#title"); + const minBtn = document.querySelector("#minimize-button"); + const maxBtn = document.querySelector("#expand-button"); + const closeBtn = document.querySelector("#close-button"); + if (title && minBtn && maxBtn && closeBtn) { + title.innerHTML = fin.me.identity.uuid; + minBtn.addEventListener("click", minimizeWindow); + maxBtn.addEventListener("click", maxOrRestore); + closeBtn.addEventListener("click", closeWindow); + } + await addContextGroupButtons(); +} +/** + * Joins a context group by passing in the top-level variable `lastFocusedView` as the `target` parameter of the `joinContextGroup` function. + * @param event - DOM click event that is passed in to the button click event from `addContextGroupButtons` local `newButton` variable + */ +async function changeContextGroup(event) { + const selectedColorElement = event.target; + const color = selectedColorElement.title; + await fin.me.interop.joinContextGroup(color, lastFocusedView); + const contextGroups = await fin.me.interop.getContextGroups(); + const focusedTab = document.querySelector(`#tab-${lastFocusedView.name}`); + if (focusedTab) { + focusedTab.classList.remove(...contextGroups.map(({ displayMetadata }) => `${displayMetadata?.name}-channel`)); + } + const focusedView = document.querySelector(`#tab-${lastFocusedView.name}`); + if (focusedView) { + focusedView.classList.add(`${color}-channel`); + } +} +/** + * Add the context group buttons. + * 1. Retrieves a Platform's interop context groups. + * 2. Iterates all context groups and creates a corresponding button per context group (color channel). + * 3. Adds a click listener to each button with the `changeContextGroup` function as the listener callback. + */ +async function addContextGroupButtons() { + const contextGroups = await fin.me.interop.getContextGroups(); + const windowFrameStyleSheet = document.styleSheets[0]; + const buttonsWrapper = document.querySelector("#buttons-wrapper"); + if (buttonsWrapper) { + for (const systemChannel of contextGroups) { + const nm = systemChannel.displayMetadata?.name; + const col = systemChannel.displayMetadata?.color; + if (nm && col) { + windowFrameStyleSheet.insertRule(`.${nm}-channel { border-left: 2px solid ${col} !important;}`); + windowFrameStyleSheet.insertRule(`#${nm}-button:after { background-color: ${col}}`); + const newButton = document.createElement("div"); + newButton.classList.add("button"); + newButton.classList.add("channel-button"); + newButton.id = `${nm}-button`; + newButton.title = nm; + newButton.addEventListener("click", changeContextGroup); + buttonsWrapper.prepend(newButton); + } + } + } +} +/** + * Maximize or restore the window. + * @returns Nothing. + */ +async function maxOrRestore() { + if ((await openfinWindow.getState()) === "normal") { + return openfinWindow.maximize(); + } + return openfinWindow.restore(); +} +/** + * Close the window. + * @returns Nothing. + */ +async function closeWindow() { + return openfinWindow.close(); +} +/** + * Minimize the window. + * @returns Nothing. + */ +async function minimizeWindow() { + return openfinWindow.minimize(); +} + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDbEMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztnQkFDMUMsU0FBUyxDQUFDLEVBQUUsR0FBRyxHQUFHLEVBQUUsU0FBUyxDQUFDO2dCQUM5QixTQUFTLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztnQkFDckIsU0FBUyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO2dCQUN4RCxjQUFjLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ25DLENBQUM7UUFDRixDQUFDO0lBQ0YsQ0FBQztBQUNGLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxLQUFLLFVBQVUsWUFBWTtJQUMxQixJQUFJLENBQUMsTUFBTSxhQUFhLENBQUMsUUFBUSxFQUFFLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNuRCxPQUFPLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNqQyxDQUFDO0lBRUQsT0FBTyxhQUFhLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDaEMsQ0FBQztBQUVEOzs7R0FHRztBQUNILEtBQUssVUFBVSxXQUFXO0lBQ3pCLE9BQU8sYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQzlCLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxLQUFLLFVBQVUsY0FBYztJQUM1QixPQUFPLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUNqQyxDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vc2V0dXAtY3Jvc3MtcGxhdGZvcm0taW50ZXJvcC93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9zZXR1cC1jcm9zcy1wbGF0Zm9ybS1pbnRlcm9wL3dlYnBhY2svcnVudGltZS9kZWZpbmUgcHJvcGVydHkgZ2V0dGVycyIsIndlYnBhY2s6Ly9zZXR1cC1jcm9zcy1wbGF0Zm9ybS1pbnRlcm9wL3dlYnBhY2svcnVudGltZS9oYXNPd25Qcm9wZXJ0eSBzaG9ydGhhbmQiLCJ3ZWJwYWNrOi8vc2V0dXAtY3Jvc3MtcGxhdGZvcm0taW50ZXJvcC93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3NldHVwLWNyb3NzLXBsYXRmb3JtLWludGVyb3AvLi9jbGllbnQvc3JjL3dpbmRvdy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIGdldHRlciBmdW5jdGlvbnMgZm9yIGhhcm1vbnkgZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5kID0gKGV4cG9ydHMsIGRlZmluaXRpb24pID0+IHtcblx0Zm9yKHZhciBrZXkgaW4gZGVmaW5pdGlvbikge1xuXHRcdGlmKF9fd2VicGFja19yZXF1aXJlX18ubyhkZWZpbml0aW9uLCBrZXkpICYmICFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywga2V5KSkge1xuXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIGtleSwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGRlZmluaXRpb25ba2V5XSB9KTtcblx0XHR9XG5cdH1cbn07IiwiX193ZWJwYWNrX3JlcXVpcmVfXy5vID0gKG9iaiwgcHJvcCkgPT4gKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApKSIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsImltcG9ydCB0eXBlIE9wZW5GaW4gZnJvbSBcIkBvcGVuZmluL2NvcmVcIjtcblxuZXhwb3J0IGNvbnN0IENPTlRBSU5FUl9JRCA9IFwibGF5b3V0LWNvbnRhaW5lclwiO1xuY29uc3Qgb3BlbmZpbldpbmRvdzogT3BlbkZpbi5XaW5kb3cgPSBmaW4uV2luZG93LmdldEN1cnJlbnRTeW5jKCk7XG5jb25zdCBvcGVuZmluQXBwbGljYXRpb246IE9wZW5GaW4uQXBwbGljYXRpb24gPSBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudFN5bmMoKTtcblxubGV0IGxhc3RGb2N1c2VkVmlldzogT3BlbkZpbi5JZGVudGl0eTtcblxub3BlbmZpbkFwcGxpY2F0aW9uXG5cdC5vbihcInZpZXctZm9jdXNlZFwiLCAodmlld0V2ZW50KTogdm9pZCA9PiB7XG5cdFx0bGFzdEZvY3VzZWRWaWV3ID0gdmlld0V2ZW50LnZpZXdJZGVudGl0eTtcblx0fSlcblx0LmNhdGNoKChlcnJvcikgPT4gY29uc29sZS5lcnJvcihlcnJvcikpO1xuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgYXN5bmMgKCkgPT4ge1xuXHRhd2FpdCBmaW4uUGxhdGZvcm0uTGF5b3V0LmluaXQoeyBjb250YWluZXJJZDogQ09OVEFJTkVSX0lEIH0pO1xuXHRhd2FpdCBzZXR1cFRpdGxlQmFyKCk7XG59KTtcblxuLyoqXG4gKiBTZXR1cCB0aGUgY29udGVudCBmb3IgdGhlIHRpdGxlIGJhci5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2V0dXBUaXRsZUJhcigpOiBQcm9taXNlPHZvaWQ+IHtcblx0Y29uc3QgdGl0bGUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3RpdGxlXCIpO1xuXHRjb25zdCBtaW5CdG4gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI21pbmltaXplLWJ1dHRvblwiKTtcblx0Y29uc3QgbWF4QnRuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNleHBhbmQtYnV0dG9uXCIpO1xuXHRjb25zdCBjbG9zZUJ0biA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjY2xvc2UtYnV0dG9uXCIpO1xuXG5cdGlmICh0aXRsZSAmJiBtaW5CdG4gJiYgbWF4QnRuICYmIGNsb3NlQnRuKSB7XG5cdFx0dGl0bGUuaW5uZXJIVE1MID0gZmluLm1lLmlkZW50aXR5LnV1aWQ7XG5cblx0XHRtaW5CdG4uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIG1pbmltaXplV2luZG93KTtcblx0XHRtYXhCdG4uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIG1heE9yUmVzdG9yZSk7XG5cdFx0Y2xvc2VCdG4uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGNsb3NlV2luZG93KTtcblx0fVxuXG5cdGF3YWl0IGFkZENvbnRleHRHcm91cEJ1dHRvbnMoKTtcbn1cblxuLyoqXG4gKiBKb2lucyBhIGNvbnRleHQgZ3JvdXAgYnkgcGFzc2luZyBpbiB0aGUgdG9wLWxldmVsIHZhcmlhYmxlIGBsYXN0Rm9jdXNlZFZpZXdgIGFzIHRoZSBgdGFyZ2V0YCBwYXJhbWV0ZXIgb2YgdGhlIGBqb2luQ29udGV4dEdyb3VwYCBmdW5jdGlvbi5cbiAqIEBwYXJhbSBldmVudCAtIERPTSBjbGljayBldmVudCB0aGF0IGlzIHBhc3NlZCBpbiB0byB0aGUgYnV0dG9uIGNsaWNrIGV2ZW50IGZyb20gYGFkZENvbnRleHRHcm91cEJ1dHRvbnNgIGxvY2FsIGBuZXdCdXR0b25gIHZhcmlhYmxlXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNoYW5nZUNvbnRleHRHcm91cChldmVudDogRXZlbnQpOiBQcm9taXNlPHZvaWQ+IHtcblx0Y29uc3Qgc2VsZWN0ZWRDb2xvckVsZW1lbnQ6IEhUTUxFbGVtZW50ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuXHRjb25zdCBjb2xvcjogc3RyaW5nID0gc2VsZWN0ZWRDb2xvckVsZW1lbnQudGl0bGU7XG5cdGF3YWl0IGZpbi5tZS5pbnRlcm9wLmpvaW5Db250ZXh0R3JvdXAoY29sb3IsIGxhc3RGb2N1c2VkVmlldyk7XG5cdGNvbnN0IGNvbnRleHRHcm91cHM6IE9wZW5GaW4uQ29udGV4dEdyb3VwSW5mb1tdID0gYXdhaXQgZmluLm1lLmludGVyb3AuZ2V0Q29udGV4dEdyb3VwcygpO1xuXHRjb25zdCBmb2N1c2VkVGFiID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihgI3RhYi0ke2xhc3RGb2N1c2VkVmlldy5uYW1lfWApO1xuXHRpZiAoZm9jdXNlZFRhYikge1xuXHRcdGZvY3VzZWRUYWIuY2xhc3NMaXN0LnJlbW92ZShcblx0XHRcdC4uLmNvbnRleHRHcm91cHMubWFwKFxuXHRcdFx0XHQoeyBkaXNwbGF5TWV0YWRhdGEgfTogT3BlbkZpbi5Db250ZXh0R3JvdXBJbmZvKSA9PiBgJHtkaXNwbGF5TWV0YWRhdGE/Lm5hbWV9LWNoYW5uZWxgXG5cdFx0XHQpXG5cdFx0KTtcblx0fVxuXHRjb25zdCBmb2N1c2VkVmlldyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYCN0YWItJHtsYXN0Rm9jdXNlZFZpZXcubmFtZX1gKTtcblx0aWYgKGZvY3VzZWRWaWV3KSB7XG5cdFx0Zm9jdXNlZFZpZXcuY2xhc3NMaXN0LmFkZChgJHtjb2xvcn0tY2hhbm5lbGApO1xuXHR9XG59XG5cbi8qKlxuICogQWRkIHRoZSBjb250ZXh0IGdyb3VwIGJ1dHRvbnMuXG4gKiAxLiBSZXRyaWV2ZXMgYSBQbGF0Zm9ybSdzIGludGVyb3AgY29udGV4dCBncm91cHMuXG4gKiAyLiBJdGVyYXRlcyBhbGwgY29udGV4dCBncm91cHMgYW5kIGNyZWF0ZXMgYSBjb3JyZXNwb25kaW5nIGJ1dHRvbiBwZXIgY29udGV4dCBncm91cCAoY29sb3IgY2hhbm5lbCkuXG4gKiAzLiBBZGRzIGEgY2xpY2sgbGlzdGVuZXIgdG8gZWFjaCBidXR0b24gd2l0aCB0aGUgYGNoYW5nZUNvbnRleHRHcm91cGAgZnVuY3Rpb24gYXMgdGhlIGxpc3RlbmVyIGNhbGxiYWNrLlxuICovXG5hc3luYyBmdW5jdGlvbiBhZGRDb250ZXh0R3JvdXBCdXR0b25zKCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBjb250ZXh0R3JvdXBzOiBPcGVuRmluLkNvbnRleHRHcm91cEluZm9bXSA9IGF3YWl0IGZpbi5tZS5pbnRlcm9wLmdldENvbnRleHRHcm91cHMoKTtcblx0Y29uc3Qgd2luZG93RnJhbWVTdHlsZVNoZWV0OiBDU1NTdHlsZVNoZWV0ID0gZG9jdW1lbnQuc3R5bGVTaGVldHNbMF07XG5cdGNvbnN0IGJ1dHRvbnNXcmFwcGVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MRWxlbWVudD4oXCIjYnV0dG9ucy13cmFwcGVyXCIpO1xuXHRpZiAoYnV0dG9uc1dyYXBwZXIpIHtcblx0XHRmb3IgKGNvbnN0IHN5c3RlbUNoYW5uZWwgb2YgY29udGV4dEdyb3Vwcykge1xuXHRcdFx0Y29uc3Qgbm0gPSBzeXN0ZW1DaGFubmVsLmRpc3BsYXlNZXRhZGF0YT8ubmFtZTtcblx0XHRcdGNvbnN0IGNvbCA9IHN5c3RlbUNoYW5uZWwuZGlzcGxheU1ldGFkYXRhPy5jb2xvcjtcblx0XHRcdGlmIChubSAmJiBjb2wpIHtcblx0XHRcdFx0d2luZG93RnJhbWVTdHlsZVNoZWV0Lmluc2VydFJ1bGUoYC4ke25tfS1jaGFubmVsIHsgYm9yZGVyLWxlZnQ6IDJweCBzb2xpZCAke2NvbH0gIWltcG9ydGFudDt9YCk7XG5cdFx0XHRcdHdpbmRvd0ZyYW1lU3R5bGVTaGVldC5pbnNlcnRSdWxlKGAjJHtubX0tYnV0dG9uOmFmdGVyIHsgYmFja2dyb3VuZC1jb2xvcjogJHtjb2x9fWApO1xuXHRcdFx0XHRjb25zdCBuZXdCdXR0b24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuXHRcdFx0XHRuZXdCdXR0b24uY2xhc3NMaXN0LmFkZChcImJ1dHRvblwiKTtcblx0XHRcdFx0bmV3QnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJjaGFubmVsLWJ1dHRvblwiKTtcblx0XHRcdFx0bmV3QnV0dG9uLmlkID0gYCR7bm19LWJ1dHRvbmA7XG5cdFx0XHRcdG5ld0J1dHRvbi50aXRsZSA9IG5tO1xuXHRcdFx0XHRuZXdCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGNoYW5nZUNvbnRleHRHcm91cCk7XG5cdFx0XHRcdGJ1dHRvbnNXcmFwcGVyLnByZXBlbmQobmV3QnV0dG9uKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBNYXhpbWl6ZSBvciByZXN0b3JlIHRoZSB3aW5kb3cuXG4gKiBAcmV0dXJucyBOb3RoaW5nLlxuICovXG5hc3luYyBmdW5jdGlvbiBtYXhPclJlc3RvcmUoKTogUHJvbWlzZTx2b2lkPiB7XG5cdGlmICgoYXdhaXQgb3BlbmZpbldpbmRvdy5nZXRTdGF0ZSgpKSA9PT0gXCJub3JtYWxcIikge1xuXHRcdHJldHVybiBvcGVuZmluV2luZG93Lm1heGltaXplKCk7XG5cdH1cblxuXHRyZXR1cm4gb3BlbmZpbldpbmRvdy5yZXN0b3JlKCk7XG59XG5cbi8qKlxuICogQ2xvc2UgdGhlIHdpbmRvdy5cbiAqIEByZXR1cm5zIE5vdGhpbmcuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNsb3NlV2luZG93KCk6IFByb21pc2U8dm9pZD4ge1xuXHRyZXR1cm4gb3BlbmZpbldpbmRvdy5jbG9zZSgpO1xufVxuXG4vKipcbiAqIE1pbmltaXplIHRoZSB3aW5kb3cuXG4gKiBAcmV0dXJucyBOb3RoaW5nLlxuICovXG5hc3luYyBmdW5jdGlvbiBtaW5pbWl6ZVdpbmRvdygpOiBQcm9taXNlPHZvaWQ+IHtcblx0cmV0dXJuIG9wZW5maW5XaW5kb3cubWluaW1pemUoKTtcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/manifest.fin.json b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/manifest.fin.json new file mode 100644 index 00000000..b8e46d6d --- /dev/null +++ b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/manifest.fin.json @@ -0,0 +1,58 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "platform-1", + "icon": "https://openfin.github.io/golden-prototype/favicon.ico", + "autoShow": false, + "providerUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/html/provider.html", + "apiDiagnostics": false, + "defaultWindowOptions": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/html/window.html", + "contextMenu": true, + "defaultWidth": 700, + "defaultHeight": 700, + "defaultLeft": 0, + "defaultTop": 0, + "saveWindowState": false, + "showBackgroundImages": true, + "backgroundThrottling": true, + "minHeight": 700, + "minWidth": 700, + "height": 700, + "width": 700 + } + }, + "snapshot": { + "windows": [ + { + "name": "window1", + "layout": { + "content": [ + { + "type": "row", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/interop-api/context/interop-broadcast-view.html" + } + }, + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/interop-api/context/interop-broadcast-view.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/second.manifest.fin.json b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/second.manifest.fin.json new file mode 100644 index 00000000..51c39a70 --- /dev/null +++ b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/second.manifest.fin.json @@ -0,0 +1,61 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "platform-2", + "icon": "https://openfin.github.io/golden-prototype/favicon.ico", + "autoShow": false, + "apiDiagnostics": false, + "providerUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/html/provider.html", + "defaultWindowOptions": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/html/window.html", + "contextMenu": true, + "defaultWidth": 700, + "defaultHeight": 700, + "defaultLeft": 0, + "defaultTop": 0, + "saveWindowState": false, + "showBackgroundImages": true, + "backgroundThrottling": true, + "minHeight": 700, + "minWidth": 700, + "height": 700, + "width": 700 + }, + "defaultViewOptions": { + "fdc3InteropApi": "1.2" + } + }, + "snapshot": { + "windows": [ + { + "name": "view", + "layout": { + "content": [ + { + "type": "row", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/fdc3/context/fdc3-broadcast-view.html" + } + }, + { + "type": "component", + "componentName": "view", + "componentState": { + "url": "https://samples.openfin.co/dev-extensions/extensions/v18.0.0/interop/interop-api/context/interop-broadcast-view.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/styles/frame-styles.css b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/styles/frame-styles.css new file mode 100644 index 00000000..14b7200b --- /dev/null +++ b/dev/john/update-logging-example/use-interop-setup-multi-platform-interop/styles/frame-styles.css @@ -0,0 +1,30 @@ +#body-container { + display: flex; + transition: 0.8s; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; + height: 96%; + width: 100%; +} + +.face { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + z-index: 1; +} + +.channel-button:after { + content: ''; + padding: 5px; + display: inline-block; + margin-left: 10px; + margin-top: 10px; +} + +#title { + color: var(--body-font-color); + margin: 0px; +} diff --git a/dev/john/update-logging-example/use-launch-external-process/assets/lep-demo.gif b/dev/john/update-logging-example/use-launch-external-process/assets/lep-demo.gif new file mode 100644 index 00000000..a127edfb Binary files /dev/null and b/dev/john/update-logging-example/use-launch-external-process/assets/lep-demo.gif differ diff --git a/dev/john/update-logging-example/use-launch-external-process/assets/openfin-dotnet-example.zip b/dev/john/update-logging-example/use-launch-external-process/assets/openfin-dotnet-example.zip new file mode 100644 index 00000000..a95ef7e5 Binary files /dev/null and b/dev/john/update-logging-example/use-launch-external-process/assets/openfin-dotnet-example.zip differ diff --git a/dev/john/update-logging-example/use-launch-external-process/common/images/icon-blue.png b/dev/john/update-logging-example/use-launch-external-process/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-launch-external-process/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-launch-external-process/common/style/app.css b/dev/john/update-logging-example/use-launch-external-process/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-launch-external-process/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-launch-external-process/dos.json b/dev/john/update-logging-example/use-launch-external-process/dos.json new file mode 100644 index 00000000..22198734 --- /dev/null +++ b/dev/john/update-logging-example/use-launch-external-process/dos.json @@ -0,0 +1,13 @@ +{ + "applicationSettings": { + "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-launch-external-process/manifest.fin.json": { + "permissions": { + "System": { + "launchExternalProcess": true, + "terminateExternalProcess": true, + "downloadAsset": true + } + } + } + } +} diff --git a/dev/john/update-logging-example/use-launch-external-process/favicon.ico b/dev/john/update-logging-example/use-launch-external-process/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-launch-external-process/favicon.ico differ diff --git a/dev/john/update-logging-example/use-launch-external-process/html/app.html b/dev/john/update-logging-example/use-launch-external-process/html/app.html new file mode 100644 index 00000000..03bcd86f --- /dev/null +++ b/dev/john/update-logging-example/use-launch-external-process/html/app.html @@ -0,0 +1,18 @@ + + + + + + OpenFin Template + + + + + + +

Launch App Asset Example

+
+ +
+ + diff --git a/dev/john/update-logging-example/use-launch-external-process/js/app.bundle.js b/dev/john/update-logging-example/use-launch-external-process/js/app.bundle.js new file mode 100644 index 00000000..14f3201c --- /dev/null +++ b/dev/john/update-logging-example/use-launch-external-process/js/app.bundle.js @@ -0,0 +1,51 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +document.addEventListener("DOMContentLoaded", () => { + const lepOptions = { + alias: "of-dotnet-example", + listener: (result) => { + console.log("result", result); + if (result.exitCode === 1) { + console.log("Successfully exited DotNetCore.exe"); + } + } + }; + const lepBtn = document.querySelector("#lep-button"); + if (lepBtn) { + lepBtn.addEventListener("click", async () => { + try { + const data = await fin.System.launchExternalProcess(lepOptions); + console.log("successfully launched DotNetCore.exe:", data); + } + catch (err) { + console.error(err); + } + }); + } +}); + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOztVQUFBO1VBQ0E7Ozs7O1dDREE7V0FDQTtXQUNBO1dBQ0EsdURBQXVELGlCQUFpQjtXQUN4RTtXQUNBLGdEQUFnRCxhQUFhO1dBQzdEOzs7Ozs7Ozs7QUNKQSxRQUFRLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsR0FBRyxFQUFFO0lBQ2xELE1BQU0sVUFBVSxHQUF1QztRQUN0RCxLQUFLLEVBQUUsbUJBQW1CO1FBQzFCLFFBQVEsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3BCLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzlCLElBQUksTUFBTSxDQUFDLFFBQVEsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDM0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDO1lBQ25ELENBQUM7UUFDRixDQUFDO0tBQ0QsQ0FBQztJQUNGLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDckQsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNaLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDM0MsSUFBSSxDQUFDO2dCQUNKLE1BQU0sSUFBSSxHQUFHLE1BQU0sR0FBRyxDQUFDLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDaEUsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1Q0FBdUMsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUM1RCxDQUFDO1lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztnQkFDZCxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3BCLENBQUM7UUFDRixDQUFDLENBQUMsQ0FBQztJQUNKLENBQUM7QUFDRixDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL2xhdW5jaC1leHRlcm5hbC1wcm9jZXNzL3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL2xhdW5jaC1leHRlcm5hbC1wcm9jZXNzL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vbGF1bmNoLWV4dGVybmFsLXByb2Nlc3MvLi9jbGllbnQvc3JjL2FwcC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCAoKSA9PiB7XG5cdGNvbnN0IGxlcE9wdGlvbnM6IE9wZW5GaW4uRXh0ZXJuYWxQcm9jZXNzUmVxdWVzdFR5cGUgPSB7XG5cdFx0YWxpYXM6IFwib2YtZG90bmV0LWV4YW1wbGVcIixcblx0XHRsaXN0ZW5lcjogKHJlc3VsdCkgPT4ge1xuXHRcdFx0Y29uc29sZS5sb2coXCJyZXN1bHRcIiwgcmVzdWx0KTtcblx0XHRcdGlmIChyZXN1bHQuZXhpdENvZGUgPT09IDEpIHtcblx0XHRcdFx0Y29uc29sZS5sb2coXCJTdWNjZXNzZnVsbHkgZXhpdGVkIERvdE5ldENvcmUuZXhlXCIpO1xuXHRcdFx0fVxuXHRcdH1cblx0fTtcblx0Y29uc3QgbGVwQnRuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNsZXAtYnV0dG9uXCIpO1xuXHRpZiAobGVwQnRuKSB7XG5cdFx0bGVwQnRuLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRjb25zdCBkYXRhID0gYXdhaXQgZmluLlN5c3RlbS5sYXVuY2hFeHRlcm5hbFByb2Nlc3MobGVwT3B0aW9ucyk7XG5cdFx0XHRcdGNvbnNvbGUubG9nKFwic3VjY2Vzc2Z1bGx5IGxhdW5jaGVkIERvdE5ldENvcmUuZXhlOlwiLCBkYXRhKTtcblx0XHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0XHRjb25zb2xlLmVycm9yKGVycik7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cbn0pO1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dev/john/update-logging-example/use-launch-external-process/manifest.fin.json b/dev/john/update-logging-example/use-launch-external-process/manifest.fin.json new file mode 100644 index 00000000..4548199e --- /dev/null +++ b/dev/john/update-logging-example/use-launch-external-process/manifest.fin.json @@ -0,0 +1,35 @@ +{ + "runtime": { + "version": "38.126.83.79" + }, + "startup_app": { + "name": "launch-app-asset", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-launch-external-process/html/app.html", + "uuid": "launch-app-asset", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-launch-external-process/common/images/icon-blue.png", + "autoShow": true, + "saveWindowState": true, + "permissions": { + "System": { + "launchExternalProcess": true, + "terminateExternalProcess": true, + "downloadAsset": true + } + } + }, + "appAssets": [ + { + "src": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-launch-external-process/assets/openfin-dotnet-example.zip", + "version": "3.1", + "alias": "of-dotnet-example", + "target": "DotNetCore.exe", + "mandatory": true + } + ], + "shortcut": { + "company": "OpenFin", + "description": "Launch App Asset", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-launch-external-process/common/images/icon-blue.png", + "name": "Launch App Asset" + } +} diff --git a/dev/john/update-logging-example/use-logging-apis/common/images/icon-blue.png b/dev/john/update-logging-example/use-logging-apis/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-logging-apis/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-logging-apis/common/style/app.css b/dev/john/update-logging-example/use-logging-apis/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-logging-apis/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-logging-apis/favicon.ico b/dev/john/update-logging-example/use-logging-apis/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-logging-apis/favicon.ico differ diff --git a/dev/john/update-logging-example/use-logging-apis/html/app.html b/dev/john/update-logging-example/use-logging-apis/html/app.html new file mode 100644 index 00000000..ff7839df --- /dev/null +++ b/dev/john/update-logging-example/use-logging-apis/html/app.html @@ -0,0 +1,62 @@ + + + + + How to collect debug logs + + + + + + + +
+
+

How to collect logs.

+

Demonstrate how to use logging APIs

+
+
+ OpenFin +
+
+
+
+
+
+
+

Select a debug log.

+
+ +
+ +
+
+

Upload your applications log.

+ +
+
+
+

Preview

+

+			
+
+ + + diff --git a/dev/john/update-logging-example/use-logging-apis/js/app.bundle.js b/dev/john/update-logging-example/use-logging-apis/js/app.bundle.js new file mode 100644 index 00000000..19bf6c9a --- /dev/null +++ b/dev/john/update-logging-example/use-logging-apis/js/app.bundle.js @@ -0,0 +1,22642 @@ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "../../node_modules/@openfin/core/out/mock.js": +/*!****************************************************!*\ + !*** ../../node_modules/@openfin/core/out/mock.js ***! + \****************************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var require$$0 = __webpack_require__(/*! events */ "../../node_modules/events/events.js"); +var require$$0$1 = __webpack_require__(/*! lodash/cloneDeep */ "../../node_modules/lodash/cloneDeep.js"); +var require$$3 = __webpack_require__(/*! lodash/isEqual */ "../../node_modules/lodash/isEqual.js"); + +function _mergeNamespaces(n, m) { + m.forEach(function (e) { + e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) { + if (k !== 'default' && !(k in n)) { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: function () { return e[k]; } + }); + } + }); + }); + return Object.freeze(n); +} + +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g : typeof self !== 'undefined' ? self : {}; + +function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; +} + +var OpenFin$2 = {}; + +var events = {}; + +var application$1 = {}; + +/** + * Namespace for events that can be emitted by an {@link OpenFin.Application}. Includes events + * re-propagated from the {@link OpenFin.Window} (and, transitively, {@link OpenFin.View}) level, prefixed with `window-` (and also, if applicable, `view-`). + * For example, a view's "attached" event will fire as 'window-view-attached' at the application level. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * This namespace contains only payload shapes for events that are unique to `Application`. Events that propagate to `Application` from + * child {@link OpenFin.Window windows} and {@link OpenFin.View views} are defined in the {@link OpenFin.WindowEvents} and + * {@link OpenFin.ViewEvents} namespaces. For a list of valid string keys for *all* application events, see {@link Application.on Application.on}. + * + * {@link ApplicationSourcedEvent Application-sourced events} (i.e. those that have not propagated from {@link OpenFin.ViewEvents Views} + * or {@link OpenFin.WindowEvents Windows} re-propagate to {@link OpenFin.SystemEvents System} with their type string prefixed with `application-`. + * {@link ApplicationWindowEvent Application events that are tied to Windows but do not propagate from them} + * are propagated to `System` without any type string prefixing. + * + * "Requested" events (e.g. {@link RunRequestedEvent}) do not propagate. + * + * @packageDocumentation + */ +Object.defineProperty(application$1, "__esModule", { value: true }); + +var base$1 = {}; + +/** + * Namespace for shared event payloads and utility types common to all event emitters. + * + * @packageDocumentation + */ +Object.defineProperty(base$1, "__esModule", { value: true }); + +var externalApplication$1 = {}; + +/** + * Namespace for events that can be transmitted by an {@link OpenFin.ExternalApplication}. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * For a list of valid string keys for external application events, see {@link ExternalApplication.on ExternalApplication.on}. + * + * @packageDocumentation + */ +Object.defineProperty(externalApplication$1, "__esModule", { value: true }); + +var frame$1 = {}; + +Object.defineProperty(frame$1, "__esModule", { value: true }); + +var globalHotkey$1 = {}; + +/** + * + * Namespace for events that can be transmitted by {@link GlobalHotkey.GlobalHotkey}. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * For a list of valid string keys for global hotkey events, see {@link GlobalHotkey.GlobalHotkey.on GlobalHotkey.on}. + * + * @packageDocumentation + */ +Object.defineProperty(globalHotkey$1, "__esModule", { value: true }); + +var platform$1 = {}; + +/** + * + * Namespace for events that can emitted by a {@link OpenFin.Platform}. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * The Platform `EventEmitter` is a superset of the {@link OpenFin.Application} `EventEmitter`, + * meaning it can listen to all {@link OpenFin.ApplicationEvents Application events} in addition to the + * Platform-specific events listed here. For a list of valid string keys for *all* platform events, see + * {@link Platform.on Platform.on}. + * + * @packageDocumentation + */ +Object.defineProperty(platform$1, "__esModule", { value: true }); + +var system$1 = {}; + +/** + * Namespace for runtime-wide OpenFin events emitted by {@link System.System}. Includes events + * re-propagated from {@link OpenFin.Application}, {@link OpenFin.Window}, and {@link OpenFin.View} (prefixed with `application-`, `window-`, and `view-`). All + * event propagations are visible at the System level. Propagated events from WebContents (windows, views, frames) to the Application level will *not* + * transitively re-propagate to the System level, because they are already visible at the system level and contain the identity + * of the application. For example, an application's "closed" event will fire as 'application-closed' at the system level. A view's 'shown' event + * will be visible as 'view-shown' at the system level, but *not* as `application-window-view-shown`. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * This namespace contains only payload shapes for events that are unique to `System`. Events that propagate to `System` from + * child {@link OpenFin.Application applications}, {@link OpenFin.Window windows}, and {@link OpenFin.View views} are defined in the + * {@link OpenFin.ApplicationEvents}, {@link OpenFin.WindowEvents}, and {@link OpenFin.ViewEvents} namespaces. For a list of valid string keys for *all* + * system events, see {@link System.on System.on}. + * + * @packageDocumentation + */ +Object.defineProperty(system$1, "__esModule", { value: true }); + +var view$1 = {}; + +/** + * Namespace for events that can be emitted by a {@link OpenFin.View}. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * This namespace contains only payload shapes for events that are unique to `View`. Events that are shared between all `WebContents` + * (i.e. {@link OpenFin.Window}, {@link OpenFin.View}) are defined in {@link OpenFin.WebContentsEvents}. For a list + * of valid string keys for *all* View events, see {@link View.on View.on}. + * + * View events propagate to their parent {@link OpenFin.WindowEvents Window}, {@link OpenFin.ApplicationEvents Application}, + * and {@link OpenFin.SystemEvents System} with an added `viewIdentity` property and their event types prefixed with `'view-'`. + * + * @packageDocumentation + */ +Object.defineProperty(view$1, "__esModule", { value: true }); + +var webcontents = {}; + +/** + * Namespace for events shared by all OpenFin WebContents elements (i.e. {@link OpenFin.Window}, + * {@link OpenFin.View}). + * + * WebContents events will re-emit on parent entities - e.g., a propagating event in a view will also be emitted on the view's + * parent window, and propagating events in a window will also be emitted on the window's parent {@link OpenFin.Application}. + * + * @packageDocumentation + */ +Object.defineProperty(webcontents, "__esModule", { value: true }); + +var window$2 = {}; + +/** + * Namespace for events that can be emitted by a {@link OpenFin.Window}. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * This namespace contains only payload shapes for events that are unique to `Window`. Events that are shared between all `WebContents` + * (i.e. {@link OpenFin.Window}, {@link OpenFin.View}) are defined in {@link OpenFin.WebContentsEvents}. Events that + * propagate from `View` are defined in {@link OpenFin.ViewEvents}. For a list of valid string keys for *all* Window events, see + * {@link Window.on Window.on} + * + * {@link OpenFin.WindowEvents.WindowSourcedEvent Window-sourced events} (i.e. those that are not propagated from a + * {@link OpenFin.ViewEvents View}) propagate to their parent {@link OpenFin.ApplicationEvents Application} and + * {@link OpenFin.SystemEvents System} with their event types prefixed with `'window-'`). + * + * "Requested" events (e.g. {@link AuthRequestedEvent}) do not propagate to `System. The {@link OpenFin.WindowEvents.WindowCloseRequestedEvent} + * does not propagate at all. + * + * @packageDocumentation + */ +Object.defineProperty(window$2, "__esModule", { value: true }); + +/** + * Namespace for OpenFin event types. Each entity that emits OpenFin events has its own sub-namespace. Event payloads + * themselves are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * + * #### Event emitters + * + * The following entities emit OpenFin events, and have corresponding sub-namespaces: + * + * * {@link OpenFin.Application}: {@link OpenFin.ApplicationEvents} + * * {@link OpenFin.ExternalApplication}: {@link OpenFin.ExternalApplicationEvents} + * * {@link OpenFin.Frame}: {@link OpenFin.FrameEvents} + * * {@link OpenFin.GlobalHotkey}: {@link OpenFin.GlobalHotkeyEvents} + * * {@link OpenFin.Platform}: {@link OpenFin.PlatformEvents} + * * {@link OpenFin.System}: {@link OpenFin.SystemEvents} + * * {@link OpenFin.View}: {@link OpenFin.ViewEvents} + * * {@link OpenFin.Window}: {@link OpenFin.WindowEvents} + * + * These `EventEmitter` entities share a common set of methods for interacting with the OpenFin event bus, which can be + * seen on the individual documentation pages for each entity type. + * + * Registering event handlers is an asynchronous operation. It is important to ensure that the returned Promises are awaited to reduce the + * risk of race conditions. + * + * When the `EventEmitter` receives an event from the browser process and emits on the renderer, all of the functions attached to that + * specific event are called synchronously. Any values returned by the called listeners are ignored and will be discarded. If the window document + * is destroyed by page navigation or reload, its registered event listeners will be removed. + * + * We recommend using Arrow Functions for event listeners to ensure the this scope is consistent with the original function context. + * + * Events re-propagate from smaller/more-local scopes to larger/more-global scopes. For example, an event emitted on a specific + * view will propagate to the window in which the view is embedded, and then to the application in which the window is running, and + * finally to the OpenFin runtime itself at the "system" level. For details on propagation semantics, see the namespace for + * the propagating (or propagated-to) entity. + * + * If you need the payload type for a specific type of event (especially propagated events), use the emitting topic's `Payload` generic + * (e.g. {@link WindowEvents.Payload}) with the event's `type` string. For example, the payload of + * a {@link ViewEvents.CreatedEvent} after it has propagated to its parent {@link WindowEvents Window} can be found with + * `WindowEvents.Payload<'view-created'>`. + * + * @packageDocumentation + */ +var __createBinding$1 = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault$1 = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar$1 = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding$1(result, mod, k); + __setModuleDefault$1(result, mod); + return result; +}; +Object.defineProperty(events, "__esModule", { value: true }); +events.WindowEvents = events.WebContentsEvents = events.ViewEvents = events.SystemEvents = events.PlatformEvents = events.GlobalHotkeyEvents = events.FrameEvents = events.ExternalApplicationEvents = events.BaseEvents = events.ApplicationEvents = void 0; +const ApplicationEvents = __importStar$1(application$1); +events.ApplicationEvents = ApplicationEvents; +const BaseEvents = __importStar$1(base$1); +events.BaseEvents = BaseEvents; +const ExternalApplicationEvents = __importStar$1(externalApplication$1); +events.ExternalApplicationEvents = ExternalApplicationEvents; +const FrameEvents = __importStar$1(frame$1); +events.FrameEvents = FrameEvents; +const GlobalHotkeyEvents = __importStar$1(globalHotkey$1); +events.GlobalHotkeyEvents = GlobalHotkeyEvents; +const PlatformEvents = __importStar$1(platform$1); +events.PlatformEvents = PlatformEvents; +const SystemEvents = __importStar$1(system$1); +events.SystemEvents = SystemEvents; +const ViewEvents = __importStar$1(view$1); +events.ViewEvents = ViewEvents; +const WebContentsEvents = __importStar$1(webcontents); +events.WebContentsEvents = WebContentsEvents; +const WindowEvents = __importStar$1(window$2); +events.WindowEvents = WindowEvents; + +(function (exports) { + /** + * Top-level namespace for types referenced by the OpenFin API. Contains: + * + * * The type of the global `fin` entry point ({@link FinApi}) + * * Classes that act as static namespaces returned from the `fin` global (e.g. {@link ApplicationModule}, accessible via `fin.Application`) + * * Instance classes that are returned from API calls (e.g. {@link Application}, accessible via `fin.Application.getCurrentSync()`) + * * Parameter shapes for API methods (e.g. {@link ApplicationOptions}, used in `fin.Application.start()`) + * * Event namespaces and payload union types (e.g. {@link ApplicationEvents} and {@link ApplicationEvent}) + * + * @packageDocumentation + */ + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + // Deprecated shim to preserve v30 namespace names + __exportStar(events, exports); +} (OpenFin$2)); + +var OpenFin = /*@__PURE__*/getDefaultExportFromCjs(OpenFin$2); + +var OpenFin$1 = /*#__PURE__*/_mergeNamespaces({ + __proto__: null, + default: OpenFin +}, [OpenFin$2]); + +var fin$2 = {}; + +var system = {}; + +var base = {}; + +var promises = {}; + +Object.defineProperty(promises, "__esModule", { value: true }); +promises.promiseMapSerial = promises.serial = promises.promiseMap = promises.promisify = void 0; +function promisify(func) { + return (...args) => new Promise((resolve, reject) => { + func(...args, (err, val) => (err ? reject(err) : resolve(val))); + }); +} +promises.promisify = promisify; +async function promiseMap(arr, asyncF) { + return Promise.all(arr.map(asyncF)); +} +promises.promiseMap = promiseMap; +async function serial(arr) { + const ret = []; + for (const func of arr) { + // eslint-disable-next-line no-await-in-loop + const next = await func(); + ret.push(next); + } + return ret; +} +promises.serial = serial; +async function promiseMapSerial(arr, func) { + return serial(arr.map((value, index, array) => () => func(value, index, array))); +} +promises.promiseMapSerial = promiseMapSerial; + +var __classPrivateFieldSet$c = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$e = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _EmitterBase_emitterAccessor; +Object.defineProperty(base, "__esModule", { value: true }); +base.Reply = base.EmitterBase = base.Base = void 0; +const promises_1 = promises; +class Base { + /** + * @internal + */ + constructor(wire) { + /** + * @internal + * @deprecated + */ + this.isNodeEnvironment = () => { + return this.wire.environment.type === 'node'; + }; + /** + * @internal + * @deprecated + */ + this.isOpenFinEnvironment = () => { + return this.wire.environment.type === 'openfin'; + }; + /** + * @internal + * @deprecated + */ + this.isBrowserEnvironment = () => { + return this.wire.environment.type === 'other'; + }; + this.wire = wire; + } + get fin() { + return this.wire.getFin(); + } + /** + * Provides access to the OpenFin representation of the current code context (usually a document + * such as a {@link OpenFin.View} or {@link OpenFin.Window}), as well as to the current `Interop` context. + * + * Useful for debugging in the devtools console, where this will intelligently type itself based + * on the context in which the devtools panel was opened. + */ + get me() { + return this.wire.me; + } +} +base.Base = Base; +/** + * An entity that emits OpenFin events. + * + * @remarks Event-binding methods are asynchronous as they must cross process boundaries + * and setup the listener in the browser process. When the `EventEmitter` receives an event from the browser process + * and emits on the renderer, all of the functions attached to that specific event are called synchronously. Any values + * returned by the called listeners are ignored and will be discarded. If the execution context of the window is destroyed + * by page navigation or reload, any events that have been setup in that context will be destroyed. + * + * It is important to keep in mind that when an ordinary listener function is called, the standard `this` keyword is intentionally + * set to reference the `EventEmitter` instance to which the listener is attached. It is possible to use ES6 Arrow Functions as + * listeners, however, when doing so, the `this` keyword will no longer reference the `EventEmitter` instance. + * + * Events re-propagate from smaller/more-local scopes to larger/more-global scopes. For example, an event emitted on a specific + * view will propagate to the window in which the view is embedded, and then to the application in which the window is running, and + * finally to the OpenFin runtime itself at the "system" level. Re-propagated events are prefixed with the name of the scope in which + * they originated - for example, a "shown" event emitted on a view will be re-propagated at the window level as "view-shown", and + * then to the application as "window-view-shown", and finally at the system level as "application-window-view-shown". + * + * All event propagations are visible at the System level, regardless of source, so transitive re-propagations (e.g. from view to window + * to application) are visible in their entirety at the system level. So, we can listen to the above event as "shown", "view-shown", + * "window-view-shown", or "application-window-view-shown." + */ +class EmitterBase extends Base { + constructor(wire, topic, ...additionalAccessors) { + super(wire); + this.topic = topic; + _EmitterBase_emitterAccessor.set(this, void 0); + this.eventNames = () => (this.hasEmitter() ? this.getOrCreateEmitter().eventNames() : []); + /** + * @internal + */ + this.emit = (eventType, payload, ...args) => { + return this.hasEmitter() ? this.getOrCreateEmitter().emit(eventType, payload, ...args) : false; + }; + this.hasEmitter = () => this.wire.eventAggregator.has(__classPrivateFieldGet$e(this, _EmitterBase_emitterAccessor, "f")); + this.getOrCreateEmitter = () => this.wire.eventAggregator.getOrCreate(__classPrivateFieldGet$e(this, _EmitterBase_emitterAccessor, "f")); + this.listeners = (type) => this.hasEmitter() ? this.getOrCreateEmitter().listeners(type) : []; + this.listenerCount = (type) => this.hasEmitter() ? this.getOrCreateEmitter().listenerCount(type) : 0; + this.registerEventListener = async (eventType, options = {}, applySubscription, undoSubscription) => { + const runtimeEvent = { + ...this.identity, + timestamp: options.timestamp || Date.now(), + topic: this.topic, + type: eventType + }; + const emitter = this.getOrCreateEmitter(); + // We apply the subscription and then undo if the async call fails to avoid + // indeterminacy in subscription application order, which can break things elsewhere + applySubscription(emitter); + try { + await this.wire.sendAction('subscribe-to-desktop-event', runtimeEvent); + } + catch (e) { + undoSubscription(emitter); + this.deleteEmitterIfNothingRegistered(emitter); + throw e; + } + }; + this.deregisterEventListener = async (eventType, options = {}) => { + if (this.hasEmitter()) { + const runtimeEvent = { + ...this.identity, + timestamp: options.timestamp || Date.now(), + topic: this.topic, + type: eventType + }; + await this.wire.sendAction('unsubscribe-to-desktop-event', runtimeEvent).catch(() => null); + const emitter = this.getOrCreateEmitter(); + return emitter; + } + // This will only be reached if unsubscribe from event that does not exist but do not want to error here + return Promise.resolve(); + }; + __classPrivateFieldSet$c(this, _EmitterBase_emitterAccessor, [topic, ...additionalAccessors], "f"); + this.listeners = (event) => this.hasEmitter() ? this.getOrCreateEmitter().listeners(event) : []; + } + /** + * Adds a listener to the end of the listeners array for the specified event. + * + * @remarks Event payloads are documented in the {@link OpenFin.Events} namespace. + */ + async on(eventType, listener, options) { + await this.registerEventListener(eventType, options, (emitter) => { + emitter.on(eventType, listener); + }, (emitter) => { + emitter.removeListener(eventType, listener); + }); + return this; + } + /** + * Adds a listener to the end of the listeners array for the specified event. + */ + async addListener(eventType, listener, options) { + return this.on(eventType, listener, options); + } + /** + * Adds a one time listener for the event. The listener is invoked only the first time the event is fired, after which it is removed. + * + * @remarks Event payloads are documented in the {@link OpenFin.Events} namespace. + */ + async once(eventType, listener, options) { + const deregister = () => this.deregisterEventListener(eventType); + await this.registerEventListener(eventType, options, (emitter) => { + emitter.once(eventType, deregister); + emitter.once(eventType, listener); + }, (emitter) => { + emitter.removeListener(eventType, deregister); + emitter.removeListener(eventType, listener); + }); + return this; + } + /** + * Adds a listener to the beginning of the listeners array for the specified event. + * + * @remarks Event payloads are documented in the {@link OpenFin.Events} namespace. + */ + async prependListener(eventType, listener, options) { + await this.registerEventListener(eventType, options, (emitter) => { + emitter.prependListener(eventType, listener); + }, (emitter) => { + emitter.removeListener(eventType, listener); + }); + return this; + } + /** + * Adds a one time listener for the event. The listener is invoked only the first time the event is fired, + * after which it is removed. The listener is added to the beginning of the listeners array. + * + * @remarks Event payloads are documented in the {@link OpenFin.Events} namespace. + */ + async prependOnceListener(eventType, listener, options) { + const deregister = () => this.deregisterEventListener(eventType); + await this.registerEventListener(eventType, options, (emitter) => { + emitter.prependOnceListener(eventType, listener); + emitter.once(eventType, deregister); + }, (emitter) => { + emitter.removeListener(eventType, listener); + emitter.removeListener(eventType, deregister); + }); + return this; + } + /** + * Remove a listener from the listener array for the specified event. + * + * @remarks Caution: Calling this method changes the array indices in the listener array behind the listener. + */ + async removeListener(eventType, listener, options) { + const emitter = await this.deregisterEventListener(eventType, options); + if (emitter) { + emitter.removeListener(eventType, listener); + this.deleteEmitterIfNothingRegistered(emitter); + } + return this; + } + async deregisterAllListeners(eventType) { + const runtimeEvent = { ...this.identity, type: eventType, topic: this.topic }; + if (this.hasEmitter()) { + const emitter = this.getOrCreateEmitter(); + const refCount = emitter.listenerCount(runtimeEvent.type); + const unsubscribePromises = []; + for (let i = 0; i < refCount; i++) { + unsubscribePromises.push(this.wire.sendAction('unsubscribe-to-desktop-event', runtimeEvent).catch(() => null)); + } + await Promise.all(unsubscribePromises); + return emitter; + } + return undefined; + } + /** + * Removes all listeners, or those of the specified event. + * + */ + async removeAllListeners(eventType) { + const removeByEvent = async (event) => { + const emitter = await this.deregisterAllListeners(event); + if (emitter) { + emitter.removeAllListeners(event); + this.deleteEmitterIfNothingRegistered(emitter); + } + }; + if (eventType) { + await removeByEvent(eventType); + } + else if (this.hasEmitter()) { + const events = this.getOrCreateEmitter().eventNames(); + await (0, promises_1.promiseMap)(events, removeByEvent); + } + return this; + } + deleteEmitterIfNothingRegistered(emitter) { + if (emitter.eventNames().length === 0) { + this.wire.eventAggregator.delete(__classPrivateFieldGet$e(this, _EmitterBase_emitterAccessor, "f")); + } + } +} +base.EmitterBase = EmitterBase; +_EmitterBase_emitterAccessor = new WeakMap(); +class Reply { +} +base.Reply = Reply; + +var transportErrors = {}; + +Object.defineProperty(transportErrors, "__esModule", { value: true }); +transportErrors.RuntimeError = transportErrors.NotSupportedError = transportErrors.NotImplementedError = transportErrors.NoAckError = transportErrors.DuplicateCorrelationError = transportErrors.UnexpectedActionError = transportErrors.DisconnectedError = void 0; +class DisconnectedError extends Error { + constructor(readyState) { + super(`Expected websocket state OPEN but found ${readyState}`); + this.readyState = readyState; + } +} +transportErrors.DisconnectedError = DisconnectedError; +class UnexpectedActionError extends Error { +} +transportErrors.UnexpectedActionError = UnexpectedActionError; +class DuplicateCorrelationError extends Error { +} +transportErrors.DuplicateCorrelationError = DuplicateCorrelationError; +class NoAckError extends Error { +} +transportErrors.NoAckError = NoAckError; +class NotImplementedError extends Error { +} +transportErrors.NotImplementedError = NotImplementedError; +class NotSupportedError extends Error { +} +transportErrors.NotSupportedError = NotSupportedError; +class InternalError extends Error { + constructor(err) { + const { message, name, stack, ...rest } = err; + super(message); + this.name = name || 'Error'; + this.stack = stack ?? this.toString(); + Object.keys(rest).forEach(key => { + this[key] = rest[key]; + }); + } +} +// For documentation of the error methods being used see here: https://v8.dev/docs/stack-trace-api +class RuntimeError extends Error { + static getCallSite(callsToRemove = 0) { + const length = Error.stackTraceLimit; + const realCallsToRemove = callsToRemove + 1; // remove this call; + Error.stackTraceLimit = length + realCallsToRemove; + // eslint-disable-next-line no-underscore-dangle + const _prepareStackTrace = Error.prepareStackTrace; + // This will be called when we access the `stack` property + Error.prepareStackTrace = (_, stack) => stack; + // stack is optional in non chromium contexts + const stack = new Error().stack?.slice(realCallsToRemove) ?? []; + Error.prepareStackTrace = _prepareStackTrace; + Error.stackTraceLimit = length; + return stack; + } + static prepareStackTrace(err, callSites) { + if (typeof Error.prepareStackTrace === 'function') { + return Error.prepareStackTrace(err, callSites); + } + let string = ""; + string += err.name || "Error"; + string += `: ${err.message || ""}`; + for (const callSite of callSites) { + string += `\n at ${callSite.toString()}`; + } + return string; + } + ; + constructor(payload, callSites) { + const { reason, error } = payload; + super(reason); + this.name = 'RuntimeError'; + if (error?.stack) { + this.cause = new InternalError(error); + } + if (callSites) { + this.stack = RuntimeError.prepareStackTrace(this, callSites); + } + } +} +transportErrors.RuntimeError = RuntimeError; + +var window$1 = {}; + +var Factory$8 = {}; + +var validate = {}; + +Object.defineProperty(validate, "__esModule", { value: true }); +validate.validateIdentity = void 0; +function validateIdentity(identity) { + let errorMsg; + if (typeof identity !== 'object' || typeof identity.uuid !== 'string') { + errorMsg = 'Not a valid identity object'; + } + return errorMsg; +} +validate.validateIdentity = validateIdentity; + +var Instance$7 = {}; + +var application = {}; + +var Factory$7 = {}; + +var Instance$6 = {}; + +var view = {}; + +var Factory$6 = {}; + +var warnings = {}; + +Object.defineProperty(warnings, "__esModule", { value: true }); +warnings.handleDeprecatedWarnings = void 0; +const handleDeprecatedWarnings = (options) => { + if (options.contentNavigation?.whitelist || + options.contentNavigation?.blacklist || + options.contentRedirect?.whitelist || + options.contentRedirect?.blacklist) { + console.warn(`The properties 'whitelist' and 'blacklist' have been marked as deprecated and will be removed in a future version. Please use 'allowlist' and 'denylist'.`); + } +}; +warnings.handleDeprecatedWarnings = handleDeprecatedWarnings; + +var hasRequiredFactory$3; + +function requireFactory$3 () { + if (hasRequiredFactory$3) return Factory$6; + hasRequiredFactory$3 = 1; + Object.defineProperty(Factory$6, "__esModule", { value: true }); + Factory$6.ViewModule = void 0; + const base_1 = base; + const validate_1 = validate; + const index_1 = requireView(); + const warnings_1 = warnings; + /** + * Static namespace for OpenFin API methods that interact with the {@link View} class, available under `fin.View`. + */ + class ViewModule extends base_1.Base { + /** + * Creates a new View. + * @param options - View creation options + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameCreate', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * createView() + * .then((createdView) => { + * view = createdView; + * console.log('View created.', view); + * view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * }) + * .catch(err => console.log(err)); + * ``` + * Note that created views needs to navigate somewhere for them to actually render a website. + * @experimental + */ + async create(options) { + const { uuid } = this.wire.me; + if (!options.name || typeof options.name !== 'string') { + throw new Error('Please provide a name property as a string in order to create a View.'); + } + (0, warnings_1.handleDeprecatedWarnings)(options); + if (this.wire.environment.childViews) { + await this.wire.environment.createChildContent({ + entityType: 'view', + options: { ...options, uuid } + }); + } + else { + await this.wire.sendAction('create-view', { ...options, uuid }); + } + return this.wrapSync({ uuid, name: options.name }); + } + /** + * Asynchronously returns an API handle for the given View identity. + * + * @remarks Wrapping a View identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a View throughout its entire lifecycle. + * + * @example + * ```js + * fin.View.wrap({ uuid: 'testViewUuid', name: 'testViewName' })) + * .then(view => console.log('wrapped view', view)) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + async wrap(identity) { + this.wire.sendAction('view-wrap').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new index_1.View(this.wire, identity); + } + /** + * Synchronously returns an API handle for the given View identity. + * + * @remarks Wrapping a View identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a View throughout its entire lifecycle. + * + * @example + * ```js + * const view = fin.View.wrapSync({ uuid: 'testView', name: 'testViewName' }); + * await view.hide(); + * ``` + * @experimental + */ + wrapSync(identity) { + this.wire.sendAction('view-wrap-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new index_1.View(this.wire, identity); + } + /** + * Asynchronously returns a View object that represents the current view + * + * @example + * ```js + * fin.View.getCurrent() + * .then(view => console.log('current view', view)) + * .catch(err => console.log(err)); + * + * ``` + * @experimental + */ + getCurrent() { + this.wire.sendAction('view-get-current').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (!this.wire.me.isView) { + throw new Error('You are not in a View context'); + } + const { uuid, name } = this.wire.me; + return this.wrap({ uuid, name }); + } + /** + * Synchronously returns a View object that represents the current view + * + * @example + * ```js + * const view = fin.View.getCurrentSync(); + * console.log(view); + * + * ``` + * @experimental + */ + getCurrentSync() { + this.wire.sendAction('view-get-current-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (!this.wire.me.isView) { + throw new Error('You are not in a View context'); + } + const { uuid, name } = this.wire.me; + return this.wrapSync({ uuid, name }); + } + } + Factory$6.ViewModule = ViewModule; + return Factory$6; +} + +var Instance$5 = {}; + +var lazy = {}; + +Object.defineProperty(lazy, "__esModule", { value: true }); +lazy.AsyncRetryableLazy = lazy.Lazy = void 0; +/** + * Handy class for managing asynchronous dependencies of classes. + * + * Will call the producer function once and only once when getValue is called, + * returning the resultant value for every subsequent call. + */ +class Lazy { + // eslint-disable-next-line + constructor(producerFn) { + this.producerFn = producerFn; + } + /** + * Lazily get the value returned by the producer. + * @returns The value returned from the producer function + */ + getValue() { + if (!this.value) { + this.value = this.producerFn(); + } + return this.value; + } +} +lazy.Lazy = Lazy; +/** + * Handy class for managing asynchronous dependencies of classes. + * + * Will call asynchronous producer only after `getValue` is called. If the + * deferred code errors, we can try it again by re-calling `getValue` after + * the promise rejects. + */ +class AsyncRetryableLazy { + // eslint-disable-next-line + constructor(producerFn) { + this.producerFn = producerFn; + } + /** + * Lazily get the value returned by the async producer. + * + * @returns The value returned from the producer function + */ + async getValue() { + if (!this.promise) { + this.promise = this.producerFn().catch((e) => { + delete this.promise; + throw e; + }); + } + return this.promise; + } +} +lazy.AsyncRetryableLazy = AsyncRetryableLazy; + +var layoutEntities = {}; + +var apiExposer$1 = {}; + +var apiConsumer = {}; + +Object.defineProperty(apiConsumer, "__esModule", { value: true }); +apiConsumer.ApiConsumer = void 0; +/** + * Consumer for apis exposed with {@see ApiExposer}. + * + * A strategy that matches the strategy used to expose a target API must be provided. + */ +class ApiConsumer { + // eslint-disable-next-line + constructor(strategy) { + this.strategy = strategy; + /** + * Consumes an api exposed using a given transport strategy, and generates a client + * for easy, type safe consumption of that client. + * @param options Strategy specific consumption options. + * @returns An api client matching the given type. + */ + this.consume = async (options) => { + const exposedProperties = await this.strategy.getExposedFunctions(options); + return exposedProperties.reduce((client, prop) => ({ + ...client, + [prop.key]: this.strategy.createFunction(prop, options) + }), {}); + }; + } +} +apiConsumer.ApiConsumer = ApiConsumer; + +var apiExposer = {}; + +var decorators = {}; + +Object.defineProperty(decorators, "__esModule", { value: true }); +decorators.expose = decorators.getExposedProperties = void 0; +const exposedProperties = Symbol('exposedProperties'); +const getExposedProperties = (target) => { + return target[exposedProperties] || target.prototype[exposedProperties] || []; +}; +decorators.getExposedProperties = getExposedProperties; +/** + * Indicates that a class member function can be exposed using {@link ApiExposer}. + * @param options Options specific to the strategy used in {@link ApiExposer} + */ +// Returns any as decorator typing is weird. +const expose = (options) => (target, key, descriptor) => { + target[exposedProperties] = target[exposedProperties] || []; + target[exposedProperties].push({ key, descriptor, options }); +}; +decorators.expose = expose; + +Object.defineProperty(apiExposer, "__esModule", { value: true }); +apiExposer.ApiExposer = void 0; +const decorators_1 = decorators; +/** + * Exposes api services on the transport of choice. + */ +class ApiExposer { + /** + * @param strategy The expose strategy to use to expose instances. + */ + // eslint-disable-next-line + constructor(strategy) { + this.strategy = strategy; + /** + * Exposes an instance of a given api on + * @param instance Instance of a class which has been decorated to indicate which functions can be exposed. + * @param instanceOptions Transport strategy specific options to use when exposing. + */ + this.exposeInstance = async (instance, instanceOptions) => { + const exposableProps = (0, decorators_1.getExposedProperties)(instance); + const exposedProps = await Promise.all(exposableProps.map(async ({ key, options }) => { + const customConsumptionOptions = await this.strategy.exposeFunction(instance[key].bind(instance), { + key, + options, + meta: instanceOptions + }); + return { + key, + options: customConsumptionOptions + }; + })); + await this.strategy.exposeMeta(instanceOptions, exposedProps); + }; + } + ; +} +apiExposer.ApiExposer = ApiExposer; + +var strategies = {}; + +var openfinChannels = {}; + +var channelsConsumer = {}; + +Object.defineProperty(channelsConsumer, "__esModule", { value: true }); +channelsConsumer.ChannelsConsumer = void 0; +class ChannelsConsumer { + // eslint-disable-next-line + constructor(channel) { + this.channel = channel; + this.getExposedFunctions = async (options) => { + const { id } = options; + const { props } = await this.channel.dispatch(`api-meta:${id}`); + return props; + }; + this.createFunction = (prop) => (...args) => { + const { action } = prop.options; + return this.channel.dispatch(action, { args }); + }; + } + ; +} +channelsConsumer.ChannelsConsumer = ChannelsConsumer; + +var channelsExposer = {}; + +Object.defineProperty(channelsExposer, "__esModule", { value: true }); +channelsExposer.ChannelsExposer = void 0; +class ChannelsExposer { + // eslint-disable-next-line + constructor(channelProviderOrClient) { + this.channelProviderOrClient = channelProviderOrClient; + this.exposeFunction = async (target, config) => { + const { key, options, meta } = config; + const { id } = meta; + const action = `${id}.${options?.action || key}`; + await this.channelProviderOrClient.register(action, async ({ args }) => { + return target(...args); + }); + return { action }; + }; + this.exposeMeta = async ({ id }, props) => { + const action = `api-meta:${id}`; + await this.channelProviderOrClient.register(action, () => ({ props })); + }; + } +} +channelsExposer.ChannelsExposer = ChannelsExposer; + +(function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(channelsConsumer, exports); + __exportStar(channelsExposer, exports); +} (openfinChannels)); + +(function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(openfinChannels, exports); +} (strategies)); + +(function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(apiConsumer, exports); + __exportStar(apiExposer, exports); + __exportStar(strategies, exports); + __exportStar(decorators, exports); +} (apiExposer$1)); + +var channelApiRelay = {}; + +Object.defineProperty(channelApiRelay, "__esModule", { value: true }); +channelApiRelay.createRelayedDispatch = channelApiRelay.relayChannelClientApi = void 0; +const EXPECTED_ERRORS = [ + 'no longer connected', + 'RTCDataChannel closed unexpectedly', + 'The client you are trying to dispatch from is disconnected from the target provider', +]; +// Checks possible error messages that we want to trap, client error message can originate +// from ChannelProvider::dispatch OR ClassicStrategy::closeEndpoint OR RTCEndPoint::dataChannel::onclose +const isDisconnectedError = (errorMsg) => { + return EXPECTED_ERRORS.some(e => errorMsg.includes(e)); +}; +/** + * @internal + * Create a channel relay for a given channel exposition, allowing a single provider to route + * actions to the designated clients. + * + * Designed to be used in conjunction with @expose + * + * @param channelProvider The channel provider to relay the actions on. + * @param config Determines which actions to relay. Please ensure action prefix matches the exposed api. + */ +const relayChannelClientApi = async (channelProvider, relayId) => { + channelProvider.register(`relay:${relayId}`, ({ action, target, payload }) => { + return channelProvider.dispatch(target, action, payload); + }); + await Promise.resolve(); +}; +channelApiRelay.relayChannelClientApi = relayChannelClientApi; +const createRelayedDispatch = (client, target, relayId, relayErrorMsg) => async (action, payload) => { + try { + return await client.dispatch(`relay:${relayId}`, { + action, + payload, + target + }); + } + catch (e) { + if (isDisconnectedError(e.message) && relayErrorMsg) { + throw new Error(relayErrorMsg); + } + throw e; + } +}; +channelApiRelay.createRelayedDispatch = createRelayedDispatch; + +var __classPrivateFieldSet$b = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$d = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _LayoutNode_client, _TabStack_client, _ColumnOrRow_client; +Object.defineProperty(layoutEntities, "__esModule", { value: true }); +layoutEntities.ColumnOrRow = layoutEntities.TabStack = layoutEntities.LayoutNode = void 0; +const api_exposer_1 = apiExposer$1; +const channel_api_relay_1 = channelApiRelay; +/* + This file includes LayoutNode, ColumnOrRow and TabStack classes, which are all closely + intertwined, and share members via parent abstract class LayoutNode. To prevent circular + refs, we define and export all the classes here. +*/ +/** + * @ignore + * @internal + * Supplies an ApiClient for {@link LayoutEntitiesController} and helper methods + * for the entities {@link TabStack} AND {@link ColumnOrRow} to use. + */ +class LayoutNode { + /** + * @internal + * @ignore + */ + constructor(client, entityId) { + /** + * @ignore + * @internal + * ApiClient for {@link LayoutEntitiesController} + */ + _LayoutNode_client.set(this, void 0); + /** + * Checks if the TabStack or ColumnOrRow is the root content item + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * const isRoot = await stack.isRoot(); + * // The TabStack is root: false + * console.log(`The TabStack is root: ${isRoot}`); + * + * // Retrieves the parent ColumnOrRow + * const parent = await stack.getParent(); + * const parentIsRoot = await parent.isRoot(); + * // The parent ColumnOrRow is root: true + * console.log(`The parent ColumnOrRow is root: ${parentIsRoot}`); + * ``` + */ + this.isRoot = () => __classPrivateFieldGet$d(this, _LayoutNode_client, "f").isRoot(this.entityId); + /** + * Checks if the TabStack or ColumnOrRow exists + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Retrieves the parent ColumnOrRow + * const columnOrRow = await stack.getParent(); + * let exists = await stack.exists(); + * // or + * let exists = await columnOrRow.exists(); + * // The entity exists: true + * console.log(`The entity exists: ${exists}`); + * ``` + */ + this.exists = () => __classPrivateFieldGet$d(this, _LayoutNode_client, "f").exists(this.entityId); + /** + * Retrieves the parent of the TabStack or ColumnOrRow + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Retrieves the parent ColumnOrRow + * const columnOrRow = await stack.getParent(); + * + * // undefined if entity is the root item + * let parent = await columnOrRow.getParent(); + * // or + * let parent = await stack.getParent(); + * ``` + */ + this.getParent = async () => { + const parent = await __classPrivateFieldGet$d(this, _LayoutNode_client, "f").getParent(this.entityId); + if (!parent) { + return undefined; + } + return LayoutNode.getEntity(parent, __classPrivateFieldGet$d(this, _LayoutNode_client, "f")); + }; + /** + * Creates a new TabStack adjacent to the given TabStack or ColumnOrRow. Inputs can be new views to create, or existing views. + * + * Known Issue: If the number of views to add overflows the tab-container, the added views will be set as active + * during each render, and then placed at the front of the tab-stack, while the underlying order of tabs will remain unchanged. + * This means the views you pass to createAdjacentStack() may not render in the order given by the array. + * Until fixed, this problem can be avoided only if your window is wide enough to fit creating all the views in the tabstack. + * + * @param views The views that will populate the new TabStack. + * @param options Additional options that control new TabStack creation. + * @returns The newly-created TabStack. + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * const columnOrRow = await stack.getParent(); + * + * // Create view references by supplying a 'name' and 'url' + * const views = [ + * // if 'name' is undefined, one will be generated + * // if 'url' is undefined, it will default the view URL to 'about:blank' + * { name: 'google-view', url: 'http://google.com/'}, + * { name: 'of-developers-view', url: 'http://developers.openfin.co/'}, + * ]; + * + * // Create a view beforehand to be included in the new tab stack + * const outsideView = await fin.View.create({ + * name: 'outside-bloomberg-view', + * url: 'https://bloomberg.com/', + * target: fin.me.identity, + * }); + * + * // Views to add can be identities, or the reference views mentioned above + * const viewsToAdd = [outsideView.identity, ...views]; + * + * // Possible position inputs: 'right' | 'left' | 'top' | 'bottom' + * let stackFrom = await columnOrRow.createAdjacentStack(viewsToAdd, { position: 'right' }); + * // Or + * let newStack = await stack.createAdjacentStack(viewsToAdd, { position: 'right' }); + * console.log(`A new TabStack created to the right has ${newStack.length} views in it`); + * + * ``` + * @experimental + */ + this.createAdjacentStack = async (views, options) => { + const entityId = await __classPrivateFieldGet$d(this, _LayoutNode_client, "f").createAdjacentStack(this.entityId, views, options); + return LayoutNode.getEntity({ entityId, type: 'stack' }, __classPrivateFieldGet$d(this, _LayoutNode_client, "f")); + }; + /** + * Retrieves the adjacent TabStacks of the given TabStack or ColumnOrRow. + * + * @param edge Edge whose adjacent TabStacks will be returned. + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * const columnOrRow = await stack.getParent(); + * // Possible position inputs: 'right' | 'left' | 'top' | 'bottom' + * let rightStacks = await columnOrRow.getAdjacentStacks('right'); + * let leftStacks = await columnOrRow.getAdjacentStacks('left'); + * // or + * let rightStacks = await stack.getAdjacentStacks('right'); + * let leftStacks = await stack.getAdjacentStacks('left'); + * + * console.log(`The entity has ${rightStacks.length} stacks to the right, and ${leftStacks.length} stacks to the left`); + * + * ``` + * @experimental + */ + this.getAdjacentStacks = async (edge) => { + const adjacentStacks = await __classPrivateFieldGet$d(this, _LayoutNode_client, "f").getAdjacentStacks({ + targetId: this.entityId, + edge + }); + return adjacentStacks.map((stack) => LayoutNode.getEntity({ + type: 'stack', + entityId: stack.entityId + }, __classPrivateFieldGet$d(this, _LayoutNode_client, "f"))); + }; + __classPrivateFieldSet$b(this, _LayoutNode_client, client, "f"); + this.entityId = entityId; + } +} +layoutEntities.LayoutNode = LayoutNode; +_LayoutNode_client = new WeakMap(); +/** + * @ignore + * @internal + * Encapsulates Api consumption of {@link LayoutEntitiesClient} with a relayed dispatch + * @param client + * @param controllerId + * @param identity + * @returns a new instance of {@link LayoutEntitiesClient} with bound to the controllerId + */ +LayoutNode.newLayoutEntitiesClient = async (client, controllerId, identity) => { + const dispatch = (0, channel_api_relay_1.createRelayedDispatch)(client, identity, 'layout-relay', 'You are trying to interact with a layout component on a window that does not exist or has been destroyed.'); + const consumer = new api_exposer_1.ApiConsumer(new api_exposer_1.ChannelsConsumer({ dispatch })); + return consumer.consume({ id: controllerId }); +}; +LayoutNode.getEntity = (definition, client) => { + const { entityId, type } = definition; + switch (type) { + case 'column': + case 'row': + return new ColumnOrRow(client, entityId, type); + case 'stack': + return new TabStack(client, entityId); + default: + throw new Error(`Unrecognised Layout Entity encountered ('${JSON.stringify(definition)})`); + } +}; +/** + * A TabStack is used to manage the state of a stack of tabs within an OpenFin Layout. + */ +class TabStack extends LayoutNode { + /** @internal */ + constructor(client, entityId) { + super(client, entityId); + /** + * @internal + * ApiClient for {@link LayoutEntitiesController} + */ + _TabStack_client.set(this, void 0); + /** + * Type of the content item. Always stack, but useful for distinguishing between a {@link TabStack} and {@link ColumnOrRow}. + */ + this.type = 'stack'; + /** + * Retrieves a list of all views belonging to this {@link TabStack}. + * + * Known Issue: If adding a view overflows the tab-container width, the added view will be set as active + * and rendered at the front of the tab-stack, while the underlying order of tabs will remain unchanged. + * If that happens and then getViews() is called, it will return the identities in a different order than + * than the currently rendered tab order. + * + * + * @throws If the {@link TabStack} has been destroyed. + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Alternatively, you can wrap any view and get the stack from there + * // const viewFromSomewhere = fin.View.wrapSync(someView.identity); + * // const stack = await viewFromSomewhere.getCurrentStack(); + * const views = await stack.getViews(); + * console.log(`Stack contains ${views.length} view(s)`); + * ``` + * @experimental + */ + this.getViews = () => __classPrivateFieldGet$d(this, _TabStack_client, "f").getStackViews(this.entityId); + /** + * Adds or creates a view in this {@link TabStack}. + * + * @remarks Known Issue: If adding a view overflows the tab-container, the added view will be set as active + * and rendered at the front of the tab-stack, while the underlying order of tabs will remain unchanged. + * + * @param view The identity of an existing view to add, or options to create a view. + * @param options Optional view options: index number used to insert the view into the stack at that index. Defaults to 0 (front of the stack) + * @returns Resolves with the {@link OpenFin.Identity identity} of the added view. + * @throws If the view does not exist or fails to create. + * @throws If the {@link TabStack} has been destroyed. + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Alternatively, you can wrap any view and get the stack from there + * // const viewFromSomewhere = fin.View.wrapSync(someView.identity); + * // const stack = await viewFromSomewhere.getCurrentStack(); + * const googleViewIdentity = await stack.addView({ name: 'google-view', url: 'http://google.com/' }); + * console.log('Identity of the google view just added', { googleViewIdentity }); + * // pass in { index: number } to set the index in the stack. Here 1 means, end of the stack (defaults to 0) + * const appleViewIdentity = await stack.addView({ name: 'apple-view', url: 'http://apple.com/' }, { index: 1 }); + * console.log('Identity of the apple view just added', { appleViewIdentity }); + * ``` + * @experimental + */ + this.addView = async (view, options = { index: 0 }) => __classPrivateFieldGet$d(this, _TabStack_client, "f").addViewToStack(this.entityId, view, options); + /** + * Removes a view from this {@link TabStack}. + * + * @remarks Throws an exception if the view identity does not exist or was already destroyed. + * + * @param view - Identity of the view to remove. + * @throws If the view does not exist or does not belong to the stack. + * @throws If the {@link TabStack} has been destroyed. + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * const googleViewIdentity = await stack.addView({ name: 'google-view', url: 'http://google.com/' }); + * + * await stack.removeView(googleViewIdentity); + * + * try { + * await stack.removeView(googleViewIdentity); + * } catch (error) { + * // Tried to remove a view ('google-view') which does not belong to the stack. + * console.log(error); + * } + * ``` + */ + this.removeView = async (view) => { + await __classPrivateFieldGet$d(this, _TabStack_client, "f").removeViewFromStack(this.entityId, view); + }; + /** + * Sets the active view of the {@link TabStack} without focusing it. + * @param view - Identity of the view to activate. + * @returns Promise which resolves with void once the view has been activated. + * @throws If the {@link TabStack} has been destroyed. + * @throws If the view does not exist. + * @example + * Change the active tab of a known View's TabStack: + * ```js + * const targetView = fin.View.wrapSync({ uuid: 'uuid', name: 'view-name' }); + * const stack = await targetView.getCurrentStack(); + * await stack.setActiveView(targetView.identity); + * ``` + * + * Set the current View as active within its TabStack: + * ```js + * const stack = await fin.me.getCurrentStack(); + * await stack.setActiveView(fin.me.identity); + * ``` + * @experimental + */ + this.setActiveView = async (view) => { + await __classPrivateFieldGet$d(this, _TabStack_client, "f").setStackActiveView(this.entityId, view); + }; + __classPrivateFieldSet$b(this, _TabStack_client, client, "f"); + } +} +layoutEntities.TabStack = TabStack; +_TabStack_client = new WeakMap(); +/** + * A ColumnOrRow is used to manage the state of Column and Rows within an OpenFin Layout. + */ +class ColumnOrRow extends LayoutNode { + /** + * @internal + */ + constructor(client, entityId, type) { + super(client, entityId); + /** + * @ignore + * @internal + * ApiClient for {@link LayoutEntitiesController} + */ + _ColumnOrRow_client.set(this, void 0); + /** + * Retrieves the content array of the ColumnOrRow + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Retrieves the parent ColumnOrRow + * const columnOrRow = await stack.getParent(); + * + * // returns [TabStack] + * const contentArray = await columnOrRow.getContent(); + * console.log(`The ColumnOrRow has ${contentArray.length} item(s)`); + * ``` + */ + this.getContent = async () => { + const contentItemEntities = await __classPrivateFieldGet$d(this, _ColumnOrRow_client, "f").getContent(this.entityId); + return contentItemEntities.map((entity) => LayoutNode.getEntity(entity, __classPrivateFieldGet$d(this, _ColumnOrRow_client, "f"))); + }; + __classPrivateFieldSet$b(this, _ColumnOrRow_client, client, "f"); + this.type = type; + } +} +layoutEntities.ColumnOrRow = ColumnOrRow; +_ColumnOrRow_client = new WeakMap(); + +var layout_constants = {}; + +Object.defineProperty(layout_constants, "__esModule", { value: true }); +layout_constants.DEFAULT_LAYOUT_KEY = layout_constants.LAYOUT_CONTROLLER_ID = void 0; +layout_constants.LAYOUT_CONTROLLER_ID = 'layout-entities'; +// TODO: eventually export this somehow +layout_constants.DEFAULT_LAYOUT_KEY = '__default__'; + +var main = {}; + +Object.defineProperty(main, "__esModule", { value: true }); +main.WebContents = void 0; +const base_1$j = base; +class WebContents extends base_1$j.EmitterBase { + /** + * @param identity The identity of the {@link OpenFin.WebContentsEvents WebContents}. + * @param entityType The type of the {@link OpenFin.WebContentsEvents WebContents}. + */ + constructor(wire, identity, entityType) { + super(wire, entityType, identity.uuid, identity.name); + this.identity = identity; + this.entityType = entityType; + } + /** + * Gets a base64 encoded image of all or part of the WebContents. + * @param options Options for the capturePage call. + * + * @example + * + * View: + * ```js + * const view = fin.View.getCurrentSync(); + * + * // PNG image of a full visible View + * console.log(await view.capturePage()); + * + * // Low-quality JPEG image of a defined visible area of the view + * const options = { + * area: { + * height: 100, + * width: 100, + * x: 10, + * y: 10, + * }, + * format: 'jpg', + * quality: 20 + * } + * console.log(await view.capturePage(options)); + * ``` + * + * Window: + * ```js + * const wnd = await fin.Window.getCurrent(); + * + * // PNG image of a full visible window + * console.log(await wnd.capturePage()); + * + * // Low-quality JPEG image of a defined visible area of the window + * const options = { + * area: { + * height: 100, + * width: 100, + * x: 10, + * y: 10, + * }, + * format: 'jpg', + * quality: 20 + * } + * console.log(await wnd.capturePage(options)); + * ``` + * + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + capturePage(options) { + return this.wire.sendAction('capture-page', { options, ...this.identity }).then(({ payload }) => payload.data); + } + /** + * Executes Javascript on the WebContents, restricted to contents you own or contents owned by + * applications you have created. + * @param code JavaScript code to be executed on the view. + * + * @example + * View: + * ```js + * async function executeJavaScript(code) { + * const view = await fin.View.wrap({uuid: 'uuid', name: 'view name'}); + * return await view.executeJavaScript(code); + * } + * + * executeJavaScript(`console.log('Hello, Openfin')`).then(() => console.log('Javascript excuted')).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function executeJavaScript(code) { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.executeJavaScript.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.executeJavaScript(code); + * } + * + * executeJavaScript(`console.log('Hello, Openfin')`).then(() => console.log('Javascript excuted')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + executeJavaScript(code) { + return this.wire + .sendAction('execute-javascript-in-window', { ...this.identity, code }) + .then(({ payload }) => payload.data); + } + /** + * Returns the zoom level of the WebContents. + * + * @example + * View: + * ```js + * async function getZoomLevel() { + * const view = await fin.View.getCurrent(); + * return await view.getZoomLevel(); + * } + * + * getZoomLevel().then(zoomLevel => console.log(zoomLevel)).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getZoomLevel.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function getZoomLevel() { + * const win = await createWin(); + * return await win.getZoomLevel(); + * } + * + * getZoomLevel().then(zoomLevel => console.log(zoomLevel)).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + getZoomLevel() { + return this.wire.sendAction('get-zoom-level', this.identity).then(({ payload }) => payload.data); + } + /** + * Sets the zoom level of the WebContents. + * @param level The zoom level + * + * @example + * View: + * ```js + * async function setZoomLevel(number) { + * const view = await fin.View.getCurrent(); + * return await view.setZoomLevel(number); + * } + * + * setZoomLevel(4).then(() => console.log('Setting a zoom level')).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.setZoomLevel.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function setZoomLevel(number) { + * const win = await createWin(); + * return await win.setZoomLevel(number); + * } + * + * setZoomLevel(4).then(() => console.log('Setting a zoom level')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + setZoomLevel(level) { + return this.wire.sendAction('set-zoom-level', { ...this.identity, level }).then(() => undefined); + } + /** + * Navigates the WebContents to a specified URL. + * + * Note: The url must contain the protocol prefix such as http:// or https://. + * @param url - The URL to navigate the WebContents to. + * + * @example + * View: + * ```js + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewName', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * createView() + * .then(view => view.navigate('https://example.com')) + * .then(() => console.log('navigation complete')) + * .catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function navigate() { + * const win = await fin.Window.getCurrent(); + * return await win.navigate('https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.navigate.html'); + * } + * navigate().then(() => console.log('Navigate to tutorial')).catch(err => console.log(err)); + * ``` + * @experimental + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + navigate(url) { + return this.wire.sendAction('navigate-window', { ...this.identity, url }).then(() => undefined); + } + /** + * Navigates the WebContents back one page. + * + * @example + * View: + * ```js + * async function navigateBack() { + * const view = await fin.View.wrap({ name: 'testapp-view', uuid: 'testapp' }); + * await view.navigate('https://www.google.com'); + * return await view.navigateBack(); + * } + * navigateBack().then(() => console.log('Navigated back')).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function navigateBack() { + * const win = await fin.Window.wrap({ name: 'testapp', uuid: 'testapp' }); + * await win.navigate('https://www.google.com'); + * return await win.navigateBack(); + * } + * navigateBack().then(() => console.log('Navigated back')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + navigateBack() { + return this.wire.sendAction('navigate-window-back', { ...this.identity }).then(() => undefined); + } + /** + * Navigates the WebContents forward one page. + * + * @example + * View: + * ```js + * async function navigateForward() { + * const view = await fin.View.getCurrent(); + * await view.navigate('https://www.google.com'); + * await view.navigateBack(); + * return await view.navigateForward(); + * } + * navigateForward().then(() => console.log('Navigated forward')).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function navigateForward() { + * const win = await fin.Window.getCurrent(); + * await win.navigate('https://www.google.com'); + * await win.navigateBack(); + * return await win.navigateForward(); + * } + * navigateForward().then(() => console.log('Navigated forward')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async navigateForward() { + await this.wire.sendAction('navigate-window-forward', { ...this.identity }); + } + /** + * Stops any current navigation the WebContents is performing. + * + * @example + * View: + * ```js + * async function stopNavigation() { + * const view = await fin.View.wrap({ name: 'testapp-view', uuid: 'testapp' }); + * await view.navigate('https://www.google.com'); + * return await view.stopNavigation(); + * } + * stopNavigation().then(() => console.log('you shall not navigate')).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function stopNavigation() { + * const win = await fin.Window.wrap({ name: 'testapp', uuid: 'testapp' }); + * await win.navigate('https://www.google.com'); + * return await win.stopNavigation(); + * } + * stopNavigation().then(() => console.log('you shall not navigate')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + stopNavigation() { + return this.wire.sendAction('stop-window-navigation', { ...this.identity }).then(() => undefined); + } + /** + * Reloads the WebContents + * + * @example + * View: + * ```js + * async function reload() { + * const view = await fin.View.getCurrent(); + * return await view.reload(); + * } + * + * reload().then(() => { + * console.log('Reloaded view') + * }).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function reloadWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.reload.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.reload(); + * } + * + * reloadWindow().then(() => { + * console.log('Reloaded window') + * }).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + reload(ignoreCache = false) { + return this.wire + .sendAction('reload-window', { + ignoreCache, + ...this.identity + }) + .then(() => undefined); + } + /** + * Prints the WebContents. + * @param options Printer Options + * + * Note: When `silent` is set to `true`, the API will pick the system's default printer if deviceName + * is empty and the default settings for printing. + * + * Use the CSS style `page-break-before: always;` to force print to a new page. + * + * @example + * ```js + * const view = fin.View.getCurrentSync(); + * + * view.print({ silent: false, deviceName: 'system-printer-name' }).then(() => { + * console.log('print call has been sent to the system'); + * }); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + print(options = {}) { + return this.wire.sendAction('print', { ...this.identity, options }).then(() => undefined); + } + /** + * Find and highlight text on a page. + * @param searchTerm Term to find in page + * @param options Search options + * + * Note: By default, each subsequent call will highlight the next text that matches the search term. + * + * Returns a promise with the results for the request. By subscribing to the + * found-in-page event, you can get the results of this call as well. + * + * @example + * View: + * ```js + * const view = fin.View.getCurrentSync(); + * + * //By subscribing to the 'found in page' event we can get the results of each findInPage call made. + * view.addListener('found-in-page', (event) => { + * console.log(event); + * }); + * + * // The promise also returns the results for the request + * view.findInPage('a').then((result) => { + * console.log(result) + * }); + * ``` + * + * Window: + * ```js + * const win = fin.Window.getCurrentSync(); + * + * //By subscribing to the 'found in page' event we can get the results of each findInPage call made. + * win.addListener('found-in-page', (event) => { + * console.log(event); + * }); + * + * // The promise also returns the results for the request + * win.findInPage('a').then((result) => { + * console.log(result) + * }); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + findInPage(searchTerm, options) { + return this.wire + .sendAction('find-in-page', { ...this.identity, searchTerm, options }) + .then(({ payload }) => payload.data); + } + /** + * Stop a {@link View#findInPage findInPage} call by specifying any of these actions: + * + * * clearSelection - Clear the selection. + * * keepSelection - Translate the selection into a normal selection. + * * activateSelection - Focus and click the selection node. + * + * @example + * View: + * ```js + * const view = fin.View.getCurrentSync(); + * + * view.addListener('found-in-page', (event) => { + * setTimeout(() => { + * view.stopFindInPage('clearSelection'); + * }, 5000); + * }); + * + * view.findInPage('a').then(results => { + * console.log(results); + * }); + * ``` + * + * Window: + * ```js + * const win = fin.Window.getCurrentSync(); + * + * win.addListener('found-in-page', (event) => { + * setTimeout(() => { + * win.stopFindInPage('clearSelection'); + * }, 5000); + * }); + * + * win.findInPage('a').then(results => { + * console.log(results); + * }); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + stopFindInPage(action) { + return this.wire.sendAction('stop-find-in-page', { ...this.identity, action }).then(() => undefined); + } + /** + * Returns an array with all system printers + * @deprecated use System.getPrinters instead + * + * @example + * View: + * ```js + * const view = fin.View.getCurrentSync(); + * + * view.getPrinters() + * .then((printers) => { + * printers.forEach((printer) => { + * if (printer.isDefault) { + * console.log(printer); + * } + * }); + * }) + * .catch((err) => { + * console.log(err); + * }); + * ``` + * + * Window: + * ```js + * const win = fin.Window.getCurrentSync(); + * + * win.getPrinters() + * .then((printers) => { + * printers.forEach((printer) => { + * if (printer.isDefault) { + * console.log(printer); + * } + * }); + * }) + * .catch((err) => { + * console.log(err); + * }); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + getPrinters() { + return this.wire.sendAction('get-printers', { ...this.identity }).then(({ payload }) => payload.data); + } + /** + * Gives focus to the WebContents. + * + * @example + * ```js + * async function focusWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.focus.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.focus(); + * } + * + * focusWindow().then(() => console.log('Window focused')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async focus({ emitSynthFocused } = { emitSynthFocused: true }) { + await this.wire.sendAction('focus-window', { emitSynthFocused, ...this.identity }); + } + /** + * Shows the Chromium Developer Tools + * + * @example + * View: + * ```js + * async function showDeveloperTools() { + * const view = await fin.View.getCurrent(); + * return view.showDeveloperTools(); + * } + * + * showDevelopertools() + * .then(() => console.log('Showing dev tools')) + * .catch(err => console.error(err)); + * ``` + * + * Window: + * ```js + * async function showDeveloperTools() { + * const win = await fin.Window.getCurrent(); + * return win.showDeveloperTools(); + * } + * + * showDevelopertools() + * .then(() => console.log('Showing dev tools')) + * .catch(err => console.error(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async showDeveloperTools() { + // Note this hits the system action map in core state for legacy reasons. + await this.wire.sendAction('show-developer-tools', this.identity); + } + /** + * Retrieves the process information associated with a WebContents. + * + * Note: This includes any iframes associated with the WebContents + * + * @example + * View: + * ```js + * const view = await fin.View.getCurrent(); + * const processInfo = await view.getProcessInfo(); + * ``` + * + * Window: + * ```js + * const win = await fin.Window.getCurrent(); + * const processInfo = await win.getProcessInfo(); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async getProcessInfo() { + const { payload: { data } } = await this.wire.sendAction('get-process-info', this.identity); + return data; + } + /** + * Retrieves information on all Shared Workers. + * + * @example + * View: + * ```js + * const view = await fin.View.create({ + * name: 'viewName', + * target: fin.me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * + * await view.navigate('https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/'); + * + * const sharedWorkers = await view.getSharedWorkers(); + * ``` + * + * Window: + * ```js + * const winOption = { + * name:'child', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/', + * frame: true, + * autoShow: true + * }; + * const win = await fin.Window.create(winOption); + * const sharedWorkers = await win.getSharedWorkers(); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async getSharedWorkers() { + return this.wire.sendAction('get-shared-workers', this.identity).then(({ payload }) => payload.data); + } + /** + * Opens the developer tools for the shared worker context. + * + * @example + * View: + * ```js + * const view = await fin.View.create({ + * name: 'viewName', + * target: fin.me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * + * await view.navigate('https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/'); + * + * await view.inspectSharedWorker(); + * ``` + * + * Example: + * ```js + * const winOption = { + * name:'child', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/', + * frame: true, + * autoShow: true + * }; + * const win = await fin.Window.create(winOption); + * await win.inspectSharedWorker(); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async inspectSharedWorker() { + await this.wire.sendAction('inspect-shared-worker', { ...this.identity }); + } + /** + * Inspects the shared worker based on its ID. + * @param workerId - The id of the shared worker. + * + * @example + * View: + * ```js + * const view = await fin.View.create({ + * name: 'viewName', + * target: fin.me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * + * await view.navigate('https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/'); + * + * const sharedWorkers = await view.getSharedWorkers(); + * await view.inspectSharedWorkerById(sharedWorkers[0].id); + * ``` + * + * Window: + * ```js + * const winOption = { + * name:'child', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/', + * frame: true, + * autoShow: true + * }; + * const win = await fin.Window.create(winOption); + * const sharedWorkers = await win.getSharedWorkers(); + * await win.inspectSharedWorkerById(sharedWorkers[0].id); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async inspectSharedWorkerById(workerId) { + await this.wire.sendAction('inspect-shared-worker-by-id', { ...this.identity, workerId }); + } + /** + * Opens the developer tools for the service worker context. + * + * @example + * View: + * ```js + * const view = await fin.View.create({ + * name: 'viewName', + * target: fin.me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * + * await view.navigate('http://googlechrome.github.io/samples/service-worker/basic/index.html'); + * + * await view.inspectServiceWorker(); + * ``` + * + * Window: + * ```js + * const winOption = { + * name:'child', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'http://googlechrome.github.io/samples/service-worker/basic/index.html', + * frame: true, + * autoShow: true + * }; + * const win = await fin.Window.create(winOption); + * await win.inspectServiceWorker(); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async inspectServiceWorker() { + await this.wire.sendAction('inspect-service-worker', { ...this.identity }); + } + /** + * Shows a popup window. + * + * Note: If this WebContents is a view and its attached window has a popup open, this will close it. + * + * Shows a popup window. Including a `name` in `options` will attempt to show an existing window as a popup, if + * that window doesn't exist or no `name` is included a window will be created. If the caller view or the caller + * view's parent window currently has a popup window open, calling `showPopupWindow` again will dismiss the currently + * open popup window before showing the new popup window. Also, if the caller view is destroyed or detached, the popup + * will be dismissed. + * + * Note: in the case where the window being shown as a popup needs to be created, it is a child of the caller view's parent window. + * + * @example + * + * Create and show a single-use popup window that returns a single result to the caller. `initialOptions` allows + * us to pass window options to the popup window that will be created. `resultDispatchBehavior: 'close'` ensures + * that once the popup window calls `dispatchPopupResult` it is closed. `blurBehavior: 'close'` will yield a dismissed + * result should the popup window lose focus. + * + * ```js + * const result = await fin.me.showPopupWindow({ + * initialOptions: { + * frame: false + * }, + * url: '', + * resultDispatchBehavior: 'close', + * blurBehavior: 'close', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0 + * }); + * ``` + * + * Same as above but using an existing window as a popup by referencing its `name`: + * + * Note: if a window with the `name` provided doesn't exist, it will be created. + * + * ```js + * const result = await fin.me.showPopupWindow({ + * initialOptions: { + * frame: true + * }, + * name: 'my-popup', // shows the 'my-popup' window if it exists, otherwise creates it + * url: '', // navigates to this url if it doesn't match the location.href of the 'my-popup' window + * resultDispatchBehavior: 'close', + * blurBehavior: 'close', + * focus: true, + * hideOnClose: true, // persist window on 'dismissed' result, alternatively change onResultDispatch and blurBehavior to 'hide' + * height: 300, + * width: 300, + * x: 0, + * y: 0 + * }); + * ``` + * + * Create and show a popup window that is able to return multiple results to the caller via an `onPopupResult` callback. Each + * time the popup window calls `dispatchPopupResult`, the callback will be executed on the result. Once the popup window is + * closed or hidden, the `showPopupWindow` promise will resolve with a `dismissed` result that will include the most recently + * dispatched result as `lastDispatchResult`: + * + * ```js + * const popupResultCallback = (payload) => { + * if (payload.result === 'clicked') { + * if (payload.data.topic === 'color-changed') { + * // do something like + * // setColor(payload.data.value); + * } + * } + * }; + * + * await fin.me.showPopupWindow({ + * initialOptions: { + * frame: false + * }, + * url: '', + * resultDispatchBehavior: 'none', + * blurBehavior: 'close', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0, + * onPopupResult: popupResultCallback + * }); + * ``` + * + * Same as above but using an existing window as a popup: + * + * ```js + * const popupResultCallback = (payload) => { + * if (payload.result === 'clicked') { + * if (payload.data.topic === 'color-changed') { + * // do something like + * // setColor(payload.data.value); + * } + * } + * }; + * + * await fin.me.showPopupWindow({ + * initialOptions: { + * frame: false + * }, + * name: 'my-popup', // shows the 'my-popup' window if it exists, otherwise creates it + * url: '', // navigates to this url if it doesn't match the location.href of the 'my-popup' window + * resultDispatchBehavior: 'none', + * blurBehavior: 'hide', + * focus: true, + * hideOnClose: true, // we can just use this or we can change blurBehavior to 'hide' + * height: 300, + * width: 300, + * x: 0, + * y: 0, + * onPopupResult: popupResultCallback + * }); + * ``` + * + * Create or show a popup window that disables user movement (positioning and resizing) in the caller + * view's parent window by using `blurBehavior: 'modal'`: + * + * ```js + * const result = await fin.me.showPopupWindow({ + * initialOptions: { + * frame: false + * }, + * url: '', + * resultDispatchBehavior: 'close', + * blurBehavior: 'modal', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0 + * }); + * ``` + * + * Create a popup window as a modal: + * + * Note: The only way to ensure true modal behavior is to create the window being shown as a popup with a + * `modalParentIdentity` that uses the caller view's parent window identity. + * + * ```js + * const result = await fin.me.showPopupWindow({ + * initialOptions: { + * frame: false, + * modalParentIdentity: fin.me.identity + * }, + * url: '', + * resultDispatchBehavior: 'close', + * blurBehavior: 'modal', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0 + * }); + * ``` + * + * Pass data to a popup window that is available when the popup is shown. + * + * Note: this is just one example for a use of `additionalOptions`, it can be used to update any updatable + * window options when creating or showing an existing window as a popup. + * + * ```js + * const result = await fin.me.showPopupWindow({ + * additionalOptions: { + * customData: { + * foo: 'bar' + * } + * }, + * url: '', + * resultDispatchBehavior: 'close', + * blurBehavior: 'close', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0 + * }); + * + * // Access from the popup window context like so: + * const { customData } = await fin.me.getOptions(); + * const { foo } = customData; + * ``` + * + * Execute a callback on the popup's OpenFin window when the popup is shown: + * + * ```js + * const popupWindowCallback = async (win) => { + * await win.flash(); + * }; + * + * const result = await fin.me.showPopupWindow({ + * url: '', + * resultDispatchBehavior: 'close', + * blurBehavior: 'close', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0, + * onPopupReady: popupWindowCallback; + * }); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async showPopupWindow(options) { + this.wire.sendAction(`${this.entityType}-show-popup-window`, this.identity).catch(() => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (options?.onPopupReady) { + const readyListener = async ({ popupName }) => { + try { + const popupWindow = this.fin.Window.wrapSync({ uuid: this.fin.me.uuid, name: popupName }); + await options.onPopupReady(popupWindow); + } + catch (error) { + throw new Error(`Something went wrong during onPopupReady execution: ${error}`); + } + }; + // TODO: fix typing (internal) + // @ts-expect-error + await this.once('popup-ready', readyListener); + } + const { payload: tryCreatePayload } = await this.wire.sendAction('try-create-popup-window', { + options: { + ...options, + // Internal use only. + // @ts-expect-error + hasResultCallback: !!options?.onPopupResult, + hasReadyCallback: !!options?.onPopupReady + }, + ...this.identity + }); + const { data: { willOpen, options: popupOptions } } = tryCreatePayload; + if (willOpen) { + // Solve the issue where Interop in a popup window with non cross-origin url is not working(core-1076). + await this.fin.Window.create(popupOptions.initialOptions); + } + const normalizePopupResult = (payload) => { + const { name, uuid, result, data } = payload; + const popupResult = { + identity: { + name, + uuid + }, + result + }; + if (data) { + popupResult.data = data; + } + return popupResult; + }; + if (options?.onPopupResult) { + const dispatchResultListener = async (payload) => { + await options.onPopupResult(normalizePopupResult(payload)); + }; + const teardownListener = async () => { + // TODO: fix typing (internal) + // @ts-expect-error + await this.removeListener('popup-result', dispatchResultListener); + }; + // TODO: fix typing (internal) + // @ts-expect-error + await this.on('popup-result', dispatchResultListener); + // TODO: fix typing (internal) + // hilariously this does not need a ts-expect-error - this is gap in type soundness + // should investigate - probably due to `teardownListener` taking a void argument + // which might play nicely with the `never` type? huh... + await this.once('popup-teardown', teardownListener); + } + const { payload } = await this.wire.sendAction('show-popup-window', { + options: popupOptions, + ...this.identity + }); + return payload.data; + } +} +main.WebContents = WebContents; + +var hasRequiredInstance$2; + +function requireInstance$2 () { + if (hasRequiredInstance$2) return Instance$5; + hasRequiredInstance$2 = 1; + var __classPrivateFieldGet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + var _View_providerChannelClient; + Object.defineProperty(Instance$5, "__esModule", { value: true }); + Instance$5.View = void 0; + const transport_errors_1 = transportErrors; + const lazy_1 = lazy; + const layout_entities_1 = layoutEntities; + const layout_constants_1 = layout_constants; + const main_1 = main; + const window_1 = requireWindow(); + /** + * A View can be used to embed additional web content into a Window. + * It is like a child window, except it is positioned relative to its owning window. + * It has the ability to listen for {@link OpenFin.ViewEvents View-specific events}. + * + * By default, a View will try to share the same renderer process as other Views owned by its parent Application. + * To change that behavior, see the processAffinity {@link OpenFin.ViewOptions view option}. + * + * A View's lifecycle is tied to its owning window and can be re-attached to a different window at any point during its lifecycle. + */ + class View extends main_1.WebContents { + /** + * @internal + */ + constructor(wire, identity) { + super(wire, identity, 'view'); + this.identity = identity; + _View_providerChannelClient.set(this, new lazy_1.Lazy(() => { + const platform = this.fin.Platform.wrapSync(this.identity); + return platform.getClient(); + })); + /** + * Attaches the current view to the given window identity. + * Identity must be the identity of a window in the same application. + * This detaches the view from its current window, and sets the view to be destroyed when its new window closes. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameAttach', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function attachView() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * const winOption = { + * name:'winOptionName', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.create.html', + * frame: true, + * autoShow: true + * }; + * const newWindow = await fin.Window.create(winOption); + * view.attach(newWindow.identity); + * } + * + * attachView() + * .then(() => console.log('View attached to new window.')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.attach = async (target) => { + await this.wire.sendAction('attach-view', { target, ...this.identity }); + }; + /** + * Destroys the current view + * + * @example + * ```js + * const view = fin.View.wrapSync({ uuid: 'viewUuid', name: 'viewName' }); + * view.destroy(); + * ``` + * @experimental + */ + this.destroy = async () => { + await this.wire.sendAction('destroy-view', { ...this.identity }); + }; + /** + * Shows the current view if it is currently hidden. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameShow', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function hideAndShowView() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url option.'); + * + * await view.hide(); + * console.log("View hidden."); + * + * view.show(); + * console.log("View shown."); + * } + * + * hideAndShowView() + * .then(() => console.log('View hidden and shown.')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.show = async () => { + await this.wire.sendAction('show-view', { ...this.identity }); + }; + /** + * Sets the bounds (top, left, width, height) of the view relative to its window and shows it if it is hidden. + * This method ensures the view is both positioned and showing. It will reposition a visible view and both show and reposition a hidden view. + * + * @remarks View position is relative to the bounds of the window. + * ({top: 0, left: 0} represents the top left corner of the window) + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameSetBounds', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function showViewAt() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * await view.showAt({ + * top: 100, + * left: 100, + * width: 300, + * height: 300 + * }, { + * bringToFront : true + * }); + * } + * + * showViewAt() + * .then(() => console.log('View set to new bounds and shown.')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.showAt = async (bounds, options = {}) => { + await this.wire.sendAction('show-view-at', { bounds, ...this.identity, options }); + }; + /** + * Brings the specified view to the front of its current window. This ensures the view will be visible on top of any other views + * which have overlapping bounds with it. + * + * Please note, this is not a permanent action - when a new view is created or attached to the window, it will display on top of all other views + * in the window that share bounds with it. + */ + this.bringToFront = async () => { + await this.wire.sendAction('bring-view-to-front', { ...this.identity }); + }; + /** + * Hides the current view if it is currently visible. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameHide', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function hideView() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * await view.hide(); + * } + * + * hideView() + * .then(() => console.log('View hidden.')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.hide = async () => { + await this.wire.sendAction('hide-view', { ...this.identity }); + }; + /** + * Sets the bounds (top, left, width, height) of the view relative to its window. + * + * @remarks View position is relative to the bounds of the window. + * ({top: 0, left: 0} represents the top left corner of the window) + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameSetBounds', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function setViewBounds() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * await view.setBounds({ + * top: 100, + * left: 100, + * width: 300, + * height: 300 + * }); + * } + * + * setViewBounds() + * .then(() => console.log('View set to new bounds.')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.setBounds = async (bounds) => { + await this.wire.sendAction('set-view-bounds', { bounds, ...this.identity }); + }; + /** + * Gets the bounds (top, left, width, height) of the view relative to its window. + * + * @remarks View position is relative to the bounds of the window. + * ({top: 0, left: 0} represents the top left corner of the window) + * + * @example + * ```js + * const view = await fin.View.create({ + * name: 'viewNameSetBounds', + * target: fin.me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * + * await view.navigate('https://google.com'); + * + * await view.setBounds({ + * top: 100, + * left: 100, + * width: 300, + * height: 300 + * }); + * + * console.log(await view.getBounds()); + * ``` + * @experimental + */ + this.getBounds = async () => { + const ack = await this.wire.sendAction('get-view-bounds', { ...this.identity }); + return ack.payload.data; + }; + /** + * Gets the View's info. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameGetInfo', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function getViewInfo() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * return view.getInfo(); + * } + * + * getViewInfo() + * .then((info) => console.log('View info fetched.', info)) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.getInfo = async () => { + const ack = await this.wire.sendAction('get-view-info', { ...this.identity }); + return ack.payload.data; + }; + /** + * Retrieves the layout for the window the view is attached to. + * + * @example + * ```js + * //get the current View + * const view = await fin.View.getCurrent(); + * + * //get a reference to the Layout for the Window the view is part of + * const layout = await view.getParentLayout(); + * ``` + * @experimental + */ + this.getParentLayout = async () => { + this.wire.sendAction('view-get-parent-layout', { ...this.identity }).catch(() => { + // don't expose + }); + const layoutWindow = await this.getCurrentWindow(); + let layoutWindowIdentity = layoutWindow.identity; + // TODO: CORE-1857 - when we tearout active layout or drag a view out of a window, the above identity includes the whole window info. + if (layoutWindowIdentity.identity) { + layoutWindowIdentity = layoutWindowIdentity.identity; + } + try { + const providerChannelClient = await __classPrivateFieldGet(this, _View_providerChannelClient, "f").getValue(); + const client = await layout_entities_1.LayoutNode.newLayoutEntitiesClient(providerChannelClient, layout_constants_1.LAYOUT_CONTROLLER_ID, layoutWindowIdentity); + const layoutIdentity = await client.getLayoutIdentityForViewOrThrow(this.identity); + return this.fin.Platform.Layout.wrap(layoutIdentity); + } + catch (e) { + const allowedErrors = [ + 'No action registered at target for', + 'getLayoutIdentityForViewOrThrow is not a function' + ]; + if (!allowedErrors.some((m) => e.message.includes(m))) { + throw e; + } + // fallback logic for missing endpoint + return this.fin.Platform.Layout.wrap(layoutWindowIdentity); + } + }; + /** + * Gets the View's options. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameGetOptions', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function getViewOptions() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * const me = await fin.Window.getCurrent(); + * view = fin.View.wrapSync({ uuid: me.identity.uuid, name: 'viewNameGetOptions' }); + * return view.getOptions(); + * } + * + * getViewOptions() + * .then((info) => console.log('View options fetched.', info)) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.getOptions = async () => { + return this.wire.sendAction('get-view-options', { ...this.identity }).then(({ payload }) => payload.data); + }; + /** + * Updates the view's options. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * url: 'https://google.com', + * name: 'viewNameUpdateOptions', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function updateViewOptions() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url option.'); + * + * const newOptions = { autoResize: { + * width: true, + * horizontal: true + * }}; + * return view.updateOptions(newOptions); + * } + * + * updateViewOptions() + * .then(payload => console.log('View options updated: ', payload)) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.updateOptions = async (options) => { + return this.wire.sendAction('update-view-options', { options, ...this.identity }).then(() => undefined); + }; + /** + * Retrieves the window the view is currently attached to. + * + * @example + * ```js + * const view = fin.View.wrapSync({ uuid: 'viewUuid', name: 'viewName' }); + * view.getCurrentWindow() + * .then(win => console.log('current window', win)) + * .catch(err => console.log(err));) + * ``` + * @experimental + */ + this.getCurrentWindow = async () => { + const { payload: { data } } = await this.wire.sendAction('get-view-window', { ...this.identity }); + return new window_1._Window(this.wire, data); + }; + /** + * Retrieves the current {@link OpenFin.TabStack} of the view if it belongs to one. + * @returns this view belongs to. + * @throws if this view does not belong to a TabStack or if the window has been destroyed. + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Alternatively, you can wrap any view and get the stack from there + * // const viewFromSomewhere = fin.View.wrapSync(someView.identity); + * // const stack = await viewFromSomewhere.getCurrentStack(); + * const views = await stack.getViews(); + * console.log(`Stack contains ${views.length} view(s)`); + * ``` + */ + this.getCurrentStack = async () => { + this.wire.sendAction('view-get-current-stack').catch(() => { + // don't expose + }); + try { + const layoutWindow = await this.getCurrentWindow(); + const providerChannelClient = await __classPrivateFieldGet(this, _View_providerChannelClient, "f").getValue(); + const client = await layout_entities_1.LayoutNode.newLayoutEntitiesClient(providerChannelClient, layout_constants_1.LAYOUT_CONTROLLER_ID, layoutWindow.identity); + const stackDefinition = (await client.getStackByView(this.identity)); + return layout_entities_1.LayoutNode.getEntity(stackDefinition, client); + } + catch (error) { + throw new transport_errors_1.RuntimeError({ reason: 'This view does not belong to a stack.', error }); + } + }; + /** + * Triggers the before-unload handler for the View, if one is set. + * + * @remarks Returns `true` if the handler is trying to prevent the View from unloading, and `false` if it isn't. + * Only enabled when setting enableBeforeUnload: true in your View options. If this option is not enabled it will + * always return false. + * + * This method is used internally by the Platform Provider to determine the status of each before unload handler in Views when closing the Window. + * + * @example + * + * ```js + * // from inside a View context + * const unloadPrevented = await fin.me.triggerBeforeUnload(); + * ``` + * + * @experimental + */ + this.triggerBeforeUnload = async () => { + const message = await this.wire.sendAction('trigger-before-unload', { ...this.identity }); + return message.payload.data; + }; + /** + * **NOTE**: Internal use only. + * Attaches this view to an HTML element in the current context. The view will resize responsively when the element bounds change. + * + * **Known issue**: View.bindToElement does not track position changes, if the element has fixed px width and height values it is possible for the view to not update responsively. + * + * **Known issue**: When View.bindToElement is used on a element that takes up the entire page in a platform window, the bound view will not respond responsively when the window is resized to be smaller. + * + * @param element - HTML element to attach the view to. + * @returns - Cleanup function that will disconnect the element resize observer. + * @internal + * @experimental + * @remarks View will resize accordingly when the element is resized. If the element is repositioned in the DOM the view will not be repositioned, to handle this case call `bindToElement` again once the element changes position. + * + * @example + * ```html + *
+ * + * ``` + */ + this.bindToElement = async (element) => { + if (!element) { + throw new Error('Element not found.'); + } + const onChange = async (bounds) => this.setBounds(bounds); + return this.wire.environment.observeBounds(element, onChange); + }; + } + /** + * Focuses the view + * + * @example + * ```js + * const view = fin.View.wrapSync({ uuid: 'viewUuid', name: 'viewName' }); + * await view.focus(); + * // do things with the focused view + * ``` + * @experimental + */ + async focus({ emitSynthFocused } = { emitSynthFocused: true }) { + const win = await this.getCurrentWindow(); + await win.focusedWebViewWasChanged(); + await super.focus({ emitSynthFocused }); + } + } + Instance$5.View = View; + _View_providerChannelClient = new WeakMap(); + return Instance$5; +} + +var hasRequiredView; + +function requireView () { + if (hasRequiredView) return view; + hasRequiredView = 1; + (function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + /** + * Entry points for the OpenFin `View` API (`fin.View`). + * + * * {@link ViewModule} contains static members of the `View` API, accessible through `fin.View`. + * * {@link View} describes an instance of an OpenFin View, e.g. as returned by `fin.View.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + */ + __exportStar(requireFactory$3(), exports); + __exportStar(requireInstance$2(), exports); + } (view)); + return view; +} + +var hasRequiredInstance$1; + +function requireInstance$1 () { + if (hasRequiredInstance$1) return Instance$6; + hasRequiredInstance$1 = 1; + Object.defineProperty(Instance$6, "__esModule", { value: true }); + Instance$6.Application = void 0; + /* eslint-disable import/prefer-default-export */ + const base_1 = base; + const window_1 = requireWindow(); + const view_1 = requireView(); + /** + * An object representing an application. Allows the developer to create, + * execute, show/close an application as well as listen to {@link OpenFin.ApplicationEvents application events}. + */ + class Application extends base_1.EmitterBase { + /** + * @internal + */ + constructor(wire, identity) { + super(wire, 'application', identity.uuid); + this.identity = identity; + this.window = new window_1._Window(this.wire, { + uuid: this.identity.uuid, + name: this.identity.uuid + }); + } + windowListFromIdentityList(identityList) { + const windowList = []; + identityList.forEach((identity) => { + windowList.push(new window_1._Window(this.wire, { + uuid: identity.uuid, + name: identity.name + })); + }); + return windowList; + } + /** + * Determines if the application is currently running. + * + * @example + * + * ```js + * async function isAppRunning() { + * const app = await fin.Application.getCurrent(); + * return await app.isRunning(); + * } + * isAppRunning().then(running => console.log(`Current app is running: ${running}`)).catch(err => console.log(err)); + * ``` + */ + isRunning() { + return this.wire.sendAction('is-application-running', this.identity).then(({ payload }) => payload.data); + } + /** + * Closes the application and any child windows created by the application. + * Cleans the application from state so it is no longer found in getAllApplications. + * @param force Close will be prevented from closing when force is false and + * ‘close-requested’ has been subscribed to for application’s main window. + * + * @example + * + * ```js + * async function closeApp() { + * const allApps1 = await fin.System.getAllApplications(); //[{uuid: 'app1', isRunning: true}, {uuid: 'app2', isRunning: true}] + * const app = await fin.Application.wrap({uuid: 'app2'}); + * await app.quit(); + * const allApps2 = await fin.System.getAllApplications(); //[{uuid: 'app1', isRunning: true}] + * + * } + * closeApp().then(() => console.log('Application quit')).catch(err => console.log(err)); + * ``` + */ + async quit(force = false) { + try { + await this._close(force); + await this.wire.sendAction('destroy-application', { force, ...this.identity }); + } + catch (error) { + const acceptableErrors = ['Remote connection has closed', 'Could not locate the requested application']; + if (!acceptableErrors.some((msg) => error.message.includes(msg))) { + throw error; + } + } + } + async _close(force = false) { + try { + await this.wire.sendAction('close-application', { force, ...this.identity }); + } + catch (error) { + if (!error.message.includes('Remote connection has closed')) { + throw error; + } + } + } + /** + * @deprecated use Application.quit instead + * Closes the application and any child windows created by the application. + * @param force - Close will be prevented from closing when force is false and ‘close-requested’ has been subscribed to for application’s main window. + * @param callback - called if the method succeeds. + * @param errorCallback - called if the method fails. The reason for failure is passed as an argument. + * + * @example + * + * ```js + * async function closeApp() { + * const app = await fin.Application.getCurrent(); + * return await app.close(); + * } + * closeApp().then(() => console.log('Application closed')).catch(err => console.log(err)); + * ``` + */ + close(force = false) { + console.warn('Deprecation Warning: Application.close is deprecated Please use Application.quit'); + this.wire.sendAction('application-close', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this._close(force); + } + /** + * Retrieves an array of wrapped fin.Windows for each of the application’s child windows. + * + * @example + * + * ```js + * async function getChildWindows() { + * const app = await fin.Application.getCurrent(); + * return await app.getChildWindows(); + * } + * + * getChildWindows().then(children => console.log(children)).catch(err => console.log(err)); + * ``` + */ + getChildWindows() { + return this.wire.sendAction('get-child-windows', this.identity).then(({ payload }) => { + const identityList = []; + payload.data.forEach((winName) => { + identityList.push({ uuid: this.identity.uuid, name: winName }); + }); + return this.windowListFromIdentityList(identityList); + }); + } + /** + * Retrieves the JSON manifest that was used to create the application. Invokes the error callback + * if the application was not created from a manifest. + * + * @example + * + * ```js + * async function getManifest() { + * const app = await fin.Application.getCurrent(); + * return await app.getManifest(); + * } + * + * getManifest().then(manifest => console.log(manifest)).catch(err => console.log(err)); + * ``` + */ + getManifest() { + return this.wire.sendAction('get-application-manifest', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves UUID of the application that launches this application. Invokes the error callback + * if the application was created from a manifest. + * + * @example + * + * ```js + * async function getParentUuid() { + * const app = await fin.Application.start({ + * uuid: 'app-1', + * name: 'myApp', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Application.getParentUuid.html', + * autoShow: true + * }); + * return await app.getParentUuid(); + * } + * + * getParentUuid().then(parentUuid => console.log(parentUuid)).catch(err => console.log(err)); + * ``` + */ + getParentUuid() { + return this.wire.sendAction('get-parent-application', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves current application's shortcut configuration. + * + * @example + * + * ```js + * async function getShortcuts() { + * const app = await fin.Application.wrap({ uuid: 'testapp' }); + * return await app.getShortcuts(); + * } + * getShortcuts().then(config => console.log(config)).catch(err => console.log(err)); + * ``` + */ + getShortcuts() { + return this.wire.sendAction('get-shortcuts', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves current application's views. + * @experimental + * + * @example + * + * ```js + * async function getViews() { + * const app = await fin.Application.getCurrent(); + * return await app.getViews(); + * } + * getViews().then(views => console.log(views)).catch(err => console.log(err)); + * ``` + */ + async getViews() { + const { payload } = await this.wire.sendAction('application-get-views', this.identity); + return payload.data.map((id) => new view_1.View(this.wire, id)); + } + /** + * Returns the current zoom level of the application. + * + * @example + * + * ```js + * async function getZoomLevel() { + * const app = await fin.Application.getCurrent(); + * return await app.getZoomLevel(); + * } + * + * getZoomLevel().then(zoomLevel => console.log(zoomLevel)).catch(err => console.log(err)); + * ``` + */ + getZoomLevel() { + return this.wire.sendAction('get-application-zoom-level', this.identity).then(({ payload }) => payload.data); + } + /** + * Returns an instance of the main Window of the application + * + * @example + * + * ```js + * async function getWindow() { + * const app = await fin.Application.start({ + * uuid: 'app-1', + * name: 'myApp', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Application.getWindow.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * getWindow().then(win => { + * win.showAt(0, 400); + * win.flash(); + * }).catch(err => console.log(err)); + * ``` + */ + getWindow() { + this.wire.sendAction('application-get-window', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return Promise.resolve(this.window); + } + /** + * Manually registers a user with the licensing service. The only data sent by this call is userName and appName. + * @param userName - username to be passed to the RVM. + * @param appName - app name to be passed to the RVM. + * + * @example + * + * ```js + * async function registerUser() { + * const app = await fin.Application.getCurrent(); + * return await app.registerUser('user', 'myApp'); + * } + * + * registerUser().then(() => console.log('Successfully registered the user')).catch(err => console.log(err)); + * ``` + */ + registerUser(userName, appName) { + return this.wire.sendAction('register-user', { userName, appName, ...this.identity }).then(() => undefined); + } + /** + * Removes the application’s icon from the tray. + * + * @example + * + * ```js + * async function removeTrayIcon() { + * const app = await fin.Application.getCurrent(); + * return await app.removeTrayIcon(); + * } + * + * removeTrayIcon().then(() => console.log('Removed the tray icon.')).catch(err => console.log(err)); + * ``` + */ + removeTrayIcon() { + return this.wire.sendAction('remove-tray-icon', this.identity).then(() => undefined); + } + /** + * Restarts the application. + * + * @example + * + * ```js + * async function restartApp() { + * const app = await fin.Application.getCurrent(); + * return await app.restart(); + * } + * restartApp().then(() => console.log('Application restarted')).catch(err => console.log(err)); + * ``` + */ + restart() { + return this.wire.sendAction('restart-application', this.identity).then(() => undefined); + } + /** + * DEPRECATED method to run the application. + * Needed when starting application via {@link Application.create}, but NOT needed when starting via {@link Application.start}. + * + * @example + * + * ```js + * async function run() { + * const app = await fin.Application.create({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Application.run.html', + * autoShow: true + * }); + * await app.run(); + * } + * run().then(() => console.log('Application is running')).catch(err => console.log(err)); + * ``` + * + * @ignore + */ + run() { + console.warn('Deprecation Warning: Application.run is deprecated Please use fin.Application.start'); + this.wire.sendAction('application-run', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this._run(); + } + _run(opts = {}) { + return this.wire + .sendAction('run-application', { + manifestUrl: this._manifestUrl, + opts, + ...this.identity + }) + .then(() => undefined); + } + /** + * Instructs the RVM to schedule one restart of the application. + * + * @example + * + * ```js + * async function scheduleRestart() { + * const app = await fin.Application.getCurrent(); + * return await app.scheduleRestart(); + * } + * + * scheduleRestart().then(() => console.log('Application is scheduled to restart')).catch(err => console.log(err)); + * ``` + */ + scheduleRestart() { + return this.wire.sendAction('relaunch-on-close', this.identity).then(() => undefined); + } + /** + * Sends a message to the RVM to upload the application's logs. On success, + * an object containing logId is returned. + * + * @example + * + * ```js + * async function sendLog() { + * const app = await fin.Application.getCurrent(); + * return await app.sendApplicationLog(); + * } + * + * sendLog().then(info => console.log(info.logId)).catch(err => console.log(err)); + * ``` + */ + async sendApplicationLog() { + const { payload } = await this.wire.sendAction('send-application-log', this.identity); + return payload.data; + } + /** + * Sets or removes a custom JumpList for the application. Only applicable in Windows OS. + * If categories is null the previously set custom JumpList (if any) will be replaced by the standard JumpList for the app (managed by Windows). + * + * Note: If the "name" property is omitted it defaults to "tasks". + * @param jumpListCategories An array of JumpList Categories to populate. If null, remove any existing JumpList configuration and set to Windows default. + * + * + * @remarks If categories is null the previously set custom JumpList (if any) will be replaced by the standard JumpList for the app (managed by Windows). + * + * The bottommost item in the jumplist will always be an item pointing to the current app. Its name is taken from the manifest's + * **` shortcut.name `** and uses **` shortcut.company `** as a fallback. Clicking that item will launch the app from its current manifest. + * + * Note: If the "name" property is omitted it defaults to "tasks". + * + * Note: Window OS caches jumplists icons, therefore an icon change might only be visible after the cache is removed or the + * uuid or shortcut.name is changed. + * + * @example + * + * ```js + * const app = fin.Application.getCurrentSync(); + * const appName = 'My App'; + * const jumpListConfig = [ // array of JumpList categories + * { + * // has no name and no type so `type` is assumed to be "tasks" + * items: [ // array of JumpList items + * { + * type: 'task', + * title: `Launch ${appName}`, + * description: `Runs ${appName} with the default configuration`, + * deepLink: 'fins://path.to/app/manifest.json', + * iconPath: 'https://path.to/app/icon.ico', + * iconIndex: 0 + * }, + * { type: 'separator' }, + * { + * type: 'task', + * title: `Restore ${appName}`, + * description: 'Restore to last configuration', + * deepLink: 'fins://path.to/app/manifest.json?$$use-last-configuration=true', + * iconPath: 'https://path.to/app/icon.ico', + * iconIndex: 0 + * }, + * ] + * }, + * { + * name: 'Tools', + * items: [ // array of JumpList items + * { + * type: 'task', + * title: 'Tool A', + * description: 'Runs Tool A', + * deepLink: 'fins://path.to/tool-a/manifest.json', + * iconPath: 'https://path.to/tool-a/icon.ico', + * iconIndex: 0 + * }, + * { + * type: 'task', + * title: 'Tool B', + * description: 'Runs Tool B', + * deepLink: 'fins://path.to/tool-b/manifest.json', + * iconPath: 'https://path.to/tool-b/icon.ico', + * iconIndex: 0 + * }] + * } + * ]; + * + * app.setJumpList(jumpListConfig).then(() => console.log('JumpList applied')).catch(e => console.log(`JumpList failed to apply: ${e.toString()}`)); + * ``` + * + * To handle deeplink args: + * ```js + * function handleUseLastConfiguration() { + * // this handler is called when the app is being launched + * app.on('run-requested', event => { + * if(event.userAppConfigArgs['use-last-configuration']) { + * // your logic here + * } + * }); + * // this handler is called when the app was already running when the launch was requested + * fin.desktop.main(function(args) { + * if(args && args['use-last-configuration']) { + * // your logic here + * } + * }); + * } + * ``` + */ + async setJumpList(jumpListCategories) { + await this.wire.sendAction('set-jump-list', { config: jumpListCategories, ...this.identity }); + } + /** + * Adds a customizable icon in the system tray. To listen for a click on the icon use the `tray-icon-clicked` event. + * @param icon Image URL or base64 encoded string to be used as the icon + * + * @example + * + * ```js + * const imageUrl = "http://cdn.openfin.co/assets/testing/icons/circled-digit-one.png"; + * const base64EncodedImage = "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX\ + * ///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII"; + * const dataURL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DH\ + * xgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; + * + * async function setTrayIcon(icon) { + * const app = await fin.Application.getCurrent(); + * return await app.setTrayIcon(icon); + * } + * + * // use image url to set tray icon + * setTrayIcon(imageUrl).then(() => console.log('Setting tray icon')).catch(err => console.log(err)); + * + * // use base64 encoded string to set tray icon + * setTrayIcon(base64EncodedImage).then(() => console.log('Setting tray icon')).catch(err => console.log(err)); + * + * // use a dataURL to set tray icon + * setTrayIcon(dataURL).then(() => console.log('Setting tray icon')).catch(err => console.log(err)); + * ``` + */ + setTrayIcon(icon) { + return this.wire + .sendAction('set-tray-icon', { + enabledIcon: icon, + ...this.identity + }) + .then(() => undefined); + } + /** + * Sets new application's shortcut configuration. Windows only. + * @param config New application's shortcut configuration. + * + * @remarks Application has to be launched with a manifest and has to have shortcut configuration (icon url, name, etc.) in its manifest + * to be able to change shortcut states. + * + * @example + * + * ```js + * async function setShortcuts(config) { + * const app = await fin.Application.getCurrent(); + * return app.setShortcuts(config); + * } + * + * setShortcuts({ + * desktop: true, + * startMenu: false, + * systemStartup: true + * }).then(() => console.log('Shortcuts are set.')).catch(err => console.log(err)); + * ``` + */ + setShortcuts(config) { + return this.wire.sendAction('set-shortcuts', { data: config, ...this.identity }).then(() => undefined); + } + /** + * Sets the query string in all shortcuts for this app. Requires RVM 5.5+. + * @param queryString The new query string for this app's shortcuts. + * + * @example + * + * ```js + * const newQueryArgs = 'arg=true&arg2=false'; + * const app = await fin.Application.getCurrent(); + * try { + * await app.setShortcutQueryParams(newQueryArgs); + * } catch(err) { + * console.error(err) + * } + * ``` + */ + async setShortcutQueryParams(queryString) { + await this.wire.sendAction('set-shortcut-query-args', { data: queryString, ...this.identity }); + } + /** + * Sets the zoom level of the application. The original size is 0 and each increment above or below represents zooming 20% + * larger or smaller to default limits of 300% and 50% of original size, respectively. + * @param level The zoom level + * + * @example + * + * ```js + * async function setZoomLevel(number) { + * const app = await fin.Application.getCurrent(); + * return await app.setZoomLevel(number); + * } + * + * setZoomLevel(5).then(() => console.log('Setting a zoom level')).catch(err => console.log(err)); + * ``` + */ + setZoomLevel(level) { + return this.wire.sendAction('set-application-zoom-level', { level, ...this.identity }).then(() => undefined); + } + /** + * Sets a username to correlate with App Log Management. + * @param username Username to correlate with App's Log. + * + * @example + * + * ```js + * async function setAppLogUser() { + * const app = await fin.Application.getCurrent(); + * return await app.setAppLogUsername('username'); + * } + * + * setAppLogUser().then(() => console.log('Success')).catch(err => console.log(err)); + * + * ``` + */ + async setAppLogUsername(username) { + await this.wire.sendAction('set-app-log-username', { data: username, ...this.identity }); + } + /** + * Retrieves information about the system tray. If the system tray is not set, it will throw an error message. + * @remarks The only information currently returned is the position and dimensions. + * + * @example + * + * ```js + * async function getTrayIconInfo() { + * const app = await fin.Application.wrap({ uuid: 'testapp' }); + * return await app.getTrayIconInfo(); + * } + * getTrayIconInfo().then(info => console.log(info)).catch(err => console.log(err)); + * ``` + */ + getTrayIconInfo() { + return this.wire.sendAction('get-tray-icon-info', this.identity).then(({ payload }) => payload.data); + } + /** + * Checks if the application has an associated tray icon. + * + * @example + * + * ```js + * const app = await fin.Application.wrap({ uuid: 'testapp' }); + * const hasTrayIcon = await app.hasTrayIcon(); + * console.log(hasTrayIcon); + * ``` + */ + hasTrayIcon() { + return this.wire.sendAction('has-tray-icon', this.identity).then(({ payload }) => payload.data); + } + /** + * Closes the application by terminating its process. + * + * @example + * + * ```js + * async function terminateApp() { + * const app = await fin.Application.getCurrent(); + * return await app.terminate(); + * } + * terminateApp().then(() => console.log('Application terminated')).catch(err => console.log(err)); + * ``` + */ + terminate() { + return this.wire.sendAction('terminate-application', this.identity).then(() => undefined); + } + /** + * Waits for a hanging application. This method can be called in response to an application + * "not-responding" to allow the application to continue and to generate another "not-responding" + * message after a certain period of time. + * + * @ignore + */ + wait() { + return this.wire.sendAction('wait-for-hung-application', this.identity).then(() => undefined); + } + /** + * Retrieves information about the application. + * + * @remarks If the application was not launched from a manifest, the call will return the closest parent application `manifest` + * and `manifestUrl`. `initialOptions` shows the parameters used when launched programmatically, or the `startup_app` options + * if launched from manifest. The `parentUuid` will be the uuid of the immediate parent (if applicable). + * + * @example + * + * ```js + * async function getInfo() { + * const app = await fin.Application.getCurrent(); + * return await app.getInfo(); + * } + * + * getInfo().then(info => console.log(info)).catch(err => console.log(err)); + * ``` + */ + getInfo() { + return this.wire.sendAction('get-info', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves all process information for entities (windows and views) associated with an application. + * + * @example + * ```js + * const app = await fin.Application.getCurrent(); + * const processInfo = await app.getProcessInfo(); + * ``` + * @experimental + */ + async getProcessInfo() { + const { payload: { data } } = await this.wire.sendAction('application-get-process-info', this.identity); + return data; + } + /** + * Sets file auto download location. It's only allowed in the same application. + * + * Note: This method is restricted by default and must be enabled via + * API security settings. + * @param downloadLocation file auto download location + * + * @throws if setting file auto download location on different applications. + * @example + * + * ```js + * const downloadLocation = 'C:\\dev\\temp'; + * const app = await fin.Application.getCurrent(); + * try { + * await app.setFileDownloadLocation(downloadLocation); + * console.log('File download location is set'); + * } catch(err) { + * console.error(err) + * } + * ``` + */ + async setFileDownloadLocation(downloadLocation) { + const { name } = this.wire.me; + const entityIdentity = { uuid: this.identity.uuid, name }; + await this.wire.sendAction('set-file-download-location', { ...entityIdentity, downloadLocation }); + } + /** + * Gets file auto download location. It's only allowed in the same application. If file auto download location is not set, it will return the default location. + * + * Note: This method is restricted by default and must be enabled via + * API security settings. + * + * @throws if getting file auto download location on different applications. + * @example + * + * ```js + * const app = await fin.Application.getCurrent(); + * const fileDownloadDir = await app.getFileDownloadLocation(); + * ``` + */ + async getFileDownloadLocation() { + const { payload: { data } } = await this.wire.sendAction('get-file-download-location', this.identity); + return data; + } + /** + * Shows a menu on the tray icon. Use with tray-icon-clicked event. + * @param options + * @typeParam Data User-defined shape for data returned upon menu item click. Should be a + * [union](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) + * of all possible data shapes for the entire menu, and the click handler should process + * these with a "reducer" pattern. + * @throws if the application has no tray icon set + * @throws if the system tray is currently hidden + * @example + * + * ```js + * const iconUrl = 'http://cdn.openfin.co/assets/testing/icons/circled-digit-one.png'; + * const app = fin.Application.getCurrentSync(); + * + * await app.setTrayIcon(iconUrl); + * + * const template = [ + * { + * label: 'Menu Item 1', + * data: 'hello from item 1' + * }, + * { type: 'separator' }, + * { + * label: 'Menu Item 2', + * type: 'checkbox', + * checked: true, + * data: 'The user clicked the checkbox' + * }, + * { + * label: 'see more', + * enabled: false, + * submenu: [ + * { label: 'submenu 1', data: 'hello from submenu' } + * ] + * } + * ]; + * + * app.addListener('tray-icon-clicked', (event) => { + * // right-click + * if (event.button === 2) { + * app.showTrayIconPopupMenu({ template }).then(r => { + * if (r.result === 'closed') { + * console.log('nothing happened'); + * } else { + * console.log(r.data); + * } + * }); + * } + * }); + * ``` + */ + async showTrayIconPopupMenu(options) { + const { name } = this.wire.me; + const entityIdentity = { uuid: this.identity.uuid, name }; + const { payload } = await this.wire.sendAction('show-tray-icon-popup-menu', { ...entityIdentity, options }); + return payload.data; + } + /** + * Closes the tray icon menu. + * + * @throws if the application has no tray icon set + * @example + * + * ```js + * const app = fin.Application.getCurrentSync(); + * + * await app.closeTrayIconPopupMenu(); + * ``` + */ + async closeTrayIconPopupMenu() { + const { name } = this.wire.me; + const entityIdentity = { uuid: this.identity.uuid, name }; + await this.wire.sendAction('close-tray-icon-popup-menu', { ...entityIdentity }); + } + } + Instance$6.Application = Application; + return Instance$6; +} + +var hasRequiredFactory$2; + +function requireFactory$2 () { + if (hasRequiredFactory$2) return Factory$7; + hasRequiredFactory$2 = 1; + Object.defineProperty(Factory$7, "__esModule", { value: true }); + Factory$7.ApplicationModule = void 0; + const base_1 = base; + const validate_1 = validate; + const Instance_1 = requireInstance$1(); + /** + * Static namespace for OpenFin API methods that interact with the {@link Application} class, available under `fin.Application`. + */ + class ApplicationModule extends base_1.Base { + /** + * Asynchronously returns an API handle for the given Application identity. + * + * @remarks Wrapping an Application identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for an Application throughout its entire lifecycle. + * + * @example + * + * ```js + * fin.Application.wrap({ uuid: 'testapp' }) + * .then(app => app.isRunning()) + * .then(running => console.log('Application is running: ' + running)) + * .catch(err => console.log(err)); + * ``` + * + */ + async wrap(identity) { + this.wire.sendAction('wrap-application').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1.Application(this.wire, identity); + } + /** + * Synchronously returns an API handle for the given Application identity. + * + * @remarks Wrapping an Application identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for an Aplication throughout its entire lifecycle. + * + * @example + * + * ```js + * const app = fin.Application.wrapSync({ uuid: 'testapp' }); + * await app.close(); + * ``` + * + */ + wrapSync(identity) { + this.wire.sendAction('wrap-application-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1.Application(this.wire, identity); + } + async _create(appOptions) { + // set defaults: + if (appOptions.waitForPageLoad === undefined) { + appOptions.waitForPageLoad = false; + } + if (appOptions.autoShow === undefined && appOptions.isPlatformController === undefined) { + appOptions.autoShow = true; + } + await this.wire.sendAction('create-application', appOptions); + return this.wrap({ uuid: appOptions.uuid }); + } + /** + * DEPRECATED method to create a new Application. Use {@link Application.ApplicationModule.start Application.start} instead. + * + * @example + * + * ```js + * async function createApp() { + * const app = await fin.Application.create({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Application.create.html', + * autoShow: true + * }); + * await app.run(); + * } + * + * createApp().then(() => console.log('Application is created')).catch(err => console.log(err)); + * ``` + * + * @ignore + */ + create(appOptions) { + console.warn('Deprecation Warning: fin.Application.create is deprecated. Please use fin.Application.start'); + this.wire.sendAction('application-create').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this._create(appOptions); + } + /** + * Creates and starts a new Application. + * + * @example + * + * ```js + * async function start() { + * return fin.Application.start({ + * name: 'app-1', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Application.start.html', + * autoShow: true + * }); + * } + * start().then(() => console.log('Application is running')).catch(err => console.log(err)); + * ``` + * + */ + async start(appOptions) { + this.wire.sendAction('start-application').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const app = await this._create(appOptions); + await this.wire.sendAction('run-application', { uuid: appOptions.uuid }); + return app; + } + /** + * Asynchronously starts a batch of applications given an array of application identifiers and manifestUrls. + * Returns once the RVM is finished attempting to launch the applications. + * @param opts - Parameters that the RVM will use. + * + * @example + * + * ```js + * + * const applicationInfoArray = [ + * { + * "uuid": 'App-1', + * "manifestUrl": 'http://localhost:5555/app1.json', + * }, + * { + * "uuid": 'App-2', + * "manifestUrl": 'http://localhost:5555/app2.json', + * }, + * { + * "uuid": 'App-3', + * "manifestUrl": 'http://localhost:5555/app3.json', + * } + * ] + * + * fin.Application.startManyManifests(applicationInfoArray) + * .then(() => { + * console.log('RVM has finished launching the application list.'); + * }) + * .catch((err) => { + * console.log(err); + * }) + * ``` + * + * @experimental + */ + async startManyManifests(applications, opts) { + return this.wire.sendAction('run-applications', { applications, opts }).then(() => undefined); + } + /** + * Asynchronously returns an Application object that represents the current application + * + * @example + * + * ```js + * async function isCurrentAppRunning () { + * const app = await fin.Application.getCurrent(); + * return app.isRunning(); + * } + * + * isCurrentAppRunning().then(running => { + * console.log(`Current app is running: ${running}`); + * }).catch(err => { + * console.error(err); + * }); + * + * ``` + */ + getCurrent() { + this.wire.sendAction('get-current-application').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.wrap({ uuid: this.wire.me.uuid }); + } + /** + * Synchronously returns an Application object that represents the current application + * + * @example + * + * ```js + * async function isCurrentAppRunning () { + * const app = fin.Application.getCurrentSync(); + * return app.isRunning(); + * } + * + * isCurrentAppRunning().then(running => { + * console.log(`Current app is running: ${running}`); + * }).catch(err => { + * console.error(err); + * }); + * + * ``` + */ + getCurrentSync() { + this.wire.sendAction('get-current-application-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.wrapSync({ uuid: this.wire.me.uuid }); + } + /** + * Retrieves application's manifest and returns a running instance of the application. + * @param manifestUrl - The URL of app's manifest. + * @param opts - Parameters that the RVM will use. + * + * @example + * + * ```js + * fin.Application.startFromManifest('http://localhost:5555/app.json').then(app => console.log('App is running')).catch(err => console.log(err)); + * + * // For a local manifest file: + * fin.Application.startFromManifest('file:///C:/somefolder/app.json').then(app => console.log('App is running')).catch(err => console.log(err)); + * ``` + */ + async startFromManifest(manifestUrl, opts) { + this.wire.sendAction('application-start-from-manifest').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const app = await this._createFromManifest(manifestUrl); + // @ts-expect-error using private method without warning. + await app._run(opts); // eslint-disable-line no-underscore-dangle + return app; + } + /** + * @deprecated Use {@link Application.ApplicationModule.startFromManifest Application.startFromManifest} instead. + * Retrieves application's manifest and returns a wrapped application. + * @param manifestUrl - The URL of app's manifest. + * @param callback - called if the method succeeds. + * @param errorCallback - called if the method fails. The reason for failure is passed as an argument. + * + * @example + * + * ```js + * fin.Application.createFromManifest('http://localhost:5555/app.json').then(app => console.log(app)).catch(err => console.log(err)); + * ``` + * @ignore + */ + createFromManifest(manifestUrl) { + console.warn('Deprecation Warning: fin.Application.createFromManifest is deprecated. Please use fin.Application.startFromManifest'); + this.wire.sendAction('application-create-from-manifest').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this._createFromManifest(manifestUrl); + } + _createFromManifest(manifestUrl) { + return this.wire + .sendAction('get-application-manifest', { manifestUrl }) + .then(({ payload }) => { + const uuid = payload.data.platform ? payload.data.platform.uuid : payload.data.startup_app.uuid; + return this.wrap({ uuid }); + }) + .then((app) => { + app._manifestUrl = manifestUrl; // eslint-disable-line no-underscore-dangle + return app; + }); + } + } + Factory$7.ApplicationModule = ApplicationModule; + return Factory$7; +} + +var hasRequiredApplication; + +function requireApplication () { + if (hasRequiredApplication) return application; + hasRequiredApplication = 1; + (function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + /** + * Entry points for the OpenFin `Application` API (`fin.Application`). + * + * * {@link ApplicationModule} contains static members of the `Application` API, accessible through `fin.Application`. + * * {@link Application} describes an instance of an OpenFin Application, e.g. as returned by `fin.Application.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + */ + __exportStar(requireFactory$2(), exports); + __exportStar(requireInstance$1(), exports); + } (application)); + return application; +} + +var promisifySubscription$1 = {}; + +Object.defineProperty(promisifySubscription$1, "__esModule", { value: true }); +promisifySubscription$1.promisifySubscription = void 0; +const promisifySubscription = async (emitter, eventName, predicate = () => true, timeout) => { + let resolve; + let reject; + let timer; + const valuePromise = new Promise((y, n) => { + resolve = y; + reject = n; + }); + const listener = (e) => { + if (predicate(e)) { + clearTimeout(timer); + resolve(e); + } + }; + await emitter.on(eventName, listener); + if (timeout) { + timer = setTimeout(() => reject(new Error('event timed out')), timeout); + } + valuePromise.finally(() => { + emitter.removeListener(eventName, listener).catch(() => null); + }); + return { + getValue: () => valuePromise + }; +}; +promisifySubscription$1.promisifySubscription = promisifySubscription; + +var hasRequiredInstance; + +function requireInstance () { + if (hasRequiredInstance) return Instance$7; + hasRequiredInstance = 1; + Object.defineProperty(Instance$7, "__esModule", { value: true }); + Instance$7._Window = void 0; + /* eslint-disable import/prefer-default-export */ + /* eslint-disable @typescript-eslint/no-unused-vars */ + /* eslint-disable no-console */ + /* eslint-disable @typescript-eslint/no-non-null-assertion */ + const application_1 = requireApplication(); + const main_1 = main; + const view_1 = requireView(); + const warnings_1 = warnings; + const promisifySubscription_1 = promisifySubscription$1; + /** + * A basic window that wraps a native HTML window. Provides more fine-grained + * control over the window state such as the ability to minimize, maximize, restore, etc. + * By default a window does not show upon instantiation; instead the window's show() method + * must be invoked manually. The new window appears in the same process as the parent window. + * It has the ability to listen for {@link OpenFin.WindowEvents window specific events}. + */ + // The window.Window name is taken + class _Window extends main_1.WebContents { + /** + * @internal + */ + constructor(wire, identity) { + super(wire, identity, 'window'); + } + async createWindow(options) { + this.wire.sendAction('window-create-window', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const CONSTRUCTOR_CB_TOPIC = 'fire-constructor-callback'; + const responseSubscription = await (0, promisifySubscription_1.promisifySubscription)(this, CONSTRUCTOR_CB_TOPIC); + // set defaults: + if (options.waitForPageLoad === undefined) { + options.waitForPageLoad = false; + } + if (options.autoShow === undefined) { + options.autoShow = true; + } + (0, warnings_1.handleDeprecatedWarnings)(options); + const windowCreation = this.wire.environment.createChildContent({ entityType: 'window', options }); + const [response] = await Promise.all([responseSubscription.getValue(), windowCreation]); + let cbPayload; + const { success } = response; + const responseData = response.data; + const { message } = responseData; + if (success) { + cbPayload = { + httpResponseCode: responseData.httpResponseCode, + apiInjected: responseData.apiInjected + }; + } + else { + cbPayload = { + message: responseData.message, + networkErrorCode: responseData.networkErrorCode, + stack: responseData.stack + }; + } + const pageResolve = { + message, + cbPayload, + success + }; + try { + // this is to enforce a 5.0 contract that the child's main function + // will not fire before the parent's success callback on creation. + // if the child window is not accessible (CORS) this contract does + // not hold. + const webWindow = this.getWebWindow(); + webWindow.fin.__internal_.openerSuccessCBCalled(); + } + catch (e) { + // common for main windows, we do not want to expose this error. here just to have a debug target. + // console.error(e); + } + if (pageResolve.success) { + return this; + } + return Promise.reject(pageResolve); + } + /** + * Retrieves an array of frame info objects representing the main frame and any + * iframes that are currently on the page. + * + * @example + * ```js + * async function getAllFrames() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getAllFrames.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getAllFrames(); + * } + * + * getAllFrames().then(framesInfo => console.log(framesInfo)).catch(err => console.log(err)); + * ``` + */ + getAllFrames() { + return this.wire.sendAction('get-all-frames', this.identity).then(({ payload }) => payload.data); + } + /** + * Gets the current bounds (top, bottom, right, left, width, height) of the window. + * + * @example + * ```js + * async function getBounds() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getBounds.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getBounds(); + * } + * + * getBounds().then(bounds => console.log(bounds)).catch(err => console.log(err)); + * ``` + */ + getBounds() { + return this.wire + .sendAction('get-window-bounds', this.identity) + .then(({ payload }) => payload.data); + } + /** + * Centers the window on its current screen. + * + * @remarks Does not have an effect on minimized or maximized windows. + * + * @example + * ```js + * async function centerWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.center.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.center(); + * } + * + * centerWindow().then(() => console.log('Window centered')).catch(err => console.log(err)); + * ``` + * + */ + center() { + return this.wire.sendAction('center-window', this.identity).then(() => undefined); + } + /** + * Removes focus from the window. + * + * @example + * ```js + * async function blurWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.blur.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.blur(); + * } + * + * blurWindow().then(() => console.log('Blured Window')).catch(err => console.log(err)); + * ``` + */ + blur() { + return this.wire.sendAction('blur-window', this.identity).then(() => undefined); + } + /** + * Brings the window to the front of the window stack. + * + * @example + * ```js + * async function BringWindowToFront() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.bringToFront.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.bringToFront(); + * } + * + * BringWindowToFront().then(() => console.log('Window is in the front')).catch(err => console.log(err)); + * ``` + */ + bringToFront() { + return this.wire.sendAction('bring-window-to-front', this.identity).then(() => undefined); + } + /** + * Performs the specified window transitions. + * @param transitions - Describes the animations to perform. See the tutorial. + * @param options - Options for the animation. See the tutorial. + * + * @example + * ``` + * async function animateWindow() { + * const transitions = { + * opacity: { + * opacity: 0.7, + * duration: 500 + * }, + * position: { + * top: 100, + * left: 100, + * duration: 500, + * relative: true + * } + * }; + * const options = { + * interrupt: true, + * tween: 'ease-in' + * }; + * + * const win = await fin.Window.getCurrent(); + * return win.animate(transitions, options); + * } + * + * animateWindow() + * .then(() => console.log('Animation done')) + * .catch(err => console.error(err)); + * ``` + */ + animate(transitions, options) { + return this.wire + .sendAction('animate-window', { + transitions, + options, + ...this.identity + }) + .then(() => undefined); + } + /** + * Hides the window. + * + * @example + * ```js + * async function hideWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.hide.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.hide(); + * } + * + * hideWindow().then(() => console.log('Window is hidden')).catch(err => console.log(err)); + * ``` + */ + hide() { + return this.wire.sendAction('hide-window', this.identity).then(() => undefined); + } + /** + * closes the window application + * @param force Close will be prevented from closing when force is false and + * ‘close-requested’ has been subscribed to for application’s main window. + * + * @example + * ```js + * async function closeWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.close.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.close(); + * } + * + * closeWindow().then(() => console.log('Window closed')).catch(err => console.log(err)); + * ``` + */ + close(force = false) { + return this.wire.sendAction('close-window', { force, ...this.identity }).then(() => { + Object.setPrototypeOf(this, null); + return undefined; + }); + } + focusedWebViewWasChanged() { + return this.wire.sendAction('focused-webview-changed', this.identity).then(() => undefined); + } + /** + * Returns the native OS level Id. + * + * @remarks In Windows, it will return the Windows [handle](https://docs.microsoft.com/en-us/windows/desktop/WinProg/windows-data-types#HWND). + * + * @example + * ```js + * async function getWindowNativeId() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getNativeId.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getNativeId(); + * } + * + * getWindowNativeId().then(nativeId => console.log(nativeId)).catch(err => console.log(err)); + * ``` + */ + getNativeId() { + return this.wire.sendAction('get-window-native-id', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves window's attached views. + * @experimental + * + * @example + * ```js + * const win = fin.Window.getCurrentSync(); + * + * win.getCurrentViews() + * .then(views => console.log(views)) + * .catch(console.error); + * ``` + */ + async getCurrentViews() { + const { payload } = await this.wire.sendAction('window-get-views', this.identity); + return payload.data.map((id) => new view_1.View(this.wire, id)); + } + /** + * @deprecated Use {@link Window._Window.disableUserMovement} instead. + */ + disableFrame() { + console.warn('Function is deprecated; use disableUserMovement instead.'); + return this.wire.sendAction('disable-window-frame', this.identity).then(() => undefined); + } + /** + * Prevents a user from changing a window's size/position when using the window's frame. + * + * @example + * ```js + * async function disableUserMovement() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.disableFrame.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.disableUserMovement(); + * } + * + * disableUserMovement().then(() => console.log('Window is disabled')).catch(err => console.log(err)); + * ``` + */ + disableUserMovement() { + return this.wire.sendAction('disable-window-frame', this.identity).then(() => undefined); + } + /** + * @deprecated Use {@link Window._Window.enableUserMovement} instead. + */ + enableFrame() { + console.warn('Function is deprecated; use enableUserMovement instead.'); + return this.wire.sendAction('enable-window-frame', this.identity).then(() => undefined); + } + /** + * Re-enables user changes to a window's size/position when using the window's frame. + * + * @example + * ```js + * async function enableUserMovement() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.enableFrame.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.enableUserMovement(); + * } + * + * enableUserMovement().then(() => console.log('Window is enabled')).catch(err => console.log(err)); + * ``` + */ + enableUserMovement() { + return this.wire.sendAction('enable-window-frame', this.identity).then(() => undefined); + } + /** + * Flashes the window’s frame and taskbar icon until stopFlashing is called or until a focus event is fired. + * + * @remarks On macOS flash only works on inactive windows. + * @example + * ```js + * async function windowFlash() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.flash.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.flash(); + * } + * + * windowFlash().then(() => console.log('Window flashing')).catch(err => console.log(err)); + * ``` + */ + flash() { + return this.wire.sendAction('flash-window', this.identity).then(() => undefined); + } + /** + * Stops the taskbar icon from flashing. + * + * @example + * ```js + * async function stopWindowFlashing() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.stopFlashing.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.stopFlashing(); + * } + * + * stopWindowFlashing().then(() => console.log('Application window flashing')).catch(err => console.log(err)); + * ``` + */ + stopFlashing() { + return this.wire.sendAction('stop-flash-window', this.identity).then(() => undefined); + } + /** + * Gets an information object for the window. + * + * @example + * ```js + * async function getInfo() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getInfo.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getInfo(); + * } + * + * getInfo().then(info => console.log(info)).catch(err => console.log(err)); + * ``` + */ + getInfo() { + return this.wire.sendAction('get-window-info', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves the window's Layout + * + * @example + * ```js + * //get the current window + * const window = await fin.Window.getCurrent(); + * + * //get the layout for the window + * const layout = await window.getLayout(); + * ``` + * @experimental + */ + async getLayout(layoutIdentity) { + this.wire.sendAction('window-get-layout', this.identity).catch((e) => { + // don't expose + }); + const opts = await this.getOptions(); + if (!opts.layout && !opts.layoutSnapshot) { + throw new Error('Window does not have a Layout'); + } + return this.fin.Platform.Layout.wrap(layoutIdentity ?? this.identity); + } + /** + * Gets the current settings of the window. + * + * @example + * ```js + * async function getWindowOptions() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getOptions.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getOptions(); + * } + * + * getWindowOptions().then(opts => console.log(opts)).catch(err => console.log(err)); + * ``` + */ + getOptions() { + return this.wire.sendAction('get-window-options', this.identity).then(({ payload }) => payload.data); + } + /** + * Gets the parent application. + * + * @example + * ```js + * async function getParentApplication() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getParentApplication.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getParentApplication(); + * } + * + * getParentApplication().then(parentApplication => console.log(parentApplication)).catch(err => console.log(err)); + * ``` + */ + getParentApplication() { + this.wire.sendAction('window-get-parent-application', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return Promise.resolve(new application_1.Application(this.wire, this.identity)); + } + /** + * Gets the parent window. + * + * @example + * ```js + * async function getParentWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getParentWindow.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getParentWindow(); + * } + * + * getParentWindow().then(parentWindow => console.log(parentWindow)).catch(err => console.log(err)); + * ``` + */ + getParentWindow() { + this.wire.sendAction('window-get-parent-window', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return Promise.resolve(new application_1.Application(this.wire, this.identity)).then((app) => app.getWindow()); + } + /** + * ***DEPRECATED - please use Window.capturePage.*** + * Gets a base64 encoded PNG image of the window or just part a of it. + * @param area The area of the window to be captured. + * Omitting it will capture the whole visible window. + * + * @tutorial Window.capturePage + */ + async getSnapshot(area) { + const req = { area, ...this.identity }; + console.warn('Window.getSnapshot has been deprecated, please use Window.capturePage'); + const res = await this.wire.sendAction('get-window-snapshot', req); + return res.payload.data; + } + /** + * Gets the current state ("minimized", "maximized", or "normal") of the window. + * + * @example + * ```js + * async function getWindowState() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getState.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getState(); + * } + * + * getWindowState().then(winState => console.log(winState)).catch(err => console.log(err)); + * ``` + */ + getState() { + return this.wire.sendAction('get-window-state', this.identity).then(({ payload }) => payload.data); + } + /** + * Previously called getNativeWindow. + * Returns the [Window Object](https://developer.mozilla.org/en-US/docs/Web/API/Window) + * that represents the web context of the target window. This is the same object that + * you would get from calling [window.open()](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) in a standard web context. + * The target window needs to be in the same application as the requesting window + * as well as comply with [same-origin](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy) policy requirements. + * + * @example + * Injecting content into an empty window: + * + * ```js + * (async ()=> { + * try { + * const winName = `child-window-${Date.now()}`; + * const win = await fin.Window.create({ + * name: winName, + * url: 'about:blank' + * }); + * win.getWebWindow().document.write('

Hello World

'); + * } catch (err) { + * console.error(err); + * } + * })(); + * ``` + * + * Cloning DOM elements from the parent window (in this example we clone an `h3` element from the parent window): + * ```js + * (async ()=> { + * try { + * const currentWindow = await fin.Window.getCurrent(); + * const parentWindow = await currentWindow.getParentWindow(); + * const clonedH3 = parentWindow.getWebWindow().document.querySelector('h3').cloneNode(true); + * document.body.append(clonedH3); + * + * } catch (err) { + * console.error(err); + * } + * })(); + * ``` + * + * Rendering on a child window via a library (in this example we are using the [lit-html](https://lit-html.polymer-project.org/) + * template library to render content on a blank child window. You are not going to be able to copy paste this example without + * configuring the project correctly but this would demonstrate some templating options available): + * ```js + * (async ()=> { + * try { + * const win = await fin.Window.create({ + * name: `child-window-${Date.now()}`, + * url: 'about:blank' + * }); + * const template = html` + *
+ * Click here: + * + *
`; + * render(template, win.getWebWindow().document.body); + * + * } catch (err) { + * console.error(err); + * } + * })(); + * ``` + */ + getWebWindow() { + this.wire.sendAction('window-get-web-window', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.wire.environment.getWebWindow(this.identity); + } + /** + * Determines if the window is a main window. + * + * @example + * ```js + * const wnd = fin.Window.getCurrentSync(); + * const isMainWnd = wnd.isMainWindow(); + * console.log('Is this a main window? ' + isMainWnd); + * ``` + */ + isMainWindow() { + this.wire.sendAction('window-is-main-window', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.me.uuid === this.me.name; + } + /** + * Determines if the window is currently showing. + * + * @example + * ```js + * async function isWindowShowing() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.isShowing.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.isShowing(); + * } + * + * isWindowShowing().then(bool => console.log(bool)).catch(err => console.log(err)); + * ``` + */ + isShowing() { + return this.wire.sendAction('is-window-showing', this.identity).then(({ payload }) => payload.data); + } + /** + * Maximizes the window + * + * @example + * ```js + * async function maxWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.maximize.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.maximize(); + * } + * + * maxWindow().then(() => console.log('Maximized window')).catch(err => console.log(err)); + * ``` + */ + maximize() { + return this.wire.sendAction('maximize-window', this.identity).then(() => undefined); + } + /** + * Minimizes the window. + * + * @example + * ```js + * async function minWindow() { + * const win = await fin.Window.getCurrent(); + * return await win.minimize(); + * } + * + * minWindow().then(() => console.log('Minimized window')).catch(err => console.log(err)); + * ``` + */ + minimize() { + return this.wire.sendAction('minimize-window', this.identity).then(() => undefined); + } + /** + * Moves the window by a specified amount. + * @param deltaLeft The change in the left position of the window + * @param deltaTop The change in the top position of the window + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.moveBy.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function moveBy(left, top) { + * const win = await createWin(); + * return await win.moveBy(left, top); + * } + * + * moveBy(580, 300).then(() => console.log('Moved')).catch(err => console.log(err)); + * ``` + */ + moveBy(deltaLeft, deltaTop, positioningOptions) { + return this.wire + .sendAction('move-window-by', { + deltaLeft, + deltaTop, + positioningOptions, + ...this.identity + }) + .then(() => undefined); + } + /** + * Moves the window to a specified location. + * @param left The left position of the window + * @param top The top position of the window + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.moveTo.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function moveTo(left, top) { + * const win = await createWin(); + * return await win.moveTo(left, top) + * } + * + * moveTo(580, 300).then(() => console.log('Moved')).catch(err => console.log(err)) + * ``` + */ + moveTo(left, top, positioningOptions) { + return this.wire + .sendAction('move-window', { + left, + top, + positioningOptions, + ...this.identity + }) + .then(() => undefined); + } + /** + * Resizes the window by a specified amount. + * @param deltaWidth The change in the width of the window + * @param deltaHeight The change in the height of the window + * @param anchor Specifies a corner to remain fixed during the resize. + * Can take the values: "top-left", "top-right", "bottom-left", or "bottom-right". + * If undefined, the default is "top-left" + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.resizeBy.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function resizeBy(left, top, anchor) { + * const win = await createWin(); + * return await win.resizeBy(left, top, anchor) + * } + * + * resizeBy(580, 300, 'top-right').then(() => console.log('Resized')).catch(err => console.log(err)); + * ``` + */ + resizeBy(deltaWidth, deltaHeight, anchor, positioningOptions) { + return this.wire + .sendAction('resize-window-by', { + deltaWidth: Math.floor(deltaWidth), + deltaHeight: Math.floor(deltaHeight), + anchor, + positioningOptions, + ...this.identity + }) + .then(() => undefined); + } + /** + * Resizes the window to the specified dimensions. + * @param width The change in the width of the window + * @param height The change in the height of the window + * @param anchor Specifies a corner to remain fixed during the resize. + * Can take the values: "top-left", "top-right", "bottom-left", or "bottom-right". + * If undefined, the default is "top-left" + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.resizeTo.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function resizeTo(left, top, anchor) { + * const win = await createWin(); + * return await win.resizeTo(left, top, anchor); + * } + * + * resizeTo(580, 300, 'top-left').then(() => console.log('Resized')).catch(err => console.log(err)); + * ``` + */ + resizeTo(width, height, anchor, positioningOptions) { + return this.wire + .sendAction('resize-window', { + width: Math.floor(width), + height: Math.floor(height), + anchor, + positioningOptions, + ...this.identity + }) + .then(() => undefined); + } + /** + * Restores the window to its normal state (i.e., unminimized, unmaximized). + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.restore.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function restore() { + * const win = await createWin(); + * return await win.restore(); + * } + * + * restore().then(() => console.log('Restored')).catch(err => console.log(err)); + * ``` + */ + restore() { + return this.wire.sendAction('restore-window', this.identity).then(() => undefined); + } + /** + * Will bring the window to the front of the entire stack and give it focus. + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.setAsForeground.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function setAsForeground() { + * const win = await createWin(); + * return await win.setAsForeground() + * } + * + * setAsForeground().then(() => console.log('In the foreground')).catch(err => console.log(err)); + * ``` + */ + setAsForeground() { + return this.wire.sendAction('set-foreground-window', this.identity).then(() => undefined); + } + /** + * Sets the window's size and position. + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.setBounds.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function setBounds(bounds) { + * const win = await createWin(); + * return await win.setBounds(bounds); + * } + * + * setBounds({ + * height: 100, + * width: 200, + * top: 400, + * left: 400 + * }).then(() => console.log('Bounds set to window')).catch(err => console.log(err)); + * ``` + */ + setBounds(bounds, positioningOptions) { + return this.wire + .sendAction('set-window-bounds', { ...bounds, ...this.identity, positioningOptions }) + .then(() => undefined); + } + /** + * Shows the window if it is hidden. + * @param force Show will be prevented from showing when force is false and + * ‘show-requested’ has been subscribed to for application’s main window. + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.show.html', + * autoShow: false + * }); + * return await app.getWindow(); + * } + * + * async function show() { + * const win = await createWin(); + * return await win.show() + * } + * + * show().then(() => console.log('Showing')).catch(err => console.log(err)); + * ``` + */ + show(force = false) { + return this.wire.sendAction('show-window', { force, ...this.identity }).then(() => undefined); + } + /** + * Shows the window if it is hidden at the specified location. + * + * @param left The left position of the window in pixels + * @param top The top position of the window in pixels + * @param force Show will be prevented from closing when force is false and + * ‘show-requested’ has been subscribed to for application’s main window + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.showAt.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function showAt(left, top) { + * const win = await createWin(); + * return await win.showAt(left, top) + * } + * + * showAt(580, 300).then(() => console.log('Showing at')).catch(err => console.log(err)); + * ``` + */ + showAt(left, top, force = false) { + return this.wire + .sendAction('show-at-window', { + force, + left: Math.floor(left), + top: Math.floor(top), + ...this.identity + }) + .then(() => undefined); + } + /** + * Shows the Chromium Developer Tools + * + * @tutorial Window.showDeveloperTools + */ + /** + * Updates the window using the passed options. + * + * @remarks Values that are objects are deep-merged, overwriting only the values that are provided. + * @param options Changes a window's options that were defined upon creation. See tutorial + * + * @example + * ```js + * async function updateOptions() { + * const win = await fin.Window.getCurrent(); + * return win.updateOptions({maxWidth: 100}); + * } + * updateOptions().then(() => console.log('options is updated')).catch(err => console.error(err)); + * ``` + */ + updateOptions(options) { + return this.wire.sendAction('update-window-options', { options, ...this.identity }).then(() => undefined); + } + /** + * Provides credentials to authentication requests + * @param userName userName to provide to the authentication challenge + * @param password password to provide to the authentication challenge + * + * @example + * ```js + * fin.Application.wrap({uuid: 'OpenfinPOC'}).then(app => { + * app.on('window-auth-requested', evt => { + * let win = fin.Window.wrap({ uuid: evt.uuid, name: evt.name}); + * win.authenticate('userName', 'P@assw0rd').then(()=> console.log('authenticated')).catch(err => console.log(err)); + * }); + * }); + * ``` + */ + authenticate(userName, password) { + return this.wire + .sendAction('window-authenticate', { userName, password, ...this.identity }) + .then(() => undefined); + } + /** + * Shows a menu on the window. + * + * @remarks Returns a promise that resolves when the user has either selected an item or closed the menu. (This may take longer than other apis). + * Resolves to an object with `{result: 'clicked', data }` where data is the data field on the menu item clicked, or `{result 'closed'}` when the user doesn't select anything. + * Calling this method will close previously opened menus. + * @experimental + * @param options + * @typeParam Data User-defined shape for data returned upon menu item click. Should be a + * [union](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) + * of all possible data shapes for the entire menu, and the click handler should process + * these with a "reducer" pattern. + * @example + * This could be used to show a drop down menu over views in a platform window: + * ```js + * const template = [ + * { + * label: 'Menu Item 1', + * data: 'hello from item 1' + * }, + * { type: 'separator' }, + * { + * label: 'Menu Item 2', + * type: 'checkbox', + * checked: true, + * data: 'The user clicked the checkbox' + * }, + * { + * label: 'see more', + * enabled: false, + * submenu: [ + * { label: 'submenu 1', data: 'hello from submenu' } + * ] + * } + * ] + * fin.me.showPopupMenu({ template }).then(r => { + * if (r.result === 'closed') { + * console.log('nothing happened'); + * } else { + * console.log(r.data) + * } + * }) + * ``` + * + * Overriding the built in context menu (note: that this can be done per element or document wide): + * ```js + * document.addEventListener('contextmenu', e => { + * e.preventDefault(); + * const template = [ + * { + * label: 'Menu Item 1', + * data: 'hello from item 1' + * }, + * { type: 'separator' }, + * { + * label: 'Menu Item 2', + * type: 'checkbox', + * checked: true, + * data: 'The user clicked the checkbox' + * }, + * { + * label: 'see more', + * enabled: false, + * submenu: [ + * { label: 'submenu 1', data: 'hello from submenu' } + * ] + * } + * ] + * fin.me.showPopupMenu({ template, x: e.x, y: e.y }).then(r => { + * if (r.result === 'closed') { + * console.log('nothing happened'); + * } else { + * console.log(r.data) + * } + * }) + * }) + * ``` + */ + async showPopupMenu(options) { + const { payload } = await this.wire.sendAction('show-popup-menu', { options, ...this.identity }); + return payload.data; + } + /** + * Closes the window's popup menu, if one exists. + * @experimental + * + * @remarks Only one popup menu will ever be showing at a time. Calling `showPopupMenu` will automatically close + * any existing popup menu. + * + * + * @example + * This could be used to close a popup menu if the user's mouse leaves an element for example. + * + * ```js + * await fin.me.closePopupMenu(); + * ``` + */ + async closePopupMenu() { + return this.wire.sendAction('close-popup-menu', { ...this.identity }).then(() => undefined); + } + /** + * Dispatch a result to the caller of `showPopupWindow`. + * + * @remarks If this window isn't currently being shown as a popup, this call will silently fail. + * @param data Serializable data to send to the caller window. + * + * @example + * ```js + * await fin.me.dispatchPopupResult({ + * foo: 'bar' + * }); + * ``` + */ + async dispatchPopupResult(data) { + this.wire.sendAction('window-dispatch-popup-result', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + await this.wire.sendAction('dispatch-popup-result', { data, ...this.identity }); + } + /** + * Prints the contents of the window. + * + * @param options Configuration for the print task. + * @remarks When `silent` is set to `true`, the API will pick the system's default printer if deviceName is empty + * and the default settings for printing. + * + * Use the CSS style `page-break-before: always;` to force print to a new page. + * + * @example + * ```js + * const win = fin.Window.getCurrentSync(); + * + * win.print({ silent: false, deviceName: 'system-printer-name' }).then(() => { + * console.log('print call has been sent to the system'); + * }); + * ``` + * + * If a window has embedded views, those views will not print by default. To print a window's contents including embedded views, + * use the `content` option: + * + * ```js + * const win = fin.Window.getCurrentSync(); + * + * // Print embedded views + * win.print({ content: 'views' }); + * + * // Print screenshot of current window + * win.print({ content: 'screenshot' }) + * ``` + * + * When `content` is set to `views`, the embedded views in the platform window will be concatenated and printed as + * individual pages. If `includeSelf` is set to `true`, the platform window itself will be printed as the first + * page - be aware that this page will *not* include the embedded views - it will only include the contents of + * the platform window itself (e.g. tab stacks), with blank spaces where the view contents would be embedded. + * + * Due to a known issue, view contents that are not visible at the time `print` is called will not appear when + * printing `contents: views`. This includes views that are obscured behind other active UI elements. + * + * To print the views embedded in their page context, set `content` to `screenshot`. + */ + async print(options = { content: 'self' }) { + switch (options.content) { + case undefined: + case 'self': + return super.print(options); + case 'screenshot': + return this.wire.sendAction('print-screenshot', this.identity).then(() => undefined); + case 'views': + return this.wire.sendAction('print-views', { ...this.identity, options }).then(() => undefined); + default: + return undefined; + } + } + } + Instance$7._Window = _Window; + return Instance$7; +} + +var hasRequiredFactory$1; + +function requireFactory$1 () { + if (hasRequiredFactory$1) return Factory$8; + hasRequiredFactory$1 = 1; + Object.defineProperty(Factory$8, "__esModule", { value: true }); + Factory$8._WindowModule = void 0; + const base_1 = base; + const validate_1 = validate; + const Instance_1 = requireInstance(); + /** + * Static namespace for OpenFin API methods that interact with the {@link _Window} class, available under `fin.Window`. + */ + class _WindowModule extends base_1.Base { + /** + * Asynchronously returns an API handle for the given Window identity. + * + * @remarks Wrapping a Window identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a Window throughout its entire lifecycle. + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.wrap.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * createWin().then(() => fin.Window.wrap({ uuid: 'app-1', name: 'myApp' })) + * .then(win => console.log('wrapped window')) + * .catch(err => console.log(err)); + * ``` + */ + async wrap(identity) { + this.wire.sendAction('window-wrap').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1._Window(this.wire, identity); + } + /** + * Synchronously returns an API handle for the given Window identity. + * + * @remarks Wrapping a Window identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a Window throughout its entire lifecycle. + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.wrapSync.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * await createWin(); + * let win = fin.Window.wrapSync({ uuid: 'app-1', name: 'myApp' }); + * ``` + */ + wrapSync(identity) { + this.wire.sendAction('window-wrap-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1._Window(this.wire, identity); + } + /** + * Creates a new Window. + * @param options - Window creation options + * + * @example + * ```js + * async function createWindow() { + * const winOption = { + * name:'child', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.create.html', + * frame: true, + * autoShow: true + * }; + * return await fin.Window.create(winOption); + * } + * + * createWindow().then(() => console.log('Window is created')).catch(err => console.log(err)); + * ``` + */ + create(options) { + this.wire.sendAction('create-window').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const win = new Instance_1._Window(this.wire, { uuid: this.me.uuid, name: options.name }); + return win.createWindow(options); + } + /** + * Asynchronously returns a Window object that represents the current window + * + * @example + * ```js + * fin.Window.getCurrent() + * .then(wnd => console.log('current window')) + * .catch(err => console.log(err)); + * + * ``` + */ + getCurrent() { + this.wire.sendAction('get-current-window').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (!this.wire.me.isWindow) { + throw new Error('You are not in a Window context'); + } + const { uuid, name } = this.wire.me; + return this.wrap({ uuid, name }); + } + /** + * Synchronously returns a Window object that represents the current window + * + * @example + * ```js + * const wnd = fin.Window.getCurrentSync(); + * const info = await wnd.getInfo(); + * console.log(info); + * + * ``` + */ + getCurrentSync() { + this.wire.sendAction('get-current-window-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (!this.wire.me.isWindow) { + throw new Error('You are not in a Window context'); + } + const { uuid, name } = this.wire.me; + return this.wrapSync({ uuid, name }); + } + } + Factory$8._WindowModule = _WindowModule; + return Factory$8; +} + +var hasRequiredWindow; + +function requireWindow () { + if (hasRequiredWindow) return window$1; + hasRequiredWindow = 1; + (function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + /** + * Entry points for the OpenFin `Window` API (`fin.Window`). + * + * * {@link _WindowModule} contains static members of the `Window` API, accessible through `fin.Window`. + * * {@link _Window} describes an instance of an OpenFin Window, e.g. as returned by `fin.Window.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * Underscore prefixing of OpenFin types that alias DOM entities will be fixed in a future version. + * + * @packageDocumentation + */ + __exportStar(requireFactory$1(), exports); + __exportStar(requireInstance(), exports); + } (window$1)); + return window$1; +} + +/** + * Entry point for the OpenFin `System` API (`fin.System`). + * + * * {@link System} contains static members of the `System` API (available under `fin.System`) + * + * @packageDocumentation + */ +Object.defineProperty(system, "__esModule", { value: true }); +system.System = void 0; +const base_1$i = base; +const transport_errors_1$1 = transportErrors; +const window_1 = requireWindow(); +const events_1$6 = require$$0; +/** + * An object representing the core of OpenFin Runtime. Allows the developer + * to perform system-level actions, such as accessing logs, viewing processes, + * clearing the cache and exiting the runtime as well as listen to {@link OpenFin.SystemEvents system events}. + * + */ +class System extends base_1$i.EmitterBase { + /** + * @internal + */ + constructor(wire) { + super(wire, 'system'); + } + sendExternalProcessRequest(action, options) { + return new Promise((resolve, reject) => { + const exitEventKey = 'external-process-exited'; + let processUuid; + let exitPayload; + let externalProcessExitHandler; + let ofWindow; + if (typeof options.listener === 'function') { + externalProcessExitHandler = (payload) => { + const data = payload || {}; + exitPayload = { + topic: 'exited', + uuid: data.processUuid || '', + exitCode: data.exitCode || 0 + }; + if (processUuid === payload.processUuid) { + options.listener(exitPayload); + ofWindow.removeListener(exitEventKey, externalProcessExitHandler); + } + }; + // window constructor expects the name is not undefined + if (!this.wire.me.name) { + this.wire.me.name = this.wire.me.uuid; + } + ofWindow = new window_1._Window(this.wire, this.wire.me); + ofWindow.on(exitEventKey, externalProcessExitHandler); + } + this.wire + .sendAction(action, options) + .then(({ payload }) => { + processUuid = payload.data.uuid; + resolve(payload.data); + if (exitPayload && processUuid === exitPayload.uuid) { + options.listener(exitPayload); + ofWindow.removeListener(exitEventKey, externalProcessExitHandler); + } + }) + .catch((err) => { + if (ofWindow) { + ofWindow.removeListener(exitEventKey, externalProcessExitHandler); + } + reject(err); + }); + }); + } + /** + * Returns the version of the runtime. The version contains the major, minor, + * build and revision numbers. + * + * @example + * ```js + * fin.System.getVersion().then(v => console.log(v)).catch(err => console.log(err)); + * ``` + */ + getVersion() { + return this.wire.sendAction('get-version').then(({ payload }) => payload.data); + } + /** + * Clears cached data containing application resource + * files (images, HTML, JavaScript files), cookies, and items stored in the + * Local Storage. + * @param options - See below for details. + * + * @remarks For more information on the accepted options, see the following pages: + * * cache: browsing data cache for html files and images ([caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching)) + * * cookies: browser [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) + * * localStorage: browser data that can be used across sessions ([local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)) + * * appcache: html5 [application cache](https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache) + * @example + * ```js + * const clearCacheOptions = { + * appcache: true, + * cache: true, + * cookies: true, + * localStorage: true + * }; + * fin.System.clearCache(clearCacheOptions).then(() => console.log('Cache cleared')).catch(err => console.log(err)); + * ``` + * + */ + clearCache(options) { + return this.wire.sendAction('clear-cache', options).then(() => undefined); + } + /** + * Clears all cached data when OpenFin Runtime exits. + * + * @example + * ```js + * fin.System.deleteCacheOnExit().then(() => console.log('Deleted Cache')).catch(err => console.log(err)); + * ``` + */ + deleteCacheOnExit() { + return this.wire.sendAction('delete-cache-request').then(() => undefined); + } + /** + * Exits the Runtime. + * + * @example + * ```js + * fin.System.exit().then(() => console.log('exit')).catch(err => console.log(err)); + * ``` + */ + exit() { + return this.wire.sendAction('exit-desktop').then(() => undefined); + } + /** + * Fetches a JSON manifest using the browser process and returns a Javascript object. + * @param manifestUrl The URL of the manifest to fetch. + * + * @example + * ```js + * const manifest = await fin.System.fetchManifest('https://www.path-to-manifest.com'); + * console.log(manifest); + * ``` + */ + async fetchManifest(manifestUrl) { + const { payload: { data } } = await this.wire.sendAction('fetch-manifest', { manifestUrl }); + return data; + } + /** + * Writes any unwritten cookies data to disk. + * + * @example + * ```js + * fin.System.flushCookieStore() + * .then(() => console.log('success')) + * .catch(err => console.error(err)); + * ``` + */ + flushCookieStore() { + return this.wire.sendAction('flush-cookie-store').then(() => undefined); + } + /** + * Retrieves an array of data (name, ids, bounds) for all application windows. + * + * @example + * ```js + * fin.System.getAllWindows().then(wins => console.log(wins)).catch(err => console.log(err)); + * ``` + */ + getAllWindows() { + return this.wire.sendAction('get-all-windows').then(({ payload }) => payload.data); + } + /** + * Retrieves an array of data for all applications. + * + * @example + * ```js + * fin.System.getAllApplications().then(apps => console.log(apps)).catch(err => console.log(err)); + * ``` + */ + getAllApplications() { + return this.wire.sendAction('get-all-applications').then(({ payload }) => payload.data); + } + /** + * Retrieves the command line argument string that started OpenFin Runtime. + * + * @example + * ```js + * fin.System.getCommandLineArguments().then(args => console.log(args)).catch(err => console.log(err)); + * ``` + */ + getCommandLineArguments() { + return this.wire.sendAction('get-command-line-arguments').then(({ payload }) => payload.data); + } + /** + * Get the current state of the crash reporter. + * + * @example + * ```js + * fin.System.getCrashReporterState().then(state => console.log(state)).catch(err => console.log(err)); + * ``` + */ + async getCrashReporterState() { + const { payload: { data: { diagnosticMode, isRunning } } } = await this.wire.sendAction('get-crash-reporter-state'); + console.warn('diagnosticMode property is deprecated. It will be removed in a future version'); + return { + // diagnosticMode will be removed in a future version + diagnosticMode, + diagnosticsMode: diagnosticMode, + isRunning + }; + } + /** + * Start the crash reporter if not already running. + * @param options - configure crash reporter + * + * @remarks You can optionally specify `diagnosticsMode` to have the logs sent to + * OpenFin on runtime close. (NOTE: `diagnosticsMode` will turn on verbose logging and disable the sandbox + * for newly launched renderer processes. See https://developers.openfin.co/of-docs/docs/debugging#diagnostics-mode for + * more details.) + * + * @example + * ```js + * fin.System.startCrashReporter({diagnosticsMode: true}).then(reporter => console.log(reporter)).catch(err => console.log(err)); + * ``` + */ + async startCrashReporter(options) { + const opts = options; + const newOpts = { ...opts, diagnosticMode: opts.diagnosticsMode || opts.diagnosticMode }; + const { payload: { data: { diagnosticMode, isRunning } } } = await this.wire.sendAction('start-crash-reporter', newOpts); + return { + // diagnosticMode will be removed in a future version + diagnosticMode, + diagnosticsMode: diagnosticMode, + isRunning + }; + } + /** + * Returns a hex encoded hash of the machine id and the currently logged in user name. + * This is the recommended way to uniquely identify a user / machine combination. + * + * @remarks For Windows systems this is a sha256 hash of the machine ID set in the registry key: + * `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid` and `USERNAME`. + * + * For OSX systems, a native-level call is used to get the machine ID. + * + * @example + * ```js + * fin.System.getUniqueUserId().then(id => console.log(id)).catch(err => console.log(err)); + * ``` + */ + getUniqueUserId() { + return this.wire.sendAction('get-unique-user-id').then(({ payload }) => payload.data); + } + /** + * Retrieves a frame info object for the uuid and name passed in + * @param uuid - The UUID of the target. + * @param name - The name of the target. + * + * @remarks The possible types are 'window', 'iframe', 'external connection' or 'unknown'. + * @example + * ```js + * const entityUuid = 'OpenfinPOC'; + * const entityName = '40c74b5d-ed98-40f7-853f-e3d3c2699175'; + * fin.System.getEntityInfo(entityUuid, entityName).then(info => console.log(info)).catch(err => console.log(err)); + * + * // example info shape + * { + * "uuid": "OpenfinPOC", + * "name": "40c74b5d-ed98-40f7-853f-e3d3c2699175", + * "parent": { + * "uuid": "OpenfinPOC", + * "name": "OpenfinPOC" + * }, + * "entityType": "iframe" + * } + * ``` + */ + getEntityInfo(uuid, name) { + return this.wire.sendAction('get-entity-info', { uuid, name }).then(({ payload }) => payload.data); + } + /** + * Gets the value of a given environment variable on the computer on which the runtime is installed + * + * @example + * ```js + * fin.System.getEnvironmentVariable('HOME').then(env => console.log(env)).catch(err => console.log(err)); + * ``` + */ + getEnvironmentVariable(envName) { + return this.wire + .sendAction('get-environment-variable', { + environmentVariables: envName + }) + .then(({ payload }) => payload.data); + } + /** + * Get currently focused Window. + * If a View currently has focus, returns the identity of View's parent Window. + * Use {@link Window._Window#getFocusedContent Window.getFocusedContent} to directly access currently focused Window or View. + * + * @example + * ```js + * fin.System.getFocusedWindow().then(winInfo => console.log(winInfo)).catch(err => console.log(err)); + * ``` + */ + getFocusedWindow() { + return this.wire.sendAction('get-focused-window').then(({ payload }) => payload.data); + } + /** + * Get currently focused content. Returns identity of entity with `entityType`. + * + * @example + * ```js + * fin.System.getFocusedContent().then(contentIdentity => console.log(contentIdentity)).catch(err => console.log(err)); + * ``` + */ + getFocusedContent() { + return this.wire.sendAction('get-focused-content').then(({ payload }) => payload.data); + } + /** + * Returns information about the given app's certification status + * + * @example + * ```js + * const manifestUrl = "http://localhost:1234/app.json" + * try { + * const certificationInfo = await fin.System.isAppCertified(manifestUrl); + * } catch(err) { + * console.error(err) + * } + * ``` + */ + async isAppCertified(manifestUrl) { + const { payload: { data: { certifiedInfo } } } = await this.wire.sendAction('is-app-certified', { manifestUrl }); + return certifiedInfo; + } + /** + * Returns an array of all the installed runtime versions in an object. + * + * @example + * ```js + * fin.System.getInstalledRuntimes().then(runtimes => console.log(runtimes)).catch(err => console.log(err)); + * ``` + */ + // incompatible with standalone node process. + getInstalledRuntimes() { + return this.wire.sendAction('get-installed-runtimes').then(({ payload }) => payload.data.runtimes); + } + // incompatible with standalone node process. + async getInstalledApps() { + const { payload: { data: { installedApps } } } = await this.wire.sendAction('get-installed-apps'); + return installedApps; + } + /** + * Retrieves the contents of the log with the specified filename. + * @param options A object that id defined by the GetLogRequestType interface + * + * @example + * ```js + * async function getLog() { + * const logs = await fin.System.getLogList(); + * return await fin.System.getLog(logs[0]); + * } + * + * getLog().then(log => console.log(log)).catch(err => console.log(err)); + * ``` + */ + getLog(options) { + return this.wire.sendAction('view-log', options).then(({ payload }) => payload.data); + } + /** + * Returns a unique identifier (UUID) provided by the machine. + * + * @example + * ```js + * fin.System.getMachineId().then(id => console.log(id)).catch(err => console.log(err)); + * ``` + */ + getMachineId() { + return this.wire.sendAction('get-machine-id').then(({ payload }) => payload.data); + } + /** + * Returns the minimum (inclusive) logging level that is currently being written to the log. + * + * @example + * ```js + * fin.System.getMinLogLevel().then(level => console.log(level)).catch(err => console.log(err)); + * ``` + */ + getMinLogLevel() { + return this.wire.sendAction('get-min-log-level').then(({ payload }) => payload.data); + } + /** + * Retrieves an array containing information for each log file. + * + * @example + * ```js + * fin.System.getLogList().then(logList => console.log(logList)).catch(err => console.log(err)); + * ``` + */ + getLogList() { + return this.wire.sendAction('list-logs').then(({ payload }) => payload.data); + } + /** + * Retrieves an object that contains data about the monitor setup of the + * computer that the runtime is running on. + * + * @example + * ```js + * fin.System.getMonitorInfo().then(monitorInfo => console.log(monitorInfo)).catch(err => console.log(err)); + * ``` + */ + getMonitorInfo() { + return this.wire.sendAction('get-monitor-info').then(({ payload }) => payload.data); + } + /** + * Returns the mouse in virtual screen coordinates (left, top). + * + * @example + * ```js + * fin.System.getMousePosition().then(mousePosition => console.log(mousePosition)).catch(err => console.log(err)); + * ``` + */ + getMousePosition() { + return this.wire.sendAction('get-mouse-position').then(({ payload }) => payload.data); + } + /** + * Retrieves an array of all of the runtime processes that are currently + * running. Each element in the array is an object containing the uuid + * and the name of the application to which the process belongs. + * @deprecated Please use our new set of process APIs: + * {@link Window._Window#getProcessInfo Window.getProcessInfo} + * {@link View.View#getProcessInfo View.getProcessInfo} + * {@link Application.Application#getProcessInfo Application.getProcessInfo} + * {@link System#getAllProcessInfo System.getAllProcessInfo} + * + * @example + * ```js + * fin.System.getProcessList().then(ProcessList => console.log(ProcessList)).catch(err => console.log(err)); + * ``` + */ + getProcessList() { + // eslint-disable-next-line no-console + console.warn('System.getProcessList has been deprecated. Please consider using our new process APIs: Window.getProcessInfo, View.getProcessInfo, Application.getProcessInfo, System.getAllProcessInfo'); + return this.wire.sendAction('process-snapshot').then(({ payload }) => payload.data); + } + /** + * Retrieves all process information. + * + * @remarks This includes the browser process and every process associated to all entities (windows and views). + * + * @example + * ```js + * const allProcessInfo = await fin.System.getAllProcessInfo(); + * ``` + * @experimental + */ + async getAllProcessInfo() { + const { payload: { data } } = await this.wire.sendAction('get-all-process-info', this.identity); + return data; + } + /** + * Retrieves the Proxy settings. + * + * @example + * ```js + * fin.System.getProxySettings().then(ProxySetting => console.log(ProxySetting)).catch(err => console.log(err)); + * + * //This response has the following shape: + * { + * config: { + * proxyAddress: "proxyAddress", //the configured Proxy Address + * proxyPort: 0, //the configured Proxy port + * type: "system" //Proxy Type + * }, + * system: { + * autoConfigUrl: "", + * bypass: "", + * enabled: false, + * proxy: "" + * } + * } + * ``` + */ + getProxySettings() { + return this.wire.sendAction('get-proxy-settings').then(({ payload }) => payload.data); + } + /** + * Returns information about the running Runtime in an object. + * + * @example + * ```js + * fin.System.getRuntimeInfo().then(RuntimeInfo => console.log(RuntimeInfo)).catch(err => console.log(err)); + * ``` + */ + getRuntimeInfo() { + return this.wire.sendAction('get-runtime-info').then(({ payload }) => payload.data); + } + /** + * Returns information about the running RVM in an object. + * + * @example + * ```js + * fin.System.getRvmInfo().then(RvmInfo => console.log(RvmInfo)).catch(err => console.log(err)); + * ``` + */ + // incompatible with standalone node process. + getRvmInfo() { + return this.wire.sendAction('get-rvm-info').then(({ payload }) => payload.data); + } + /** + * Retrieves general system information. If you need more detailed information about the + * OS and the currently logged in user, use `fin.System.getOSInfo()` instead. + * + * @example + * ```js + * fin.System.getHostSpecs().then(specs => console.log(specs)).catch(err => console.log(err)); + * ``` + */ + getHostSpecs() { + return this.wire.sendAction('get-host-specs').then(({ payload }) => payload.data); + } + /** + * Retrieves information about the OS and the currently logged in user. + * + * @example + * ```js + * fin.System.getOSInfo().then(specs => console.log(specs)).catch(err => console.log(err)); + * ``` + */ + getOSInfo() { + return this.wire.sendAction('get-os-info').then(({ payload }) => payload.data); + } + /** + * Runs an executable or batch file. A path to the file must be included in options. + *
A uuid may be optionally provided. If not provided, OpenFin will create a uuid for the new process. + *
Note: This method is restricted by default and must be enabled via + * API security settings. Also, this api has an enhanced permission set to make it less dangerous. So application owners can only allow to launch the assets owned by the application, the enabled downloaded files or the restricted executables. + * @param options A object that is defined in the ExternalProcessRequestType interface + * + * @remarks If an unused UUID is provided in options, it will be used. If no UUID is provided, OpenFin will assign one. + * This api has an enhanced permission set to make it less dangerous. So application owners can only allow to launch the + * assets owned by the application, the enabled downloaded files or the restricted executables. + * + * **Note:** Since _appAssets_ relies on the RVM, which is missing on MAC_OS, 'alias' is not available. Instead provide + * the full path e.g. _/Applications/Calculator.app/Contents/MacOS/Calculator_. + * + * @example + * Basic Example: + * ```js + * fin.System.launchExternalProcess({ + * path: 'notepad', + * arguments: '', + * listener: function (result) { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * Promise resolution: + * + * ```js + * //This response has the following shape: + * { + * uuid: "FB3E6E36-0976-4C2B-9A09-FB2E54D2F1BB" // The mapped UUID which identifies the launched process + * } + * ``` + * + * Listener callback: + * ```js + * //This response has the following shape: + * { + * topic: "exited", // Or "released" on a call to releaseExternalProcess + * uuid: "FB3E6E36-0976-4C2B-9A09-FB2E54D2F1BB", // The mapped UUID which identifies the launched process + * exitCode: 0 // Process exit code + * } + * ``` + * + * By specifying a lifetime, an external process can live as long the window/application that launched it or + * persist after the application exits. The default value is null, which is equivalent to 'persist', meaning + * the process lives on after the application exits: + * + * ```js + * fin.System.launchExternalProcess({ + * path: 'notepad', + * arguments: '', + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * }, + * lifetime: 'window' + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * Note: A process that exits when the window/application exits cannot be released via fin.desktop.System.releaseExternalProcess. + * + * By specifying a cwd, it will set current working directory when launching an external process: + * + * ```js + * fin.System.launchExternalProcess({ + * path: 'cmd.exe', + * cwd: 'c:\\temp', + * arguments: '', + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * Example using an alias from app.json appAssets property: + * + * ```json + * "appAssets": [ + * { + * "src": "exe.zip", + * "alias": "myApp", + * "version": "4.12.8", + * "target": "myApp.exe", + * "args": "a b c d" + * }, + * ] + * ``` + * + * ```js + * // When called, if no arguments are passed then the arguments (if any) + * // are taken from the 'app.json' file, from the 'args' parameter + * // of the 'appAssets' Object with the relevant 'alias'. + * fin.System.launchExternalProcess({ + * //Additionally note that the executable found in the zip file specified in appAssets + * //will default to the one mentioned by appAssets.target + * //If the the path below refers to a specific path it will override this default + * alias: 'myApp', + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * Example using an alias but overriding the arguments: + * + * ```json + * "appAssets": [ + * { + * "src": "exe.zip", + * "alias": "myApp", + * "version": "4.12.8", + * "target": "myApp.exe", + * "args": "a b c d" + * }, + * ] + * ``` + * + * ```js + * // If 'arguments' is passed as a parameter it takes precedence + * // over any 'args' set in the 'app.json'. + * fin.System.launchExternalProcess({ + * alias: 'myApp', + * arguments: 'e f g', + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * It is now possible to optionally perform any combination of the following certificate checks + * against an absolute target via `fin.desktop.System.launchExternalProcess()`: + * + * ```js + * "certificate": { + * "serial": "3c a5 ...", // A hex string with or without spaces + * "subject": "O=OpenFin INC., L=New York, ...", // An internally tokenized and comma delimited string allowing partial or full checks of the subject fields + * "publickey": "3c a5 ...", // A hex string with or without spaces + * "thumbprint": "3c a5 ...", // A hex string with or without spaces + * "trusted": true // A boolean indicating that the certificate is trusted and not revoked + * } + * ``` + * + * Providing this information as part of the default configurations for assets in an application's manifest + * will be added in a future RVM update: + * + * ```js + * fin.System.launchExternalProcess({ + * path: 'C:\\Users\\ExampleUser\\AppData\\Local\\OpenFin\\OpenFinRVM.exe', + * arguments: '--version', + * certificate: { + * trusted: true, + * subject: 'O=OpenFin INC., L=New York, S=NY, C=US', + * thumbprint: '‎3c a5 28 19 83 05 fe 69 88 e6 8f 4b 3a af c5 c5 1b 07 80 5b' + * }, + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * It is possible to launch files that have been downloaded by the user by listening to the window + * `file-download-completed` event and using the `fileUuid` provided by the event: + * + * ```js + * const win = fin.Window.getCurrentSync(); + * win.addListener('file-download-completed', (evt) => { + * if (evt.state === 'completed') { + * fin.System.launchExternalProcess({ + * fileUuid: evt.fileUuid, + * arguments: '', + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * } + * }); + * ``` + * + * Launching assets specified in the app manifest: + * + * Sample appAssets section in app.json + * ```js + * "appAssets": [ + * { + * "src": "http://filesamples.com/exe.zip", + * "alias": "myApp", + * "version": "4.12.8", + * "target": "myApp.exe", + * "args": "a b c d" + * }, + * { + * "src": "http://examples.com/exe.zip", + * "alias": "myApp2", + * "version": "5.12.8", + * "target": "myApp2.exe", + * "args": "a b c" + * } + * ] + * ``` + * + * This permission allows for launching of all assets specified in the above appAssets section. ("myApp" and "myApp2"): + * + * ```js + * "permissions": { + * "System": { + * "launchExternalProcess": { + * "enabled": true, + * "assets": { + * "enabled": true + * } + * } + * } + * } + * ``` + * + * This permission allows for launching of _only_ the "myApp" asset in the above appAssets section, as defined in `srcRules`: + * ```js + * "permissions": { + * "System": { + * "launchExternalProcess": { + * "enabled": true, + * "assets": { + * "enabled": true + * "srcRules": [ + * { + * "match": [ + * "*://filesamples.com/*" + * ], + * "behavior": "allow" + * }, + * { + * "match": [ + * "" + * ], + * "behavior": "block" + * } + * ] + * } + * } + * } + * } + * ``` + * + * Launching downloaded files: + * ```js + * "permissions": { + * "System": { + * "launchExternalProcess": { + * "enabled": true, + * "downloads": { + * "enabled": true + * } + * } + * } + * } + * ``` + * + * This permission allows to launch all the executables: + * ```js + * "permissions": { + * "System": { + * "launchExternalProcess": { + * "enabled": true, + * "executables": { + * "enabled": true + * } + * } + * } + * } + * ``` + * + * + * This permission only allows launching of executables whose file paths match the corresponding `pathRules`: + * ```js + * "permissions": { + * "System": { + * "launchExternalProcess": { + * "enabled": true, + * "executables": { + * "enabled": true + * "pathRules": [ + * { + * "match": [ + * "/Windows/System32/*.exe" + * ], + * "behavior": "allow" + * }, + * { + * "match": [ + * "*.exe" + * ], + * "behavior": "block" + * } + * ] + * } + * } + * } + * } + * ``` + */ + launchExternalProcess(options) { + return this.sendExternalProcessRequest('launch-external-process', options); + } + /** + * Monitors a running process. A pid for the process must be included in options. + *
A uuid may be optionally provided. If not provided, OpenFin will create a uuid for the new process. + * + * @remarks If an unused uuid is provided in options, it will be used. If no uuid is provided, OpefinFin will assign a uuid. + * @example + * ```js + * fin.System.monitorExternalProcess({ + * pid: 10208, + * uuid: 'my-external-process', // optional + * listener: function (result) { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => console.log(processIdentity)).catch(err => console.log(err)); + * ``` + */ + monitorExternalProcess(options) { + return this.sendExternalProcessRequest('monitor-external-process', options); + } + /** + * Writes the passed message into both the log file and the console. + * @param level The log level for the entry. Can be either "info", "warning" or "error" + * @param message The log message text + * + * @example + * ```js + * fin.System.log("info", "An example log message").then(() => console.log('Log info message')).catch(err => console.log(err)); + * ``` + */ + log(level, message) { + return this.wire.sendAction('write-to-log', { level, message }).then(() => undefined); + } + /** + * Opens the passed URL in the default web browser. + * + * @remarks It only supports http(s) and fin(s) protocols by default. + * In order to use other custom protocols, they have to be enabled via + * [API security settings](https://developers.openfin.co/docs/api-security). + * File protocol and file path are not supported. + * @param url The URL to open + * + * @example + * ```js + * fin.System.openUrlWithBrowser('https://cdn.openfin.co/docs/javascript/stable/tutorial-System.openUrlWithBrowser.html') + * .then(() => console.log('Opened URL')) + * .catch(err => console.log(err)); + * ``` + * + * Example of permission definition to enable non-default protocols: + * + * Note: permission definition should be specified in an app manifest file if there is no DOS settings. + * Otherwise it has to be specified in both DOS and app manifest files. + * + * ```js + * "permissions": { + * "System": { + * "openUrlWithBrowser": { + * "enabled": true, + * "protocols": [ "msteams", "slack"] + * } + * } + * } + * ``` + */ + openUrlWithBrowser(url) { + return this.wire.sendAction('open-url-with-browser', { url }).then(() => undefined); + } + /** + * Creates a new registry entry under the HKCU root Windows registry key if the given custom protocol name doesn't exist or + * overwrites the existing registry entry if the given custom protocol name already exists. + * + * Note: This method is restricted by default and must be enabled via + * {@link https://developers.openfin.co/docs/api-security API security settings}. It requires RVM 12 or higher version. + * + * + * @remarks These protocols are reserved and cannot be registered: + * - fin + * - fins + * - openfin + * - URI Schemes registered with {@link https://en.wikipedia.org/wiki/List_of_URI_schemes#Official_IANA-registered_schemes IANA} + * + * @throws if a given custom protocol failed to be registered. + * @throws if a manifest URL contains the '%1' string. + * @throws if a manifest URL contains a query string parameter which name equals to the Protocol Launch Request Parameter Name. + * @throws if the full length of the command string that is to be written to the registry exceeds 2048 bytes. + * + * @example + * ```js + * fin.System.registerCustomProtocol({protocolName:'protocol1'}).then(console.log).catch(console.error); + * ``` + */ + async registerCustomProtocol(options) { + if (typeof options !== 'object') { + throw new Error('Must provide an object with a `protocolName` property having a string value.'); + } + await this.wire.sendAction('register-custom-protocol', options); + } + /** + * Removes the registry entry for a given custom protocol. + * + * Note: This method is restricted by default and must be enabled via + * {@link https://developers.openfin.co/docs/api-security API security settings}. It requires RVM 12 or higher version. + * + * + * @remarks These protocols are reserved and cannot be unregistered: + * - fin + * - fins + * - openfin + * - URI Schemes registered with {@link https://en.wikipedia.org/wiki/List_of_URI_schemes#Official_IANA-registered_schemes IANA} + * + * @throws if a protocol entry failed to be removed in registry. + * + * @example + * ```js + * await fin.System.unregisterCustomProtocol('protocol1'); + * ``` + */ + async unregisterCustomProtocol(protocolName) { + await this.wire.sendAction('unregister-custom-protocol', { protocolName }); + } + /** + * Retrieves the registration state for a given custom protocol. + * + * Note: This method is restricted by default and must be enabled via + * {@link https://developers.openfin.co/docs/api-security API security settings}. It requires RVM 12 or higher version. + * + * @remarks These protocols are reserved and cannot get states for them: + * - fin + * - fins + * - openfin + * - URI Schemes registered with {@link https://en.wikipedia.org/wiki/List_of_URI_schemes#Official_IANA-registered_schemes IANA} + * + * + * @example + * ```js + * const protocolState = await fin.System.getCustomProtocolState('protocol1'); + */ + async getCustomProtocolState(protocolName) { + return this.wire.sendAction('get-custom-protocol-state', { protocolName }).then(({ payload }) => payload.data); + } + /** + * Removes the process entry for the passed UUID obtained from a prior call + * of fin.System.launchExternalProcess(). + * @param uuid The UUID for a process obtained from a prior call to fin.desktop.System.launchExternalProcess() + * + * @example + * ```js + * fin.System.launchExternalProcess({ + * path: "notepad", + * listener: function (result) { + * console.log("The exit code", result.exitCode); + * } + * }) + * .then(identity => fin.System.releaseExternalProcess(identity.uuid)) + * .then(() => console.log('Process has been unmapped!')) + * .catch(err => console.log(err)); + * ``` + */ + releaseExternalProcess(uuid) { + return this.wire.sendAction('release-external-process', { uuid }).then(() => undefined); + } + /** + * Shows the Chromium Developer Tools for the specified window + * @param identity This is a object that is defined by the Identity interface + * + * @tutorial System.showDeveloperTools + */ + showDeveloperTools(identity) { + return this.wire.sendAction('show-developer-tools', identity).then(() => undefined); + } + /** + * Attempt to close an external process. The process will be terminated if it + * has not closed after the elapsed timeout in milliseconds. + * + * Note: This method is restricted by default and must be enabled via + * API security settings. + * @param options A object defined in the TerminateExternalRequestType interface + * + * @example + * ```js + * fin.System.launchExternalProcess({ + * path: "notepad", + * listener: function (result) { + * console.log("The exit code", result.exitCode); + * } + * }) + * .then(identity => fin.System.terminateExternalProcess({uuid: identity.uuid, timeout:2000, killTree: false})) + * .then(() => console.log('Terminate the process')) + * .catch(err => console.log(err)); + * ``` + */ + terminateExternalProcess(options) { + return this.wire.sendAction('terminate-external-process', options).then(() => undefined); + } + /** + * Update the OpenFin Runtime Proxy settings. + * @param options A config object defined in the ProxyConfig interface + * + * @example + * ```js + * fin.System.updateProxySettings({proxyAddress:'127.0.0.1', proxyPort:8080, type:'http'}) + * .then(() => console.log('Update proxy successfully')) + * .catch(err => console.error(err)); + * ``` + */ + updateProxySettings(options) { + return this.wire.sendAction('update-proxy', options).then(() => undefined); + } + /** + * Downloads the given application asset. + * + * Note: This method is restricted by default and must be enabled via + * API security settings. + * @param appAsset App asset object + * + * @example + * ```js + * async function downloadAsset() { + * const appAsset = { + * src: `${ location.origin }/assets.zip`, + * alias: 'dirApp', + * version: '1.23.24', + * target: 'assets/run.bat' + * }; + * + * return fin.System.downloadAsset(appAsset, (progress => { + * //Print progress as we download the asset. + * const downloadedPercent = Math.floor((progress.downloadedBytes / progress.totalBytes) * 100); + * console.log(`Downloaded ${downloadedPercent}%`); + * })); + * } + * + * downloadAsset() + * .then(() => console.log('Success')) + * .catch(err => console.error(err)); + * + * ``` + */ + // incompatible with standalone node process. + async downloadAsset(appAsset, progressListener) { + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-empty-function + const noop = () => { }; + let resolve = noop; + let reject = noop; + const downloadCompletePromise = new Promise((y, n) => { + resolve = y; + reject = n; + }); + // node.js environment not supported + if (this.wire.environment.type !== 'openfin') { + throw new transport_errors_1$1.NotSupportedError('downloadAsset only supported in an OpenFin Render process'); + } + const callSite = transport_errors_1$1.RuntimeError.getCallSite(); + const downloadId = this.wire.environment.getNextMessageId().toString(); + const dlProgressKey = `asset-download-progress-${downloadId}`; + const dlErrorKey = `asset-download-error-${downloadId}`; + const dlCompleteKey = `asset-download-complete-${downloadId}`; + const dlProgress = (progress) => { + const p = { + downloadedBytes: progress.downloadedBytes, + totalBytes: progress.totalBytes + }; + progressListener(p); + }; + const cleanListeners = () => { + // TODO: fix internal types + // @ts-expect-error + this.removeListener(dlProgressKey, dlProgress); + }; + const dlError = (payload) => { + cleanListeners(); + const { reason, err: error } = payload; + reject(new transport_errors_1$1.RuntimeError({ reason, error }, callSite)); + }; + const dlComplete = () => { + cleanListeners(); + resolve(); + }; + await Promise.all([ + // TODO: fix internal types + // @ts-expect-error + this.on(dlProgressKey, dlProgress), + // TODO: fix internal types + // @ts-expect-error + this.once(dlErrorKey, dlError), + // TODO: fix internal types + // @ts-expect-error + this.once(dlCompleteKey, dlComplete) + ]); + const downloadOptions = Object.assign(appAsset, { downloadId }); + await this.wire.sendAction('download-asset', downloadOptions).catch((err) => { + cleanListeners(); + throw err; + }); + return downloadCompletePromise; + } + /** + * Downloads a version of the runtime. + * @param options - Download options. + * @param progressListener - called as the runtime is downloaded with progress information. + * + * @remarks Only supported in an OpenFin Render process. + * + * @example + * ```js + * var downloadOptions = { + * //Specific version number required, if given a release channel the call will produce an error. + * version: '9.61.30.1' + * }; + * + * function onProgress(progress) { + * console.log(`${Math.floor((progress.downloadedBytes / progress.totalBytes) * 100)}%`); + * } + * + * fin.System.downloadRuntime(downloadOptions, onProgress).then(() => { + * console.log('Download complete'); + * }).catch(err => { + * console.log(`Download Failed, we could retry: ${err.message}`); + * console.log(err); + * }); + * ``` + */ + downloadRuntime(options, progressListener) { + const callsites = transport_errors_1$1.RuntimeError.getCallSite(); + return new Promise((resolve, reject) => { + // node.js environment not supported + if (this.wire.environment.type !== 'openfin') { + reject(new transport_errors_1$1.NotSupportedError('downloadRuntime only supported in an OpenFin Render process')); + return; + } + const downloadId = this.wire.environment.getNextMessageId().toString(); + const dlProgressKey = `runtime-download-progress-${downloadId}`; + const dlErrorKey = `runtime-download-error-${downloadId}`; + const dlCompleteKey = `runtime-download-complete-${downloadId}`; + const dlProgress = (progress) => { + const p = { + downloadedBytes: progress.downloadedBytes, + totalBytes: progress.totalBytes + }; + progressListener(p); + }; + const cleanListeners = () => { + // TODO: fix internal types + // @ts-expect-error + this.removeListener(dlProgressKey, dlProgress); + }; + const dlError = (payload) => { + cleanListeners(); + const { reason, err: error } = payload; + reject(new transport_errors_1$1.RuntimeError({ reason, error }, callsites)); + }; + const dlComplete = () => { + cleanListeners(); + resolve(); + }; + // TODO: fix internal types + // @ts-expect-error + this.on(dlProgressKey, dlProgress); + // TODO: fix internal types + // @ts-expect-error + this.once(dlErrorKey, dlError); + // TODO: fix internal types + // @ts-expect-error + this.once(dlCompleteKey, dlComplete); + const downloadOptions = Object.assign(options, { downloadId }); + this.wire.sendAction('download-runtime', downloadOptions).catch((err) => { + cleanListeners(); + reject(err); + }); + }); + } + /** + * Download preload scripts from given URLs + * @param scripts - URLs of preload scripts. + * + * @example + * ```js + * const scripts = [ + * { url: 'http://.../preload.js' }, + * { url: 'http://.../preload2.js' } + * ]; + * + * fin.System.downloadPreloadScripts(scripts).then(results => { + * results.forEach(({url, success, error}) => { + * console.log(`URL: ${url}`); + * console.log(`Success: ${success}`); + * if (error) { + * console.log(`Error: ${error}`); + * } + * }); + * }); + * ``` + */ + downloadPreloadScripts(scripts) { + return this.wire.sendAction('download-preload-scripts', { scripts }).then(({ payload }) => payload.data); + } + /** + * Retrieves an array of data (name, ids, bounds) for all application windows. + * + * @example + * ```js + * fin.System.getAllExternalApplications() + * .then(externalApps => console.log('Total external apps: ' + externalApps.length)) + * .catch(err => console.log(err)); + * ``` + */ + getAllExternalApplications() { + return this.wire.sendAction('get-all-external-applications').then(({ payload }) => payload.data); + } + /** + * Retrieves app asset information. + * @param options + * + * @example + * ```js + * fin.System.getAppAssetInfo({alias:'procexp'}).then(assetInfo => console.log(assetInfo)).catch(err => console.log(err)); + * ``` + */ + getAppAssetInfo(options) { + return this.wire.sendAction('get-app-asset-info', options).then(({ payload }) => payload.data); + } + /** + * Get additional info of cookies. + * + * @example + * ```js + * fin.System.getCookies({name: 'myCookie'}).then(cookies => console.log(cookies)).catch(err => console.log(err)); + * ``` + */ + getCookies(options) { + const url = this.wire.environment.getUrl(); + const newOptions = Object.assign(options, { url }); + return this.wire.sendAction('get-cookies', newOptions).then(({ payload }) => payload.data); + } + /** + * Set the minimum log level above which logs will be written to the OpenFin log + * @param The minimum level (inclusive) above which all calls to log will be written + * + * @example + * ```js + * fin.System.setMinLogLevel("verbose").then(() => console.log("log level is set to verbose")).catch(err => console.log(err)); + * ``` + */ + setMinLogLevel(level) { + return this.wire.sendAction('set-min-log-level', { level }).then(() => undefined); + } + /** + * Retrieves the UUID of the computer on which the runtime is installed + * @param uuid The uuid of the running application + * + * @example + * ```js + * fin.System.resolveUuid('OpenfinPOC').then(entity => console.log(entity)).catch(err => console.log(err)); + * ``` + */ + resolveUuid(uuid) { + return this.wire + .sendAction('resolve-uuid', { + entityKey: uuid + }) + .then(({ payload }) => payload.data); + } + /** + * Retrieves an array of data for all external applications + * @param requestingIdentity This object is described in the Identity typedef + * @param data Any data type to pass to the method + * + * @ignore + */ + executeOnRemote(requestingIdentity, data) { + data.requestingIdentity = requestingIdentity; + return this.wire.ferryAction(data); + } + /** + * Reads the specifed value from the registry. + * @remarks This method is restricted by default and must be enabled via + * [API security settings](https://developers.openfin.co/docs/api-security). + * @param rootKey - The registry root key. + * @param subkey - The registry key. + * @param value - The registry value name. + * + * @example + * ```js + * fin.System.readRegistryValue("HKEY_LOCAL_MACHINE", "HARDWARE\\DESCRIPTION\\System", "BootArchitecture").then(val => console.log(val)).catch(err => console.log(err)); + * ``` + * + * See {@link https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx here} for Window's error code definitions. + * + * Example payloads of different registry types: + * + * See list of types {@link https://msdn.microsoft.com/en-us/library/windows/desktop/ms724884(v=vs.85).aspx here}. + * + * ```js + * // REG_DWORD + * { + * data: 1, + * rootKey: "HKEY_LOCAL_MACHINE", + * subkey: "Foo\Bar", + * type: "REG_DWORD", + * value: "Baz" + * } + * + * // REG_QWORD + * { + * data: 13108146671334112, + * rootKey: "HKEY_LOCAL_MACHINE", + * subkey: "Foo\Bar", + * type: "REG_QWORD", + * value: "Baz" + * } + * + * // REG_SZ + * { + * data: "FooBarBaz", + * rootKey: "HKEY_LOCAL_MACHINE", + * subkey: "Foo\Bar", + * type: "REG_SZ", + * value: "Baz" + * } + * + * // REG_EXPAND_SZ + * { + * data: "C:\User\JohnDoe\AppData\Local", + * rootKey: "HKEY_CURRENT_USER", + * subkey: "Foo\Bar", + * type: "REG_EXPAND_SZ", + * value: "Baz" + * } + * + * // REG_MULTI_SZ + * { + * data: [ + * "Foo", + * "Bar", + * "Baz" + * ], + * rootKey: "HKEY_CURRENT_USER", + * subkey: "Foo\Bar", + * type: "REG_MULTI_SZ", + * value: "Baz" + * } + * + * // REG_BINARY + * { + * data: { + * data: [ + * 255, + * 255, + * 0, + * 43, + * 55, + * 0, + * 0, + * 255, + * 255 + * ], + * type: "Buffer" + * }, + * rootKey: "HKEY_CURRENT_USER", + * subkey: "Foo\Bar", + * type: "REG_BINARY", + * value: "Baz" + * } + * ``` + */ + readRegistryValue(rootKey, subkey, value) { + return this.wire + .sendAction('read-registry-value', { + rootKey, + subkey, + value + }) + .then(({ payload }) => payload.data); + } + /** + * This function call will register a unique id and produce a token. + * The token can be used to broker an external connection. + * @param uuid - A UUID for the remote connection. + * + * @example + * ```js + * fin.System.registerExternalConnection("remote-connection-uuid").then(conn => console.log(conn)).catch(err => console.log(err)); + * + * + * // object comes back with + * // token: "0489EAC5-6404-4F0D-993B-92BB8EAB445D", // this will be unique each time + * // uuid: "remote-connection-uuid" + * + * ``` + */ + registerExternalConnection(uuid) { + return this.wire.sendAction('register-external-connection', { uuid }).then(({ payload }) => payload.data); + } + /** + * Returns the json blob found in the [desktop owner settings](https://openfin.co/documentation/desktop-owner-settings/) + * for the specified service. + * @param serviceIdentifier An object containing a name key that identifies the service. + * + * @remarks More information about desktop services can be found [here](https://developers.openfin.co/docs/desktop-services). + * This call will reject if the desktop owner settings file is not present, not correctly formatted, or if the service requested is not configured or configured incorrectly. + * + * @example + * ```js + * // Here we are using the [layouts](https://github.com/HadoukenIO/layouts-service) service. + * fin.System.getServiceConfiguration({name:'layouts'}).then(console.log).catch(console.error); + * ``` + */ + async getServiceConfiguration(serviceIdentifier) { + if (typeof serviceIdentifier.name !== 'string') { + throw new Error('Must provide an object with a `name` property having a string value'); + } + const { name } = serviceIdentifier; + return this.wire.sendAction('get-service-configuration', { name }).then(({ payload }) => payload.data); + } + async getSystemAppConfig(name) { + if (typeof name !== 'string') { + throw new Error('Must provide a string value for name of system app'); + } + return this.wire.sendAction('get-system-app-configuration', { name }).then(({ payload }) => payload.data); + } + /** + * Registers a system shutdown handler so user can do some cleanup before system is shutting down. + * @remarks Once system shutdown starts, you are unable to cancel it. + * @param handler system shutdown handler + * + * @example + * ```js + * fin.System.registerShutdownHandler((shutdownEvent) => { + * // save state or cleanup + * console.log('do some cleanup before shutdown'); + * // Notify app is ready for termination. + * shutdownEvent.proceed(); + * }) + * .then(() => console.log('Shutdown handler registered!')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + async registerShutdownHandler(handler) { + this.wire.sendAction('system-register-shutdown-handler').catch((e) => { + // don't expose, analytics-only call + }); + const SystemShutdownEventName = 'system-shutdown'; + const SystemShutdownHandledEventName = 'system-shutdown-handled'; + const { uuid, name } = this.wire.me; + const shutdownHandler = (payload) => { + const proceed = () => { + // notify core that the app is ready for shutdown + this.wire.environment.raiseEvent(`application/${SystemShutdownHandledEventName}`, { + uuid, + name, + topic: 'application' + }); + }; + handler({ proceed }); + }; + this.on(SystemShutdownEventName, shutdownHandler); + } + /** + * Signals the RVM to perform a health check and returns the results as json. + * + * @remarks Requires RVM 5.5+ + * + * @example + * ```js + * try { + * const results = await fin.System.runRvmHealthCheck(); + * console.log(results); + * } catch(e) { + * console.error(e); + * } + * ``` + */ + runRvmHealthCheck() { + return this.wire.sendAction('run-rvm-health-check').then(({ payload }) => payload.data); + } + /** + * Launch application using a manifest URL/path. It differs from Application.startFromManifest in that this API can accept a manifest using the fin protocol. + * @param manifestUrl - The manifest's URL or path. + * @param opts - Parameters that the RVM will use. + * + * @experimental + * @remarks Supports protocols http/s and fin/s, and also a local path. + * + * Note: This API is Windows only. + * + * @example + * + * This API can handle most manifest types. Some examples below. + * + * Traditional: + * ```js + * const manifest = await fin.System.launchManifest( + * 'https://demoappdirectory.openf.in/desktop/config/apps/OpenFin/HelloOpenFin/app.json'); + * console.log(manifest); + * ``` + * + * Platform: + * ```js + * const manifest = await fin.System.launchManifest('https://openfin.github.io/platform-api-project-seed/public.json'); + * console.log(manifest); + * ``` + * + * Launching traditional manifest into a platform: + * ```js + * const manifest = await fin.System.launchManifest( + * 'https://openfin.github.io/platform-api-project-seed/public.json?\ + * $$appManifestUrl=https://demoappdirectory.openf.in/desktop/config/\ + * apps/OpenFin/HelloOpenFin/app.json'); + * console.log(manifest); + * ``` + * + * Launching with RVM options: + * ```js + * const manifest = await fin.System.launchManifest('https://openfin.github.io/platform-api-project-seed/public.json', + * { noUi: true, userAppConfigArgs: { abc: '123', xyz: '789' } }); + * console.log(manifest); + * ``` + * + * Local Path: + * ```js + * const manifest = await fin.System.launchManifest('file://c:\\path\\to\\manifest\\file.json'); + * console.log(manifest); + * ``` + * + * Launching with RVM 'subscribe' option: + * + * This option allows users to subscribe to app version resolver events when + * calling launchManifest with fallbackManifests specified. + * + * ```js + * fin.System.launchManifest('fins://system-apps/notifications/app.json', { subscribe: (launch) => { + * launch.on('app-version-progress', (progress) => { + * console.log("Trying manifest " + progress.manifest) + * }); + * + * launch.on('runtime-status', (status) => { + * console.log("Runtime status: " + JSON.stringify(status)); + * }); + * + * // RVM has successfully found the target runtime version + * launch.on('app-version-complete', (complete) => { + * console.log("Parent app " + complete.srcManifest + " resolved to " + complete.manifest); + * launch.removeAllListeners(); + * }); + * + * // RVM failed to find an available runtime version + * launch.on('app-version-error', (error) => { + * console.log("Failed to resolve " + error.srcManifest + " from the fallbackManifests"); + * launch.removeAllListeners(); + * }); + * } + * }); + * ``` + */ + async launchManifest(manifestUrl, opts = {}) { + const { subscribe, ..._sendOpts } = opts; + const sendOpts = _sendOpts; + if (subscribe) { + const launchEmitter = new events_1$6.EventEmitter(); + subscribe(launchEmitter); + const AppVersionProgressEventName = 'app-version-progress'; + const RuntimeStatusEventName = 'runtime-status'; + const AppVersionCompleteEventName = 'app-version-complete'; + const AppVersionErrorEventName = 'app-version-error'; + // add id to avoid multiple api calls getting duplicated events + const id = this.wire.environment.getNextMessageId().toString(); + sendOpts.appVersionId = id; + const supportedEvents = [ + AppVersionCompleteEventName, + AppVersionProgressEventName, + RuntimeStatusEventName, + AppVersionErrorEventName + ]; + const cleanEventPayload = (payload) => { + // We need to do type castings below to make sure the return type is correct. + const { appVersionId, topic, type: typeWithId, ...rest } = payload; + const type = supportedEvents.find((x) => typeWithId.includes(x)); + return { + ...rest, + type + }; + }; + const appVersionListener = (payload) => { + const cleanPayload = cleanEventPayload(payload); + launchEmitter.emit(cleanPayload.type, cleanPayload); + }; + const removeAllListeners = () => { + this.removeListener(`${AppVersionProgressEventName}.${id}`, appVersionListener); + this.removeListener(`${RuntimeStatusEventName}.${id}`, appVersionListener); + this.removeListener(`${AppVersionCompleteEventName}.${id}`, appVersionListener); + this.removeListener(`${AppVersionErrorEventName}.${id}`, appVersionListener); + this.removeListener(`${AppVersionCompleteEventName}.${id}`, removeAllListeners); + this.removeListener(`${AppVersionErrorEventName}.${id}`, removeAllListeners); + }; + await Promise.all([ + this.on(`${AppVersionProgressEventName}.${id}`, appVersionListener), + this.on(`${RuntimeStatusEventName}.${id}`, appVersionListener), + this.once(`${AppVersionCompleteEventName}.${id}`, appVersionListener), + this.once(`${AppVersionErrorEventName}.${id}`, appVersionListener), + this.once(`${AppVersionCompleteEventName}.${id}`, removeAllListeners), + this.once(`${AppVersionErrorEventName}.${id}`, removeAllListeners) + ]); + } + const response = await this.wire.sendAction('launch-manifest', { + manifestUrl, + opts: sendOpts + }); + return response.payload.data.manifest; + } + /** + * Query permission of a secured api in current context. + * + * @param apiName - The full name of a secured API. + * + * @remarks If a function has a structured permission value, the value of `granted` will reflect the `enabled` key + * of the call's permissions literal. In this case, *permission may still be denied to a call* pending arguments or other + * runtime state. This is indicated with `state: unavailable`. + * + * @example + * ```js + * fin.System.queryPermissionForCurrentContext('System.launchExternalProcess').then(result => console.log(result)).catch(err => console.log(err)); + * + * //This response has the following shape: + * { + * permission: 'System.launchExternalProcess', // api full name + * state: 'granted', // state of permission + * granted: true + * } + * ``` + */ + async queryPermissionForCurrentContext(apiName) { + const identity = { uuid: this.wire.me.uuid, name: this.wire.me.name }; + const response = await this.wire.sendAction('query-permission-for-current-context', { + apiName, + identity + }); + return response.payload.data; + } + // Not documenting, internal use only. + async enableNativeWindowIntegrationProvider(permissions) { + const { payload } = await this.wire.sendAction('enable-native-window-integration-provider', { permissions }); + return payload.data; + } + /** + * (Internal) Register the usage of a component with a platform + * @param options - Object with data and type + * + * @example + * ```js + * async function registerUsage() { + * const app = await fin.System.getCurrent(); + * return await fin.System.registerUsage({ + * type: 'workspace-licensing', + * // example values for the following data object + * data: { + * apiVersion: '1.0', + * componentName: 'home', + * componentVersion: '1.0', + * allowed: true, + * rejectionCode: '' + * } + * }); + * } + * + * registerUsage().then(() => console.log('Successfully registered component application')).catch(err => console.log(err)); + * ``` + */ + async registerUsage({ data, type }) { + await this.wire.sendAction('register-usage', { data, type }); + } + /** + * Returns an array with all printers of the caller and not all the printers on the desktop. + * + * @example + * ```js + * fin.System.getPrinters() + * .then((printers) => { + * printers.forEach((printer) => { + * if (printer.isDefault) { + * console.log(printer); + * } + * }); + * }) + * .catch((err) => { + * console.log(err); + * }); + * ``` + */ + async getPrinters() { + const { payload } = await this.wire.sendAction('system-get-printers'); + return payload.data; + } + /** + * Updates Process Logging values: periodic interval and outlier detection entries and interval. + * @param options Process Logging updatable options. + * + * @remarks When enabling verbose mode, additional process information is logged to the debug.log: + * + * 1. Periodically process usage (memory, cpu, etc) will be logged for each PID along with the windows, views and + * iframes that belong to them. The default is every 30 seconds. Updatable by passing the interval option. + * 2. When Windows and Views are created or navigated the PID they belong to and their options will be logged. + * 3. When Windows and Views are destroyed their last known process usage will be logged. + * 4. Whenever an outlier memory usage is detected it will be logged. By default, on an interval of 5 seconds we will + * collect process usage for all PIDs and when 144 such entries are collected, we will start analyzing the data for any + * possible outliers in the following entries. The interval and maximum number of entries stored in the running buffer + * can be updatable by passing the outlierDetection.interval and outlierDetection.entries options. + * + * @example + * + * ```js + * await fin.System.updateProcessLoggingOptions({ + * interval: 10, + * outlierDetection: { + * interval: 15, + * entries: 200 + * } + * }); + * ``` + */ + async updateProcessLoggingOptions(options) { + await this.wire.sendAction('system-update-process-logging-options', { options }); + } + /** + * Returns domain settings for the current application. + * Initial settings are configured with the defaultDomainSettings application option via manifest. + * Domain settings can be overwritten during runtime with System.setDomainSettings. + * @example + * ```js + * const domainSettings = await fin.System.getDomainSettings(); + * // { + * // "rules": [ + * // { + * // "match": [ + * // "https://openfin.co" + * // ], + * // "options": { + * // "downloadSettings": { + * // "rules": [ + * // { + * // "match": [ + * // "" + * // ], + * // "behavior": "prompt" + * // } + * // ] + * // } + * // } + * // } + * // ] + * // } + * ``` + */ + async getDomainSettings() { + const { payload: { data } } = await this.wire.sendAction('get-domain-settings', this.identity); + return data; + } + /** + * Sets the domain settings for the current application. + * @param domainSettings - domain settings object + * @example + * ```js + * const domainSettings = await fin.System.getDomainSettings(); + * // { + * // "rules": [ + * // { + * // "match": [ + * // "https://openfin.co" + * // ], + * // "options": { + * // "downloadSettings": { + * // "rules": [ + * // { + * // "match": [ + * // "" + * // ], + * // "behavior": "prompt" + * // } + * // ] + * // } + * // } + * // } + * // ] + * // } + * + * // Valid rule behaviors are 'prompt' and 'no-prompt' + * domainSettings.rules[0].options.downloadSettings.rules[0].behavior = 'no-prompt'; + * + * await fin.System.setDomainSettings(domainSettings); + * + * const newDomainSettings = await fin.System.getDomainSettings(); + * // { + * // "rules": [ + * // { + * // "match": [ + * // "https://openfin.co" + * // ], + * // "options": { + * // "downloadSettings": { + * // "rules": [ + * // { + * // "match": [ + * // "" + * // ], + * // "behavior": "no-prompt" + * // } + * // ] + * // } + * // } + * // } + * // ] + * // } + * ``` + */ + async setDomainSettings(domainSettings) { + await this.wire.sendAction('set-domain-settings', { domainSettings, ...this.identity }); + } + /** + * Attempts to install and enable extensions for the security realm. Users may want to call this function in response + * to an `extensions-install-failed` event. Only extensions allowed by every application on the current security realm + * will be installed/enabled. + */ + async refreshExtensions() { + const { payload } = await this.wire.sendAction('refresh-extensions'); + return payload.data; + } + /** + * Gets the currently-installed + */ + async getInstalledExtensions() { + const { payload } = await this.wire.sendAction('get-installed-extensions'); + return payload.data; + } +} +system.System = System; + +var interappbus = {}; + +var refCounter = {}; + +Object.defineProperty(refCounter, "__esModule", { value: true }); +refCounter.RefCounter = void 0; +class RefCounter { + constructor() { + this.topicRefMap = new Map(); + } + // returns the ref count after incrementing + incRefCount(key) { + const refCount = this.topicRefMap.get(key); + let returnCount; + if (!refCount) { + this.topicRefMap.set(key, 1); + returnCount = 1; + } + else { + const newRefCount = refCount + 1; + returnCount = newRefCount; + this.topicRefMap.set(key, newRefCount); + } + return returnCount; + } + // returns the ref count after decrementing, or -1 if the key already had no references + decRefCount(key) { + const refCount = this.topicRefMap.get(key); + let returnCount; + if (refCount) { + const newRefCount = refCount - 1; + this.topicRefMap.set(key, newRefCount); + returnCount = newRefCount; + } + else { + returnCount = -1; + } + return returnCount; + } + // Execute firstAction if it is the first such ref, else execute nonFirstAction. + // In either case the return value is that of the action executed + actOnFirst(key, firstAction, nonFirstAction) { + const numRefs = this.incRefCount(key); + const isFirstRef = numRefs === 1; + return isFirstRef ? firstAction() : nonFirstAction(); + } + // Execute lastAction if it is the first such ref, else execute nonLastAction. + // In either case the return value is that of the action executed + actOnLast(key, lastAction, nonLastAction) { + const numRefs = this.decRefCount(key); + const isLastRef = numRefs === 0; + return isLastRef ? lastAction() : nonLastAction(); + } +} +refCounter.RefCounter = RefCounter; + +var channel$1 = {}; + +var client = {}; + +var channel = {}; + +Object.defineProperty(channel, "__esModule", { value: true }); +channel.ChannelBase = channel.ProtectedItems = void 0; +const resultOrPayload = (func) => async (topic, payload, senderIdentity) => { + const res = await func(topic, payload, senderIdentity); + return res === undefined ? payload : res; +}; +class ProtectedItems { + /** + * @internal + */ + // eslint-disable-next-line no-useless-constructor + constructor(providerIdentity, close) { + this.providerIdentity = providerIdentity; + this.close = close; + } +} +channel.ProtectedItems = ProtectedItems; +class ChannelBase { + static defaultAction(topic) { + throw new Error(`No action registered at target for ${topic}`); + } + constructor() { + this.subscriptions = new Map(); + } + async processAction(topic, payload, senderIdentity) { + try { + const mainAction = this.subscriptions.has(topic) + ? this.subscriptions.get(topic) + : (currentPayload, id) => (this.defaultAction ?? ChannelBase.defaultAction)(topic, currentPayload, id); + const preActionProcessed = this.preAction ? await this.preAction(topic, payload, senderIdentity) : payload; + const actionProcessed = await mainAction(preActionProcessed, senderIdentity); + return this.postAction ? await this.postAction(topic, actionProcessed, senderIdentity) : actionProcessed; + } + catch (e) { + if (this.errorMiddleware) { + return this.errorMiddleware(topic, e, senderIdentity); + } + throw e; + } + } + /** + * Register middleware that fires before the action. + * + * @param func + * + * @example + * + * Channel Provider: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * provider.register('provider-action', (payload, identity) => { + * console.log(payload, identity); + * return { + * echo: payload + * }; + * }); + * + * provider.beforeAction((action, payload, identity) => { + * //The payload can be altered here before handling the action. + * payload.received = Date.now(); + * return payload; + * }); + * + * })(); + * ``` + * + * Channel Client: + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * client.register('client-action', (payload, identity) => { + * console.log(payload, identity); + * return { + * echo: payload + * }; + * }); + * + * client.beforeAction((action, payload, identity) => { + * //The payload can be altered here before handling the action. + * payload.received = Date.now(); + * return payload; + * }); + * + * const providerResponse = await client.dispatch('provider-action', { message: 'Hello From the client' }); + * console.log(providerResponse); + * })(); + * ``` + */ + beforeAction(func) { + if (this.preAction) { + throw new Error('Already registered beforeAction middleware'); + } + this.preAction = resultOrPayload(func); + } + /** + * Register an error handler. This is called before responding on any error. + * + * @param func + * + * Channel Provider: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * provider.register('provider-action', (payload, identity) => { + * console.log(payload); + * throw new Error('Action error'); + * return { + * echo: payload + * }; + * }); + * + * provider.onError((action, error, identity) => { + * console.log('uncaught Exception in action:', action); + * console.error(error); + * }); + * + * })(); + * ``` + * + * Channel Client: + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * client.register('client-action', (payload, identity) => { + * console.log(payload); + * throw new Error('Action error'); + * return { + * echo: payload + * }; + * }); + * + * client.onError((action, error, identity) => { + * console.log('uncaught Exception in action:', action); + * console.error(error); + * }); + * })(); + * ``` + */ + onError(func) { + if (this.errorMiddleware) { + throw new Error('Already registered error middleware'); + } + this.errorMiddleware = func; + } + /** + * Register middleware that fires after the action. + * + * @param func + * + * @remarks If the action does not return the payload, then the afterAction will not have access to the payload object. + * + * @example + * + * Channel Provider: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.register('provider-action', (payload, identity) => { + * return { + * echo: payload + * }; + * }); + * + * await provider.afterAction((action, payload, identity) => { + * //the payload can be altered here after handling the action but before sending an acknowledgement. + * payload.sent = date.now(); + * return payload; + * }); + * + * })(); + * ``` + * + * Channel Client: + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.register('client-action', (payload, identity) => { + * return { + * echo: payload + * }; + * }); + * + * await client.afterAction((action, payload, identity) => { + * //the payload can be altered here after handling the action but before sending an acknowledgement. + * payload.sent = date.now(); + * return payload; + * }); + * + * })(); + * ``` + */ + afterAction(func) { + if (this.postAction) { + throw new Error('Already registered afterAction middleware'); + } + this.postAction = resultOrPayload(func); + } + /** + * Remove an action by action name. + * + * @param action + * + * @example + * + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.register('provider-action', (payload, identity) => { + * console.log(payload); + * return { + * echo: payload + * }; + * }); + * + * await provider.remove('provider-action'); + * + * })(); + * ``` + */ + remove(action) { + this.subscriptions.delete(action); + } + /** + * Registers a default action. This is used any time an action that has not been registered is invoked. + * + * @example + * + * Channel Provider: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.setDefaultAction((action, payload, identity) => { + * console.log(`Client with identity ${JSON.stringify(identity)} has attempted to dispatch unregistered action: ${action}.`); + * + * return { + * echo: payload + * }; + * }); + * + * })(); + * ``` + * + * Channel Client: + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.setDefaultAction((action, payload, identity) => { + * console.log(`Provider with identity ${JSON.stringify(identity)} has attempted to dispatch unregistered action: ${action}.`); + * + * return { + * echo: payload + * }; + * }); + * + * })(); + * ``` + * @param func + */ + setDefaultAction(func) { + if (this.defaultAction) { + throw new Error('default action can only be set once'); + } + else { + this.defaultAction = func; + } + } + /** + * Register an action to be called by dispatching from any channelClient or channelProvider. + * + * @param topic + * @param listener + * + * @remarks The return value will be sent back as an acknowledgement to the original caller. You can throw an + * error to send a negative-acknowledgement and the error will reject the promise returned to the sender by the + * dispatch call. Once a listener is registered for a particular action, it stays in place receiving and responding + * to incoming messages until it is removed. This messaging mechanism works exactly the same when messages are + * dispatched from the provider to a client. However, the provider has an additional publish method that sends messages + * to all connected clients. + * + * Because multiple clients can share the same `name` and `uuid`, in order to distinguish between individual clients, + * the `identity` argument in a provider's registered action callback contains an `endpointId` property. When dispatching + * from a provider to a client, the `endpointId` property must be provided in order to send an action to a specific client. + * + * @example + * + * Channel Provider: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.register('provider-action', (payload, identity) => { + * console.log('Action dispatched by client: ', identity); + * console.log('Payload sent in dispatch: ', payload); + * + * return { echo: payload }; + * }); + * })(); + * ``` + * + * Channel Client: + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.register('client-action', (payload, identity) => { + * console.log('Action dispatched by client: ', identity); + * console.log('Payload sent in dispatch: ', payload); + * + * return { echo: payload }; + * }); + * })(); + * ``` + */ + register(topic, listener) { + if (this.subscriptions.has(topic)) { + throw new Error(`Subscription already registered for action: ${topic}. Unsubscribe before adding new subscription`); + } + else { + this.subscriptions.set(topic, listener); + return true; + } + } +} +channel.ChannelBase = ChannelBase; + +var __classPrivateFieldGet$c = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet$a = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _ChannelClient_protectedObj, _ChannelClient_strategy, _ChannelClient_close; +Object.defineProperty(client, "__esModule", { value: true }); +client.ChannelClient = void 0; +const channel_1$1 = channel; +const channelClientsByEndpointId = new Map(); +/** + * Instance created to enable use of a channel as a client. Allows for communication with the + * {@link ChannelProvider ChannelProvider} by invoking an action on the + * provider via {@link ChannelClient#dispatch dispatch} and to listen for communication + * from the provider by registering an action via {@link ChannelClient#register register}. + * + * ### Synchronous Methods: + * * {@link ChannelClient#onDisconnection onDisconnection(listener)} + * * {@link ChannelClient#register register(action, listener)} + * * {@link ChannelClient#remove remove(action)} + * + * ### Asynchronous Methods: + * * {@link ChannelClient#disconnect disconnect()} + * * {@link ChannelClient#dispatch dispatch(action, payload)} + * + * ### Middleware: + * Middleware functions receive the following arguments: (action, payload, senderId). + * The return value of the middleware function will be passed on as the payload from beforeAction, to the action listener, to afterAction + * unless it is undefined, in which case the original payload is used. Middleware can be used for side effects. + * * {@link ChannelClient#setDefaultAction setDefaultAction(middleware)} + * * {@link ChannelClient#onError onError(middleware)} + * * {@link ChannelClient#beforeAction beforeAction(middleware)} + * * {@link ChannelClient#afterAction afterAction(middleware)} + */ +class ChannelClient extends channel_1$1.ChannelBase { + /** + * @internal + */ + static closeChannelByEndpointId(id) { + const channel = channelClientsByEndpointId.get(id); + if (channel) { + __classPrivateFieldGet$c(channel, _ChannelClient_close, "f").call(channel); + } + } + /** + * @internal + * closes the corresponding channel and invokes the disconnect listener if an event payload is passed. + */ + static handleProviderDisconnect(eventPayload) { + for (const channelClient of channelClientsByEndpointId.values()) { + if (channelClient.providerIdentity.channelId === eventPayload.channelId) { + channelClient.disconnectListener(eventPayload); + __classPrivateFieldGet$c(channelClient, _ChannelClient_close, "f").call(channelClient); + } + } + } + /** + * @internal + */ + constructor(routingInfo, close, strategy) { + super(); + _ChannelClient_protectedObj.set(this, void 0); + _ChannelClient_strategy.set(this, void 0); + // needs to be bound; + this.processAction = (action, payload, senderIdentity) => super.processAction(action, payload, senderIdentity); + _ChannelClient_close.set(this, () => { + channelClientsByEndpointId.delete(this.endpointId); + __classPrivateFieldGet$c(this, _ChannelClient_strategy, "f").close(); + }); + __classPrivateFieldSet$a(this, _ChannelClient_protectedObj, new channel_1$1.ProtectedItems(routingInfo, close), "f"); + this.disconnectListener = () => undefined; + this.endpointId = routingInfo.endpointId; + __classPrivateFieldSet$a(this, _ChannelClient_strategy, strategy, "f"); + channelClientsByEndpointId.set(this.endpointId, this); + strategy.receive(this.processAction); + } + /** + * a read-only provider identity + */ + get providerIdentity() { + const protectedObj = __classPrivateFieldGet$c(this, _ChannelClient_protectedObj, "f"); + return protectedObj.providerIdentity; + } + /** + * Dispatch the given action to the channel provider. Returns a promise that resolves with the response from + * the provider for that action. + * + * @param action + * @param payload + * + * @example + * + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.register('client-action', (payload, identity) => { + * console.log(payload, identity); + * return { + * echo: payload + * }; + * }); + * + * const providerResponse = await client.dispatch('provider-action', { message: 'Hello From the client'}); + * console.log(providerResponse); + * })(); + * ``` + */ + async dispatch(action, payload) { + if (__classPrivateFieldGet$c(this, _ChannelClient_strategy, "f").isEndpointConnected(this.providerIdentity.channelId)) { + return __classPrivateFieldGet$c(this, _ChannelClient_strategy, "f").send(this.providerIdentity.channelId, action, payload); + } + throw new Error('The client you are trying to dispatch from is disconnected from the target provider.'); + } + /** + * Register a listener that is called on provider disconnection. It is passed the disconnection event of the + * disconnecting provider. + * + * @param listener + * + * @example + * + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.onDisconnection(evt => { + * console.log('Provider disconnected', `uuid: ${evt.uuid}, name: ${evt.name}`); + * }); + * })(); + * ``` + */ + onDisconnection(listener) { + this.disconnectListener = (payload) => { + try { + listener(payload); + } + catch (err) { + throw new Error(`Error while calling the onDisconnection callback: ${err.message}`); + } + finally { + this.disconnectListener = () => undefined; + } + }; + } + /** + * Disconnects the client from the channel. + * + * @example + * + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.disconnect(); + * })(); + * ``` + */ + async disconnect() { + await this.sendDisconnectAction(); + __classPrivateFieldGet$c(this, _ChannelClient_close, "f").call(this); + } + async sendDisconnectAction() { + const protectedObj = __classPrivateFieldGet$c(this, _ChannelClient_protectedObj, "f"); + await protectedObj.close(); + } + /** + * @internal + * Writing this as a static to keep code together, but in environments with a wire, this will be DI'd into the protectedObject class as close. + */ + static async wireClose(wire, providerIdentity, endpointId) { + const { channelName, uuid, name } = providerIdentity; + await wire.sendAction('disconnect-from-channel', { + channelName, + uuid, + name, + endpointId + }); + } +} +client.ChannelClient = ChannelClient; +_ChannelClient_protectedObj = new WeakMap(), _ChannelClient_strategy = new WeakMap(), _ChannelClient_close = new WeakMap(); + +var connectionManager = {}; + +var exhaustive = {}; + +Object.defineProperty(exhaustive, "__esModule", { value: true }); +exhaustive.exhaustiveCheck = void 0; +function exhaustiveCheck(value, allowed) { + throw new Error(`Unsupported value: ${value}${allowed ? `\n Supported values are: ${allowed.join('')}` : ''}`); +} +exhaustive.exhaustiveCheck = exhaustiveCheck; + +var strategy$3 = {}; + +var __classPrivateFieldSet$9 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$b = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _ClassicStrategy_wire, _ClassicStrategy_endpointIdentityMap, _ClassicStrategy_pendingMessagesByEndpointId; +Object.defineProperty(strategy$3, "__esModule", { value: true }); +strategy$3.ClassicInfo = strategy$3.ClassicStrategy = void 0; +/* +This is used to abstract out ipc messaging from the channels implementation. It is only concerned with sending messages and registration with the MessageReceiver +*/ +class ClassicStrategy { + constructor(wire, messageReceiver, endpointId, // Provider endpointId is channelId + providerIdentity) { + this.messageReceiver = messageReceiver; + this.endpointId = endpointId; + this.providerIdentity = providerIdentity; + _ClassicStrategy_wire.set(this, void 0); + // Store full endpointIdentity by endpointId of all known endpoints for this strategy instance. + // (clients will only have 1: the provider, the provider will have all clients) + _ClassicStrategy_endpointIdentityMap.set(this, new Map()); + // Store a set of cancellable promises to be able to reject them when client + // connection problems occur + _ClassicStrategy_pendingMessagesByEndpointId.set(this, new Map); + this.send = async (endpointId, action, payload) => { + const to = __classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").get(endpointId); + if (!to) { + throw new Error(`Could not locate routing info for endpoint ${endpointId}`); + } + // as casting to any because typescript complains. The following is only relevant if this is a locally set endpointId on a ClientIdentity. + // We delete these properties to not change backwards compatibility. + const cleanId = { ...to }; + if (cleanId.isLocalEndpointId) { + delete cleanId.endpointId; + } + delete cleanId.isLocalEndpointId; + // grab the promise before awaiting it to save in our pending messages map + const p = __classPrivateFieldGet$b(this, _ClassicStrategy_wire, "f") + .sendAction('send-channel-message', { + ...cleanId, + providerIdentity: this.providerIdentity, + action, + payload + }); + __classPrivateFieldGet$b(this, _ClassicStrategy_pendingMessagesByEndpointId, "f").get(endpointId)?.add(p); + const raw = await p.catch((error) => { + throw new Error(error.message); + }).finally(() => { + // clean up the pending promise + __classPrivateFieldGet$b(this, _ClassicStrategy_pendingMessagesByEndpointId, "f").get(endpointId)?.delete(p); + }); + return raw.payload.data.result; + }; + this.close = async () => { + this.messageReceiver.removeEndpoint(this.providerIdentity.channelId, this.endpointId); + [...__classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").keys()].forEach((id) => this.closeEndpoint(id)); + __classPrivateFieldSet$9(this, _ClassicStrategy_endpointIdentityMap, new Map(), "f"); + }; + __classPrivateFieldSet$9(this, _ClassicStrategy_wire, wire, "f"); + } + onEndpointDisconnect(endpointId, listener) { + // Never fires for 'classic'. + } + receive(listener) { + this.messageReceiver.addEndpoint(listener, this.providerIdentity.channelId, this.endpointId); + } + async closeEndpoint(endpointId) { + const id = __classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").get(endpointId); + __classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").delete(endpointId); + const pendingSet = __classPrivateFieldGet$b(this, _ClassicStrategy_pendingMessagesByEndpointId, "f").get(endpointId); + pendingSet?.forEach((p) => { + const errorMsg = `Channel connection with identity uuid: ${id?.uuid} / name: ${id?.name} / endpointId: ${endpointId} no longer connected.`; + p.cancel(new Error(errorMsg)); + }); + } + isEndpointConnected(endpointId) { + return __classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").has(endpointId); + } + addEndpoint(endpointId, payload) { + __classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").set(endpointId, payload.endpointIdentity); + __classPrivateFieldGet$b(this, _ClassicStrategy_pendingMessagesByEndpointId, "f").set(endpointId, new Set()); + } + isValidEndpointPayload(payload) { + return (typeof payload?.endpointIdentity?.endpointId === 'string' || + typeof payload?.endpointIdentity?.channelId === 'string'); + } +} +strategy$3.ClassicStrategy = ClassicStrategy; +_ClassicStrategy_wire = new WeakMap(), _ClassicStrategy_endpointIdentityMap = new WeakMap(), _ClassicStrategy_pendingMessagesByEndpointId = new WeakMap(); +// Arbitrarily starting at 5 to leave the door open to backfilling pre endpointId etc. +strategy$3.ClassicInfo = { version: 5, minimumVersion: 0, type: 'classic' }; + +var strategy$2 = {}; + +var endpoint = {}; + +var errors = {}; + +Object.defineProperty(errors, "__esModule", { value: true }); +errors.errorToPOJO = void 0; +function errorToPOJO(error) { + return { + stack: error.stack, + name: error.name, + message: error.message, + // support the case where stack is empty or missing + toString: () => error.stack || error.toString() + }; +} +errors.errorToPOJO = errorToPOJO; + +var __classPrivateFieldGet$a = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet$8 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _RTCEndpoint_processAction, _RTCEndpoint_disconnectListener; +Object.defineProperty(endpoint, "__esModule", { value: true }); +endpoint.RTCEndpoint = void 0; +/* eslint-disable @typescript-eslint/no-unused-vars */ +const errors_1$1 = errors; +/* +This handles sending RTC messages between RTC connections over the request and response data channels. +*/ +class RTCEndpoint { + static isValidEndpointPayload(payload) { + const isObject = (x) => { + return typeof x === 'object' && x !== null; + }; + return ( + // TODO in factory PR: + // payload.type === 'rtc' && + isObject(payload) && + isObject(payload.endpointIdentity) && + isObject(payload.rtc) && + typeof payload.endpointIdentity.endpointId === 'string'); + } + constructor({ rtc, endpointIdentity }) { + this.responseMap = new Map(); + _RTCEndpoint_processAction.set(this, null); + _RTCEndpoint_disconnectListener.set(this, void 0); + this.connectionStateChangeHandler = (event) => { + if (this.rtc.rtcClient.connectionState !== 'connected') { + this.rtc.rtcClient.removeEventListener('connectionstatechange', this.connectionStateChangeHandler); + this.close(); + if (__classPrivateFieldGet$a(this, _RTCEndpoint_disconnectListener, "f")) { + __classPrivateFieldGet$a(this, _RTCEndpoint_disconnectListener, "f").call(this); + } + } + }; + this.send = async (action, payload) => { + const messageId = `message-${Math.random()}`; + const promise = new Promise((resolve, reject) => { + this.responseMap.set(messageId, { resolve, reject }); + }); + this.rtc.channels.request.send(JSON.stringify({ action, payload, messageId })); + return promise; + }; + this.close = () => { + this.responseMap.forEach((response) => response.reject('Connection has closed.')); + this.responseMap = new Map(); + this.rtc.channels.request.close(); + this.rtc.channels.response.close(); + this.rtc.rtcClient.close(); + }; + this.rtc = rtc; + this.endpointIdentity = endpointIdentity; + this.rtc.channels.response.addEventListener('message', (e) => { + let { data } = e; + if (e.data instanceof ArrayBuffer) { + data = new TextDecoder().decode(e.data); + } + const { messageId, payload, success, error } = JSON.parse(data); + const { resolve, reject } = this.responseMap.get(messageId) ?? {}; + if (resolve && reject) { + this.responseMap.delete(messageId); + if (success) { + resolve(payload); + } + else { + reject(error); + } + } + else { + console.log('Could not find id in responseMap.'); + console.log(e); + } + }); + this.rtc.channels.request.addEventListener('message', async (e) => { + let { data } = e; + if (e.data instanceof ArrayBuffer) { + data = new TextDecoder().decode(e.data); + } + const { messageId, action, payload } = JSON.parse(data); + if (__classPrivateFieldGet$a(this, _RTCEndpoint_processAction, "f")) { + try { + const res = await __classPrivateFieldGet$a(this, _RTCEndpoint_processAction, "f").call(this, action, payload, endpointIdentity); + this.rtc.channels.response.send(JSON.stringify({ + messageId, + payload: res, + success: true + })); + } + catch (error) { + // Check if RTCDataChannel is open before sending, error gets swallowed here in the case where + // client dispatched then closed or disconnected before the dispatch resolves. + if (this.rtc.channels.response.readyState === 'open') { + this.rtc.channels.response.send(JSON.stringify({ + messageId, + error: (0, errors_1$1.errorToPOJO)(error), + success: false + })); + } + } + // Check if RTCDataChannel is open for same reason as catch block above. + } + else if (this.rtc.channels.response.readyState === 'open') { + this.rtc.channels.response.send(JSON.stringify({ + messageId, + success: false, + error: 'Connection not ready.' + })); + } + }); + this.rtc.rtcClient.addEventListener('connectionstatechange', this.connectionStateChangeHandler); + // Disconnect if data channels close unexpectedly, e.g. can happen due to message size > ~255kB (RTCPeerConnection.sctp.maxMessageSizeLimit: 262144) + Object.values(this.rtc.channels).forEach((datachannel) => { + datachannel.onclose = (e) => { + [...this.responseMap.values()].forEach((promise) => promise.reject(new Error('RTCDataChannel closed unexpectedly, this is most commonly caused by message size. Note: RTC Channels have a message size limit of ~255kB.'))); + this.close(); + if (__classPrivateFieldGet$a(this, _RTCEndpoint_disconnectListener, "f")) { + __classPrivateFieldGet$a(this, _RTCEndpoint_disconnectListener, "f").call(this); + } + }; + }); + } + onDisconnect(listener) { + if (!__classPrivateFieldGet$a(this, _RTCEndpoint_disconnectListener, "f")) { + __classPrivateFieldSet$8(this, _RTCEndpoint_disconnectListener, listener, "f"); + } + else { + throw new Error('RTCEndpoint disconnectListener cannot be set twice.'); + } + } + receive(listener) { + if (__classPrivateFieldGet$a(this, _RTCEndpoint_processAction, "f")) { + throw new Error('You have already set a listener for this RTC Endpoint.'); + } + __classPrivateFieldSet$8(this, _RTCEndpoint_processAction, listener, "f"); + } + get connected() { + return this.rtc.rtcClient.connectionState === 'connected'; + } +} +endpoint.RTCEndpoint = RTCEndpoint; +_RTCEndpoint_processAction = new WeakMap(), _RTCEndpoint_disconnectListener = new WeakMap(); + +var strategy$1 = {}; + +var __classPrivateFieldGet$9 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet$7 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _EndpointStrategy_processAction, _EndpointStrategy_endpointMap, _EndpointStrategy_connected; +Object.defineProperty(strategy$1, "__esModule", { value: true }); +strategy$1.EndpointStrategy = void 0; +class EndpointStrategy { + // Need to pass in validate endpoint separately from constructor because ts interfaces don't do well with static methods + constructor(EndpointType, validateEndpoint, StrategyName) { + this.EndpointType = EndpointType; + this.StrategyName = StrategyName; + _EndpointStrategy_processAction.set(this, null); + _EndpointStrategy_endpointMap.set(this, new Map()); + _EndpointStrategy_connected.set(this, true); + this.send = async (endpointId, action, payload) => { + return this.getEndpointById(endpointId).send(action, payload); + }; + this.close = async () => { + if (__classPrivateFieldGet$9(this, _EndpointStrategy_connected, "f")) { + __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").forEach((endpoint) => endpoint.close()); + __classPrivateFieldSet$7(this, _EndpointStrategy_endpointMap, new Map(), "f"); + } + __classPrivateFieldSet$7(this, _EndpointStrategy_connected, false, "f"); + }; + this.isValidEndpointPayload = validateEndpoint; + } + onEndpointDisconnect(endpointId, listener) { + this.getEndpointById(endpointId).onDisconnect(listener); + } + receive(listener) { + if (__classPrivateFieldGet$9(this, _EndpointStrategy_processAction, "f")) { + throw new Error(`You have already set a listener for this ${this.StrategyName} Strategy`); + } + __classPrivateFieldSet$7(this, _EndpointStrategy_processAction, listener, "f"); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").forEach((endpoint) => endpoint.receive(__classPrivateFieldGet$9(this, _EndpointStrategy_processAction, "f"))); + } + getEndpointById(endpointId) { + const endpoint = __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").get(endpointId); + if (!endpoint) { + throw new Error(`Client with endpoint id ${endpointId} is not connected`); + } + return endpoint; + } + get connected() { + return __classPrivateFieldGet$9(this, _EndpointStrategy_connected, "f"); + } + isEndpointConnected(endpointId) { + return __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").has(endpointId); + } + addEndpoint(endpointId, payload) { + if (!__classPrivateFieldGet$9(this, _EndpointStrategy_connected, "f")) { + console.warn(`Adding endpoint to disconnected ${this.StrategyName} Strategy`); + return; + } + const clientStrat = new this.EndpointType(payload); + if (__classPrivateFieldGet$9(this, _EndpointStrategy_processAction, "f")) { + clientStrat.receive(__classPrivateFieldGet$9(this, _EndpointStrategy_processAction, "f")); + } + __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").set(endpointId, clientStrat); + } + async closeEndpoint(endpointId) { + __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").delete(endpointId); + } +} +strategy$1.EndpointStrategy = EndpointStrategy; +_EndpointStrategy_processAction = new WeakMap(), _EndpointStrategy_endpointMap = new WeakMap(), _EndpointStrategy_connected = new WeakMap(); + +Object.defineProperty(strategy$2, "__esModule", { value: true }); +strategy$2.RTCInfo = strategy$2.RTCStrategy = void 0; +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable class-methods-use-this */ +const endpoint_1 = endpoint; +const strategy_1$1 = strategy$1; +/* +This is used to abstract out rtc messaging from the channels implementation using RTCEndpoints. +*/ +class RTCStrategy extends strategy_1$1.EndpointStrategy { + constructor() { + super(endpoint_1.RTCEndpoint, endpoint_1.RTCEndpoint.isValidEndpointPayload, 'RTC'); + } +} +strategy$2.RTCStrategy = RTCStrategy; +strategy$2.RTCInfo = { version: 2, minimumVersion: 0, type: 'rtc' }; + +var iceManager = {}; + +Object.defineProperty(iceManager, "__esModule", { value: true }); +iceManager.RTCICEManager = void 0; +const base_1$h = base; +/* +Singleton that facilitates Offer and Answer exchange required for establishing RTC connections. +*/ +class RTCICEManager extends base_1$h.EmitterBase { + constructor(wire) { + super(wire, 'channel'); + this.ensureChannelOpened = (channel) => { + return new Promise((resolve, reject) => { + if (channel.readyState === 'open') { + resolve(); + } + else if (channel.readyState === 'connecting') { + const listener = () => { + channel.removeEventListener('open', listener); + resolve(); + }; + channel.addEventListener('open', listener); + } + else { + reject(new Error('This Channel has already closed')); + } + }); + }; + } + static createDataChannelPromise(label, rtcClient) { + let resolver; + const promise = new Promise((resolve) => { + resolver = resolve; + }); + const listener = (e) => { + const openListener = () => { + e.channel.removeEventListener('open', openListener); + resolver(e.channel); + }; + if (e.channel.label === label) { + e.channel.addEventListener('open', openListener); + rtcClient.removeEventListener('datachannel', listener); + } + }; + rtcClient.addEventListener('datachannel', listener); + return promise; + } + async listenForProviderIce(rtcConnectionId, listener) { + await this.on(this.createProviderEventName(rtcConnectionId), listener, { timestamp: Date.now() }); + } + async raiseProviderIce(rtcConnectionId, payload) { + await this.wire.environment.raiseEvent(this.createRouteString(this.createProviderEventName(rtcConnectionId)), payload); + } + async listenForClientIce(rtcConnectionId, listener) { + await this.on(this.createClientEventName(rtcConnectionId), listener, { timestamp: Date.now() }); + } + async raiseClientIce(rtcConnectionId, payload) { + await this.wire.environment.raiseEvent(this.createRouteString(this.createClientEventName(rtcConnectionId)), payload); + } + cleanupIceListeners(rtcConnectionId) { + this.removeAllListeners(this.createClientEventName(rtcConnectionId)); + this.removeAllListeners(this.createProviderEventName(rtcConnectionId)); + } + createClientEventName(rtcConnectionId) { + return `ice-client-${rtcConnectionId}`; + } + createProviderEventName(rtcConnectionId) { + return `ice-provider-${rtcConnectionId}`; + } + createRouteString(name) { + return `channel/${name}`; + } + createRtcPeer() { + return this.wire.environment.getRtcPeer(); + } + async startClientOffer() { + // TODO replace with real guid. + const rtcConnectionId = Math.random().toString(); + const rtcClient = this.createRtcPeer(); + rtcClient.addEventListener('icecandidate', async (e) => { + if (e.candidate) { + await this.raiseClientIce(rtcConnectionId, { candidate: e.candidate?.toJSON() }); + } + }); + await this.listenForProviderIce(rtcConnectionId, async (payload) => { + await rtcClient.addIceCandidate(payload.candidate); + }); + const channels = { + request: rtcClient.createDataChannel('request'), + response: rtcClient.createDataChannel('response') + }; + const offer = await rtcClient.createOffer(); + await rtcClient.setLocalDescription(offer); + const channelsOpened = Promise.all([channels.request, channels.response].map(this.ensureChannelOpened)).then(() => undefined); + return { rtcClient, channels, offer, rtcConnectionId, channelsOpened }; + } + async finishClientOffer(rtcClient, answer, providerReady) { + await rtcClient.setRemoteDescription(answer); + await providerReady; + return true; + } + async createProviderAnswer(rtcConnectionId, offer) { + const rtcClient = this.createRtcPeer(); + const requestChannelPromise = RTCICEManager.createDataChannelPromise('request', rtcClient); + const responseChannelPromise = RTCICEManager.createDataChannelPromise('response', rtcClient); + rtcClient.addEventListener('icecandidate', async (e) => { + if (e.candidate) { + await this.raiseProviderIce(rtcConnectionId, { candidate: e.candidate?.toJSON() }); + } + }); + await this.listenForClientIce(rtcConnectionId, async (payload) => { + await rtcClient.addIceCandidate(payload.candidate); + }); + await rtcClient.setRemoteDescription(offer); + const answer = await rtcClient.createAnswer(); + await rtcClient.setLocalDescription(answer); + const channels = Promise.all([requestChannelPromise, responseChannelPromise]).then(([request, response]) => { + // Clean up ice events. + this.cleanupIceListeners(rtcConnectionId); + return { request, response }; + }); + return { + rtcClient, + answer, + channels + }; + } +} +iceManager.RTCICEManager = RTCICEManager; + +var provider = {}; + +var runtimeVersioning = {}; + +Object.defineProperty(runtimeVersioning, "__esModule", { value: true }); +runtimeVersioning.runtimeUuidMeetsMinimumRuntimeVersion = runtimeVersioning.parseRuntimeUuid = runtimeVersioning.meetsMinimumRuntimeVersion = void 0; +function vNum(x) { + return [...x.split('.').reverse().entries()].reduce((p, [i, v]) => p + +v * 10000 ** i, 0); +} +/* + Compares runtime versions to see if the current runtime meets your desired minimum. +*/ +function meetsMinimumRuntimeVersion(currentVersion, minVersion) { + const currentVersionParsed = vNum(currentVersion); + const minVersionParsed = vNum(minVersion); + return currentVersionParsed >= minVersionParsed; +} +runtimeVersioning.meetsMinimumRuntimeVersion = meetsMinimumRuntimeVersion; +// Strips the port info from the runtimeUuid, leaving just the runtime version. +function parseRuntimeUuid(runtimeUuid) { + return runtimeUuid.split('/')[0]; +} +runtimeVersioning.parseRuntimeUuid = parseRuntimeUuid; +function runtimeUuidMeetsMinimumRuntimeVersion(runtimeUuid, minVersion) { + const runtimeVersion = parseRuntimeUuid(runtimeUuid); + return meetsMinimumRuntimeVersion(runtimeVersion, minVersion); +} +runtimeVersioning.runtimeUuidMeetsMinimumRuntimeVersion = runtimeUuidMeetsMinimumRuntimeVersion; + +var __classPrivateFieldGet$8 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet$6 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _ChannelProvider_connections, _ChannelProvider_protectedObj, _ChannelProvider_strategy, _ChannelProvider_removeEndpoint, _ChannelProvider_close; +Object.defineProperty(provider, "__esModule", { value: true }); +provider.ChannelProvider = void 0; +const channel_1 = channel; +const runtimeVersioning_1 = runtimeVersioning; +/** + * Instance created to enable use of a channel as a provider. Allows for communication with the {@link ChannelClient ChannelClients} by invoking an action on + * a single client via {@link ChannelProvider#dispatch dispatch} or all clients via {@link ChannelProvider#publish publish} + * and to listen for communication from clients by registering an action via {@link ChannelProvider#register register}. + * + * ### Synchronous Methods: + * * {@link ChannelProvider#onConnection onConnection(listener)} + * * {@link ChannelProvider#onDisconnection onDisconnection(listener)} + * * {@link ChannelProvider#publish publish(action, payload)} + * * {@link ChannelProvider#register register(action, listener)} + * * {@link ChannelProvider#remove remove(action)} + * + * ### Asynchronous Methods: + * * {@link ChannelProvider#destroy destroy()} + * * {@link ChannelProvider#dispatch dispatch(to, action, payload)} + * * {@link ChannelProvider#getAllClientInfo getAllClientInfo()} + * + * ### Middleware: + * Middleware functions receive the following arguments: (action, payload, senderId). + * The return value of the middleware function will be passed on as the payload from beforeAction, to the action listener, to afterAction + * unless it is undefined, in which case the most recently defined payload is used. Middleware can be used for side effects. + * * {@link ChannelProvider#setDefaultAction setDefaultAction(middleware)} + * * {@link ChannelProvider#onError onError(middleware)} + * * {@link ChannelProvider#beforeAction beforeAction(middleware)} + * * {@link ChannelProvider#afterAction afterAction(middleware)} + */ +class ChannelProvider extends channel_1.ChannelBase { + /** + * a read-only array containing all the identities of connecting clients. + */ + get connections() { + return [...__classPrivateFieldGet$8(this, _ChannelProvider_connections, "f")]; + } + static handleClientDisconnection(channel, payload) { + const removeById = channel.connections.find((identity) => identity.endpointId === payload.endpointId); + if (removeById) { + __classPrivateFieldGet$8(channel, _ChannelProvider_removeEndpoint, "f").call(channel, removeById); + } + else { + const multipleRemoves = channel.connections.filter((identity) => { + return identity.uuid === payload.uuid && identity.name === payload.name; + }); + multipleRemoves.forEach(__classPrivateFieldGet$8(channel, _ChannelProvider_removeEndpoint, "f")); + } + channel.disconnectListener(payload); + } + static setProviderRemoval(provider, remove) { + ChannelProvider.removalMap.set(provider, remove); + } + /** + * @internal + */ + constructor(providerIdentity, close, strategy) { + super(); + _ChannelProvider_connections.set(this, void 0); + _ChannelProvider_protectedObj.set(this, void 0); + _ChannelProvider_strategy.set(this, void 0); + _ChannelProvider_removeEndpoint.set(this, (identity) => { + const remainingConnections = this.connections.filter((clientIdentity) => clientIdentity.endpointId !== identity.endpointId); + __classPrivateFieldGet$8(this, _ChannelProvider_strategy, "f").closeEndpoint(identity.endpointId); + __classPrivateFieldSet$6(this, _ChannelProvider_connections, remainingConnections, "f"); + }); + // Must be bound. + this.processAction = async (action, payload, senderIdentity) => { + if (ChannelProvider.clientIsMultiRuntime(senderIdentity) && + !(0, runtimeVersioning_1.runtimeUuidMeetsMinimumRuntimeVersion)(senderIdentity.runtimeUuid, '18.87.56.0')) { + this.handleMultiRuntimeLegacyClient(senderIdentity); + } + else { + this.checkForClientConnection(senderIdentity); + } + return super.processAction(action, payload, senderIdentity); + }; + _ChannelProvider_close.set(this, () => { + __classPrivateFieldGet$8(this, _ChannelProvider_strategy, "f").close(); + const remove = ChannelProvider.removalMap.get(this); + if (remove) { + remove(); + } + }); + __classPrivateFieldSet$6(this, _ChannelProvider_protectedObj, new channel_1.ProtectedItems(providerIdentity, close), "f"); + this.connectListener = () => undefined; + this.disconnectListener = () => undefined; + __classPrivateFieldSet$6(this, _ChannelProvider_connections, [], "f"); + __classPrivateFieldSet$6(this, _ChannelProvider_strategy, strategy, "f"); + strategy.receive(this.processAction); + } + /** + * Dispatch an action to a specified client. Returns a promise for the result of executing that action on the client side. + * + * @param to - Identity of the target client. + * @param action - Name of the action to be invoked by the client. + * @param payload - Payload to be sent along with the action. + * + * @remarks + * + * Because multiple clients can share the same `name` and `uuid`, when dispatching from a provider to a client, + * the `identity` you provide must include the client's unique `endpointId` property. This `endpointId` is + * passed to the provider in both the `Provider.onConnection` callback and in any registered action callbacks. + * + * @example + * + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.register('provider-action', async (payload, identity) => { + * console.log(payload, identity); + * return await provider.dispatch(identity, 'client-action', 'Hello, World!'); + * }); + * })(); + * ``` + */ + dispatch(to, action, payload) { + const endpointId = to.endpointId ?? this.getEndpointIdForOpenFinId(to, action); + if (endpointId && __classPrivateFieldGet$8(this, _ChannelProvider_strategy, "f").isEndpointConnected(endpointId)) { + return __classPrivateFieldGet$8(this, _ChannelProvider_strategy, "f").send(endpointId, action, payload); + } + return Promise.reject(new Error(`Client connection with identity uuid: ${to.uuid} / name: ${to.name} / endpointId: ${endpointId} no longer connected.`)); + } + async processConnection(senderId, payload) { + __classPrivateFieldGet$8(this, _ChannelProvider_connections, "f").push(senderId); + return this.connectListener(senderId, payload); + } + /** + * Publish an action and payload to every connected client. + * Synchronously returns an array of promises for each action (see dispatch). + * + * @param action + * @param payload + * + * @example + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.register('provider-action', async (payload, identity) => { + * console.log(payload, identity); + * return await Promise.all(provider.publish('client-action', { message: 'Broadcast from provider'})); + * }); + * })(); + * ``` + */ + publish(action, payload) { + return this.connections.map((to) => __classPrivateFieldGet$8(this, _ChannelProvider_strategy, "f").send(to.endpointId, action, payload)); + } + /** + * Register a listener that is called on every new client connection. + * + * @remarks It is passed the identity of the connecting client and a payload if it was provided to Channel.connect. + * If you wish to reject the connection, throw an error. Be sure to synchronously provide an onConnection upon receipt of + * the channelProvider to ensure all potential client connections are caught by the listener. + * + * Because multiple clients can exist at the same `name` and `uuid`, in order to distinguish between individual clients, + * the `identity` argument in a provider's `onConnection` callback contains an `endpointId` property. When dispatching from a + * provider to a client, the `endpointId` property must be provided in order to send an action to a specific client. + * + * @example + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * provider.onConnection(identity => { + * console.log('Client connected', identity); + * }); + * })(); + * ``` + * + * Reject connection: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * provider.onConnection(identity => { + * throw new Error('Connection Rejected'); + * }); + * })(); + * ``` + * @param listener + */ + onConnection(listener) { + this.connectListener = listener; + } + /** + * Register a listener that is called on client disconnection. It is passed the disconnection event of the disconnecting + * client. + * + * @param listener + * + * @example + * + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.onDisconnection(evt => { + * console.log('Client disconnected', `uuid: ${evt.uuid}, name: ${evt.name}`); + * }); + * })(); + * ``` + */ + onDisconnection(listener) { + this.disconnectListener = listener; + } + /** + * Destroy the channel, raises `disconnected` events on all connected channel clients. + * + * @example + * + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.destroy(); + * })(); + * ``` + */ + async destroy() { + const protectedObj = __classPrivateFieldGet$8(this, _ChannelProvider_protectedObj, "f"); + protectedObj.providerIdentity; + __classPrivateFieldSet$6(this, _ChannelProvider_connections, [], "f"); + await protectedObj.close(); + __classPrivateFieldGet$8(this, _ChannelProvider_close, "f").call(this); + } + /** + * Returns an array with info on every Client connected to the Provider + * + * @example + * + * ```js + * const provider = await fin.InterApplicationBus.Channel.create('openfin'); + * const client = await fin.InterApplicationBus.Channel.connect('openfin'); + * const clientInfo = await provider.getAllClientInfo(); + * + * console.log(clientInfo); + * + * // [ + * // { + * // "uuid": "openfin", + * // "name": "openfin-view", + * // "endpointId": "6d4c7ca8-4a74-4634-87f8-760558229613", + * // "entityType": "view", + * // "url": "https://openfin.co" + * // }, + * // { + * // "uuid": "openfin2", + * // "name": "openfin-view2", + * // "endpointId": "4z5d8ab9-2b81-3691-91ex-142179382511", + * // "entityType": "view", + * // "url": "https://example.com" + * // } + * //] + * ``` + */ + async getAllClientInfo() { + return this.connections.map((clientInfo) => { + const { uuid, name, endpointId, entityType, connectionUrl } = clientInfo; + return { uuid, name, endpointId, entityType, connectionUrl }; + }); + } + checkForClientConnection(clientIdentity) { + if (!this.isClientConnected(clientIdentity)) { + throw new Error(`This action was sent from a client that is not connected to the provider. + Client Identity: {uuid: ${clientIdentity.uuid}, name: ${clientIdentity.name}, endpointId: ${clientIdentity.endpointId}}`); + } + } + isClientConnected(clientIdentity) { + if (ChannelProvider.clientIdentityIncludesEndpointId(clientIdentity)) { + return this.connections.some((identity) => { + return ( + // Might be redundant to check for uuid and name here after we get an endpointId match, but just in case + identity.endpointId === clientIdentity.endpointId && + identity.uuid === clientIdentity.uuid && + identity.name === clientIdentity.name); + }); + } + return this.isLegacyClientConnected(clientIdentity); + } + isLegacyClientConnected(clientIdentity) { + return this.connections.some((identity) => { + return identity.uuid === clientIdentity.uuid && identity.name === clientIdentity.name; + }); + } + handleMultiRuntimeLegacyClient(senderIdentity) { + if (!this.isLegacyClientConnected(senderIdentity)) { + throw new Error(`This action was sent from a client that is not connected to the provider. Client Identity: + {uuid: ${senderIdentity.uuid}, name: ${senderIdentity.name}, endpointId: ${senderIdentity.endpointId}}`); + } + } + getEndpointIdForOpenFinId(clientIdentity, action) { + const matchingConnections = this.connections.filter((c) => c.name === clientIdentity.name && c.uuid === clientIdentity.uuid); + if (matchingConnections.length >= 2) { + const protectedObj = __classPrivateFieldGet$8(this, _ChannelProvider_protectedObj, "f"); + const { uuid, name } = clientIdentity; + const providerUuid = protectedObj?.providerIdentity.uuid; + const providerName = protectedObj?.providerIdentity.name; + // eslint-disable-next-line no-console + console.warn(`WARNING: Dispatch call may have unintended results. The "to" argument of your dispatch call is missing the + "endpointId" parameter. The identity you are dispatching to ({uuid: ${uuid}, name: ${name}}) + has multiple channelClients for this channel. Your dispatched action: (${action}) from the provider: + ({uuid: ${providerUuid}, name: ${providerName}}) will only be processed by the most recently-created client.`); + } + // Pop to return the most recently created endpointId. + return matchingConnections.pop()?.endpointId; + } + // eslint-disable-next-line class-methods-use-this + static clientIdentityIncludesEndpointId(subscriptionIdentity) { + return subscriptionIdentity.endpointId !== undefined; + } + // eslint-disable-next-line class-methods-use-this + static clientIsMultiRuntime(subscriptionIdentity) { + return subscriptionIdentity.runtimeUuid !== undefined; + } + static async wireClose(wire, channelName) { + await wire.sendAction('destroy-channel', { channelName }); + } +} +provider.ChannelProvider = ChannelProvider; +_ChannelProvider_connections = new WeakMap(), _ChannelProvider_protectedObj = new WeakMap(), _ChannelProvider_strategy = new WeakMap(), _ChannelProvider_removeEndpoint = new WeakMap(), _ChannelProvider_close = new WeakMap(); +// The following line should be changed following a typescript update. +// static #removalMap = new WeakMap(); +ChannelProvider.removalMap = new WeakMap(); + +var messageReceiver = {}; + +Object.defineProperty(messageReceiver, "__esModule", { value: true }); +messageReceiver.MessageReceiver = void 0; +const client_1$1 = client; +const base_1$g = base; +/* +This is a singleton (per fin object) tasked with routing messages coming off the ipc to the correct endpoint. +It needs to be a singleton because there can only be one per wire. It tracks both clients and providers' processAction passed in via the strategy. +If functionality is not about receiving messages, it does not belong here. +*/ +class MessageReceiver extends base_1$g.Base { + constructor(wire) { + super(wire); + this.onmessage = (msg) => { + if (msg.action === 'process-channel-message') { + this.processChannelMessage(msg); + return true; + } + return false; + }; + this.endpointMap = new Map(); + this.latestEndpointIdByChannelId = new Map(); + wire.registerMessageHandler(this.onmessage.bind(this)); + } + async processChannelMessage(msg) { + const { senderIdentity, providerIdentity, action, ackToSender, payload, intendedTargetIdentity } = msg.payload; + const key = intendedTargetIdentity.channelId ?? // The recipient is a provider + intendedTargetIdentity.endpointId ?? // The recipient is a client + this.latestEndpointIdByChannelId.get(providerIdentity.channelId); // No endpointId was passed, make best attempt + const handler = this.endpointMap.get(key); + if (!handler) { + ackToSender.payload.success = false; + ackToSender.payload.reason = `Client connection with identity uuid: ${this.wire.me.uuid} / name: ${this.wire.me.name} / endpointId: ${key} no longer connected.`; + return this.wire.sendRaw(ackToSender); + } + try { + const res = await handler(action, payload, senderIdentity); + ackToSender.payload.payload = ackToSender.payload.payload || {}; + ackToSender.payload.payload.result = res; + return this.wire.sendRaw(ackToSender); + } + catch (e) { + ackToSender.payload.success = false; + ackToSender.payload.reason = e.message; + return this.wire.sendRaw(ackToSender); + } + } + addEndpoint(handler, channelId, endpointId) { + this.endpointMap.set(endpointId, handler); + // Providers have the same endpointId and channelId. + // This is only used when clients are receiving messages from providers, so we shouldn't save provider endpointId here. + if (channelId !== endpointId) { + this.latestEndpointIdByChannelId.set(channelId, endpointId); + } + } + removeEndpoint(channelId, endpointId) { + this.endpointMap.delete(endpointId); + if (this.latestEndpointIdByChannelId.get(channelId) === endpointId) { + this.latestEndpointIdByChannelId.delete(channelId); + } + } + checkForPreviousClientConnection(channelId) { + const endpointIdFromPreviousConnection = this.latestEndpointIdByChannelId.get(channelId); + if (endpointIdFromPreviousConnection) { + // Not convinced by this way of doing things, but pushing up for now. + client_1$1.ChannelClient.closeChannelByEndpointId(endpointIdFromPreviousConnection); + // eslint-disable-next-line no-console + console.warn('You have created a second connection to an older provider. First connection has been removed from the clientMap'); + // eslint-disable-next-line no-console + console.warn('If the provider calls publish(), you may receive multiple messages.'); + } + } +} +messageReceiver.MessageReceiver = MessageReceiver; + +var protocolManager = {}; + +Object.defineProperty(protocolManager, "__esModule", { value: true }); +protocolManager.ProtocolManager = void 0; +/* +This should be agnostic of any actual openfin code to be unit testable. +Dependencies on the actual srategies should be handled in ConnectionManager +*/ +class ProtocolManager { + // eslint-disable-next-line no-useless-constructor + constructor(ProtocolsInPreferenceOrder) { + this.ProtocolsInPreferenceOrder = ProtocolsInPreferenceOrder; + this.DefaultClientProtocols = ['classic']; + this.DefaultProviderProtocols = ['classic']; + this.getClientProtocols = (protocols) => { + const supported = protocols + ? this.ProtocolsInPreferenceOrder.filter((x) => protocols.includes(x)) + : this.DefaultClientProtocols; + if (!supported.length) { + throw new Error(`No valid protocols were passed in. Accepted values are: ${this.ProtocolsInPreferenceOrder.join(', ')}.`); + } + return supported; + }; + this.getProviderProtocols = (protocols) => { + const supported = protocols + ? this.ProtocolsInPreferenceOrder.filter((x) => protocols.includes(x)) + : this.DefaultProviderProtocols; + if (!supported.length) { + throw new Error(`No valid protocols were passed in. Accepted values are: ${this.ProtocolsInPreferenceOrder.join(', ')}.`); + } + return supported; + }; + this.getCompatibleProtocols = (providerProtocols, clientOffer) => { + const supported = clientOffer.supportedProtocols.filter((clientProtocol) => providerProtocols.some((providerProtocol) => providerProtocol.type === clientProtocol.type && + clientProtocol.version >= providerProtocol.minimumVersion && + providerProtocol.version >= (clientProtocol.minimumVersion ?? 0))); + return supported.slice(0, clientOffer.maxProtocols); + }; + } +} +protocolManager.ProtocolManager = ProtocolManager; + +var strategy = {}; + +Object.defineProperty(strategy, "__esModule", { value: true }); +class CombinedStrategy { + // Making this a static method because the constructor can't be typed. + // Otherwise it will error when calling addEndpoint but I'd rather the whole instance be typed as never. + static combine(a, b) { + return new CombinedStrategy(a, b); + } + // eslint-disable-next-line no-useless-constructor + constructor(primary, secondary) { + this.primary = primary; + this.secondary = secondary; + } + onEndpointDisconnect(endpointId, listener) { + this.primary.onEndpointDisconnect(endpointId, () => { + if (!this.secondary.isEndpointConnected(endpointId)) { + listener(); + } + }); + this.secondary.onEndpointDisconnect(endpointId, () => { + if (!this.primary.isEndpointConnected(endpointId)) { + listener(); + } + }); + } + isValidEndpointPayload(payload) { + return this.primary.isValidEndpointPayload(payload) || this.secondary.isValidEndpointPayload(payload); + } + async closeEndpoint(endpointId) { + await this.primary.closeEndpoint(endpointId); + await this.secondary.closeEndpoint(endpointId); + } + isEndpointConnected(endpoint) { + return this.primary.isEndpointConnected(endpoint) || this.secondary.isEndpointConnected(endpoint); + } + async addEndpoint(endpoint, payload) { + if (this.primary.isValidEndpointPayload(payload)) { + await this.primary.addEndpoint(endpoint, payload); + } + if (this.secondary.isValidEndpointPayload(payload)) { + await this.secondary.addEndpoint(endpoint, payload); + } + } + receive(listener) { + this.primary.receive(listener); + this.secondary.receive(listener); + } + send(endpointId, action, payload) { + if (this.primary.isEndpointConnected(endpointId)) { + return this.primary.send(endpointId, action, payload); + } + return this.secondary.send(endpointId, action, payload); + } + async close() { + await Promise.all([this.primary.close(), this.secondary.close()]); + } +} +strategy.default = CombinedStrategy; + +var __classPrivateFieldSet$5 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$7 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault$1 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _ConnectionManager_messageReceiver, _ConnectionManager_rtcConnectionManager; +Object.defineProperty(connectionManager, "__esModule", { value: true }); +connectionManager.ConnectionManager = void 0; +const exhaustive_1 = exhaustive; +const base_1$f = base; +const strategy_1 = strategy$3; +const strategy_2 = strategy$2; +const ice_manager_1 = iceManager; +const provider_1$1 = provider; +const message_receiver_1 = messageReceiver; +const protocol_manager_1 = protocolManager; +const strategy_3 = __importDefault$1(strategy); +class ConnectionManager extends base_1$f.Base { + static getProtocolOptionsFromStrings(protocols) { + return protocols.map((protocol) => { + switch (protocol) { + case 'rtc': + return strategy_2.RTCInfo; + case 'classic': + return strategy_1.ClassicInfo; + default: + return (0, exhaustive_1.exhaustiveCheck)(protocol, ['rtc', 'classic']); + } + }); + } + constructor(wire) { + super(wire); + _ConnectionManager_messageReceiver.set(this, void 0); + _ConnectionManager_rtcConnectionManager.set(this, void 0); + this.removeChannelFromProviderMap = (channelId) => { + this.providerMap.delete(channelId); + }; + this.onmessage = (msg) => { + if (msg.action === 'process-channel-connection') { + this.processChannelConnection(msg); + return true; + } + return false; + }; + this.providerMap = new Map(); + this.protocolManager = new protocol_manager_1.ProtocolManager(this.wire.environment.type === 'node' ? ['classic'] : ['rtc', 'classic']); + __classPrivateFieldSet$5(this, _ConnectionManager_messageReceiver, new message_receiver_1.MessageReceiver(wire), "f"); + __classPrivateFieldSet$5(this, _ConnectionManager_rtcConnectionManager, new ice_manager_1.RTCICEManager(wire), "f"); + wire.registerMessageHandler(this.onmessage.bind(this)); + } + createProvider(options, providerIdentity) { + const opts = Object.assign(this.wire.environment.getDefaultChannelOptions().create, options || {}); + const protocols = this.protocolManager.getProviderProtocols(opts?.protocols); + const createSingleStrategy = (stratType) => { + switch (stratType) { + case 'rtc': + return new strategy_2.RTCStrategy(); + case 'classic': + return new strategy_1.ClassicStrategy(this.wire, __classPrivateFieldGet$7(this, _ConnectionManager_messageReceiver, "f"), + // Providers do not have an endpointId, use channelId as endpointId in the strategy. + providerIdentity.channelId, providerIdentity); + default: + return (0, exhaustive_1.exhaustiveCheck)(stratType, ['rtc', 'classic']); + } + }; + const strategies = protocols.map(createSingleStrategy); + let strategy; + if (strategies.length === 2) { + const [a, b] = strategies; + strategy = strategy_3.default.combine(a, b); + } + else if (strategies.length === 1) { + [strategy] = strategies; + } + else { + // Should be impossible. + throw new Error('failed to combine strategies'); + } + const channel = new provider_1$1.ChannelProvider(providerIdentity, () => provider_1$1.ChannelProvider.wireClose(this.wire, providerIdentity.channelName), strategy); + const key = providerIdentity.channelId; + this.providerMap.set(key, { + provider: channel, + strategy, + supportedProtocols: ConnectionManager.getProtocolOptionsFromStrings(protocols) + }); + provider_1$1.ChannelProvider.setProviderRemoval(channel, this.removeChannelFromProviderMap.bind(this)); + return channel; + } + async createClientOffer(options) { + const protocols = this.protocolManager.getClientProtocols(options?.protocols); + let rtcPacket; + const supportedProtocols = await Promise.all(protocols.map(async (type) => { + switch (type) { + case 'rtc': { + const { rtcClient, channels, offer, rtcConnectionId, channelsOpened } = await __classPrivateFieldGet$7(this, _ConnectionManager_rtcConnectionManager, "f").startClientOffer(); + rtcPacket = { rtcClient, channels, channelsOpened }; + return { + type: 'rtc', + version: strategy_2.RTCInfo.version, + payload: { offer, rtcConnectionId } + }; + } + case 'classic': + return { type: 'classic', version: strategy_1.ClassicInfo.version }; + default: + return (0, exhaustive_1.exhaustiveCheck)(type, ['rtc', 'classic']); + } + })); + return { + offer: { + supportedProtocols, + maxProtocols: 2 + }, + rtc: rtcPacket + }; + } + async createClientStrategy(rtcPacket, routingInfo) { + if (!routingInfo.endpointId) { + routingInfo.endpointId = this.wire.environment.getNextMessageId(); + // For New Clients connecting to Old Providers. To prevent multi-dispatching and publishing, we delete previously-connected + // clients that are in the same context as the newly-connected client. + __classPrivateFieldGet$7(this, _ConnectionManager_messageReceiver, "f").checkForPreviousClientConnection(routingInfo.channelId); + } + const answer = routingInfo.answer ?? { + supportedProtocols: [{ type: 'classic', version: 1 }] + }; + const createStrategyFromAnswer = async (protocol) => { + if (protocol.type === 'rtc' && rtcPacket) { + await __classPrivateFieldGet$7(this, _ConnectionManager_rtcConnectionManager, "f").finishClientOffer(rtcPacket.rtcClient, protocol.payload.answer, rtcPacket.channelsOpened); + return new strategy_2.RTCStrategy(); + } + if (protocol.type === 'classic') { + return new strategy_1.ClassicStrategy(this.wire, __classPrivateFieldGet$7(this, _ConnectionManager_messageReceiver, "f"), routingInfo.endpointId, routingInfo); + } + return null; + }; + const allProtocols = (await Promise.all(answer.supportedProtocols.map(createStrategyFromAnswer))).filter((x) => x !== null); + // Clean up logic if provider didn't support rtc. + if (rtcPacket && !allProtocols.some((x) => x instanceof strategy_2.RTCStrategy)) { + if (rtcPacket) { + rtcPacket.rtcClient.close(); + } + } + let strategy; + if (allProtocols.length >= 2) { + strategy = strategy_3.default.combine(allProtocols[0], allProtocols[1]); + } + else if (allProtocols.length) { + [strategy] = allProtocols; + } + else { + // Should be impossible. + throw new Error('No compatible protocols'); + } + // as casting rtcPacket because we won't have an rtcStrategy if rtcPacket is undefined; + const endpointPayload = { endpointIdentity: routingInfo, rtc: rtcPacket }; + strategy.addEndpoint(routingInfo.channelId, endpointPayload); + return strategy; + } + async processChannelConnection(msg) { + const { clientIdentity, providerIdentity, ackToSender, payload, offer: clientOffer } = msg.payload; + if (!clientIdentity.endpointId) { + // Should be polyfilled by core but not in cases of node connecting to an old runtime. + clientIdentity.endpointId = this.wire.environment.getNextMessageId(); + clientIdentity.isLocalEndpointId = true; + } + else { + clientIdentity.isLocalEndpointId = false; + } + const key = providerIdentity.channelId; + const bus = this.providerMap.get(key); + if (!bus) { + ackToSender.payload.success = false; + ackToSender.payload.reason = `Channel "${providerIdentity.channelName}" has been destroyed.`; + return this.wire.sendRaw(ackToSender); + } + const { provider, strategy, supportedProtocols } = bus; + try { + if (!(provider instanceof provider_1$1.ChannelProvider)) { + throw Error('Cannot connect to a channel client'); + } + const offer = clientOffer ?? { + supportedProtocols: [{ type: 'classic', version: 1 }], + maxProtocols: 1 + }; + const overlappingProtocols = this.protocolManager.getCompatibleProtocols(supportedProtocols, offer); + if (!overlappingProtocols.length) { + throw new Error('This provider does not support any of the offered protocols.'); + } + const res = await provider.processConnection(clientIdentity, payload); + ackToSender.payload.payload = ackToSender.payload.payload || {}; + // Loop through all supported protocols and accumulate them into the answer + // addEndpoint is tricky but we need to wait for channel resolution before adding the endpoint. + let clientAnswer = { + supportedProtocols: [], + endpointPayloadPromise: Promise.resolve({ endpointIdentity: clientIdentity }) + }; + clientAnswer = await overlappingProtocols.reduce(async (accumP, protocolToUse) => { + const answer = await accumP; + if (protocolToUse.type === 'rtc') { + const { answer: rtcAnswer, rtcClient, channels } = await __classPrivateFieldGet$7(this, _ConnectionManager_rtcConnectionManager, "f").createProviderAnswer(protocolToUse.payload.rtcConnectionId, protocolToUse.payload.offer); + answer.supportedProtocols.push({ + type: 'rtc', + version: strategy_2.RTCInfo.version, + payload: { + answer: rtcAnswer + } + }); + answer.endpointPayloadPromise = answer.endpointPayloadPromise.then((endpointPayload) => channels.then((resolvedChannels) => { + return { + ...endpointPayload, + rtc: { + rtcClient, + channels: resolvedChannels + } + }; + })); + } + else { + answer.supportedProtocols.push({ type: 'classic', version: strategy_1.ClassicInfo.version }); + } + return answer; + }, Promise.resolve(clientAnswer)); + // Need to as cast here. + clientAnswer.endpointPayloadPromise.then((endpointPayload) => strategy.addEndpoint(clientIdentity.endpointId, endpointPayload)); + ackToSender.payload.payload.result = res; + ackToSender.payload.payload.answer = clientAnswer; + return this.wire.sendRaw(ackToSender); + } + catch (e) { + ackToSender.payload.success = false; + ackToSender.payload.reason = e.message; + return this.wire.sendRaw(ackToSender); + } + } +} +connectionManager.ConnectionManager = ConnectionManager; +_ConnectionManager_messageReceiver = new WeakMap(), _ConnectionManager_rtcConnectionManager = new WeakMap(); + +/** + * Entry points for the `Channel` subset of the `InterApplicationBus` API (`fin.InterApplicationBus.Channel`). + * + * * {@link Channel} contains static members of the `Channel` API, accessible through `fin.InterApplicationBus.Channel`. + * * {@link OpenFin.ChannelClient} describes a client of a channel, e.g. as returned by `fin.InterApplicationBus.Channel.connect`. + * * {@link OpenFin.ChannelProvider} describes a provider of a channel, e.g. as returned by `fin.InterApplicationBus.Channel.create`. + * + * @packageDocumentation + */ +var __classPrivateFieldSet$4 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$6 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _Channel_connectionManager, _Channel_internalEmitter, _Channel_readyToConnect; +Object.defineProperty(channel$1, "__esModule", { value: true }); +channel$1.Channel = void 0; +/* eslint-disable no-console */ +const events_1$5 = require$$0; +const lazy_1$1 = lazy; +const base_1$e = base; +const client_1 = client; +const connection_manager_1 = connectionManager; +const provider_1 = provider; +function retryDelay(count) { + const interval = 500; // base delay + const steps = 10; // How many retries to do before incrementing the delay + const base = 2; // How much to multiply the previous delay by + const max = 30000; // max delay + const step = Math.floor(count / steps); + const delay = Math.min(max, interval * base ** step); + return new Promise((resolve) => { + setTimeout(() => { + resolve(false); + }, delay); + }); +} +/** + * The Channel API allows an OpenFin application to create a channel as a {@link ChannelProvider ChannelProvider}, + * or connect to a channel as a {@link ChannelClient ChannelClient}. + * @remarks The "handshake" between the communication partners is + * simplified when using a channel. A request to connect to a channel as a client will return a promise that resolves if/when the channel has been created. Both the + * provider and client can dispatch actions that have been registered on their opposites, and dispatch returns a promise that resolves with a payload from the other + * communication participant. There can be only one provider per channel, but many clients. Version `9.61.35.*` or later is required for both communication partners. + * + * Asynchronous Methods: + * * {@link Channel.create create(channelName, options)} + * * {@link Channel.connect connect(channelName, options)} + * * {@link Channel.onChannelConnect onChannelConnect(listener)} + * * {@link Channel.onChannelDisconnect onChannelDisconnect(listener)} + */ +class Channel extends base_1$e.EmitterBase { + /** + * @internal + */ + constructor(wire) { + super(wire, 'channel'); + _Channel_connectionManager.set(this, void 0); + _Channel_internalEmitter.set(this, new events_1$5.EventEmitter()); + // OpenFin API has not been injected at construction time, *must* wait for API to be ready. + _Channel_readyToConnect.set(this, new lazy_1$1.AsyncRetryableLazy(async () => { + await Promise.all([ + this.on('disconnected', (eventPayload) => { + client_1.ChannelClient.handleProviderDisconnect(eventPayload); + }), + this.on('connected', (...args) => { + __classPrivateFieldGet$6(this, _Channel_internalEmitter, "f").emit('connected', ...args); + }) + ]).catch(() => new Error('error setting up channel connection listeners')); + })); + __classPrivateFieldSet$4(this, _Channel_connectionManager, new connection_manager_1.ConnectionManager(wire), "f"); + } + /** + * + * @internal + */ + async getAllChannels() { + return this.wire.sendAction('get-all-channels').then(({ payload }) => payload.data); + } + /** + * Listens for channel connections. + * + * @param listener - callback to execute. + * + * @example + * + * ```js + * const listener = (channelPayload) => console.log(channelPayload); // see return value below + * + * fin.InterApplicationBus.Channel.onChannelConnect(listener); + * + * // example shape + * { + * "topic": "channel", + * "type": "connected", + * "uuid": "OpenfinPOC", + * "name": "OpenfinPOC", + * "channelName": "counter", + * "channelId": "OpenfinPOC/OpenfinPOC/counter" + * } + * + * ``` + */ + async onChannelConnect(listener) { + await this.on('connected', listener); + } + /** + * Listen for channel disconnections. + * + * @param listener - callback to execute. + * + * @example + * + * ```js + * const listener = (channelPayload) => console.log(channelPayload); // see return value below + * + * fin.InterApplicationBus.Channel.onChannelDisconnect(listener); + * + * // example shape + * { + * "topic": "channel", + * "type": "disconnected", + * "uuid": "OpenfinPOC", + * "name": "OpenfinPOC", + * "channelName": "counter", + * "channelId": "OpenfinPOC/OpenfinPOC/counter" + * } + * + * ``` + */ + async onChannelDisconnect(listener) { + await this.on('disconnected', listener); + } + async safeConnect(channelName, shouldWait, connectPayload) { + const retryInfo = { count: 0 }; + /* eslint-disable no-await-in-loop, no-constant-condition */ + do { + // setup a listener and a connected promise to await in case we connect before the channel is ready + let connectedListener = () => undefined; + const connectedPromise = new Promise((resolve) => { + connectedListener = (payload) => { + if (channelName === payload.channelName) { + resolve(true); + } + }; + __classPrivateFieldGet$6(this, _Channel_internalEmitter, "f").on('connected', connectedListener); + }); + try { + if (retryInfo.count > 0) { + // Wait before retrying + // Delay returns false connectedPromise returns true so we can know if a retry is due to connected event + retryInfo.gotConnectedEvent = await Promise.race([retryDelay(retryInfo.count), connectedPromise]); + const result = await this.wire.sendAction('connect-to-channel', { ...connectPayload, retryInfo }); + // log only if there was a retry + console.log(`Successfully connected to channelName: ${channelName}`); + return result.payload.data; + } + // Send retryInfo to the core for debug log inclusion + const sentMessagePromise = this.wire.sendAction('connect-to-channel', connectPayload); + // Save messageId from the first connection attempt + retryInfo.originalMessageId = sentMessagePromise.messageId; + const result = await sentMessagePromise; + return result.payload.data; + } + catch (error) { + if (!error.message.includes('internal-nack')) { + // Not an internal nack, break the loop + throw error; + } + if (shouldWait && retryInfo.count === 0) { + // start waiting on the next iteration, warn the user + console.warn(`No channel found for channelName: ${channelName}. Waiting for connection...`); + } + } + finally { + retryInfo.count += 1; + // in case of other errors, remove our listener + __classPrivateFieldGet$6(this, _Channel_internalEmitter, "f").removeListener('connected', connectedListener); + } + } while (shouldWait); // If we're waiting we retry the above loop + // Should wait was false, no channel was found. + throw new Error(`No channel found for channelName: ${channelName}.`); + /* eslint-enable no-await-in-loop, no-constant-condition */ + } + /** + * Connect to a channel. If you wish to send a payload to the provider, add a payload property to the options argument. + * EXPERIMENTAL: pass { protocols: ['rtc'] } as options to opt-in to High Throughput Channels. + * + * @param channelName - Name of the target channel. + * @param options - Connection options. + * @returns Returns a promise that resolves with an instance of {@link ChannelClient ChannelClient}. + * + * @remarks The connection request will be routed to the channelProvider if/when the channel is created. If the connect + * request is sent prior to creation, the promise will not resolve or reject until the channel is created by a channelProvider + * (whether or not to wait for creation is configurable in the connectOptions). + * + * The connect call returns a promise that will resolve with a channelClient bus if accepted by the channelProvider, or reject if + * the channelProvider throws an error to reject the connection. This bus can communicate with the Provider, but not to other + * clients on the channel. Using the bus, the channelClient can register actions and middleware. Channel lifecycle can also be + * handled with an onDisconnection listener. + * + * @example + * + * ```js + * async function makeClient(channelName) { + * // A payload can be sent along with channel connection requests to help with authentication + * const connectPayload = { payload: 'token' }; + * + * // If the channel has been created this request will be sent to the provider. If not, the + * // promise will not be resolved or rejected until the channel has been created. + * const clientBus = await fin.InterApplicationBus.Channel.connect(channelName, connectPayload); + * + * clientBus.onDisconnection(channelInfo => { + * // handle the channel lifecycle here - we can connect again which will return a promise + * // that will resolve if/when the channel is re-created. + * makeClient(channelInfo.channelName); + * }) + * + * clientBus.register('topic', (payload, identity) => { + * // register a callback for a topic to which the channel provider can dispatch an action + * console.log('Action dispatched by provider: ', JSON.stringify(identity)); + * console.log('Payload sent in dispatch: ', JSON.stringify(payload)); + * return { + * echo: payload + * }; + * }); + * } + * + * makeClient('channelName') + * .then(() => console.log('Connected')) + * .catch(console.error); + * ``` + */ + async connect(channelName, options = {}) { + // Make sure we don't connect before listeners are set up + // This also errors if we're not in OpenFin, ensuring we don't run unnecessary code + await __classPrivateFieldGet$6(this, _Channel_readyToConnect, "f").getValue(); + if (!channelName || typeof channelName !== 'string') { + throw new Error('Please provide a channelName string to connect to a channel.'); + } + const opts = { wait: true, ...this.wire.environment.getDefaultChannelOptions().connect, ...options }; + const { offer, rtc: rtcPacket } = await __classPrivateFieldGet$6(this, _Channel_connectionManager, "f").createClientOffer(opts); + let connectionUrl; + if (this.fin.me.isFrame || this.fin.me.isView || this.fin.me.isWindow) { + connectionUrl = (await this.fin.me.getInfo()).url; + } + const connectPayload = { + channelName, + ...opts, + offer, + connectionUrl + }; + const routingInfo = await this.safeConnect(channelName, opts.wait, connectPayload); + const strategy = await __classPrivateFieldGet$6(this, _Channel_connectionManager, "f").createClientStrategy(rtcPacket, routingInfo); + const channel = new client_1.ChannelClient(routingInfo, () => client_1.ChannelClient.wireClose(this.wire, routingInfo, routingInfo.endpointId), strategy); + // It is the client's responsibility to handle endpoint disconnection to the provider. + // If the endpoint dies, the client will force a disconnection through the core. + // The provider does not care about endpoint disconnection. + strategy.onEndpointDisconnect(routingInfo.channelId, async () => { + try { + await channel.sendDisconnectAction(); + } + catch (error) { + console.warn(`Something went wrong during disconnect for client with uuid: ${routingInfo.uuid} / name: ${routingInfo.name} / endpointId: ${routingInfo.endpointId}.`); + } + finally { + client_1.ChannelClient.handleProviderDisconnect(routingInfo); + } + }); + return channel; + } + /** + * Create a new channel. + * You must provide a unique channelName. If a channelName is not provided, or it is not unique, the creation will fail. + * EXPERIMENTAL: pass { protocols: ['rtc'] } as options to opt-in to High Throughput Channels. + * + * @param channelName - Name of the channel to be created. + * @param options - Creation options. + * @returns Returns a promise that resolves with an instance of {@link ChannelProvider ChannelProvider}. + * + * @remarks If successful, the create method returns a promise that resolves to an instance of the channelProvider bus. The caller + * then becomes the “channel provider” and can use the channelProvider bus to register actions and middleware. + * + * The caller can also set an onConnection and/or onDisconnection listener that will execute on any new channel + * connection/disconnection attempt from a channel client. To reject a connection, simply throw an error in the + * onConnection listener. The default behavior is to accept all new connections. + * + * A map of client connections is updated automatically on client connection and disconnection and saved in the + * [read-only] `connections` property on the channelProvider bus. The channel will exist until the provider + * destroys it or disconnects by closing or destroying the context (navigating or reloading). To setup a channel + * as a channelProvider, call `Channel.create` with a unique channel name. A map of client connections is updated + * automatically on client connection and disconnection. + * + * @example + * + * ```js + * (async ()=> { + * // entity creates a channel and becomes the channelProvider + * const providerBus = await fin.InterApplicationBus.Channel.create('channelName'); + * + * providerBus.onConnection((identity, payload) => { + * // can reject a connection here by throwing an error + * console.log('Client connection request identity: ', JSON.stringify(identity)); + * console.log('Client connection request payload: ', JSON.stringify(payload)); + * }); + * + * providerBus.register('topic', (payload, identity) => { + * // register a callback for a 'topic' to which clients can dispatch an action + * console.log('Action dispatched by client: ', JSON.stringify(identity)); + * console.log('Payload sent in dispatch: ', JSON.stringify(payload)); + * return { + * echo: payload + * }; + * }); + * })(); + * ``` + */ + async create(channelName, options) { + if (!channelName) { + throw new Error('Please provide a channelName to create a channel'); + } + const { payload: { data: providerIdentity } } = await this.wire.sendAction('create-channel', { channelName }); + const channel = __classPrivateFieldGet$6(this, _Channel_connectionManager, "f").createProvider(options, providerIdentity); + // TODO: fix typing (internal) + // @ts-expect-error + this.on('client-disconnected', (eventPayload) => { + if (eventPayload.channelName === channelName) { + provider_1.ChannelProvider.handleClientDisconnection(channel, eventPayload); + } + }); + return channel; + } +} +channel$1.Channel = Channel; +_Channel_connectionManager = new WeakMap(), _Channel_internalEmitter = new WeakMap(), _Channel_readyToConnect = new WeakMap(); + +Object.defineProperty(interappbus, "__esModule", { value: true }); +interappbus.InterAppPayload = interappbus.InterApplicationBus = void 0; +/** + * Entry point for the OpenFin `InterApplicationBus` API (`fin.InterApplicationBus`). + * + * * {@link InterApplicationBus} contains static members of the `InterApplicationBus` API, accessible through `fin.InterApplicationBus`. + * + * @packageDocumentation + */ +const events_1$4 = require$$0; +const base_1$d = base; +const ref_counter_1 = refCounter; +const index_1$2 = channel$1; +const validate_1$3 = validate; +/** + * A messaging bus that allows for pub/sub messaging between different applications. + * + */ +class InterApplicationBus extends base_1$d.Base { + /** + * @internal + */ + constructor(wire) { + super(wire); + this.events = { + subscriberAdded: 'subscriber-added', + subscriberRemoved: 'subscriber-removed' + }; + this.refCounter = new ref_counter_1.RefCounter(); + this.Channel = new index_1$2.Channel(wire); + this.emitter = new events_1$4.EventEmitter(); + wire.registerMessageHandler(this.onmessage.bind(this)); + this.on = this.emitter.on.bind(this.emitter); + this.removeAllListeners = this.emitter.removeAllListeners.bind(this.emitter); + } + /** + * Publishes a message to all applications running on OpenFin Runtime that + * are subscribed to the specified topic. + * @param topic The topic on which the message is sent + * @param message The message to be published. Can be either a primitive + * data type (string, number, or boolean) or composite data type (object, array) + * that is composed of other primitive or composite data types + * + * @example + * ```js + * fin.InterApplicationBus.publish('topic', 'hello').then(() => console.log('Published')).catch(err => console.log(err)); + * ``` + */ + async publish(topic, message) { + await this.wire.sendAction('publish-message', { + topic, + message, + sourceWindowName: this.me.name + }); + } + /** + * Sends a message to a specific application on a specific topic. + * @param destination The identity of the application to which the message is sent + * @param topic The topic on which the message is sent + * @param message The message to be sent. Can be either a primitive data + * type (string, number, or boolean) or composite data type (object, array) that + * is composed of other primitive or composite data types + * + * @example + * ```js + * fin.InterApplicationBus.send(fin.me, 'topic', 'Hello there!').then(() => console.log('Message sent')).catch(err => console.log(err)); + * ``` + */ + async send(destination, topic, message) { + const errorMsg = (0, validate_1$3.validateIdentity)(destination); + if (errorMsg) { + throw new Error(errorMsg); + } + await this.wire.sendAction('send-message', { + destinationUuid: destination.uuid, + destinationWindowName: destination.name, + topic, + message, + sourceWindowName: this.me.name + }); + } + /** + * Subscribes to messages from the specified application on the specified topic. + * @param source This object is described in the Identity in the typedef + * @param topic The topic on which the message is sent + * @param listener A function that is called when a message has + * been received. It is passed the message, uuid and name of the sending application. + * The message can be either a primitive data type (string, number, or boolean) or + * composite data type (object, array) that is composed of other primitive or composite + * data types + * + * @example + * ```js + * // subscribe to a specified application + * fin.InterApplicationBus.subscribe(fin.me, 'topic', sub_msg => console.log(sub_msg)).then(() => console.log('Subscribed to the specified application')).catch(err => console.log(err)); + * + * // subscribe to wildcard + * fin.InterApplicationBus.subscribe({ uuid: '*' }, 'topic', sub_msg => console.log(sub_msg)).then(() => console.log('Subscribed to *')).catch(err => console.log(err)); + * ``` + */ + subscribe(source, topic, listener) { + const subKey = this.createSubscriptionKey(source.uuid, source.name || '*', topic); + const sendSubscription = async () => { + await this.wire.sendAction('subscribe', { + sourceUuid: source.uuid, + sourceWindowName: source.name || '*', + topic, + destinationWindowName: this.me.name + }); + }; + const alreadySubscribed = () => { + return Promise.resolve(); + }; + this.emitter.on(subKey, listener); + return this.refCounter.actOnFirst(subKey, sendSubscription, alreadySubscribed); + } + /** + * Unsubscribes to messages from the specified application on the specified topic. + * + * @remarks If you are listening to all apps on a topic, (i.e you passed `{ uuid:'*' }` to the subscribe function) + * then you need to pass `{ uuid:'*' }` to unsubscribe as well. If you are listening to a specific application, + * (i.e you passed `{ uuid:'some_app' }` to the subscribe function) then you need to provide the same identifier to + * unsubscribe, unsubscribing to `*` on that same topic will not unhook your initial listener otherwise. + * + * @param source This object is described in the Identity in the typedef + * @param topic The topic on which the message is sent + * @param listener A callback previously registered with subscribe() + * + * @example + * ```js + * const listener = console.log; + * + * // If any application publishes a message on topic `foo`, our listener will be called. + * await fin.InterApplicationBus.subscribe({ uuid:'*' }, 'foo', listener) + * + * // When you want to unsubscribe, you need to specify the uuid of the app you'd like to + * // unsubscribe from (or `*`) and provide the same function you gave the subscribe function + * await fin.InterApplicationBus.unsubscribe({ uuid:'*' }, 'foo', listener) + * ``` + */ + unsubscribe(source, topic, listener) { + const sourceWindowName = source.name || '*'; + const subKey = this.createSubscriptionKey(source.uuid, sourceWindowName, topic); + const sendUnsubscription = async () => { + await this.wire.sendAction('unsubscribe', { + sourceUuid: source.uuid, + sourceWindowName, + topic, + destinationWindowName: this.me.name + }); + }; + const dontSendUnsubscription = () => { + return new Promise((r) => r).then(() => undefined); + }; + this.emitter.removeListener(subKey, listener); + return this.refCounter.actOnLast(subKey, sendUnsubscription, dontSendUnsubscription); + } + processMessage(message) { + const { payload: { message: payloadMessage, sourceWindowName, sourceUuid, topic } } = message; + const keys = [ + this.createSubscriptionKey(sourceUuid, sourceWindowName, topic), + this.createSubscriptionKey(sourceUuid, '*', topic), + this.createSubscriptionKey('*', '*', topic) + ]; + const idOfSender = { uuid: sourceUuid, name: sourceWindowName }; + keys.forEach((key) => { + this.emitter.emit(key, payloadMessage, idOfSender); + }); + } + emitSubscriverEvent(type, message) { + const { payload: { targetName: name, uuid, topic } } = message; + const payload = { name, uuid, topic }; + this.emitter.emit(type, payload); + } + // eslint-disable-next-line class-methods-use-this + createSubscriptionKey(uuid, name, topic) { + const n = name || '*'; + if (!(uuid && n && topic)) { + throw new Error('Missing uuid, name, or topic string'); + } + return createKey(uuid, n, topic); + } + onmessage(message) { + const { action } = message; + switch (action) { + case 'process-message': + this.processMessage(message); + break; + case this.events.subscriberAdded: + this.emitSubscriverEvent(this.events.subscriberAdded, message); + break; + case this.events.subscriberRemoved: + this.emitSubscriverEvent(this.events.subscriberRemoved, message); + break; + } + return true; + } +} +interappbus.InterApplicationBus = InterApplicationBus; +/** + * @internal + */ +class InterAppPayload { +} +interappbus.InterAppPayload = InterAppPayload; +function createKey(...toHash) { + return toHash + .map((item) => { + return Buffer.from(`${item}`).toString('base64'); + }) + .join('/'); +} + +var clipboard = {}; + +/** + * Entry point for the OpenFin `Clipboard` API (`fin.Clipboard`). + * + * * {@link Clipboard} contains static members of the `Clipboard` API, accessible through `fin.Clipboard`. + * + * @packageDocumentation + */ +Object.defineProperty(clipboard, "__esModule", { value: true }); +clipboard.Clipboard = void 0; +const base_1$c = base; +/** + * The Clipboard API allows reading and writing to the clipboard in multiple formats. + * + */ +class Clipboard extends base_1$c.Base { + /** + * Writes data into the clipboard as plain text + * @param writeObj The object for writing data into the clipboard + * + * @example + * ```js + * fin.Clipboard.writeText({ + * data: 'hello, world' + * }).then(() => console.log('Text On clipboard')).catch(err => console.log(err)); + * ``` + */ + async writeText(writeObj) { + await this.wire.sendAction('clipboard-write-text', writeObj); + } + /** + * Read the content of the clipboard as plain text + * @param type Clipboard Type defaults to 'clipboard', use 'selection' for linux + * + * @example + * ```js + * fin.Clipboard.readText().then(text => console.log(text)).catch(err => console.log(err)); + * ``` + */ + async readText(type) { + // NOTE: When we start supporting linux, we could detect the OS and choose 'selection' automatically for the user + const { payload } = await this.wire.sendAction('clipboard-read-text', { type }); + return payload.data; + } + /** + * Writes data into the clipboard as an Image + * @param writeRequest The object to write an image to the clipboard + * + * @example + * ```js + * fin.Clipboard.writeImage({ + * // raw base64 string, or dataURL of either data:image/png or data:image/jpeg type + * image: '...' + * }).then(() => console.log('Image written to clipboard')).catch(err => console.log(err)); + * ``` + */ + async writeImage(writeRequest) { + await this.wire.sendAction('clipboard-write-image', writeRequest); + } + /** + * Read the content of the clipboard as a base64 string or a dataURL based on the input parameter 'format', defaults to 'dataURL' + * @param readRequest Clipboard Read Image request with formatting options + * + * @example + * ```js + * // see TS type: OpenFin.ImageFormatOptions + * + * const pngOrDataURLOrBmpOptions = { + * format: 'png', // can be: 'png' | 'dataURL' | 'bmp' + * }; + * + * const jpgOptions = { + * format: 'jpg', + * quality: 80 // optional, if omitted defaults to 100 + * }; + * + * fin.Clipboard.readImage(pngOrDataURLOrBmpOptions) + * .then(image => console.log('Image read from clipboard as PNG, DataURL or BMP', image)) + * .catch(err => console.log(err)); + * + * fin.Clipboard.readImage(jpgOptions) + * .then(image => console.log('Image read from clipboard as JPG', image)) + * .catch(err => console.log(err)); + * + * // defaults to {format: 'dataURL'} + * fin.Clipboard.readImage() + * .then(image => console.log('Image read from clipboard as DataURL', image)) + * .catch(err => console.log(err)); + * + * ``` + */ + async readImage(readRequest = { format: 'dataURL' }) { + const { payload } = await this.wire.sendAction('clipboard-read-image', readRequest); + return payload.data; + } + /** + * Writes data into the clipboard as Html + * @param writeObj The object for writing data into the clipboard + * + * @example + * ```js + * fin.Clipboard.writeHtml({ + * data: '

Hello, World!

' + * }).then(() => console.log('HTML On clipboard')).catch(err => console.log(err)); + * ``` + */ + async writeHtml(writeObj) { + await this.wire.sendAction('clipboard-write-html', writeObj); + } + /** + * Read the content of the clipboard as Html + * @param type Clipboard Type defaults to 'clipboard', use 'selection' for linux + * + * @example + * ```js + * fin.Clipboard.readHtml().then(html => console.log(html)).catch(err => console.log(err)); + * ``` + */ + async readHtml(type) { + const { payload } = await this.wire.sendAction('clipboard-read-html', { type }); + return payload.data; + } + /** + * Writes data into the clipboard as Rtf + * @param writeObj The object for writing data into the clipboard + * + * @example + * ```js + * fin.Clipboard.writeRtf({ + * data: 'some text goes here' + * }).then(() => console.log('RTF On clipboard')).catch(err => console.log(err)); + * ``` + */ + async writeRtf(writeObj) { + await this.wire.sendAction('clipboard-write-rtf', writeObj); + } + /** + * Read the content of the clipboard as Rtf + * @param type Clipboard Type defaults to 'clipboard', use 'selection' for linux + * + * @example + * + * ```js + * const writeObj = { + * data: 'some text goes here' + * }; + * async function readRtf() { + * await fin.Clipboard.writeRtf(writeObj); + * return await fin.Clipboard.readRtf(); + * } + * readRtf().then(rtf => console.log(rtf)).catch(err => console.log(err)); + * ``` + */ + async readRtf(type) { + const { payload } = await this.wire.sendAction('clipboard-read-rtf', { type }); + return payload.data; + } + /** + * Writes data into the clipboard + * @param writeObj The object for writing data into the clipboard + * + * @example + * ```js + * fin.Clipboard.write({ + * data: { + * text: 'a', + * html: 'b', + * rtf: 'c', + * // Can be either a base64 string, or a DataURL string. If using DataURL, the + * // supported formats are `data:image/png[;base64],` and `data:image/jpeg[;base64],`. + * // Using other image/ DataURLs will throw an Error. + * image: '...' + * } + * }).then(() => console.log('write data into clipboard')).catch(err => console.log(err)); + * ``` + */ + async write(writeObj) { + await this.wire.sendAction('clipboard-write', writeObj); + } + /** + * Reads available formats for the clipboard type + * @param type Clipboard Type defaults to 'clipboard', use 'selection' for linux + * + * @example + * ```js + * fin.Clipboard.getAvailableFormats().then(formats => console.log(formats)).catch(err => console.log(err)); + * ``` + */ + async getAvailableFormats(type) { + const { payload } = await this.wire.sendAction('clipboard-read-formats', { type }); + return payload.data; + } +} +clipboard.Clipboard = Clipboard; + +var externalApplication = {}; + +var Factory$5 = {}; + +var Instance$4 = {}; + +Object.defineProperty(Instance$4, "__esModule", { value: true }); +Instance$4.ExternalApplication = void 0; +/* eslint-disable import/prefer-default-export */ +const base_1$b = base; +/** + * An ExternalApplication object representing native language adapter connections to the runtime. Allows + * the developer to listen to {@link OpenFin.ExternalApplicationEvents external application events}. + * Discovery of connections is provided by {@link System.System.getAllExternalApplications getAllExternalApplications}. + * + * Processes that can be wrapped as `ExternalApplication`s include the following: + * - Processes which have connected to an OpenFin runtime via an adapter + * - Processes started via `System.launchExternalApplication` + * - Processes monitored via `System.monitorExternalProcess` + */ +class ExternalApplication extends base_1$b.EmitterBase { + /** + * @internal + */ + constructor(wire, identity) { + super(wire, 'external-application', identity.uuid); + this.identity = identity; + } + /** + * Retrieves information about the external application. + * + * @example + * ```js + * async function getInfo() { + * const extApp = await fin.ExternalApplication.wrap('javaApp-uuid'); + * return await extApp.getInfo(); + * } + * getInfo().then(info => console.log(info)).catch(err => console.log(err)); + * ``` + */ + getInfo() { + return this.wire.sendAction('get-external-application-info', this.identity).then(({ payload }) => payload.data); + } +} +Instance$4.ExternalApplication = ExternalApplication; + +Object.defineProperty(Factory$5, "__esModule", { value: true }); +Factory$5.ExternalApplicationModule = void 0; +const base_1$a = base; +const Instance_1$4 = Instance$4; +/** + * Static namespace for OpenFin API methods that interact with the {@link ExternalApplication} class, available under `fin.ExternalApplication`. + */ +class ExternalApplicationModule extends base_1$a.Base { + /** + * Asynchronously returns an External Application object that represents an external application. + *
It is possible to wrap a process that does not yet exist, (for example, to listen for startup-related events) + * provided its uuid is already known. + * @param uuid The UUID of the external application to be wrapped + * + * @example + * ```js + * fin.ExternalApplication.wrap('javaApp-uuid'); + * .then(extApp => console.log('wrapped external application')) + * .catch(err => console.log(err)); + * ``` + */ + wrap(uuid) { + this.wire.sendAction('external-application-wrap').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return Promise.resolve(new Instance_1$4.ExternalApplication(this.wire, { uuid })); + } + /** + * Synchronously returns an External Application object that represents an external application. + *
It is possible to wrap a process that does not yet exist, (for example, to listen for startup-related events) + * provided its uuid is already known. + * @param uuid The UUID of the external application to be wrapped + * + * @example + * ```js + * const extApp = fin.ExternalApplication.wrapSync('javaApp-uuid'); + * const info = await extApp.getInfo(); + * console.log(info); + * ``` + */ + wrapSync(uuid) { + this.wire.sendAction('external-application-wrap-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return new Instance_1$4.ExternalApplication(this.wire, { uuid }); + } +} +Factory$5.ExternalApplicationModule = ExternalApplicationModule; + +(function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + /** + * Entry points for the OpenFin `ExternalApplication` API (`fin.ExternalApplication`). + * + * * {@link ExternalApplicationModule} contains static members of the `ExternalApplication` type, accessible through `fin.ExternalApplication`. + * * {@link ExternalApplication} describes an instance of an OpenFin ExternalApplication, e.g. as returned by `fin.ExternalApplication.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + */ + __exportStar(Factory$5, exports); + __exportStar(Instance$4, exports); +} (externalApplication)); + +var frame = {}; + +var Factory$4 = {}; + +var Instance$3 = {}; + +Object.defineProperty(Instance$3, "__esModule", { value: true }); +Instance$3._Frame = void 0; +/* eslint-disable import/prefer-default-export */ +const base_1$9 = base; +/** + * An iframe represents an embedded HTML page within a parent HTML page. Because this embedded page + * has its own DOM and global JS context (which may or may not be linked to that of the parent depending + * on if it is considered out of the root domain or not), it represents a unique endpoint as an OpenFin + * connection. Iframes may be generated dynamically, or be present on initial page load and each non-CORS + * iframe has the OpenFin API injected by default. It is possible to opt into cross-origin iframes having + * the API by setting api.iframe.crossOriginInjection to true in a window's options. To block all iframes + * from getting the API injected you can set api.frame.sameOriginInjection + * to false ({@link OpenFin.WindowCreationOptions see Window Options}). + * + * To be able to directly address this context for eventing and messaging purposes, it needs a + * unique uuid name pairing. For OpenFin applications and windows this is provided via a configuration + * object in the form of a manifest URL or options object, but there is no configuration object for iframes. + * Just as a call to window.open outside of our Window API returns a new window with a random GUID assigned + * for the name, each iframe that has the API injected will be assigned a GUID as its name, the UUID will be + * the same as the parent window's. + * + * The fin.Frame namespace represents a way to interact with `iframes` and facilitates the discovery of current context + * (iframe or main window) as well as the ability to listen for {@link OpenFin.FrameEvents frame-specific events}. + */ +class _Frame extends base_1$9.EmitterBase { + /** + * @internal + */ + constructor(wire, identity) { + super(wire, 'frame', identity.uuid, identity.name); + this.identity = identity; + } + /** + * Returns a frame info object for the represented frame. + * + * @example + * ```js + * async function getInfo() { + * const frm = await fin.Frame.getCurrent(); + * return await frm.getInfo(); + * } + * getInfo().then(info => console.log(info)).catch(err => console.log(err)); + * ``` + */ + getInfo() { + return this.wire.sendAction('get-frame-info', this.identity).then(({ payload }) => payload.data); + } + /** + * Returns a frame info object representing the window that the referenced iframe is + * currently embedded in. + * + * @remarks If the frame is embedded in a view, this will return an invalid stub with empty fields. + * + * @example + * ```js + * async function getParentWindow() { + * const frm = await fin.Frame.getCurrent(); + * return await frm.getParentWindow(); + * } + * getParentWindow().then(winInfo => console.log(winInfo)).catch(err => console.log(err)); + * ``` + */ + getParentWindow() { + return this.wire.sendAction('get-parent-window', this.identity).then(({ payload }) => payload.data); + } +} +Instance$3._Frame = _Frame; + +Object.defineProperty(Factory$4, "__esModule", { value: true }); +Factory$4._FrameModule = void 0; +const base_1$8 = base; +const validate_1$2 = validate; +const Instance_1$3 = Instance$3; +/** + * Static namespace for OpenFin API methods that interact with the {@link _Frame} class, available under `fin.Frame`. + */ +class _FrameModule extends base_1$8.Base { + /** + * Asynchronously returns an API handle for the given Frame identity. + * + * @remarks Wrapping a Frame identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a Frame throughout its entire lifecycle. + * + * @example + * ```js + * fin.Frame.wrap({ uuid: 'testFrame', name: 'testFrame' }) + * .then(frm => console.log('wrapped frame')) + * .catch(err => console.log(err)); + * ``` + */ + async wrap(identity) { + this.wire.sendAction('frame-wrap').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1$2.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1$3._Frame(this.wire, identity); + } + /** + * Synchronously returns an API handle for the given Frame identity. + * + * @remarks Wrapping a Frame identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a Frame throughout its entire lifecycle. + * + * @example + * ```js + * const frm = fin.Frame.wrapSync({ uuid: 'testFrame', name: 'testFrame' }); + * const info = await frm.getInfo(); + * console.log(info); + * ``` + */ + wrapSync(identity) { + this.wire.sendAction('frame-wrap-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1$2.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1$3._Frame(this.wire, identity); + } + /** + * Asynchronously returns a reference to the current frame + * + * @example + * ```js + * fin.Frame.getCurrent() + * .then(frm => console.log('current frame')) + * .catch(err => console.log(err)); + * ``` + */ + getCurrent() { + this.wire.sendAction('frame-get-current').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return Promise.resolve(new Instance_1$3._Frame(this.wire, this.wire.environment.getCurrentEntityIdentity())); + } + /** + * Synchronously returns a reference to the current frame + * + * @example + * ```js + * const frm = fin.Frame.getCurrentSync(); + * const info = await frm.getInfo(); + * console.log(info); + * ``` + */ + getCurrentSync() { + this.wire.sendAction('frame-get-current-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return new Instance_1$3._Frame(this.wire, this.wire.environment.getCurrentEntityIdentity()); + } +} +Factory$4._FrameModule = _FrameModule; + +(function (exports) { + /** + * Entry points for the OpenFin `Frame` API (`fin.Frame`). + * + * * {@link _FrameModule} contains static members of the `Frame` API, accessible through `fin.Frame`. + * * {@link _Frame} describes an instance of an OpenFin Frame, e.g. as returned by `fin.Frame.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * Underscore prefixing of OpenFin types that alias DOM entities will be fixed in a future version. + * + * @packageDocumentation + */ + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(Factory$4, exports); + __exportStar(Instance$3, exports); +} (frame)); + +var globalHotkey = {}; + +Object.defineProperty(globalHotkey, "__esModule", { value: true }); +globalHotkey.GlobalHotkey = void 0; +const base_1$7 = base; +/** + * The GlobalHotkey module can register/unregister a global hotkeys. + * + */ +class GlobalHotkey extends base_1$7.EmitterBase { + /** + * @internal + */ + constructor(wire) { + super(wire, 'global-hotkey'); + } + /** + * Registers a global hotkey with the operating system. + * @param hotkey a hotkey string + * @param listener called when the registered hotkey is pressed by the user. + * @throws If the `hotkey` is reserved, see list below. + * @throws if the `hotkey` is already registered by another application. + * + * @remarks The `hotkey` parameter expects an electron compatible [accelerator](https://github.com/electron/electron/blob/master/docs/api/accelerator.md) and the `listener` will be called if the `hotkey` is pressed by the user. + * If successfull, the hotkey will be 'claimed' by the application, meaning that this register call can be called multiple times from within the same application but will fail if another application has registered the hotkey. + *
The register call will fail if given any of these reserved Hotkeys: + * * `CommandOrControl+0` + * * `CommandOrControl+=` + * * `CommandOrControl+Plus` + * * `CommandOrControl+-` + * * `CommandOrControl+_` + * * `CommandOrControl+Shift+I` + * * `F5` + * * `CommandOrControl+R` + * * `Shift+F5` + * * `CommandOrControl+Shift+R` + * + * Raises the `registered` event. + * + * @example + * ```js + * const hotkey = 'CommandOrControl+X'; + * + * fin.GlobalHotkey.register(hotkey, () => { + * console.log(`${hotkey} pressed`); + * }) + * .then(() => { + * console.log('Success'); + * }) + * .catch(err => { + * console.log('Error registering the hotkey', err); + * }); + * ``` + */ + async register(hotkey, listener) { + // TODO: fix typing (hotkey events are not typed) + // @ts-expect-error + await this.on(hotkey, listener); + await this.wire.sendAction('global-hotkey-register', { hotkey }); + return undefined; + } + /** + * Unregisters a global hotkey with the operating system. + * @param hotkey a hotkey string + * + * @remarks This method will unregister all existing registrations of the hotkey within the application. + * Raises the `unregistered` event. + * + * @example + * ```js + * const hotkey = 'CommandOrControl+X'; + * + * fin.GlobalHotkey.unregister(hotkey) + * .then(() => { + * console.log('Success'); + * }) + * .catch(err => { + * console.log('Error unregistering the hotkey', err); + * }); + * ``` + */ + async unregister(hotkey) { + // TODO: fix typing (hotkey events are not typed) + // @ts-expect-error + await this.removeAllListeners(hotkey); + await this.wire.sendAction('global-hotkey-unregister', { hotkey }); + return undefined; + } + /** + * Unregisters all global hotkeys for the current application. + * + * @remarks Raises the `unregistered` event for each hotkey unregistered. + * + * @example + * ```js + * fin.GlobalHotkey.unregisterAll() + * .then(() => { + * console.log('Success'); + * }) + * .catch(err => { + * console.log('Error unregistering all hotkeys for this application', err); + * }); + * ``` + */ + async unregisterAll() { + await Promise.all(this.eventNames() + .filter((name) => !(name === 'registered' || name === 'unregistered')) + // TODO: fix typing (hotkey events are not typed) + // @ts-expect-error + .map((name) => this.removeAllListeners(name))); + await this.wire.sendAction('global-hotkey-unregister-all', {}); + return undefined; + } + /** + * Checks if a given hotkey has been registered by an application within the current runtime. + * @param hotkey a hotkey string + * + * @example + * ```js + * const hotkey = 'CommandOrControl+X'; + * + * fin.GlobalHotkey.isRegistered(hotkey) + * .then((registered) => { + * console.log(`hotkey ${hotkey} is registered ? ${registered}`); + * }) + * .catch(err => { + * console.log('Error unregistering the hotkey', err); + * }); + * ``` + */ + async isRegistered(hotkey) { + const { payload: { data } } = await this.wire.sendAction('global-hotkey-is-registered', { hotkey }); + return data; + } +} +globalHotkey.GlobalHotkey = GlobalHotkey; + +var platform = {}; + +var Factory$3 = {}; + +var Instance$2 = {}; + +var __classPrivateFieldGet$5 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _Platform_connectToProvider; +Object.defineProperty(Instance$2, "__esModule", { value: true }); +Instance$2.Platform = void 0; +/* eslint-disable import/prefer-default-export, no-undef */ +const base_1$6 = base; +const validate_1$1 = validate; +// Reuse clients to avoid overwriting already-registered client in provider +const clientMap = new Map(); +/** Manages the life cycle of windows and views in the application. + * + * Enables taking snapshots of itself and applying them to restore a previous configuration + * as well as listen to {@link OpenFin.PlatformEvents platform events}. + */ +class Platform extends base_1$6.EmitterBase { + /** + * @internal + */ + // eslint-disable-next-line no-shadow + constructor(identity, channel) { + // we piggyback off of application event emitter because from the core's perspective platform is just an app. + super(channel.wire, 'application', identity.uuid); + this.getClient = (identity) => { + this.wire.sendAction('platform-get-client', this.identity).catch((e) => { + // don't expose + }); + const target = identity || this.identity; + const { uuid } = target; + if (!clientMap.has(uuid)) { + const clientPromise = __classPrivateFieldGet$5(this, _Platform_connectToProvider, "f").call(this, uuid); + clientMap.set(uuid, clientPromise); + } + // we set it above + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return clientMap.get(uuid); + }; + _Platform_connectToProvider.set(this, async (uuid) => { + try { + const channelName = `custom-frame-${uuid}`; + const client = await this._channel.connect(channelName, { wait: false }); + client.onDisconnection(() => { + clientMap.delete(uuid); + }); + return client; + } + catch (e) { + clientMap.delete(uuid); + throw new Error('The targeted Platform is not currently running. Listen for application-started event for the given Uuid.'); + } + }); + /** + * @deprecated (renamed) + * @ignore + */ + this.launchLegacyManifest = this.launchContentManifest; + const errorMsg = (0, validate_1$1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + this._channel = channel; + this.identity = { uuid: identity.uuid }; + this.Layout = this.fin.Platform.Layout; + this.Application = this.fin.Application.wrapSync(this.identity); + } + /** + * Creates a new view and attaches it to a specified target window. + * @param viewOptions View creation options + * @param target The window to which the new view is to be attached. If no target, create a view in a new window. + * @param targetView If provided, the new view will be added to the same tabstrip as targetView. + * + * @remarks If the view already exists, will reparent the view to the new target. You do not need to set a name for a View. + * Views that are not passed a name get a randomly generated one. + * + * @example + * ```js + * let windowIdentity; + * if (fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const platform = fin.Platform.getCurrentSync(); + * + * platform.createView({ + * name: 'test_view', + * url: 'https://developers.openfin.co/docs/platform-api' + * }, windowIdentity).then(console.log); + * ``` + * + * Reparenting a view: + * ```js + * let windowIdentity; + * if (fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * let platform = fin.Platform.getCurrentSync(); + * let viewOptions = { + * name: 'example_view', + * url: 'https://example.com' + * }; + * // a new view will now show in the current window + * await platform.createView(viewOptions, windowIdentity); + * + * const view = fin.View.wrapSync({ uuid: windowIdentity.uuid, name: 'yahoo_view' }); + * // reparent `example_view` when a view in the new window is shown + * view.on('shown', async () => { + * let viewIdentity = { uuid: windowIdentity.uuid, name: 'example_view'}; + * let target = {uuid: windowIdentity.uuid, name: 'test_win'}; + * platform.createView(viewOptions, target); + * }); + * + * // create a new window + * await platform.createWindow({ + * name: "test_win", + * layout: { + * content: [ + * { + * type: 'stack', + * content: [ + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'yahoo_view', + * url: 'https://yahoo.com' + * } + * } + * ] + * } + * ] + * } + * }).then(console.log); + * ``` + */ + async createView(viewOptions, target, targetView) { + this.wire.sendAction('platform-create-view', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + const response = await client.dispatch('create-view', { + target, + opts: viewOptions, + targetView + }); + if (!response || (0, validate_1$1.validateIdentity)(response.identity)) { + throw new Error(`When overwriting the createView call, please return an object that has a valid 'identity' property: ${JSON.stringify(response)}`); + } + return this.fin.View.wrapSync(response.identity); + } + /** + * Creates a new Window. + * @param options Window creation options + * + * @remarks There are two Window types at your disposal while using OpenFin Platforms - Default Window and Custom Window. + * + * The Default Window uses the standard OpenFin Window UI. It contains the standard close, maximize and minimize buttons, + * and will automatically render the Window's layout if one is specified. + * + * For deeper customization, you can bring your own Window code into a Platform. This is called a Custom Window. + * + * @example + * + * + * The example below will create a Default Window which uses OpenFin default Window UI.
+ * The Window contains two Views in a stack Layout: + * + * ```js + * const platform = fin.Platform.getCurrentSync(); + * platform.createWindow({ + * layout: { + * content: [ + * { + * type: 'stack', + * content: [ + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'test_view_1', + * url: 'https://cdn.openfin.co/docs/javascript/canary/Platform.html' + * } + * }, + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'test_view_2', + * url: 'https://cdn.openfin.co/docs/javascript/canary/Platform.html' + * } + * } + * ] + * } + * ] + * } + * }).then(console.log); + * ``` + * The Default Window's design can be customized by specifying the `stylesheetUrl` property in the manifest: + * + * ```json + * { + * platform: { + * defaultWindowOptions: { + * stylesheetUrl: 'some-url.css', + * ... + * } + * } + * } + * ``` + * For a list of common Layout CSS classes you can override in your custom stylesheet, see Useful Layout CSS Classes + ** + * To specify a Platform Custom Window, provide a `url` property when creating a Window. + * If you intend to render a Layout in your Custom Window, you must also specify an `HTMLElement` that the Layout will inject into and set its `id` property to `"layout-container"`. + * + * The example below will create a Platform Custom Window: + * + * ```js + * // in an OpenFin app: + * const platform = fin.Platform.getCurrentSync(); + * const windowConfig = + * { + * url: "https://www.my-domain.com/my-custom-window.html", // here we point to where the Custom Frame is hosted. + * layout: { + * content: [ + * { + * type: "stack", + * content: [ + * { + * type: "component", + * componentName: "view", + * componentState: { + * name: "app #1", + * url: "https://cdn.openfin.co/docs/javascript/canary/Platform.html" + * } + * }, + * { + * type: "component", + * componentName: "view", + * componentState: { + * name: "app #2", + * url: "https://cdn.openfin.co/docs/javascript/canary/Platform.html" + * } + * } + * ] + * } + * ] + * } + * }; + * platform.createWindow(windowConfig); + * ``` + * + * Here's an example of a minimalist Custom Platform Window implementation: + * ```html + * + * + * + * + * + * + * + *
+ *
+ *
+ *
This is a custom frame!
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * + *
+ * + * + * ``` + * Your Custom Window can use in-domain resources for further customization (such as CSS, scripts, etc.).
+ * For a list of common Layout CSS classes you can override in your stylesheet, see Useful Layout CSS Classes + * + * The example above will require the `body` element to have `height: 100%;` set in order to render the layout correctly. + */ + async createWindow(options) { + this.wire.sendAction('platform-create-window', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + if (!options.reason) { + options.reason = 'api-call'; + } + const response = await client.dispatch('create-view-container', options); + if (!response || (0, validate_1$1.validateIdentity)(response.identity)) { + throw new Error(`When overwriting the createWindow call, please return an object that has a valid 'identity' property: ${JSON.stringify(response)}`); + } + const { identity } = response; + const res = this.fin.Window.wrapSync(identity); + // we add the identity at the top level for backwards compatibility. + res.name = identity.name; + res.uuid = identity.uuid; + return res; + } + /** + * Closes current platform, all its windows, and their views. + * + * @example + * ```js + * const platform = await fin.Platform.getCurrent(); + * platform.quit(); + * // All windows/views in current layout platform will close and platform will shut down + * ``` + */ + async quit() { + this.wire.sendAction('platform-quit', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + return client.dispatch('quit'); + } + /** + * Closes a specified view in a target window. + * @param viewIdentity View identity + * + * @example + * ```js + * let windowIdentity; + * if (fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const viewOptions = { + * name: 'test_view', + * url: 'https://example.com' + * }; + * + * function sleep(ms) { + * return new Promise(resolve => setTimeout(resolve, ms)); + * } + * + * const platform = await fin.Platform.getCurrent(); + * + * await platform.createView(viewOptions, windowIdentity); + * // a new view will now show in the current window + * + * await sleep(5000); + * + * const viewIdentity = { uuid: windowIdentity.uuid, name: 'test_view'}; + * platform.closeView(viewIdentity); + * // the view will now close + * ``` + */ + async closeView(viewIdentity) { + this.wire.sendAction('platform-close-view', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + await client.dispatch('close-view', { + view: viewIdentity + }); + } + /** + * ***DEPRECATED - please use {@link Platform.createView Platform.createView}.*** + * Reparents a specified view in a new target window. + * @param viewIdentity View identity + * @param target new owner window identity + * + */ + async reparentView(viewIdentity, target) { + // eslint-disable-next-line no-console + console.warn('Platform.reparentView has been deprecated, please use Platform.createView'); + this.wire.sendAction('platform-reparent-view', this.identity).catch((e) => { + // don't expose + }); + const normalizedViewIdentity = { + ...viewIdentity, + uuid: viewIdentity.uuid ?? this.identity.uuid + }; + const view = await this.fin.View.wrap(normalizedViewIdentity); + const viewOptions = await view.getOptions(); + return this.createView(viewOptions, target); + } + /** + * Returns a snapshot of the platform in its current state. You can pass the returning object to + * [Platform.applySnapshot]{@link Platform#applySnapshot} to launch it. + * + * @remarks The snapshot will include details such as an [ISO format](https://en.wikipedia.org/wiki/ISO_8601) + * timestamp of when the snapshot was taken, OpenFin runtime version the platform is running on, monitor information + * and the list of currently running windows. + * + * @example + * ```js + * const platform = await fin.Platform.getCurrent(); + * const snapshot = await platform.getSnapshot(); + * ``` + */ + async getSnapshot() { + this.wire.sendAction('platform-get-snapshot', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + return client.dispatch('get-snapshot'); + } + /** + * **NOTE**: Internal use only. It is not recommended to manage the state of individual views. + * + * Returns a snapshot of a single view's options in its current state. + * + * Can be used to restore a view to a previous state. + * + * @param viewIdentity View identity + * + * @internal + * @experimental + * @remarks This slice of snapshot state is equivalent to what is stored as `componentState` for views + * when capturing platform state using [Platform.getSnapshot]{@link Platform#getSnapshot}. + * + * @example + * ```js + * const platform = await fin.Platform.getCurrent(); + * const url = 'https://google.com'; + * const view = await fin.View.create({ name: 'my-view', target: fin.me.identity, url }); + * + * await view.navigate(url); + * + * const viewState = await platform.getViewSnapshot(view.identity); + * + * console.log(viewState); + * ``` + */ + async getViewSnapshot(viewIdentity) { + const client = await this.getClient(); + return client.dispatch('get-view-snapshot', { viewIdentity }); + } + /** + * Adds a snapshot to a running Platform. + * Requested snapshot must be a valid Snapshot object, or a url or filepath to such an object. + * + * Can optionally close existing windows and overwrite current platform state with that of a snapshot. + * + * The function accepts either a snapshot taken using {@link Platform#getSnapshot getSnapshot}, + * or a url or filepath to a snapshot JSON object. + * @param requestedSnapshot Snapshot to apply, or a url or filepath. + * @param options Optional parameters to specify whether existing windows should be closed. + * + * @remarks Will create any windows and views that are not running but are passed in the snapshot object. Any View + * specified in the snapshot is assigned a randomly generated name to avoid collisions. + * + * @example + * ```js + * // Get a wrapped layout platform instance + * const platform = await fin.Platform.getCurrent(); + * + * const snapshot = { + * windows: [ + * { + * layout: { + * content: [ + * { + * type: 'stack', + * content: [ + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'component_X', + * url: 'https://www.openfin.co' + * } + * }, + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'component_Y', + * url: 'https://cdn.openfin.co/embed-web/chart.html' + * } + * } + * ] + * } + * ] + * } + * } + * ] + * } + * + * platform.applySnapshot(snapshot); + * ``` + * + * In place of a snapshot object, `applySnapshot` can take a url or filepath and to retrieve a JSON snapshot. + * + * ```js + * const platform = await fin.Platform.getCurrent(); + * platform.applySnapshot('https://api.jsonbin.io/b/5e6f903ef4331e681fc1231d/1'); + * ``` + * + * Optionally, `applySnapshot` can close existing windows and restore a Platform to a previously saved state. + * This is accomplished by providing `{ closeExistingWindows: true }` as an option. + * + * ```js + * // Get a wrapped layout platform instance + * const platform = await fin.Platform.getCurrent(); + * + * async function addViewToWindow(winId) { + * return await platform.createView({ + * name: 'test_view_3', + * url: 'https://openfin.co' + * }, winId); + * } + * + * async function createWindowWithTwoViews() { + * const platform = await fin.Platform.getCurrent(); + * + * return platform.createWindow({ + * layout: { + * content: [ + * { + * type: 'stack', + * content: [ + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'test_view_1', + * url: 'https://example.com' + * } + * }, + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'test_view_2', + * url: 'https://yahoo.com' + * } + * } + * ] + * } + * ] + * } + * }); + * } + * + * const win = await createWindowWithTwoViews(); + * // ... you will now see a new window with two views in it + * + * // we take a snapshot of the current state of the app, before changing it + * const snapshotOfInitialAppState = await platform.getSnapshot(); + * + * // now let's change the state of the app: + * await addViewToWindow(win.identity); + * // ... the window now has three views in it + * + * await platform.applySnapshot(snapshotOfInitialAppState, { closeExistingWindows: true }); + * // ... the window will revert to previous state, with just two views + * + * ``` + */ + async applySnapshot(requestedSnapshot, options) { + this.wire.sendAction('platform-apply-snapshot', this.identity).catch((e) => { + // don't expose + }); + const errMsg = 'Requested snapshot must be a valid Snapshot object, or a url or filepath to such an object.'; + let snapshot; + if (typeof requestedSnapshot === 'string') { + // Fetch and parse snapshot + try { + const response = await this._channel.wire.sendAction('get-application-manifest', { + manifestUrl: requestedSnapshot + }); + snapshot = response.payload.data; + } + catch (err) { + throw new Error(`${errMsg}: ${err}`); + } + } + else { + snapshot = requestedSnapshot; + } + if (!snapshot.windows) { + throw new Error(errMsg); + } + const client = await this.getClient(); + await client.dispatch('apply-snapshot', { + snapshot, + options + }); + return this; + } + /** + * Fetches a JSON manifest using the browser process and returns a Javascript object. + * Can be overwritten using {@link Platform.PlatformModule.init Platform.init}. + * @param manifestUrl The URL of the manifest to fetch. + * + * @remarks Can be overwritten using {@link Platform#init Platform.init}. + * + * @example + * + * ```js + * const platform = fin.Platform.getCurrentSync(); + * const manifest = await platform.fetchManifest('https://www.path-to-manifest.com/app.json'); + * console.log(manifest); + * ``` + */ + async fetchManifest(manifestUrl) { + const client = await this.getClient(); + return client.dispatch('platform-fetch-manifest', { manifestUrl }); + } + /** + * Retrieves a manifest by url and launches a legacy application manifest or snapshot into the platform. Returns a promise that + * resolves to the wrapped Platform. + * @param manifestUrl - The URL of the manifest that will be launched into the platform. If this app manifest + * contains a snapshot, that will be launched into the platform. If not, the application described in startup_app options + * will be launched into the platform. The applicable startup_app options will become {@link OpenFin.ViewCreationOptions View Options}. + * + * @remarks If the app manifest contains a snapshot, that will be launched into the platform. If not, the + * application described in startup_app options will be launched into the platform as a window with a single view. + * The applicable startup_app options will become View Options. + * + * @example + * ```js + * try { + * const platform = fin.Platform.getCurrentSync(); + * await platform.launchContentManifest('http://localhost:5555/app.json'); + * console.log(`content launched successfully into platform`); + * } catch(e) { + * console.error(e); + * } + * // For a local manifest file: + * try { + * const platform = fin.Platform.getCurrentSync(); + * platform.launchContentManifest('file:///C:/somefolder/app.json'); + * console.log(`content launched successfully into platform`); + * } catch(e) { + * console.error(e); + * } + * ``` + * @experimental + */ + async launchContentManifest(manifestUrl) { + this.wire.sendAction('platform-launch-content-manifest', this.identity).catch(() => { + // don't expose + }); + const client = await this.getClient(); + const manifest = await this.fetchManifest(manifestUrl); + client.dispatch('launch-into-platform', { manifest, manifestUrl }); + return this; + } + /** + * Set the context of a host window. The context will be available to the window itself, and to its child Views. It will be saved in any platform snapshots. + * It can be retrieved using {@link Platform#getWindowContext getWindowContext}. + * @param context - A field where serializable context data can be stored to be saved in platform snapshots. + * @param target - A target window or view may optionally be provided. If no target is provided, the update will be applied + * to the current window (if called from a Window) or the current host window (if called from a View). + * + * @remarks The context data must be serializable. This can only be called from a window or view that has been launched into a + * platform. + * This method can be called from the window itself, or from any child view. Context data is shared by all + * entities within a window. + * + * @example + * Setting own context: + * ```js + * const platform = fin.Platform.getCurrentSync(); + * const contextData = { + * security: 'STOCK', + * currentView: 'detailed' + * } + * + * await platform.setWindowContext(contextData); + * // Context of current window is now set to `contextData` + * ``` + * + * Setting the context of another window or view: + * ```js + * const platform = fin.Platform.getCurrentSync(); + * const contextData = { + * security: 'STOCK', + * currentView: 'detailed' + * } + * + * const windowOrViewIdentity = { uuid: fin.me.uuid, name: 'nameOfWindowOrView' }; + * await platform.setWindowContext(contextData, windowOrViewIdentity); + * // Context of the target window or view is now set to `contextData` + * ``` + * + * A view can listen to changes to its host window's context by listening to the `host-context-changed` event. + * This event will fire when a host window's context is updated or when the view is reparented to a new window: + * + * ```js + * // From a view + * const contextChangeHandler = ({ context }) => { + * console.log('Host window\'s context has changed. New context data:', context); + * // react to new context data here + * } + * await fin.me.on('host-context-changed', contextChangeHandler); + * + * const platform = await fin.Platform.getCurrentSync(); + * const contextData = { + * security: 'STOCK', + * currentView: 'detailed' + * } + * platform.setWindowContext(contextData) // contextChangeHandler will log the new context + * ``` + * + * To listen to a window's context updates, use the `context-changed` event: + * ```js + * // From a window + * const contextChangeHandler = ({ context }) => { + * console.log('This window\'s context has changed. New context data:', context); + * // react to new context data here + * } + * await fin.me.on('context-changed', contextChangeHandler); + * + * const platform = await fin.Platform.getCurrentSync(); + * const contextData = { + * security: 'STOCK', + * currentView: 'detailed' + * } + * platform.setWindowContext(contextData) // contextChangeHandler will log the new context + * ``` + * @experimental + */ + async setWindowContext(context = {}, target) { + this.wire.sendAction('platform-set-window-context', this.identity).catch((e) => { + // don't expose + }); + if (!context) { + throw new Error('Please provide a serializable object or string to set the context.'); + } + const client = await this.getClient(); + const { entityType } = target ? await this.fin.System.getEntityInfo(target.uuid, target.name) : this.fin.me; + await client.dispatch('set-window-context', { + context, + entityType, + target: target || { uuid: this.fin.me.uuid, name: this.fin.me.name } + }); + } + /** + * Get the context context of a host window that was previously set using {@link Platform#setWindowContext setWindowContext}. + * The context will be saved in any platform snapshots. Returns a promise that resolves to the context. + * @param target - A target window or view may optionally be provided. If no target is provided, target will be + * the current window (if called from a Window) or the current host window (if called from a View). + * + * @remarks This method can be called from the window itself, or from any child view. Context data is shared + * by all entities within a window. + * + * @example + * + * Retrieving context from current window: + * ```js + * const platform = fin.Platform.getCurrentSync(); + * const customContext = { answer: 42 }; + * await platform.setWindowContext(customContext); + * + * const myContext = await platform.getWindowContext(); + * console.log(myContext); // { answer: 42 } + * ``` + * + * Retrieving the context of another window or view: + * ```js + * const platform = fin.Platform.getCurrentSync(); + * + * const windowOrViewIdentity = { uuid: fin.me.uuid, name: 'nameOfWindowOrView' }; + * + * const targetWindowContext = await platform.getWindowContext(windowOrViewIdentity); + * console.log(targetWindowContext); // context of target window + * ``` + * @experimental + */ + async getWindowContext(target) { + this.wire.sendAction('platform-get-window-context', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + const { entityType } = target ? await this.fin.System.getEntityInfo(target.uuid, target.name) : this.fin.me; + return client.dispatch('get-window-context', { + target: target || { uuid: this.fin.me.uuid, name: this.fin.me.name }, + entityType + }); + } + /** + * Closes a window. If enableBeforeUnload is enabled in the Platform options, any beforeunload handler set on Views will fire + * This behavior can be disabled by setting skipBeforeUnload to false in the options parameter. + * @param winId + * @param options + * + * @remarks This method works by setting a `close-requested` handler on the Platform Window. If you have your own `close-requested` handler set on the Platform Window as well, + * it is recommended to move that logic over to the [PlatformProvider.closeWindow]{@link PlatformProvider#closeWindow} override to ensure it runs when the Window closes. + * + * @example + * + * ```js + * // Close the current Window inside a Window context + * const platform = await fin.Platform.getCurrent(); + * platform.closeWindow(fin.me.identity); + * + * // Close the Window from inside a View context + * const platform = await fin.Platform.getCurrent(); + * const parentWindow = await fin.me.getCurrentWindow(); + * platform.closeWindow(parentWindow.identity); + * + * // Close the Window and do not fire the before unload handler on Views + * const platform = await fin.Platform.getCurrent(); + * platform.closeWindow(fin.me.identity, { skipBeforeUnload: true }); + * ``` + * @experimental + */ + async closeWindow(windowId, options = { skipBeforeUnload: false }) { + this.wire.sendAction('platform-close-window', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + return client.dispatch('close-window', { windowId, options }); + } +} +Instance$2.Platform = Platform; +_Platform_connectToProvider = new WeakMap(); + +var layout = {}; + +var Factory$2 = {}; + +var Instance$1 = {}; + +var commonUtils = {}; + +Object.defineProperty(commonUtils, "__esModule", { value: true }); +commonUtils.overrideFromComposables = commonUtils.isValidPresetType = void 0; +function isValidPresetType(type) { + switch (type) { + case 'columns': + case 'grid': + case 'rows': + case 'tabs': + return true; + default: + return false; + } +} +commonUtils.isValidPresetType = isValidPresetType; +function overrideFromComposables(...overrides) { + return (base) => overrides.reduceRight((p, c) => (b) => c(p(b)), (x) => x)(base); +} +commonUtils.overrideFromComposables = overrideFromComposables; +commonUtils.default = { isValidPresetType }; + +var __classPrivateFieldGet$4 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _Layout_layoutClient; +Object.defineProperty(Instance$1, "__esModule", { value: true }); +Instance$1.Layout = void 0; +const lazy_1 = lazy; +const validate_1 = validate; +const base_1$5 = base; +const common_utils_1 = commonUtils; +const layout_entities_1 = layoutEntities; +const layout_constants_1$1 = layout_constants; +/** + * + * Layouts give app providers the ability to embed multiple views in a single window. The Layout namespace + * enables the initialization and manipulation of a window's Layout. A Layout will + * emit events locally on the DOM element representing the layout-container. + * + * + * ### Layout.DOMEvents + * + * When a Layout is created, it emits events onto the DOM element representing the Layout container. + * This Layout container is the DOM element referenced by containerId in {@link Layout.LayoutModule#init Layout.init}. + * You can use the built-in event emitter to listen to these events using [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener). + * The events are emitted synchronously and only in the process where the Layout exists. + * Any values returned by the called listeners are ignored and will be discarded. + * If the target DOM element is destroyed, any events that have been set up on that element will be destroyed. + * + * @remarks The built-in event emitter is not an OpenFin event emitter so it doesn't share propagation semantics. + * + * #### {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener addEventListener(type, listener [, options]);} + * Adds a listener to the end of the listeners array for the specified event. + * @example + * ```js + * const myLayoutContainer = document.getElementById('layout-container'); + * + * myLayoutContainer.addEventListener('tab-created', function(event) { + * const { tabSelector } = event.detail; + * const tabElement = document.getElementById(tabSelector); + * const existingColor = tabElement.style.backgroundColor; + * tabElement.style.backgroundColor = "red"; + * setTimeout(() => { + * tabElement.style.backgroundColor = existingColor; + * }, 2000); + * }); + * ``` + * + * #### {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener removeEventListener(type, listener [, options]);} + * Adds a listener to the end of the listeners array for the specified event. + * @example + * ```js + * const myLayoutContainer = document.getElementById('layout-container'); + * + * const listener = function(event) { + * console.log(event.detail); + * console.log('container-created event fired once, removing listener'); + * myLayoutContainer.removeEventListener('container-created', listener); + * }; + * + * myLayoutContainer.addEventListener('container-created', listener); + * ``` + * + * ### Supported event types are: + * + * * tab-created + * * container-created + * * layout-state-changed + * * tab-closed + * * tab-dropped + * + * ### Layout DOM Node Events + * + * #### tab-created + * Generated when a tab is created. As a user drags and drops tabs within window, new tabs are created. A single view may have multiple tabs created and destroyed during its lifetime attached to a single window. + * ```js + * // The response has the following shape in event.detail: + * { + * containerSelector: "container-component_A", + * name: "component_A", + * tabSelector: "tab-component_A", + * topic: "openfin-DOM-event", + * type: "tab-created", + * uuid: "OpenFin POC" + * } + * ``` + * + * #### container-created + * Generated when a container is created. A single view will have only one container during its lifetime attached to a single window and the container's lifecycle is tied to the view. To discover when the container is destroyed, please listen to view-detached event. + * ```js + * // The response has the following shape in event.detail: + * { + * containerSelector: "container-component_A", + * name: "component_A", + * tabSelector: "tab-component_A", + * topic: "openfin-DOM-event", + * type: "container-created", + * uuid: "OpenFin POC" + * } + * ``` + * + * ### layout-state-changed + * Generated when the state of the layout changes in any way, such as a view added/removed/replaced. Note that this event can fire frequently as the underlying layout can change multiple components from all kinds of changes (resizing for example). Given this, it is recommended to debounce this event and then you can use the {@link Layout#getConfig Layout.getConfig} API to retrieve the most up-to-date state. + * ```js + * // The response has the following shape in event.detail + * { + * containerSelector: "container-component_A", + * name: "component_A", + * tabSelector: "tab-component_A", + * topic: "openfin-DOM-event", + * type: "layout-state-changed", + * uuid: "OpenFin POC" + * } + * ``` + * + * #### tab-closed + * Generated when a tab is closed. + * ```js + * // The response has the following shape in event.detail: + * { + * containerSelector: "container-component_A", + * name: "component_A", + * tabSelector: "tab-component_A", + * topic: "openfin-DOM-event", + * type: "tab-closed", + * uuid: "OpenFin POC", + * url: "http://openfin.co" // The url of the view that was closed. + * } + * ``` + * + * #### tab-dropped + * Generated when a tab is dropped. + * ```js + * // The response has the following shape in event.detail: + * { + * containerSelector: "container-component_A", + * name: "component_A", + * tabSelector: "tab-component_A", + * topic: "openfin-DOM-event", + * type: "tab-dropped", + * uuid: "OpenFin POC", + * url: "http://openfin.co" // The url of the view linked to the dropped tab. + * } + * ``` + */ +class Layout extends base_1$5.Base { + /** + * @internal + */ + // eslint-disable-next-line no-shadow + constructor(identity, wire) { + super(wire); + /** + * @internal + * Lazily constructed {@link LayoutEntitiesClient} bound to this platform's client and identity + * The client is for {@link LayoutEntitiesController} + */ + _Layout_layoutClient.set(this, new lazy_1.Lazy(async () => layout_entities_1.LayoutNode.newLayoutEntitiesClient(await this.platform.getClient(), layout_constants_1$1.LAYOUT_CONTROLLER_ID, this.identity))); + /** + * Replaces a Platform window's layout with a new layout. + * + * @remarks Any views that were in the old layout but not the new layout will be destroyed. Views will be assigned a randomly generated name to avoid collisions. + * @example + * ```js + * let windowIdentity; + * if (fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const layout = fin.Platform.Layout.wrapSync(windowIdentity); + * + * const newLayout = { + * content: [ + * { + * type: 'stack', + * content: [ + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'new_component_A1', + * processAffinity: 'ps_1', + * url: 'https://www.example.com' + * } + * }, + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'new_component_A2', + * url: 'https://cdn.openfin.co/embed-web/chart.html' + * } + * } + * ] + * } + * ] + * }; + * + * layout.replace(newLayout); + * ``` + */ + this.replace = async (layout) => { + this.wire.sendAction('layout-replace').catch((e) => { + // don't expose + }); + const client = await this.platform.getClient(); + await client.dispatch('replace-layout', { + target: this.identity, + opts: { layout } + }); + }; + /** + * Replaces the specified view with a view with the provided configuration. + * + * @remarks The old view is stripped of its listeners and either closed or attached to the provider window + * depending on `detachOnClose` view option. + * + * @param viewToReplace Identity of the view to be replaced + * @param newView Creation options of the new view. + * + * @example + * ```js + * let currentWindow; + * if (fin.me.isWindow) { + * currentWindow = fin.me; + * } else if (fin.me.isView) { + * currentWindow = await fin.me.getCurrentWindow(); + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const layout = fin.Platform.Layout.wrapSync(currentWindow.identity); + * const viewToReplace = (await currentWindow.getCurrentViews())[0]; + * const newViewConfig = {url: 'https://example.com'}; + * await layout.replaceView(viewToReplace.identity, newViewConfig); + * ``` + */ + this.replaceView = async (viewToReplace, newView) => { + this.wire.sendAction('layout-replace-view').catch((e) => { + // don't expose + }); + const client = await this.platform.getClient(); + await client.dispatch('replace-view', { + target: this.identity, + opts: { viewToReplace, newView } + }); + }; + /** + * Replaces a Platform window's layout with a preset layout arrangement using the existing Views attached to the window. + * The preset options are `columns`, `grid`, `rows`, and `tabs`. + * @param options Mandatory object with `presetType` property that sets which preset layout arrangement to use. + * The preset options are `columns`, `grid`, `rows`, and `tabs`. + * + * @example + * ```js + * let windowIdentity; + * if (fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const layout = fin.Platform.Layout.wrapSync(windowIdentity); + * await layout.applyPreset({ presetType: 'grid' }); + * + * // wait 5 seconds until you change the layout from grid to tabs + * await new Promise (res => setTimeout(res, 5000)); + * await layout.applyPreset({ presetType: 'tabs' }); + * ``` + */ + this.applyPreset = async (options) => { + this.wire.sendAction('layout-apply-preset').catch((e) => { + // don't expose + }); + const client = await this.platform.getClient(); + const { presetType } = options; + if (!presetType || !(0, common_utils_1.isValidPresetType)(presetType)) { + throw new Error('Cannot apply preset layout, please include an applicable presetType property in the PresetLayoutOptions.'); + } + await client.dispatch('apply-preset-layout', { + target: this.identity, + opts: { presetType } + }); + }; + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + this.identity = identity; + this.platform = this.fin.Platform.wrapSync({ uuid: identity.uuid }); + if (identity.uuid === this.fin.me.uuid && identity.name === this.fin.me.name) { + this.init = this.fin.Platform.Layout.init; + } + } + /** + * Returns the configuration of the window's layout. Returns the same information that is returned for all windows in getSnapshot. + * + * @remarks Cannot be called from a View. + * + * + * @example + * ```js + * const layout = fin.Platform.Layout.getCurrentSync(); + * // Use wrapped instance to get the layout configuration of the current window's Layout: + * const layoutConfig = await layout.getConfig(); + * ``` + */ + async getConfig() { + this.wire.sendAction('layout-get-config').catch((e) => { + // don't expose + }); + const client = await this.platform.getClient(); + return client.dispatch('get-frame-snapshot', { + target: this.identity + }); + } + /** + * Retrieves the attached views in current window layout. + * + * @example + * ```js + * const layout = fin.Platform.Layout.getCurrentSync(); + * const views = await layout.getCurrentViews(); + * ``` + */ + async getCurrentViews() { + this.wire.sendAction('layout-get-views').catch((e) => { + // don't expose + }); + const client = await this.platform.getClient(); + const viewIdentities = await client.dispatch('get-layout-views', { + target: this.identity + }); + return viewIdentities.map((identity) => this.fin.View.wrapSync(identity)); + } + /** + * Retrieves the top level content item of the layout. + * + * @remarks Cannot be called from a view. + * + * + * + * @example + * ```js + * if (!fin.me.isWindow) { + * throw new Error('Not running in a platform View.'); + * } + * + * // From the layout window + * const layout = fin.Platform.Layout.getCurrentSync(); + * // Retrieves the ColumnOrRow instance + * const rootItem = await layout.getRootItem(); + * const content = await rootItem.getContent(); + * console.log(`The root ColumnOrRow instance has ${content.length} item(s)`); + * ``` + */ + async getRootItem() { + this.wire.sendAction('layout-get-root-item').catch(() => { + // don't expose + }); + const client = await __classPrivateFieldGet$4(this, _Layout_layoutClient, "f").getValue(); + const root = await client.getRoot('layoutName' in this.identity ? this.identity : undefined); + return layout_entities_1.LayoutNode.getEntity(root, client); + } +} +Instance$1.Layout = Layout; +_Layout_layoutClient = new WeakMap(); + +var __classPrivateFieldGet$3 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet$3 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _LayoutModule_instances, _LayoutModule_layoutInitializationAttempted, _LayoutModule_layoutManager, _LayoutModule_getLayoutManagerSpy, _LayoutModule_getSafeLayoutManager; +Object.defineProperty(Factory$2, "__esModule", { value: true }); +Factory$2.LayoutModule = void 0; +const base_1$4 = base; +const Instance_1$2 = Instance$1; +const layout_constants_1 = layout_constants; +/** + * Static namespace for OpenFin API methods that interact with the {@link Layout} class, available under `fin.Platform.Layout`. + */ +class LayoutModule extends base_1$4.Base { + constructor() { + super(...arguments); + _LayoutModule_instances.add(this); + _LayoutModule_layoutInitializationAttempted.set(this, false); + _LayoutModule_layoutManager.set(this, null); + /** + * Initialize the window's Layout. + * + * @remarks Must be called from a custom window that has a 'layout' option set upon creation of that window. + * If a containerId is not provided, this method attempts to find an element with the id `layout-container`. + * A Layout will emit events locally on the DOM element representing the layout-container. + * In order to capture the relevant events during Layout initiation, set up the listeners on the DOM element prior to calling `init`. + * @param options - Layout init options. + * + * @experimental + * + * @example + * ```js + * // If no options are included, the layout in the window options is initialized in an element with the id `layout-container` + * const layout = await fin.Platform.Layout.init(); + * ``` + *
+ * + * ```js + * const containerId = 'my-custom-container-id'; + * + * const myLayoutContainer = document.getElementById(containerId); + * + * myLayoutContainer.addEventListener('tab-created', function(event) { + * const { tabSelector } = event.detail; + * const tabElement = document.getElementById(tabSelector); + * const existingColor = tabElement.style.backgroundColor; + * tabElement.style.backgroundColor = "red"; + * setTimeout(() => { + * tabElement.style.backgroundColor = existingColor; + * }, 2000); + * }); + * + * // initialize the layout into an existing HTML element with the div `my-custom-container-id` + * // the window must have been created with a layout in its window options + * const layout = await fin.Platform.Layout.init({ containerId }); + * ``` + */ + this.init = async (options = {}) => { + this.wire.sendAction('layout-init').catch((e) => { + // don't expose + }); + if (!this.wire.environment.layoutAllowedInContext(this.fin)) { + throw new Error('Layout.init can only be called from a Window context.'); + } + if (__classPrivateFieldGet$3(this, _LayoutModule_layoutInitializationAttempted, "f")) { + throw new Error('Layout.init was already called, please use Layout.create to add additional layouts.'); + } + if (this.wire.environment.type === 'openfin') { + // preload the client + await this.fin.Platform.getCurrentSync().getClient(); + } + __classPrivateFieldSet$3(this, _LayoutModule_layoutInitializationAttempted, true, "f"); + // TODO: rename to createLayoutManager + __classPrivateFieldSet$3(this, _LayoutModule_layoutManager, await this.wire.environment.initLayoutManager(this.fin, this.wire, options), "f"); + await this.wire.environment.applyLayoutSnapshot(this.fin, __classPrivateFieldGet$3(this, _LayoutModule_layoutManager, "f"), options); + const meIdentity = { name: this.fin.me.name, uuid: this.fin.me.uuid }; + if (!options.layoutManagerOverride) { + // CORE-1081 to be removed when we actually delete the `layoutManager` prop + // in single-layout case, we return the undocumented layoutManager type + const layoutIdentity = { layoutName: layout_constants_1.DEFAULT_LAYOUT_KEY, ...meIdentity }; + return __classPrivateFieldGet$3(this, _LayoutModule_getLayoutManagerSpy, "f").call(this, layoutIdentity); + } + return this.wrapSync(meIdentity); + }; + _LayoutModule_getLayoutManagerSpy.set(this, (layoutIdentity) => { + const msg = '[Layout] You are using a deprecated property `layoutManager` - it will throw if you access it starting in v37.'; + const managerProxy = new Proxy({}, { + get(target, key) { + console.warn(`[Layout-mgr-proxy] accessing ${key.toString()}`); + throw new Error(msg); + } + }); + const layout = Object.assign(this.wrapSync(layoutIdentity), { layoutManager: managerProxy }); + const layoutProxy = new Proxy(layout, { + get(target, key) { + if (key === 'layoutManager') { + console.warn(`[Layout-proxy] accessing ${key.toString()}`); + throw new Error(msg); + } + return target[key]; + } + }); + return layoutProxy; + }); + /** + * Returns the layout manager for the current window + * @returns + */ + this.getCurrentLayoutManagerSync = () => { + return __classPrivateFieldGet$3(this, _LayoutModule_instances, "m", _LayoutModule_getSafeLayoutManager).call(this, `fin.Platform.Layout.getCurrentLayoutManagerSync()`); + }; + this.create = async (options) => { + return this.wire.environment.createLayout(__classPrivateFieldGet$3(this, _LayoutModule_instances, "m", _LayoutModule_getSafeLayoutManager).call(this, `fin.Platform.Layout.create()`), options); + }; + this.destroy = async (layoutIdentity) => { + return this.wire.environment.destroyLayout(__classPrivateFieldGet$3(this, _LayoutModule_instances, "m", _LayoutModule_getSafeLayoutManager).call(this, `fin.Platform.Layout.destroy()`), layoutIdentity); + }; + } + /** + * Asynchronously returns a Layout object that represents a Window's layout. + * + * @example + * ```js + * let windowIdentity; + * if (!fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const layout = await fin.Platform.Layout.wrap(windowIdentity); + * // Use wrapped instance to control layout, e.g.: + * const layoutConfig = await layout.getConfig(); + * ``` + */ + async wrap(identity) { + this.wire.sendAction('layout-wrap').catch((e) => { + // don't expose + }); + return new Instance_1$2.Layout(identity, this.wire); + } + /** + * Synchronously returns a Layout object that represents a Window's layout. + * + * @example + * ```js + * let windowIdentity; + * if (!fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const layout = fin.Platform.Layout.wrapSync(windowIdentity); + * // Use wrapped instance to control layout, e.g.: + * const layoutConfig = await layout.getConfig(); + * ``` + */ + wrapSync(identity) { + this.wire.sendAction('layout-wrap-sync').catch((e) => { + // don't expose + }); + return new Instance_1$2.Layout(identity, this.wire); + } + /** + * Asynchronously returns a Layout object that represents a Window's layout. + * + * @example + * ```js + * const layout = await fin.Platform.Layout.getCurrent(); + * // Use wrapped instance to control layout, e.g.: + * const layoutConfig = await layout.getConfig(); + * ``` + */ + async getCurrent() { + this.wire.sendAction('layout-get-current').catch((e) => { + // don't expose + }); + if (!this.fin.me.isWindow) { + throw new Error('You are not in a Window context. Only Windows can have a Layout.'); + } + const { uuid, name } = this.fin.me; + return this.wrap({ uuid, name }); + } + /** + * Synchronously returns a Layout object that represents a Window's layout. + * + * @remarks Cannot be called from a view. + * + * + * @example + * ```js + * const layout = fin.Platform.Layout.getCurrentSync(); + * // Use wrapped instance to control layout, e.g.: + * const layoutConfig = await layout.getConfig(); + * ``` + */ + getCurrentSync() { + this.wire.sendAction('layout-get-current-sync').catch((e) => { + // don't expose + }); + if (!this.fin.me.isWindow) { + throw new Error('You are not in a Window context. Only Windows can have a Layout.'); + } + const { uuid, name } = this.fin.me; + return this.wrapSync({ uuid, name }); + } +} +Factory$2.LayoutModule = LayoutModule; +_LayoutModule_layoutInitializationAttempted = new WeakMap(), _LayoutModule_layoutManager = new WeakMap(), _LayoutModule_getLayoutManagerSpy = new WeakMap(), _LayoutModule_instances = new WeakSet(), _LayoutModule_getSafeLayoutManager = function _LayoutModule_getSafeLayoutManager(method) { + if (!__classPrivateFieldGet$3(this, _LayoutModule_layoutManager, "f")) { + throw new Error(`You must call init before using the API ${method}`); + } + return __classPrivateFieldGet$3(this, _LayoutModule_layoutManager, "f"); +}; + +(function (exports) { + /** + * Entry point for the OpenFin `Layout` subset of the `Platform` API (`fin.Platform.Layout`). + * + * * {@link LayoutModule} contains static members of the `Layout` API, accessible through `fin.Platform.Layout`. + * * {@link Layout} describes an instance of an OpenFin Layout, e.g. as returned by `fin.Platform.Layout.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + * + */ + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(Factory$2, exports); + __exportStar(Instance$1, exports); +} (layout)); + +Object.defineProperty(Factory$3, "__esModule", { value: true }); +Factory$3.PlatformModule = void 0; +const base_1$3 = base; +const Instance_1$1 = Instance$2; +const index_1$1 = layout; +/** + * Static namespace for OpenFin API methods that interact with the {@link Platform} class, available under `fin.Platform`. + */ +class PlatformModule extends base_1$3.Base { + /** + * @internal + */ + constructor(wire, channel) { + super(wire); + this._channel = channel; + /** + * + * @desc Layouts give app providers the ability to embed multiple views in a single window. The Layout namespace + * enables the initialization and manipulation of a window's Layout. A Layout will + * emit events locally on the DOM element representing the layout-container. + */ + this.Layout = new index_1$1.LayoutModule(this.wire); + } + /** + * Initializes a Platform. Must be called from the Provider when using a custom provider. + * @param options - platform options including a callback function that can be used to extend or replace + * default Provider behavior. + * + * @remarks Must be called from the Provider when using a custom provider. + * + * @example + * + * ```js + * // From Provider context + * await fin.Platform.init(); + * // Platform API is now hooked up and windows contained in the manifest snapshot are open. + * ``` + * + * `Platform.init` accepts an options object that can contain a callback function which can be used to extend or + * replace default Provider behavior. As an argument, this function will receive the `Provider` class, which is + * used to handle Platform actions. The function must return an object with methods to handle Platform API actions. + * The recommended approach is to extend the `Provider` class, overriding the methods you wish to alter, and return an + * instance of your subclass: + * + * ```js + * const overrideCallback = async (PlatformProvider) => { + * // Actions can be performed before initialization. + * // e.g. we might authenticate a user, set up a Channel, etc before initializing the Platform. + * const { manifestUrl } = await fin.Application.getCurrentSync().getInfo(); + * + * // Extend or replace default PlatformProvider behavior by extending the PlatformProvider class. + * class MyOverride extends PlatformProvider { + * // Default behavior can be changed by implementing methods with the same names as those used by the default PlatformProvider. + * async getSnapshot() { + * // Since we are extending the class, we can call `super` methods to access default behavior. + * const snapshot = await super.getSnapshot(); + * // But we can modify return values. + * return { ...snapshot, answer: 42, manifestUrl }; + * } + * async replaceLayout({ opts, target }) { + * // To disable an API method, overwrite with a noop function. + * return; + * } + * } + * // Return instance with methods to be consumed by Platform. + * // The returned object must implement all methods of the PlatformProvider class. + * // By extending the class, we can simply inherit methods we do not wish to alter. + * return new MyOverride(); + * }; + * + * fin.Platform.init({overrideCallback}); + * ``` + * @experimental + */ + async init(options) { + if (!fin.__internal_.isPlatform || fin.me.name !== fin.me.uuid) { + throw new Error('fin.Platform.init should only be called from a custom platform provider running in the main window of the application.'); + } + return this.wire.environment.initPlatform(this.fin, options); + } + /** + * Asynchronously returns a Platform object that represents an existing platform. + * + * @example + * ```js + * const { identity } = fin.me; + * const platform = await fin.Platform.wrap(identity); + * // Use wrapped instance to control layout, e.g.: + * const snapshot = await platform.getSnapshot(); + * ``` + */ + async wrap(identity) { + this.wire.sendAction('platform-wrap').catch((e) => { + // don't expose + }); + return new Instance_1$1.Platform({ uuid: identity.uuid }, this._channel); + } + /** + * Synchronously returns a Platform object that represents an existing platform. + * + * @example + * ```js + * const { identity } = fin.me; + * const platform = fin.Platform.wrapSync(identity); + * // Use wrapped instance to control layout, e.g.: + * const snapshot = await platform.getSnapshot(); + * ``` + */ + wrapSync(identity) { + this.wire.sendAction('platform-wrap-sync').catch((e) => { + // don't expose + }); + return new Instance_1$1.Platform({ uuid: identity.uuid }, this._channel); + } + /** + * Asynchronously returns a Platform object that represents the current platform. + * + * @example + * ```js + * const platform = await fin.Platform.getCurrent(); + * // Use wrapped instance to control layout, e.g.: + * const snapshot = await platform.getSnapshot(); + * ``` + */ + async getCurrent() { + this.wire.sendAction('platform-get-current').catch((e) => { + // don't expose + }); + return this.wrap({ uuid: this.wire.me.uuid }); + } + /** + * Synchronously returns a Platform object that represents the current platform. + * + * @example + * ```js + * const platform = fin.Platform.getCurrentSync(); + * // Use wrapped instance to control layout, e.g.: + * const snapshot = await platform.getSnapshot(); + * ``` + */ + getCurrentSync() { + this.wire.sendAction('platform-get-current-sync').catch((e) => { + // don't expose + }); + return this.wrapSync({ uuid: this.wire.me.uuid }); + } + /** + * Creates and starts a Platform and returns a wrapped and running Platform instance. The wrapped Platform methods can + * be used to launch content into the platform. Promise will reject if the platform is already running. + * + * @example + * ```js + * try { + * const platform = await fin.Platform.start({ + * uuid: 'platform-1', + * autoShow: false, + * defaultWindowOptions: { + * stylesheetUrl: 'css-sheet-url', + * cornerRounding: { + * height: 10, + * width: 10 + * } + * } + * }); + * console.log('Platform is running', platform); + * } catch(e) { + * console.error(e); + * } + * ``` + */ + start(platformOptions) { + this.wire.sendAction('platform-start').catch((e) => { + // don't expose + }); + // eslint-disable-next-line no-async-promise-executor + return new Promise(async (resolve, reject) => { + try { + const { uuid } = platformOptions; + // @ts-expect-error using private variable. + const app = await this.fin.Application._create({ ...platformOptions, isPlatformController: true }); + // TODO: fix typing (internal) + // @ts-expect-error + app.once('platform-api-ready', () => resolve(this.wrapSync({ uuid }))); + // @ts-expect-error using private variable. + app._run({ uuid }); + } + catch (e) { + reject(e); + } + }); + } + /** + * Retrieves platforms's manifest and returns a wrapped and running Platform. If there is a snapshot in the manifest, + * it will be launched into the platform. + * @param manifestUrl - The URL of platform's manifest. + * @param opts - Parameters that the RVM will use. + * + * @example + * ```js + * try { + * const platform = await fin.Platform.startFromManifest('https://openfin.github.io/golden-prototype/public.json'); + * console.log('Platform is running, wrapped platform: ', platform); + * } catch(e) { + * console.error(e); + * } + * // For a local manifest file: + * try { + * const platform = await fin.Platform.startFromManifest('file:///C:/somefolder/app.json'); + * console.log('Platform is running, wrapped platform: ', platform); + * } catch(e) { + * console.error(e); + * } + * ``` + */ + startFromManifest(manifestUrl, opts) { + this.wire.sendAction('platform-start-from-manifest').catch((e) => { + // don't expose + }); + // eslint-disable-next-line no-async-promise-executor + return new Promise(async (resolve, reject) => { + try { + // @ts-expect-error using private variable. + const app = await this.fin.Application._createFromManifest(manifestUrl); + // TODO: fix typing (internal) + // @ts-expect-error + app.once('platform-api-ready', () => resolve(this.wrapSync({ uuid: app.identity.uuid }))); + // @ts-expect-error using private method without warning. + app._run(opts); + } + catch (e) { + reject(e); + } + }); + } +} +Factory$3.PlatformModule = PlatformModule; + +(function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + /** + * Entry points for the OpenFin `Platform` API (`fin.Platform`) + * + * * {@link PlatformModule} contains static members of the `Platform` API, accessible through `fin.Platform`. + * * {@link Platform} describes an instance of an OpenFin Platform, e.g. as returned by `fin.Platform.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + */ + __exportStar(Factory$3, exports); + __exportStar(Instance$2, exports); +} (platform)); + +var me = {}; + +(function (exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + exports.getMe = exports.getBaseMe = exports.environmentUnsupportedMessage = void 0; + const view_1 = requireView(); + const frame_1 = frame; + const window_1 = requireWindow(); + const external_application_1 = externalApplication; + exports.environmentUnsupportedMessage = 'You are not running in OpenFin.'; + function getBaseMe(entityType, uuid, name) { + const entityTypeHelpers = { + isView: entityType === 'view', + isWindow: entityType === 'window', + isFrame: entityType === 'iframe', + isExternal: entityType === 'external connection' + }; + return { ...entityTypeHelpers, uuid, name, entityType }; + } + exports.getBaseMe = getBaseMe; + // We need to do a lot of casting as unknown here because the compiler get's confused about matching types. What matters is that it works on the outside + function getMe(wire) { + const { uuid, name, entityType } = wire.me; + const unsupportedInterop = { + setContext() { + throw new Error(exports.environmentUnsupportedMessage); + }, + addContextHandler() { + throw new Error(exports.environmentUnsupportedMessage); + }, + getContextGroups() { + throw new Error(exports.environmentUnsupportedMessage); + }, + joinContextGroup() { + throw new Error(exports.environmentUnsupportedMessage); + }, + removeFromContextGroup() { + throw new Error(exports.environmentUnsupportedMessage); + }, + getAllClientsInContextGroup() { + throw new Error(exports.environmentUnsupportedMessage); + }, + getInfoForContextGroup() { + throw new Error(exports.environmentUnsupportedMessage); + } + }; + const fallbackErrorMessage = 'Interop API has not been instantiated. Either connection has failed or you have not declared interop in your config.'; + const fallbackInterop = { + setContext() { + throw new Error(fallbackErrorMessage); + }, + addContextHandler() { + throw new Error(fallbackErrorMessage); + }, + getContextGroups() { + throw new Error(fallbackErrorMessage); + }, + joinContextGroup() { + throw new Error(fallbackErrorMessage); + }, + removeFromContextGroup() { + throw new Error(fallbackErrorMessage); + }, + getAllClientsInContextGroup() { + throw new Error(fallbackErrorMessage); + }, + getInfoForContextGroup() { + throw new Error(fallbackErrorMessage); + } + }; + const unsupportedEventBase = { + eventNames: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + emit: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + listeners: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + listenerCount: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + on: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + addListener: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + once: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + prependListener: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + prependOnceListener: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + removeListener: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + removeAllListeners: () => { + throw new Error(exports.environmentUnsupportedMessage); + } + }; + switch (entityType) { + case 'view': + return Object.assign(new view_1.View(wire, { uuid, name }), getBaseMe(entityType, uuid, name), { + interop: fallbackInterop, + isOpenFin: true + }); + case 'window': + return Object.assign(new window_1._Window(wire, { uuid, name }), getBaseMe(entityType, uuid, name), { + interop: fallbackInterop, + isOpenFin: true + }); + case 'iframe': + return Object.assign(new frame_1._Frame(wire, { uuid, name }), getBaseMe(entityType, uuid, name), { + interop: fallbackInterop, + isOpenFin: true + }); + case 'external connection': + return Object.assign(new external_application_1.ExternalApplication(wire, { uuid }), getBaseMe(entityType, uuid, name), { + interop: fallbackInterop, + isOpenFin: false + }); + default: + return { + ...getBaseMe(entityType, uuid, name), + ...unsupportedEventBase, + interop: unsupportedInterop, + isOpenFin: false + }; + } + } + exports.getMe = getMe; +} (me)); + +var interop = {}; + +var Factory$1 = {}; + +var inaccessibleObject = {}; + +Object.defineProperty(inaccessibleObject, "__esModule", { value: true }); +inaccessibleObject.createWarningObject = inaccessibleObject.createUnusableObject = void 0; +function createUnusableObject(message) { + const handle = () => { + throw new Error(message); + }; + return new Proxy({}, { + apply: handle, + construct: handle, + defineProperty: handle, + deleteProperty: handle, + get: handle, + getOwnPropertyDescriptor: handle, + getPrototypeOf: handle, + has: handle, + isExtensible: handle, + ownKeys: handle, + preventExtensions: handle, + set: handle, + setPrototypeOf: handle + }); +} +inaccessibleObject.createUnusableObject = createUnusableObject; +function createWarningObject(message, obj) { + return new Proxy(obj, { + get: (...args) => { + // eslint-disable-next-line no-console + console.warn(message); + return Reflect.get(...args); + }, + set: (...args) => { + // eslint-disable-next-line no-console + console.warn(message); + return Reflect.set(...args); + }, + getOwnPropertyDescriptor: (...args) => { + // eslint-disable-next-line no-console + console.warn(message); + return Reflect.getOwnPropertyDescriptor(...args); + }, + ownKeys: (...args) => { + // eslint-disable-next-line no-console + console.warn(message); + return Reflect.ownKeys(...args); + } + }); +} +inaccessibleObject.createWarningObject = createWarningObject; + +var InteropBroker = {}; + +var SessionContextGroupBroker = {}; + +var hasRequiredSessionContextGroupBroker; + +function requireSessionContextGroupBroker () { + if (hasRequiredSessionContextGroupBroker) return SessionContextGroupBroker; + hasRequiredSessionContextGroupBroker = 1; + Object.defineProperty(SessionContextGroupBroker, "__esModule", { value: true }); + const _1 = requireInterop(); + let SessionContextGroupBroker$1 = class SessionContextGroupBroker { + constructor(provider, id) { + this.provider = provider; + this.id = id; + this.lastContext = undefined; + this.contextGroupMap = new Map(); + this.clients = new Map(); + this.registerListeners(); + } + registerListeners() { + this.provider.register(`sessionContextGroup:getContext-${this.id}`, this.getCurrentContext.bind(this)); + this.provider.register(`sessionContextGroup:setContext-${this.id}`, this.setContext.bind(this)); + this.provider.register(`sessionContextGroup:handlerAdded-${this.id}`, this.handlerAdded.bind(this)); + this.provider.register(`sessionContextGroup:handlerRemoved-${this.id}`, this.handlerRemoved.bind(this)); + } + getCurrentContext(payload) { + return payload.type ? this.contextGroupMap.get(payload.type) : this.lastContext; + } + setContext(payload, clientIdentity) { + const { context } = payload; + const contextIntegrityCheckResult = _1.InteropBroker.checkContextIntegrity(context); + if (contextIntegrityCheckResult.isValid === false) { + throw new Error(`Failed to set Context - bad Context. Reason: ${contextIntegrityCheckResult.reason}. Context: ${JSON.stringify(context)}`); + } + const clientState = this.getClientState(clientIdentity); + if (!clientState) { + // This shouldn't get hit. + throw new Error(`Client with Identity: ${clientIdentity.uuid} ${clientIdentity.name} not in Session Client State Map`); + } + // set the context + this.contextGroupMap.set(context.type, context); + this.lastContext = context; + const clientSubscriptionStates = Array.from(this.clients.values()); + clientSubscriptionStates.forEach((client) => { + // eslint-disable-next-line no-unused-expressions + client.contextHandlers.get(context.type)?.forEach((handlerId) => { + this.provider.dispatch(client.clientIdentity, handlerId, context); + }); + if (client.globalHandler) { + this.provider.dispatch(client.clientIdentity, client.globalHandler, context); + } + }); + } + getClientState(id) { + return this.clients.get(id.endpointId); + } + async handlerAdded(payload, clientIdentity) { + const { handlerId, contextType } = payload; + const clientSubscriptionState = this.getClientState(clientIdentity); + if (!clientSubscriptionState) { + throw new Error(`Client with Identity: ${clientIdentity.uuid} ${clientIdentity.name} not in Client State Map`); + } + if (contextType) { + const currentHandlerList = clientSubscriptionState.contextHandlers.get(contextType) || []; + clientSubscriptionState.contextHandlers.set(contextType, [...currentHandlerList, handlerId]); + const currentContext = this.contextGroupMap.get(contextType); + if (currentContext) { + await this.provider.dispatch(clientIdentity, handlerId, currentContext); + } + } + else { + clientSubscriptionState.globalHandler = handlerId; + const globalDispatchPromises = [...this.contextGroupMap.keys()].map(async (currentContextType) => { + const currentContext = this.contextGroupMap.get(currentContextType); + if (currentContext) { + await this.provider.dispatch(clientIdentity, handlerId, currentContext); + } + }); + await Promise.all(globalDispatchPromises); + } + } + handlerRemoved(payload, clientIdentity) { + const { handlerId } = payload; + const client = this.clients.get(clientIdentity.endpointId); + if (client) { + Array.from(client.contextHandlers).forEach(([, handlers]) => { + const index = handlers.indexOf(handlerId); + if (index > -1) { + handlers.splice(index, 1); + } + }); + if (client.globalHandler === handlerId) { + client.globalHandler = undefined; + } + } + else { + console.warn(`Trying to remove a handler from a client that isn't mapped. handlerId: ${handlerId}. clientIdentity: ${clientIdentity}`); + } + } + registerNewClient(clientIdentity) { + if (!this.clients.has(clientIdentity.endpointId)) { + const clientSubscriptionState = { + contextHandlers: new Map(), + clientIdentity, + globalHandler: undefined + }; + this.clients.set(clientIdentity.endpointId, clientSubscriptionState); + } + } + onDisconnection(clientIdentity) { + this.clients.delete(clientIdentity.endpointId); + } + }; + SessionContextGroupBroker.default = SessionContextGroupBroker$1; + return SessionContextGroupBroker; +} + +var utils$3 = {}; + +(function (exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + exports.wrapIntentHandler = exports.BROKER_ERRORS = exports.generateOverrideWarning = exports.generateOverrideError = exports.wrapContextHandler = exports.wrapInTryCatch = exports.generateId = void 0; + const generateId = () => `${Math.random()}${Date.now()}`; + exports.generateId = generateId; + const wrapInTryCatch = (f, prefix) => (...args) => { + try { + return f(...args); + } + catch (e) { + throw new Error((prefix || '') + e); + } + }; + exports.wrapInTryCatch = wrapInTryCatch; + const wrapContextHandler = (handler, handlerId) => { + return async (context) => { + try { + await handler(context); + } + catch (error) { + console.error(`Error thrown by handler ${handlerId} for context type ${context.type}: ${error}`); + throw error; + } + }; + }; + exports.wrapContextHandler = wrapContextHandler; + const generateOverrideError = (clientApi, brokerApi) => { + return `You have tried to to use ${clientApi} but ${brokerApi} has not been overridden in the Interop Broker. Please override this function. Refer to our documentation for more info.`; + }; + exports.generateOverrideError = generateOverrideError; + const generateOverrideWarning = (fdc3ClientApi, brokerApi, identity, interopClientApi) => { + const { uuid, name } = identity; + const message = interopClientApi + ? `Entity with identity: ${uuid}/${name} has called ${interopClientApi} or ${fdc3ClientApi} but ${brokerApi} has not been overridden.` + : `Entity with identity: ${uuid}/${name} has called ${fdc3ClientApi} but ${brokerApi} has not been overridden.`; + return message; + }; + exports.generateOverrideWarning = generateOverrideWarning; + exports.BROKER_ERRORS = { + fireIntent: (0, exports.generateOverrideError)('fireIntent', 'handleFiredIntent'), + fireIntentForContext: (0, exports.generateOverrideError)('fireIntentForContext', 'handleFiredIntentForContext'), + getInfoForIntent: (0, exports.generateOverrideError)('getInfoForIntent', 'handleInfoForIntent'), + getInfoForIntentsByContext: (0, exports.generateOverrideError)('getInfoForIntentsByContext', 'handleInfoForIntentsByContext'), + joinSessionContextGroupWithJoinContextGroup: 'The Context Group you have tried to join is a Session Context Group. Custom Context Groups can only be defined by the Interop Broker through code or manifest configuration. Please use joinSessionContextGroup.', + fdc3Open: (0, exports.generateOverrideError)('fdc3.open', 'fdc3HandleOpen'), + fdc3FindInstances: (0, exports.generateOverrideError)('fdc3.findInstances', 'fdc3HandleFindInstances'), + fdc3GetAppMetadata: (0, exports.generateOverrideError)('fdc3.getAppMetadata', 'fdc3HandleGetAppMetadata'), + fdc3GetInfo: (0, exports.generateOverrideError)('fdc3.getInfo', 'fdc3HandleGetInfo') + }; + const wrapIntentHandler = (handler, handlerId) => { + return async (intent) => { + try { + return handler(intent); + } + catch (error) { + console.error(`Error thrown by handler ${handlerId}: ${error}`); + throw error; + } + }; + }; + exports.wrapIntentHandler = wrapIntentHandler; +} (utils$3)); + +var PrivateChannelProvider = {}; + +var hasRequiredPrivateChannelProvider; + +function requirePrivateChannelProvider () { + if (hasRequiredPrivateChannelProvider) return PrivateChannelProvider; + hasRequiredPrivateChannelProvider = 1; + Object.defineProperty(PrivateChannelProvider, "__esModule", { value: true }); + PrivateChannelProvider.PrivateChannelProvider = void 0; + const InteropBroker_1 = requireInteropBroker(); + let PrivateChannelProvider$1 = class PrivateChannelProvider { + constructor(provider, id) { + this.provider = provider; + this.id = id; + this.clients = new Map(); + this.registerListeners(); + this.contextByContextType = new Map(); + this.lastContext = undefined; + this.provider.onConnection((clientIdentity) => this.registerNewClient(clientIdentity)); + this.provider.onDisconnection(async (clientIdentity) => { + const { endpointId } = clientIdentity; + if (this.clients.has(endpointId)) { + await this.handleClientDisconnecting(clientIdentity); + } + if ((await this.provider.getAllClientInfo()).length === 0) { + this.provider.destroy(); + } + }); + } + getClientState(id) { + return this.clients.get(id.endpointId); + } + registerListeners() { + this.provider.register('broadcast', this.broadcast.bind(this)); + this.provider.register('getCurrentContext', this.getCurrentContext.bind(this)); + this.provider.register('contextHandlerAdded', this.contextHandlerAdded.bind(this)); + this.provider.register('contextHandlerRemoved', this.contextHandlerRemoved.bind(this)); + this.provider.register('nonStandardHandlerRemoved', this.nonStandardHandlerRemoved.bind(this)); + this.provider.register('onAddContextHandlerAdded', this.onAddContextHandlerAdded.bind(this)); + this.provider.register('onDisconnectHandlerAdded', this.onDisconnectHandlerAdded.bind(this)); + this.provider.register('onUnsubscribeHandlerAdded', this.onUnsubscribeHandlerAdded.bind(this)); + this.provider.register('clientDisconnecting', (payload, clientIdentity) => { + this.handleClientDisconnecting(clientIdentity); + }); + } + broadcast(payload, broadcasterClientIdentity) { + const { context } = payload; + const broadcasterClientState = this.getClientState(broadcasterClientIdentity); + if (!broadcasterClientState) { + throw new Error(`Client with Identity: ${broadcasterClientIdentity.uuid} ${broadcasterClientIdentity.name}, tried to call broadcast, is not connected to this Private Channel`); + } + const contextIntegrityCheckResult = InteropBroker_1.InteropBroker.checkContextIntegrity(context); + if (contextIntegrityCheckResult.isValid === false) { + throw new Error(`Failed to broadcast - bad Context. Reason: ${contextIntegrityCheckResult.reason}. Context: ${JSON.stringify(context)}`); + } + this.contextByContextType.set(context.type, context); + this.lastContext = context; + Array.from(this.clients.values()).forEach((currClientState) => { + const handlerIdsForContextType = currClientState.handlerIdsByContextTypes.get(context.type); + if (handlerIdsForContextType) { + handlerIdsForContextType.forEach((handlerId) => { + this.provider.dispatch(currClientState.clientIdentity, handlerId, context); + }); + } + if (currClientState.globalHandler) { + this.provider.dispatch(currClientState.clientIdentity, currClientState.globalHandler, context); + } + }); + } + getCurrentContext(payload, senderClientIdentity) { + const { contextType } = payload; + const clientState = this.getClientState(senderClientIdentity); + if (!clientState) { + throw new Error(`Client with Identity: ${senderClientIdentity.uuid} ${senderClientIdentity.name}, tried to call getCurrentContext, is not connected to this Private Channel`); + } + if (contextType !== undefined) { + const currentContext = this.contextByContextType.get(contextType); + if (currentContext) + return currentContext; + return null; + } + return this.lastContext ? this.lastContext : null; + } + contextHandlerAdded(payload, senderClientIdentity) { + const { handlerId, contextType } = payload; + const senderClientState = this.getClientState(senderClientIdentity); + if (!senderClientState) { + throw new Error(`Client with Identity: ${senderClientIdentity.uuid} ${senderClientIdentity.name}, tried to call addContextListener, is not connected to this Private Channel`); + } + if (contextType) { + const currentHandlersList = senderClientState.handlerIdsByContextTypes.get(contextType) || []; + senderClientState.handlerIdsByContextTypes.set(contextType, [...currentHandlersList, handlerId]); + } + else { + senderClientState.globalHandler = handlerId; + } + Array.from(this.clients.values()).forEach((currClientState) => { + if (currClientState.clientIdentity.endpointId !== senderClientIdentity.endpointId && + currClientState.onAddContextListenerHandlerId) { + this.provider.dispatch(currClientState.clientIdentity, currClientState.onAddContextListenerHandlerId, contextType); + } + }); + } + async contextHandlerRemoved(payload, removingClientIdentity) { + // MC: Made this removal async to ensure that onUnsubscribe handlers are hit before anything else happens. + const { handlerId } = payload; + const removingClientState = this.getClientState(removingClientIdentity); + if (removingClientState) { + let contextType; + if (removingClientState.globalHandler === handlerId) { + removingClientState.globalHandler = undefined; + } + else { + for (const [currContextType, handlersIds] of removingClientState.handlerIdsByContextTypes) { + const index = handlersIds.indexOf(handlerId); + if (index > -1) { + handlersIds.splice(index, 1); + contextType = currContextType; + } + } + } + // getting only valid client connections here, it is possible we haven't removed a disconnected client from the map yet + // so we need to ensure we don't dispatch to any disconnected client + // TODO: Take a look at our client disconnection logic and see if we can handle client disconnection cleanly + const clientsToDispatchTo = await this.getConnectedClients(); + const dispatchPromises = clientsToDispatchTo.map(async (otherClientState) => { + const { clientIdentity, clientIdentity: { endpointId }, onUnsubscribeHandlerId } = otherClientState; + if (endpointId !== removingClientIdentity.endpointId && onUnsubscribeHandlerId) { + await this.provider.dispatch(clientIdentity, onUnsubscribeHandlerId, contextType); + } + }); + try { + await Promise.all(dispatchPromises); + } + catch (error) { + console.error(`Problem when attempting to dispatch to onUnsubscribeHandlers. Error: ${error} Removing Client: ${handlerId}. uuid: ${removingClientIdentity.uuid}. name: ${removingClientIdentity.name}. endpointId: ${removingClientIdentity.endpointId}`); + throw new Error(error); + } + } + else { + console.warn(`Trying to remove a handler from a client that isn't mapped. handlerId: ${handlerId}. uuid: ${removingClientIdentity.uuid}. name: ${removingClientIdentity.name}. endpointId: ${removingClientIdentity.endpointId}.`); + } + } + nonStandardHandlerRemoved(payload, id) { + const { handlerId } = payload; + const clientState = this.getClientState(id); + if (clientState) { + if (clientState.onDisconnectHandlerId === handlerId) { + clientState.onDisconnectHandlerId = undefined; + } + else if (clientState.onAddContextListenerHandlerId === handlerId) { + clientState.onAddContextListenerHandlerId = undefined; + } + else if (clientState.onUnsubscribeHandlerId === handlerId) { + clientState.onUnsubscribeHandlerId = undefined; + } + } + else { + console.warn(`Trying to remove a handler from a client that isn't mapped. handlerId: ${handlerId}. clientIdentity: ${id}`); + } + } + onAddContextHandlerAdded(payload, senderClientIdentity) { + const clientState = this.getClientState(senderClientIdentity); + const { handlerId } = payload; + if (!clientState) { + throw new Error(`Client with Identity: ${senderClientIdentity.uuid} ${senderClientIdentity.name}, tried to call onAddContextListener, is not connected to this Private Channel`); + } + clientState.onAddContextListenerHandlerId = handlerId; + // FDC3 Spec says that the added listener should fire for all previously-registered addContextListeners from the other client + Array.from(this.clients.values()).forEach((otherClientState) => { + if (otherClientState.clientIdentity.endpointId !== senderClientIdentity.endpointId) { + Array.from(otherClientState.handlerIdsByContextTypes.keys()).forEach((subscribedContextType) => { + this.provider.dispatch(senderClientIdentity, handlerId, subscribedContextType); + }); + } + }); + } + onDisconnectHandlerAdded(payload, id) { + const clientState = this.getClientState(id); + const { handlerId } = payload; + if (!clientState) { + throw new Error(`Client with Identity: ${id.uuid} ${id.name}, tried to call onDisconnect, is not connected to this Private Channel`); + } + clientState.onDisconnectHandlerId = handlerId; + } + onUnsubscribeHandlerAdded(payload, id) { + const clientState = this.getClientState(id); + const { handlerId } = payload; + if (!clientState) { + throw new Error(`Client with Identity: ${id.uuid} ${id.name}, tried to call onUnsubscribe, is not connected to this Private Channel`); + } + clientState.onUnsubscribeHandlerId = handlerId; + } + removeClient(disconnectingClientIdentity) { + const disconnectingClientState = this.getClientState(disconnectingClientIdentity); + if (!disconnectingClientState) { + throw new Error(`Client with Identity: ${disconnectingClientIdentity.uuid} ${disconnectingClientIdentity.name}, tried to call disconnect, is not connected to this Private Channel`); + } + disconnectingClientState.handlerIdsByContextTypes.clear(); + this.clients.delete(disconnectingClientIdentity.endpointId); + } + async fireOnDisconnectForOtherClients(disconnectingClientIdentity) { + // TODO: call onDisconnect Handler of the other client only. + // CURRENTLY, just calling the onDisconnect handler for all the other clients. Once we limit it to just one other client, we can eliminate all the iteration code. + const { endpointId } = disconnectingClientIdentity; + // getting only valid client connections here, it is possible we haven't removed a disconnected client from the map yet + // so we need to ensure we don't dispatch to any disconnected client + // TODO: Take a look at our client disconnection logic and see if we can handle client disconnection cleanly + const clientsToDispatchTo = await this.getConnectedClients(); + const dispatchPromises = clientsToDispatchTo.map(async (otherClientState) => { + const { clientIdentity: { endpointId: otherClientEndpointId }, onDisconnectHandlerId } = otherClientState; + if (otherClientEndpointId !== endpointId && onDisconnectHandlerId) { + await this.provider.dispatch(otherClientState.clientIdentity, onDisconnectHandlerId); + } + }); + try { + await Promise.all(dispatchPromises); + } + catch (error) { + console.error(`Problem when attempting to dispatch to onDisconnectHandlers. Error: ${error} Disconnecting Client: uuid: ${disconnectingClientIdentity.uuid}. name: ${disconnectingClientIdentity.name}. endpointId: ${disconnectingClientIdentity.endpointId}`); + throw new Error(error); + } + } + async unsubscribeAll(clientIdentity) { + const { endpointId } = clientIdentity; + const state = this.clients.get(endpointId); + if (state) { + const contextTypeHandlerIds = Array.from(state.handlerIdsByContextTypes.values()).flat(); + const globalHandlerId = state.globalHandler; + if (contextTypeHandlerIds.length > 0) { + const unsubPromises = contextTypeHandlerIds.map(async (handlerId) => { + return this.contextHandlerRemoved({ handlerId }, clientIdentity); + }); + try { + await Promise.all(unsubPromises); + } + catch (error) { + console.error(error.message); + } + } + if (globalHandlerId) { + try { + await this.contextHandlerRemoved({ handlerId: globalHandlerId }, clientIdentity); + } + catch (error) { + console.error(error.message); + } + } + } + } + async handleClientDisconnecting(disconnectingClientIdentity) { + await this.unsubscribeAll(disconnectingClientIdentity); + this.removeClient(disconnectingClientIdentity); + await this.fireOnDisconnectForOtherClients(disconnectingClientIdentity); + } + registerNewClient(clientIdentity) { + if (!this.clients.has(clientIdentity.endpointId)) { + const clientSubscriptionState = { + clientIdentity, + handlerIdsByContextTypes: new Map(), + globalHandler: undefined, + onAddContextListenerHandlerId: undefined, + onUnsubscribeHandlerId: undefined, + onDisconnectHandlerId: undefined + }; + this.clients.set(clientIdentity.endpointId, clientSubscriptionState); + } + } + async getConnectedClients() { + const allClientInfo = await this.provider.getAllClientInfo(); + return Array.from(this.clients.values()).filter((clientState) => { + const { uuid, name } = clientState.clientIdentity; + return allClientInfo.some((clientInfo) => { + return name === clientInfo.name && uuid === clientInfo.uuid; + }); + }); + } + static init(channelProvider, id) { + return new PrivateChannelProvider(channelProvider, id); + } + }; + PrivateChannelProvider.PrivateChannelProvider = PrivateChannelProvider$1; + return PrivateChannelProvider; +} + +var hasRequiredInteropBroker; + +function requireInteropBroker () { + if (hasRequiredInteropBroker) return InteropBroker; + hasRequiredInteropBroker = 1; + var __classPrivateFieldSet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; + }; + var __classPrivateFieldGet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + var _InteropBroker_fdc3Info, _InteropBroker_contextGroups, _InteropBroker_providerPromise; + Object.defineProperty(InteropBroker, "__esModule", { value: true }); + InteropBroker.InteropBroker = void 0; + const base_1 = base; + const SessionContextGroupBroker_1 = __importDefault(requireSessionContextGroupBroker()); + const utils_1 = utils$3; + const isEqual_1 = __importDefault(require$$3); + const PrivateChannelProvider_1 = requirePrivateChannelProvider(); + const lazy_1 = lazy; + const defaultContextGroups = [ + { + id: 'green', + displayMetadata: { + color: '#00CC88', + name: 'green' + } + }, + { + id: 'purple', + displayMetadata: { + color: '#8C61FF', + name: 'purple' + } + }, + { + id: 'orange', + displayMetadata: { + color: '#FF8C4C', + name: 'orange' + } + }, + { + id: 'red', + displayMetadata: { + color: '#FF5E60', + name: 'red' + } + }, + { + id: 'pink', + displayMetadata: { + color: '#FF8FB8', + name: 'pink' + } + }, + { + id: 'yellow', + displayMetadata: { + color: '#E9FF8F', + name: 'yellow' + } + } + ]; + /** + * {@link https://developers.openfin.co/of-docs/docs/enable-color-linking} + * + * The Interop Broker is responsible for keeping track of the Interop state of the Platform, and for directing messages to the proper locations. + * + * @remarks This class contains some types related to FDC3 that are specific to OpenFin. {@link https://developers.openfin.co/of-docs/docs/fdc3-support-in-openfin OpenFin's FDC3 support} is forward- and backward-compatible. + * Standard types for {@link https://fdc3.finos.org/ FDC3} do not appear in OpenFin’s API documentation, to avoid duplication. + * + * --- + * + * There are 2 ways to inject custom functionality into the Interop Broker: + * + * **1. Configuration** + * + * At the moment, you can configure the default context groups for the Interop Broker without having to override it. To do so, include the `interopBrokerConfiguration` `contextGroups` option in your `platform` options in your manifest. This is the preferred method. + * ```js + * { + * "runtime": { + * "arguments": "--v=1 --inspect", + * "version": "alpha-v19" + * }, + * "platform": { + * "uuid": "platform_customization_local", + * "applicationIcon": "https://openfin.github.io/golden-prototype/favicon.ico", + * "autoShow": false, + * "providerUrl": "http://localhost:5555/provider.html", + * "interopBrokerConfiguration": { + * "contextGroups": [ + * { + * "id": "green", + * "displayMetadata": { + * "color": "#00CC88", + * "name": "green" + * } + * }, + * { + * "id": "purple", + * "displayMetadata": { + * "color": "#8C61FF", + * "name": "purple" + * } + * }, + * ] + * } + * } + * } + * ``` + * + * By default the Interop Broker logs all actions to the console. You can disable this by using the logging option in `interopBrokerConfiguration`: + * ```js + * { + * "runtime": { + * "arguments": "--v=1 --inspect", + * "version": "alpha-v19" + * }, + * "platform": { + * "uuid": "platform_customization_local", + * "applicationIcon": "https://openfin.github.io/golden-prototype/favicon.ico", + * "autoShow": false, + * "providerUrl": "http://localhost:5555/provider.html", + * "interopBrokerConfiguration": { + * "logging": { + * "beforeAction": { + * "enabled": false + * }, + * "afterAction": { + * "enabled": false + * } + * } + * } + * } + * } + * ``` + * + * --- + * **2. Overriding** + * + * Similarly to how {@link https://developers.openfin.co/docs/platform-customization#section-customizing-platform-behavior Platform Overriding} works, you can override functions in the Interop Broker in `fin.Platform.init`. An example of that is shown below. Overriding `isConnectionAuthorized` and `isActionAuthorized` will allow you to control allowed connections and allowed actions. + * + * However, if there is custom functionality you wish to include in the Interop Broker, please let us know. We would like to provide better configuration options so that you don't have to continually maintain your own override code. + * + * ```js + * fin.Platform.init({ + * overrideCallback: async (Provider) => { + * class Override extends Provider { + * async getSnapshot() { + * console.log('before getSnapshot') + * const snapshot = await super.getSnapshot(); + * console.log('after getSnapshot') + * return snapshot; + * } + * + * async applySnapshot({ snapshot, options }) { + * console.log('before applySnapshot') + * const originalPromise = super.applySnapshot({ snapshot, options }); + * console.log('after applySnapshot') + * + * return originalPromise; + * } + * }; + * return new Override(); + * }, + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async joinContextGroup(channelName = 'default', target) { + * console.log('before super joinContextGroup') + * super.joinContextGroup(channelName, target); + * console.log('after super joinContextGroup') + * } + * } + * + * return new Override(); + * } + * }); + * ``` + * + * --- + * + */ + let InteropBroker$1 = class InteropBroker extends base_1.Base { + /** + * @internal + */ + constructor(wire, createProvider, options) { + // Tip from Pierre and Michael from the overrideCheck work: Don't use bound methods for overrideable InteropBroker functions. + super(wire); + _InteropBroker_fdc3Info.set(this, void 0); + _InteropBroker_contextGroups.set(this, void 0); + _InteropBroker_providerPromise.set(this, void 0); + this.getProvider = () => { + return __classPrivateFieldGet(this, _InteropBroker_providerPromise, "f").getValue(); + }; + this.interopClients = new Map(); + this.contextGroupsById = new Map(); + __classPrivateFieldSet(this, _InteropBroker_contextGroups, options.contextGroups ?? [...defaultContextGroups], "f"); + __classPrivateFieldSet(this, _InteropBroker_fdc3Info, options.fdc3Info, "f"); + if (options?.logging) { + this.logging = options.logging; + } + this.intentClientMap = new Map(); + this.lastContextMap = new Map(); + this.sessionContextGroupMap = new Map(); + __classPrivateFieldSet(this, _InteropBroker_providerPromise, new lazy_1.Lazy(createProvider), "f"); + this.setContextGroupMap(); + this.setupChannelProvider(); + } + static createClosedConstructor(...args) { + return class OverrideableBroker extends InteropBroker { + constructor(...unused) { + if (unused.length) { + const [_ignore1, ignore2, opts] = unused; + if (opts && typeof opts === 'object' && !(0, isEqual_1.default)(opts, args[2])) { + // eslint-disable-next-line no-console + console.warn('You have modified the parameters of the InteropOverride constructor. This behavior is deprecated and will be removed in a future version. You can modify these options in your manifest. Please consult our Interop docs for guidance on migrating to the new override scheme.'); + super(args[0], args[1], opts); + return; + } + // eslint-disable-next-line no-console + console.warn('You are attempting to pass arguments to the InteropOverride constructor. This is not necessary, and these passed arguments will be ignored. You are likely using an older InteropBroker override scheme. Please consult our Interop docs for guidance on migrating to the new override scheme.'); + } + super(...args); + } + }; + } + /* + Client API + */ + /** + * Sets a context for the context group of the incoming current entity. + * @param setContextOptions - New context to set. + * @param clientIdentity - Identity of the client sender. + * + */ + setContext({ context }, clientIdentity) { + this.wire.sendAction('interop-broker-set-context').catch((e) => { + // don't expose, analytics-only call + }); + const clientState = this.getClientState(clientIdentity); + if (clientState && clientState.contextGroupId) { + const { contextGroupId } = clientState; + this.setContextForGroup({ context }, contextGroupId); + } + else if (clientState) { + // Client has not joined any context group behavior. + throw new Error('You must join a context group before you can set context.'); + } + else { + // This shouldn't get hit. + throw new Error(`Client with Identity: ${clientIdentity.uuid} ${clientIdentity.name} not in Client State Map`); + } + } + /** + * Sets a context for the context group. + * @param setContextOptions - New context to set. + * @param contextGroupId - Context group id. + * + */ + setContextForGroup({ context }, contextGroupId) { + this.wire.sendAction('interop-broker-set-context-for-group').catch((e) => { + // don't expose, analytics-only call + }); + const contextGroupState = this.contextGroupsById.get(contextGroupId); + if (!contextGroupState) { + throw new Error(`Unable to set context for context group that isn't in the context group mapping: ${contextGroupId}.`); + } + const contextIntegrityCheckResult = InteropBroker.checkContextIntegrity(context); + if (contextIntegrityCheckResult.isValid === false) { + throw new Error(`Failed to set Context - bad Context. Reason: ${contextIntegrityCheckResult.reason}. Context: ${JSON.stringify(context)}`); + } + const broadcastedContextType = context.type; + contextGroupState.set(broadcastedContextType, context); + this.lastContextMap.set(contextGroupId, broadcastedContextType); + const clientsInSameContextGroup = Array.from(this.interopClients.values()).filter((connectedClient) => connectedClient.contextGroupId === contextGroupId); + clientsInSameContextGroup.forEach((client) => { + for (const [, handlerInfo] of client.contextHandlers) { + if (InteropBroker.isContextTypeCompatible(broadcastedContextType, handlerInfo.contextType)) { + this.invokeContextHandler(client.clientIdentity, handlerInfo.handlerId, context); + } + } + }); + } + /** + * Get current context for a client subscribed to a Context Group. + * + * @remarks It takes an optional Context Type argument and returns the last context of that type. + * + * @param getContextOptions - Options for getting context + * @param clientIdentity - Identity of the client sender. + * + */ + getCurrentContext(getCurrentContextOptions, clientIdentity) { + this.wire.sendAction('interop-broker-get-current-context').catch((e) => { + // don't expose, analytics-only call + }); + const clientState = this.getClientState(clientIdentity); + if (!clientState?.contextGroupId) { + throw new Error('You must be a member of a context group to call getCurrentContext'); + } + const { contextGroupId } = clientState; + const contextGroupState = this.contextGroupsById.get(contextGroupId); + const lastContextType = this.lastContextMap.get(contextGroupId); + const contextType = getCurrentContextOptions?.contextType ?? lastContextType; + return contextGroupState && contextType ? contextGroupState.get(contextType) : undefined; + } + /* + Platform Window APIs + */ + // joinContextGroup and addClientToContextGroup are separate functions here, for easier overrides and separation of concerns. + // joinContextGroup checks all connections for matching identities, in case we have multiple connection from an entity. + /** + * Join all connections at the given identity (or just one if endpointId provided) to context group `contextGroupId`. + * If no target is specified, it adds the sender to the context group. + * joinContextGroup is responsible for checking connections at the incoming identity. It calls {@link InteropBroker#addClientToContextGroup InteropBroker.addClientToContextGroup} to actually group the client. + * Used by Platform Windows. + * + * @param joinContextGroupOptions - Id of the Context Group and identity of the entity to join to the group. + * @param senderIdentity - Identity of the client sender. + */ + async joinContextGroup({ contextGroupId, target }, senderIdentity) { + this.wire.sendAction('interop-broker-join-context-group').catch((e) => { + // don't expose, analytics-only call + }); + if (this.sessionContextGroupMap.has(contextGroupId)) { + throw new Error(utils_1.BROKER_ERRORS.joinSessionContextGroupWithJoinContextGroup); + } + if (target) { + // If an endpointId is provided, use that. This will likely be used by external adapters. + if (InteropBroker.hasEndpointId(target)) { + await this.addClientToContextGroup({ contextGroupId }, target); + } + // Sanity check here in case a single app has multiple connections + try { + const allConnections = this.channel.connections.filter((x) => x.uuid === target.uuid && x.name === target.name); + if (!allConnections.length) { + throw new Error(`Given Identity ${target.uuid} ${target.name} is not connected to the Interop Broker.`); + } + if (allConnections.length > 1) { + // Should figure out how we want to handle this situation. In the meantime, just change context group for all connections. + console.warn(`More than one connection found for identity ${target.uuid} ${target.name}`); + } + const promises = []; + for (const connection of allConnections) { + promises.push(this.addClientToContextGroup({ contextGroupId }, connection)); + } + await Promise.all(promises); + } + catch (error) { + throw new Error(error); + } + } + else { + // No target provided, add the sender to the context group. + await this.addClientToContextGroup({ contextGroupId }, senderIdentity); + } + } + // addClientToContextGroup does the actual addition of the client to the Context Group + /** + * Helper function for {@link InteropBroker#joinContextGroup InteropBroker.joinContextGroup}. Does the work of actually adding the client to the Context Group. + * Used by Platform Windows. + * + * @param addClientToContextGroupOptions - Contains the contextGroupId + * @param clientIdentity - Identity of the client sender. + */ + async addClientToContextGroup({ contextGroupId }, clientIdentity) { + this.wire.sendAction('interop-broker-add-client-to-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const clientSubscriptionState = this.getClientState(clientIdentity); + if (!clientSubscriptionState) { + throw new Error(`Client with Identity: ${clientIdentity.uuid} ${clientIdentity.name} not in Client State Map`); + } + if (!this.getContextGroups().find((contextGroupInfo) => contextGroupInfo.id === contextGroupId)) { + throw new Error(`Attempting to join a context group that does not exist: ${contextGroupId}. You may only join existing context groups.`); + } + const oldContextGroupId = clientSubscriptionState.contextGroupId; + if (oldContextGroupId !== contextGroupId) { + clientSubscriptionState.contextGroupId = contextGroupId; + await this.setCurrentContextGroupInClientOptions(clientIdentity, contextGroupId); + const contextGroupMap = this.contextGroupsById.get(contextGroupId); + for (const [, handlerInfo] of clientSubscriptionState.contextHandlers) { + const { contextType, handlerId } = handlerInfo; + if (contextType === undefined) { + // Send this single handler all of the context, because it accepts all. + contextGroupMap.forEach((context, _) => { + this.invokeContextHandler(clientIdentity, handlerId, context); + }); + } + else if (contextGroupMap.has(contextType)) { + const contextForType = contextGroupMap.get(contextType); + if (contextForType) { + this.invokeContextHandler(clientIdentity, handlerId, contextForType); + } + } + } + } + } + // Removes the target from its context group. Similar structure to joinContextGroup. + /** + * Removes the specified target from a context group. + * If no target is specified, it removes the sender from their context group. + * removeFromContextGroup is responsible for checking connections at the incoming identity. + * + * @remarks It calls {@link InteropBroker#removeClientFromContextGroup InteropBroker.removeClientFromContextGroup} to actually ungroup + * the client. Used by Platform Windows. + * + * @param removeFromContextGroupOptions - Contains the target identity to remove. + * @param senderIdentity - Identity of the client sender. + */ + async removeFromContextGroup({ target }, senderIdentity) { + this.wire.sendAction('interop-broker-remove-from-context-group').catch((e) => { + // don't expose, analytics-only call + }); + if (target) { + // If an endpointId is provided, use that. This will likely be used by external adapters. + if (InteropBroker.hasEndpointId(target)) { + await this.removeClientFromContextGroup(target); + } + try { + // Sanity check here in case a single app has multiple connections + const allConnections = this.channel.connections.filter((x) => x.uuid === target.uuid && x.name === target.name); + if (!allConnections.length) { + throw new Error(`No connection found for given Identity ${target.uuid} ${target.name}`); + } + if (allConnections.length > 1) { + console.warn(`More than one connection found for identity ${target.uuid} ${target.name}`); + } + const promises = []; + for (const connection of allConnections) { + promises.push(this.removeClientFromContextGroup(connection)); + } + await Promise.all(promises); + } + catch (error) { + throw new Error(error); + } + } + else { + // No target provided, remove the sender from the context group. + await this.removeClientFromContextGroup(senderIdentity); + } + } + // removeClientFromContextGroup does the actual remove of the client from the Context Group + /** + * Helper function for {@link InteropBroker#removeFromContextGroup InteropBroker.removeFromContextGroup}. Does the work of actually removing the client from the Context Group. + * Used by Platform Windows. + * + * @property { ClientIdentity } clientIdentity - Identity of the client sender. + */ + async removeClientFromContextGroup(clientIdentity) { + this.wire.sendAction('interop-broker-remove-client-from-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const clientState = this.getClientState(clientIdentity); + if (clientState) { + clientState.contextGroupId = undefined; + } + await this.setCurrentContextGroupInClientOptions(clientIdentity, null); + } + // Used by platform windows to know what client groups the provider has declared. Also used internally to access context groups. Overrideable so that the platform developer can modify it. + /** + * Returns the Interop-Broker-defined context groups available for an entity to join. Because this function is used in the rest of the Interop Broker to fetch the Context Groups, overriding this allows you to customize the Context Groups for the Interop Broker. However, we recommend customizing the context groups through configuration instead. + * Used by Platform Windows. + * + */ + // eslint-disable-next-line class-methods-use-this + getContextGroups() { + this.wire.sendAction('interop-broker-get-context-groups').catch((e) => { + // don't expose, analytics-only call + }); + // Create copy for immutability + return __classPrivateFieldGet(this, _InteropBroker_contextGroups, "f").map((contextGroup) => { + return { ...contextGroup }; + }); + } + // Used to by platform windows to get display metadata for a context group. + /** + * Gets display info for a context group + * + * @remarks Used by Platform Windows. + * + * @param getInfoForContextGroupOptions - Contains contextGroupId, the context group you wish to get display info for. + * + */ + getInfoForContextGroup({ contextGroupId }) { + this.wire.sendAction('interop-broker-get-info-for-context-group').catch((e) => { + // don't expose, analytics-only call + }); + return this.getContextGroups().find((contextGroup) => contextGroup.id === contextGroupId); + } + // Used by platform windows to get all clients for a context group. + /** + * Gets all clients for a context group. + * + * @remarks **This is primarily used for platform windows. Views within a platform should not have to use this API.** + * Returns the Interop-Broker-defined context groups available for an entity to join. + * + * @param getAllClientsInContextGroupOptions - Contains contextGroupId, the context group you wish to get clients for. + * + */ + getAllClientsInContextGroup({ contextGroupId }) { + this.wire.sendAction('interop-broker-get-all-clients-in-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const clientsInContextGroup = Array.from(this.interopClients.values()) + .filter((connectedClient) => connectedClient.contextGroupId === contextGroupId) + .map((subscriptionState) => { + return subscriptionState.clientIdentity; + }); + return clientsInContextGroup; + } + /** + * Responsible for launching of applications that can handle a given intent, and delegation of intents to those applications. + * Must be overridden. + * + * @remarks To make this call FDC3-Compliant it would need to return an IntentResolution. + * + * ```js + * interface IntentResolution { + * source: TargetApp; + * // deprecated, not assignable from intent listeners + * data?: object; + * version: string; + * } + * ``` + * + * More information on the IntentResolution type can be found in the [FDC3 documentation](https://fdc3.finos.org/docs/api/ref/IntentResolution). + * + * @param intent The combination of an action and a context that is passed to an application for resolution. + * @param clientIdentity Identity of the Client making the request. + * + * @example + * ```js + * // override call so we set intent target and create view that will handle it + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async handleFiredIntent(intent) { + * super.setIntentTarget(intent, { uuid: 'platform-uuid', name: 'intent-view' }); + * const platform = fin.Platform.getCurrentSync(); + * const win = fin.Window.wrapSync({ name: 'foo', uuid: 'platform-uuid' }); + * const createdView = await platform.createView({ url: 'http://openfin.co', name: 'intent-view' }, win.identity); + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + // eslint-disable-next-line class-methods-use-this + async handleFiredIntent(intent, clientIdentity // TODO(CORE-811): remove inline intersected type + ) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.raiseIntent', 'InteropBroker.handleFiredIntent', clientIdentity, 'interopClient.fireIntent'); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.fireIntent); + } + /** + * Should be called in {@link InteropBroker#handleFiredIntent InteropBroker.handleFiredIntent}. + * While handleFiredIntent is responsible for launching applications, setIntentTarget is used to tell the InteropBroker which application should receive the intent when it is ready. + * @param intent The combination of an action and a context that is passed to an application for resolution. + * @param target - Identity of the target that will handle the intent. + * + */ + async setIntentTarget(intent, target) { + this.wire.sendAction('interop-broker-set-intent-target').catch((e) => { + // don't expose, this is only for api analytics purposes + }); + const targetInfo = this.intentClientMap.get(target.name); + const handlerId = `intent-handler-${intent.name}`; + if (!targetInfo) { + this.intentClientMap.set(target.name, new Map()); + const newHandlerInfoMap = this.intentClientMap.get(target.name); + if (newHandlerInfoMap) { + newHandlerInfoMap.set(handlerId, { isReady: false, pendingIntents: [intent] }); + } + } + else { + const handlerInfo = targetInfo.get(handlerId); + if (!handlerInfo) { + targetInfo.set(handlerId, { isReady: false, pendingIntents: [intent] }); + } + else { + handlerInfo.pendingIntents.push(intent); + if (handlerInfo.clientIdentity && handlerInfo.isReady) { + const { clientIdentity, pendingIntents } = handlerInfo; + try { + const intentToSend = pendingIntents[pendingIntents.length - 1]; + await this.invokeIntentHandler(clientIdentity, handlerId, intentToSend); + handlerInfo.pendingIntents = []; + } + catch (error) { + console.error(`Error invoking intent handler for client ${clientIdentity.uuid}/${clientIdentity.name}/${clientIdentity.endpointId}`); + handlerInfo.isReady = false; + } + } + } + } + } + /** + * Responsible for returning information on a particular Intent. + * + * @remarks Whenever InteropClient.getInfoForIntent is called this function will fire. The options argument gives you + * access to the intent name and any optional context that was passed and clientIdentity is the identity of the client + * that made the call. Ideally here you would fetch the info for the intent and return it with the shape that the + * InteropClient.getInfoForIntent call is expecting. + * + * To make this call FDC3-Compliant it would need to return an App Intent: + * + * ```js + * // { + * // intent: { name: "StartChat", displayName: "Chat" }, + * // apps: [{ name: "Skype" }, { name: "Symphony" }, { name: "Slack" }] + * // } + * ``` + * + * More information on the AppIntent type can be found in the [FDC3 documentation](https://fdc3.finos.org/docs/api/ref/AppIntent). + * + * @param options + * @param clientIdentity Identity of the Client making the request. + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async handleInfoForIntent(options, clientIdentity) { + * // Your code goes here. + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + // eslint-disable-next-line class-methods-use-this + async handleInfoForIntent(options, clientIdentity // TODO(CORE-811): remove inline intersected type + ) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.findIntent', 'InteropBroker.handleInfoForIntent', clientIdentity, 'interopClient.getInfoForIntent'); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.getInfoForIntent); + } + /** + * Responsible for returning information on which Intents are meant to handle a specific Context. + * Must be overridden. + * + * @remarks Responsible for returning information on which Intents are meant to handle a specific Context. Must be overridden. + * + * Whenever InteropClient.getInfoForIntentsByContext is called this function will fire. The context argument gives you access to the context that the client wants information on and clientIdentity is the identity of the client that made the call. Ideally here you would fetch the info for any intent that can handle and return it with the shape that the InteropClient.getInfoForIntentsByContext call is expecting. + * + * To make this call FDC3-Compliant it would need to return an array of AppIntents: + * + * ```js + * // [{ + * // intent: { name: "StartCall", displayName: "Call" }, + * // apps: [{ name: "Skype" }] + * // }, + * // { + * // intent: { name: "StartChat", displayName: "Chat" }, + * // apps: [{ name: "Skype" }, { name: "Symphony" }, { name: "Slack" }] + * // }]; + * ``` + * + * More information on the AppIntent type can be found in the [FDC3 documentation](https://fdc3.finos.org/docs/api/ref/AppIntent). + * + * @param context Data passed between entities and applications. + * @param clientIdentity Identity of the Client making the request. + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async handleInfoForIntentsByContext(context, clientIdentity) { + * // Your code goes here. + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + // eslint-disable-next-line class-methods-use-this + async handleInfoForIntentsByContext(context, clientIdentity // TODO(CORE-811): remove inline intersected type + ) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.findIntentsByContext', 'InteropBroker.handleInfoForIntentsByContext', clientIdentity, 'interopClient.getInfoForIntentsByContext'); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.getInfoForIntentsByContext); + } + /** + * Responsible for resolving an Intent based on a specific Context. + * Must be overridden. + * + * @remarks Whenever InteropClient.fireIntentForContext is called this function will fire. The contextForIntent argument + * gives you access to the context that will be resolved to an intent. It also can optionally contain any metadata relevant + * to resolving it, like a specific app the client wants the context to be handled by. The clientIdentity is the identity + * of the client that made the call. + * + * To make this call FDC3-Compliant it would need to return an IntentResolution: + * + * ```js + * // { + * // intent: { name: "StartChat", displayName: "Chat" }, + * // apps: [{ name: "Skype" }, { name: "Symphony" }, { name: "Slack" }] + * // } + * ``` + * + * More information on the IntentResolution type can be found in the [FDC3 documentation](https://fdc3.finos.org/docs/api/ref/Metadata#intentresolution). + * + * @param contextForIntent Data passed between entities and applications. + * @param clientIdentity Identity of the Client making the request. + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async handleFiredIntentForContext(contextForIntent, clientIdentity) { + * // Your code goes here. + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + // eslint-disable-next-line class-methods-use-this + async handleFiredIntentForContext(contextForIntent, clientIdentity) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.raiseIntentForContext', 'InteropBroker.handleFiredIntentForContext', clientIdentity, 'interopClient.fireIntentForContext'); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.fireIntentForContext); + } + /** + * Provides the identity of any Interop Client that disconnects from the Interop Broker. It is meant to be overriden. + * @param clientIdentity + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async clientDisconnected(clientIdentity) { + * const { uuid, name } = clientIdentity; + * console.log(`Client with identity ${uuid}/${name} has been disconnected`); + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + // eslint-disable-next-line class-methods-use-this + async clientDisconnected(clientIdentity) { + // This function is called in channel.onDisconnection. + // It is meant to be overridden to inform when an Interop Client has been disconnected. + } + /** + * Responsible for resolving an fdc3.open call. + * Must be overridden. + * @param fdc3OpenOptions fdc3.open options + * @param clientIdentity Identity of the Client making the request. + */ + // eslint-disable-next-line class-methods-use-this + async fdc3HandleOpen({ app, context }, clientIdentity) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.open', 'InteropBroker.fdc3HandleOpen', clientIdentity); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.fdc3Open); + } + /** + * Responsible for resolving the fdc3.findInstances call. + * Must be overridden + * @param app AppIdentifier that was passed to fdc3.findInstances + * @param clientIdentity Identity of the Client making the request. + */ + // eslint-disable-next-line class-methods-use-this + async fdc3HandleFindInstances(app, clientIdentity) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.open', 'InteropBroker.fdc3HandleFindInstances', clientIdentity); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.fdc3FindInstances); + } + /** + * Responsible for resolving the fdc3.getAppMetadata call. + * Must be overridden + * @param app AppIdentifier that was passed to fdc3.getAppMetadata + * @param clientIdentity Identity of the Client making the request. + */ + // eslint-disable-next-line class-methods-use-this + async fdc3HandleGetAppMetadata(app, clientIdentity) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.getAppMetadata', 'InteropBroker.fdc3HandleGetAppMetadata', clientIdentity); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.fdc3GetAppMetadata); + } + /** + * This function is called by the Interop Broker whenever a Context handler would fire. + * For FDC3 2.0 you would need to override this function and add the contextMetadata as + * part of the Context object. Then would you need to call + * super.invokeContextHandler passing it this new Context object along with the clientIdentity and handlerId + * @param clientIdentity + * @param handlerId + * @param context + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async invokeContextHandler(clientIdentity, handlerId, context) { + * return super.invokeContextHandler(clientIdentity, handlerId, { + * ...context, + * contextMetadata: { + * source: { + * appId: 'openfin-app', + * instanceId: '3D54D456D9HT0' + * } + * } + * }); + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + async invokeContextHandler(clientIdentity, handlerId, context) { + const provider = await this.getProvider(); + try { + await provider.dispatch(clientIdentity, handlerId, context); + } + catch (error) { + console.error(`Error invoking context handler ${handlerId} for context type ${context.type} in client ${clientIdentity.uuid}/${clientIdentity.name}/${clientIdentity.endpointId}`, error); + } + } + /** + * This function is called by the Interop Broker whenever an Intent handler would fire. + * For FDC3 2.0 you would need to override this function and add the contextMetadata as + * part of the Context object inside the Intent object. Then would you need to call + * super.invokeIntentHandler passing it this new Intent object along with the clientIdentity and handlerId + * @param ClientIdentity + * @param handlerId + * @param context + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async invokeIntentHandler(clientIdentity, handlerId, context) { + * const { context } = intent; + * return super.invokeIntentHandler(clientIdentity, handlerId, { + * ...intent, + * context: { + * ...context, + * contextMetadata: { + * source: { + * appId: 'openfin-app', + * instanceId: '3D54D456D9HT0' + * } + * } + * } + * }); + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + async invokeIntentHandler(clientIdentity, handlerId, intent) { + const provider = await this.getProvider(); + await provider.dispatch(clientIdentity, handlerId, intent); + } + /** + * Responsible for resolving fdc3.getInfo for FDC3 2.0 + * Would need to return the optionalFeatures and appMetadata for the {@link https://fdc3.finos.org/docs/api/ref/Metadata#implementationmetadata ImplementationMetadata}. + * Must be overridden. + * @param clientIdentity + * + */ + // eslint-disable-next-line class-methods-use-this + async fdc3HandleGetInfo(payload, clientIdentity) { + const { fdc3Version } = payload; + return { + fdc3Version, + ...__classPrivateFieldGet(this, _InteropBroker_fdc3Info, "f"), + optionalFeatures: { + OriginatingAppMetadata: false, + UserChannelMembershipAPIs: true + }, + appMetadata: { + appId: '', + instanceId: '' + } + }; + } + /** + * Returns an array of info for each Interop Client connected to the Interop Broker. + * + * FDC3 2.0: Use the endpointId in the ClientInfo as the instanceId when generating + * an AppIdentifier. + * + * @remarks FDC3 2.0 Note: When needing an instanceId to generate an AppIdentifier use this call to + * get the endpointId and use it as the instanceId. In the Example below we override handleFiredIntent + * and then call super.getAllClientInfo to generate the AppIdentifier for the IntentResolution. + * + * + * @example + * ```js + * // FDC3 2.0 Example: + * fin.Platform.init({ + * interopOverride: async (InteropBroker, ...args) => { + * class Override extends InteropBroker { + * async handleFiredIntent(intent) { + * super.setIntentTarget(intent, { uuid: 'platform-uuid', name: 'intent-view' }); + * const platform = fin.Platform.getCurrentSync(); + * const win = fin.Window.wrapSync({ name: 'foo', uuid: 'platform-uuid' }); + * const createdView = await platform.createView({ url: 'http://openfin.co', name: 'intent-view' }, win.identity); + * + * const allClientInfo = await super.getAllClientInfo(); + * + * const infoForTarget = allClientInfo.find((clientInfo) => { + * return clientInfo.uuid === 'platform-uuid' && clientInfo.name === 'intent-view'; + * }); + * + * const source = { + * appId: 'intent-view', + * instanceId: infoForTarget.endpointId + * } + * + * return { + * source, + * intent: intent.name + * } + * + * } + * } + * return new Override(...args); + * } + * }); + * ``` + */ + async getAllClientInfo() { + const provider = await this.getProvider(); + return provider.getAllClientInfo(); + } + /* + Snapshot APIs + */ + // Used to save interop broker state in snapshots + decorateSnapshot(snapshot) { + return { ...snapshot, interopSnapshotDetails: { contextGroupStates: this.getContextGroupStates() } }; + } + // Used to restore interop broker state in snapshots. + applySnapshot(snapshot, options) { + const contextGroupStates = snapshot?.interopSnapshotDetails?.contextGroupStates; + if (contextGroupStates) { + if (!options?.closeExistingWindows) { + this.updateExistingClients(contextGroupStates); + } + this.rehydrateContextGroupStates(contextGroupStates); + } + } + updateExistingClients(contextGroupStates) { + const clients = this.interopClients; + clients.forEach((subState) => { + const { clientIdentity, contextGroupId, contextHandlers } = subState; + if (contextGroupId) { + const groupContexts = contextGroupStates[contextGroupId]; + for (const [, context] of Object.entries(groupContexts)) { + contextHandlers.forEach((contextHandler) => { + const { handlerId, contextType } = contextHandler; + if (InteropBroker.isContextTypeCompatible(context.type, contextType)) { + this.invokeContextHandler(clientIdentity, handlerId, context); + } + }); + } + } + }); + } + // Used to store context group state in snapshots + getContextGroupStates() { + return InteropBroker.toObject(this.contextGroupsById); + } + // Used to rehydrate the context state from a snapshot + rehydrateContextGroupStates(incomingContextGroupStates) { + const contextGroupStates = Object.entries(incomingContextGroupStates); + for (const [contextGroupId, contexts] of contextGroupStates) { + const contextObjects = Object.entries(contexts); + for (const [contextType, context] of contextObjects) { + if (this.contextGroupsById.has(contextGroupId)) { + const currentContextGroupState = this.contextGroupsById.get(contextGroupId); + currentContextGroupState.set(contextType, context); + } + else { + // This logic will change when dynamic context group creation comes in. + console.warn(`Attempting to set a context group that isn't in the context group mapping. Skipping context group rehydration for: ${contextGroupId}`); + } + } + } + } + /* + Internal Context Handler APIs + */ + // Used to give context to a client that has registered their context handler + contextHandlerRegistered({ contextType, handlerId }, clientIdentity) { + const handlerInfo = { contextType, handlerId }; + const clientState = this.getClientState(clientIdentity); + clientState?.contextHandlers.set(handlerId, handlerInfo); + if (clientState && clientState.contextGroupId) { + const { contextGroupId } = clientState; + const contextGroupMap = this.contextGroupsById.get(contextGroupId); + if (contextType === undefined) { + // Send this single handler all of the context, because it accepts all. + contextGroupMap.forEach((context, _) => { + this.invokeContextHandler(clientIdentity, handlerId, context); + }); + } + else if (contextGroupMap.has(contextType)) { + const contextForType = contextGroupMap.get(contextType); + if (contextForType) { + this.invokeContextHandler(clientIdentity, handlerId, contextForType); + } + } + } + } + // eslint-disable-next-line class-methods-use-this + async intentHandlerRegistered(payload, clientIdentity) { + const { handlerId } = payload; + const clientIntentInfo = this.intentClientMap.get(clientIdentity.name); + const handlerInfo = clientIntentInfo?.get(handlerId); + if (!clientIntentInfo) { + this.intentClientMap.set(clientIdentity.name, new Map()); + const newHandlerInfoMap = this.intentClientMap.get(clientIdentity.name); + if (newHandlerInfoMap) { + newHandlerInfoMap.set(handlerId, { isReady: true, pendingIntents: [], clientIdentity }); + } + } + else if (!handlerInfo) { + clientIntentInfo.set(handlerId, { isReady: true, pendingIntents: [], clientIdentity }); + } + else { + const { pendingIntents } = handlerInfo; + handlerInfo.clientIdentity = clientIdentity; + handlerInfo.isReady = true; + try { + if (pendingIntents.length > 0) { + const intentToSend = pendingIntents[pendingIntents.length - 1]; + await this.invokeIntentHandler(clientIdentity, handlerId, intentToSend); + handlerInfo.pendingIntents = []; + } + } + catch (error) { + console.error(`Error invoking intent handler: ${handlerId} for client ${clientIdentity.uuid}/${clientIdentity.name}/${clientIdentity.endpointId}`); + } + } + } + // Used to remove a context handler for a client + removeContextHandler({ handlerId }, clientIdentity) { + const clientState = this.getClientState(clientIdentity); + if (clientState) { + clientState.contextHandlers.delete(handlerId); + } + } + handleJoinSessionContextGroup({ sessionContextGroupId }, clientIdentity) { + try { + if (!sessionContextGroupId) { + throw new Error('Failed to join session context group: must specify group id.'); + } + const sessionContextGroup = this.sessionContextGroupMap.get(sessionContextGroupId); + if (sessionContextGroup) { + sessionContextGroup.registerNewClient(clientIdentity); + } + else { + const newSessionContextGroupBroker = new SessionContextGroupBroker_1.default(this.channel, sessionContextGroupId); + newSessionContextGroupBroker.registerNewClient(clientIdentity); + this.sessionContextGroupMap.set(sessionContextGroupId, newSessionContextGroupBroker); + } + return { hasConflict: this.contextGroupsById.has(sessionContextGroupId) }; + } + catch (error) { + throw new Error(error); + } + } + /* + Internal Utilties + */ + // Getter for interop info for a client. + getClientState(id) { + return this.interopClients.get(id.endpointId); + } + // Util for getContextGroupStates. Serializes the contextGroupStates object so we can store it. + static toObject(map) { + const objectFromMap = Object.fromEntries(map); + const newObject = {}; + Object.entries(objectFromMap).forEach(([contextGroupId, contextMap]) => { + const newContextObject = Object.fromEntries(contextMap); + newObject[contextGroupId] = newContextObject; + }); + return newObject; + } + static checkContextIntegrity(context) { + if (!context) { + return { isValid: false, reason: 'No context supplied' }; + } + if (typeof context !== 'object') { + return { isValid: false, reason: 'Context must be an Object' }; + } + if (!context.type) { + return { isValid: false, reason: 'Context must have a type property' }; + } + if (context.id && typeof context.id !== 'object') { + return { + isValid: false, + reason: 'Context id must be an Object populated with key-value identifiers (if set)' + }; + } + if (context.id) { + const { id } = context; + const keys = Object.keys(id); + let foundBadIdentifier = false; + if (!keys.length) { + return { isValid: false, reason: 'Context id must have at least one key-value identifier' }; + } + keys.forEach((key) => { + if (typeof key !== 'string' || typeof id[key] !== 'string') { + foundBadIdentifier = true; + } + }); + if (foundBadIdentifier) { + return { isValid: false, reason: 'Context id key-value identifiers must be of type string' }; + } + } + if (context.name && typeof context.name !== 'string') { + return { isValid: false, reason: 'Context name must be of string type (if set)' }; + } + return { isValid: true }; + } + // Util to check a client identity. + static hasEndpointId(target) { + return target.endpointId !== undefined; + } + // Util to check if we should send a context to a handler. + static isContextTypeCompatible(contextType, registeredContextType) { + return typeof registeredContextType === 'undefined' || contextType === registeredContextType; + } + // Setup function for state mapping + setContextGroupMap() { + // This way, if a user overrides this.getContextGroups, it's reflected in the contextGroupMapping. + for (const contextGroupInfo of this.getContextGroups()) { + this.contextGroupsById.set(contextGroupInfo.id, new Map()); + } + } + async setCurrentContextGroupInClientOptions(clientIdentity, contextGroupId) { + try { + const entityInfo = await this.fin.System.getEntityInfo(clientIdentity.uuid, clientIdentity.name); + let entity; + if (entityInfo.entityType === 'view') { + entity = await this.fin.View.wrap(clientIdentity); + } + else if (entityInfo.entityType === 'window') { + entity = await this.fin.Window.wrap(clientIdentity); + } + if (entity) { + await entity.updateOptions({ + interop: { + currentContextGroup: contextGroupId + } + }); + } + } + catch (error) { + // May file in interop + } + } + async setupChannelProvider() { + try { + const channel = await this.getProvider(); + this.channel = channel; + this.wireChannel(channel); + } + catch (error) { + throw new Error(`Error setting up Interop Broker Channel Provider: ${error}`); + } + } + // Setup Channel Connection Logic + wireChannel(channel) { + channel.onConnection(async (clientIdentity, // TODO(CORE-811): remove inline intersected type + payload) => { + if (!(await this.isConnectionAuthorized(clientIdentity, payload))) { + throw new Error(`Connection not authorized for ${clientIdentity.uuid}, ${clientIdentity.name}`); + } + if (!clientIdentity.endpointId) { + throw new Error('Version too old to be compatible with Interop. Please upgrade your runtime to a more recent version.'); + } + const clientSubscriptionState = { + contextGroupId: undefined, + contextHandlers: new Map(), + clientIdentity + }; + // Only allow the client to join a contextGroup that actually exists. + if (payload?.currentContextGroup && this.contextGroupsById.has(payload.currentContextGroup)) { + clientSubscriptionState.contextGroupId = payload?.currentContextGroup; + } + this.interopClients.set(clientIdentity.endpointId, clientSubscriptionState); + }); + channel.onDisconnection((clientIdentity) => { + this.interopClients.delete(clientIdentity.endpointId); + const targetInfo = this.intentClientMap.get(clientIdentity.name); + if (targetInfo && clientIdentity.uuid === this.fin.me.uuid) { + targetInfo.forEach((handler) => { + handler.isReady = false; + }); + } + this.sessionContextGroupMap.forEach((sessionContextGroup) => { + sessionContextGroup.onDisconnection(clientIdentity); + }); + this.clientDisconnected(clientIdentity); + }); + channel.beforeAction(async (action, payload, clientIdentity) => { + if (!(await this.isActionAuthorized(action, payload, clientIdentity))) { + throw new Error(`Action (${action}) not authorized for ${clientIdentity.uuid}, ${clientIdentity.name}`); + } + if (this.logging?.beforeAction?.enabled) { + console.log(action, payload, clientIdentity); + } + }); + channel.afterAction((action, payload, clientIdentity) => { + if (this.logging?.afterAction?.enabled) { + console.log(action, payload, clientIdentity); + } + }); + // Client functions + channel.register('setContext', this.setContext.bind(this)); + channel.register('fireIntent', this.handleFiredIntent.bind(this)); + channel.register('getCurrentContext', this.getCurrentContext.bind(this)); + channel.register('getInfoForIntent', this.handleInfoForIntent.bind(this)); + channel.register('getInfoForIntentsByContext', this.handleInfoForIntentsByContext.bind(this)); + channel.register('fireIntentForContext', this.handleFiredIntentForContext.bind(this)); + // Platform window functions + channel.register('getContextGroups', this.getContextGroups.bind(this)); + channel.register('joinContextGroup', this.joinContextGroup.bind(this)); + channel.register('removeFromContextGroup', this.removeFromContextGroup.bind(this)); + channel.register('getAllClientsInContextGroup', this.getAllClientsInContextGroup.bind(this)); + channel.register('getInfoForContextGroup', this.getInfoForContextGroup.bind(this)); + // Internal methods + channel.register('contextHandlerRegistered', this.contextHandlerRegistered.bind(this)); + channel.register('intentHandlerRegistered', this.intentHandlerRegistered.bind(this)); + channel.register('removeContextHandler', this.removeContextHandler.bind(this)); + channel.register('sessionContextGroup:createIfNeeded', this.handleJoinSessionContextGroup.bind(this)); + // fdc3 only methods + channel.register('fdc3Open', this.fdc3HandleOpen.bind(this)); + channel.register('fdc3v2FindIntentsByContext', this.handleInfoForIntentsByContext.bind(this)); + channel.register('fdc3FindInstances', this.fdc3HandleFindInstances.bind(this)); + channel.register('fdc3GetAppMetadata', this.fdc3HandleGetAppMetadata.bind(this)); + channel.register('fdc3v2GetInfo', async (payload, clientIdentity) => { + return this.fdc3HandleGetInfo.bind(this)(payload, clientIdentity); + }); + channel.register('createPrivateChannelProvider', async (payload) => { + const { channelId } = payload; + const channelProvider = await this.fin.InterApplicationBus.Channel.create(channelId); + PrivateChannelProvider_1.PrivateChannelProvider.init(channelProvider, channelId); + }); + } + /** + * Can be used to completely prevent a connection. Return false to prevent connections. Allows all connections by default. + * @param _id the identity tryinc to connect + * @param _connectionPayload optional payload to use in custom implementations, will be undefined by default + */ + isConnectionAuthorized(_id, _connectionPayload) { + this.wire.sendAction('interop-broker-is-connection-authorized').catch((e) => { + // don't expose, analytics-only call + }); + return Promise.resolve(true); + } + /** + * Called before every action to check if this entity should be allowed to take the action. + * Return false to prevent the action + * @param _action the string action to authorize in camel case + * @param _payload the data being sent for this action + * @param _identity the connection attempting to dispatch this action + */ + isActionAuthorized(_action, _payload, _identity) { + this.wire.sendAction('interop-broker-is-action-authorized').catch((e) => { + // don't expose, analytics-only call + }); + return Promise.resolve(true); + } + }; + InteropBroker.InteropBroker = InteropBroker$1; + _InteropBroker_fdc3Info = new WeakMap(), _InteropBroker_contextGroups = new WeakMap(), _InteropBroker_providerPromise = new WeakMap(); + return InteropBroker; +} + +var InteropClient = {}; + +var SessionContextGroupClient$1 = {}; + +var __classPrivateFieldSet$2 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$2 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _SessionContextGroupClient_clientPromise; +Object.defineProperty(SessionContextGroupClient$1, "__esModule", { value: true }); +const base_1$2 = base; +const utils_1$2 = utils$3; +class SessionContextGroupClient extends base_1$2.Base { + constructor(wire, client, id) { + super(wire); + _SessionContextGroupClient_clientPromise.set(this, void 0); + this.id = id; + __classPrivateFieldSet$2(this, _SessionContextGroupClient_clientPromise, client, "f"); + } + /** + * Sets a context for the session context group. + * @param context - New context to set. + * + * @tutorial interop.setContext + */ + async setContext(context) { + this.wire.sendAction('interop-session-context-group-set-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet$2(this, _SessionContextGroupClient_clientPromise, "f"); + return client.dispatch(`sessionContextGroup:setContext-${this.id}`, { + sessionContextGroupId: this.id, + context + }); + } + async getCurrentContext(type) { + this.wire.sendAction('interop-session-context-group-get-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet$2(this, _SessionContextGroupClient_clientPromise, "f"); + return client.dispatch(`sessionContextGroup:getContext-${this.id}`, { + sessionContextGroupId: this.id, + type + }); + } + async addContextHandler(contextHandler, contextType) { + this.wire.sendAction('interop-session-context-group-add-handler').catch((e) => { + // don't expose, analytics-only call + }); + if (typeof contextHandler !== 'function') { + throw new Error("Non-function argument passed to the first parameter 'handler'. Be aware that the argument order does not match the FDC3 standard."); + } + const client = await __classPrivateFieldGet$2(this, _SessionContextGroupClient_clientPromise, "f"); + let handlerId; + if (contextType) { + handlerId = `sessionContextHandler:invoke-${this.id}-${contextType}-${(0, utils_1$2.generateId)()}`; + } + else { + handlerId = `sessionContextHandler:invoke-${this.id}`; + } + client.register(handlerId, (0, utils_1$2.wrapContextHandler)(contextHandler, handlerId)); + await client.dispatch(`sessionContextGroup:handlerAdded-${this.id}`, { handlerId, contextType }); + return { unsubscribe: await this.createUnsubscribeCb(handlerId) }; + } + async createUnsubscribeCb(handlerId) { + const client = await __classPrivateFieldGet$2(this, _SessionContextGroupClient_clientPromise, "f"); + return async () => { + client.remove(handlerId); + await client.dispatch(`sessionContextGroup:handlerRemoved-${this.id}`, { handlerId }); + }; + } + getUserInstance() { + return { + id: this.id, + setContext: (0, utils_1$2.wrapInTryCatch)(this.setContext.bind(this), 'Failed to set context: '), + getCurrentContext: (0, utils_1$2.wrapInTryCatch)(this.getCurrentContext.bind(this), 'Failed to get context: '), + addContextHandler: (0, utils_1$2.wrapInTryCatch)(this.addContextHandler.bind(this), 'Failed to add context handler: ') + }; + } +} +SessionContextGroupClient$1.default = SessionContextGroupClient; +_SessionContextGroupClient_clientPromise = new WeakMap(); + +var fdc31_2 = {}; + +var fdc3Common = {}; + +var utils$2 = {}; + +var PrivateChannelClient$1 = {}; + +var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(PrivateChannelClient$1, "__esModule", { value: true }); +PrivateChannelClient$1.PrivateChannelClient = void 0; +const utils$1 = __importStar(utils$3); +class PrivateChannelClient { + constructor(client, id) { + this.id = id; + this.client = client; + this.listeners = new Map(); + } + async broadcast(context) { + return this.client.dispatch('broadcast', { context }); + } + async getCurrentContext(contextType) { + return this.client.dispatch('getCurrentContext', { contextType }); + } + async addContextListener(contextType, handler) { + if (typeof handler !== 'function') { + throw new Error("Non-function argument passed to the second parameter 'handler'. Be aware that the argument order does not match the FDC3 standard."); + } + let handlerId; + if (contextType) { + handlerId = `contextHandler:invoke-${this.id}-${contextType}-${utils$1.generateId()}`; + } + else { + handlerId = `contextHandler:invoke-${this.id}-${utils$1.generateId()}`; + } + this.client.register(handlerId, utils$1.wrapContextHandler(handler, handlerId)); + const listener = { unsubscribe: await this.createContextUnsubscribeCb(handlerId) }; + this.listeners.set(handlerId, listener); + await this.client.dispatch(`contextHandlerAdded`, { handlerId, contextType }); + return listener; + } + createNonStandardUnsubscribeCb(handlerId) { + return async () => { + this.client.remove(handlerId); + this.listeners.delete(handlerId); + await this.client.dispatch('nonStandardHandlerRemoved', { handlerId }); + }; + } + createContextUnsubscribeCb(handlerId) { + return async () => { + this.client.remove(handlerId); + this.listeners.delete(handlerId); + await this.client.dispatch('contextHandlerRemoved', { handlerId }); + }; + } + onAddContextListener(handler) { + const handlerId = `onContextHandlerAdded:invoke-${this.id}-${utils$1.generateId()}`; + this.client.register(handlerId, handler); + const listener = { unsubscribe: this.createNonStandardUnsubscribeCb(handlerId) }; + this.listeners.set(handlerId, listener); + this.client.dispatch(`onAddContextHandlerAdded`, { handlerId }); + return listener; + } + onDisconnect(handler) { + const handlerId = `onDisconnect:invoke-${this.id}-${utils$1.generateId()}`; + this.client.register(handlerId, handler); + const listener = { unsubscribe: this.createNonStandardUnsubscribeCb(handlerId) }; + this.listeners.set(handlerId, listener); + this.client.dispatch(`onDisconnectHandlerAdded`, { handlerId }); + return listener; + } + onUnsubscribe(handler) { + const handlerId = `onUnsubscribe:invoke-${this.id}-${utils$1.generateId()}`; + this.client.register(handlerId, handler); + const listener = { unsubscribe: this.createNonStandardUnsubscribeCb(handlerId) }; + this.listeners.set(handlerId, listener); + this.client.dispatch(`onUnsubscribeHandlerAdded`, { handlerId }); + return listener; + } + async cleanUpAllSubs() { + const listenerUnsubscribers = Array.from(this.listeners.keys()); + listenerUnsubscribers.forEach((handlerId) => { + this.client.remove(handlerId); + this.listeners.delete(handlerId); + }); + } + async disconnect() { + try { + await this.client.dispatch('clientDisconnecting'); + await this.cleanUpAllSubs(); + await this.client.disconnect(); + } + catch (error) { + throw new Error(error.message); + } + } +} +PrivateChannelClient$1.PrivateChannelClient = PrivateChannelClient; + +(function (exports) { + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.getIntentResolution = exports.isChannel = exports.isContext = exports.connectPrivateChannel = exports.buildAppChannelObject = exports.buildPrivateChannelObject = exports.ChannelError = exports.ResultError = exports.UnsupportedChannelApiError = exports.getUnsupportedChannelApis = void 0; + const utils_1 = utils$3; + const PrivateChannelClient_1 = PrivateChannelClient$1; + const isEqual_1 = __importDefault(require$$3); + const getUnsupportedChannelApis = (channelType) => { + return { + addContextListener: () => { + throw new UnsupportedChannelApiError('Channel.addContextListener', channelType); + }, + broadcast: () => { + throw new UnsupportedChannelApiError('Channel.broadcast', channelType); + }, + getCurrentContext: () => { + throw new UnsupportedChannelApiError('Channel.getCurrentContext', channelType); + } + }; + }; + exports.getUnsupportedChannelApis = getUnsupportedChannelApis; + class UnsupportedChannelApiError extends Error { + constructor(apiName, channelType = 'System') { + super(apiName); + this.message = `Calling ${apiName} on an instance of a ${channelType} Channel returned by fdc3.get${channelType}Channels is not supported. If you would like to use a ${channelType} Channel, please use fdc3.joinChannel, fdc3.addContextListener, and fdc3.broadcast instead.`; + } + } + exports.UnsupportedChannelApiError = UnsupportedChannelApiError; + var ResultError; + (function (ResultError) { + /** Returned if the `IntentHandler` exited without returning a Promise or that + * Promise was not resolved with a Context or Channel object. + */ + ResultError["NoResultReturned"] = "NoResultReturned"; + /** Returned if the `IntentHandler` function processing the raised intent + * throws an error or rejects the Promise it returned. + */ + ResultError["IntentHandlerRejected"] = "IntentHandlerRejected"; + })(ResultError = exports.ResultError || (exports.ResultError = {})); + (function (ChannelError) { + /** Returned if the specified channel is not found when attempting to join a + * channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`). + */ + ChannelError["NoChannelFound"] = "NoChannelFound"; + /** SHOULD be returned when a request to join a user channel or to a retrieve + * a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods + * of the DesktopAgent (`fdc3`) object is denied. + */ + ChannelError["AccessDenied"] = "AccessDenied"; + /** SHOULD be returned when a channel cannot be created or retrieved via the + * `getOrCreateChannel` method of the DesktopAgent (`fdc3`). + */ + ChannelError["CreationFailed"] = "CreationFailed"; + })(exports.ChannelError || (exports.ChannelError = {})); + const buildPrivateChannelObject = (privateChannelClient) => { + let clientDisconnected = false; + const checkIfClientDisconnected = () => { + if (clientDisconnected) { + throw new Error('Private Channel Client has been disconnected from the Private Channel'); + } + }; + return { + id: privateChannelClient.id, + type: 'private', + broadcast: async (context) => { + checkIfClientDisconnected(); + return privateChannelClient.broadcast(context); + }, + getCurrentContext: async (contextType) => { + checkIfClientDisconnected(); + return privateChannelClient.getCurrentContext(contextType); + }, + // @ts-expect-error TODO [CORE-1524] + addContextListener: async (contextType, handler) => { + checkIfClientDisconnected(); + let handlerInUse = handler; + let contextTypeInUse = contextType; + if (typeof contextType === 'function') { + console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)'); + handlerInUse = contextType; + contextTypeInUse = null; + } + const listener = privateChannelClient.addContextListener(contextTypeInUse, handlerInUse); + return listener; + }, + onAddContextListener: (handler) => { + checkIfClientDisconnected(); + return privateChannelClient.onAddContextListener(handler); + }, + disconnect: async () => { + checkIfClientDisconnected(); + clientDisconnected = true; + return privateChannelClient.disconnect(); + }, + onDisconnect: (handler) => { + checkIfClientDisconnected(); + return privateChannelClient.onDisconnect(handler); + }, + onUnsubscribe: (handler) => { + checkIfClientDisconnected(); + return privateChannelClient.onUnsubscribe(handler); + } + }; + }; + exports.buildPrivateChannelObject = buildPrivateChannelObject; + const buildAppChannelObject = (sessionContextGroup) => { + return { + id: sessionContextGroup.id, + type: 'app', + broadcast: sessionContextGroup.setContext, + getCurrentContext: async (contextType) => { + const context = await sessionContextGroup.getCurrentContext(contextType); + return context === undefined ? null : context; + }, + // @ts-expect-error TODO [CORE-1524] + addContextListener: (contextType, handler) => { + let realHandler; + let realType; + if (typeof contextType === 'function') { + console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)'); + realHandler = contextType; + } + else { + realHandler = handler; + if (typeof contextType === 'string') { + realType = contextType; + } + } + const listener = (async () => { + let first = true; + const currentContext = await sessionContextGroup.getCurrentContext(realType); + const wrappedHandler = (context, contextMetadata) => { + if (first) { + first = false; + if ((0, isEqual_1.default)(currentContext, context)) { + return; + } + } + // eslint-disable-next-line consistent-return + return realHandler(context, contextMetadata); + }; + return sessionContextGroup.addContextHandler(wrappedHandler, realType); + })(); + return { + ...listener, + unsubscribe: () => listener.then((l) => l.unsubscribe()) + }; + } + }; + }; + exports.buildAppChannelObject = buildAppChannelObject; + const connectPrivateChannel = async (channelId) => { + try { + const channelClient = await fin.InterApplicationBus.Channel.connect(channelId); + const privateChannelClient = new PrivateChannelClient_1.PrivateChannelClient(channelClient, channelId); + return (0, exports.buildPrivateChannelObject)(privateChannelClient); + } + catch (error) { + throw new Error(`Private Channel with id: ${channelId} doesn't exist`); + } + }; + exports.connectPrivateChannel = connectPrivateChannel; + const isContext = (context) => { + if (context && typeof context === 'object' && 'type' in context) { + const { type } = context; + return typeof type === 'string'; + } + return false; + }; + exports.isContext = isContext; + const isChannel = (channel) => { + if (channel && typeof channel === 'object' && 'type' in channel && 'id' in channel) { + const { type, id } = channel; + return typeof type === 'string' && typeof id === 'string' && (type === 'app' || type === 'private'); + } + return false; + }; + exports.isChannel = isChannel; + const getIntentResolution = async (interopModule, context, app, intent) => { + // Generate an ID to make a session context group with. We will pass that ID to the Broker. + // The broker will then setContext on that session context group later with our Intent Result, + const guid = (0, utils_1.generateId)(); // TODO make this undefined in web + // Promise we'll use in getResult + const getResultPromise = new Promise((resolve, reject) => { + fin.InterApplicationBus.subscribe({ uuid: '*' }, guid, (intentResult) => { + resolve(intentResult); + }).catch(() => reject(new Error('getResult is not supported in this environment'))); + }); + // Adding the intentResolutionResultId to the intentObj. Because fireIntent only accepts a single arg, we have to slap it in here. + const metadata = app ? { target: app, intentResolutionResultId: guid } : { intentResolutionResultId: guid }; + const intentObj = intent ? { name: intent, context, metadata } : { ...context, metadata }; + // Set up the getResult call. + const getResult = async () => { + let intentResult = await getResultPromise; + if (!intentResult || typeof intentResult !== 'object') { + throw new Error(ResultError.NoResultReturned); + } + const { error } = intentResult; + if (error) { + throw new Error(ResultError.IntentHandlerRejected); + } + if ((0, exports.isChannel)(intentResult)) { + const { id, type } = intentResult; + switch (type) { + case 'private': { + intentResult = await (0, exports.connectPrivateChannel)(id); + break; + } + case 'app': { + const sessionContextGroup = await interopModule.joinSessionContextGroup(id); + intentResult = (0, exports.buildAppChannelObject)(sessionContextGroup); + break; + } + } + } + else if (!(0, exports.isContext)(intentResult)) { + throw new Error(ResultError.NoResultReturned); + } + return intentResult; + }; + // Finally fire the intent. + const intentResolutionInfoFromBroker = intent + ? await interopModule.fireIntent(intentObj) + : await interopModule.fireIntentForContext(intentObj); + if (typeof intentResolutionInfoFromBroker !== 'object') { + return { + source: { + appId: '', + instanceId: '' + }, + intent: '', + version: '2.0', + getResult + }; + } + return { ...intentResolutionInfoFromBroker, getResult }; + }; + exports.getIntentResolution = getIntentResolution; +} (utils$2)); + +var hasRequiredFdc3Common; + +function requireFdc3Common () { + if (hasRequiredFdc3Common) return fdc3Common; + hasRequiredFdc3Common = 1; + var __classPrivateFieldGet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + var __classPrivateFieldSet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; + }; + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + var _FDC3ModuleBase_producer; + Object.defineProperty(fdc3Common, "__esModule", { value: true }); + fdc3Common.FDC3ModuleBase = void 0; + const utils_1 = utils$2; + const utils_2 = utils$3; + const InteropClient_1 = requireInteropClient(); + const isEqual_1 = __importDefault(require$$3); + class FDC3ModuleBase { + get client() { + return __classPrivateFieldGet(this, _FDC3ModuleBase_producer, "f").call(this); + } + get fin() { + return this.wire.getFin(); + } + // eslint-disable-next-line no-useless-constructor + constructor(producer, wire) { + this.wire = wire; + _FDC3ModuleBase_producer.set(this, void 0); + __classPrivateFieldSet(this, _FDC3ModuleBase_producer, producer, "f"); + } + /** + * Broadcasts a context for the channel of the current entity. + * @param context - New context to set. + * + * @tutorial fdc3.broadcast + * @static + */ + async broadcast(context) { + this.wire.sendAction('fdc3-broadcast').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.client.setContext(context); + } + /** + * Launches an app with target information, which can either be a string or an AppMetadata object. + * @param app + * @param context + * + * @tutorial fdc3.open + */ + async _open(app, context) { + this.wire.sendAction('fdc3-open').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'fdc3Open', { app, context }); + } + catch (error) { + const errorToThrow = error.message === utils_2.BROKER_ERRORS.fdc3Open ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + async _getChannels() { + const channels = await this.client.getContextGroups(); + // fdc3 implementation of getSystemChannels returns an array of channels, have to decorate over + // this so people know that these APIs are not supported + return channels.map((channel) => { + return { ...channel, type: 'system', ...(0, utils_1.getUnsupportedChannelApis)() }; + }); + } + /** + * Returns a Channel object for the specified channel, creating it as an App Channel if it does not exist. + * @param channelId + * + * @tutorial fdc3.getOrCreateChannel + */ + async getOrCreateChannel(channelId) { + this.wire.sendAction('fdc3-get-or-create-channel').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const systemChannels = await this._getChannels(); + const userChannel = systemChannels.find((channel) => channel.id === channelId); + if (userChannel) { + return { ...userChannel, type: 'system', ...(0, utils_1.getUnsupportedChannelApis)() }; + } + try { + const sessionContextGroup = await this.client.joinSessionContextGroup(channelId); + return (0, utils_1.buildAppChannelObject)(sessionContextGroup); + } + catch (error) { + console.error(error.message); + throw new Error(utils_1.ChannelError.CreationFailed); + } + } + /** + * Returns the Interop-Broker-defined context groups available for an entity to join. + * + * @tutorial fdc3.getSystemChannels + * @static + */ + async getSystemChannels() { + this.wire.sendAction('fdc3-get-system-channels').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this._getChannels(); + } + /** + * Join all Interop Clients at the given identity to context group `contextGroupId`. + * If no target is specified, it adds the sender to the context group. + * Because multiple Channel connections/Interop Clients can potentially exist at a `uuid`/`name` combo, we currently join all Channel connections/Interop Clients at the given identity to the context group. + * If an `endpointId` is provided (which is unlikely, unless the call is coming from an external adapter), then we only join that single connection to the context group. + * For all intents and purposes, there will only be 1 connection present in Platform and Browser implementations, so this point is more-or-less moot. + * @param channelId - Id of the context group. + * + * @tutorial fdc3.joinChannel + * @static + */ + async joinChannel(channelId) { + this.wire.sendAction('fdc3-join-channel').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await this.client.joinContextGroup(channelId); + } + catch (error) { + if (error.message === utils_2.BROKER_ERRORS.joinSessionContextGroupWithJoinContextGroup) { + console.error('The Channel you have tried to join is an App Channel. Custom Channels can only be defined by the Interop Broker through code or manifest configuration. Please use getOrCreateChannel.'); + } + else { + console.error(error.message); + } + if (error.message.startsWith('Attempting to join a context group that does not exist')) { + throw new Error(utils_1.ChannelError.NoChannelFound); + } + throw new Error(utils_1.ChannelError.AccessDenied); + } + } + /** + * Returns the Channel that the entity is subscribed to. Returns null if not joined to a channel. + * + * @tutorial fdc3.getCurrentChannel + */ + async getCurrentChannel() { + this.wire.sendAction('fdc3-get-current-channel').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const currentContextGroupInfo = await this.getCurrentContextGroupInfo(); + if (!currentContextGroupInfo) { + return null; + } + return this.buildChannelObject(currentContextGroupInfo); + } + /** + * Removes the specified target from a context group. + * If no target is specified, it removes the sender from their context group. + * + * @tutorial fdc3.leaveCurrentChannel + * @static + */ + async leaveCurrentChannel() { + this.wire.sendAction('fdc3-leave-current-channel').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.client.removeFromContextGroup(); + } + // utils + // eslint-disable-next-line class-methods-use-this + async getCurrentContextGroupInfo() { + const contextGroups = await this.client.getContextGroups(); + const clientsInCtxGroupsPromise = contextGroups.map(async (ctxGroup) => { + return this.client.getAllClientsInContextGroup(ctxGroup.id); + }); + const clientsInCtxGroups = await Promise.all(clientsInCtxGroupsPromise); + const clientIdx = clientsInCtxGroups.findIndex((clientIdentityArr) => { + return clientIdentityArr.some((clientIdentity) => { + const { uuid, name } = clientIdentity; + return this.wire.me.uuid === uuid && this.wire.me.name === name; + }); + }); + return contextGroups[clientIdx]; + } + async buildChannelObject(currentContextGroupInfo) { + // @ts-expect-error + return { + ...currentContextGroupInfo, + type: 'system', + addContextListener: (...[contextType, handler]) => { + let realHandler; + let realType; + if (typeof contextType === 'function') { + console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)'); + realHandler = contextType; + } + else { + realHandler = handler; + if (typeof contextType === 'string') { + realType = contextType; + } + } + const listener = (async () => { + let first = true; + const currentContext = await this.client.getCurrentContext(realType); + const wrappedHandler = (context, contextMetadata) => { + if (first) { + first = false; + if ((0, isEqual_1.default)(currentContext, context)) { + return; + } + } + // eslint-disable-next-line consistent-return + return realHandler(context, contextMetadata); + }; + return this.client.addContextHandler(wrappedHandler, realType); + })(); + // @ts-expect-error TODO [CORE-1524] + return { + ...listener, + unsubscribe: () => listener.then((l) => l.unsubscribe()) + }; + }, + broadcast: this.broadcast.bind(this), + // @ts-expect-error Typescript fails to infer the returntype is a Promise + getCurrentContext: async (contextType) => { + const context = await this.client.getCurrentContext(contextType); + // @ts-expect-error Typescript fails to infer the returntype is a Promise + return context === undefined ? null : context; + } + }; + } + } + fdc3Common.FDC3ModuleBase = FDC3ModuleBase; + _FDC3ModuleBase_producer = new WeakMap(); + return fdc3Common; +} + +var hasRequiredFdc31_2; + +function requireFdc31_2 () { + if (hasRequiredFdc31_2) return fdc31_2; + hasRequiredFdc31_2 = 1; + Object.defineProperty(fdc31_2, "__esModule", { value: true }); + fdc31_2.Fdc3Module = void 0; + const utils_1 = utils$3; + const fdc3_common_1 = requireFdc3Common(); + /** + * @version 1.2 + * The FDC3 Client Library provides a set APIs to be used for FDC3 compliance, + * while using our Interop API under the hood. In order to use this set of APIs + * you will need to set up your own {@link InteropBroker InteropBroker} or use a Platform application, which does the setup for you. Refer to our documentation on + * our {@link https://developers.openfin.co/of-docs/docs/enable-color-linking Interop API}. + * + * To enable the FDC3 APIs in a {@link Window Window} or {@link View View}, add the fdc3InteropApi + * property to its options: + * + * ```js + * { + * autoShow: false, + * saveWindowState: true, + * url: 'https://openfin.co', + * fdc3InteropApi: '1.2' + * } + * ``` + * + * If using a {@link Platform Platform } application, you can set this property in defaultWindowOptions and defaultViewOptions. + * + * In order to ensure that the FDC3 Api is ready before use, you can use the 'fdc3Ready' event fired on the DOM Window object: + * + * ```js + * function fdc3Action() { + * // Make some fdc3 API calls here + * } + * + * if (window.fdc3) { + * fdc3Action(); + * } else { + * window.addEventListener('fdc3Ready', fdc3Action); + * } + * ``` + */ + class Fdc3Module extends fdc3_common_1.FDC3ModuleBase { + async open(app, context) { + // eslint-disable-next-line no-underscore-dangle + await super._open(app, context); + } + /** + * Add a context handler for incoming context. If an entity is part of a context group, and then sets its context handler, it will receive all of its declared contexts. If you wish to listen for all incoming contexts, pass `null` for the contextType argument. + * @param contextType - The type of context you wish to handle. + * @param handler - Handler for incoming context. + * + * @tutorial fdc3.addContextListener + * @static + */ + // @ts-expect-error TODO [CORE-1524] + addContextListener(contextType, handler) { + this.wire.sendAction('fdc3-add-context-listener').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + let listener; + if (typeof contextType === 'function') { + console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)'); + listener = this.client.addContextHandler(contextType); + } + else { + listener = this.client.addContextHandler(handler, contextType === null ? undefined : contextType); + } + return { + ...listener, + unsubscribe: () => listener.then((l) => l.unsubscribe()) + }; + } + /** + * Adds a listener for incoming Intents. + * @param intent - Name of the Intent + * @param handler - Handler for incoming Intent + * + * @tutorial fdc3.addIntentListener + * @static + */ + addIntentListener(intent, handler) { + this.wire.sendAction('fdc3-add-intent-listener').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const contextHandler = (raisedIntent) => { + const { context, metadata: intentMetadata } = raisedIntent; + const { metadata } = context; + const intentResolutionResultId = intentMetadata?.intentResolutionResultId || metadata?.intentResolutionResultId; + if (intentResolutionResultId) { + this.fin.InterApplicationBus.publish(intentResolutionResultId, null).catch(() => null); + } + handler(raisedIntent.context); + }; + const listener = this.client.registerIntentHandler(contextHandler, intent, { + fdc3Version: '1.2' + }); + return { + ...listener, + unsubscribe: () => listener.then((l) => l.unsubscribe()) + }; + } + /** + * Raises a specific intent. + * @param intent Name of the Intent. + * @param context Context associated with the Intent. + * @param app App that will resolve the Intent. This is added as metadata to the Intent. Can be accessed by the app provider in {@link InteropBroker#handleFiredIntent InteropBroker.handleFiredIntent}. + * + * @tutorial fdc3.raiseIntent + * @static + */ + async raiseIntent(intent, context, app) { + this.wire.sendAction('fdc3-raise-intent').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const intentObj = app + ? { name: intent, context, metadata: { target: app } } + : { name: intent, context }; + try { + return await this.client.fireIntent(intentObj); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fireIntent ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Find out more information about a particular intent by passing its name, and optionally its context. + * @param intent Name of the Intent + * @param context + * + * @tutorial fdc3.findIntent + */ + async findIntent(intent, context) { + this.wire.sendAction('fdc3-find-intent').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await this.client.getInfoForIntent({ name: intent, context }); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.getInfoForIntent ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Find all the available intents for a particular context. + * @param context + * + * @tutorial fdc3.findIntentsByContext + */ + async findIntentsByContext(context) { + this.wire.sendAction('fdc3-find-intents-by-context').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await this.client.getInfoForIntentsByContext(context); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.getInfoForIntentsByContext ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Finds and raises an intent against a target app based purely on context data. + * @param context + * @param app + * + * @tutorial fdc3.raiseIntentForContext + */ + async raiseIntentForContext(context, app) { + this.wire.sendAction('fdc3-raise-intent-for-context').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await this.client.fireIntentForContext({ ...context, metadata: { target: app } }); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fireIntentForContext ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Returns a Channel object for the specified channel, creating it as an App Channel if it does not exist. + * @param channelId + * + * @tutorial fdc3.getOrCreateChannel + */ + async getOrCreateChannel(channelId) { + return super.getOrCreateChannel(channelId); + } + /** + * Returns metadata relating to the FDC3 object and its provider, including the supported version of the FDC3 specification and the name of the provider of the implementation. + * + * @tutorial fdc3.getInfo + */ + getInfo() { + this.wire.sendAction('fdc3-get-info').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const version = this.wire.environment.getAdapterVersionSync(); + return { + providerVersion: version, + provider: `openfin-${this.wire.me.uuid}`, + fdc3Version: '1.2' + }; + } + } + fdc31_2.Fdc3Module = Fdc3Module; + return fdc31_2; +} + +var fdc32_0 = {}; + +var hasRequiredFdc32_0; + +function requireFdc32_0 () { + if (hasRequiredFdc32_0) return fdc32_0; + hasRequiredFdc32_0 = 1; + Object.defineProperty(fdc32_0, "__esModule", { value: true }); + fdc32_0.Fdc3Module2 = void 0; + const fdc3_common_1 = requireFdc3Common(); + const utils_1 = utils$3; + const InteropClient_1 = requireInteropClient(); + const utils_2 = utils$2; + const PrivateChannelClient_1 = PrivateChannelClient$1; + /** + * @version 2.0 + * The FDC3 Client Library provides a set APIs to be used for FDC3 compliance, + * while using our Interop API under the hood. In order to use this set of APIs + * you will need to set up your own {@link InteropBroker InteropBroker} or use a Platform application, which does the setup for you. Refer to our documentation on + * our {@link https://developers.openfin.co/of-docs/docs/enable-context-sharing Interop API}. + * + * To enable the FDC3 APIs in a {@link Window Window} or {@link View View}, add the fdc3InteropApi + * property to its options: + * + * ```js + * { + * autoShow: false, + * saveWindowState: true, + * url: 'https://openfin.co', + * fdc3InteropApi: '2.0' + * } + * ``` + * + * If using a {@link Platform Platform } application, you can set this property in defaultWindowOptions and defaultViewOptions. + * + * In order to ensure that the FDC3 Api is ready before use, you can use the 'fdc3Ready' event fired on the DOM Window object: + * + * ```js + * function fdc3Action() { + * // Make some fdc3 API calls here + * } + * + * if (window.fdc3) { + * fdc3Action(); + * } else { + * window.addEventListener('fdc3Ready', fdc3Action); + * } + * ``` + */ + class Fdc3Module2 extends fdc3_common_1.FDC3ModuleBase { + /** + * Launches an app, specified via an AppIdentifier object. + * @param app + * @param context + * + * @tutorial fdc3.open + */ + async open(app, context) { + if (typeof app === 'string') { + console.warn('Passing a string as the app parameter is deprecated, please use an AppIdentifier ({ appId: string; instanceId?: string }).'); + } + // eslint-disable-next-line no-underscore-dangle + return super._open(app, context); + } + /** + * Find all the available instances for a particular application. + * @param app + * + * @tutorial fdc3v2.findInstances + */ + async findInstances(app) { + this.wire.sendAction('fdc3-find-instances').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'fdc3FindInstances', app); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fdc3FindInstances ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Retrieves the AppMetadata for an AppIdentifier, which provides additional metadata (such as icons, a title and description) from the App Directory record for the application, that may be used for display purposes. + * @param app + * + * @tutorial fdc3v2.getAppMetadata + */ + async getAppMetadata(app) { + this.wire.sendAction('fdc3-get-app-metadata').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'fdc3GetAppMetadata', app); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fdc3GetAppMetadata ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Add a context handler for incoming context. If an entity is part of a context group, and then sets its context handler, it will receive all of its declared contexts. If you wish to listen for all incoming contexts, pass `null` for the contextType argument. + * @param contextType + * @param handler + * + * @tutorial fdc3.addContextListener + */ + // @ts-expect-error TODO [CORE-1524] + async addContextListener(contextType, handler) { + this.wire.sendAction('fdc3-add-context-listener').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + // The FDC3 ContextHandler only expects the context and optional ContextMetadata, so we wrap the handler + // here so it only gets passed these parameters + const getWrappedHandler = (handlerToWrap) => { + return (context) => { + const { contextMetadata, ...rest } = context; + const args = contextMetadata ? [{ ...rest }, contextMetadata] : [context, null]; + handlerToWrap(...args); + }; + }; + let actualHandler = handler; + let wrappedHandler = getWrappedHandler(actualHandler); + if (typeof contextType === 'function') { + console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)'); + actualHandler = contextType; + wrappedHandler = getWrappedHandler(actualHandler); + return this.client.addContextHandler(wrappedHandler); + } + return this.client.addContextHandler(wrappedHandler, contextType === null ? undefined : contextType); + } + /** + * Find out more information about a particular intent by passing its name, and optionally its context and resultType. + * @param intent Name of the Intent + * @param context Context + * @param resultType The type of result returned for any intent specified during resolution. + * + * @tutorial fdc3.findIntent + */ + async findIntent(intent, context, resultType) { + this.wire.sendAction('fdc3-find-intent').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await this.client.getInfoForIntent({ name: intent, context, metadata: { resultType } }); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.getInfoForIntent ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Find all the available intents for a particular context. + * @param context + * @param resultType The type of result returned for any intent specified during resolution. + * + * @tutorial fdc3v2.findIntentsByContext + */ + async findIntentsByContext(context, resultType) { + this.wire.sendAction('fdc3-find-intents-by-context').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const payload = resultType ? { context, metadata: { resultType } } : context; + try { + return await InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'fdc3v2FindIntentsByContext', payload); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.getInfoForIntentsByContext ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Raises a specific intent for resolution against apps registered with the desktop agent. + * @param intent Name of the Intent + * @param context Context associated with the Intent + * @param app + * + * @tutorial fdc3v2.raiseIntent + */ + async raiseIntent(intent, context, app) { + this.wire.sendAction('fdc3-raise-intent').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + if (typeof app === 'string') { + console.warn('Passing a string as the app parameter is deprecated, please use an AppIdentifier ({ appId: string; instanceId?: string }).'); + } + return (0, utils_2.getIntentResolution)(this.client, context, app, intent); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fireIntent ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Finds and raises an intent against apps registered with the desktop agent based purely on the type of the context data. + * @param context Context associated with the Intent + * @param app + * + * @tutorial fdc3v2.raiseIntentForContext + */ + async raiseIntentForContext(context, app) { + // TODO: We have to do the same thing we do for raiseIntent here as well. + this.wire.sendAction('fdc3-raise-intent-for-context').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + if (typeof app === 'string') { + console.warn('Passing a string as the app parameter is deprecated, please use an AppIdentifier ({ appId: string; instanceId?: string }).'); + } + return (0, utils_2.getIntentResolution)(this.client, context, app); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fireIntent ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Adds a listener for incoming intents. + * @param intent Name of the Intent + * @param handler A callback that handles a context event and may return a promise of a Context or Channel object to be returned to the application that raised the intent. + * + * @tutorial fdc3.addIntentListener + */ + async addIntentListener(intent, handler) { + this.wire.sendAction('fdc3-add-intent-listener').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (typeof intent !== 'string') { + throw new Error('First argument must be an Intent name'); + } + // The FDC3 Intenter handler only expects the context and contextMetadata to be passed to the handler, + // so we wrap it here and only pass those paramaters. + const contextHandler = async (raisedIntent) => { + let intentResult; + let intentResultToSend; + const { context, metadata: intentMetadata } = raisedIntent; + const { contextMetadata, metadata, ...rest } = context; + const intentResolutionResultId = intentMetadata?.intentResolutionResultId || metadata?.intentResolutionResultId; + try { + const newContext = metadata ? { metadata, ...rest } : { ...rest }; + intentResult = await handler(newContext, contextMetadata); + intentResultToSend = intentResult; + } + catch (error) { + intentResult = error; + intentResultToSend = { error: true }; + } + if (intentResolutionResultId) { + this.fin.InterApplicationBus.publish(intentResolutionResultId, intentResultToSend).catch(() => null); + } + if (intentResult instanceof Error) { + throw new Error(intentResult.message); + } + return intentResult; + }; + return this.client.registerIntentHandler(contextHandler, intent, { fdc3Version: '2.0' }); + } + /** + * Returns a Channel object for the specified channel, creating it as an App Channel if it does not exist. + * @param channelId + * + * @tutorial fdc3.getOrCreateChannel + */ + async getOrCreateChannel(channelId) { + return super.getOrCreateChannel(channelId); + } + /** + * Returns a Channel with an auto-generated identity that is intended for private communication between applications. Primarily used to create channels that will be returned to other applications via an IntentResolution for a raised intent. + * + * @tutorial fdc3v2.createPrivateChannel + */ + async createPrivateChannel() { + const channelId = (0, utils_1.generateId)(); + await InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'createPrivateChannelProvider', { channelId }); + const channelClient = await this.fin.InterApplicationBus.Channel.connect(channelId); + const newPrivateChannelClient = new PrivateChannelClient_1.PrivateChannelClient(channelClient, channelId); + return (0, utils_2.buildPrivateChannelObject)(newPrivateChannelClient); + } + /** + * Retrieves a list of the User Channels available for the app to join. + * + * @tutorial fdc3v2.getUserChannels + */ + async getUserChannels() { + const channels = await this.client.getContextGroups(); + // fdc3 implementation of getUserChannels returns on array of channels, have to decorate over + // this so people know that these APIs are not supported + return channels.map((channel) => { + // @ts-expect-error TODO [CORE-1524] + return { ...channel, type: 'user', ...(0, utils_2.getUnsupportedChannelApis)('User') }; + }); + } + /** + * Retrieves a list of the User Channels available for the app to join. + * + * @deprecated Please use {@link fdc3.getUserChannels fdc3.getUserChannels} instead + * @tutorial fdc3.getSystemChannels + */ + async getSystemChannels() { + console.warn('This API has been deprecated. Please use fdc3.getUserChannels instead.'); + return super.getSystemChannels(); + } + /** + * Join an app to a specified User channel. + * @param channelId Channel name + * + * @tutorial fdc3v2.joinUserChannel + */ + async joinUserChannel(channelId) { + return super.joinChannel(channelId); + } + /** + * Join an app to a specified User channel. + * @param channelId Channel name + * @deprecated Please use {@link fdc3.joinUserChannel fdc3.joinUserChannel} instead + * + * @tutorial fdc3.joinChannel + */ + async joinChannel(channelId) { + console.warn('This API has been deprecated. Please use fdc3.joinUserChannel instead.'); + return super.joinChannel(channelId); + } + /** + * Returns the Channel object for the current User channel membership + * + * @tutorial fdc3.getCurrentChannel + */ + async getCurrentChannel() { + const currentChannel = await super.getCurrentChannel(); + if (!currentChannel) { + return null; + } + return { + ...currentChannel, + type: 'user', + broadcast: this.broadcast.bind(this) + }; + } + /** + * Retrieves information about the FDC3 implementation, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number, details of whether optional API features are implemented and the metadata of the calling application according to the desktop agent. + * fdc3HandleGetInfo must be overridden in the InteropBroker so that the ImplementationMetadata will have the appMetadata info. + * + * @tutorial fdc3v2.getInfo + */ + async getInfo() { + return InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'fdc3v2GetInfo', { fdc3Version: '2.0' }); + } + } + fdc32_0.Fdc3Module2 = Fdc3Module2; + return fdc32_0; +} + +var hasRequiredInteropClient; + +function requireInteropClient () { + if (hasRequiredInteropClient) return InteropClient; + hasRequiredInteropClient = 1; + var __classPrivateFieldSet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; + }; + var __classPrivateFieldGet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + var _InteropClient_clientPromise, _InteropClient_sessionContextGroups; + Object.defineProperty(InteropClient, "__esModule", { value: true }); + InteropClient.InteropClient = void 0; + const base_1 = base; + const SessionContextGroupClient_1 = __importDefault(SessionContextGroupClient$1); + const fdc3_1_2_1 = requireFdc31_2(); + const fdc3_2_0_1 = requireFdc32_0(); + const utils_1 = utils$3; + /** + * The Interop Client API is broken up into two groups: + * + * **Content Facing APIs** - For Application Developers putting Views into a Platform Window, who care about Context. These are APIs that send out and receive the Context data that flows between applications. Think of this as the Water in the Interop Pipes. + * + * **Context Grouping APIs** - For Platform Developers, to add and remove Views to and from Context Groups. These APIs are utilized under-the-hood in Platforms, so they don't need to be used to participate in Interop. These are the APIs that decide which entities the context data flows between. Think of these as the valves or pipes that control the flow of Context Data for Interop. + * + * --- + * + * All APIs are available at the `fin.me.interop` namespace. + * + * --- + * + * **You only need 2 things to participate in Interop Context Grouping:** + * * A Context Handler for incoming context: {@link InteropClient#addContextHandler addContextHandler(handler, contextType?)} + * * Call setContext on your context group when you want to share context with other group members: {@link InteropClient#setContext setContext(context)} + * + * --- + * + * ##### Constructor + * Returned by {@link Interop.connectSync Interop.connectSync}. + * + * --- + * + * ##### Interop methods intended for Views + * + * + * **Context Groups API** + * * {@link InteropClient#addContextHandler addContextHandler(handler, contextType?)} + * * {@link InteropClient#setContext setContext(context)} + * * {@link InteropClient#getCurrentContext getCurrentContext(contextType?)} + * * {@link InteropClient#joinSessionContextGroup joinSessionContextGroup(sessionContextGroupId)} + * + * + * **Intents API** + * * {@link InteropClient#fireIntent fireIntent(intent)} + * * {@link InteropClient#registerIntentHandler registerIntentHandler(intentHandler, intentName)} + * * {@link InteropClient#getInfoForIntent getInfoForIntent(infoForIntentOptions)} + * * {@link InteropClient#getInfoForIntentsByContext getInfoForIntentsByContext(context)} + * * {@link InteropClient#fireIntentForContext fireIntentForContext(contextForIntent)} + * + * ##### Interop methods intended for Windows + * * {@link InteropClient#getContextGroups getContextGroups()} + * * {@link InteropClient#joinContextGroup joinContextGroup(contextGroupId, target?)} + * * {@link InteropClient#removeFromContextGroup removeFromContextGroup(target?)} + * * {@link InteropClient#getInfoForContextGroup getInfoForContextGroup(contextGroupId)} + * * {@link InteropClient#getAllClientsInContextGroup getAllClientsInContextGroup(contextGroupId)} + * + */ + let InteropClient$1 = class InteropClient extends base_1.Base { + /** + * @internal + */ + constructor(wire, clientPromise) { + super(wire); + _InteropClient_clientPromise.set(this, void 0); + _InteropClient_sessionContextGroups.set(this, void 0); + __classPrivateFieldSet(this, _InteropClient_sessionContextGroups, new Map(), "f"); + __classPrivateFieldSet(this, _InteropClient_clientPromise, clientPromise, "f"); + } + /* + Client APIs + */ + /** + * Sets a context for the context group of the current entity. + * + * @remarks The entity must be part of a context group in order set a context. + * + * @param context - New context to set. + * + * @example + * ```js + * setInstrumentContext = async (ticker) => { + * fin.me.interop.setContext({type: 'instrument', id: {ticker}}) + * } + * + * // The user clicks an instrument of interest. We want to set that Instrument context so that the rest of our workflow updates with information for that instrument + * instrumentElement.on('click', (evt) => { + * setInstrumentContext(evt.ticker) + * }) + * ``` + */ + async setContext(context) { + this.wire.sendAction('interop-client-set-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('setContext', { context }); + } + /** + * Add a context handler for incoming context. If an entity is part of a context group, and then sets its context handler, + * it will receive all of its declared contexts. + * + * @param handler - Handler for incoming context. + * @param contextType - The type of context you wish to handle. + * + * @example + * ```js + * function handleIncomingContext(contextInfo) { + * const { type, id } = contextInfo; + * switch (type) { + * case 'instrument': + * handleInstrumentContext(contextInfo); + * break; + * case 'country': + * handleCountryContext(contextInfo); + * break; + * + * default: + * break; + * } + * } + * + * + * function handleInstrumentContext(contextInfo) { + * const { type, id } = contextInfo; + * console.log('contextInfo for instrument', contextInfo) + * } + * + * function handleCountryContext(contextInfo) { + * const { type, id } = contextInfo; + * console.log('contextInfo for country', contextInfo) + * } + * + * fin.me.interop.addContextHandler(handleIncomingContext); + * ``` + * + * + * Passing in a context type as the second parameter will cause the handler to only be invoked with that context type. + * + * ```js + * function handleInstrumentContext(contextInfo) { + * const { type, id } = contextInfo; + * console.log('contextInfo for instrument', contextInfo) + * } + * + * function handleCountryContext(contextInfo) { + * const { type, id } = contextInfo; + * console.log('contextInfo for country', contextInfo) + * } + * + * + * fin.me.interop.addContextHandler(handleInstrumentContext, 'instrument') + * fin.me.interop.addContextHandler(handleCountryContext, 'country') + * ``` + */ + async addContextHandler(handler, contextType) { + this.wire.sendAction('interop-client-add-context-handler').catch((e) => { + // don't expose, analytics-only call + }); + if (typeof handler !== 'function') { + throw new Error("Non-function argument passed to the first parameter 'handler'. Be aware that the argument order does not match the FDC3 standard."); + } + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + let handlerId; + if (contextType) { + handlerId = `invokeContextHandler-${contextType}-${(0, utils_1.generateId)()}`; + } + else { + handlerId = 'invokeContextHandler'; + } + const wrappedHandler = (0, utils_1.wrapContextHandler)(handler, handlerId); + client.register(handlerId, wrappedHandler); + await client.dispatch('contextHandlerRegistered', { handlerId, contextType }); + return { + unsubscribe: async () => { + client.remove(handlerId); + await client.dispatch('removeContextHandler', { handlerId }); + } + }; + } + /* + Platform Window APIs + */ + /** + * Returns the Interop-Broker-defined context groups available for an entity to join. + * Used by Platform Windows. + * + * @example + * ```js + * fin.me.interop.getContextGroups() + * .then(contextGroups => { + * contextGroups.forEach(contextGroup => { + * console.log(contextGroup.displayMetadata.name) + * console.log(contextGroup.displayMetadata.color) + * }) + * }) + * ``` + */ + async getContextGroups() { + this.wire.sendAction('interop-client-get-context-groups').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('getContextGroups'); + } + /** + * Join all Interop Clients at the given identity to context group `contextGroupId`. + * If no target is specified, it adds the sender to the context group. + * + * @remarks Because multiple Channel connections/Interop Clients can potentially exist at a `uuid`/`name` combo, we currently join all Channel connections/Interop Clients at the given identity to the context group. + * If an `endpointId` is provided (which is unlikely, unless the call is coming from an external adapter), then we only join that single connection to the context group. + * For all intents and purposes, there will only be 1 connection present in Platform and Browser implmentations, so this point is more-or-less moot. + * Used by Platform Windows. + * + * @param contextGroupId - Id of the context group. + * @param target - Identity of the entity you wish to join to a context group. + * + * @example + * ```js + * joinViewToContextGroup = async (contextGroupId, view) => { + * await fin.me.interop.joinContextGroup(contextGroupId, view); + * } + * + * getLastFocusedView() + * .then(lastFocusedViewIdentity => { + * joinViewToContextGroup('red', lastFocusedViewIdentity) + * }) + * ``` + */ + async joinContextGroup(contextGroupId, target) { + this.wire.sendAction('interop-client-join-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + if (!contextGroupId) { + throw new Error('No contextGroupId specified for joinContextGroup.'); + } + return client.dispatch('joinContextGroup', { contextGroupId, target }); + } + /** + * Removes the specified target from a context group. + * If no target is specified, it removes the sender from their context group. + * Used by Platform Windows. + * + * @param target - Identity of the entity you wish to join to a context group. + * + * @example + * ```js + * removeViewFromContextGroup = async (view) => { + * await fin.me.interop.removeFromContextGroup(view); + * } + * + * getLastFocusedView() + * .then(lastFocusedViewIdentity => { + * removeViewFromContextGroup(lastFocusedViewIdentity) + * }) + * ``` + */ + async removeFromContextGroup(target) { + this.wire.sendAction('interop-client-remove-from-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('removeFromContextGroup', { target }); + } + /** + * Gets all clients for a context group. + * + * @remarks **This is primarily used for platform windows. Views within a platform should not have to use this API.** + * + * Returns the Interop-Broker-defined context groups available for an entity to join. + * @param contextGroupId - The id of context group you wish to get clients for. + * + * @example + * ```js + * fin.me.interop.getAllClientsInContextGroup('red') + * .then(clientsInContextGroup => { + * console.log(clientsInContextGroup) + * }) + * ``` + */ + async getAllClientsInContextGroup(contextGroupId) { + this.wire.sendAction('interop-client-get-all-clients-in-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + if (!contextGroupId) { + throw new Error('No contextGroupId specified for getAllClientsInContextGroup.'); + } + return client.dispatch('getAllClientsInContextGroup', { contextGroupId }); + } + /** + * Gets display info for a context group + * + * @remarks Used by Platform Windows. + * @param contextGroupId - The id of context group you wish to get display info for. + * + * @example + * ```js + * fin.me.interop.getInfoForContextGroup('red') + * .then(contextGroupInfo => { + * console.log(contextGroupInfo.displayMetadata.name) + * console.log(contextGroupInfo.displayMetadata.color) + * }) + * ``` + */ + async getInfoForContextGroup(contextGroupId) { + this.wire.sendAction('interop-client-get-info-for-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + if (!contextGroupId) { + throw new Error('No contextGroupId specified for getInfoForContextGroup.'); + } + return client.dispatch('getInfoForContextGroup', { contextGroupId }); + } + /** + * Sends an intent to the Interop Broker to resolve. + * @param intent - The combination of an action and a context that is passed to an application for resolution. + * + * @example + * ```js + * // View wants to fire an Intent after a user clicks on a ticker + * tickerElement.on('click', (element) => { + * const ticker = element.innerText; + * const intent = { + * name: 'ViewChart', + * context: {type: 'fdc3.instrument', id: { ticker }} + * } + * + * fin.me.interop.fireIntent(intent); + * }) + * ``` + */ + async fireIntent(intent) { + this.wire.sendAction('interop-client-fire-intent').catch((e) => { + // don't expose, this is only for api analytics purposes + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('fireIntent', intent); + } + /** + * Adds an intent handler for incoming intents. The last intent sent of the name subscribed to will be received. + * @param handler - Registered function meant to handle a specific intent type. + * @param intentName - The name of an intent. + * + * @example + * ```js + * const intentHandler = (intent) => { + * const { context } = intent; + * myViewChartHandler(context); + * }; + * + * const subscription = await fin.me.interop.registerIntentHandler(intentHandler, 'ViewChart'); + * + * function myAppCloseSequence() { + * // to unsubscribe the handler, simply call: + * subscription.unsubscribe(); + * } + * ``` + */ + async registerIntentHandler(handler, intentName, options) { + this.wire.sendAction('interop-client-register-intent-handler').catch((e) => { + // don't expose, this is only for api analytics purposes + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + const handlerId = `intent-handler-${intentName}`; + const wrappedHandler = (0, utils_1.wrapIntentHandler)(handler, handlerId); + try { + await client.register(handlerId, wrappedHandler); + await client.dispatch('intentHandlerRegistered', { handlerId, ...options }); + } + catch (error) { + throw new Error('Unable to register intent handler'); + } + return { + unsubscribe: async () => { + client.remove(handlerId); + } + }; + } + /** + * Gets the last context of the Context Group currently subscribed to. It takes an optional Context Type and returns the + * last context of that type. + * @param contextType + * + * @example + * ```js + * await fin.me.interop.joinContextGroup('yellow'); + * await fin.me.interop.setContext({ type: 'instrument', id: { ticker: 'FOO' }}); + * const currentContext = await fin.me.interop.getCurrentContext(); + * + * // with a specific context + * await fin.me.interop.joinContextGroup('yellow'); + * await fin.me.interop.setContext({ type: 'country', id: { ISOALPHA3: 'US' }}); + * await fin.me.interop.setContext({ type: 'instrument', id: { ticker: 'FOO' }}); + * const currentContext = await fin.me.interop.getCurrentContext('country'); + * ``` + */ + async getCurrentContext(contextType) { + this.wire.sendAction('interop-client-get-current-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('getCurrentContext', { contextType }); + } + /** + * Get information for a particular Intent from the Interop Broker. + * + * @remarks To resolve this info, the function handleInfoForIntent is meant to be overridden in the Interop Broker. + * The format for the response will be determined by the App Provider overriding the function. + * + * @param options + * + * @example + * ```js + * const intentInfo = await fin.me.interop.getInfoForIntent('ViewChart'); + * ``` + */ + async getInfoForIntent(options) { + this.wire.sendAction('interop-client-get-info-for-intent').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('getInfoForIntent', options); + } + /** + * Get information from the Interop Broker on all Intents that are meant to handle a particular context. + * + * @remarks To resolve this info, the function handleInfoForIntentsByContext is meant to be overridden in the Interop Broker. + * The format for the response will be determined by the App Provider overriding the function. + * + * @param context + * + * @example + * ```js + * tickerElement.on('click', (element) => { + * const ticker = element.innerText; + * + * const context = { + * type: 'fdc3.instrument', + * id: { + * ticker + * } + * } + * + * const intentsInfo = await fin.me.interop.getInfoForIntentByContext(context); + * }) + * ``` + */ + async getInfoForIntentsByContext(context) { + this.wire.sendAction('interop-client-get-info-for-intents-by-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('getInfoForIntentsByContext', context); + } + /** + * Sends a Context that will be resolved to an Intent by the Interop Broker. + * This context accepts a metadata property. + * + * @remarks To resolve this info, the function handleFiredIntentByContext is meant to be overridden in the Interop Broker. + * The format for the response will be determined by the App Provider overriding the function. + * + * @param context + * + * @example + * ```js + * tickerElement.on('click', (element) => { + * const ticker = element.innerText; + * + * const context = { + * type: 'fdc3.instrument', + * id: { + * ticker + * } + * } + * + * const intentResolution = await fin.me.interop.fireIntentForContext(context); + * }) + * ``` + */ + async fireIntentForContext(context) { + this.wire.sendAction('interop-client-fire-intent-for-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('fireIntentForContext', context); + } + /** + * Join the current entity to session context group `sessionContextGroupId` and return a sessionContextGroup instance. + * If the sessionContextGroup doesn't exist, one will get created. + * + * @remarks Session Context Groups do not persist between runs and aren't present on snapshots. + * @param sessionContextGroupId - Id of the context group. + * + * @example + * Say we want to have a Session Context Group that holds UI theme information for all apps to consume: + * + * My color-picker View: + * ```js + * const themeSessionContextGroup = await fin.me.interop.joinSessionContextGroup('theme'); + * + * const myColorPickerElement = document.getElementById('color-palette-picker'); + * myColorPickerElement.addEventListener('change', event => { + * themeSessionContextGroup.setContext({ type: 'color-palette', selection: event.value }); + * }); + * ``` + * + * In other views: + * ```js + * const themeSessionContextGroup = await fin.me.interop.joinSessionContextGroup('theme'); + * + * const changeColorPalette = ({ selection }) => { + * // change the color palette to the selection + * }; + * + * // If the context is already set by the time the handler was set, the handler will get invoked immediately with the current context. + * themeSessionContextGroup.addContextHandler(changeColorPalette, 'color-palette'); + * ``` + */ + async joinSessionContextGroup(sessionContextGroupId) { + try { + const currentSessionContextGroup = __classPrivateFieldGet(this, _InteropClient_sessionContextGroups, "f").get(sessionContextGroupId); + if (currentSessionContextGroup) { + return currentSessionContextGroup.getUserInstance(); + } + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + const { hasConflict } = await client.dispatch('sessionContextGroup:createIfNeeded', { + sessionContextGroupId + }); + if (hasConflict) { + console.warn(`A (non-session) context group with the name "${sessionContextGroupId}" already exists. If you are trying to join a Context Group, call joinContextGroup instead.`); + } + const newSessionContextGroup = new SessionContextGroupClient_1.default(this.wire, __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"), sessionContextGroupId); + __classPrivateFieldGet(this, _InteropClient_sessionContextGroups, "f").set(sessionContextGroupId, newSessionContextGroup); + return newSessionContextGroup.getUserInstance(); + } + catch (error) { + console.error(`Error thrown trying to create Session Context Group with id "${sessionContextGroupId}": ${error}`); + throw error; + } + } + /** + * Register a listener that is called when the Interop Client has been disconnected from the Interop Broker. + * Only one listener per Interop Client can be set. + * @param listener + * + * @example + * ```js + * const listener = (event) => { + * const { type, topic, brokerName} = event; + * console.log(`Disconnected from Interop Broker ${brokerName} `); + * } + * + * await fin.me.interop.onDisconnection(listener); + * ``` + */ + async onDisconnection(listener) { + this.wire.sendAction('interop-client-add-ondisconnection-listener').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.onDisconnection((event) => { + const { uuid } = event; + listener({ type: 'interop-broker', topic: 'disconnected', brokerName: uuid }); + }); + } + getFDC3Sync(version) { + switch (version) { + case '1.2': + return new fdc3_1_2_1.Fdc3Module(() => this, this.wire); + case '2.0': + return new fdc3_2_0_1.Fdc3Module2(() => this, this.wire); + default: + throw new Error(`Invalid FDC3 version provided: ${version}. Must be '1.2' or '2.0'`); + } + } + async getFDC3(version) { + return this.getFDC3Sync(version); + } + /** + * @internal + * + * Used to ferry fdc3-only calls from the fdc3 shim to the Interop Broker + */ + static async ferryFdc3Call(interopClient, action, payload) { + const client = await __classPrivateFieldGet(interopClient, _InteropClient_clientPromise, "f"); + return client.dispatch(action, payload || null); + } + }; + InteropClient.InteropClient = InteropClient$1; + _InteropClient_clientPromise = new WeakMap(), _InteropClient_sessionContextGroups = new WeakMap(); + return InteropClient; +} + +var overrideCheck = {}; + +var hasRequiredOverrideCheck; + +function requireOverrideCheck () { + if (hasRequiredOverrideCheck) return overrideCheck; + hasRequiredOverrideCheck = 1; + Object.defineProperty(overrideCheck, "__esModule", { value: true }); + overrideCheck.overrideCheck = overrideCheck.checkFDC32Overrides = overrideCheck.getDefaultViewFdc3VersionFromAppInfo = void 0; + const InteropBroker_1 = requireInteropBroker(); + function getDefaultViewFdc3VersionFromAppInfo({ manifest, initialOptions }) { + const setVersion = manifest?.platform?.defaultViewOptions?.fdc3InteropApi ?? initialOptions.defaultViewOptions?.fdc3InteropApi; + return ['1.2', '2.0'].includes(setVersion ?? '') ? setVersion : undefined; + } + overrideCheck.getDefaultViewFdc3VersionFromAppInfo = getDefaultViewFdc3VersionFromAppInfo; + function checkFDC32Overrides(overriddenBroker) { + // These are the APIs that must be overridden for FDC3 2.0 compliance + const mustOverrideAPIs = [ + 'fdc3HandleFindInstances', + 'handleInfoForIntent', + 'handleInfoForIntentsByContext', + 'fdc3HandleGetAppMetadata', + 'fdc3HandleGetInfo', + 'fdc3HandleOpen', + 'handleFiredIntent', + 'handleFiredIntentForContext' + ]; + return mustOverrideAPIs.filter((api) => { + return overriddenBroker[api] === InteropBroker_1.InteropBroker.prototype[api]; + }); + } + overrideCheck.checkFDC32Overrides = checkFDC32Overrides; + function overrideCheck$1(overriddenBroker, fdc3InteropApi) { + if (fdc3InteropApi && fdc3InteropApi === '2.0') { + const notOverridden = checkFDC32Overrides(overriddenBroker); + if (notOverridden.length > 0) { + console.warn(`WARNING: FDC3 2.0 has been set as a default option for Views in this Platform, but the required InteropBroker APIs for FDC3 2.0 compliance have not all been overridden.\nThe following APIs need to be overridden:\n${notOverridden.join('\n')}`); + } + } + } + overrideCheck.overrideCheck = overrideCheck$1; + return overrideCheck; +} + +var hasRequiredFactory; + +function requireFactory () { + if (hasRequiredFactory) return Factory$1; + hasRequiredFactory = 1; + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + Object.defineProperty(Factory$1, "__esModule", { value: true }); + Factory$1.InteropModule = void 0; + const cloneDeep_1 = __importDefault(require$$0$1); + const inaccessibleObject_1 = inaccessibleObject; + const base_1 = base; + const InteropBroker_1 = requireInteropBroker(); + const InteropClient_1 = requireInteropClient(); + const overrideCheck_1 = requireOverrideCheck(); + const common_utils_1 = commonUtils; + const defaultOverride = (Class) => new Class(); + const BrokerParamAccessError = 'You have attempted to use or modify InteropBroker parameters, which is not allowed. You are likely using an older InteropBroker override scheme. Please consult our Interop docs for guidance on migrating to the new override scheme.'; + /** + * Manages creation of Interop Brokers and Interop Clients. These APIs are called under-the-hood in Platforms. + * + */ + class InteropModule extends base_1.Base { + /** + * Initializes an Interop Broker. This is called under-the-hood for Platforms. + * + * @remarks For Platforms, this is set up automatically. We advise to only create your own Interop Broker + * when not using a Platform app. You can override functions in the Interop Broker. More info {@link InteropBroker here}. + * + * @param name - Name of the Interop Broker. + * @param override - A callback function or array of callback functions that can be used to extend or replace default Interop Broker behavior. + * + * @example + * ``` js + * const interopBroker = await fin.Interop.init('openfin'); + * const contextGroups = await interopBroker.getContextGroups(); + * console.log(contextGroups); + * ``` + */ + async init(name, override = defaultOverride) { + this.wire.sendAction('interop-init').catch(() => { + // don't expose, analytics-only call + }); + // Allows for manifest-level configuration, without having to override. (e.g. specifying custom context groups) + const options = await this.wire.environment.getInteropInfo(this.wire.getFin()); + const objectThatThrows = (0, inaccessibleObject_1.createUnusableObject)(BrokerParamAccessError); + const warningOptsClone = (0, inaccessibleObject_1.createWarningObject)(BrokerParamAccessError, (0, cloneDeep_1.default)(options)); + const getProvider = () => { + return this.fin.InterApplicationBus.Channel.create(`interop-broker-${name}`); + }; + const throwingGetProvider = async () => { + // eslint-disable-next-line no-console + throw new Error(BrokerParamAccessError); + }; + const OverrideableBroker = InteropBroker_1.InteropBroker.createClosedConstructor(this.wire, getProvider, options); + let broker; + if (Array.isArray(override)) { + const BrokerConstructor = (0, common_utils_1.overrideFromComposables)(...override)(OverrideableBroker); + // We need to use these objects because removing them entirely would be a breaking change and we want an informative error + // @ts-expect-error + broker = new BrokerConstructor(objectThatThrows, throwingGetProvider, warningOptsClone); + } + else { + // We need to use these objects because removing them entirely would be a breaking change and we want an informative error + // @ts-expect-error + broker = await override(OverrideableBroker, objectThatThrows, throwingGetProvider, warningOptsClone); + } + (0, overrideCheck_1.overrideCheck)(broker, options.fdc3Version); + return broker; + } + /** + * Connects a client to an Interop broker. This is called under-the-hood for Views in a Platform. + * + * @remarks + * @param name - The name of the Interop Broker to connect to. For Platforms, this will default to the uuid of the Platform. + * @param interopConfig - Information relevant to the Interop Broker. Typically a declaration of + * what context(s) the entity wants to subscribe to, and the current Context Group of the entity. + * + * @example + * ```js + * const interopConfig = { + * currentContextGroup: 'green' + * } + * + * const interopBroker = await fin.Interop.init('openfin'); + * const client = await fin.Interop.connectSync('openfin', interopConfig); + * const contextGroupInfo = await client.getInfoForContextGroup(); + * console.log(contextGroupInfo); + * ``` + */ + connectSync(name, interopConfig) { + this.wire.sendAction('interop-connect-sync').catch(() => { + // don't expose, analytics-only call + }); + return new InteropClient_1.InteropClient(this.wire, this.wire.environment.whenReady().then(() => { + return this.fin.InterApplicationBus.Channel.connect(`interop-broker-${name}`, { + payload: interopConfig + }); + })); + } + } + Factory$1.InteropModule = InteropModule; + return Factory$1; +} + +var hasRequiredInterop; + +function requireInterop () { + if (hasRequiredInterop) return interop; + hasRequiredInterop = 1; + (function (exports) { + /** + * Entry point for the OpenFin `Interop` API (`fin.Interop`). + * + * * {@link InteropModule} contains static members of the `Interop` API (available under `fin.Interop`) + * * {@link InteropClient} and {@link InteropBroker} document instances of their respective classes. + * + * @packageDocumentation + */ + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(requireFactory(), exports); + __exportStar(requireInteropClient(), exports); + __exportStar(requireInteropBroker(), exports); + } (interop)); + return interop; +} + +var snapshotSource = {}; + +var Factory = {}; + +var Instance = {}; + +var utils = {}; + +Object.defineProperty(utils, "__esModule", { value: true }); +utils.getSnapshotSourceChannelName = void 0; +const channelPrefix = 'snapshot-source-provider-'; +const getSnapshotSourceChannelName = (id) => `${channelPrefix}${id.uuid}`; +utils.getSnapshotSourceChannelName = getSnapshotSourceChannelName; + +var __classPrivateFieldSet$1 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$1 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _SnapshotSource_identity, _SnapshotSource_getConnection, _SnapshotSource_getClient, _SnapshotSource_startConnection, _SnapshotSource_setUpConnectionListener; +Object.defineProperty(Instance, "__esModule", { value: true }); +Instance.SnapshotSource = void 0; +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +const base_1$1 = base; +const utils_1$1 = utils; +const connectionMap = new Map(); +/** + * Enables configuring a SnapshotSource with custom getSnapshot and applySnapshot methods. + * + * @typeParam Snapshot Implementation-defined shape of an application snapshot. Allows + * custom snapshot implementations for legacy applications to define their own snapshot format. + */ +class SnapshotSource extends base_1$1.Base { + /** + * @internal + */ + constructor(wire, id) { + super(wire); + _SnapshotSource_identity.set(this, void 0); + _SnapshotSource_getConnection.set(this, () => { + if (!connectionMap.has(this.identity.uuid)) { + connectionMap.set(this.identity.uuid, { eventFired: null, clientPromise: null }); + } + return connectionMap.get(this.identity.uuid); + }); + _SnapshotSource_getClient.set(this, () => { + if (!__classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).clientPromise) { + __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).clientPromise = __classPrivateFieldGet$1(this, _SnapshotSource_startConnection, "f").call(this); + } + return __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).clientPromise; + }); + _SnapshotSource_startConnection.set(this, async () => { + const channelName = (0, utils_1$1.getSnapshotSourceChannelName)(this.identity); + try { + if (!__classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).eventFired) { + await __classPrivateFieldGet$1(this, _SnapshotSource_setUpConnectionListener, "f").call(this); + } + const client = await this.fin.InterApplicationBus.Channel.connect(channelName, { wait: false }); + client.onDisconnection(() => { + __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).clientPromise = null; + __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).eventFired = null; + }); + return client; + } + catch (e) { + __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).clientPromise = null; + throw new Error("The targeted SnapshotSource is not currently initialized. Await this object's ready() method."); + } + }); + _SnapshotSource_setUpConnectionListener.set(this, async () => { + const channelName = (0, utils_1$1.getSnapshotSourceChannelName)(this.identity); + let resolve; + let reject; + const eventFired = new Promise((y, n) => { + resolve = y; + reject = n; + }); + __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).eventFired = eventFired; + const listener = async (e) => { + try { + if (e.channelName === channelName) { + resolve(); + await this.fin.InterApplicationBus.Channel.removeListener('connected', listener); + } + } + catch (err) { + reject(err); + } + }; + await this.fin.InterApplicationBus.Channel.on('connected', listener); + }); + __classPrivateFieldSet$1(this, _SnapshotSource_identity, id, "f"); + } + get identity() { + return __classPrivateFieldGet$1(this, _SnapshotSource_identity, "f"); + } + /** + * Method to determine if the SnapshotSource has been initialized. + * + * @remarks Use when the parent application is starting up to ensure the SnapshotSource is able to accept and + * apply a snapshot using the {@link SnapshotSource#applySnapshot applySnapshot} method. + * + * @example + * ```js + * let snapshotSource = fin.SnapshotSource.wrapSync(fin.me); + * + * const snapshotProvider = { + * async getSnapshot() { return 'foo' }, + * async applySnapshot(snapshot) { + * console.log(snapshot); + * return undefined; + * } + * } + * await fin.SnapshotSource.init(snapshotProvider); + * + * try { + * await snapshotSource.ready(); + * await snapshotSource.applySnapshot('foo'); + * } catch (err) { + * console.log(err) + * } + * ``` + */ + async ready() { + this.wire.sendAction('snapshot-source-ready').catch((e) => { + // don't expose, analytics-only call + }); + // eslint-disable-next-line no-async-promise-executor + try { + // If getClient was already called before this, do we have a timing issue where the channel might have been created but we missed the event but this still fails? + await __classPrivateFieldGet$1(this, _SnapshotSource_getClient, "f").call(this); + } + catch (e) { + // it was not running. + await __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).eventFired; + } + } + /** + * Call the SnapshotSource's getSnapshot method defined by {@link SnapshotSource.SnapshotSourceModule#init init}. + * + */ + async getSnapshot() { + this.wire.sendAction('snapshot-source-get-snapshot').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet$1(this, _SnapshotSource_getClient, "f").call(this); + const response = (await client.dispatch('get-snapshot')); + return (await response).snapshot; + } + /** + * Call the SnapshotSource's applySnapshot method defined by {@link SnapshotSource.SnapshotSourceModule#init init}. + * + */ + async applySnapshot(snapshot) { + this.wire.sendAction('snapshot-source-apply-snapshot').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet$1(this, _SnapshotSource_getClient, "f").call(this); + return client.dispatch('apply-snapshot', { snapshot }); + } +} +Instance.SnapshotSource = SnapshotSource; +_SnapshotSource_identity = new WeakMap(), _SnapshotSource_getConnection = new WeakMap(), _SnapshotSource_getClient = new WeakMap(), _SnapshotSource_startConnection = new WeakMap(), _SnapshotSource_setUpConnectionListener = new WeakMap(); + +Object.defineProperty(Factory, "__esModule", { value: true }); +Factory.SnapshotSourceModule = void 0; +const base_1 = base; +const Instance_1 = Instance; +const utils_1 = utils; +/** + * Static namespace for OpenFin API methods that interact with the {@link SnapshotSource} class, available under `fin.SnapshotSource`. + */ +class SnapshotSourceModule extends base_1.Base { + /** + * Initializes a SnapshotSource with the getSnapshot and applySnapshot methods defined. + * + * @typeParam Snapshot Implementation-defined shape of an application snapshot. Allows + * custom snapshot implementations for legacy applications to define their own snapshot format. + * + * @example + * ```js + * const snapshotProvider = { + * async getSnapshot() { + * const bounds = await fin.me.getBounds(); + * return bounds; + * }, + * async applySnapshot(snapshot) { + * await fin.me.setBounds(snapshot); + * return undefined; + * } + * } + * + * await fin.SnapshotSource.init(snapshotProvider); + * ``` + * + */ + async init(provider) { + this.wire.sendAction('snapshot-source-init').catch((e) => { + // don't expose, analytics-only call + }); + if (typeof provider !== 'object' || + typeof provider.getSnapshot !== 'function' || + typeof provider.applySnapshot !== 'function') { + throw new Error('you must pass in a valid SnapshotProvider'); + } + const channel = await this.fin.InterApplicationBus.Channel.create((0, utils_1.getSnapshotSourceChannelName)(this.fin.me)); + channel.register('get-snapshot', async () => { + const snapshot = await provider.getSnapshot(); + return { snapshot }; + }); + channel.register('apply-snapshot', ({ snapshot }) => provider.applySnapshot(snapshot)); + } + /** + * Synchronously returns a SnapshotSource object that represents the current SnapshotSource. + * + * @example + * ```js + * const snapshotSource = fin.SnapshotSource.wrapSync(fin.me); + * // Use wrapped instance's getSnapshot method, e.g.: + * const snapshot = await snapshotSource.getSnapshot(); + * ``` + */ + wrapSync(identity) { + this.wire.sendAction('snapshot-source-wrap-sync').catch((e) => { + // don't expose, analytics-only call + }); + return new Instance_1.SnapshotSource(this.wire, identity); + } + /** + * Asynchronously returns a SnapshotSource object that represents the current SnapshotSource. + * + * @example + * ```js + * const snapshotSource = await fin.SnapshotSource.wrap(fin.me); + * // Use wrapped instance's getSnapshot method, e.g.: + * const snapshot = await snapshotSource.getSnapshot(); + * ``` + */ + async wrap(identity) { + this.wire.sendAction('snapshot-source-wrap').catch((e) => { + // don't expose, analytics-only call + }); + return this.wrapSync(identity); + } +} +Factory.SnapshotSourceModule = SnapshotSourceModule; + +(function (exports) { + /** + * Entry points for the OpenFin `SnapshotSource` API (`fin.SnapshotSource`). + * + * * {@link SnapshotSourceModule} contains static members of the `SnapshotSource` API, accessible through `fin.SnapshotSource`. + * * {@link SnapshotSource} describes an instance of an OpenFin SnapshotSource, e.g. as returned by `fin.SnapshotSource.wrap`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + */ + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(Factory, exports); + __exportStar(Instance, exports); +} (snapshotSource)); + +Object.defineProperty(fin$2, "__esModule", { value: true }); +var Fin_1 = fin$2.Fin = void 0; +const events_1$3 = require$$0; +// Import from the file rather than the directory in case someone consuming types is using module resolution other than "node" +const index_1 = system; +const index_2 = requireWindow(); +const index_3 = requireApplication(); +const index_4 = interappbus; +const index_5 = clipboard; +const index_6 = externalApplication; +const index_7 = frame; +const index_8 = globalHotkey; +const index_9 = requireView(); +const index_10 = platform; +const me_1$2 = me; +const interop_1 = requireInterop(); +const snapshot_source_1 = snapshotSource; +/** + * @internal + */ +class Fin extends events_1$3.EventEmitter { + /** + * @internal + */ + constructor(wire) { + super(); + this.wire = wire; + this.System = new index_1.System(wire); + this.Window = new index_2._WindowModule(wire); + this.Application = new index_3.ApplicationModule(wire); + this.InterApplicationBus = new index_4.InterApplicationBus(wire); + this.Clipboard = new index_5.Clipboard(wire); + this.ExternalApplication = new index_6.ExternalApplicationModule(wire); + this.Frame = new index_7._FrameModule(wire); + this.GlobalHotkey = new index_8.GlobalHotkey(wire); + this.Platform = new index_10.PlatformModule(wire, this.InterApplicationBus.Channel); + this.View = new index_9.ViewModule(wire); + this.Interop = new interop_1.InteropModule(wire); + this.SnapshotSource = new snapshot_source_1.SnapshotSourceModule(wire); + wire.registerFin(this); + this.me = (0, me_1$2.getMe)(wire); + // Handle disconnect events + wire.on('disconnected', () => { + this.emit('disconnected'); + }); + } +} +Fin_1 = fin$2.Fin = Fin; + +var transport = {}; + +var wire = {}; + +Object.defineProperty(wire, "__esModule", { value: true }); +wire.isInternalConnectConfig = wire.isPortDiscoveryConfig = wire.isNewConnectConfig = wire.isConfigWithReceiver = wire.isRemoteConfig = wire.isExistingConnectConfig = wire.isExternalConfig = void 0; +function isExternalConfig(config) { + if (typeof config.manifestUrl === 'string') { + return true; + } + return false; +} +wire.isExternalConfig = isExternalConfig; +function isExistingConnectConfig(config) { + return hasUuid(config) && typeof config.address === 'string'; +} +wire.isExistingConnectConfig = isExistingConnectConfig; +function isRemoteConfig(config) { + return isExistingConnectConfig(config) && typeof config.token === 'string'; +} +wire.isRemoteConfig = isRemoteConfig; +function isConfigWithReceiver(config) { + return typeof config.receiver === 'object' && isRemoteConfig({ ...config, address: '' }); +} +wire.isConfigWithReceiver = isConfigWithReceiver; +function hasUuid(config) { + return typeof config.uuid === 'string'; +} +function hasRuntimeVersion(config) { + return config.runtime && typeof config.runtime.version === 'string'; +} +function isNewConnectConfig(config) { + return hasUuid(config) && hasRuntimeVersion(config); +} +wire.isNewConnectConfig = isNewConnectConfig; +function isPortDiscoveryConfig(config) { + return (isExternalConfig(config) && hasRuntimeVersion(config)) || isNewConnectConfig(config); +} +wire.isPortDiscoveryConfig = isPortDiscoveryConfig; +function isInternalConnectConfig(config) { + return isExistingConnectConfig(config) || isNewConnectConfig(config); +} +wire.isInternalConnectConfig = isInternalConnectConfig; + +var eventAggregator = {}; + +var emitterMap = {}; + +Object.defineProperty(emitterMap, "__esModule", { value: true }); +emitterMap.EmitterMap = void 0; +const events_1$2 = require$$0; +class EmitterMap { + constructor() { + this.storage = new Map(); + } + // eslint-disable-next-line class-methods-use-this + hashKeys(keys) { + const hashed = keys.map(normalizeString); + return hashed.join('/'); + } + getOrCreate(keys) { + const hash = this.hashKeys(keys); + if (!this.storage.has(hash)) { + this.storage.set(hash, new events_1$2.EventEmitter()); + } + // We set it above + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return this.storage.get(hash); + } + has(keys) { + return this.storage.has(this.hashKeys(keys)); + } + delete(keys) { + const hash = this.hashKeys(keys); + return this.storage.delete(hash); + } +} +emitterMap.EmitterMap = EmitterMap; +function normalizeString(s) { + const b = Buffer.from(s); + return b.toString('base64'); +} + +Object.defineProperty(eventAggregator, "__esModule", { value: true }); +const emitterMap_1 = emitterMap; +function isEventMessage(message) { + return message.action === 'process-desktop-event'; +} +function mapKeyFromEvent(event) { + const { topic } = event; + if (topic === 'frame' || topic === 'window' || topic === 'view') { + const { uuid, name } = event; + return [topic, uuid, name]; + } + if (topic === 'application') { + const { uuid } = event; + return [topic, uuid]; + } + return [topic]; +} +class EventAggregator extends emitterMap_1.EmitterMap { + constructor() { + super(...arguments); + this.dispatchEvent = (message) => { + if (isEventMessage(message)) { + const { payload } = message; + const accessor = mapKeyFromEvent(payload); + if (this.has(accessor)) { + this.getOrCreate(accessor).emit(payload.type, payload); + return true; + } + } + return false; + }; + } +} +eventAggregator.default = EventAggregator; + +var __classPrivateFieldSet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _Transport_wire, _Transport_fin; +Object.defineProperty(transport, "__esModule", { value: true }); +var Transport_1 = transport.Transport = void 0; +const events_1$1 = require$$0; +const wire_1 = wire; +const transport_errors_1 = transportErrors; +const eventAggregator_1 = __importDefault(eventAggregator); +const me_1$1 = me; +const errors_1 = errors; +class Transport extends events_1$1.EventEmitter { + constructor(WireType, environment, config) { + super(); + this.wireListeners = new Map(); + this.topicRefMap = new Map(); + this.eventAggregator = new eventAggregator_1.default(); + this.messageHandlers = [this.eventAggregator.dispatchEvent]; + _Transport_wire.set(this, void 0); + // Typing as unknown to avoid circular dependency, should not be used directly. + _Transport_fin.set(this, void 0); + this.connectSync = () => { + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + wire.connectSync(); + }; + // This function is only used in our tests. + this.getPort = () => { + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + return wire.getPort(); + }; + __classPrivateFieldSet(this, _Transport_wire, new WireType(this.onmessage.bind(this)), "f"); + this.environment = environment; + this.sendRaw = __classPrivateFieldGet(this, _Transport_wire, "f").send.bind(__classPrivateFieldGet(this, _Transport_wire, "f")); + this.registerMessageHandler(this.handleMessage.bind(this)); + __classPrivateFieldGet(this, _Transport_wire, "f").on('disconnected', () => { + for (const [, { handleNack }] of this.wireListeners) { + handleNack({ reason: 'Remote connection has closed' }); + } + this.wireListeners.clear(); + this.emit('disconnected'); + }); + const { uuid, name } = config; + const entityType = this.environment.getCurrentEntityType(); + this.me = (0, me_1$1.getBaseMe)(entityType, uuid, name); + } + getFin() { + if (!__classPrivateFieldGet(this, _Transport_fin, "f")) { + throw new Error('No Fin object registered for this transport'); + } + return __classPrivateFieldGet(this, _Transport_fin, "f"); + } + registerFin(_fin) { + if (__classPrivateFieldGet(this, _Transport_fin, "f")) { + throw new Error('Fin object has already been registered for this transport'); + } + __classPrivateFieldSet(this, _Transport_fin, _fin, "f"); + } + shutdown() { + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + return wire.shutdown(); + } + async connect(config) { + if ((0, wire_1.isConfigWithReceiver)(config)) { + await __classPrivateFieldGet(this, _Transport_wire, "f").connect(config.receiver); + return this.authorize(config); + } + if ((0, wire_1.isRemoteConfig)(config)) { + return this.connectRemote(config); + } + if ((0, wire_1.isExistingConnectConfig)(config)) { + return this.connectByPort(config); + } + if ((0, wire_1.isNewConnectConfig)(config)) { + const port = await this.environment.retrievePort(config); + return this.connectByPort({ ...config, address: `ws://localhost:${port}` }); + } + return undefined; + } + async connectRemote(config) { + await __classPrivateFieldGet(this, _Transport_wire, "f").connect(new (this.environment.getWsConstructor())(config.address)); + return this.authorize(config); + } + async connectByPort(config) { + const { address, uuid } = config; + const reqAuthPayload = { ...config, type: 'file-token' }; + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + await wire.connect(new (this.environment.getWsConstructor())(config.address)); + const requestExtAuthRet = await this.sendAction('request-external-authorization', { + uuid, + type: 'file-token' + }, true); + if (requestExtAuthRet.action !== 'external-authorization-response') { + throw new transport_errors_1.UnexpectedActionError(requestExtAuthRet.action); + } + await this.environment.writeToken(requestExtAuthRet.payload.file, requestExtAuthRet.payload.token); + return this.authorize(reqAuthPayload); + } + async authorize(reqAuthPayload) { + const requestAuthRet = await this.sendAction('request-authorization', reqAuthPayload, true); + if (requestAuthRet.action !== 'authorization-response') { + throw new transport_errors_1.UnexpectedActionError(requestAuthRet.action); + } + else if (requestAuthRet.payload.success !== true) { + throw new transport_errors_1.RuntimeError(requestAuthRet.payload); + } + } + sendAction(action, payload = {}, uncorrelated = false + // specialResponse type is only used for 'requestAuthorization' + ) { + // eslint-disable-next-line @typescript-eslint/no-empty-function + let cancel = () => { }; + // We want the callsite from the caller of this function, not from here. + const callSites = transport_errors_1.RuntimeError.getCallSite(1); + const messageId = this.environment.getNextMessageId(); + const prom = new Promise((resolve, reject) => { + cancel = reject; + const msg = { + action, + payload, + messageId + }; + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + this.addWireListener(messageId, resolve, (payload) => this.nackHandler(payload, reject, callSites), uncorrelated); + return wire.send(msg).catch(reject); + }); + return Object.assign(prom, { cancel, messageId }); + } + nackHandler(payloadOrMessage, reject, callSites) { + if (typeof payloadOrMessage === 'string') { + // NOTE: this is for backwards compatibility to support plain string rejections + reject(payloadOrMessage); + } + else { + reject(new transport_errors_1.RuntimeError(payloadOrMessage, callSites)); + } + } + ferryAction(origData) { + return new Promise((resolve, reject) => { + const id = this.environment.getNextMessageId(); + origData.messageId = id; + const resolver = (data) => { + resolve(data.payload); + }; + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + return wire + .send(origData) + .then(() => this.addWireListener(id, resolver, (payload) => this.nackHandler(payload, reject), false)) + .catch(reject); + }); + } + registerMessageHandler(handler) { + this.messageHandlers.push(handler); + } + addWireListener(id, resolve, handleNack, uncorrelated) { + if (uncorrelated) { + this.uncorrelatedListener = resolve; + } + else if (this.wireListeners.has(id)) { + handleNack({ + reason: 'Duplicate handler id', + error: (0, errors_1.errorToPOJO)(new transport_errors_1.DuplicateCorrelationError(String(id))) + }); + } + else { + this.wireListeners.set(id, { resolve, handleNack }); + } + // Timeout and reject()? + } + // This method executes message handlers until the _one_ that handles the message (returns truthy) has run + onmessage(data) { + for (const h of this.messageHandlers) { + h.call(null, data); + } + } + handleMessage(data) { + const id = data.correlationId || NaN; + if (!('correlationId' in data)) { + if (this.uncorrelatedListener) { + this.uncorrelatedListener.call(null, data); + } + this.uncorrelatedListener = () => { + // empty block + }; + } + else if (!this.wireListeners.has(id)) { + return false; + } + else { + // We just checked for existence above + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const { resolve, handleNack } = this.wireListeners.get(id); + if (data.action !== 'ack') { + handleNack({ reason: 'Did not receive ack action', error: (0, errors_1.errorToPOJO)(new transport_errors_1.NoAckError(data.action)) }); + } + else if (!('payload' in data)) { + // I'm not sure when this code would actually run, but passing in something that doeesn't have a reason to the runtimeerror constructor will not end well. + // @ts-expect-error + if (typeof data.reason === 'string') { + handleNack(data); + } + else { + console.warn('Received invalid response from core', data); + handleNack({ reason: 'invalid response shape' }); + } + } + else if (!data.payload.success) { + handleNack(data.payload); + } + else { + resolve.call(null, data); + } + this.wireListeners.delete(id); + } + return true; + } +} +Transport_1 = transport.Transport = Transport; +_Transport_wire = new WeakMap(), _Transport_fin = new WeakMap(); + +var mockEnvironment = {}; + +Object.defineProperty(mockEnvironment, "__esModule", { value: true }); +var MockEnvironment_1 = mockEnvironment.MockEnvironment = void 0; +const me_1 = me; +class MockEnvironment { + constructor() { + this.type = 'other'; + this.childViews = true; + } + getAdapterVersionSync() { + throw new Error(me_1.environmentUnsupportedMessage); + } + async getInteropInfo() { + throw new Error(me_1.environmentUnsupportedMessage); + } + getDefaultChannelOptions() { + throw new Error(me_1.environmentUnsupportedMessage); + } + getRtcPeer() { + throw new Error(me_1.environmentUnsupportedMessage); + } + layoutAllowedInContext(_fin) { + throw new Error(me_1.environmentUnsupportedMessage); + } + initLayoutManager() { + throw new Error(me_1.environmentUnsupportedMessage); + } + applyLayoutSnapshot() { + throw new Error(me_1.environmentUnsupportedMessage); + } + async createLayout() { + throw new Error(me_1.environmentUnsupportedMessage); + } + async destroyLayout() { + throw new Error(me_1.environmentUnsupportedMessage); + } + async resolveLayout() { + throw new Error(me_1.environmentUnsupportedMessage); + } + initPlatform() { + throw new Error(me_1.environmentUnsupportedMessage); + } + observeBounds() { + throw new Error(me_1.environmentUnsupportedMessage); + } + writeToken(path, token) { + throw new Error(me_1.environmentUnsupportedMessage); + } + retrievePort(config) { + throw new Error(me_1.environmentUnsupportedMessage); + } + getNextMessageId() { + return `mock-message-id-${Math.random()}`; + } + getRandomId() { + throw new Error(me_1.environmentUnsupportedMessage); + } + createChildContent(options) { + throw new Error(me_1.environmentUnsupportedMessage); + } + getWebWindow(identity) { + throw new Error(me_1.environmentUnsupportedMessage); + } + getCurrentEntityIdentity() { + throw new Error(me_1.environmentUnsupportedMessage); + } + getCurrentEntityType() { + return 'unknown'; + } + raiseEvent(eventName, eventArgs) { + throw new Error(me_1.environmentUnsupportedMessage); + } + getUrl() { + throw new Error(me_1.environmentUnsupportedMessage); + } + whenReady() { + throw new Error(me_1.environmentUnsupportedMessage); + } + getWsConstructor() { + throw new Error('Method not implemented.'); + } +} +MockEnvironment_1 = mockEnvironment.MockEnvironment = MockEnvironment; + +var mockWire = {}; + +Object.defineProperty(mockWire, "__esModule", { value: true }); +var MockWire_1 = mockWire.MockWire = void 0; +/* eslint-disable @typescript-eslint/no-unused-vars */ +const events_1 = require$$0; +class MockWire extends events_1.EventEmitter { + connect() { + throw new Error('You are not running in OpenFin.'); + } + connectSync() { + throw new Error('You are not running in OpenFin.'); + } + send(data) { + throw new Error('You are not running in OpenFin.'); + } + shutdown() { + throw new Error('You are not running in OpenFin.'); + } + getPort() { + throw new Error('This transport has no port'); + } + // eslint-disable-next-line no-useless-constructor + constructor() { + super(); + } +} +MockWire_1 = mockWire.MockWire = MockWire; + +const fin$1 = ((typeof window !== 'undefined' && window?.fin) || + (() => { + const environment = new MockEnvironment_1(); + const transport = new Transport_1(MockWire_1, environment, { + uuid: '', + name: '' + }); + return new Fin_1(transport); + })()); + +exports.OpenFin = OpenFin$1; +exports["default"] = OpenFin$1; +exports.fin = fin$1; + + +/***/ }), + +/***/ "../../node_modules/events/events.js": +/*!*******************************************!*\ + !*** ../../node_modules/events/events.js ***! + \*******************************************/ +/***/ ((module) => { + +"use strict"; +// 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. + + + +var R = typeof Reflect === 'object' ? Reflect : null +var ReflectApply = R && typeof R.apply === 'function' + ? R.apply + : function ReflectApply(target, receiver, args) { + return Function.prototype.apply.call(target, receiver, args); + } + +var ReflectOwnKeys +if (R && typeof R.ownKeys === 'function') { + ReflectOwnKeys = R.ownKeys +} else if (Object.getOwnPropertySymbols) { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target) + .concat(Object.getOwnPropertySymbols(target)); + }; +} else { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target); + }; +} + +function ProcessEmitWarning(warning) { + if (console && console.warn) console.warn(warning); +} + +var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { + return value !== value; +} + +function EventEmitter() { + EventEmitter.init.call(this); +} +module.exports = EventEmitter; +module.exports.once = once; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._eventsCount = 0; +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. +var defaultMaxListeners = 10; + +function checkListener(listener) { + if (typeof listener !== 'function') { + throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); + } +} + +Object.defineProperty(EventEmitter, 'defaultMaxListeners', { + enumerable: true, + get: function() { + return defaultMaxListeners; + }, + set: function(arg) { + if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { + throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); + } + defaultMaxListeners = arg; + } +}); + +EventEmitter.init = function() { + + if (this._events === undefined || + this._events === Object.getPrototypeOf(this)._events) { + this._events = Object.create(null); + this._eventsCount = 0; + } + + this._maxListeners = this._maxListeners || undefined; +}; + +// 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 setMaxListeners(n) { + if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { + throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); + } + this._maxListeners = n; + return this; +}; + +function _getMaxListeners(that) { + if (that._maxListeners === undefined) + return EventEmitter.defaultMaxListeners; + return that._maxListeners; +} + +EventEmitter.prototype.getMaxListeners = function getMaxListeners() { + return _getMaxListeners(this); +}; + +EventEmitter.prototype.emit = function emit(type) { + var args = []; + for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); + var doError = (type === 'error'); + + var events = this._events; + if (events !== undefined) + doError = (doError && events.error === undefined); + else if (!doError) + return false; + + // If there is no 'error' event listener then throw. + if (doError) { + var er; + if (args.length > 0) + er = args[0]; + if (er instanceof Error) { + // Note: The comments on the `throw` lines are intentional, they show + // up in Node's output if this results in an unhandled exception. + throw er; // Unhandled 'error' event + } + // At least give some kind of context to the user + var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); + err.context = er; + throw err; // Unhandled 'error' event + } + + var handler = events[type]; + + if (handler === undefined) + return false; + + if (typeof handler === 'function') { + ReflectApply(handler, this, args); + } else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + ReflectApply(listeners[i], this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + checkListener(listener); + + events = target._events; + if (events === undefined) { + events = target._events = Object.create(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener !== undefined) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (existing === undefined) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + // If we've already got an array, just append. + } else if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + + // Check for listener leak + m = _getMaxListeners(target); + if (m > 0 && existing.length > m && !existing.warned) { + existing.warned = true; + // No error code for this since it is a Warning + // eslint-disable-next-line no-restricted-syntax + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' ' + String(type) + ' listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + ProcessEmitWarning(w); + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + if (arguments.length === 0) + return this.listener.call(this.target); + return this.listener.apply(this.target, arguments); + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = onceWrapper.bind(state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + checkListener(listener); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + checkListener(listener); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + checkListener(listener); + + events = this._events; + if (events === undefined) + return this; + + list = events[type]; + if (list === undefined) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else { + spliceOne(list, position); + } + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener !== undefined) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (events === undefined) + return this; + + // not listening for removeListener, no need to emit + if (events.removeListener === undefined) { + if (arguments.length === 0) { + this._events = Object.create(null); + this._eventsCount = 0; + } else if (events[type] !== undefined) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = Object.keys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = Object.create(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners !== undefined) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (events === undefined) + return []; + + var evlistener = events[type]; + if (evlistener === undefined) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? + unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events !== undefined) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener !== undefined) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; +}; + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function spliceOne(list, index) { + for (; index + 1 < list.length; index++) + list[index] = list[index + 1]; + list.pop(); +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function once(emitter, name) { + return new Promise(function (resolve, reject) { + function errorListener(err) { + emitter.removeListener(name, resolver); + reject(err); + } + + function resolver() { + if (typeof emitter.removeListener === 'function') { + emitter.removeListener('error', errorListener); + } + resolve([].slice.call(arguments)); + }; + + eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); + if (name !== 'error') { + addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); + } + }); +} + +function addErrorHandlerIfEventEmitter(emitter, handler, flags) { + if (typeof emitter.on === 'function') { + eventTargetAgnosticAddListener(emitter, 'error', handler, flags); + } +} + +function eventTargetAgnosticAddListener(emitter, name, listener, flags) { + if (typeof emitter.on === 'function') { + if (flags.once) { + emitter.once(name, listener); + } else { + emitter.on(name, listener); + } + } else if (typeof emitter.addEventListener === 'function') { + // EventTarget does not have `error` event semantics like Node + // EventEmitters, we do not listen for `error` events here. + emitter.addEventListener(name, function wrapListener(arg) { + // IE does not have builtin `{ once: true }` support so we + // have to do it manually. + if (flags.once) { + emitter.removeEventListener(name, wrapListener); + } + listener(arg); + }); + } else { + throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter); + } +} + + +/***/ }), + +/***/ "../../node_modules/lodash/_DataView.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_DataView.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../node_modules/lodash/_getNative.js"), + root = __webpack_require__(/*! ./_root */ "../../node_modules/lodash/_root.js"); + +/* Built-in method references that are verified to be native. */ +var DataView = getNative(root, 'DataView'); + +module.exports = DataView; + + +/***/ }), + +/***/ "../../node_modules/lodash/_Hash.js": +/*!******************************************!*\ + !*** ../../node_modules/lodash/_Hash.js ***! + \******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var hashClear = __webpack_require__(/*! ./_hashClear */ "../../node_modules/lodash/_hashClear.js"), + hashDelete = __webpack_require__(/*! ./_hashDelete */ "../../node_modules/lodash/_hashDelete.js"), + hashGet = __webpack_require__(/*! ./_hashGet */ "../../node_modules/lodash/_hashGet.js"), + hashHas = __webpack_require__(/*! ./_hashHas */ "../../node_modules/lodash/_hashHas.js"), + hashSet = __webpack_require__(/*! ./_hashSet */ "../../node_modules/lodash/_hashSet.js"); + +/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `Hash`. +Hash.prototype.clear = hashClear; +Hash.prototype['delete'] = hashDelete; +Hash.prototype.get = hashGet; +Hash.prototype.has = hashHas; +Hash.prototype.set = hashSet; + +module.exports = Hash; + + +/***/ }), + +/***/ "../../node_modules/lodash/_ListCache.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_ListCache.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var listCacheClear = __webpack_require__(/*! ./_listCacheClear */ "../../node_modules/lodash/_listCacheClear.js"), + listCacheDelete = __webpack_require__(/*! ./_listCacheDelete */ "../../node_modules/lodash/_listCacheDelete.js"), + listCacheGet = __webpack_require__(/*! ./_listCacheGet */ "../../node_modules/lodash/_listCacheGet.js"), + listCacheHas = __webpack_require__(/*! ./_listCacheHas */ "../../node_modules/lodash/_listCacheHas.js"), + listCacheSet = __webpack_require__(/*! ./_listCacheSet */ "../../node_modules/lodash/_listCacheSet.js"); + +/** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `ListCache`. +ListCache.prototype.clear = listCacheClear; +ListCache.prototype['delete'] = listCacheDelete; +ListCache.prototype.get = listCacheGet; +ListCache.prototype.has = listCacheHas; +ListCache.prototype.set = listCacheSet; + +module.exports = ListCache; + + +/***/ }), + +/***/ "../../node_modules/lodash/_Map.js": +/*!*****************************************!*\ + !*** ../../node_modules/lodash/_Map.js ***! + \*****************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../node_modules/lodash/_getNative.js"), + root = __webpack_require__(/*! ./_root */ "../../node_modules/lodash/_root.js"); + +/* Built-in method references that are verified to be native. */ +var Map = getNative(root, 'Map'); + +module.exports = Map; + + +/***/ }), + +/***/ "../../node_modules/lodash/_MapCache.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_MapCache.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var mapCacheClear = __webpack_require__(/*! ./_mapCacheClear */ "../../node_modules/lodash/_mapCacheClear.js"), + mapCacheDelete = __webpack_require__(/*! ./_mapCacheDelete */ "../../node_modules/lodash/_mapCacheDelete.js"), + mapCacheGet = __webpack_require__(/*! ./_mapCacheGet */ "../../node_modules/lodash/_mapCacheGet.js"), + mapCacheHas = __webpack_require__(/*! ./_mapCacheHas */ "../../node_modules/lodash/_mapCacheHas.js"), + mapCacheSet = __webpack_require__(/*! ./_mapCacheSet */ "../../node_modules/lodash/_mapCacheSet.js"); + +/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `MapCache`. +MapCache.prototype.clear = mapCacheClear; +MapCache.prototype['delete'] = mapCacheDelete; +MapCache.prototype.get = mapCacheGet; +MapCache.prototype.has = mapCacheHas; +MapCache.prototype.set = mapCacheSet; + +module.exports = MapCache; + + +/***/ }), + +/***/ "../../node_modules/lodash/_Promise.js": +/*!*********************************************!*\ + !*** ../../node_modules/lodash/_Promise.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../node_modules/lodash/_getNative.js"), + root = __webpack_require__(/*! ./_root */ "../../node_modules/lodash/_root.js"); + +/* Built-in method references that are verified to be native. */ +var Promise = getNative(root, 'Promise'); + +module.exports = Promise; + + +/***/ }), + +/***/ "../../node_modules/lodash/_Set.js": +/*!*****************************************!*\ + !*** ../../node_modules/lodash/_Set.js ***! + \*****************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../node_modules/lodash/_getNative.js"), + root = __webpack_require__(/*! ./_root */ "../../node_modules/lodash/_root.js"); + +/* Built-in method references that are verified to be native. */ +var Set = getNative(root, 'Set'); + +module.exports = Set; + + +/***/ }), + +/***/ "../../node_modules/lodash/_SetCache.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_SetCache.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var MapCache = __webpack_require__(/*! ./_MapCache */ "../../node_modules/lodash/_MapCache.js"), + setCacheAdd = __webpack_require__(/*! ./_setCacheAdd */ "../../node_modules/lodash/_setCacheAdd.js"), + setCacheHas = __webpack_require__(/*! ./_setCacheHas */ "../../node_modules/lodash/_setCacheHas.js"); + +/** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ +function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } +} + +// Add methods to `SetCache`. +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; +SetCache.prototype.has = setCacheHas; + +module.exports = SetCache; + + +/***/ }), + +/***/ "../../node_modules/lodash/_Stack.js": +/*!*******************************************!*\ + !*** ../../node_modules/lodash/_Stack.js ***! + \*******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var ListCache = __webpack_require__(/*! ./_ListCache */ "../../node_modules/lodash/_ListCache.js"), + stackClear = __webpack_require__(/*! ./_stackClear */ "../../node_modules/lodash/_stackClear.js"), + stackDelete = __webpack_require__(/*! ./_stackDelete */ "../../node_modules/lodash/_stackDelete.js"), + stackGet = __webpack_require__(/*! ./_stackGet */ "../../node_modules/lodash/_stackGet.js"), + stackHas = __webpack_require__(/*! ./_stackHas */ "../../node_modules/lodash/_stackHas.js"), + stackSet = __webpack_require__(/*! ./_stackSet */ "../../node_modules/lodash/_stackSet.js"); + +/** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; +} + +// Add methods to `Stack`. +Stack.prototype.clear = stackClear; +Stack.prototype['delete'] = stackDelete; +Stack.prototype.get = stackGet; +Stack.prototype.has = stackHas; +Stack.prototype.set = stackSet; + +module.exports = Stack; + + +/***/ }), + +/***/ "../../node_modules/lodash/_Symbol.js": +/*!********************************************!*\ + !*** ../../node_modules/lodash/_Symbol.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var root = __webpack_require__(/*! ./_root */ "../../node_modules/lodash/_root.js"); + +/** Built-in value references. */ +var Symbol = root.Symbol; + +module.exports = Symbol; + + +/***/ }), + +/***/ "../../node_modules/lodash/_Uint8Array.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_Uint8Array.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var root = __webpack_require__(/*! ./_root */ "../../node_modules/lodash/_root.js"); + +/** Built-in value references. */ +var Uint8Array = root.Uint8Array; + +module.exports = Uint8Array; + + +/***/ }), + +/***/ "../../node_modules/lodash/_WeakMap.js": +/*!*********************************************!*\ + !*** ../../node_modules/lodash/_WeakMap.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../node_modules/lodash/_getNative.js"), + root = __webpack_require__(/*! ./_root */ "../../node_modules/lodash/_root.js"); + +/* Built-in method references that are verified to be native. */ +var WeakMap = getNative(root, 'WeakMap'); + +module.exports = WeakMap; + + +/***/ }), + +/***/ "../../node_modules/lodash/_arrayEach.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_arrayEach.js ***! + \***********************************************/ +/***/ ((module) => { + +/** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ +function arrayEach(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; +} + +module.exports = arrayEach; + + +/***/ }), + +/***/ "../../node_modules/lodash/_arrayFilter.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_arrayFilter.js ***! + \*************************************************/ +/***/ ((module) => { + +/** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ +function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; +} + +module.exports = arrayFilter; + + +/***/ }), + +/***/ "../../node_modules/lodash/_arrayLikeKeys.js": +/*!***************************************************!*\ + !*** ../../node_modules/lodash/_arrayLikeKeys.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseTimes = __webpack_require__(/*! ./_baseTimes */ "../../node_modules/lodash/_baseTimes.js"), + isArguments = __webpack_require__(/*! ./isArguments */ "../../node_modules/lodash/isArguments.js"), + isArray = __webpack_require__(/*! ./isArray */ "../../node_modules/lodash/isArray.js"), + isBuffer = __webpack_require__(/*! ./isBuffer */ "../../node_modules/lodash/isBuffer.js"), + isIndex = __webpack_require__(/*! ./_isIndex */ "../../node_modules/lodash/_isIndex.js"), + isTypedArray = __webpack_require__(/*! ./isTypedArray */ "../../node_modules/lodash/isTypedArray.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ +function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; +} + +module.exports = arrayLikeKeys; + + +/***/ }), + +/***/ "../../node_modules/lodash/_arrayPush.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_arrayPush.js ***! + \***********************************************/ +/***/ ((module) => { + +/** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ +function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} + +module.exports = arrayPush; + + +/***/ }), + +/***/ "../../node_modules/lodash/_arraySome.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_arraySome.js ***! + \***********************************************/ +/***/ ((module) => { + +/** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ +function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; +} + +module.exports = arraySome; + + +/***/ }), + +/***/ "../../node_modules/lodash/_assignValue.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_assignValue.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseAssignValue = __webpack_require__(/*! ./_baseAssignValue */ "../../node_modules/lodash/_baseAssignValue.js"), + eq = __webpack_require__(/*! ./eq */ "../../node_modules/lodash/eq.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } +} + +module.exports = assignValue; + + +/***/ }), + +/***/ "../../node_modules/lodash/_assocIndexOf.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_assocIndexOf.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var eq = __webpack_require__(/*! ./eq */ "../../node_modules/lodash/eq.js"); + +/** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +module.exports = assocIndexOf; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseAssign.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_baseAssign.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var copyObject = __webpack_require__(/*! ./_copyObject */ "../../node_modules/lodash/_copyObject.js"), + keys = __webpack_require__(/*! ./keys */ "../../node_modules/lodash/keys.js"); + +/** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ +function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); +} + +module.exports = baseAssign; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseAssignIn.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_baseAssignIn.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var copyObject = __webpack_require__(/*! ./_copyObject */ "../../node_modules/lodash/_copyObject.js"), + keysIn = __webpack_require__(/*! ./keysIn */ "../../node_modules/lodash/keysIn.js"); + +/** + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ +function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); +} + +module.exports = baseAssignIn; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseAssignValue.js": +/*!*****************************************************!*\ + !*** ../../node_modules/lodash/_baseAssignValue.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var defineProperty = __webpack_require__(/*! ./_defineProperty */ "../../node_modules/lodash/_defineProperty.js"); + +/** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } +} + +module.exports = baseAssignValue; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseClone.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_baseClone.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Stack = __webpack_require__(/*! ./_Stack */ "../../node_modules/lodash/_Stack.js"), + arrayEach = __webpack_require__(/*! ./_arrayEach */ "../../node_modules/lodash/_arrayEach.js"), + assignValue = __webpack_require__(/*! ./_assignValue */ "../../node_modules/lodash/_assignValue.js"), + baseAssign = __webpack_require__(/*! ./_baseAssign */ "../../node_modules/lodash/_baseAssign.js"), + baseAssignIn = __webpack_require__(/*! ./_baseAssignIn */ "../../node_modules/lodash/_baseAssignIn.js"), + cloneBuffer = __webpack_require__(/*! ./_cloneBuffer */ "../../node_modules/lodash/_cloneBuffer.js"), + copyArray = __webpack_require__(/*! ./_copyArray */ "../../node_modules/lodash/_copyArray.js"), + copySymbols = __webpack_require__(/*! ./_copySymbols */ "../../node_modules/lodash/_copySymbols.js"), + copySymbolsIn = __webpack_require__(/*! ./_copySymbolsIn */ "../../node_modules/lodash/_copySymbolsIn.js"), + getAllKeys = __webpack_require__(/*! ./_getAllKeys */ "../../node_modules/lodash/_getAllKeys.js"), + getAllKeysIn = __webpack_require__(/*! ./_getAllKeysIn */ "../../node_modules/lodash/_getAllKeysIn.js"), + getTag = __webpack_require__(/*! ./_getTag */ "../../node_modules/lodash/_getTag.js"), + initCloneArray = __webpack_require__(/*! ./_initCloneArray */ "../../node_modules/lodash/_initCloneArray.js"), + initCloneByTag = __webpack_require__(/*! ./_initCloneByTag */ "../../node_modules/lodash/_initCloneByTag.js"), + initCloneObject = __webpack_require__(/*! ./_initCloneObject */ "../../node_modules/lodash/_initCloneObject.js"), + isArray = __webpack_require__(/*! ./isArray */ "../../node_modules/lodash/isArray.js"), + isBuffer = __webpack_require__(/*! ./isBuffer */ "../../node_modules/lodash/isBuffer.js"), + isMap = __webpack_require__(/*! ./isMap */ "../../node_modules/lodash/isMap.js"), + isObject = __webpack_require__(/*! ./isObject */ "../../node_modules/lodash/isObject.js"), + isSet = __webpack_require__(/*! ./isSet */ "../../node_modules/lodash/isSet.js"), + keys = __webpack_require__(/*! ./keys */ "../../node_modules/lodash/keys.js"), + keysIn = __webpack_require__(/*! ./keysIn */ "../../node_modules/lodash/keysIn.js"); + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG = 1, + CLONE_FLAT_FLAG = 2, + CLONE_SYMBOLS_FLAG = 4; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + weakMapTag = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values supported by `_.clone`. */ +var cloneableTags = {}; +cloneableTags[argsTag] = cloneableTags[arrayTag] = +cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = +cloneableTags[boolTag] = cloneableTags[dateTag] = +cloneableTags[float32Tag] = cloneableTags[float64Tag] = +cloneableTags[int8Tag] = cloneableTags[int16Tag] = +cloneableTags[int32Tag] = cloneableTags[mapTag] = +cloneableTags[numberTag] = cloneableTags[objectTag] = +cloneableTags[regexpTag] = cloneableTags[setTag] = +cloneableTags[stringTag] = cloneableTags[symbolTag] = +cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = +cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; +cloneableTags[errorTag] = cloneableTags[funcTag] = +cloneableTags[weakMapTag] = false; + +/** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ +function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG; + + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = (isFlat || isFunc) ? {} : initCloneObject(value); + if (!isDeep) { + return isFlat + ? copySymbolsIn(value, baseAssignIn(result, value)) + : copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + if (isSet(value)) { + value.forEach(function(subValue) { + result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); + }); + } else if (isMap(value)) { + value.forEach(function(subValue, key) { + result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + } + + var keysFunc = isFull + ? (isFlat ? getAllKeysIn : getAllKeys) + : (isFlat ? keysIn : keys); + + var props = isArr ? undefined : keysFunc(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + return result; +} + +module.exports = baseClone; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseCreate.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_baseCreate.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isObject = __webpack_require__(/*! ./isObject */ "../../node_modules/lodash/isObject.js"); + +/** Built-in value references. */ +var objectCreate = Object.create; + +/** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ +var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; +}()); + +module.exports = baseCreate; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseGetAllKeys.js": +/*!****************************************************!*\ + !*** ../../node_modules/lodash/_baseGetAllKeys.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var arrayPush = __webpack_require__(/*! ./_arrayPush */ "../../node_modules/lodash/_arrayPush.js"), + isArray = __webpack_require__(/*! ./isArray */ "../../node_modules/lodash/isArray.js"); + +/** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ +function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); +} + +module.exports = baseGetAllKeys; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseGetTag.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_baseGetTag.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Symbol = __webpack_require__(/*! ./_Symbol */ "../../node_modules/lodash/_Symbol.js"), + getRawTag = __webpack_require__(/*! ./_getRawTag */ "../../node_modules/lodash/_getRawTag.js"), + objectToString = __webpack_require__(/*! ./_objectToString */ "../../node_modules/lodash/_objectToString.js"); + +/** `Object#toString` result references. */ +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); +} + +module.exports = baseGetTag; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseIsArguments.js": +/*!*****************************************************!*\ + !*** ../../node_modules/lodash/_baseIsArguments.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseGetTag = __webpack_require__(/*! ./_baseGetTag */ "../../node_modules/lodash/_baseGetTag.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../node_modules/lodash/isObjectLike.js"); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]'; + +/** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ +function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; +} + +module.exports = baseIsArguments; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseIsEqual.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_baseIsEqual.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsEqualDeep = __webpack_require__(/*! ./_baseIsEqualDeep */ "../../node_modules/lodash/_baseIsEqualDeep.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../node_modules/lodash/isObjectLike.js"); + +/** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ +function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); +} + +module.exports = baseIsEqual; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseIsEqualDeep.js": +/*!*****************************************************!*\ + !*** ../../node_modules/lodash/_baseIsEqualDeep.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Stack = __webpack_require__(/*! ./_Stack */ "../../node_modules/lodash/_Stack.js"), + equalArrays = __webpack_require__(/*! ./_equalArrays */ "../../node_modules/lodash/_equalArrays.js"), + equalByTag = __webpack_require__(/*! ./_equalByTag */ "../../node_modules/lodash/_equalByTag.js"), + equalObjects = __webpack_require__(/*! ./_equalObjects */ "../../node_modules/lodash/_equalObjects.js"), + getTag = __webpack_require__(/*! ./_getTag */ "../../node_modules/lodash/_getTag.js"), + isArray = __webpack_require__(/*! ./isArray */ "../../node_modules/lodash/isArray.js"), + isBuffer = __webpack_require__(/*! ./isBuffer */ "../../node_modules/lodash/isBuffer.js"), + isTypedArray = __webpack_require__(/*! ./isTypedArray */ "../../node_modules/lodash/isTypedArray.js"); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + objectTag = '[object Object]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); +} + +module.exports = baseIsEqualDeep; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseIsMap.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_baseIsMap.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getTag = __webpack_require__(/*! ./_getTag */ "../../node_modules/lodash/_getTag.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../node_modules/lodash/isObjectLike.js"); + +/** `Object#toString` result references. */ +var mapTag = '[object Map]'; + +/** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ +function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; +} + +module.exports = baseIsMap; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseIsNative.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_baseIsNative.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isFunction = __webpack_require__(/*! ./isFunction */ "../../node_modules/lodash/isFunction.js"), + isMasked = __webpack_require__(/*! ./_isMasked */ "../../node_modules/lodash/_isMasked.js"), + isObject = __webpack_require__(/*! ./isObject */ "../../node_modules/lodash/isObject.js"), + toSource = __webpack_require__(/*! ./_toSource */ "../../node_modules/lodash/_toSource.js"); + +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + +/** Used to detect host constructors (Safari). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** Used for built-in method references. */ +var funcProto = Function.prototype, + objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ +function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); +} + +module.exports = baseIsNative; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseIsSet.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_baseIsSet.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getTag = __webpack_require__(/*! ./_getTag */ "../../node_modules/lodash/_getTag.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../node_modules/lodash/isObjectLike.js"); + +/** `Object#toString` result references. */ +var setTag = '[object Set]'; + +/** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ +function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; +} + +module.exports = baseIsSet; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseIsTypedArray.js": +/*!******************************************************!*\ + !*** ../../node_modules/lodash/_baseIsTypedArray.js ***! + \******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseGetTag = __webpack_require__(/*! ./_baseGetTag */ "../../node_modules/lodash/_baseGetTag.js"), + isLength = __webpack_require__(/*! ./isLength */ "../../node_modules/lodash/isLength.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../node_modules/lodash/isObjectLike.js"); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values of typed arrays. */ +var typedArrayTags = {}; +typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = +typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = +typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = +typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = +typedArrayTags[uint32Tag] = true; +typedArrayTags[argsTag] = typedArrayTags[arrayTag] = +typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = +typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = +typedArrayTags[errorTag] = typedArrayTags[funcTag] = +typedArrayTags[mapTag] = typedArrayTags[numberTag] = +typedArrayTags[objectTag] = typedArrayTags[regexpTag] = +typedArrayTags[setTag] = typedArrayTags[stringTag] = +typedArrayTags[weakMapTag] = false; + +/** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ +function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; +} + +module.exports = baseIsTypedArray; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseKeys.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_baseKeys.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isPrototype = __webpack_require__(/*! ./_isPrototype */ "../../node_modules/lodash/_isPrototype.js"), + nativeKeys = __webpack_require__(/*! ./_nativeKeys */ "../../node_modules/lodash/_nativeKeys.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; +} + +module.exports = baseKeys; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseKeysIn.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_baseKeysIn.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isObject = __webpack_require__(/*! ./isObject */ "../../node_modules/lodash/isObject.js"), + isPrototype = __webpack_require__(/*! ./_isPrototype */ "../../node_modules/lodash/_isPrototype.js"), + nativeKeysIn = __webpack_require__(/*! ./_nativeKeysIn */ "../../node_modules/lodash/_nativeKeysIn.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; +} + +module.exports = baseKeysIn; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseTimes.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_baseTimes.js ***! + \***********************************************/ +/***/ ((module) => { + +/** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ +function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} + +module.exports = baseTimes; + + +/***/ }), + +/***/ "../../node_modules/lodash/_baseUnary.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_baseUnary.js ***! + \***********************************************/ +/***/ ((module) => { + +/** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ +function baseUnary(func) { + return function(value) { + return func(value); + }; +} + +module.exports = baseUnary; + + +/***/ }), + +/***/ "../../node_modules/lodash/_cacheHas.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_cacheHas.js ***! + \**********************************************/ +/***/ ((module) => { + +/** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function cacheHas(cache, key) { + return cache.has(key); +} + +module.exports = cacheHas; + + +/***/ }), + +/***/ "../../node_modules/lodash/_cloneArrayBuffer.js": +/*!******************************************************!*\ + !*** ../../node_modules/lodash/_cloneArrayBuffer.js ***! + \******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Uint8Array = __webpack_require__(/*! ./_Uint8Array */ "../../node_modules/lodash/_Uint8Array.js"); + +/** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ +function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; +} + +module.exports = cloneArrayBuffer; + + +/***/ }), + +/***/ "../../node_modules/lodash/_cloneBuffer.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_cloneBuffer.js ***! + \*************************************************/ +/***/ ((module, exports, __webpack_require__) => { + +/* module decorator */ module = __webpack_require__.nmd(module); +var root = __webpack_require__(/*! ./_root */ "../../node_modules/lodash/_root.js"); + +/** Detect free variable `exports`. */ +var freeExports = true && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && "object" == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? root.Buffer : undefined, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined; + +/** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ +function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; +} + +module.exports = cloneBuffer; + + +/***/ }), + +/***/ "../../node_modules/lodash/_cloneDataView.js": +/*!***************************************************!*\ + !*** ../../node_modules/lodash/_cloneDataView.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var cloneArrayBuffer = __webpack_require__(/*! ./_cloneArrayBuffer */ "../../node_modules/lodash/_cloneArrayBuffer.js"); + +/** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ +function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); +} + +module.exports = cloneDataView; + + +/***/ }), + +/***/ "../../node_modules/lodash/_cloneRegExp.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_cloneRegExp.js ***! + \*************************************************/ +/***/ ((module) => { + +/** Used to match `RegExp` flags from their coerced string values. */ +var reFlags = /\w*$/; + +/** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ +function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; +} + +module.exports = cloneRegExp; + + +/***/ }), + +/***/ "../../node_modules/lodash/_cloneSymbol.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_cloneSymbol.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Symbol = __webpack_require__(/*! ./_Symbol */ "../../node_modules/lodash/_Symbol.js"); + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined; + +/** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ +function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; +} + +module.exports = cloneSymbol; + + +/***/ }), + +/***/ "../../node_modules/lodash/_cloneTypedArray.js": +/*!*****************************************************!*\ + !*** ../../node_modules/lodash/_cloneTypedArray.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var cloneArrayBuffer = __webpack_require__(/*! ./_cloneArrayBuffer */ "../../node_modules/lodash/_cloneArrayBuffer.js"); + +/** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ +function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); +} + +module.exports = cloneTypedArray; + + +/***/ }), + +/***/ "../../node_modules/lodash/_copyArray.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_copyArray.js ***! + \***********************************************/ +/***/ ((module) => { + +/** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ +function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; +} + +module.exports = copyArray; + + +/***/ }), + +/***/ "../../node_modules/lodash/_copyObject.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_copyObject.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var assignValue = __webpack_require__(/*! ./_assignValue */ "../../node_modules/lodash/_assignValue.js"), + baseAssignValue = __webpack_require__(/*! ./_baseAssignValue */ "../../node_modules/lodash/_baseAssignValue.js"); + +/** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ +function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; +} + +module.exports = copyObject; + + +/***/ }), + +/***/ "../../node_modules/lodash/_copySymbols.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_copySymbols.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var copyObject = __webpack_require__(/*! ./_copyObject */ "../../node_modules/lodash/_copyObject.js"), + getSymbols = __webpack_require__(/*! ./_getSymbols */ "../../node_modules/lodash/_getSymbols.js"); + +/** + * Copies own symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ +function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); +} + +module.exports = copySymbols; + + +/***/ }), + +/***/ "../../node_modules/lodash/_copySymbolsIn.js": +/*!***************************************************!*\ + !*** ../../node_modules/lodash/_copySymbolsIn.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var copyObject = __webpack_require__(/*! ./_copyObject */ "../../node_modules/lodash/_copyObject.js"), + getSymbolsIn = __webpack_require__(/*! ./_getSymbolsIn */ "../../node_modules/lodash/_getSymbolsIn.js"); + +/** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ +function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); +} + +module.exports = copySymbolsIn; + + +/***/ }), + +/***/ "../../node_modules/lodash/_coreJsData.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_coreJsData.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var root = __webpack_require__(/*! ./_root */ "../../node_modules/lodash/_root.js"); + +/** Used to detect overreaching core-js shims. */ +var coreJsData = root['__core-js_shared__']; + +module.exports = coreJsData; + + +/***/ }), + +/***/ "../../node_modules/lodash/_defineProperty.js": +/*!****************************************************!*\ + !*** ../../node_modules/lodash/_defineProperty.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../node_modules/lodash/_getNative.js"); + +var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} +}()); + +module.exports = defineProperty; + + +/***/ }), + +/***/ "../../node_modules/lodash/_equalArrays.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_equalArrays.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var SetCache = __webpack_require__(/*! ./_SetCache */ "../../node_modules/lodash/_SetCache.js"), + arraySome = __webpack_require__(/*! ./_arraySome */ "../../node_modules/lodash/_arraySome.js"), + cacheHas = __webpack_require__(/*! ./_cacheHas */ "../../node_modules/lodash/_cacheHas.js"); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ +function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Check that cyclic values are equal. + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; +} + +module.exports = equalArrays; + + +/***/ }), + +/***/ "../../node_modules/lodash/_equalByTag.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_equalByTag.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Symbol = __webpack_require__(/*! ./_Symbol */ "../../node_modules/lodash/_Symbol.js"), + Uint8Array = __webpack_require__(/*! ./_Uint8Array */ "../../node_modules/lodash/_Uint8Array.js"), + eq = __webpack_require__(/*! ./eq */ "../../node_modules/lodash/eq.js"), + equalArrays = __webpack_require__(/*! ./_equalArrays */ "../../node_modules/lodash/_equalArrays.js"), + mapToArray = __webpack_require__(/*! ./_mapToArray */ "../../node_modules/lodash/_mapToArray.js"), + setToArray = __webpack_require__(/*! ./_setToArray */ "../../node_modules/lodash/_setToArray.js"); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + mapTag = '[object Map]', + numberTag = '[object Number]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]'; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined; + +/** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; +} + +module.exports = equalByTag; + + +/***/ }), + +/***/ "../../node_modules/lodash/_equalObjects.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_equalObjects.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getAllKeys = __webpack_require__(/*! ./_getAllKeys */ "../../node_modules/lodash/_getAllKeys.js"); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Check that cyclic values are equal. + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; +} + +module.exports = equalObjects; + + +/***/ }), + +/***/ "../../node_modules/lodash/_freeGlobal.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_freeGlobal.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof __webpack_require__.g == 'object' && __webpack_require__.g && __webpack_require__.g.Object === Object && __webpack_require__.g; + +module.exports = freeGlobal; + + +/***/ }), + +/***/ "../../node_modules/lodash/_getAllKeys.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_getAllKeys.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseGetAllKeys = __webpack_require__(/*! ./_baseGetAllKeys */ "../../node_modules/lodash/_baseGetAllKeys.js"), + getSymbols = __webpack_require__(/*! ./_getSymbols */ "../../node_modules/lodash/_getSymbols.js"), + keys = __webpack_require__(/*! ./keys */ "../../node_modules/lodash/keys.js"); + +/** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); +} + +module.exports = getAllKeys; + + +/***/ }), + +/***/ "../../node_modules/lodash/_getAllKeysIn.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_getAllKeysIn.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseGetAllKeys = __webpack_require__(/*! ./_baseGetAllKeys */ "../../node_modules/lodash/_baseGetAllKeys.js"), + getSymbolsIn = __webpack_require__(/*! ./_getSymbolsIn */ "../../node_modules/lodash/_getSymbolsIn.js"), + keysIn = __webpack_require__(/*! ./keysIn */ "../../node_modules/lodash/keysIn.js"); + +/** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); +} + +module.exports = getAllKeysIn; + + +/***/ }), + +/***/ "../../node_modules/lodash/_getMapData.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_getMapData.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isKeyable = __webpack_require__(/*! ./_isKeyable */ "../../node_modules/lodash/_isKeyable.js"); + +/** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ +function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; +} + +module.exports = getMapData; + + +/***/ }), + +/***/ "../../node_modules/lodash/_getNative.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_getNative.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsNative = __webpack_require__(/*! ./_baseIsNative */ "../../node_modules/lodash/_baseIsNative.js"), + getValue = __webpack_require__(/*! ./_getValue */ "../../node_modules/lodash/_getValue.js"); + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; +} + +module.exports = getNative; + + +/***/ }), + +/***/ "../../node_modules/lodash/_getPrototype.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_getPrototype.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var overArg = __webpack_require__(/*! ./_overArg */ "../../node_modules/lodash/_overArg.js"); + +/** Built-in value references. */ +var getPrototype = overArg(Object.getPrototypeOf, Object); + +module.exports = getPrototype; + + +/***/ }), + +/***/ "../../node_modules/lodash/_getRawTag.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_getRawTag.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Symbol = __webpack_require__(/*! ./_Symbol */ "../../node_modules/lodash/_Symbol.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ +function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} + +module.exports = getRawTag; + + +/***/ }), + +/***/ "../../node_modules/lodash/_getSymbols.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_getSymbols.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var arrayFilter = __webpack_require__(/*! ./_arrayFilter */ "../../node_modules/lodash/_arrayFilter.js"), + stubArray = __webpack_require__(/*! ./stubArray */ "../../node_modules/lodash/stubArray.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); +}; + +module.exports = getSymbols; + + +/***/ }), + +/***/ "../../node_modules/lodash/_getSymbolsIn.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_getSymbolsIn.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var arrayPush = __webpack_require__(/*! ./_arrayPush */ "../../node_modules/lodash/_arrayPush.js"), + getPrototype = __webpack_require__(/*! ./_getPrototype */ "../../node_modules/lodash/_getPrototype.js"), + getSymbols = __webpack_require__(/*! ./_getSymbols */ "../../node_modules/lodash/_getSymbols.js"), + stubArray = __webpack_require__(/*! ./stubArray */ "../../node_modules/lodash/stubArray.js"); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; +}; + +module.exports = getSymbolsIn; + + +/***/ }), + +/***/ "../../node_modules/lodash/_getTag.js": +/*!********************************************!*\ + !*** ../../node_modules/lodash/_getTag.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var DataView = __webpack_require__(/*! ./_DataView */ "../../node_modules/lodash/_DataView.js"), + Map = __webpack_require__(/*! ./_Map */ "../../node_modules/lodash/_Map.js"), + Promise = __webpack_require__(/*! ./_Promise */ "../../node_modules/lodash/_Promise.js"), + Set = __webpack_require__(/*! ./_Set */ "../../node_modules/lodash/_Set.js"), + WeakMap = __webpack_require__(/*! ./_WeakMap */ "../../node_modules/lodash/_WeakMap.js"), + baseGetTag = __webpack_require__(/*! ./_baseGetTag */ "../../node_modules/lodash/_baseGetTag.js"), + toSource = __webpack_require__(/*! ./_toSource */ "../../node_modules/lodash/_toSource.js"); + +/** `Object#toString` result references. */ +var mapTag = '[object Map]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + setTag = '[object Set]', + weakMapTag = '[object WeakMap]'; + +var dataViewTag = '[object DataView]'; + +/** Used to detect maps, sets, and weakmaps. */ +var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + +/** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +var getTag = baseGetTag; + +// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. +if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; +} + +module.exports = getTag; + + +/***/ }), + +/***/ "../../node_modules/lodash/_getValue.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_getValue.js ***! + \**********************************************/ +/***/ ((module) => { + +/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function getValue(object, key) { + return object == null ? undefined : object[key]; +} + +module.exports = getValue; + + +/***/ }), + +/***/ "../../node_modules/lodash/_hashClear.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_hashClear.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var nativeCreate = __webpack_require__(/*! ./_nativeCreate */ "../../node_modules/lodash/_nativeCreate.js"); + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; +} + +module.exports = hashClear; + + +/***/ }), + +/***/ "../../node_modules/lodash/_hashDelete.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_hashDelete.js ***! + \************************************************/ +/***/ ((module) => { + +/** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; +} + +module.exports = hashDelete; + + +/***/ }), + +/***/ "../../node_modules/lodash/_hashGet.js": +/*!*********************************************!*\ + !*** ../../node_modules/lodash/_hashGet.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var nativeCreate = __webpack_require__(/*! ./_nativeCreate */ "../../node_modules/lodash/_nativeCreate.js"); + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; +} + +module.exports = hashGet; + + +/***/ }), + +/***/ "../../node_modules/lodash/_hashHas.js": +/*!*********************************************!*\ + !*** ../../node_modules/lodash/_hashHas.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var nativeCreate = __webpack_require__(/*! ./_nativeCreate */ "../../node_modules/lodash/_nativeCreate.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); +} + +module.exports = hashHas; + + +/***/ }), + +/***/ "../../node_modules/lodash/_hashSet.js": +/*!*********************************************!*\ + !*** ../../node_modules/lodash/_hashSet.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var nativeCreate = __webpack_require__(/*! ./_nativeCreate */ "../../node_modules/lodash/_nativeCreate.js"); + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ +function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; +} + +module.exports = hashSet; + + +/***/ }), + +/***/ "../../node_modules/lodash/_initCloneArray.js": +/*!****************************************************!*\ + !*** ../../node_modules/lodash/_initCloneArray.js ***! + \****************************************************/ +/***/ ((module) => { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ +function initCloneArray(array) { + var length = array.length, + result = new array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; +} + +module.exports = initCloneArray; + + +/***/ }), + +/***/ "../../node_modules/lodash/_initCloneByTag.js": +/*!****************************************************!*\ + !*** ../../node_modules/lodash/_initCloneByTag.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var cloneArrayBuffer = __webpack_require__(/*! ./_cloneArrayBuffer */ "../../node_modules/lodash/_cloneArrayBuffer.js"), + cloneDataView = __webpack_require__(/*! ./_cloneDataView */ "../../node_modules/lodash/_cloneDataView.js"), + cloneRegExp = __webpack_require__(/*! ./_cloneRegExp */ "../../node_modules/lodash/_cloneRegExp.js"), + cloneSymbol = __webpack_require__(/*! ./_cloneSymbol */ "../../node_modules/lodash/_cloneSymbol.js"), + cloneTypedArray = __webpack_require__(/*! ./_cloneTypedArray */ "../../node_modules/lodash/_cloneTypedArray.js"); + +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]', + dateTag = '[object Date]', + mapTag = '[object Map]', + numberTag = '[object Number]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return new Ctor; + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return new Ctor; + + case symbolTag: + return cloneSymbol(object); + } +} + +module.exports = initCloneByTag; + + +/***/ }), + +/***/ "../../node_modules/lodash/_initCloneObject.js": +/*!*****************************************************!*\ + !*** ../../node_modules/lodash/_initCloneObject.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseCreate = __webpack_require__(/*! ./_baseCreate */ "../../node_modules/lodash/_baseCreate.js"), + getPrototype = __webpack_require__(/*! ./_getPrototype */ "../../node_modules/lodash/_getPrototype.js"), + isPrototype = __webpack_require__(/*! ./_isPrototype */ "../../node_modules/lodash/_isPrototype.js"); + +/** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; +} + +module.exports = initCloneObject; + + +/***/ }), + +/***/ "../../node_modules/lodash/_isIndex.js": +/*!*********************************************!*\ + !*** ../../node_modules/lodash/_isIndex.js ***! + \*********************************************/ +/***/ ((module) => { + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?:0|[1-9]\d*)$/; + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); +} + +module.exports = isIndex; + + +/***/ }), + +/***/ "../../node_modules/lodash/_isKeyable.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/_isKeyable.js ***! + \***********************************************/ +/***/ ((module) => { + +/** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ +function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); +} + +module.exports = isKeyable; + + +/***/ }), + +/***/ "../../node_modules/lodash/_isMasked.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_isMasked.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var coreJsData = __webpack_require__(/*! ./_coreJsData */ "../../node_modules/lodash/_coreJsData.js"); + +/** Used to detect methods masquerading as native. */ +var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; +}()); + +/** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ +function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); +} + +module.exports = isMasked; + + +/***/ }), + +/***/ "../../node_modules/lodash/_isPrototype.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_isPrototype.js ***! + \*************************************************/ +/***/ ((module) => { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ +function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; +} + +module.exports = isPrototype; + + +/***/ }), + +/***/ "../../node_modules/lodash/_listCacheClear.js": +/*!****************************************************!*\ + !*** ../../node_modules/lodash/_listCacheClear.js ***! + \****************************************************/ +/***/ ((module) => { + +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear() { + this.__data__ = []; + this.size = 0; +} + +module.exports = listCacheClear; + + +/***/ }), + +/***/ "../../node_modules/lodash/_listCacheDelete.js": +/*!*****************************************************!*\ + !*** ../../node_modules/lodash/_listCacheDelete.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var assocIndexOf = __webpack_require__(/*! ./_assocIndexOf */ "../../node_modules/lodash/_assocIndexOf.js"); + +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; + +/** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; +} + +module.exports = listCacheDelete; + + +/***/ }), + +/***/ "../../node_modules/lodash/_listCacheGet.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_listCacheGet.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var assocIndexOf = __webpack_require__(/*! ./_assocIndexOf */ "../../node_modules/lodash/_assocIndexOf.js"); + +/** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; +} + +module.exports = listCacheGet; + + +/***/ }), + +/***/ "../../node_modules/lodash/_listCacheHas.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_listCacheHas.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var assocIndexOf = __webpack_require__(/*! ./_assocIndexOf */ "../../node_modules/lodash/_assocIndexOf.js"); + +/** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; +} + +module.exports = listCacheHas; + + +/***/ }), + +/***/ "../../node_modules/lodash/_listCacheSet.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_listCacheSet.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var assocIndexOf = __webpack_require__(/*! ./_assocIndexOf */ "../../node_modules/lodash/_assocIndexOf.js"); + +/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ +function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} + +module.exports = listCacheSet; + + +/***/ }), + +/***/ "../../node_modules/lodash/_mapCacheClear.js": +/*!***************************************************!*\ + !*** ../../node_modules/lodash/_mapCacheClear.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Hash = __webpack_require__(/*! ./_Hash */ "../../node_modules/lodash/_Hash.js"), + ListCache = __webpack_require__(/*! ./_ListCache */ "../../node_modules/lodash/_ListCache.js"), + Map = __webpack_require__(/*! ./_Map */ "../../node_modules/lodash/_Map.js"); + +/** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; +} + +module.exports = mapCacheClear; + + +/***/ }), + +/***/ "../../node_modules/lodash/_mapCacheDelete.js": +/*!****************************************************!*\ + !*** ../../node_modules/lodash/_mapCacheDelete.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getMapData = __webpack_require__(/*! ./_getMapData */ "../../node_modules/lodash/_getMapData.js"); + +/** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; +} + +module.exports = mapCacheDelete; + + +/***/ }), + +/***/ "../../node_modules/lodash/_mapCacheGet.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_mapCacheGet.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getMapData = __webpack_require__(/*! ./_getMapData */ "../../node_modules/lodash/_getMapData.js"); + +/** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function mapCacheGet(key) { + return getMapData(this, key).get(key); +} + +module.exports = mapCacheGet; + + +/***/ }), + +/***/ "../../node_modules/lodash/_mapCacheHas.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_mapCacheHas.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getMapData = __webpack_require__(/*! ./_getMapData */ "../../node_modules/lodash/_getMapData.js"); + +/** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function mapCacheHas(key) { + return getMapData(this, key).has(key); +} + +module.exports = mapCacheHas; + + +/***/ }), + +/***/ "../../node_modules/lodash/_mapCacheSet.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_mapCacheSet.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getMapData = __webpack_require__(/*! ./_getMapData */ "../../node_modules/lodash/_getMapData.js"); + +/** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ +function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; +} + +module.exports = mapCacheSet; + + +/***/ }), + +/***/ "../../node_modules/lodash/_mapToArray.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_mapToArray.js ***! + \************************************************/ +/***/ ((module) => { + +/** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ +function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} + +module.exports = mapToArray; + + +/***/ }), + +/***/ "../../node_modules/lodash/_nativeCreate.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_nativeCreate.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../node_modules/lodash/_getNative.js"); + +/* Built-in method references that are verified to be native. */ +var nativeCreate = getNative(Object, 'create'); + +module.exports = nativeCreate; + + +/***/ }), + +/***/ "../../node_modules/lodash/_nativeKeys.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_nativeKeys.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var overArg = __webpack_require__(/*! ./_overArg */ "../../node_modules/lodash/_overArg.js"); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeKeys = overArg(Object.keys, Object); + +module.exports = nativeKeys; + + +/***/ }), + +/***/ "../../node_modules/lodash/_nativeKeysIn.js": +/*!**************************************************!*\ + !*** ../../node_modules/lodash/_nativeKeysIn.js ***! + \**************************************************/ +/***/ ((module) => { + +/** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; +} + +module.exports = nativeKeysIn; + + +/***/ }), + +/***/ "../../node_modules/lodash/_nodeUtil.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_nodeUtil.js ***! + \**********************************************/ +/***/ ((module, exports, __webpack_require__) => { + +/* module decorator */ module = __webpack_require__.nmd(module); +var freeGlobal = __webpack_require__(/*! ./_freeGlobal */ "../../node_modules/lodash/_freeGlobal.js"); + +/** Detect free variable `exports`. */ +var freeExports = true && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && "object" == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Detect free variable `process` from Node.js. */ +var freeProcess = moduleExports && freeGlobal.process; + +/** Used to access faster Node.js helpers. */ +var nodeUtil = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule && freeModule.require && freeModule.require('util').types; + + if (types) { + return types; + } + + // Legacy `process.binding('util')` for Node.js < 10. + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} +}()); + +module.exports = nodeUtil; + + +/***/ }), + +/***/ "../../node_modules/lodash/_objectToString.js": +/*!****************************************************!*\ + !*** ../../node_modules/lodash/_objectToString.js ***! + \****************************************************/ +/***/ ((module) => { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ +function objectToString(value) { + return nativeObjectToString.call(value); +} + +module.exports = objectToString; + + +/***/ }), + +/***/ "../../node_modules/lodash/_overArg.js": +/*!*********************************************!*\ + !*** ../../node_modules/lodash/_overArg.js ***! + \*********************************************/ +/***/ ((module) => { + +/** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} + +module.exports = overArg; + + +/***/ }), + +/***/ "../../node_modules/lodash/_root.js": +/*!******************************************!*\ + !*** ../../node_modules/lodash/_root.js ***! + \******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var freeGlobal = __webpack_require__(/*! ./_freeGlobal */ "../../node_modules/lodash/_freeGlobal.js"); + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +module.exports = root; + + +/***/ }), + +/***/ "../../node_modules/lodash/_setCacheAdd.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_setCacheAdd.js ***! + \*************************************************/ +/***/ ((module) => { + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ +function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; +} + +module.exports = setCacheAdd; + + +/***/ }), + +/***/ "../../node_modules/lodash/_setCacheHas.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_setCacheHas.js ***! + \*************************************************/ +/***/ ((module) => { + +/** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ +function setCacheHas(value) { + return this.__data__.has(value); +} + +module.exports = setCacheHas; + + +/***/ }), + +/***/ "../../node_modules/lodash/_setToArray.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_setToArray.js ***! + \************************************************/ +/***/ ((module) => { + +/** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ +function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; +} + +module.exports = setToArray; + + +/***/ }), + +/***/ "../../node_modules/lodash/_stackClear.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/_stackClear.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var ListCache = __webpack_require__(/*! ./_ListCache */ "../../node_modules/lodash/_ListCache.js"); + +/** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ +function stackClear() { + this.__data__ = new ListCache; + this.size = 0; +} + +module.exports = stackClear; + + +/***/ }), + +/***/ "../../node_modules/lodash/_stackDelete.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/_stackDelete.js ***! + \*************************************************/ +/***/ ((module) => { + +/** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; +} + +module.exports = stackDelete; + + +/***/ }), + +/***/ "../../node_modules/lodash/_stackGet.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_stackGet.js ***! + \**********************************************/ +/***/ ((module) => { + +/** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function stackGet(key) { + return this.__data__.get(key); +} + +module.exports = stackGet; + + +/***/ }), + +/***/ "../../node_modules/lodash/_stackHas.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_stackHas.js ***! + \**********************************************/ +/***/ ((module) => { + +/** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function stackHas(key) { + return this.__data__.has(key); +} + +module.exports = stackHas; + + +/***/ }), + +/***/ "../../node_modules/lodash/_stackSet.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_stackSet.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var ListCache = __webpack_require__(/*! ./_ListCache */ "../../node_modules/lodash/_ListCache.js"), + Map = __webpack_require__(/*! ./_Map */ "../../node_modules/lodash/_Map.js"), + MapCache = __webpack_require__(/*! ./_MapCache */ "../../node_modules/lodash/_MapCache.js"); + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ +function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; +} + +module.exports = stackSet; + + +/***/ }), + +/***/ "../../node_modules/lodash/_toSource.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/_toSource.js ***! + \**********************************************/ +/***/ ((module) => { + +/** Used for built-in method references. */ +var funcProto = Function.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ +function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; +} + +module.exports = toSource; + + +/***/ }), + +/***/ "../../node_modules/lodash/cloneDeep.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/cloneDeep.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseClone = __webpack_require__(/*! ./_baseClone */ "../../node_modules/lodash/_baseClone.js"); + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG = 1, + CLONE_SYMBOLS_FLAG = 4; + +/** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @see _.clone + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ +function cloneDeep(value) { + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); +} + +module.exports = cloneDeep; + + +/***/ }), + +/***/ "../../node_modules/lodash/eq.js": +/*!***************************************!*\ + !*** ../../node_modules/lodash/eq.js ***! + \***************************************/ +/***/ ((module) => { + +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +module.exports = eq; + + +/***/ }), + +/***/ "../../node_modules/lodash/isArguments.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/isArguments.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsArguments = __webpack_require__(/*! ./_baseIsArguments */ "../../node_modules/lodash/_baseIsArguments.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../node_modules/lodash/isObjectLike.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); +}; + +module.exports = isArguments; + + +/***/ }), + +/***/ "../../node_modules/lodash/isArray.js": +/*!********************************************!*\ + !*** ../../node_modules/lodash/isArray.js ***! + \********************************************/ +/***/ ((module) => { + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +module.exports = isArray; + + +/***/ }), + +/***/ "../../node_modules/lodash/isArrayLike.js": +/*!************************************************!*\ + !*** ../../node_modules/lodash/isArrayLike.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isFunction = __webpack_require__(/*! ./isFunction */ "../../node_modules/lodash/isFunction.js"), + isLength = __webpack_require__(/*! ./isLength */ "../../node_modules/lodash/isLength.js"); + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +module.exports = isArrayLike; + + +/***/ }), + +/***/ "../../node_modules/lodash/isBuffer.js": +/*!*********************************************!*\ + !*** ../../node_modules/lodash/isBuffer.js ***! + \*********************************************/ +/***/ ((module, exports, __webpack_require__) => { + +/* module decorator */ module = __webpack_require__.nmd(module); +var root = __webpack_require__(/*! ./_root */ "../../node_modules/lodash/_root.js"), + stubFalse = __webpack_require__(/*! ./stubFalse */ "../../node_modules/lodash/stubFalse.js"); + +/** Detect free variable `exports`. */ +var freeExports = true && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && "object" == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? root.Buffer : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; + +/** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ +var isBuffer = nativeIsBuffer || stubFalse; + +module.exports = isBuffer; + + +/***/ }), + +/***/ "../../node_modules/lodash/isEqual.js": +/*!********************************************!*\ + !*** ../../node_modules/lodash/isEqual.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsEqual = __webpack_require__(/*! ./_baseIsEqual */ "../../node_modules/lodash/_baseIsEqual.js"); + +/** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ +function isEqual(value, other) { + return baseIsEqual(value, other); +} + +module.exports = isEqual; + + +/***/ }), + +/***/ "../../node_modules/lodash/isFunction.js": +/*!***********************************************!*\ + !*** ../../node_modules/lodash/isFunction.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseGetTag = __webpack_require__(/*! ./_baseGetTag */ "../../node_modules/lodash/_baseGetTag.js"), + isObject = __webpack_require__(/*! ./isObject */ "../../node_modules/lodash/isObject.js"); + +/** `Object#toString` result references. */ +var asyncTag = '[object AsyncFunction]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[object Proxy]'; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; +} + +module.exports = isFunction; + + +/***/ }), + +/***/ "../../node_modules/lodash/isLength.js": +/*!*********************************************!*\ + !*** ../../node_modules/lodash/isLength.js ***! + \*********************************************/ +/***/ ((module) => { + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +module.exports = isLength; + + +/***/ }), + +/***/ "../../node_modules/lodash/isMap.js": +/*!******************************************!*\ + !*** ../../node_modules/lodash/isMap.js ***! + \******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsMap = __webpack_require__(/*! ./_baseIsMap */ "../../node_modules/lodash/_baseIsMap.js"), + baseUnary = __webpack_require__(/*! ./_baseUnary */ "../../node_modules/lodash/_baseUnary.js"), + nodeUtil = __webpack_require__(/*! ./_nodeUtil */ "../../node_modules/lodash/_nodeUtil.js"); + +/* Node.js helper references. */ +var nodeIsMap = nodeUtil && nodeUtil.isMap; + +/** + * Checks if `value` is classified as a `Map` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + * @example + * + * _.isMap(new Map); + * // => true + * + * _.isMap(new WeakMap); + * // => false + */ +var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + +module.exports = isMap; + + +/***/ }), + +/***/ "../../node_modules/lodash/isObject.js": +/*!*********************************************!*\ + !*** ../../node_modules/lodash/isObject.js ***! + \*********************************************/ +/***/ ((module) => { + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +module.exports = isObject; + + +/***/ }), + +/***/ "../../node_modules/lodash/isObjectLike.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/isObjectLike.js ***! + \*************************************************/ +/***/ ((module) => { + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +module.exports = isObjectLike; + + +/***/ }), + +/***/ "../../node_modules/lodash/isSet.js": +/*!******************************************!*\ + !*** ../../node_modules/lodash/isSet.js ***! + \******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsSet = __webpack_require__(/*! ./_baseIsSet */ "../../node_modules/lodash/_baseIsSet.js"), + baseUnary = __webpack_require__(/*! ./_baseUnary */ "../../node_modules/lodash/_baseUnary.js"), + nodeUtil = __webpack_require__(/*! ./_nodeUtil */ "../../node_modules/lodash/_nodeUtil.js"); + +/* Node.js helper references. */ +var nodeIsSet = nodeUtil && nodeUtil.isSet; + +/** + * Checks if `value` is classified as a `Set` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + * @example + * + * _.isSet(new Set); + * // => true + * + * _.isSet(new WeakSet); + * // => false + */ +var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + +module.exports = isSet; + + +/***/ }), + +/***/ "../../node_modules/lodash/isTypedArray.js": +/*!*************************************************!*\ + !*** ../../node_modules/lodash/isTypedArray.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsTypedArray = __webpack_require__(/*! ./_baseIsTypedArray */ "../../node_modules/lodash/_baseIsTypedArray.js"), + baseUnary = __webpack_require__(/*! ./_baseUnary */ "../../node_modules/lodash/_baseUnary.js"), + nodeUtil = __webpack_require__(/*! ./_nodeUtil */ "../../node_modules/lodash/_nodeUtil.js"); + +/* Node.js helper references. */ +var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + +/** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ +var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + +module.exports = isTypedArray; + + +/***/ }), + +/***/ "../../node_modules/lodash/keys.js": +/*!*****************************************!*\ + !*** ../../node_modules/lodash/keys.js ***! + \*****************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var arrayLikeKeys = __webpack_require__(/*! ./_arrayLikeKeys */ "../../node_modules/lodash/_arrayLikeKeys.js"), + baseKeys = __webpack_require__(/*! ./_baseKeys */ "../../node_modules/lodash/_baseKeys.js"), + isArrayLike = __webpack_require__(/*! ./isArrayLike */ "../../node_modules/lodash/isArrayLike.js"); + +/** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ +function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); +} + +module.exports = keys; + + +/***/ }), + +/***/ "../../node_modules/lodash/keysIn.js": +/*!*******************************************!*\ + !*** ../../node_modules/lodash/keysIn.js ***! + \*******************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var arrayLikeKeys = __webpack_require__(/*! ./_arrayLikeKeys */ "../../node_modules/lodash/_arrayLikeKeys.js"), + baseKeysIn = __webpack_require__(/*! ./_baseKeysIn */ "../../node_modules/lodash/_baseKeysIn.js"), + isArrayLike = __webpack_require__(/*! ./isArrayLike */ "../../node_modules/lodash/isArrayLike.js"); + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); +} + +module.exports = keysIn; + + +/***/ }), + +/***/ "../../node_modules/lodash/stubArray.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/stubArray.js ***! + \**********************************************/ +/***/ ((module) => { + +/** + * This method returns a new empty array. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Array} Returns the new empty array. + * @example + * + * var arrays = _.times(2, _.stubArray); + * + * console.log(arrays); + * // => [[], []] + * + * console.log(arrays[0] === arrays[1]); + * // => false + */ +function stubArray() { + return []; +} + +module.exports = stubArray; + + +/***/ }), + +/***/ "../../node_modules/lodash/stubFalse.js": +/*!**********************************************!*\ + !*** ../../node_modules/lodash/stubFalse.js ***! + \**********************************************/ +/***/ ((module) => { + +/** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */ +function stubFalse() { + return false; +} + +module.exports = stubFalse; + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ id: moduleId, +/******/ loaded: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/node module decorator */ +/******/ (() => { +/******/ __webpack_require__.nmd = (module) => { +/******/ module.paths = []; +/******/ if (!module.children) module.children = []; +/******/ return module; +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be in strict mode. +(() => { +"use strict"; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _openfin_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @openfin/core */ "../../node_modules/@openfin/core/out/mock.js"); + +let fileName; +let debugLogStr; +let debugLogFile; +document.addEventListener("DOMContentLoaded", async () => { + try { + await initDom(); + } + catch (error) { + console.error(error); + } +}); +/** + * Populates DOM with the UI elements and adds listeners obtaining selected/submitted options. + */ +async function initDom() { + const logListElement = document.querySelector("#log-list"); + if (logListElement) { + await createLogDropDown(logListElement); + logListElement.addEventListener("change", async (selectionChangeEvent) => { + fileName = selectionChangeEvent.target.value; + }); + } + const upload = document.querySelector("#upload-form"); + if (upload) { + upload.addEventListener("submit", uploadHandler); + } + const sendAppLogBtn = document.querySelector("#send-app-log"); + if (sendAppLogBtn) { + sendAppLogBtn.addEventListener("click", sendApplicationLogs); + } +} +/** + * Handle uploads. + * 1. Creates a FormData object. + * 2. Creates a File object from the string of the Runtime debug log file contents. + * 3. Populates the FormData object with necessary parameters to be read by the server. + * 4. Uploads the created runtime debug log file to a server endpoint. + * @param submitEvent The event to handle. + */ +async function uploadHandler(submitEvent) { + submitEvent.preventDefault(); + if (!fileName) { + fileName = "debug.log"; + } + const formData = new FormData(); + debugLogStr = await getLogFromName(fileName); + debugLogFile = new File([debugLogStr], fileName, { type: "text/plain" }); + formData.append("file", debugLogFile); + formData.append("filename", fileName); + formData.append("uuid", _openfin_core__WEBPACK_IMPORTED_MODULE_0__.fin.me.uuid); + const uploadState = await fetch("https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-logging-apis/uploads", { + method: "POST", + body: formData + }); + const uploadStateJson = await uploadState.json(); + const uploadStateJsonString = JSON.stringify(uploadStateJson, null, 5); + const logs = `${new Date().toLocaleTimeString()}: ${uploadStateJsonString}\n`; + const logPreview = document.querySelector("#preview"); + if (logPreview) { + logPreview.textContent += logs; + } +} +/** + * Sends a message to the OpenFin RVM to send the application logs. + */ +async function sendApplicationLogs() { + try { + const appLogResponse = await _openfin_core__WEBPACK_IMPORTED_MODULE_0__.fin.Application.getCurrentSync().sendApplicationLog(); + console.log(`Log ID: ${appLogResponse.logId}`); + } + catch { + // swallow unnecessary errors. + } +} +/** + * Retrieves the runtime debug log from a filename. + * @param name file name of the runtime debug log to retrieve. + * @returns the log content. + */ +async function getLogFromName(name) { + const log = await _openfin_core__WEBPACK_IMPORTED_MODULE_0__.fin.System.getLog({ name }); + return log; +} +/** + * Creates an HTMLOptionElement for each of the Runtime debug logs. + * @param parentElement HTML Element to append the log filename HTMLOptionElement to. + */ +async function createLogDropDown(parentElement) { + const logList = await _openfin_core__WEBPACK_IMPORTED_MODULE_0__.fin.System.getLogList(); + for (const log of logList) { + const logElement = document.createElement("option"); + logElement.id = log.date; + logElement.textContent = log.name; + logElement.value = log.name; + parentElement.append(logElement); + } +} + +})(); + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQWE7O0FBRWIsOENBQTZDLEVBQUUsYUFBYSxFQUFDOztBQUU3RCxpQkFBaUIsbUJBQU8sQ0FBQyxtREFBUTtBQUNqQyxtQkFBbUIsbUJBQU8sQ0FBQyxnRUFBa0I7QUFDN0MsaUJBQWlCLG1CQUFPLENBQUMsNERBQWdCOztBQUV6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QixLQUFLO0FBQ0w7QUFDQSxHQUFHO0FBQ0gsRUFBRTtBQUNGO0FBQ0E7O0FBRUEsc0hBQXNILHFCQUFNLG1CQUFtQixxQkFBTTs7QUFFcko7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0EsbURBQW1ELDBCQUEwQjtBQUM3RSwyQkFBMkIsc0JBQXNCLHFCQUFxQixtQkFBbUI7QUFDekY7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQsY0FBYztBQUN6RTtBQUNBO0FBQ0EsVUFBVSw4QkFBOEIsS0FBSywwQkFBMEIsb0JBQW9CLDRCQUE0QjtBQUN2SCxJQUFJLDBCQUEwQixnRkFBZ0Ysb0NBQW9DO0FBQ2xKO0FBQ0EsSUFBSSwwREFBMEQsMkNBQTJDO0FBQ3pHLE9BQU8sb0NBQW9DLGlCQUFpQixtQ0FBbUM7QUFDL0YsSUFBSTtBQUNKO0FBQ0E7QUFDQSw2QkFBNkIsd0JBQXdCO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRCxhQUFhOztBQUVsRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGFBQWE7O0FBRTNEOztBQUVBO0FBQ0EsdURBQXVELGtDQUFrQztBQUN6RjtBQUNBO0FBQ0E7QUFDQSwyREFBMkQsY0FBYztBQUN6RTtBQUNBLHlFQUF5RSxvREFBb0Q7QUFDN0g7QUFDQTtBQUNBO0FBQ0EsNkRBQTZELGFBQWE7O0FBRTFFOztBQUVBLCtDQUErQyxhQUFhOztBQUU1RDs7QUFFQTtBQUNBO0FBQ0Esb0RBQW9ELGdDQUFnQztBQUNwRjtBQUNBO0FBQ0E7QUFDQSwyREFBMkQsY0FBYztBQUN6RTtBQUNBLGtFQUFrRSxtREFBbUQ7QUFDckg7QUFDQTtBQUNBO0FBQ0Esc0RBQXNELGFBQWE7O0FBRW5FOztBQUVBO0FBQ0E7QUFDQSwrQ0FBK0MsdUJBQXVCO0FBQ3RFO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCxjQUFjO0FBQ3pFO0FBQ0EscURBQXFELDJCQUEyQjtBQUNoRixpQ0FBaUMsb0RBQW9EO0FBQ3JGO0FBQ0EsSUFBSSw4QkFBOEI7QUFDbEM7QUFDQTtBQUNBO0FBQ0Esa0RBQWtELGFBQWE7O0FBRS9EOztBQUVBO0FBQ0EseURBQXlELG9CQUFvQjtBQUM3RSx1QkFBdUIsMEJBQTBCLEdBQUcscUJBQXFCLE9BQU8sb0JBQW9CO0FBQ3BHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkRBQTJELGNBQWM7QUFDekU7QUFDQTtBQUNBLFVBQVUsdUNBQXVDLEdBQUcsNkJBQTZCLE9BQU8sMEJBQTBCO0FBQ2xILElBQUksZ0NBQWdDLEdBQUcsMkJBQTJCLE9BQU8sMEJBQTBCO0FBQ25HLHVCQUF1QiwwQkFBMEI7QUFDakQ7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdELGFBQWE7O0FBRTdEOztBQUVBO0FBQ0Esa0RBQWtELG1CQUFtQjtBQUNyRTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQsY0FBYztBQUN6RTtBQUNBO0FBQ0EsVUFBVSxxQkFBcUIsR0FBRyxtQkFBbUIsa0JBQWtCLGdDQUFnQztBQUN2RyxvREFBb0Qsc0JBQXNCO0FBQzFFO0FBQ0EsMENBQTBDLGtDQUFrQyxHQUFHLDRDQUE0QztBQUMzSCxRQUFRLG1DQUFtQztBQUMzQztBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsYUFBYTs7QUFFM0Q7O0FBRUE7QUFDQSwwRUFBMEUscUJBQXFCO0FBQy9GLElBQUksbUJBQW1CO0FBQ3ZCO0FBQ0E7QUFDQSxrR0FBa0csMEJBQTBCO0FBQzVIO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRCxhQUFhOztBQUVoRTs7QUFFQTtBQUNBLGtEQUFrRCxxQkFBcUI7QUFDdkU7QUFDQTtBQUNBO0FBQ0EsMkRBQTJELGNBQWM7QUFDekU7QUFDQTtBQUNBLFVBQVUscUJBQXFCLEdBQUcsbUJBQW1CLGtCQUFrQixnQ0FBZ0M7QUFDdkcseUNBQXlDLHlCQUF5QjtBQUNsRSxJQUFJO0FBQ0o7QUFDQSxJQUFJLHFFQUFxRTtBQUN6RSxJQUFJLDhCQUE4Qiw2QkFBNkIsNkNBQTZDO0FBQzVHLElBQUksbUNBQW1DO0FBQ3ZDO0FBQ0EsNkJBQTZCLHlCQUF5QixxQ0FBcUM7QUFDM0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0QsYUFBYTs7QUFFN0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU0sMEJBQTBCLEdBQUc7QUFDbkMsTUFBTSxrQ0FBa0MsR0FBRztBQUMzQyxNQUFNLG9CQUFvQixHQUFHO0FBQzdCLE1BQU0sMkJBQTJCLEdBQUc7QUFDcEMsTUFBTSx1QkFBdUIsR0FBRztBQUNoQyxNQUFNLHFCQUFxQixHQUFHO0FBQzlCLE1BQU0sbUJBQW1CLEdBQUc7QUFDNUIsTUFBTSxxQkFBcUIsR0FBRztBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsMkJBQTJCO0FBQ3JDLE1BQU0sK0JBQStCLHVDQUF1QywyQkFBMkI7QUFDdkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsb0NBQW9DO0FBQ25EO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBLDBDQUEwQyw0QkFBNEI7QUFDdEUsQ0FBQztBQUNEO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLGFBQWE7QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaURBQWlELGFBQWE7QUFDOUQsa0ZBQWtGLHdCQUF3QjtBQUMxRywrREFBK0Qsa0JBQWtCO0FBQ2pGLDhDQUE4Qyx5QkFBeUI7QUFDdkUsc0RBQXNELHlCQUF5QixLQUFLLHVCQUF1QjtBQUMzRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixvQ0FBb0M7QUFDcEQ7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBLGdEQUFnRCxhQUFhO0FBQzdEO0FBQ0E7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUEsZ0RBQWdELGFBQWE7QUFDN0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0Q0FBNEMsYUFBYTtBQUN6RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLG9CQUFvQixJQUFJLHFCQUFxQjtBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtRUFBbUU7QUFDbkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxRUFBcUU7QUFDckU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxzQkFBc0I7QUFDNUU7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxzQkFBc0I7QUFDNUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxzQkFBc0I7QUFDNUU7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0RBQXNELHNCQUFzQjtBQUM1RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRCQUE0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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEVBQThFLFNBQVM7QUFDdkY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLFNBQVM7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVEQUF1RCx5QkFBeUI7QUFDaEY7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvRkFBb0YsU0FBUztBQUM3RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUIsVUFBVTtBQUMzQjtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIsMENBQTBDO0FBQ25FO0FBQ0E7QUFDQSwrQ0FBK0M7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5Qix5Q0FBeUM7QUFDbEU7QUFDQTtBQUNBLCtDQUErQztBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrRUFBK0UsU0FBUztBQUN4RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtGQUFrRixTQUFTO0FBQzNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0ZBQWdGLFNBQVM7QUFDekY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdELFdBQVc7QUFDM0Q7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyxXQUFXO0FBQ3JEO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxpQ0FBaUM7QUFDMUU7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlGQUFpRixTQUFTO0FBQzFGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtFQUFrRSxTQUFTO0FBQzNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0VBQWdFLFNBQVM7QUFDekU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDREQUE0RCxTQUFTO0FBQ3JFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQsU0FBUztBQUN2RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCxTQUFTO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQSxRQUFRO0FBQ1I7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxnQkFBZ0I7QUFDdEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrREFBK0QsS0FBSztBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLDRFQUE0RTtBQUNwRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQSw4RUFBOEUsU0FBUztBQUN2RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLFdBQVcsU0FBUztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQsa0NBQWtDO0FBQzlGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLFVBQVU7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLFVBQVU7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEsa0RBQWtELGFBQWE7QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQSwrQ0FBK0MsYUFBYTtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQsTUFBTTtBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0EsK0VBQStFLGtDQUFrQztBQUNqSDtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1osUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRCwwQkFBMEIsaURBQWlELE9BQU87QUFDckk7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRCwwQkFBMEIsaURBQWlELE9BQU87QUFDdkk7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSx1REFBdUQsYUFBYTtBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJGQUEyRiwyQ0FBMkM7QUFDdEk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJGQUEyRiwyQ0FBMkM7QUFDdEk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGdEQUFnRCxhQUFhO0FBQzdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QztBQUM3QztBQUNBO0FBQ0EseURBQXlELGFBQWE7QUFDdEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0MsK0NBQStDO0FBQ3ZGO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEMseUJBQXlCO0FBQ3pCO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxtSUFBbUkseUJBQXlCO0FBQzVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0VBQStFO0FBQy9FO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFJQUFxSSx5QkFBeUI7QUFDOUo7QUFDQSxnQkFBZ0IsV0FBVztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7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O0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLG9CQUFvQixTQUFTO0FBQzdCO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7O0FBRUEsa0NBQWtDLFFBQVE7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7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ekIsVUFBVSxDQUFDLFdBQVcsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ2xDLFVBQVUsQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQztRQUM1QixhQUFhLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ2xDLENBQUM7QUFDRixDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvQG9wZW5maW4vY29yZS9vdXQvbW9jay5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9ldmVudHMvZXZlbnRzLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fRGF0YVZpZXcuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19IYXNoLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fTGlzdENhY2hlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fTWFwLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fTWFwQ2FjaGUuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19Qcm9taXNlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fU2V0LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fU2V0Q2FjaGUuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19TdGFjay5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX1N5bWJvbC5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX1VpbnQ4QXJyYXkuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19XZWFrTWFwLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYXJyYXlFYWNoLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYXJyYXlGaWx0ZXIuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19hcnJheUxpa2VLZXlzLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYXJyYXlQdXNoLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYXJyYXlTb21lLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYXNzaWduVmFsdWUuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19hc3NvY0luZGV4T2YuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19iYXNlQXNzaWduLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUFzc2lnbkluLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUFzc2lnblZhbHVlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUNsb25lLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUNyZWF0ZS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Jhc2VHZXRBbGxLZXlzLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUdldFRhZy5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Jhc2VJc0FyZ3VtZW50cy5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Jhc2VJc0VxdWFsLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUlzRXF1YWxEZWVwLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUlzTWFwLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUlzTmF0aXZlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUlzU2V0LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUlzVHlwZWRBcnJheS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Jhc2VLZXlzLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUtleXNJbi5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Jhc2VUaW1lcy5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Jhc2VVbmFyeS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2NhY2hlSGFzLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fY2xvbmVBcnJheUJ1ZmZlci5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Nsb25lQnVmZmVyLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fY2xvbmVEYXRhVmlldy5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Nsb25lUmVnRXhwLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fY2xvbmVTeW1ib2wuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19jbG9uZVR5cGVkQXJyYXkuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19jb3B5QXJyYXkuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19jb3B5T2JqZWN0LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fY29weVN5bWJvbHMuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19jb3B5U3ltYm9sc0luLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fY29yZUpzRGF0YS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2RlZmluZVByb3BlcnR5LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZXF1YWxBcnJheXMuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19lcXVhbEJ5VGFnLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZXF1YWxPYmplY3RzLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZnJlZUdsb2JhbC5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2dldEFsbEtleXMuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19nZXRBbGxLZXlzSW4uanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19nZXRNYXBEYXRhLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZ2V0TmF0aXZlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZ2V0UHJvdG90eXBlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZ2V0UmF3VGFnLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZ2V0U3ltYm9scy5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2dldFN5bWJvbHNJbi5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2dldFRhZy5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2dldFZhbHVlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faGFzaENsZWFyLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faGFzaERlbGV0ZS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2hhc2hHZXQuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19oYXNoSGFzLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faGFzaFNldC5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2luaXRDbG9uZUFycmF5LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faW5pdENsb25lQnlUYWcuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19pbml0Q2xvbmVPYmplY3QuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19pc0luZGV4LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faXNLZXlhYmxlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faXNNYXNrZWQuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19pc1Byb3RvdHlwZS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2xpc3RDYWNoZUNsZWFyLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fbGlzdENhY2hlRGVsZXRlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fbGlzdENhY2hlR2V0LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fbGlzdENhY2hlSGFzLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fbGlzdENhY2hlU2V0LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fbWFwQ2FjaGVDbGVhci5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX21hcENhY2hlRGVsZXRlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fbWFwQ2FjaGVHZXQuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19tYXBDYWNoZUhhcy5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX21hcENhY2hlU2V0LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fbWFwVG9BcnJheS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX25hdGl2ZUNyZWF0ZS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX25hdGl2ZUtleXMuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19uYXRpdmVLZXlzSW4uanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19ub2RlVXRpbC5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX29iamVjdFRvU3RyaW5nLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fb3ZlckFyZy5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX3Jvb3QuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19zZXRDYWNoZUFkZC5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX3NldENhY2hlSGFzLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fc2V0VG9BcnJheS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX3N0YWNrQ2xlYXIuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19zdGFja0RlbGV0ZS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX3N0YWNrR2V0LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fc3RhY2tIYXMuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19zdGFja1NldC5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX3RvU291cmNlLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9jbG9uZURlZXAuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2VxLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9pc0FyZ3VtZW50cy5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvaXNBcnJheS5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvaXNBcnJheUxpa2UuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2lzQnVmZmVyLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9pc0VxdWFsLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9pc0Z1bmN0aW9uLmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9pc0xlbmd0aC5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvaXNNYXAuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2lzT2JqZWN0LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9pc09iamVjdExpa2UuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2lzU2V0LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9pc1R5cGVkQXJyYXkuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2tleXMuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2tleXNJbi5qcyIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvc3R1YkFycmF5LmpzIiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9zdHViRmFsc2UuanMiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzL3dlYnBhY2svcnVudGltZS9nbG9iYWwiLCJ3ZWJwYWNrOi8vdXNlLWxvZ2dpbmctYXBpcy93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3VzZS1sb2dnaW5nLWFwaXMvd2VicGFjay9ydW50aW1lL25vZGUgbW9kdWxlIGRlY29yYXRvciIsIndlYnBhY2s6Ly91c2UtbG9nZ2luZy1hcGlzLy4vY2xpZW50L3NyYy9hcHAudHMiXSwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG52YXIgcmVxdWlyZSQkMCA9IHJlcXVpcmUoJ2V2ZW50cycpO1xudmFyIHJlcXVpcmUkJDAkMSA9IHJlcXVpcmUoJ2xvZGFzaC9jbG9uZURlZXAnKTtcbnZhciByZXF1aXJlJCQzID0gcmVxdWlyZSgnbG9kYXNoL2lzRXF1YWwnKTtcblxuZnVuY3Rpb24gX21lcmdlTmFtZXNwYWNlcyhuLCBtKSB7XG5cdG0uZm9yRWFjaChmdW5jdGlvbiAoZSkge1xuXHRcdGUgJiYgdHlwZW9mIGUgIT09ICdzdHJpbmcnICYmICFBcnJheS5pc0FycmF5KGUpICYmIE9iamVjdC5rZXlzKGUpLmZvckVhY2goZnVuY3Rpb24gKGspIHtcblx0XHRcdGlmIChrICE9PSAnZGVmYXVsdCcgJiYgIShrIGluIG4pKSB7XG5cdFx0XHRcdHZhciBkID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihlLCBrKTtcblx0XHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KG4sIGssIGQuZ2V0ID8gZCA6IHtcblx0XHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuXHRcdFx0XHRcdGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gZVtrXTsgfVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG5cdHJldHVybiBPYmplY3QuZnJlZXplKG4pO1xufVxuXG52YXIgY29tbW9uanNHbG9iYWwgPSB0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWxUaGlzIDogdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJyA/IHNlbGYgOiB7fTtcblxuZnVuY3Rpb24gZ2V0RGVmYXVsdEV4cG9ydEZyb21DanMgKHgpIHtcblx0cmV0dXJuIHggJiYgeC5fX2VzTW9kdWxlICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh4LCAnZGVmYXVsdCcpID8geFsnZGVmYXVsdCddIDogeDtcbn1cblxudmFyIE9wZW5GaW4kMiA9IHt9O1xuXG52YXIgZXZlbnRzID0ge307XG5cbnZhciBhcHBsaWNhdGlvbiQxID0ge307XG5cbi8qKlxuICogTmFtZXNwYWNlIGZvciBldmVudHMgdGhhdCBjYW4gYmUgZW1pdHRlZCBieSBhbiB7QGxpbmsgT3BlbkZpbi5BcHBsaWNhdGlvbn0uICBJbmNsdWRlcyBldmVudHNcbiAqIHJlLXByb3BhZ2F0ZWQgZnJvbSB0aGUge0BsaW5rIE9wZW5GaW4uV2luZG93fSAoYW5kLCB0cmFuc2l0aXZlbHksIHtAbGluayBPcGVuRmluLlZpZXd9KSBsZXZlbCwgcHJlZml4ZWQgd2l0aCBgd2luZG93LWAgKGFuZCBhbHNvLCBpZiBhcHBsaWNhYmxlLCBgdmlldy1gKS5cbiAqIEZvciBleGFtcGxlLCBhIHZpZXcncyBcImF0dGFjaGVkXCIgZXZlbnQgd2lsbCBmaXJlIGFzICd3aW5kb3ctdmlldy1hdHRhY2hlZCcgYXQgdGhlIGFwcGxpY2F0aW9uIGxldmVsLlxuICpcbiAqIEV2ZW50IHBheWxvYWRzIGFyZSBkb2N1bWVudGVkIGFzIGludGVyZmFjZXMsIHdoaWxlIGFsZ2VicmFpYyBoZWxwZXIgdHlwZXMgYW5kIGRlcml2ZWQgdHlwZXMgYXJlIGRvY3VtZW50ZWQgYXMgdHlwZSBhbGlhc2VzLlxuICogRXZlbnRzIGdhaW4gbWV0YWRhdGEgYXMgdGhleSBwcm9wYWdhdGUsIHdoaWNoIGlzICpub3QqIHByZXNlbnQgb24gdGhlIGV4cGxpY2l0IHBheWxvYWQgaW50ZXJmYWNlcy4gIFRvIHJlZmVyIHRvIHRoZSBmdWxsIHR5cGVcbiAqIG9mIGFuIGV2ZW50IGFzIGl0IHdvdWxkIGJlIHJhaXNlZCBvbiB0aGlzIGVtaXR0ZXIsIHVzZSB7QGxpbmsgUGF5bG9hZH0uXG4gKlxuICogVGhpcyBuYW1lc3BhY2UgY29udGFpbnMgb25seSBwYXlsb2FkIHNoYXBlcyBmb3IgZXZlbnRzIHRoYXQgYXJlIHVuaXF1ZSB0byBgQXBwbGljYXRpb25gLiAgRXZlbnRzIHRoYXQgcHJvcGFnYXRlIHRvIGBBcHBsaWNhdGlvbmAgZnJvbVxuICogY2hpbGQge0BsaW5rIE9wZW5GaW4uV2luZG93IHdpbmRvd3N9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3IHZpZXdzfSBhcmUgZGVmaW5lZCBpbiB0aGUge0BsaW5rIE9wZW5GaW4uV2luZG93RXZlbnRzfSBhbmRcbiAqIHtAbGluayBPcGVuRmluLlZpZXdFdmVudHN9IG5hbWVzcGFjZXMuICBGb3IgYSBsaXN0IG9mIHZhbGlkIHN0cmluZyBrZXlzIGZvciAqYWxsKiBhcHBsaWNhdGlvbiBldmVudHMsIHNlZSB7QGxpbmsgQXBwbGljYXRpb24ub24gQXBwbGljYXRpb24ub259LlxuICpcbiAqIHtAbGluayBBcHBsaWNhdGlvblNvdXJjZWRFdmVudCBBcHBsaWNhdGlvbi1zb3VyY2VkIGV2ZW50c30gKGkuZS4gdGhvc2UgdGhhdCBoYXZlIG5vdCBwcm9wYWdhdGVkIGZyb20ge0BsaW5rIE9wZW5GaW4uVmlld0V2ZW50cyBWaWV3c31cbiAqIG9yIHtAbGluayBPcGVuRmluLldpbmRvd0V2ZW50cyBXaW5kb3dzfSByZS1wcm9wYWdhdGUgdG8ge0BsaW5rIE9wZW5GaW4uU3lzdGVtRXZlbnRzIFN5c3RlbX0gd2l0aCB0aGVpciB0eXBlIHN0cmluZyBwcmVmaXhlZCB3aXRoIGBhcHBsaWNhdGlvbi1gLlxuICoge0BsaW5rIEFwcGxpY2F0aW9uV2luZG93RXZlbnQgQXBwbGljYXRpb24gZXZlbnRzIHRoYXQgYXJlIHRpZWQgdG8gV2luZG93cyBidXQgZG8gbm90IHByb3BhZ2F0ZSBmcm9tIHRoZW19XG4gKiBhcmUgcHJvcGFnYXRlZCB0byBgU3lzdGVtYCB3aXRob3V0IGFueSB0eXBlIHN0cmluZyBwcmVmaXhpbmcuXG4gKlxuICogXCJSZXF1ZXN0ZWRcIiBldmVudHMgKGUuZy4ge0BsaW5rIFJ1blJlcXVlc3RlZEV2ZW50fSkgZG8gbm90IHByb3BhZ2F0ZS5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGFwcGxpY2F0aW9uJDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG52YXIgYmFzZSQxID0ge307XG5cbi8qKlxuICogTmFtZXNwYWNlIGZvciBzaGFyZWQgZXZlbnQgcGF5bG9hZHMgYW5kIHV0aWxpdHkgdHlwZXMgY29tbW9uIHRvIGFsbCBldmVudCBlbWl0dGVycy5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGJhc2UkMSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cbnZhciBleHRlcm5hbEFwcGxpY2F0aW9uJDEgPSB7fTtcblxuLyoqXG4gKiBOYW1lc3BhY2UgZm9yIGV2ZW50cyB0aGF0IGNhbiBiZSB0cmFuc21pdHRlZCBieSBhbiB7QGxpbmsgT3BlbkZpbi5FeHRlcm5hbEFwcGxpY2F0aW9ufS5cbiAqXG4gKiBFdmVudCBwYXlsb2FkcyBhcmUgZG9jdW1lbnRlZCBhcyBpbnRlcmZhY2VzLCB3aGlsZSBhbGdlYnJhaWMgaGVscGVyIHR5cGVzIGFuZCBkZXJpdmVkIHR5cGVzIGFyZSBkb2N1bWVudGVkIGFzIHR5cGUgYWxpYXNlcy5cbiAqIEV2ZW50cyBnYWluIG1ldGFkYXRhIGFzIHRoZXkgcHJvcGFnYXRlLCB3aGljaCBpcyAqbm90KiBwcmVzZW50IG9uIHRoZSBleHBsaWNpdCBwYXlsb2FkIGludGVyZmFjZXMuICBUbyByZWZlciB0byB0aGUgZnVsbCB0eXBlXG4gKiBvZiBhbiBldmVudCBhcyBpdCB3b3VsZCBiZSByYWlzZWQgb24gdGhpcyBlbWl0dGVyLCB1c2Uge0BsaW5rIFBheWxvYWR9LlxuICpcbiAqIEZvciBhIGxpc3Qgb2YgdmFsaWQgc3RyaW5nIGtleXMgZm9yIGV4dGVybmFsIGFwcGxpY2F0aW9uIGV2ZW50cywgc2VlIHtAbGluayBFeHRlcm5hbEFwcGxpY2F0aW9uLm9uIEV4dGVybmFsQXBwbGljYXRpb24ub259LlxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXh0ZXJuYWxBcHBsaWNhdGlvbiQxLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIGZyYW1lJDEgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGZyYW1lJDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG52YXIgZ2xvYmFsSG90a2V5JDEgPSB7fTtcblxuLyoqXG4gKlxuICogTmFtZXNwYWNlIGZvciBldmVudHMgdGhhdCBjYW4gYmUgdHJhbnNtaXR0ZWQgYnkge0BsaW5rIEdsb2JhbEhvdGtleS5HbG9iYWxIb3RrZXl9LlxuICpcbiAqIEV2ZW50IHBheWxvYWRzIGFyZSBkb2N1bWVudGVkIGFzIGludGVyZmFjZXMsIHdoaWxlIGFsZ2VicmFpYyBoZWxwZXIgdHlwZXMgYW5kIGRlcml2ZWQgdHlwZXMgYXJlIGRvY3VtZW50ZWQgYXMgdHlwZSBhbGlhc2VzLlxuICogRXZlbnRzIGdhaW4gbWV0YWRhdGEgYXMgdGhleSBwcm9wYWdhdGUsIHdoaWNoIGlzICpub3QqIHByZXNlbnQgb24gdGhlIGV4cGxpY2l0IHBheWxvYWQgaW50ZXJmYWNlcy4gIFRvIHJlZmVyIHRvIHRoZSBmdWxsIHR5cGVcbiAqIG9mIGFuIGV2ZW50IGFzIGl0IHdvdWxkIGJlIHJhaXNlZCBvbiB0aGlzIGVtaXR0ZXIsIHVzZSB7QGxpbmsgUGF5bG9hZH0uXG4gKlxuICogRm9yIGEgbGlzdCBvZiB2YWxpZCBzdHJpbmcga2V5cyBmb3IgZ2xvYmFsIGhvdGtleSBldmVudHMsIHNlZSB7QGxpbmsgR2xvYmFsSG90a2V5Lkdsb2JhbEhvdGtleS5vbiBHbG9iYWxIb3RrZXkub259LlxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZ2xvYmFsSG90a2V5JDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG52YXIgcGxhdGZvcm0kMSA9IHt9O1xuXG4vKipcbiAqXG4gKiBOYW1lc3BhY2UgZm9yIGV2ZW50cyB0aGF0IGNhbiBlbWl0dGVkIGJ5IGEge0BsaW5rIE9wZW5GaW4uUGxhdGZvcm19LlxuICpcbiAqIEV2ZW50IHBheWxvYWRzIGFyZSBkb2N1bWVudGVkIGFzIGludGVyZmFjZXMsIHdoaWxlIGFsZ2VicmFpYyBoZWxwZXIgdHlwZXMgYW5kIGRlcml2ZWQgdHlwZXMgYXJlIGRvY3VtZW50ZWQgYXMgdHlwZSBhbGlhc2VzLlxuICogRXZlbnRzIGdhaW4gbWV0YWRhdGEgYXMgdGhleSBwcm9wYWdhdGUsIHdoaWNoIGlzICpub3QqIHByZXNlbnQgb24gdGhlIGV4cGxpY2l0IHBheWxvYWQgaW50ZXJmYWNlcy4gIFRvIHJlZmVyIHRvIHRoZSBmdWxsIHR5cGVcbiAqIG9mIGFuIGV2ZW50IGFzIGl0IHdvdWxkIGJlIHJhaXNlZCBvbiB0aGlzIGVtaXR0ZXIsIHVzZSB7QGxpbmsgUGF5bG9hZH0uXG4gKlxuICogVGhlIFBsYXRmb3JtIGBFdmVudEVtaXR0ZXJgIGlzIGEgc3VwZXJzZXQgb2YgdGhlIHtAbGluayBPcGVuRmluLkFwcGxpY2F0aW9ufSBgRXZlbnRFbWl0dGVyYCxcbiAqIG1lYW5pbmcgaXQgY2FuIGxpc3RlbiB0byBhbGwge0BsaW5rIE9wZW5GaW4uQXBwbGljYXRpb25FdmVudHMgQXBwbGljYXRpb24gZXZlbnRzfSBpbiBhZGRpdGlvbiB0byB0aGVcbiAqIFBsYXRmb3JtLXNwZWNpZmljIGV2ZW50cyBsaXN0ZWQgaGVyZS4gIEZvciBhIGxpc3Qgb2YgdmFsaWQgc3RyaW5nIGtleXMgZm9yICphbGwqIHBsYXRmb3JtIGV2ZW50cywgc2VlXG4gKiB7QGxpbmsgUGxhdGZvcm0ub24gUGxhdGZvcm0ub259LlxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkocGxhdGZvcm0kMSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cbnZhciBzeXN0ZW0kMSA9IHt9O1xuXG4vKipcbiAqIE5hbWVzcGFjZSBmb3IgcnVudGltZS13aWRlIE9wZW5GaW4gZXZlbnRzIGVtaXR0ZWQgYnkge0BsaW5rIFN5c3RlbS5TeXN0ZW19LiAgSW5jbHVkZXMgZXZlbnRzXG4gKiByZS1wcm9wYWdhdGVkIGZyb20ge0BsaW5rIE9wZW5GaW4uQXBwbGljYXRpb259LCB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9LCBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30gKHByZWZpeGVkIHdpdGggYGFwcGxpY2F0aW9uLWAsIGB3aW5kb3ctYCwgYW5kIGB2aWV3LWApLiAgQWxsXG4gKiBldmVudCBwcm9wYWdhdGlvbnMgYXJlIHZpc2libGUgYXQgdGhlIFN5c3RlbSBsZXZlbC4gUHJvcGFnYXRlZCBldmVudHMgZnJvbSBXZWJDb250ZW50cyAod2luZG93cywgdmlld3MsIGZyYW1lcykgdG8gdGhlIEFwcGxpY2F0aW9uIGxldmVsIHdpbGwgKm5vdCpcbiAqIHRyYW5zaXRpdmVseSByZS1wcm9wYWdhdGUgdG8gdGhlIFN5c3RlbSBsZXZlbCwgYmVjYXVzZSB0aGV5IGFyZSBhbHJlYWR5IHZpc2libGUgYXQgdGhlIHN5c3RlbSBsZXZlbCBhbmQgY29udGFpbiB0aGUgaWRlbnRpdHlcbiAqIG9mIHRoZSBhcHBsaWNhdGlvbi4gIEZvciBleGFtcGxlLCBhbiBhcHBsaWNhdGlvbidzIFwiY2xvc2VkXCIgZXZlbnQgd2lsbCBmaXJlIGFzICdhcHBsaWNhdGlvbi1jbG9zZWQnIGF0IHRoZSBzeXN0ZW0gbGV2ZWwuICBBIHZpZXcncyAnc2hvd24nIGV2ZW50XG4gKiB3aWxsIGJlIHZpc2libGUgYXMgJ3ZpZXctc2hvd24nIGF0IHRoZSBzeXN0ZW0gbGV2ZWwsIGJ1dCAqbm90KiBhcyBgYXBwbGljYXRpb24td2luZG93LXZpZXctc2hvd25gLlxuICpcbiAqIEV2ZW50IHBheWxvYWRzIGFyZSBkb2N1bWVudGVkIGFzIGludGVyZmFjZXMsIHdoaWxlIGFsZ2VicmFpYyBoZWxwZXIgdHlwZXMgYW5kIGRlcml2ZWQgdHlwZXMgYXJlIGRvY3VtZW50ZWQgYXMgdHlwZSBhbGlhc2VzLlxuICogRXZlbnRzIGdhaW4gbWV0YWRhdGEgYXMgdGhleSBwcm9wYWdhdGUsIHdoaWNoIGlzICpub3QqIHByZXNlbnQgb24gdGhlIGV4cGxpY2l0IHBheWxvYWQgaW50ZXJmYWNlcy4gIFRvIHJlZmVyIHRvIHRoZSBmdWxsIHR5cGVcbiAqIG9mIGFuIGV2ZW50IGFzIGl0IHdvdWxkIGJlIHJhaXNlZCBvbiB0aGlzIGVtaXR0ZXIsIHVzZSB7QGxpbmsgUGF5bG9hZH0uXG4gKlxuICogVGhpcyBuYW1lc3BhY2UgY29udGFpbnMgb25seSBwYXlsb2FkIHNoYXBlcyBmb3IgZXZlbnRzIHRoYXQgYXJlIHVuaXF1ZSB0byBgU3lzdGVtYC4gIEV2ZW50cyB0aGF0IHByb3BhZ2F0ZSB0byBgU3lzdGVtYCBmcm9tXG4gKiBjaGlsZCB7QGxpbmsgT3BlbkZpbi5BcHBsaWNhdGlvbiBhcHBsaWNhdGlvbnN9LCB7QGxpbmsgT3BlbkZpbi5XaW5kb3cgd2luZG93c30sIGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3IHZpZXdzfSBhcmUgZGVmaW5lZCBpbiB0aGVcbiAqIHtAbGluayBPcGVuRmluLkFwcGxpY2F0aW9uRXZlbnRzfSwge0BsaW5rIE9wZW5GaW4uV2luZG93RXZlbnRzfSwgYW5kIHtAbGluayBPcGVuRmluLlZpZXdFdmVudHN9IG5hbWVzcGFjZXMuICBGb3IgYSBsaXN0IG9mIHZhbGlkIHN0cmluZyBrZXlzIGZvciAqYWxsKlxuICogc3lzdGVtIGV2ZW50cywgc2VlIHtAbGluayBTeXN0ZW0ub24gU3lzdGVtLm9ufS5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KHN5c3RlbSQxLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIHZpZXckMSA9IHt9O1xuXG4vKipcbiAqIE5hbWVzcGFjZSBmb3IgZXZlbnRzIHRoYXQgY2FuIGJlIGVtaXR0ZWQgYnkgYSB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAqXG4gKiBFdmVudCBwYXlsb2FkcyBhcmUgZG9jdW1lbnRlZCBhcyBpbnRlcmZhY2VzLCB3aGlsZSBhbGdlYnJhaWMgaGVscGVyIHR5cGVzIGFuZCBkZXJpdmVkIHR5cGVzIGFyZSBkb2N1bWVudGVkIGFzIHR5cGUgYWxpYXNlcy5cbiAqIEV2ZW50cyBnYWluIG1ldGFkYXRhIGFzIHRoZXkgcHJvcGFnYXRlLCB3aGljaCBpcyAqbm90KiBwcmVzZW50IG9uIHRoZSBleHBsaWNpdCBwYXlsb2FkIGludGVyZmFjZXMuICBUbyByZWZlciB0byB0aGUgZnVsbCB0eXBlXG4gKiBvZiBhbiBldmVudCBhcyBpdCB3b3VsZCBiZSByYWlzZWQgb24gdGhpcyBlbWl0dGVyLCB1c2Uge0BsaW5rIFBheWxvYWR9LlxuICpcbiAqIFRoaXMgbmFtZXNwYWNlIGNvbnRhaW5zIG9ubHkgcGF5bG9hZCBzaGFwZXMgZm9yIGV2ZW50cyB0aGF0IGFyZSB1bmlxdWUgdG8gYFZpZXdgLiAgRXZlbnRzIHRoYXQgYXJlIHNoYXJlZCBiZXR3ZWVuIGFsbCBgV2ViQ29udGVudHNgXG4gKiAoaS5lLiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9LCB7QGxpbmsgT3BlbkZpbi5WaWV3fSkgYXJlIGRlZmluZWQgaW4ge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHN9LiAgRm9yIGEgbGlzdFxuICogb2YgdmFsaWQgc3RyaW5nIGtleXMgZm9yICphbGwqIFZpZXcgZXZlbnRzLCBzZWUge0BsaW5rIFZpZXcub24gVmlldy5vbn0uXG4gKlxuICogVmlldyBldmVudHMgcHJvcGFnYXRlIHRvIHRoZWlyIHBhcmVudCB7QGxpbmsgT3BlbkZpbi5XaW5kb3dFdmVudHMgV2luZG93fSwge0BsaW5rIE9wZW5GaW4uQXBwbGljYXRpb25FdmVudHMgQXBwbGljYXRpb259LFxuICogYW5kIHtAbGluayBPcGVuRmluLlN5c3RlbUV2ZW50cyBTeXN0ZW19IHdpdGggYW4gYWRkZWQgYHZpZXdJZGVudGl0eWAgcHJvcGVydHkgYW5kIHRoZWlyIGV2ZW50IHR5cGVzIHByZWZpeGVkIHdpdGggYCd2aWV3LSdgLlxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkodmlldyQxLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIHdlYmNvbnRlbnRzID0ge307XG5cbi8qKlxuICogTmFtZXNwYWNlIGZvciBldmVudHMgc2hhcmVkIGJ5IGFsbCBPcGVuRmluIFdlYkNvbnRlbnRzIGVsZW1lbnRzIChpLmUuIHtAbGluayBPcGVuRmluLldpbmRvd30sXG4gKiB7QGxpbmsgT3BlbkZpbi5WaWV3fSkuXG4gKlxuICogV2ViQ29udGVudHMgZXZlbnRzIHdpbGwgcmUtZW1pdCBvbiBwYXJlbnQgZW50aXRpZXMgLSBlLmcuLCBhIHByb3BhZ2F0aW5nIGV2ZW50IGluIGEgdmlldyB3aWxsIGFsc28gYmUgZW1pdHRlZCBvbiB0aGUgdmlldydzXG4gKiBwYXJlbnQgd2luZG93LCBhbmQgcHJvcGFnYXRpbmcgZXZlbnRzIGluIGEgd2luZG93IHdpbGwgYWxzbyBiZSBlbWl0dGVkIG9uIHRoZSB3aW5kb3cncyBwYXJlbnQge0BsaW5rIE9wZW5GaW4uQXBwbGljYXRpb259LlxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkod2ViY29udGVudHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG52YXIgd2luZG93JDIgPSB7fTtcblxuLyoqXG4gKiBOYW1lc3BhY2UgZm9yIGV2ZW50cyB0aGF0IGNhbiBiZSBlbWl0dGVkIGJ5IGEge0BsaW5rIE9wZW5GaW4uV2luZG93fS5cbiAqXG4gKiBFdmVudCBwYXlsb2FkcyBhcmUgZG9jdW1lbnRlZCBhcyBpbnRlcmZhY2VzLCB3aGlsZSBhbGdlYnJhaWMgaGVscGVyIHR5cGVzIGFuZCBkZXJpdmVkIHR5cGVzIGFyZSBkb2N1bWVudGVkIGFzIHR5cGUgYWxpYXNlcy5cbiAqIEV2ZW50cyBnYWluIG1ldGFkYXRhIGFzIHRoZXkgcHJvcGFnYXRlLCB3aGljaCBpcyAqbm90KiBwcmVzZW50IG9uIHRoZSBleHBsaWNpdCBwYXlsb2FkIGludGVyZmFjZXMuICBUbyByZWZlciB0byB0aGUgZnVsbCB0eXBlXG4gKiBvZiBhbiBldmVudCBhcyBpdCB3b3VsZCBiZSByYWlzZWQgb24gdGhpcyBlbWl0dGVyLCB1c2Uge0BsaW5rIFBheWxvYWR9LlxuICpcbiAqIFRoaXMgbmFtZXNwYWNlIGNvbnRhaW5zIG9ubHkgcGF5bG9hZCBzaGFwZXMgZm9yIGV2ZW50cyB0aGF0IGFyZSB1bmlxdWUgdG8gYFdpbmRvd2AuICBFdmVudHMgdGhhdCBhcmUgc2hhcmVkIGJldHdlZW4gYWxsIGBXZWJDb250ZW50c2BcbiAqIChpLmUuIHtAbGluayBPcGVuRmluLldpbmRvd30sIHtAbGluayBPcGVuRmluLlZpZXd9KSBhcmUgZGVmaW5lZCBpbiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50c30uIEV2ZW50cyB0aGF0XG4gKiBwcm9wYWdhdGUgZnJvbSBgVmlld2AgYXJlIGRlZmluZWQgaW4ge0BsaW5rIE9wZW5GaW4uVmlld0V2ZW50c30uIEZvciBhIGxpc3Qgb2YgdmFsaWQgc3RyaW5nIGtleXMgZm9yICphbGwqIFdpbmRvdyBldmVudHMsIHNlZVxuICoge0BsaW5rIFdpbmRvdy5vbiBXaW5kb3cub259XG4gKlxuICoge0BsaW5rIE9wZW5GaW4uV2luZG93RXZlbnRzLldpbmRvd1NvdXJjZWRFdmVudCBXaW5kb3ctc291cmNlZCBldmVudHN9IChpLmUuIHRob3NlIHRoYXQgYXJlIG5vdCBwcm9wYWdhdGVkIGZyb20gYVxuICoge0BsaW5rIE9wZW5GaW4uVmlld0V2ZW50cyBWaWV3fSkgcHJvcGFnYXRlIHRvIHRoZWlyIHBhcmVudCB7QGxpbmsgT3BlbkZpbi5BcHBsaWNhdGlvbkV2ZW50cyBBcHBsaWNhdGlvbn0gYW5kXG4gKiB7QGxpbmsgT3BlbkZpbi5TeXN0ZW1FdmVudHMgU3lzdGVtfSB3aXRoIHRoZWlyIGV2ZW50IHR5cGVzIHByZWZpeGVkIHdpdGggYCd3aW5kb3ctJ2ApLlxuICpcbiAqIFwiUmVxdWVzdGVkXCIgZXZlbnRzIChlLmcuIHtAbGluayBBdXRoUmVxdWVzdGVkRXZlbnR9KSBkbyBub3QgcHJvcGFnYXRlIHRvIGBTeXN0ZW0uICBUaGUge0BsaW5rIE9wZW5GaW4uV2luZG93RXZlbnRzLldpbmRvd0Nsb3NlUmVxdWVzdGVkRXZlbnR9XG4gKiBkb2VzIG5vdCBwcm9wYWdhdGUgYXQgYWxsLlxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkod2luZG93JDIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG4vKipcbiAqIE5hbWVzcGFjZSBmb3IgT3BlbkZpbiBldmVudCB0eXBlcy4gRWFjaCBlbnRpdHkgdGhhdCBlbWl0cyBPcGVuRmluIGV2ZW50cyBoYXMgaXRzIG93biBzdWItbmFtZXNwYWNlLiBFdmVudCBwYXlsb2Fkc1xuICogdGhlbXNlbHZlcyBhcmUgZG9jdW1lbnRlZCBhcyBpbnRlcmZhY2VzLCB3aGlsZSBhbGdlYnJhaWMgaGVscGVyIHR5cGVzIGFuZCBkZXJpdmVkIHR5cGVzIGFyZSBkb2N1bWVudGVkIGFzIHR5cGUgYWxpYXNlcy5cbiAqXG4gKiAjIyMjIEV2ZW50IGVtaXR0ZXJzXG4gKlxuICogVGhlIGZvbGxvd2luZyBlbnRpdGllcyBlbWl0IE9wZW5GaW4gZXZlbnRzLCBhbmQgaGF2ZSBjb3JyZXNwb25kaW5nIHN1Yi1uYW1lc3BhY2VzOlxuICpcbiAqICoge0BsaW5rIE9wZW5GaW4uQXBwbGljYXRpb259OiB7QGxpbmsgT3BlbkZpbi5BcHBsaWNhdGlvbkV2ZW50c31cbiAqICoge0BsaW5rIE9wZW5GaW4uRXh0ZXJuYWxBcHBsaWNhdGlvbn06IHtAbGluayBPcGVuRmluLkV4dGVybmFsQXBwbGljYXRpb25FdmVudHN9XG4gKiAqIHtAbGluayBPcGVuRmluLkZyYW1lfToge0BsaW5rIE9wZW5GaW4uRnJhbWVFdmVudHN9XG4gKiAqIHtAbGluayBPcGVuRmluLkdsb2JhbEhvdGtleX06IHtAbGluayBPcGVuRmluLkdsb2JhbEhvdGtleUV2ZW50c31cbiAqICoge0BsaW5rIE9wZW5GaW4uUGxhdGZvcm19OiB7QGxpbmsgT3BlbkZpbi5QbGF0Zm9ybUV2ZW50c31cbiAqICoge0BsaW5rIE9wZW5GaW4uU3lzdGVtfToge0BsaW5rIE9wZW5GaW4uU3lzdGVtRXZlbnRzfVxuICogKiB7QGxpbmsgT3BlbkZpbi5WaWV3fToge0BsaW5rIE9wZW5GaW4uVmlld0V2ZW50c31cbiAqICoge0BsaW5rIE9wZW5GaW4uV2luZG93fToge0BsaW5rIE9wZW5GaW4uV2luZG93RXZlbnRzfVxuICpcbiAqIFRoZXNlIGBFdmVudEVtaXR0ZXJgIGVudGl0aWVzIHNoYXJlIGEgY29tbW9uIHNldCBvZiBtZXRob2RzIGZvciBpbnRlcmFjdGluZyB3aXRoIHRoZSBPcGVuRmluIGV2ZW50IGJ1cywgd2hpY2ggY2FuIGJlXG4gKiBzZWVuIG9uIHRoZSBpbmRpdmlkdWFsIGRvY3VtZW50YXRpb24gcGFnZXMgZm9yIGVhY2ggZW50aXR5IHR5cGUuXG4gKlxuICogUmVnaXN0ZXJpbmcgZXZlbnQgaGFuZGxlcnMgaXMgYW4gYXN5bmNocm9ub3VzIG9wZXJhdGlvbi4gSXQgaXMgaW1wb3J0YW50IHRvIGVuc3VyZSB0aGF0IHRoZSByZXR1cm5lZCBQcm9taXNlcyBhcmUgYXdhaXRlZCB0byByZWR1Y2UgdGhlXG4gKiByaXNrIG9mIHJhY2UgY29uZGl0aW9ucy5cbiAqXG4gKiBXaGVuIHRoZSBgRXZlbnRFbWl0dGVyYCByZWNlaXZlcyBhbiBldmVudCBmcm9tIHRoZSBicm93c2VyIHByb2Nlc3MgYW5kIGVtaXRzIG9uIHRoZSByZW5kZXJlciwgYWxsIG9mIHRoZSBmdW5jdGlvbnMgYXR0YWNoZWQgdG8gdGhhdFxuICogc3BlY2lmaWMgZXZlbnQgYXJlIGNhbGxlZCBzeW5jaHJvbm91c2x5LiBBbnkgdmFsdWVzIHJldHVybmVkIGJ5IHRoZSBjYWxsZWQgbGlzdGVuZXJzIGFyZSBpZ25vcmVkIGFuZCB3aWxsIGJlIGRpc2NhcmRlZC4gIElmIHRoZSB3aW5kb3cgZG9jdW1lbnRcbiAqIGlzIGRlc3Ryb3llZCBieSBwYWdlIG5hdmlnYXRpb24gb3IgcmVsb2FkLCBpdHMgcmVnaXN0ZXJlZCBldmVudCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICpcbiAqIFdlIHJlY29tbWVuZCB1c2luZyBBcnJvdyBGdW5jdGlvbnMgZm9yIGV2ZW50IGxpc3RlbmVycyB0byBlbnN1cmUgdGhlIHRoaXMgc2NvcGUgaXMgY29uc2lzdGVudCB3aXRoIHRoZSBvcmlnaW5hbCBmdW5jdGlvbiBjb250ZXh0LlxuICpcbiAqIEV2ZW50cyByZS1wcm9wYWdhdGUgZnJvbSBzbWFsbGVyL21vcmUtbG9jYWwgc2NvcGVzIHRvIGxhcmdlci9tb3JlLWdsb2JhbCBzY29wZXMuICBGb3IgZXhhbXBsZSwgYW4gZXZlbnQgZW1pdHRlZCBvbiBhIHNwZWNpZmljXG4gKiB2aWV3IHdpbGwgcHJvcGFnYXRlIHRvIHRoZSB3aW5kb3cgaW4gd2hpY2ggdGhlIHZpZXcgaXMgZW1iZWRkZWQsIGFuZCB0aGVuIHRvIHRoZSBhcHBsaWNhdGlvbiBpbiB3aGljaCB0aGUgd2luZG93IGlzIHJ1bm5pbmcsIGFuZFxuICogZmluYWxseSB0byB0aGUgT3BlbkZpbiBydW50aW1lIGl0c2VsZiBhdCB0aGUgXCJzeXN0ZW1cIiBsZXZlbC4gIEZvciBkZXRhaWxzIG9uIHByb3BhZ2F0aW9uIHNlbWFudGljcywgc2VlIHRoZSBuYW1lc3BhY2UgZm9yXG4gKiB0aGUgcHJvcGFnYXRpbmcgKG9yIHByb3BhZ2F0ZWQtdG8pIGVudGl0eS5cbiAqXG4gKiBJZiB5b3UgbmVlZCB0aGUgcGF5bG9hZCB0eXBlIGZvciBhIHNwZWNpZmljIHR5cGUgb2YgZXZlbnQgKGVzcGVjaWFsbHkgcHJvcGFnYXRlZCBldmVudHMpLCB1c2UgdGhlIGVtaXR0aW5nIHRvcGljJ3MgYFBheWxvYWRgIGdlbmVyaWNcbiAqIChlLmcuIHtAbGluayBXaW5kb3dFdmVudHMuUGF5bG9hZH0pIHdpdGggdGhlIGV2ZW50J3MgYHR5cGVgIHN0cmluZy4gIEZvciBleGFtcGxlLCB0aGUgcGF5bG9hZCBvZlxuICogYSB7QGxpbmsgVmlld0V2ZW50cy5DcmVhdGVkRXZlbnR9IGFmdGVyIGl0IGhhcyBwcm9wYWdhdGVkIHRvIGl0cyBwYXJlbnQge0BsaW5rIFdpbmRvd0V2ZW50cyBXaW5kb3d9IGNhbiBiZSBmb3VuZCB3aXRoXG4gKiBgV2luZG93RXZlbnRzLlBheWxvYWQ8J3ZpZXctY3JlYXRlZCc+YC5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xudmFyIF9fY3JlYXRlQmluZGluZyQxID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY3JlYXRlQmluZGluZykgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcbiAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xuICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcbiAgICB9XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcbn0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcbiAgICBvW2syXSA9IG1ba107XG59KSk7XG52YXIgX19zZXRNb2R1bGVEZWZhdWx0JDEgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19zZXRNb2R1bGVEZWZhdWx0KSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCB2KSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIFwiZGVmYXVsdFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xufSkgOiBmdW5jdGlvbihvLCB2KSB7XG4gICAgb1tcImRlZmF1bHRcIl0gPSB2O1xufSk7XG52YXIgX19pbXBvcnRTdGFyJDEgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19pbXBvcnRTdGFyKSB8fCBmdW5jdGlvbiAobW9kKSB7XG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcbiAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgaWYgKG1vZCAhPSBudWxsKSBmb3IgKHZhciBrIGluIG1vZCkgaWYgKGsgIT09IFwiZGVmYXVsdFwiICYmIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtb2QsIGspKSBfX2NyZWF0ZUJpbmRpbmckMShyZXN1bHQsIG1vZCwgayk7XG4gICAgX19zZXRNb2R1bGVEZWZhdWx0JDEocmVzdWx0LCBtb2QpO1xuICAgIHJldHVybiByZXN1bHQ7XG59O1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV2ZW50cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5ldmVudHMuV2luZG93RXZlbnRzID0gZXZlbnRzLldlYkNvbnRlbnRzRXZlbnRzID0gZXZlbnRzLlZpZXdFdmVudHMgPSBldmVudHMuU3lzdGVtRXZlbnRzID0gZXZlbnRzLlBsYXRmb3JtRXZlbnRzID0gZXZlbnRzLkdsb2JhbEhvdGtleUV2ZW50cyA9IGV2ZW50cy5GcmFtZUV2ZW50cyA9IGV2ZW50cy5FeHRlcm5hbEFwcGxpY2F0aW9uRXZlbnRzID0gZXZlbnRzLkJhc2VFdmVudHMgPSBldmVudHMuQXBwbGljYXRpb25FdmVudHMgPSB2b2lkIDA7XG5jb25zdCBBcHBsaWNhdGlvbkV2ZW50cyA9IF9faW1wb3J0U3RhciQxKGFwcGxpY2F0aW9uJDEpO1xuZXZlbnRzLkFwcGxpY2F0aW9uRXZlbnRzID0gQXBwbGljYXRpb25FdmVudHM7XG5jb25zdCBCYXNlRXZlbnRzID0gX19pbXBvcnRTdGFyJDEoYmFzZSQxKTtcbmV2ZW50cy5CYXNlRXZlbnRzID0gQmFzZUV2ZW50cztcbmNvbnN0IEV4dGVybmFsQXBwbGljYXRpb25FdmVudHMgPSBfX2ltcG9ydFN0YXIkMShleHRlcm5hbEFwcGxpY2F0aW9uJDEpO1xuZXZlbnRzLkV4dGVybmFsQXBwbGljYXRpb25FdmVudHMgPSBFeHRlcm5hbEFwcGxpY2F0aW9uRXZlbnRzO1xuY29uc3QgRnJhbWVFdmVudHMgPSBfX2ltcG9ydFN0YXIkMShmcmFtZSQxKTtcbmV2ZW50cy5GcmFtZUV2ZW50cyA9IEZyYW1lRXZlbnRzO1xuY29uc3QgR2xvYmFsSG90a2V5RXZlbnRzID0gX19pbXBvcnRTdGFyJDEoZ2xvYmFsSG90a2V5JDEpO1xuZXZlbnRzLkdsb2JhbEhvdGtleUV2ZW50cyA9IEdsb2JhbEhvdGtleUV2ZW50cztcbmNvbnN0IFBsYXRmb3JtRXZlbnRzID0gX19pbXBvcnRTdGFyJDEocGxhdGZvcm0kMSk7XG5ldmVudHMuUGxhdGZvcm1FdmVudHMgPSBQbGF0Zm9ybUV2ZW50cztcbmNvbnN0IFN5c3RlbUV2ZW50cyA9IF9faW1wb3J0U3RhciQxKHN5c3RlbSQxKTtcbmV2ZW50cy5TeXN0ZW1FdmVudHMgPSBTeXN0ZW1FdmVudHM7XG5jb25zdCBWaWV3RXZlbnRzID0gX19pbXBvcnRTdGFyJDEodmlldyQxKTtcbmV2ZW50cy5WaWV3RXZlbnRzID0gVmlld0V2ZW50cztcbmNvbnN0IFdlYkNvbnRlbnRzRXZlbnRzID0gX19pbXBvcnRTdGFyJDEod2ViY29udGVudHMpO1xuZXZlbnRzLldlYkNvbnRlbnRzRXZlbnRzID0gV2ViQ29udGVudHNFdmVudHM7XG5jb25zdCBXaW5kb3dFdmVudHMgPSBfX2ltcG9ydFN0YXIkMSh3aW5kb3ckMik7XG5ldmVudHMuV2luZG93RXZlbnRzID0gV2luZG93RXZlbnRzO1xuXG4oZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0LyoqXG5cdCAqIFRvcC1sZXZlbCBuYW1lc3BhY2UgZm9yIHR5cGVzIHJlZmVyZW5jZWQgYnkgdGhlIE9wZW5GaW4gQVBJLiAgQ29udGFpbnM6XG5cdCAqXG5cdCAqICogVGhlIHR5cGUgb2YgdGhlIGdsb2JhbCBgZmluYCBlbnRyeSBwb2ludCAoe0BsaW5rIEZpbkFwaX0pXG5cdCAqICogQ2xhc3NlcyB0aGF0IGFjdCBhcyBzdGF0aWMgbmFtZXNwYWNlcyByZXR1cm5lZCBmcm9tIHRoZSBgZmluYCBnbG9iYWwgKGUuZy4ge0BsaW5rIEFwcGxpY2F0aW9uTW9kdWxlfSwgYWNjZXNzaWJsZSB2aWEgYGZpbi5BcHBsaWNhdGlvbmApXG5cdCAqICogSW5zdGFuY2UgY2xhc3NlcyB0aGF0IGFyZSByZXR1cm5lZCBmcm9tIEFQSSBjYWxscyAoZS5nLiB7QGxpbmsgQXBwbGljYXRpb259LCBhY2Nlc3NpYmxlIHZpYSBgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnRTeW5jKClgKVxuXHQgKiAqIFBhcmFtZXRlciBzaGFwZXMgZm9yIEFQSSBtZXRob2RzIChlLmcuIHtAbGluayBBcHBsaWNhdGlvbk9wdGlvbnN9LCB1c2VkIGluIGBmaW4uQXBwbGljYXRpb24uc3RhcnQoKWApXG5cdCAqICogRXZlbnQgbmFtZXNwYWNlcyBhbmQgcGF5bG9hZCB1bmlvbiB0eXBlcyAoZS5nLiB7QGxpbmsgQXBwbGljYXRpb25FdmVudHN9IGFuZCB7QGxpbmsgQXBwbGljYXRpb25FdmVudH0pXG5cdCAqXG5cdCAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuXHQgKi9cblx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0ICAgIH1cblx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgb1trMl0gPSBtW2tdO1xuXHR9KSk7XG5cdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0Ly8gRGVwcmVjYXRlZCBzaGltIHRvIHByZXNlcnZlIHYzMCBuYW1lc3BhY2UgbmFtZXNcblx0X19leHBvcnRTdGFyKGV2ZW50cywgZXhwb3J0cyk7IFxufSAoT3BlbkZpbiQyKSk7XG5cbnZhciBPcGVuRmluID0gLypAX19QVVJFX18qL2dldERlZmF1bHRFeHBvcnRGcm9tQ2pzKE9wZW5GaW4kMik7XG5cbnZhciBPcGVuRmluJDEgPSAvKiNfX1BVUkVfXyovX21lcmdlTmFtZXNwYWNlcyh7XG5cdF9fcHJvdG9fXzogbnVsbCxcblx0ZGVmYXVsdDogT3BlbkZpblxufSwgW09wZW5GaW4kMl0pO1xuXG52YXIgZmluJDIgPSB7fTtcblxudmFyIHN5c3RlbSA9IHt9O1xuXG52YXIgYmFzZSA9IHt9O1xuXG52YXIgcHJvbWlzZXMgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb21pc2VzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnByb21pc2VzLnByb21pc2VNYXBTZXJpYWwgPSBwcm9taXNlcy5zZXJpYWwgPSBwcm9taXNlcy5wcm9taXNlTWFwID0gcHJvbWlzZXMucHJvbWlzaWZ5ID0gdm9pZCAwO1xuZnVuY3Rpb24gcHJvbWlzaWZ5KGZ1bmMpIHtcbiAgICByZXR1cm4gKC4uLmFyZ3MpID0+IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgZnVuYyguLi5hcmdzLCAoZXJyLCB2YWwpID0+IChlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUodmFsKSkpO1xuICAgIH0pO1xufVxucHJvbWlzZXMucHJvbWlzaWZ5ID0gcHJvbWlzaWZ5O1xuYXN5bmMgZnVuY3Rpb24gcHJvbWlzZU1hcChhcnIsIGFzeW5jRikge1xuICAgIHJldHVybiBQcm9taXNlLmFsbChhcnIubWFwKGFzeW5jRikpO1xufVxucHJvbWlzZXMucHJvbWlzZU1hcCA9IHByb21pc2VNYXA7XG5hc3luYyBmdW5jdGlvbiBzZXJpYWwoYXJyKSB7XG4gICAgY29uc3QgcmV0ID0gW107XG4gICAgZm9yIChjb25zdCBmdW5jIG9mIGFycikge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYXdhaXQtaW4tbG9vcFxuICAgICAgICBjb25zdCBuZXh0ID0gYXdhaXQgZnVuYygpO1xuICAgICAgICByZXQucHVzaChuZXh0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbn1cbnByb21pc2VzLnNlcmlhbCA9IHNlcmlhbDtcbmFzeW5jIGZ1bmN0aW9uIHByb21pc2VNYXBTZXJpYWwoYXJyLCBmdW5jKSB7XG4gICAgcmV0dXJuIHNlcmlhbChhcnIubWFwKCh2YWx1ZSwgaW5kZXgsIGFycmF5KSA9PiAoKSA9PiBmdW5jKHZhbHVlLCBpbmRleCwgYXJyYXkpKSk7XG59XG5wcm9taXNlcy5wcm9taXNlTWFwU2VyaWFsID0gcHJvbWlzZU1hcFNlcmlhbDtcblxudmFyIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkYyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcbn07XG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRlID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcbn07XG52YXIgX0VtaXR0ZXJCYXNlX2VtaXR0ZXJBY2Nlc3Nvcjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShiYXNlLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmJhc2UuUmVwbHkgPSBiYXNlLkVtaXR0ZXJCYXNlID0gYmFzZS5CYXNlID0gdm9pZCAwO1xuY29uc3QgcHJvbWlzZXNfMSA9IHByb21pc2VzO1xuY2xhc3MgQmFzZSB7XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iod2lyZSkge1xuICAgICAgICAvKipcbiAgICAgICAgICogQGludGVybmFsXG4gICAgICAgICAqIEBkZXByZWNhdGVkXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmlzTm9kZUVudmlyb25tZW50ID0gKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5lbnZpcm9ubWVudC50eXBlID09PSAnbm9kZSc7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAaW50ZXJuYWxcbiAgICAgICAgICogQGRlcHJlY2F0ZWRcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaXNPcGVuRmluRW52aXJvbm1lbnQgPSAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aXJlLmVudmlyb25tZW50LnR5cGUgPT09ICdvcGVuZmluJztcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBpbnRlcm5hbFxuICAgICAgICAgKiBAZGVwcmVjYXRlZFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5pc0Jyb3dzZXJFbnZpcm9ubWVudCA9ICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuZW52aXJvbm1lbnQudHlwZSA9PT0gJ290aGVyJztcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy53aXJlID0gd2lyZTtcbiAgICB9XG4gICAgZ2V0IGZpbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5nZXRGaW4oKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUHJvdmlkZXMgYWNjZXNzIHRvIHRoZSBPcGVuRmluIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBjdXJyZW50IGNvZGUgY29udGV4dCAodXN1YWxseSBhIGRvY3VtZW50XG4gICAgICogc3VjaCBhcyBhIHtAbGluayBPcGVuRmluLlZpZXd9IG9yIHtAbGluayBPcGVuRmluLldpbmRvd30pLCBhcyB3ZWxsIGFzIHRvIHRoZSBjdXJyZW50IGBJbnRlcm9wYCBjb250ZXh0LlxuICAgICAqXG4gICAgICogVXNlZnVsIGZvciBkZWJ1Z2dpbmcgaW4gdGhlIGRldnRvb2xzIGNvbnNvbGUsIHdoZXJlIHRoaXMgd2lsbCBpbnRlbGxpZ2VudGx5IHR5cGUgaXRzZWxmIGJhc2VkXG4gICAgICogb24gdGhlIGNvbnRleHQgaW4gd2hpY2ggdGhlIGRldnRvb2xzIHBhbmVsIHdhcyBvcGVuZWQuXG4gICAgICovXG4gICAgZ2V0IG1lKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLm1lO1xuICAgIH1cbn1cbmJhc2UuQmFzZSA9IEJhc2U7XG4vKipcbiAqIEFuIGVudGl0eSB0aGF0IGVtaXRzIE9wZW5GaW4gZXZlbnRzLlxuICpcbiAqIEByZW1hcmtzIEV2ZW50LWJpbmRpbmcgbWV0aG9kcyBhcmUgYXN5bmNocm9ub3VzIGFzIHRoZXkgbXVzdCBjcm9zcyBwcm9jZXNzIGJvdW5kYXJpZXNcbiAqIGFuZCBzZXR1cCB0aGUgbGlzdGVuZXIgaW4gdGhlIGJyb3dzZXIgcHJvY2Vzcy4gIFdoZW4gdGhlIGBFdmVudEVtaXR0ZXJgIHJlY2VpdmVzIGFuIGV2ZW50IGZyb20gdGhlIGJyb3dzZXIgcHJvY2Vzc1xuICogYW5kIGVtaXRzIG9uIHRoZSByZW5kZXJlciwgYWxsIG9mIHRoZSBmdW5jdGlvbnMgYXR0YWNoZWQgdG8gdGhhdCBzcGVjaWZpYyBldmVudCBhcmUgY2FsbGVkIHN5bmNocm9ub3VzbHkuICBBbnkgdmFsdWVzXG4gKiByZXR1cm5lZCBieSB0aGUgY2FsbGVkIGxpc3RlbmVycyBhcmUgaWdub3JlZCBhbmQgd2lsbCBiZSBkaXNjYXJkZWQuICBJZiB0aGUgZXhlY3V0aW9uIGNvbnRleHQgb2YgdGhlIHdpbmRvdyBpcyBkZXN0cm95ZWRcbiAqIGJ5IHBhZ2UgbmF2aWdhdGlvbiBvciByZWxvYWQsIGFueSBldmVudHMgdGhhdCBoYXZlIGJlZW4gc2V0dXAgaW4gdGhhdCBjb250ZXh0IHdpbGwgYmUgZGVzdHJveWVkLlxuICpcbiAqIEl0IGlzIGltcG9ydGFudCB0byBrZWVwIGluIG1pbmQgdGhhdCB3aGVuIGFuIG9yZGluYXJ5IGxpc3RlbmVyIGZ1bmN0aW9uIGlzIGNhbGxlZCwgdGhlIHN0YW5kYXJkIGB0aGlzYCBrZXl3b3JkIGlzIGludGVudGlvbmFsbHlcbiAqIHNldCB0byByZWZlcmVuY2UgdGhlIGBFdmVudEVtaXR0ZXJgIGluc3RhbmNlIHRvIHdoaWNoIHRoZSBsaXN0ZW5lciBpcyBhdHRhY2hlZC4gIEl0IGlzIHBvc3NpYmxlIHRvIHVzZSBFUzYgQXJyb3cgRnVuY3Rpb25zIGFzXG4gKiBsaXN0ZW5lcnMsIGhvd2V2ZXIsIHdoZW4gZG9pbmcgc28sIHRoZSBgdGhpc2Aga2V5d29yZCB3aWxsIG5vIGxvbmdlciByZWZlcmVuY2UgdGhlIGBFdmVudEVtaXR0ZXJgIGluc3RhbmNlLlxuICpcbiAqIEV2ZW50cyByZS1wcm9wYWdhdGUgZnJvbSBzbWFsbGVyL21vcmUtbG9jYWwgc2NvcGVzIHRvIGxhcmdlci9tb3JlLWdsb2JhbCBzY29wZXMuICBGb3IgZXhhbXBsZSwgYW4gZXZlbnQgZW1pdHRlZCBvbiBhIHNwZWNpZmljXG4gKiB2aWV3IHdpbGwgcHJvcGFnYXRlIHRvIHRoZSB3aW5kb3cgaW4gd2hpY2ggdGhlIHZpZXcgaXMgZW1iZWRkZWQsIGFuZCB0aGVuIHRvIHRoZSBhcHBsaWNhdGlvbiBpbiB3aGljaCB0aGUgd2luZG93IGlzIHJ1bm5pbmcsIGFuZFxuICogZmluYWxseSB0byB0aGUgT3BlbkZpbiBydW50aW1lIGl0c2VsZiBhdCB0aGUgXCJzeXN0ZW1cIiBsZXZlbC4gIFJlLXByb3BhZ2F0ZWQgZXZlbnRzIGFyZSBwcmVmaXhlZCB3aXRoIHRoZSBuYW1lIG9mIHRoZSBzY29wZSBpbiB3aGljaFxuICogdGhleSBvcmlnaW5hdGVkIC0gZm9yIGV4YW1wbGUsIGEgXCJzaG93blwiIGV2ZW50IGVtaXR0ZWQgb24gYSB2aWV3IHdpbGwgYmUgcmUtcHJvcGFnYXRlZCBhdCB0aGUgd2luZG93IGxldmVsIGFzIFwidmlldy1zaG93blwiLCBhbmRcbiAqIHRoZW4gdG8gdGhlIGFwcGxpY2F0aW9uIGFzIFwid2luZG93LXZpZXctc2hvd25cIiwgYW5kIGZpbmFsbHkgYXQgdGhlIHN5c3RlbSBsZXZlbCBhcyBcImFwcGxpY2F0aW9uLXdpbmRvdy12aWV3LXNob3duXCIuXG4gKlxuICogQWxsIGV2ZW50IHByb3BhZ2F0aW9ucyBhcmUgdmlzaWJsZSBhdCB0aGUgU3lzdGVtIGxldmVsLCByZWdhcmRsZXNzIG9mIHNvdXJjZSwgc28gdHJhbnNpdGl2ZSByZS1wcm9wYWdhdGlvbnMgKGUuZy4gZnJvbSB2aWV3IHRvIHdpbmRvd1xuICogdG8gYXBwbGljYXRpb24pIGFyZSB2aXNpYmxlIGluIHRoZWlyIGVudGlyZXR5IGF0IHRoZSBzeXN0ZW0gbGV2ZWwuICBTbywgd2UgY2FuIGxpc3RlbiB0byB0aGUgYWJvdmUgZXZlbnQgYXMgXCJzaG93blwiLCBcInZpZXctc2hvd25cIixcbiAqIFwid2luZG93LXZpZXctc2hvd25cIiwgb3IgXCJhcHBsaWNhdGlvbi13aW5kb3ctdmlldy1zaG93bi5cIlxuICovXG5jbGFzcyBFbWl0dGVyQmFzZSBleHRlbmRzIEJhc2Uge1xuICAgIGNvbnN0cnVjdG9yKHdpcmUsIHRvcGljLCAuLi5hZGRpdGlvbmFsQWNjZXNzb3JzKSB7XG4gICAgICAgIHN1cGVyKHdpcmUpO1xuICAgICAgICB0aGlzLnRvcGljID0gdG9waWM7XG4gICAgICAgIF9FbWl0dGVyQmFzZV9lbWl0dGVyQWNjZXNzb3Iuc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIHRoaXMuZXZlbnROYW1lcyA9ICgpID0+ICh0aGlzLmhhc0VtaXR0ZXIoKSA/IHRoaXMuZ2V0T3JDcmVhdGVFbWl0dGVyKCkuZXZlbnROYW1lcygpIDogW10pO1xuICAgICAgICAvKipcbiAgICAgICAgICogQGludGVybmFsXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmVtaXQgPSAoZXZlbnRUeXBlLCBwYXlsb2FkLCAuLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5oYXNFbWl0dGVyKCkgPyB0aGlzLmdldE9yQ3JlYXRlRW1pdHRlcigpLmVtaXQoZXZlbnRUeXBlLCBwYXlsb2FkLCAuLi5hcmdzKSA6IGZhbHNlO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhc0VtaXR0ZXIgPSAoKSA9PiB0aGlzLndpcmUuZXZlbnRBZ2dyZWdhdG9yLmhhcyhfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGUodGhpcywgX0VtaXR0ZXJCYXNlX2VtaXR0ZXJBY2Nlc3NvciwgXCJmXCIpKTtcbiAgICAgICAgdGhpcy5nZXRPckNyZWF0ZUVtaXR0ZXIgPSAoKSA9PiB0aGlzLndpcmUuZXZlbnRBZ2dyZWdhdG9yLmdldE9yQ3JlYXRlKF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZSh0aGlzLCBfRW1pdHRlckJhc2VfZW1pdHRlckFjY2Vzc29yLCBcImZcIikpO1xuICAgICAgICB0aGlzLmxpc3RlbmVycyA9ICh0eXBlKSA9PiB0aGlzLmhhc0VtaXR0ZXIoKSA/IHRoaXMuZ2V0T3JDcmVhdGVFbWl0dGVyKCkubGlzdGVuZXJzKHR5cGUpIDogW107XG4gICAgICAgIHRoaXMubGlzdGVuZXJDb3VudCA9ICh0eXBlKSA9PiB0aGlzLmhhc0VtaXR0ZXIoKSA/IHRoaXMuZ2V0T3JDcmVhdGVFbWl0dGVyKCkubGlzdGVuZXJDb3VudCh0eXBlKSA6IDA7XG4gICAgICAgIHRoaXMucmVnaXN0ZXJFdmVudExpc3RlbmVyID0gYXN5bmMgKGV2ZW50VHlwZSwgb3B0aW9ucyA9IHt9LCBhcHBseVN1YnNjcmlwdGlvbiwgdW5kb1N1YnNjcmlwdGlvbikgPT4ge1xuICAgICAgICAgICAgY29uc3QgcnVudGltZUV2ZW50ID0ge1xuICAgICAgICAgICAgICAgIC4uLnRoaXMuaWRlbnRpdHksXG4gICAgICAgICAgICAgICAgdGltZXN0YW1wOiBvcHRpb25zLnRpbWVzdGFtcCB8fCBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgIHRvcGljOiB0aGlzLnRvcGljLFxuICAgICAgICAgICAgICAgIHR5cGU6IGV2ZW50VHlwZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IGVtaXR0ZXIgPSB0aGlzLmdldE9yQ3JlYXRlRW1pdHRlcigpO1xuICAgICAgICAgICAgLy8gV2UgYXBwbHkgdGhlIHN1YnNjcmlwdGlvbiBhbmQgdGhlbiB1bmRvIGlmIHRoZSBhc3luYyBjYWxsIGZhaWxzIHRvIGF2b2lkXG4gICAgICAgICAgICAvLyBpbmRldGVybWluYWN5IGluIHN1YnNjcmlwdGlvbiBhcHBsaWNhdGlvbiBvcmRlciwgd2hpY2ggY2FuIGJyZWFrIHRoaW5ncyBlbHNld2hlcmVcbiAgICAgICAgICAgIGFwcGx5U3Vic2NyaXB0aW9uKGVtaXR0ZXIpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc3Vic2NyaWJlLXRvLWRlc2t0b3AtZXZlbnQnLCBydW50aW1lRXZlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICB1bmRvU3Vic2NyaXB0aW9uKGVtaXR0ZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVsZXRlRW1pdHRlcklmTm90aGluZ1JlZ2lzdGVyZWQoZW1pdHRlcik7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kZXJlZ2lzdGVyRXZlbnRMaXN0ZW5lciA9IGFzeW5jIChldmVudFR5cGUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuaGFzRW1pdHRlcigpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcnVudGltZUV2ZW50ID0ge1xuICAgICAgICAgICAgICAgICAgICAuLi50aGlzLmlkZW50aXR5LFxuICAgICAgICAgICAgICAgICAgICB0aW1lc3RhbXA6IG9wdGlvbnMudGltZXN0YW1wIHx8IERhdGUubm93KCksXG4gICAgICAgICAgICAgICAgICAgIHRvcGljOiB0aGlzLnRvcGljLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiBldmVudFR5cGVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCd1bnN1YnNjcmliZS10by1kZXNrdG9wLWV2ZW50JywgcnVudGltZUV2ZW50KS5jYXRjaCgoKSA9PiBudWxsKTtcbiAgICAgICAgICAgICAgICBjb25zdCBlbWl0dGVyID0gdGhpcy5nZXRPckNyZWF0ZUVtaXR0ZXIoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZW1pdHRlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFRoaXMgd2lsbCBvbmx5IGJlIHJlYWNoZWQgaWYgdW5zdWJzY3JpYmUgZnJvbSBldmVudCB0aGF0IGRvZXMgbm90IGV4aXN0IGJ1dCBkbyBub3Qgd2FudCB0byBlcnJvciBoZXJlXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkYyh0aGlzLCBfRW1pdHRlckJhc2VfZW1pdHRlckFjY2Vzc29yLCBbdG9waWMsIC4uLmFkZGl0aW9uYWxBY2Nlc3NvcnNdLCBcImZcIik7XG4gICAgICAgIHRoaXMubGlzdGVuZXJzID0gKGV2ZW50KSA9PiB0aGlzLmhhc0VtaXR0ZXIoKSA/IHRoaXMuZ2V0T3JDcmVhdGVFbWl0dGVyKCkubGlzdGVuZXJzKGV2ZW50KSA6IFtdO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqXG4gICAgICogQHJlbWFya3MgRXZlbnQgcGF5bG9hZHMgYXJlIGRvY3VtZW50ZWQgaW4gdGhlIHtAbGluayBPcGVuRmluLkV2ZW50c30gbmFtZXNwYWNlLlxuICAgICAqL1xuICAgIGFzeW5jIG9uKGV2ZW50VHlwZSwgbGlzdGVuZXIsIG9wdGlvbnMpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5yZWdpc3RlckV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBvcHRpb25zLCAoZW1pdHRlcikgPT4ge1xuICAgICAgICAgICAgZW1pdHRlci5vbihldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICAgICAgfSwgKGVtaXR0ZXIpID0+IHtcbiAgICAgICAgICAgIGVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBlbmQgb2YgdGhlIGxpc3RlbmVycyBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKi9cbiAgICBhc3luYyBhZGRMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9uKGV2ZW50VHlwZSwgbGlzdGVuZXIsIG9wdGlvbnMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgb25lIHRpbWUgbGlzdGVuZXIgZm9yIHRoZSBldmVudC4gVGhlIGxpc3RlbmVyIGlzIGludm9rZWQgb25seSB0aGUgZmlyc3QgdGltZSB0aGUgZXZlbnQgaXMgZmlyZWQsIGFmdGVyIHdoaWNoIGl0IGlzIHJlbW92ZWQuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBFdmVudCBwYXlsb2FkcyBhcmUgZG9jdW1lbnRlZCBpbiB0aGUge0BsaW5rIE9wZW5GaW4uRXZlbnRzfSBuYW1lc3BhY2UuXG4gICAgICovXG4gICAgYXN5bmMgb25jZShldmVudFR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGRlcmVnaXN0ZXIgPSAoKSA9PiB0aGlzLmRlcmVnaXN0ZXJFdmVudExpc3RlbmVyKGV2ZW50VHlwZSk7XG4gICAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgb3B0aW9ucywgKGVtaXR0ZXIpID0+IHtcbiAgICAgICAgICAgIGVtaXR0ZXIub25jZShldmVudFR5cGUsIGRlcmVnaXN0ZXIpO1xuICAgICAgICAgICAgZW1pdHRlci5vbmNlKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICB9LCAoZW1pdHRlcikgPT4ge1xuICAgICAgICAgICAgZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihldmVudFR5cGUsIGRlcmVnaXN0ZXIpO1xuICAgICAgICAgICAgZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGJlZ2lubmluZyBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqXG4gICAgICogQHJlbWFya3MgRXZlbnQgcGF5bG9hZHMgYXJlIGRvY3VtZW50ZWQgaW4gdGhlIHtAbGluayBPcGVuRmluLkV2ZW50c30gbmFtZXNwYWNlLlxuICAgICAqL1xuICAgIGFzeW5jIHByZXBlbmRMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKSB7XG4gICAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgb3B0aW9ucywgKGVtaXR0ZXIpID0+IHtcbiAgICAgICAgICAgIGVtaXR0ZXIucHJlcGVuZExpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICB9LCAoZW1pdHRlcikgPT4ge1xuICAgICAgICAgICAgZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgb25lIHRpbWUgbGlzdGVuZXIgZm9yIHRoZSBldmVudC4gVGhlIGxpc3RlbmVyIGlzIGludm9rZWQgb25seSB0aGUgZmlyc3QgdGltZSB0aGUgZXZlbnQgaXMgZmlyZWQsXG4gICAgICogYWZ0ZXIgd2hpY2ggaXQgaXMgcmVtb3ZlZC4gVGhlIGxpc3RlbmVyIGlzIGFkZGVkIHRvIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGxpc3RlbmVycyBhcnJheS5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIEV2ZW50IHBheWxvYWRzIGFyZSBkb2N1bWVudGVkIGluIHRoZSB7QGxpbmsgT3BlbkZpbi5FdmVudHN9IG5hbWVzcGFjZS5cbiAgICAgKi9cbiAgICBhc3luYyBwcmVwZW5kT25jZUxpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgZGVyZWdpc3RlciA9ICgpID0+IHRoaXMuZGVyZWdpc3RlckV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlKTtcbiAgICAgICAgYXdhaXQgdGhpcy5yZWdpc3RlckV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBvcHRpb25zLCAoZW1pdHRlcikgPT4ge1xuICAgICAgICAgICAgZW1pdHRlci5wcmVwZW5kT25jZUxpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgZW1pdHRlci5vbmNlKGV2ZW50VHlwZSwgZGVyZWdpc3Rlcik7XG4gICAgICAgIH0sIChlbWl0dGVyKSA9PiB7XG4gICAgICAgICAgICBlbWl0dGVyLnJlbW92ZUxpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihldmVudFR5cGUsIGRlcmVnaXN0ZXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbW92ZSBhIGxpc3RlbmVyIGZyb20gdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqXG4gICAgICogQHJlbWFya3MgQ2F1dGlvbjogQ2FsbGluZyB0aGlzIG1ldGhvZCBjaGFuZ2VzIHRoZSBhcnJheSBpbmRpY2VzIGluIHRoZSBsaXN0ZW5lciBhcnJheSBiZWhpbmQgdGhlIGxpc3RlbmVyLlxuICAgICAqL1xuICAgIGFzeW5jIHJlbW92ZUxpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgZW1pdHRlciA9IGF3YWl0IHRoaXMuZGVyZWdpc3RlckV2ZW50TGlzdGVuZXIoZXZlbnRUeXBlLCBvcHRpb25zKTtcbiAgICAgICAgaWYgKGVtaXR0ZXIpIHtcbiAgICAgICAgICAgIGVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICB0aGlzLmRlbGV0ZUVtaXR0ZXJJZk5vdGhpbmdSZWdpc3RlcmVkKGVtaXR0ZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBhc3luYyBkZXJlZ2lzdGVyQWxsTGlzdGVuZXJzKGV2ZW50VHlwZSkge1xuICAgICAgICBjb25zdCBydW50aW1lRXZlbnQgPSB7IC4uLnRoaXMuaWRlbnRpdHksIHR5cGU6IGV2ZW50VHlwZSwgdG9waWM6IHRoaXMudG9waWMgfTtcbiAgICAgICAgaWYgKHRoaXMuaGFzRW1pdHRlcigpKSB7XG4gICAgICAgICAgICBjb25zdCBlbWl0dGVyID0gdGhpcy5nZXRPckNyZWF0ZUVtaXR0ZXIoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlZkNvdW50ID0gZW1pdHRlci5saXN0ZW5lckNvdW50KHJ1bnRpbWVFdmVudC50eXBlKTtcbiAgICAgICAgICAgIGNvbnN0IHVuc3Vic2NyaWJlUHJvbWlzZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVmQ291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgIHVuc3Vic2NyaWJlUHJvbWlzZXMucHVzaCh0aGlzLndpcmUuc2VuZEFjdGlvbigndW5zdWJzY3JpYmUtdG8tZGVza3RvcC1ldmVudCcsIHJ1bnRpbWVFdmVudCkuY2F0Y2goKCkgPT4gbnVsbCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwodW5zdWJzY3JpYmVQcm9taXNlcyk7XG4gICAgICAgICAgICByZXR1cm4gZW1pdHRlcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMsIG9yIHRob3NlIG9mIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICpcbiAgICAgKi9cbiAgICBhc3luYyByZW1vdmVBbGxMaXN0ZW5lcnMoZXZlbnRUeXBlKSB7XG4gICAgICAgIGNvbnN0IHJlbW92ZUJ5RXZlbnQgPSBhc3luYyAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVtaXR0ZXIgPSBhd2FpdCB0aGlzLmRlcmVnaXN0ZXJBbGxMaXN0ZW5lcnMoZXZlbnQpO1xuICAgICAgICAgICAgaWYgKGVtaXR0ZXIpIHtcbiAgICAgICAgICAgICAgICBlbWl0dGVyLnJlbW92ZUFsbExpc3RlbmVycyhldmVudCk7XG4gICAgICAgICAgICAgICAgdGhpcy5kZWxldGVFbWl0dGVySWZOb3RoaW5nUmVnaXN0ZXJlZChlbWl0dGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGV2ZW50VHlwZSkge1xuICAgICAgICAgICAgYXdhaXQgcmVtb3ZlQnlFdmVudChldmVudFR5cGUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHRoaXMuaGFzRW1pdHRlcigpKSB7XG4gICAgICAgICAgICBjb25zdCBldmVudHMgPSB0aGlzLmdldE9yQ3JlYXRlRW1pdHRlcigpLmV2ZW50TmFtZXMoKTtcbiAgICAgICAgICAgIGF3YWl0ICgwLCBwcm9taXNlc18xLnByb21pc2VNYXApKGV2ZW50cywgcmVtb3ZlQnlFdmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGRlbGV0ZUVtaXR0ZXJJZk5vdGhpbmdSZWdpc3RlcmVkKGVtaXR0ZXIpIHtcbiAgICAgICAgaWYgKGVtaXR0ZXIuZXZlbnROYW1lcygpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy53aXJlLmV2ZW50QWdncmVnYXRvci5kZWxldGUoX19jbGFzc1ByaXZhdGVGaWVsZEdldCRlKHRoaXMsIF9FbWl0dGVyQmFzZV9lbWl0dGVyQWNjZXNzb3IsIFwiZlwiKSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5iYXNlLkVtaXR0ZXJCYXNlID0gRW1pdHRlckJhc2U7XG5fRW1pdHRlckJhc2VfZW1pdHRlckFjY2Vzc29yID0gbmV3IFdlYWtNYXAoKTtcbmNsYXNzIFJlcGx5IHtcbn1cbmJhc2UuUmVwbHkgPSBSZXBseTtcblxudmFyIHRyYW5zcG9ydEVycm9ycyA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkodHJhbnNwb3J0RXJyb3JzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnRyYW5zcG9ydEVycm9ycy5SdW50aW1lRXJyb3IgPSB0cmFuc3BvcnRFcnJvcnMuTm90U3VwcG9ydGVkRXJyb3IgPSB0cmFuc3BvcnRFcnJvcnMuTm90SW1wbGVtZW50ZWRFcnJvciA9IHRyYW5zcG9ydEVycm9ycy5Ob0Fja0Vycm9yID0gdHJhbnNwb3J0RXJyb3JzLkR1cGxpY2F0ZUNvcnJlbGF0aW9uRXJyb3IgPSB0cmFuc3BvcnRFcnJvcnMuVW5leHBlY3RlZEFjdGlvbkVycm9yID0gdHJhbnNwb3J0RXJyb3JzLkRpc2Nvbm5lY3RlZEVycm9yID0gdm9pZCAwO1xuY2xhc3MgRGlzY29ubmVjdGVkRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IocmVhZHlTdGF0ZSkge1xuICAgICAgICBzdXBlcihgRXhwZWN0ZWQgd2Vic29ja2V0IHN0YXRlIE9QRU4gYnV0IGZvdW5kICR7cmVhZHlTdGF0ZX1gKTtcbiAgICAgICAgdGhpcy5yZWFkeVN0YXRlID0gcmVhZHlTdGF0ZTtcbiAgICB9XG59XG50cmFuc3BvcnRFcnJvcnMuRGlzY29ubmVjdGVkRXJyb3IgPSBEaXNjb25uZWN0ZWRFcnJvcjtcbmNsYXNzIFVuZXhwZWN0ZWRBY3Rpb25FcnJvciBleHRlbmRzIEVycm9yIHtcbn1cbnRyYW5zcG9ydEVycm9ycy5VbmV4cGVjdGVkQWN0aW9uRXJyb3IgPSBVbmV4cGVjdGVkQWN0aW9uRXJyb3I7XG5jbGFzcyBEdXBsaWNhdGVDb3JyZWxhdGlvbkVycm9yIGV4dGVuZHMgRXJyb3Ige1xufVxudHJhbnNwb3J0RXJyb3JzLkR1cGxpY2F0ZUNvcnJlbGF0aW9uRXJyb3IgPSBEdXBsaWNhdGVDb3JyZWxhdGlvbkVycm9yO1xuY2xhc3MgTm9BY2tFcnJvciBleHRlbmRzIEVycm9yIHtcbn1cbnRyYW5zcG9ydEVycm9ycy5Ob0Fja0Vycm9yID0gTm9BY2tFcnJvcjtcbmNsYXNzIE5vdEltcGxlbWVudGVkRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG59XG50cmFuc3BvcnRFcnJvcnMuTm90SW1wbGVtZW50ZWRFcnJvciA9IE5vdEltcGxlbWVudGVkRXJyb3I7XG5jbGFzcyBOb3RTdXBwb3J0ZWRFcnJvciBleHRlbmRzIEVycm9yIHtcbn1cbnRyYW5zcG9ydEVycm9ycy5Ob3RTdXBwb3J0ZWRFcnJvciA9IE5vdFN1cHBvcnRlZEVycm9yO1xuY2xhc3MgSW50ZXJuYWxFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3RvcihlcnIpIHtcbiAgICAgICAgY29uc3QgeyBtZXNzYWdlLCBuYW1lLCBzdGFjaywgLi4ucmVzdCB9ID0gZXJyO1xuICAgICAgICBzdXBlcihtZXNzYWdlKTtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZSB8fCAnRXJyb3InO1xuICAgICAgICB0aGlzLnN0YWNrID0gc3RhY2sgPz8gdGhpcy50b1N0cmluZygpO1xuICAgICAgICBPYmplY3Qua2V5cyhyZXN0KS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICB0aGlzW2tleV0gPSByZXN0W2tleV07XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbi8vIEZvciBkb2N1bWVudGF0aW9uIG9mIHRoZSBlcnJvciBtZXRob2RzIGJlaW5nIHVzZWQgc2VlIGhlcmU6IGh0dHBzOi8vdjguZGV2L2RvY3Mvc3RhY2stdHJhY2UtYXBpXG5jbGFzcyBSdW50aW1lRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgc3RhdGljIGdldENhbGxTaXRlKGNhbGxzVG9SZW1vdmUgPSAwKSB7XG4gICAgICAgIGNvbnN0IGxlbmd0aCA9IEVycm9yLnN0YWNrVHJhY2VMaW1pdDtcbiAgICAgICAgY29uc3QgcmVhbENhbGxzVG9SZW1vdmUgPSBjYWxsc1RvUmVtb3ZlICsgMTsgLy8gcmVtb3ZlIHRoaXMgY2FsbDtcbiAgICAgICAgRXJyb3Iuc3RhY2tUcmFjZUxpbWl0ID0gbGVuZ3RoICsgcmVhbENhbGxzVG9SZW1vdmU7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlcnNjb3JlLWRhbmdsZVxuICAgICAgICBjb25zdCBfcHJlcGFyZVN0YWNrVHJhY2UgPSBFcnJvci5wcmVwYXJlU3RhY2tUcmFjZTtcbiAgICAgICAgLy8gVGhpcyB3aWxsIGJlIGNhbGxlZCB3aGVuIHdlIGFjY2VzcyB0aGUgYHN0YWNrYCBwcm9wZXJ0eVxuICAgICAgICBFcnJvci5wcmVwYXJlU3RhY2tUcmFjZSA9IChfLCBzdGFjaykgPT4gc3RhY2s7XG4gICAgICAgIC8vIHN0YWNrIGlzIG9wdGlvbmFsIGluIG5vbiBjaHJvbWl1bSBjb250ZXh0c1xuICAgICAgICBjb25zdCBzdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrPy5zbGljZShyZWFsQ2FsbHNUb1JlbW92ZSkgPz8gW107XG4gICAgICAgIEVycm9yLnByZXBhcmVTdGFja1RyYWNlID0gX3ByZXBhcmVTdGFja1RyYWNlO1xuICAgICAgICBFcnJvci5zdGFja1RyYWNlTGltaXQgPSBsZW5ndGg7XG4gICAgICAgIHJldHVybiBzdGFjaztcbiAgICB9XG4gICAgc3RhdGljIHByZXBhcmVTdGFja1RyYWNlKGVyciwgY2FsbFNpdGVzKSB7XG4gICAgICAgIGlmICh0eXBlb2YgRXJyb3IucHJlcGFyZVN0YWNrVHJhY2UgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJldHVybiBFcnJvci5wcmVwYXJlU3RhY2tUcmFjZShlcnIsIGNhbGxTaXRlcyk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHN0cmluZyA9IFwiXCI7XG4gICAgICAgIHN0cmluZyArPSBlcnIubmFtZSB8fCBcIkVycm9yXCI7XG4gICAgICAgIHN0cmluZyArPSBgOiAke2Vyci5tZXNzYWdlIHx8IFwiXCJ9YDtcbiAgICAgICAgZm9yIChjb25zdCBjYWxsU2l0ZSBvZiBjYWxsU2l0ZXMpIHtcbiAgICAgICAgICAgIHN0cmluZyArPSBgXFxuICAgIGF0ICR7Y2FsbFNpdGUudG9TdHJpbmcoKX1gO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgfVxuICAgIDtcbiAgICBjb25zdHJ1Y3RvcihwYXlsb2FkLCBjYWxsU2l0ZXMpIHtcbiAgICAgICAgY29uc3QgeyByZWFzb24sIGVycm9yIH0gPSBwYXlsb2FkO1xuICAgICAgICBzdXBlcihyZWFzb24pO1xuICAgICAgICB0aGlzLm5hbWUgPSAnUnVudGltZUVycm9yJztcbiAgICAgICAgaWYgKGVycm9yPy5zdGFjaykge1xuICAgICAgICAgICAgdGhpcy5jYXVzZSA9IG5ldyBJbnRlcm5hbEVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2FsbFNpdGVzKSB7XG4gICAgICAgICAgICB0aGlzLnN0YWNrID0gUnVudGltZUVycm9yLnByZXBhcmVTdGFja1RyYWNlKHRoaXMsIGNhbGxTaXRlcyk7XG4gICAgICAgIH1cbiAgICB9XG59XG50cmFuc3BvcnRFcnJvcnMuUnVudGltZUVycm9yID0gUnVudGltZUVycm9yO1xuXG52YXIgd2luZG93JDEgPSB7fTtcblxudmFyIEZhY3RvcnkkOCA9IHt9O1xuXG52YXIgdmFsaWRhdGUgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHZhbGlkYXRlLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnZhbGlkYXRlLnZhbGlkYXRlSWRlbnRpdHkgPSB2b2lkIDA7XG5mdW5jdGlvbiB2YWxpZGF0ZUlkZW50aXR5KGlkZW50aXR5KSB7XG4gICAgbGV0IGVycm9yTXNnO1xuICAgIGlmICh0eXBlb2YgaWRlbnRpdHkgIT09ICdvYmplY3QnIHx8IHR5cGVvZiBpZGVudGl0eS51dWlkICE9PSAnc3RyaW5nJykge1xuICAgICAgICBlcnJvck1zZyA9ICdOb3QgYSB2YWxpZCBpZGVudGl0eSBvYmplY3QnO1xuICAgIH1cbiAgICByZXR1cm4gZXJyb3JNc2c7XG59XG52YWxpZGF0ZS52YWxpZGF0ZUlkZW50aXR5ID0gdmFsaWRhdGVJZGVudGl0eTtcblxudmFyIEluc3RhbmNlJDcgPSB7fTtcblxudmFyIGFwcGxpY2F0aW9uID0ge307XG5cbnZhciBGYWN0b3J5JDcgPSB7fTtcblxudmFyIEluc3RhbmNlJDYgPSB7fTtcblxudmFyIHZpZXcgPSB7fTtcblxudmFyIEZhY3RvcnkkNiA9IHt9O1xuXG52YXIgd2FybmluZ3MgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHdhcm5pbmdzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbndhcm5pbmdzLmhhbmRsZURlcHJlY2F0ZWRXYXJuaW5ncyA9IHZvaWQgMDtcbmNvbnN0IGhhbmRsZURlcHJlY2F0ZWRXYXJuaW5ncyA9IChvcHRpb25zKSA9PiB7XG4gICAgaWYgKG9wdGlvbnMuY29udGVudE5hdmlnYXRpb24/LndoaXRlbGlzdCB8fFxuICAgICAgICBvcHRpb25zLmNvbnRlbnROYXZpZ2F0aW9uPy5ibGFja2xpc3QgfHxcbiAgICAgICAgb3B0aW9ucy5jb250ZW50UmVkaXJlY3Q/LndoaXRlbGlzdCB8fFxuICAgICAgICBvcHRpb25zLmNvbnRlbnRSZWRpcmVjdD8uYmxhY2tsaXN0KSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgVGhlIHByb3BlcnRpZXMgJ3doaXRlbGlzdCcgYW5kICdibGFja2xpc3QnIGhhdmUgYmVlbiBtYXJrZWQgYXMgZGVwcmVjYXRlZCBhbmQgd2lsbCBiZSByZW1vdmVkIGluIGEgZnV0dXJlIHZlcnNpb24uIFBsZWFzZSB1c2UgJ2FsbG93bGlzdCcgYW5kICdkZW55bGlzdCcuYCk7XG4gICAgfVxufTtcbndhcm5pbmdzLmhhbmRsZURlcHJlY2F0ZWRXYXJuaW5ncyA9IGhhbmRsZURlcHJlY2F0ZWRXYXJuaW5ncztcblxudmFyIGhhc1JlcXVpcmVkRmFjdG9yeSQzO1xuXG5mdW5jdGlvbiByZXF1aXJlRmFjdG9yeSQzICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkRmFjdG9yeSQzKSByZXR1cm4gRmFjdG9yeSQ2O1xuXHRoYXNSZXF1aXJlZEZhY3RvcnkkMyA9IDE7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShGYWN0b3J5JDYsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRGYWN0b3J5JDYuVmlld01vZHVsZSA9IHZvaWQgMDtcblx0Y29uc3QgYmFzZV8xID0gYmFzZTtcblx0Y29uc3QgdmFsaWRhdGVfMSA9IHZhbGlkYXRlO1xuXHRjb25zdCBpbmRleF8xID0gcmVxdWlyZVZpZXcoKTtcblx0Y29uc3Qgd2FybmluZ3NfMSA9IHdhcm5pbmdzO1xuXHQvKipcblx0ICogU3RhdGljIG5hbWVzcGFjZSBmb3IgT3BlbkZpbiBBUEkgbWV0aG9kcyB0aGF0IGludGVyYWN0IHdpdGggdGhlIHtAbGluayBWaWV3fSBjbGFzcywgYXZhaWxhYmxlIHVuZGVyIGBmaW4uVmlld2AuXG5cdCAqL1xuXHRjbGFzcyBWaWV3TW9kdWxlIGV4dGVuZHMgYmFzZV8xLkJhc2Uge1xuXHQgICAgLyoqXG5cdCAgICAgKiBDcmVhdGVzIGEgbmV3IFZpZXcuXG5cdCAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIFZpZXcgY3JlYXRpb24gb3B0aW9uc1xuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogbGV0IHZpZXc7XG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVWaWV3KCkge1xuXHQgICAgICogICAgIGNvbnN0IG1lID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGZpbi5WaWV3LmNyZWF0ZSh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZUNyZWF0ZScsXG5cdCAgICAgKiAgICAgICAgIHRhcmdldDogbWUuaWRlbnRpdHksXG5cdCAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBjcmVhdGVWaWV3KClcblx0ICAgICAqICAgICAudGhlbigoY3JlYXRlZFZpZXcpID0+IHtcblx0ICAgICAqICAgICAgICAgdmlldyA9IGNyZWF0ZWRWaWV3O1xuXHQgICAgICogICAgICAgICBjb25zb2xlLmxvZygnVmlldyBjcmVhdGVkLicsIHZpZXcpO1xuXHQgICAgICogICAgICAgICB2aWV3Lm5hdmlnYXRlKCdodHRwczovL2dvb2dsZS5jb20nKTtcblx0ICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ1ZpZXcgbmF2aWdhdGVkIHRvIGdpdmVuIHVybC4nKTtcblx0ICAgICAqICAgICB9KVxuXHQgICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqIE5vdGUgdGhhdCBjcmVhdGVkIHZpZXdzIG5lZWRzIHRvIG5hdmlnYXRlIHNvbWV3aGVyZSBmb3IgdGhlbSB0byBhY3R1YWxseSByZW5kZXIgYSB3ZWJzaXRlLlxuXHQgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICovXG5cdCAgICBhc3luYyBjcmVhdGUob3B0aW9ucykge1xuXHQgICAgICAgIGNvbnN0IHsgdXVpZCB9ID0gdGhpcy53aXJlLm1lO1xuXHQgICAgICAgIGlmICghb3B0aW9ucy5uYW1lIHx8IHR5cGVvZiBvcHRpb25zLm5hbWUgIT09ICdzdHJpbmcnKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGxlYXNlIHByb3ZpZGUgYSBuYW1lIHByb3BlcnR5IGFzIGEgc3RyaW5nIGluIG9yZGVyIHRvIGNyZWF0ZSBhIFZpZXcuJyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgICgwLCB3YXJuaW5nc18xLmhhbmRsZURlcHJlY2F0ZWRXYXJuaW5ncykob3B0aW9ucyk7XG5cdCAgICAgICAgaWYgKHRoaXMud2lyZS5lbnZpcm9ubWVudC5jaGlsZFZpZXdzKSB7XG5cdCAgICAgICAgICAgIGF3YWl0IHRoaXMud2lyZS5lbnZpcm9ubWVudC5jcmVhdGVDaGlsZENvbnRlbnQoe1xuXHQgICAgICAgICAgICAgICAgZW50aXR5VHlwZTogJ3ZpZXcnLFxuXHQgICAgICAgICAgICAgICAgb3B0aW9uczogeyAuLi5vcHRpb25zLCB1dWlkIH1cblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignY3JlYXRlLXZpZXcnLCB7IC4uLm9wdGlvbnMsIHV1aWQgfSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiB0aGlzLndyYXBTeW5jKHsgdXVpZCwgbmFtZTogb3B0aW9ucy5uYW1lIH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBBc3luY2hyb25vdXNseSByZXR1cm5zIGFuIEFQSSBoYW5kbGUgZm9yIHRoZSBnaXZlbiBWaWV3IGlkZW50aXR5LlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFdyYXBwaW5nIGEgVmlldyBpZGVudGl0eSB0aGF0IGRvZXMgbm90IHlldCBleGlzdCB3aWxsICpub3QqIHRocm93IGFuIGVycm9yLCBhbmQgaW5zdGVhZFxuXHQgICAgICogcmV0dXJucyBhIHN0dWIgb2JqZWN0IHRoYXQgY2Fubm90IHlldCBwZXJmb3JtIHJlbmRlcmluZyB0YXNrcy4gVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBwbHVtYmluZyBldmVudGluZ1xuXHQgICAgICogZm9yIGEgVmlldyB0aHJvdWdob3V0IGl0cyBlbnRpcmUgbGlmZWN5Y2xlLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLlZpZXcud3JhcCh7IHV1aWQ6ICd0ZXN0Vmlld1V1aWQnLCBuYW1lOiAndGVzdFZpZXdOYW1lJyB9KSlcblx0ICAgICAqICAgICAudGhlbih2aWV3ID0+IGNvbnNvbGUubG9nKCd3cmFwcGVkIHZpZXcnLCB2aWV3KSlcblx0ICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHdyYXAoaWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigndmlldy13cmFwJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgZXJyb3JNc2cgPSAoMCwgdmFsaWRhdGVfMS52YWxpZGF0ZUlkZW50aXR5KShpZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKGVycm9yTXNnKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvck1zZyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiBuZXcgaW5kZXhfMS5WaWV3KHRoaXMud2lyZSwgaWRlbnRpdHkpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTeW5jaHJvbm91c2x5IHJldHVybnMgYW4gQVBJIGhhbmRsZSBmb3IgdGhlIGdpdmVuIFZpZXcgaWRlbnRpdHkuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgV3JhcHBpbmcgYSBWaWV3IGlkZW50aXR5IHRoYXQgZG9lcyBub3QgeWV0IGV4aXN0IHdpbGwgKm5vdCogdGhyb3cgYW4gZXJyb3IsIGFuZCBpbnN0ZWFkXG5cdCAgICAgKiByZXR1cm5zIGEgc3R1YiBvYmplY3QgdGhhdCBjYW5ub3QgeWV0IHBlcmZvcm0gcmVuZGVyaW5nIHRhc2tzLiBUaGlzIGNhbiBiZSB1c2VmdWwgZm9yIHBsdW1iaW5nIGV2ZW50aW5nXG5cdCAgICAgKiBmb3IgYSBWaWV3IHRocm91Z2hvdXQgaXRzIGVudGlyZSBsaWZlY3ljbGUuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCB2aWV3ID0gZmluLlZpZXcud3JhcFN5bmMoeyB1dWlkOiAndGVzdFZpZXcnLCBuYW1lOiAndGVzdFZpZXdOYW1lJyB9KTtcblx0ICAgICAqIGF3YWl0IHZpZXcuaGlkZSgpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgKi9cblx0ICAgIHdyYXBTeW5jKGlkZW50aXR5KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3ZpZXctd3JhcC1zeW5jJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgZXJyb3JNc2cgPSAoMCwgdmFsaWRhdGVfMS52YWxpZGF0ZUlkZW50aXR5KShpZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKGVycm9yTXNnKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvck1zZyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiBuZXcgaW5kZXhfMS5WaWV3KHRoaXMud2lyZSwgaWRlbnRpdHkpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBBc3luY2hyb25vdXNseSByZXR1cm5zIGEgVmlldyBvYmplY3QgdGhhdCByZXByZXNlbnRzIHRoZSBjdXJyZW50IHZpZXdcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5WaWV3LmdldEN1cnJlbnQoKVxuXHQgICAgICogICAgIC50aGVuKHZpZXcgPT4gY29uc29sZS5sb2coJ2N1cnJlbnQgdmlldycsIHZpZXcpKVxuXHQgICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKlxuXHQgICAgICogYGBgXG5cdCAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgKi9cblx0ICAgIGdldEN1cnJlbnQoKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3ZpZXctZ2V0LWN1cnJlbnQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBpZiAoIXRoaXMud2lyZS5tZS5pc1ZpZXcpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgYXJlIG5vdCBpbiBhIFZpZXcgY29udGV4dCcpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IHRoaXMud2lyZS5tZTtcblx0ICAgICAgICByZXR1cm4gdGhpcy53cmFwKHsgdXVpZCwgbmFtZSB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGEgVmlldyBvYmplY3QgdGhhdCByZXByZXNlbnRzIHRoZSBjdXJyZW50IHZpZXdcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IHZpZXcgPSBmaW4uVmlldy5nZXRDdXJyZW50U3luYygpO1xuXHQgICAgICogY29uc29sZS5sb2codmlldyk7XG5cdCAgICAgKlxuXHQgICAgICogYGBgXG5cdCAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgKi9cblx0ICAgIGdldEN1cnJlbnRTeW5jKCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd2aWV3LWdldC1jdXJyZW50LXN5bmMnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBpZiAoIXRoaXMud2lyZS5tZS5pc1ZpZXcpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgYXJlIG5vdCBpbiBhIFZpZXcgY29udGV4dCcpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IHRoaXMud2lyZS5tZTtcblx0ICAgICAgICByZXR1cm4gdGhpcy53cmFwU3luYyh7IHV1aWQsIG5hbWUgfSk7XG5cdCAgICB9XG5cdH1cblx0RmFjdG9yeSQ2LlZpZXdNb2R1bGUgPSBWaWV3TW9kdWxlO1xuXHRyZXR1cm4gRmFjdG9yeSQ2O1xufVxuXG52YXIgSW5zdGFuY2UkNSA9IHt9O1xuXG52YXIgbGF6eSA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkobGF6eSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5sYXp5LkFzeW5jUmV0cnlhYmxlTGF6eSA9IGxhenkuTGF6eSA9IHZvaWQgMDtcbi8qKlxuICogSGFuZHkgY2xhc3MgZm9yIG1hbmFnaW5nIGFzeW5jaHJvbm91cyBkZXBlbmRlbmNpZXMgb2YgY2xhc3Nlcy5cbiAqXG4gKiBXaWxsIGNhbGwgdGhlIHByb2R1Y2VyIGZ1bmN0aW9uIG9uY2UgYW5kIG9ubHkgb25jZSB3aGVuIGdldFZhbHVlIGlzIGNhbGxlZCxcbiAqIHJldHVybmluZyB0aGUgcmVzdWx0YW50IHZhbHVlIGZvciBldmVyeSBzdWJzZXF1ZW50IGNhbGwuXG4gKi9cbmNsYXNzIExhenkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnN0cnVjdG9yKHByb2R1Y2VyRm4pIHtcbiAgICAgICAgdGhpcy5wcm9kdWNlckZuID0gcHJvZHVjZXJGbjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogTGF6aWx5IGdldCB0aGUgdmFsdWUgcmV0dXJuZWQgYnkgdGhlIHByb2R1Y2VyLlxuICAgICAqIEByZXR1cm5zIFRoZSB2YWx1ZSByZXR1cm5lZCBmcm9tIHRoZSBwcm9kdWNlciBmdW5jdGlvblxuICAgICAqL1xuICAgIGdldFZhbHVlKCkge1xuICAgICAgICBpZiAoIXRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB0aGlzLnByb2R1Y2VyRm4oKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICB9XG59XG5sYXp5LkxhenkgPSBMYXp5O1xuLyoqXG4gKiBIYW5keSBjbGFzcyBmb3IgbWFuYWdpbmcgYXN5bmNocm9ub3VzIGRlcGVuZGVuY2llcyBvZiBjbGFzc2VzLlxuICpcbiAqIFdpbGwgY2FsbCBhc3luY2hyb25vdXMgcHJvZHVjZXIgb25seSBhZnRlciBgZ2V0VmFsdWVgIGlzIGNhbGxlZC4gIElmIHRoZVxuICogZGVmZXJyZWQgY29kZSBlcnJvcnMsIHdlIGNhbiB0cnkgaXQgYWdhaW4gYnkgcmUtY2FsbGluZyBgZ2V0VmFsdWVgIGFmdGVyXG4gKiB0aGUgcHJvbWlzZSByZWplY3RzLlxuICovXG5jbGFzcyBBc3luY1JldHJ5YWJsZUxhenkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnN0cnVjdG9yKHByb2R1Y2VyRm4pIHtcbiAgICAgICAgdGhpcy5wcm9kdWNlckZuID0gcHJvZHVjZXJGbjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogTGF6aWx5IGdldCB0aGUgdmFsdWUgcmV0dXJuZWQgYnkgdGhlIGFzeW5jIHByb2R1Y2VyLlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIHZhbHVlIHJldHVybmVkIGZyb20gdGhlIHByb2R1Y2VyIGZ1bmN0aW9uXG4gICAgICovXG4gICAgYXN5bmMgZ2V0VmFsdWUoKSB7XG4gICAgICAgIGlmICghdGhpcy5wcm9taXNlKSB7XG4gICAgICAgICAgICB0aGlzLnByb21pc2UgPSB0aGlzLnByb2R1Y2VyRm4oKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnByb21pc2U7XG4gICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnByb21pc2U7XG4gICAgfVxufVxubGF6eS5Bc3luY1JldHJ5YWJsZUxhenkgPSBBc3luY1JldHJ5YWJsZUxhenk7XG5cbnZhciBsYXlvdXRFbnRpdGllcyA9IHt9O1xuXG52YXIgYXBpRXhwb3NlciQxID0ge307XG5cbnZhciBhcGlDb25zdW1lciA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoYXBpQ29uc3VtZXIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuYXBpQ29uc3VtZXIuQXBpQ29uc3VtZXIgPSB2b2lkIDA7XG4vKipcbiAqIENvbnN1bWVyIGZvciBhcGlzIGV4cG9zZWQgd2l0aCB7QHNlZSBBcGlFeHBvc2VyfS5cbiAqXG4gKiBBIHN0cmF0ZWd5IHRoYXQgbWF0Y2hlcyB0aGUgc3RyYXRlZ3kgdXNlZCB0byBleHBvc2UgYSB0YXJnZXQgQVBJIG11c3QgYmUgcHJvdmlkZWQuXG4gKi9cbmNsYXNzIEFwaUNvbnN1bWVyIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICBjb25zdHJ1Y3RvcihzdHJhdGVneSkge1xuICAgICAgICB0aGlzLnN0cmF0ZWd5ID0gc3RyYXRlZ3k7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb25zdW1lcyBhbiBhcGkgZXhwb3NlZCB1c2luZyBhIGdpdmVuIHRyYW5zcG9ydCBzdHJhdGVneSwgYW5kIGdlbmVyYXRlcyBhIGNsaWVudFxuICAgICAgICAgKiBmb3IgZWFzeSwgdHlwZSBzYWZlIGNvbnN1bXB0aW9uIG9mIHRoYXQgY2xpZW50LlxuICAgICAgICAgKiBAcGFyYW0gb3B0aW9ucyBTdHJhdGVneSBzcGVjaWZpYyBjb25zdW1wdGlvbiBvcHRpb25zLlxuICAgICAgICAgKiBAcmV0dXJucyBBbiBhcGkgY2xpZW50IG1hdGNoaW5nIHRoZSBnaXZlbiB0eXBlLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5jb25zdW1lID0gYXN5bmMgKG9wdGlvbnMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGV4cG9zZWRQcm9wZXJ0aWVzID0gYXdhaXQgdGhpcy5zdHJhdGVneS5nZXRFeHBvc2VkRnVuY3Rpb25zKG9wdGlvbnMpO1xuICAgICAgICAgICAgcmV0dXJuIGV4cG9zZWRQcm9wZXJ0aWVzLnJlZHVjZSgoY2xpZW50LCBwcm9wKSA9PiAoe1xuICAgICAgICAgICAgICAgIC4uLmNsaWVudCxcbiAgICAgICAgICAgICAgICBbcHJvcC5rZXldOiB0aGlzLnN0cmF0ZWd5LmNyZWF0ZUZ1bmN0aW9uKHByb3AsIG9wdGlvbnMpXG4gICAgICAgICAgICB9KSwge30pO1xuICAgICAgICB9O1xuICAgIH1cbn1cbmFwaUNvbnN1bWVyLkFwaUNvbnN1bWVyID0gQXBpQ29uc3VtZXI7XG5cbnZhciBhcGlFeHBvc2VyID0ge307XG5cbnZhciBkZWNvcmF0b3JzID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShkZWNvcmF0b3JzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmRlY29yYXRvcnMuZXhwb3NlID0gZGVjb3JhdG9ycy5nZXRFeHBvc2VkUHJvcGVydGllcyA9IHZvaWQgMDtcbmNvbnN0IGV4cG9zZWRQcm9wZXJ0aWVzID0gU3ltYm9sKCdleHBvc2VkUHJvcGVydGllcycpO1xuY29uc3QgZ2V0RXhwb3NlZFByb3BlcnRpZXMgPSAodGFyZ2V0KSA9PiB7XG4gICAgcmV0dXJuIHRhcmdldFtleHBvc2VkUHJvcGVydGllc10gfHwgdGFyZ2V0LnByb3RvdHlwZVtleHBvc2VkUHJvcGVydGllc10gfHwgW107XG59O1xuZGVjb3JhdG9ycy5nZXRFeHBvc2VkUHJvcGVydGllcyA9IGdldEV4cG9zZWRQcm9wZXJ0aWVzO1xuLyoqXG4gKiBJbmRpY2F0ZXMgdGhhdCBhIGNsYXNzIG1lbWJlciBmdW5jdGlvbiBjYW4gYmUgZXhwb3NlZCB1c2luZyB7QGxpbmsgQXBpRXhwb3Nlcn0uXG4gKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25zIHNwZWNpZmljIHRvIHRoZSBzdHJhdGVneSB1c2VkIGluIHtAbGluayBBcGlFeHBvc2VyfVxuICovXG4vLyBSZXR1cm5zIGFueSBhcyBkZWNvcmF0b3IgdHlwaW5nIGlzIHdlaXJkLlxuY29uc3QgZXhwb3NlID0gKG9wdGlvbnMpID0+ICh0YXJnZXQsIGtleSwgZGVzY3JpcHRvcikgPT4ge1xuICAgIHRhcmdldFtleHBvc2VkUHJvcGVydGllc10gPSB0YXJnZXRbZXhwb3NlZFByb3BlcnRpZXNdIHx8IFtdO1xuICAgIHRhcmdldFtleHBvc2VkUHJvcGVydGllc10ucHVzaCh7IGtleSwgZGVzY3JpcHRvciwgb3B0aW9ucyB9KTtcbn07XG5kZWNvcmF0b3JzLmV4cG9zZSA9IGV4cG9zZTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGFwaUV4cG9zZXIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuYXBpRXhwb3Nlci5BcGlFeHBvc2VyID0gdm9pZCAwO1xuY29uc3QgZGVjb3JhdG9yc18xID0gZGVjb3JhdG9ycztcbi8qKlxuICogRXhwb3NlcyBhcGkgc2VydmljZXMgb24gdGhlIHRyYW5zcG9ydCBvZiBjaG9pY2UuXG4gKi9cbmNsYXNzIEFwaUV4cG9zZXIge1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBzdHJhdGVneSBUaGUgZXhwb3NlIHN0cmF0ZWd5IHRvIHVzZSB0byBleHBvc2UgaW5zdGFuY2VzLlxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnN0cnVjdG9yKHN0cmF0ZWd5KSB7XG4gICAgICAgIHRoaXMuc3RyYXRlZ3kgPSBzdHJhdGVneTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEV4cG9zZXMgYW4gaW5zdGFuY2Ugb2YgYSBnaXZlbiBhcGkgb25cbiAgICAgICAgICogQHBhcmFtIGluc3RhbmNlIEluc3RhbmNlIG9mIGEgY2xhc3Mgd2hpY2ggaGFzIGJlZW4gZGVjb3JhdGVkIHRvIGluZGljYXRlIHdoaWNoIGZ1bmN0aW9ucyBjYW4gYmUgZXhwb3NlZC5cbiAgICAgICAgICogQHBhcmFtIGluc3RhbmNlT3B0aW9ucyBUcmFuc3BvcnQgc3RyYXRlZ3kgc3BlY2lmaWMgb3B0aW9ucyB0byB1c2Ugd2hlbiBleHBvc2luZy5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZXhwb3NlSW5zdGFuY2UgPSBhc3luYyAoaW5zdGFuY2UsIGluc3RhbmNlT3B0aW9ucykgPT4ge1xuICAgICAgICAgICAgY29uc3QgZXhwb3NhYmxlUHJvcHMgPSAoMCwgZGVjb3JhdG9yc18xLmdldEV4cG9zZWRQcm9wZXJ0aWVzKShpbnN0YW5jZSk7XG4gICAgICAgICAgICBjb25zdCBleHBvc2VkUHJvcHMgPSBhd2FpdCBQcm9taXNlLmFsbChleHBvc2FibGVQcm9wcy5tYXAoYXN5bmMgKHsga2V5LCBvcHRpb25zIH0pID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjdXN0b21Db25zdW1wdGlvbk9wdGlvbnMgPSBhd2FpdCB0aGlzLnN0cmF0ZWd5LmV4cG9zZUZ1bmN0aW9uKGluc3RhbmNlW2tleV0uYmluZChpbnN0YW5jZSksIHtcbiAgICAgICAgICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgICAgICAgICAgICBtZXRhOiBpbnN0YW5jZU9wdGlvbnNcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXksXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnM6IGN1c3RvbUNvbnN1bXB0aW9uT3B0aW9uc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnN0cmF0ZWd5LmV4cG9zZU1ldGEoaW5zdGFuY2VPcHRpb25zLCBleHBvc2VkUHJvcHMpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICA7XG59XG5hcGlFeHBvc2VyLkFwaUV4cG9zZXIgPSBBcGlFeHBvc2VyO1xuXG52YXIgc3RyYXRlZ2llcyA9IHt9O1xuXG52YXIgb3BlbmZpbkNoYW5uZWxzID0ge307XG5cbnZhciBjaGFubmVsc0NvbnN1bWVyID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShjaGFubmVsc0NvbnN1bWVyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNoYW5uZWxzQ29uc3VtZXIuQ2hhbm5lbHNDb25zdW1lciA9IHZvaWQgMDtcbmNsYXNzIENoYW5uZWxzQ29uc3VtZXIge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnN0cnVjdG9yKGNoYW5uZWwpIHtcbiAgICAgICAgdGhpcy5jaGFubmVsID0gY2hhbm5lbDtcbiAgICAgICAgdGhpcy5nZXRFeHBvc2VkRnVuY3Rpb25zID0gYXN5bmMgKG9wdGlvbnMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgaWQgfSA9IG9wdGlvbnM7XG4gICAgICAgICAgICBjb25zdCB7IHByb3BzIH0gPSBhd2FpdCB0aGlzLmNoYW5uZWwuZGlzcGF0Y2goYGFwaS1tZXRhOiR7aWR9YCk7XG4gICAgICAgICAgICByZXR1cm4gcHJvcHM7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY3JlYXRlRnVuY3Rpb24gPSAocHJvcCkgPT4gKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgYWN0aW9uIH0gPSBwcm9wLm9wdGlvbnM7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jaGFubmVsLmRpc3BhdGNoKGFjdGlvbiwgeyBhcmdzIH0pO1xuICAgICAgICB9O1xuICAgIH1cbiAgICA7XG59XG5jaGFubmVsc0NvbnN1bWVyLkNoYW5uZWxzQ29uc3VtZXIgPSBDaGFubmVsc0NvbnN1bWVyO1xuXG52YXIgY2hhbm5lbHNFeHBvc2VyID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShjaGFubmVsc0V4cG9zZXIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY2hhbm5lbHNFeHBvc2VyLkNoYW5uZWxzRXhwb3NlciA9IHZvaWQgMDtcbmNsYXNzIENoYW5uZWxzRXhwb3NlciB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgY29uc3RydWN0b3IoY2hhbm5lbFByb3ZpZGVyT3JDbGllbnQpIHtcbiAgICAgICAgdGhpcy5jaGFubmVsUHJvdmlkZXJPckNsaWVudCA9IGNoYW5uZWxQcm92aWRlck9yQ2xpZW50O1xuICAgICAgICB0aGlzLmV4cG9zZUZ1bmN0aW9uID0gYXN5bmMgKHRhcmdldCwgY29uZmlnKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IGtleSwgb3B0aW9ucywgbWV0YSB9ID0gY29uZmlnO1xuICAgICAgICAgICAgY29uc3QgeyBpZCB9ID0gbWV0YTtcbiAgICAgICAgICAgIGNvbnN0IGFjdGlvbiA9IGAke2lkfS4ke29wdGlvbnM/LmFjdGlvbiB8fCBrZXl9YDtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2hhbm5lbFByb3ZpZGVyT3JDbGllbnQucmVnaXN0ZXIoYWN0aW9uLCBhc3luYyAoeyBhcmdzIH0pID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGFyZ2V0KC4uLmFyZ3MpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4geyBhY3Rpb24gfTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5leHBvc2VNZXRhID0gYXN5bmMgKHsgaWQgfSwgcHJvcHMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGFjdGlvbiA9IGBhcGktbWV0YToke2lkfWA7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNoYW5uZWxQcm92aWRlck9yQ2xpZW50LnJlZ2lzdGVyKGFjdGlvbiwgKCkgPT4gKHsgcHJvcHMgfSkpO1xuICAgICAgICB9O1xuICAgIH1cbn1cbmNoYW5uZWxzRXhwb3Nlci5DaGFubmVsc0V4cG9zZXIgPSBDaGFubmVsc0V4cG9zZXI7XG5cbihmdW5jdGlvbiAoZXhwb3J0cykge1xuXHR2YXIgX19jcmVhdGVCaW5kaW5nID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY3JlYXRlQmluZGluZykgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdCAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XG5cdCAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xuXHQgICAgICBkZXNjID0geyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbVtrXTsgfSB9O1xuXHQgICAgfVxuXHQgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcblx0fSkgOiAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdCAgICBvW2syXSA9IG1ba107XG5cdH0pKTtcblx0dmFyIF9fZXhwb3J0U3RhciA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2V4cG9ydFN0YXIpIHx8IGZ1bmN0aW9uKG0sIGV4cG9ydHMpIHtcblx0ICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZXhwb3J0cywgcCkpIF9fY3JlYXRlQmluZGluZyhleHBvcnRzLCBtLCBwKTtcblx0fTtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRfX2V4cG9ydFN0YXIoY2hhbm5lbHNDb25zdW1lciwgZXhwb3J0cyk7XG5cdF9fZXhwb3J0U3RhcihjaGFubmVsc0V4cG9zZXIsIGV4cG9ydHMpOyBcbn0gKG9wZW5maW5DaGFubmVscykpO1xuXG4oZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0ICAgIH1cblx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgb1trMl0gPSBtW2tdO1xuXHR9KSk7XG5cdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0X19leHBvcnRTdGFyKG9wZW5maW5DaGFubmVscywgZXhwb3J0cyk7IFxufSAoc3RyYXRlZ2llcykpO1xuXG4oZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0ICAgIH1cblx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgb1trMl0gPSBtW2tdO1xuXHR9KSk7XG5cdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0X19leHBvcnRTdGFyKGFwaUNvbnN1bWVyLCBleHBvcnRzKTtcblx0X19leHBvcnRTdGFyKGFwaUV4cG9zZXIsIGV4cG9ydHMpO1xuXHRfX2V4cG9ydFN0YXIoc3RyYXRlZ2llcywgZXhwb3J0cyk7XG5cdF9fZXhwb3J0U3RhcihkZWNvcmF0b3JzLCBleHBvcnRzKTsgXG59IChhcGlFeHBvc2VyJDEpKTtcblxudmFyIGNoYW5uZWxBcGlSZWxheSA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoY2hhbm5lbEFwaVJlbGF5LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNoYW5uZWxBcGlSZWxheS5jcmVhdGVSZWxheWVkRGlzcGF0Y2ggPSBjaGFubmVsQXBpUmVsYXkucmVsYXlDaGFubmVsQ2xpZW50QXBpID0gdm9pZCAwO1xuY29uc3QgRVhQRUNURURfRVJST1JTID0gW1xuICAgICdubyBsb25nZXIgY29ubmVjdGVkJyxcbiAgICAnUlRDRGF0YUNoYW5uZWwgY2xvc2VkIHVuZXhwZWN0ZWRseScsXG4gICAgJ1RoZSBjbGllbnQgeW91IGFyZSB0cnlpbmcgdG8gZGlzcGF0Y2ggZnJvbSBpcyBkaXNjb25uZWN0ZWQgZnJvbSB0aGUgdGFyZ2V0IHByb3ZpZGVyJyxcbl07XG4vLyBDaGVja3MgcG9zc2libGUgZXJyb3IgbWVzc2FnZXMgdGhhdCB3ZSB3YW50IHRvIHRyYXAsIGNsaWVudCBlcnJvciBtZXNzYWdlIGNhbiBvcmlnaW5hdGVcbi8vIGZyb20gQ2hhbm5lbFByb3ZpZGVyOjpkaXNwYXRjaCBPUiBDbGFzc2ljU3RyYXRlZ3k6OmNsb3NlRW5kcG9pbnQgT1IgUlRDRW5kUG9pbnQ6OmRhdGFDaGFubmVsOjpvbmNsb3NlXG5jb25zdCBpc0Rpc2Nvbm5lY3RlZEVycm9yID0gKGVycm9yTXNnKSA9PiB7XG4gICAgcmV0dXJuIEVYUEVDVEVEX0VSUk9SUy5zb21lKGUgPT4gZXJyb3JNc2cuaW5jbHVkZXMoZSkpO1xufTtcbi8qKlxuICogQGludGVybmFsXG4gKiBDcmVhdGUgYSBjaGFubmVsIHJlbGF5IGZvciBhIGdpdmVuIGNoYW5uZWwgZXhwb3NpdGlvbiwgYWxsb3dpbmcgYSBzaW5nbGUgcHJvdmlkZXIgdG8gcm91dGVcbiAqIGFjdGlvbnMgdG8gdGhlIGRlc2lnbmF0ZWQgY2xpZW50cy5cbiAqXG4gKiBEZXNpZ25lZCB0byBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggQGV4cG9zZVxuICpcbiAqIEBwYXJhbSBjaGFubmVsUHJvdmlkZXIgVGhlIGNoYW5uZWwgcHJvdmlkZXIgdG8gcmVsYXkgdGhlIGFjdGlvbnMgb24uXG4gKiBAcGFyYW0gY29uZmlnIERldGVybWluZXMgd2hpY2ggYWN0aW9ucyB0byByZWxheS4gUGxlYXNlIGVuc3VyZSBhY3Rpb24gcHJlZml4IG1hdGNoZXMgdGhlIGV4cG9zZWQgYXBpLlxuICovXG5jb25zdCByZWxheUNoYW5uZWxDbGllbnRBcGkgPSBhc3luYyAoY2hhbm5lbFByb3ZpZGVyLCByZWxheUlkKSA9PiB7XG4gICAgY2hhbm5lbFByb3ZpZGVyLnJlZ2lzdGVyKGByZWxheToke3JlbGF5SWR9YCwgKHsgYWN0aW9uLCB0YXJnZXQsIHBheWxvYWQgfSkgPT4ge1xuICAgICAgICByZXR1cm4gY2hhbm5lbFByb3ZpZGVyLmRpc3BhdGNoKHRhcmdldCwgYWN0aW9uLCBwYXlsb2FkKTtcbiAgICB9KTtcbiAgICBhd2FpdCBQcm9taXNlLnJlc29sdmUoKTtcbn07XG5jaGFubmVsQXBpUmVsYXkucmVsYXlDaGFubmVsQ2xpZW50QXBpID0gcmVsYXlDaGFubmVsQ2xpZW50QXBpO1xuY29uc3QgY3JlYXRlUmVsYXllZERpc3BhdGNoID0gKGNsaWVudCwgdGFyZ2V0LCByZWxheUlkLCByZWxheUVycm9yTXNnKSA9PiBhc3luYyAoYWN0aW9uLCBwYXlsb2FkKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGNsaWVudC5kaXNwYXRjaChgcmVsYXk6JHtyZWxheUlkfWAsIHtcbiAgICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICAgIHBheWxvYWQsXG4gICAgICAgICAgICB0YXJnZXRcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChpc0Rpc2Nvbm5lY3RlZEVycm9yKGUubWVzc2FnZSkgJiYgcmVsYXlFcnJvck1zZykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHJlbGF5RXJyb3JNc2cpO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IGU7XG4gICAgfVxufTtcbmNoYW5uZWxBcGlSZWxheS5jcmVhdGVSZWxheWVkRGlzcGF0Y2ggPSBjcmVhdGVSZWxheWVkRGlzcGF0Y2g7XG5cbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JGIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XG59O1xudmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9MYXlvdXROb2RlX2NsaWVudCwgX1RhYlN0YWNrX2NsaWVudCwgX0NvbHVtbk9yUm93X2NsaWVudDtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShsYXlvdXRFbnRpdGllcywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5sYXlvdXRFbnRpdGllcy5Db2x1bW5PclJvdyA9IGxheW91dEVudGl0aWVzLlRhYlN0YWNrID0gbGF5b3V0RW50aXRpZXMuTGF5b3V0Tm9kZSA9IHZvaWQgMDtcbmNvbnN0IGFwaV9leHBvc2VyXzEgPSBhcGlFeHBvc2VyJDE7XG5jb25zdCBjaGFubmVsX2FwaV9yZWxheV8xID0gY2hhbm5lbEFwaVJlbGF5O1xuLypcbiAgICBUaGlzIGZpbGUgaW5jbHVkZXMgTGF5b3V0Tm9kZSwgQ29sdW1uT3JSb3cgYW5kIFRhYlN0YWNrIGNsYXNzZXMsIHdoaWNoIGFyZSBhbGwgY2xvc2VseVxuICAgIGludGVydHdpbmVkLCBhbmQgc2hhcmUgbWVtYmVycyB2aWEgcGFyZW50IGFic3RyYWN0IGNsYXNzIExheW91dE5vZGUuIFRvIHByZXZlbnQgY2lyY3VsYXJcbiAgICByZWZzLCB3ZSBkZWZpbmUgYW5kIGV4cG9ydCBhbGwgdGhlIGNsYXNzZXMgaGVyZS5cbiovXG4vKipcbiAqIEBpZ25vcmVcbiAqIEBpbnRlcm5hbFxuICogU3VwcGxpZXMgYW4gQXBpQ2xpZW50IGZvciB7QGxpbmsgTGF5b3V0RW50aXRpZXNDb250cm9sbGVyfSBhbmQgaGVscGVyIG1ldGhvZHNcbiAqIGZvciB0aGUgZW50aXRpZXMge0BsaW5rIFRhYlN0YWNrfSBBTkQge0BsaW5rIENvbHVtbk9yUm93fSB0byB1c2UuXG4gKi9cbmNsYXNzIExheW91dE5vZGUge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqIEBpZ25vcmVcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihjbGllbnQsIGVudGl0eUlkKSB7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAaWdub3JlXG4gICAgICAgICAqIEBpbnRlcm5hbFxuICAgICAgICAgKiBBcGlDbGllbnQgZm9yIHtAbGluayBMYXlvdXRFbnRpdGllc0NvbnRyb2xsZXJ9XG4gICAgICAgICAqL1xuICAgICAgICBfTGF5b3V0Tm9kZV9jbGllbnQuc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDaGVja3MgaWYgdGhlIFRhYlN0YWNrIG9yIENvbHVtbk9yUm93IGlzIHRoZSByb290IGNvbnRlbnQgaXRlbVxuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBpZiAoIWZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3LicpO1xuICAgICAgICAgKiB9XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiBjb25zdCBpc1Jvb3QgPSBhd2FpdCBzdGFjay5pc1Jvb3QoKTtcbiAgICAgICAgICogLy8gVGhlIFRhYlN0YWNrIGlzIHJvb3Q6IGZhbHNlXG4gICAgICAgICAqIGNvbnNvbGUubG9nKGBUaGUgVGFiU3RhY2sgaXMgcm9vdDogJHtpc1Jvb3R9YCk7XG4gICAgICAgICAqXG4gICAgICAgICAqIC8vIFJldHJpZXZlcyB0aGUgcGFyZW50IENvbHVtbk9yUm93XG4gICAgICAgICAqIGNvbnN0IHBhcmVudCA9IGF3YWl0IHN0YWNrLmdldFBhcmVudCgpO1xuICAgICAgICAgKiBjb25zdCBwYXJlbnRJc1Jvb3QgPSBhd2FpdCBwYXJlbnQuaXNSb290KCk7XG4gICAgICAgICAqIC8vIFRoZSBwYXJlbnQgQ29sdW1uT3JSb3cgaXMgcm9vdDogdHJ1ZVxuICAgICAgICAgKiBjb25zb2xlLmxvZyhgVGhlIHBhcmVudCBDb2x1bW5PclJvdyBpcyByb290OiAke3BhcmVudElzUm9vdH1gKTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmlzUm9vdCA9ICgpID0+IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZCh0aGlzLCBfTGF5b3V0Tm9kZV9jbGllbnQsIFwiZlwiKS5pc1Jvb3QodGhpcy5lbnRpdHlJZCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDaGVja3MgaWYgdGhlIFRhYlN0YWNrIG9yIENvbHVtbk9yUm93IGV4aXN0c1xuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBpZiAoIWZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3LicpO1xuICAgICAgICAgKiB9XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiAvLyBSZXRyaWV2ZXMgdGhlIHBhcmVudCBDb2x1bW5PclJvd1xuICAgICAgICAgKiBjb25zdCBjb2x1bW5PclJvdyA9IGF3YWl0IHN0YWNrLmdldFBhcmVudCgpO1xuICAgICAgICAgKiBsZXQgZXhpc3RzID0gYXdhaXQgc3RhY2suZXhpc3RzKCk7XG4gICAgICAgICAqIC8vIG9yXG4gICAgICAgICAqIGxldCBleGlzdHMgPSBhd2FpdCBjb2x1bW5PclJvdy5leGlzdHMoKTtcbiAgICAgICAgICogLy8gVGhlIGVudGl0eSBleGlzdHM6IHRydWVcbiAgICAgICAgICogY29uc29sZS5sb2coYFRoZSBlbnRpdHkgZXhpc3RzOiAke2V4aXN0c31gKTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmV4aXN0cyA9ICgpID0+IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZCh0aGlzLCBfTGF5b3V0Tm9kZV9jbGllbnQsIFwiZlwiKS5leGlzdHModGhpcy5lbnRpdHlJZCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXRyaWV2ZXMgdGhlIHBhcmVudCBvZiB0aGUgVGFiU3RhY2sgb3IgQ29sdW1uT3JSb3dcbiAgICAgICAgICpcbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogaWYgKCFmaW4ubWUuaXNWaWV3KSB7XG4gICAgICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldy4nKTtcbiAgICAgICAgICogfVxuICAgICAgICAgKlxuICAgICAgICAgKiBjb25zdCBzdGFjayA9IGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50U3RhY2soKTtcbiAgICAgICAgICogLy8gUmV0cmlldmVzIHRoZSBwYXJlbnQgQ29sdW1uT3JSb3dcbiAgICAgICAgICogY29uc3QgY29sdW1uT3JSb3cgPSBhd2FpdCBzdGFjay5nZXRQYXJlbnQoKTtcbiAgICAgICAgICpcbiAgICAgICAgICogLy8gdW5kZWZpbmVkIGlmIGVudGl0eSBpcyB0aGUgcm9vdCBpdGVtXG4gICAgICAgICAqIGxldCBwYXJlbnQgPSBhd2FpdCBjb2x1bW5PclJvdy5nZXRQYXJlbnQoKTtcbiAgICAgICAgICogLy8gb3JcbiAgICAgICAgICogbGV0IHBhcmVudCA9IGF3YWl0IHN0YWNrLmdldFBhcmVudCgpO1xuICAgICAgICAgKiBgYGBcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZ2V0UGFyZW50ID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGFyZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRkKHRoaXMsIF9MYXlvdXROb2RlX2NsaWVudCwgXCJmXCIpLmdldFBhcmVudCh0aGlzLmVudGl0eUlkKTtcbiAgICAgICAgICAgIGlmICghcGFyZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBMYXlvdXROb2RlLmdldEVudGl0eShwYXJlbnQsIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZCh0aGlzLCBfTGF5b3V0Tm9kZV9jbGllbnQsIFwiZlwiKSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IFRhYlN0YWNrIGFkamFjZW50IHRvIHRoZSBnaXZlbiBUYWJTdGFjayBvciBDb2x1bW5PclJvdy4gSW5wdXRzIGNhbiBiZSBuZXcgdmlld3MgdG8gY3JlYXRlLCBvciBleGlzdGluZyB2aWV3cy5cbiAgICAgICAgICpcbiAgICAgICAgICogS25vd24gSXNzdWU6IElmIHRoZSBudW1iZXIgb2Ygdmlld3MgdG8gYWRkIG92ZXJmbG93cyB0aGUgdGFiLWNvbnRhaW5lciwgdGhlIGFkZGVkIHZpZXdzIHdpbGwgYmUgc2V0IGFzIGFjdGl2ZVxuICAgICAgICAgKiBkdXJpbmcgZWFjaCByZW5kZXIsIGFuZCB0aGVuIHBsYWNlZCBhdCB0aGUgZnJvbnQgb2YgdGhlIHRhYi1zdGFjaywgd2hpbGUgdGhlIHVuZGVybHlpbmcgb3JkZXIgb2YgdGFicyB3aWxsIHJlbWFpbiB1bmNoYW5nZWQuXG4gICAgICAgICAqIFRoaXMgbWVhbnMgdGhlIHZpZXdzIHlvdSBwYXNzIHRvIGNyZWF0ZUFkamFjZW50U3RhY2soKSBtYXkgbm90IHJlbmRlciBpbiB0aGUgb3JkZXIgZ2l2ZW4gYnkgdGhlIGFycmF5LlxuICAgICAgICAgKiBVbnRpbCBmaXhlZCwgdGhpcyBwcm9ibGVtIGNhbiBiZSBhdm9pZGVkIG9ubHkgaWYgeW91ciB3aW5kb3cgaXMgd2lkZSBlbm91Z2ggdG8gZml0IGNyZWF0aW5nIGFsbCB0aGUgdmlld3MgaW4gdGhlIHRhYnN0YWNrLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdmlld3MgVGhlIHZpZXdzIHRoYXQgd2lsbCBwb3B1bGF0ZSB0aGUgbmV3IFRhYlN0YWNrLlxuICAgICAgICAgKiBAcGFyYW0gb3B0aW9ucyBBZGRpdGlvbmFsIG9wdGlvbnMgdGhhdCBjb250cm9sIG5ldyBUYWJTdGFjayBjcmVhdGlvbi5cbiAgICAgICAgICogQHJldHVybnMgVGhlIG5ld2x5LWNyZWF0ZWQgVGFiU3RhY2suXG4gICAgICAgICAqXG4gICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAqIGBgYGpzXG4gICAgICAgICAqIGlmICghZmluLm1lLmlzVmlldykge1xuICAgICAgICAgKiAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgcnVubmluZyBpbiBhIHBsYXRmb3JtIFZpZXcuJyk7XG4gICAgICAgICAqIH1cbiAgICAgICAgICpcbiAgICAgICAgICogY29uc3Qgc3RhY2sgPSBhd2FpdCBmaW4ubWUuZ2V0Q3VycmVudFN0YWNrKCk7XG4gICAgICAgICAqIGNvbnN0IGNvbHVtbk9yUm93ID0gYXdhaXQgc3RhY2suZ2V0UGFyZW50KCk7XG4gICAgICAgICAqXG4gICAgICAgICAqIC8vIENyZWF0ZSB2aWV3IHJlZmVyZW5jZXMgYnkgc3VwcGx5aW5nIGEgJ25hbWUnIGFuZCAndXJsJ1xuICAgICAgICAgKiBjb25zdCB2aWV3cyA9IFtcbiAgICAgICAgICogICAgIC8vIGlmICduYW1lJyBpcyB1bmRlZmluZWQsIG9uZSB3aWxsIGJlIGdlbmVyYXRlZFxuICAgICAgICAgKiAgICAgLy8gaWYgJ3VybCcgaXMgdW5kZWZpbmVkLCBpdCB3aWxsIGRlZmF1bHQgdGhlIHZpZXcgVVJMIHRvICdhYm91dDpibGFuaydcbiAgICAgICAgICogICAgIHsgbmFtZTogJ2dvb2dsZS12aWV3JywgdXJsOiAnaHR0cDovL2dvb2dsZS5jb20vJ30sXG4gICAgICAgICAqICAgICB7IG5hbWU6ICdvZi1kZXZlbG9wZXJzLXZpZXcnLCB1cmw6ICdodHRwOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvLyd9LFxuICAgICAgICAgKiBdO1xuICAgICAgICAgKlxuICAgICAgICAgKiAvLyBDcmVhdGUgYSB2aWV3IGJlZm9yZWhhbmQgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIG5ldyB0YWIgc3RhY2tcbiAgICAgICAgICogY29uc3Qgb3V0c2lkZVZpZXcgPSBhd2FpdCBmaW4uVmlldy5jcmVhdGUoe1xuICAgICAgICAgKiAgICAgbmFtZTogJ291dHNpZGUtYmxvb21iZXJnLXZpZXcnLFxuICAgICAgICAgKiAgICAgdXJsOiAnaHR0cHM6Ly9ibG9vbWJlcmcuY29tLycsXG4gICAgICAgICAqICAgICB0YXJnZXQ6IGZpbi5tZS5pZGVudGl0eSxcbiAgICAgICAgICogfSk7XG4gICAgICAgICAqXG4gICAgICAgICAqIC8vIFZpZXdzIHRvIGFkZCBjYW4gYmUgaWRlbnRpdGllcywgb3IgdGhlIHJlZmVyZW5jZSB2aWV3cyBtZW50aW9uZWQgYWJvdmVcbiAgICAgICAgICogY29uc3Qgdmlld3NUb0FkZCA9IFtvdXRzaWRlVmlldy5pZGVudGl0eSwgLi4udmlld3NdO1xuICAgICAgICAgKlxuICAgICAgICAgKiAvLyBQb3NzaWJsZSBwb3NpdGlvbiBpbnB1dHM6ICdyaWdodCcgfCAnbGVmdCcgfCAndG9wJyB8ICdib3R0b20nXG4gICAgICAgICAqIGxldCBzdGFja0Zyb20gPSBhd2FpdCBjb2x1bW5PclJvdy5jcmVhdGVBZGphY2VudFN0YWNrKHZpZXdzVG9BZGQsIHsgcG9zaXRpb246ICdyaWdodCcgfSk7XG4gICAgICAgICAqIC8vIE9yXG4gICAgICAgICAqIGxldCBuZXdTdGFjayA9IGF3YWl0IHN0YWNrLmNyZWF0ZUFkamFjZW50U3RhY2sodmlld3NUb0FkZCwgeyBwb3NpdGlvbjogJ3JpZ2h0JyB9KTtcbiAgICAgICAgICogY29uc29sZS5sb2coYEEgbmV3IFRhYlN0YWNrIGNyZWF0ZWQgdG8gdGhlIHJpZ2h0IGhhcyAke25ld1N0YWNrLmxlbmd0aH0gdmlld3MgaW4gaXRgKTtcbiAgICAgICAgICpcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBleHBlcmltZW50YWxcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuY3JlYXRlQWRqYWNlbnRTdGFjayA9IGFzeW5jICh2aWV3cywgb3B0aW9ucykgPT4ge1xuICAgICAgICAgICAgY29uc3QgZW50aXR5SWQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX0xheW91dE5vZGVfY2xpZW50LCBcImZcIikuY3JlYXRlQWRqYWNlbnRTdGFjayh0aGlzLmVudGl0eUlkLCB2aWV3cywgb3B0aW9ucyk7XG4gICAgICAgICAgICByZXR1cm4gTGF5b3V0Tm9kZS5nZXRFbnRpdHkoeyBlbnRpdHlJZCwgdHlwZTogJ3N0YWNrJyB9LCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX0xheW91dE5vZGVfY2xpZW50LCBcImZcIikpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogUmV0cmlldmVzIHRoZSBhZGphY2VudCBUYWJTdGFja3Mgb2YgdGhlIGdpdmVuIFRhYlN0YWNrIG9yIENvbHVtbk9yUm93LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gZWRnZSBFZGdlIHdob3NlIGFkamFjZW50IFRhYlN0YWNrcyB3aWxsIGJlIHJldHVybmVkLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBpZiAoIWZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3LicpO1xuICAgICAgICAgKiB9XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiBjb25zdCBjb2x1bW5PclJvdyA9IGF3YWl0IHN0YWNrLmdldFBhcmVudCgpO1xuICAgICAgICAgKiAvLyBQb3NzaWJsZSBwb3NpdGlvbiBpbnB1dHM6ICdyaWdodCcgfCAnbGVmdCcgfCAndG9wJyB8ICdib3R0b20nXG4gICAgICAgICAqIGxldCByaWdodFN0YWNrcyA9IGF3YWl0IGNvbHVtbk9yUm93LmdldEFkamFjZW50U3RhY2tzKCdyaWdodCcpO1xuICAgICAgICAgKiBsZXQgbGVmdFN0YWNrcyA9IGF3YWl0IGNvbHVtbk9yUm93LmdldEFkamFjZW50U3RhY2tzKCdsZWZ0Jyk7XG4gICAgICAgICAqIC8vIG9yXG4gICAgICAgICAqIGxldCByaWdodFN0YWNrcyA9IGF3YWl0IHN0YWNrLmdldEFkamFjZW50U3RhY2tzKCdyaWdodCcpO1xuICAgICAgICAgKiBsZXQgbGVmdFN0YWNrcyA9IGF3YWl0IHN0YWNrLmdldEFkamFjZW50U3RhY2tzKCdsZWZ0Jyk7XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnNvbGUubG9nKGBUaGUgZW50aXR5IGhhcyAke3JpZ2h0U3RhY2tzLmxlbmd0aH0gc3RhY2tzIHRvIHRoZSByaWdodCwgYW5kICR7bGVmdFN0YWNrcy5sZW5ndGh9IHN0YWNrcyB0byB0aGUgbGVmdGApO1xuICAgICAgICAgKlxuICAgICAgICAgKiBgYGBcbiAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5nZXRBZGphY2VudFN0YWNrcyA9IGFzeW5jIChlZGdlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBhZGphY2VudFN0YWNrcyA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZCh0aGlzLCBfTGF5b3V0Tm9kZV9jbGllbnQsIFwiZlwiKS5nZXRBZGphY2VudFN0YWNrcyh7XG4gICAgICAgICAgICAgICAgdGFyZ2V0SWQ6IHRoaXMuZW50aXR5SWQsXG4gICAgICAgICAgICAgICAgZWRnZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gYWRqYWNlbnRTdGFja3MubWFwKChzdGFjaykgPT4gTGF5b3V0Tm9kZS5nZXRFbnRpdHkoe1xuICAgICAgICAgICAgICAgIHR5cGU6ICdzdGFjaycsXG4gICAgICAgICAgICAgICAgZW50aXR5SWQ6IHN0YWNrLmVudGl0eUlkXG4gICAgICAgICAgICB9LCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX0xheW91dE5vZGVfY2xpZW50LCBcImZcIikpKTtcbiAgICAgICAgfTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCRiKHRoaXMsIF9MYXlvdXROb2RlX2NsaWVudCwgY2xpZW50LCBcImZcIik7XG4gICAgICAgIHRoaXMuZW50aXR5SWQgPSBlbnRpdHlJZDtcbiAgICB9XG59XG5sYXlvdXRFbnRpdGllcy5MYXlvdXROb2RlID0gTGF5b3V0Tm9kZTtcbl9MYXlvdXROb2RlX2NsaWVudCA9IG5ldyBXZWFrTWFwKCk7XG4vKipcbiAqIEBpZ25vcmVcbiAqIEBpbnRlcm5hbFxuICogRW5jYXBzdWxhdGVzIEFwaSBjb25zdW1wdGlvbiBvZiB7QGxpbmsgTGF5b3V0RW50aXRpZXNDbGllbnR9IHdpdGggYSByZWxheWVkIGRpc3BhdGNoXG4gKiBAcGFyYW0gY2xpZW50XG4gKiBAcGFyYW0gY29udHJvbGxlcklkXG4gKiBAcGFyYW0gaWRlbnRpdHlcbiAqIEByZXR1cm5zIGEgbmV3IGluc3RhbmNlIG9mIHtAbGluayBMYXlvdXRFbnRpdGllc0NsaWVudH0gd2l0aCBib3VuZCB0byB0aGUgY29udHJvbGxlcklkXG4gKi9cbkxheW91dE5vZGUubmV3TGF5b3V0RW50aXRpZXNDbGllbnQgPSBhc3luYyAoY2xpZW50LCBjb250cm9sbGVySWQsIGlkZW50aXR5KSA9PiB7XG4gICAgY29uc3QgZGlzcGF0Y2ggPSAoMCwgY2hhbm5lbF9hcGlfcmVsYXlfMS5jcmVhdGVSZWxheWVkRGlzcGF0Y2gpKGNsaWVudCwgaWRlbnRpdHksICdsYXlvdXQtcmVsYXknLCAnWW91IGFyZSB0cnlpbmcgdG8gaW50ZXJhY3Qgd2l0aCBhIGxheW91dCBjb21wb25lbnQgb24gYSB3aW5kb3cgdGhhdCBkb2VzIG5vdCBleGlzdCBvciBoYXMgYmVlbiBkZXN0cm95ZWQuJyk7XG4gICAgY29uc3QgY29uc3VtZXIgPSBuZXcgYXBpX2V4cG9zZXJfMS5BcGlDb25zdW1lcihuZXcgYXBpX2V4cG9zZXJfMS5DaGFubmVsc0NvbnN1bWVyKHsgZGlzcGF0Y2ggfSkpO1xuICAgIHJldHVybiBjb25zdW1lci5jb25zdW1lKHsgaWQ6IGNvbnRyb2xsZXJJZCB9KTtcbn07XG5MYXlvdXROb2RlLmdldEVudGl0eSA9IChkZWZpbml0aW9uLCBjbGllbnQpID0+IHtcbiAgICBjb25zdCB7IGVudGl0eUlkLCB0eXBlIH0gPSBkZWZpbml0aW9uO1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlICdjb2x1bW4nOlxuICAgICAgICBjYXNlICdyb3cnOlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBDb2x1bW5PclJvdyhjbGllbnQsIGVudGl0eUlkLCB0eXBlKTtcbiAgICAgICAgY2FzZSAnc3RhY2snOlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBUYWJTdGFjayhjbGllbnQsIGVudGl0eUlkKTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5yZWNvZ25pc2VkIExheW91dCBFbnRpdHkgZW5jb3VudGVyZWQgKCcke0pTT04uc3RyaW5naWZ5KGRlZmluaXRpb24pfSlgKTtcbiAgICB9XG59O1xuLyoqXG4gKiBBIFRhYlN0YWNrIGlzIHVzZWQgdG8gbWFuYWdlIHRoZSBzdGF0ZSBvZiBhIHN0YWNrIG9mIHRhYnMgd2l0aGluIGFuIE9wZW5GaW4gTGF5b3V0LlxuICovXG5jbGFzcyBUYWJTdGFjayBleHRlbmRzIExheW91dE5vZGUge1xuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBjb25zdHJ1Y3RvcihjbGllbnQsIGVudGl0eUlkKSB7XG4gICAgICAgIHN1cGVyKGNsaWVudCwgZW50aXR5SWQpO1xuICAgICAgICAvKipcbiAgICAgICAgICogQGludGVybmFsXG4gICAgICAgICAqIEFwaUNsaWVudCBmb3Ige0BsaW5rIExheW91dEVudGl0aWVzQ29udHJvbGxlcn1cbiAgICAgICAgICovXG4gICAgICAgIF9UYWJTdGFja19jbGllbnQuc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUeXBlIG9mIHRoZSBjb250ZW50IGl0ZW0uIEFsd2F5cyBzdGFjaywgYnV0IHVzZWZ1bCBmb3IgZGlzdGluZ3Vpc2hpbmcgYmV0d2VlbiBhIHtAbGluayBUYWJTdGFja30gYW5kIHtAbGluayBDb2x1bW5PclJvd30uXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnR5cGUgPSAnc3RhY2snO1xuICAgICAgICAvKipcbiAgICAgICAgICogUmV0cmlldmVzIGEgbGlzdCBvZiBhbGwgdmlld3MgYmVsb25naW5nIHRvIHRoaXMge0BsaW5rIFRhYlN0YWNrfS5cbiAgICAgICAgICpcbiAgICAgICAgICogS25vd24gSXNzdWU6IElmIGFkZGluZyBhIHZpZXcgb3ZlcmZsb3dzIHRoZSB0YWItY29udGFpbmVyIHdpZHRoLCB0aGUgYWRkZWQgdmlldyB3aWxsIGJlIHNldCBhcyBhY3RpdmVcbiAgICAgICAgICogYW5kIHJlbmRlcmVkIGF0IHRoZSBmcm9udCBvZiB0aGUgdGFiLXN0YWNrLCB3aGlsZSB0aGUgdW5kZXJseWluZyBvcmRlciBvZiB0YWJzIHdpbGwgcmVtYWluIHVuY2hhbmdlZC5cbiAgICAgICAgICogSWYgdGhhdCBoYXBwZW5zIGFuZCB0aGVuIGdldFZpZXdzKCkgaXMgY2FsbGVkLCBpdCB3aWxsIHJldHVybiB0aGUgaWRlbnRpdGllcyBpbiBhIGRpZmZlcmVudCBvcmRlciB0aGFuXG4gICAgICAgICAqIHRoYW4gdGhlIGN1cnJlbnRseSByZW5kZXJlZCB0YWIgb3JkZXIuXG4gICAgICAgICAqXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0aHJvd3MgSWYgdGhlIHtAbGluayBUYWJTdGFja30gaGFzIGJlZW4gZGVzdHJveWVkLlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBpZiAoIWZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3LicpO1xuICAgICAgICAgKiB9XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiAvLyBBbHRlcm5hdGl2ZWx5LCB5b3UgY2FuIHdyYXAgYW55IHZpZXcgYW5kIGdldCB0aGUgc3RhY2sgZnJvbSB0aGVyZVxuICAgICAgICAgKiAvLyBjb25zdCB2aWV3RnJvbVNvbWV3aGVyZSA9IGZpbi5WaWV3LndyYXBTeW5jKHNvbWVWaWV3LmlkZW50aXR5KTtcbiAgICAgICAgICogLy8gY29uc3Qgc3RhY2sgPSBhd2FpdCB2aWV3RnJvbVNvbWV3aGVyZS5nZXRDdXJyZW50U3RhY2soKTtcbiAgICAgICAgICogY29uc3Qgdmlld3MgPSBhd2FpdCBzdGFjay5nZXRWaWV3cygpO1xuICAgICAgICAgKiBjb25zb2xlLmxvZyhgU3RhY2sgY29udGFpbnMgJHt2aWV3cy5sZW5ndGh9IHZpZXcocylgKTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBleHBlcmltZW50YWxcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZ2V0Vmlld3MgPSAoKSA9PiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX1RhYlN0YWNrX2NsaWVudCwgXCJmXCIpLmdldFN0YWNrVmlld3ModGhpcy5lbnRpdHlJZCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBZGRzIG9yIGNyZWF0ZXMgYSB2aWV3IGluIHRoaXMge0BsaW5rIFRhYlN0YWNrfS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJlbWFya3MgS25vd24gSXNzdWU6IElmIGFkZGluZyBhIHZpZXcgb3ZlcmZsb3dzIHRoZSB0YWItY29udGFpbmVyLCB0aGUgYWRkZWQgdmlldyB3aWxsIGJlIHNldCBhcyBhY3RpdmVcbiAgICAgICAgICogYW5kIHJlbmRlcmVkIGF0IHRoZSBmcm9udCBvZiB0aGUgdGFiLXN0YWNrLCB3aGlsZSB0aGUgdW5kZXJseWluZyBvcmRlciBvZiB0YWJzIHdpbGwgcmVtYWluIHVuY2hhbmdlZC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHZpZXcgVGhlIGlkZW50aXR5IG9mIGFuIGV4aXN0aW5nIHZpZXcgdG8gYWRkLCBvciBvcHRpb25zIHRvIGNyZWF0ZSBhIHZpZXcuXG4gICAgICAgICAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbmFsIHZpZXcgb3B0aW9uczogaW5kZXggbnVtYmVyIHVzZWQgdG8gaW5zZXJ0IHRoZSB2aWV3IGludG8gdGhlIHN0YWNrIGF0IHRoYXQgaW5kZXguIERlZmF1bHRzIHRvIDAgKGZyb250IG9mIHRoZSBzdGFjaylcbiAgICAgICAgICogQHJldHVybnMgUmVzb2x2ZXMgd2l0aCB0aGUge0BsaW5rIE9wZW5GaW4uSWRlbnRpdHkgaWRlbnRpdHl9IG9mIHRoZSBhZGRlZCB2aWV3LlxuICAgICAgICAgKiBAdGhyb3dzIElmIHRoZSB2aWV3IGRvZXMgbm90IGV4aXN0IG9yIGZhaWxzIHRvIGNyZWF0ZS5cbiAgICAgICAgICogQHRocm93cyBJZiB0aGUge0BsaW5rIFRhYlN0YWNrfSBoYXMgYmVlbiBkZXN0cm95ZWQuXG4gICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAqIGBgYGpzXG4gICAgICAgICAqIGlmICghZmluLm1lLmlzVmlldykge1xuICAgICAgICAgKiAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgcnVubmluZyBpbiBhIHBsYXRmb3JtIFZpZXcuJyk7XG4gICAgICAgICAqIH1cbiAgICAgICAgICpcbiAgICAgICAgICogY29uc3Qgc3RhY2sgPSBhd2FpdCBmaW4ubWUuZ2V0Q3VycmVudFN0YWNrKCk7XG4gICAgICAgICAqIC8vIEFsdGVybmF0aXZlbHksIHlvdSBjYW4gd3JhcCBhbnkgdmlldyBhbmQgZ2V0IHRoZSBzdGFjayBmcm9tIHRoZXJlXG4gICAgICAgICAqIC8vIGNvbnN0IHZpZXdGcm9tU29tZXdoZXJlID0gZmluLlZpZXcud3JhcFN5bmMoc29tZVZpZXcuaWRlbnRpdHkpO1xuICAgICAgICAgKiAvLyBjb25zdCBzdGFjayA9IGF3YWl0IHZpZXdGcm9tU29tZXdoZXJlLmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiBjb25zdCBnb29nbGVWaWV3SWRlbnRpdHkgPSBhd2FpdCBzdGFjay5hZGRWaWV3KHsgbmFtZTogJ2dvb2dsZS12aWV3JywgdXJsOiAnaHR0cDovL2dvb2dsZS5jb20vJyB9KTtcbiAgICAgICAgICogY29uc29sZS5sb2coJ0lkZW50aXR5IG9mIHRoZSBnb29nbGUgdmlldyBqdXN0IGFkZGVkJywgeyBnb29nbGVWaWV3SWRlbnRpdHkgfSk7XG4gICAgICAgICAqIC8vIHBhc3MgaW4geyBpbmRleDogbnVtYmVyIH0gdG8gc2V0IHRoZSBpbmRleCBpbiB0aGUgc3RhY2suIEhlcmUgMSBtZWFucywgZW5kIG9mIHRoZSBzdGFjayAoZGVmYXVsdHMgdG8gMClcbiAgICAgICAgICogY29uc3QgYXBwbGVWaWV3SWRlbnRpdHkgPSBhd2FpdCBzdGFjay5hZGRWaWV3KHsgbmFtZTogJ2FwcGxlLXZpZXcnLCB1cmw6ICdodHRwOi8vYXBwbGUuY29tLycgfSwgeyBpbmRleDogMSB9KTtcbiAgICAgICAgICogY29uc29sZS5sb2coJ0lkZW50aXR5IG9mIHRoZSBhcHBsZSB2aWV3IGp1c3QgYWRkZWQnLCB7IGFwcGxlVmlld0lkZW50aXR5IH0pO1xuICAgICAgICAgKiBgYGBcbiAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5hZGRWaWV3ID0gYXN5bmMgKHZpZXcsIG9wdGlvbnMgPSB7IGluZGV4OiAwIH0pID0+IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZCh0aGlzLCBfVGFiU3RhY2tfY2xpZW50LCBcImZcIikuYWRkVmlld1RvU3RhY2sodGhpcy5lbnRpdHlJZCwgdmlldywgb3B0aW9ucyk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZW1vdmVzIGEgdmlldyBmcm9tIHRoaXMge0BsaW5rIFRhYlN0YWNrfS5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJlbWFya3MgVGhyb3dzIGFuIGV4Y2VwdGlvbiBpZiB0aGUgdmlldyBpZGVudGl0eSBkb2VzIG5vdCBleGlzdCBvciB3YXMgYWxyZWFkeSBkZXN0cm95ZWQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB2aWV3IC0gSWRlbnRpdHkgb2YgdGhlIHZpZXcgdG8gcmVtb3ZlLlxuICAgICAgICAgKiBAdGhyb3dzIElmIHRoZSB2aWV3IGRvZXMgbm90IGV4aXN0IG9yIGRvZXMgbm90IGJlbG9uZyB0byB0aGUgc3RhY2suXG4gICAgICAgICAqIEB0aHJvd3MgSWYgdGhlIHtAbGluayBUYWJTdGFja30gaGFzIGJlZW4gZGVzdHJveWVkLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBpZiAoIWZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3LicpO1xuICAgICAgICAgKiB9XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiBjb25zdCBnb29nbGVWaWV3SWRlbnRpdHkgPSBhd2FpdCBzdGFjay5hZGRWaWV3KHsgbmFtZTogJ2dvb2dsZS12aWV3JywgdXJsOiAnaHR0cDovL2dvb2dsZS5jb20vJyB9KTtcbiAgICAgICAgICpcbiAgICAgICAgICogYXdhaXQgc3RhY2sucmVtb3ZlVmlldyhnb29nbGVWaWV3SWRlbnRpdHkpO1xuICAgICAgICAgKlxuICAgICAgICAgKiB0cnkge1xuICAgICAgICAgKiAgICAgYXdhaXQgc3RhY2sucmVtb3ZlVmlldyhnb29nbGVWaWV3SWRlbnRpdHkpO1xuICAgICAgICAgKiB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgKiAgICAgLy8gVHJpZWQgdG8gcmVtb3ZlIGEgdmlldyAoJ2dvb2dsZS12aWV3Jykgd2hpY2ggZG9lcyBub3QgYmVsb25nIHRvIHRoZSBzdGFjay5cbiAgICAgICAgICogICAgIGNvbnNvbGUubG9nKGVycm9yKTtcbiAgICAgICAgICogfVxuICAgICAgICAgKiBgYGBcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMucmVtb3ZlVmlldyA9IGFzeW5jICh2aWV3KSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX1RhYlN0YWNrX2NsaWVudCwgXCJmXCIpLnJlbW92ZVZpZXdGcm9tU3RhY2sodGhpcy5lbnRpdHlJZCwgdmlldyk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTZXRzIHRoZSBhY3RpdmUgdmlldyBvZiB0aGUge0BsaW5rIFRhYlN0YWNrfSB3aXRob3V0IGZvY3VzaW5nIGl0LlxuICAgICAgICAgKiBAcGFyYW0gdmlldyAtIElkZW50aXR5IG9mIHRoZSB2aWV3IHRvIGFjdGl2YXRlLlxuICAgICAgICAgKiBAcmV0dXJucyBQcm9taXNlIHdoaWNoIHJlc29sdmVzIHdpdGggdm9pZCBvbmNlIHRoZSB2aWV3IGhhcyBiZWVuIGFjdGl2YXRlZC5cbiAgICAgICAgICogQHRocm93cyBJZiB0aGUge0BsaW5rIFRhYlN0YWNrfSBoYXMgYmVlbiBkZXN0cm95ZWQuXG4gICAgICAgICAqIEB0aHJvd3MgSWYgdGhlIHZpZXcgZG9lcyBub3QgZXhpc3QuXG4gICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAqIENoYW5nZSB0aGUgYWN0aXZlIHRhYiBvZiBhIGtub3duIFZpZXcncyBUYWJTdGFjazpcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogY29uc3QgdGFyZ2V0VmlldyA9IGZpbi5WaWV3LndyYXBTeW5jKHsgdXVpZDogJ3V1aWQnLCBuYW1lOiAndmlldy1uYW1lJyB9KTtcbiAgICAgICAgICogY29uc3Qgc3RhY2sgPSBhd2FpdCB0YXJnZXRWaWV3LmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiBhd2FpdCBzdGFjay5zZXRBY3RpdmVWaWV3KHRhcmdldFZpZXcuaWRlbnRpdHkpO1xuICAgICAgICAgKiBgYGBcbiAgICAgICAgICpcbiAgICAgICAgICogU2V0IHRoZSBjdXJyZW50IFZpZXcgYXMgYWN0aXZlIHdpdGhpbiBpdHMgVGFiU3RhY2s6XG4gICAgICAgICAqIGBgYGpzXG4gICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiBhd2FpdCBzdGFjay5zZXRBY3RpdmVWaWV3KGZpbi5tZS5pZGVudGl0eSk7XG4gICAgICAgICAqIGBgYFxuICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnNldEFjdGl2ZVZpZXcgPSBhc3luYyAodmlldykgPT4ge1xuICAgICAgICAgICAgYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRkKHRoaXMsIF9UYWJTdGFja19jbGllbnQsIFwiZlwiKS5zZXRTdGFja0FjdGl2ZVZpZXcodGhpcy5lbnRpdHlJZCwgdmlldyk7XG4gICAgICAgIH07XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkYih0aGlzLCBfVGFiU3RhY2tfY2xpZW50LCBjbGllbnQsIFwiZlwiKTtcbiAgICB9XG59XG5sYXlvdXRFbnRpdGllcy5UYWJTdGFjayA9IFRhYlN0YWNrO1xuX1RhYlN0YWNrX2NsaWVudCA9IG5ldyBXZWFrTWFwKCk7XG4vKipcbiAqIEEgQ29sdW1uT3JSb3cgaXMgdXNlZCB0byBtYW5hZ2UgdGhlIHN0YXRlIG9mIENvbHVtbiBhbmQgUm93cyB3aXRoaW4gYW4gT3BlbkZpbiBMYXlvdXQuXG4gKi9cbmNsYXNzIENvbHVtbk9yUm93IGV4dGVuZHMgTGF5b3V0Tm9kZSB7XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2xpZW50LCBlbnRpdHlJZCwgdHlwZSkge1xuICAgICAgICBzdXBlcihjbGllbnQsIGVudGl0eUlkKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBpZ25vcmVcbiAgICAgICAgICogQGludGVybmFsXG4gICAgICAgICAqIEFwaUNsaWVudCBmb3Ige0BsaW5rIExheW91dEVudGl0aWVzQ29udHJvbGxlcn1cbiAgICAgICAgICovXG4gICAgICAgIF9Db2x1bW5PclJvd19jbGllbnQuc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXRyaWV2ZXMgdGhlIGNvbnRlbnQgYXJyYXkgb2YgdGhlIENvbHVtbk9yUm93XG4gICAgICAgICAqXG4gICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAqIGBgYGpzXG4gICAgICAgICAqIGlmICghZmluLm1lLmlzVmlldykge1xuICAgICAgICAgKiAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgcnVubmluZyBpbiBhIHBsYXRmb3JtIFZpZXcuJyk7XG4gICAgICAgICAqIH1cbiAgICAgICAgICpcbiAgICAgICAgICogY29uc3Qgc3RhY2sgPSBhd2FpdCBmaW4ubWUuZ2V0Q3VycmVudFN0YWNrKCk7XG4gICAgICAgICAqIC8vIFJldHJpZXZlcyB0aGUgcGFyZW50IENvbHVtbk9yUm93XG4gICAgICAgICAqIGNvbnN0IGNvbHVtbk9yUm93ID0gYXdhaXQgc3RhY2suZ2V0UGFyZW50KCk7XG4gICAgICAgICAqXG4gICAgICAgICAqIC8vIHJldHVybnMgW1RhYlN0YWNrXVxuICAgICAgICAgKiBjb25zdCBjb250ZW50QXJyYXkgPSBhd2FpdCBjb2x1bW5PclJvdy5nZXRDb250ZW50KCk7XG4gICAgICAgICAqIGNvbnNvbGUubG9nKGBUaGUgQ29sdW1uT3JSb3cgaGFzICR7Y29udGVudEFycmF5Lmxlbmd0aH0gaXRlbShzKWApO1xuICAgICAgICAgKiBgYGBcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZ2V0Q29udGVudCA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbnRlbnRJdGVtRW50aXRpZXMgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX0NvbHVtbk9yUm93X2NsaWVudCwgXCJmXCIpLmdldENvbnRlbnQodGhpcy5lbnRpdHlJZCk7XG4gICAgICAgICAgICByZXR1cm4gY29udGVudEl0ZW1FbnRpdGllcy5tYXAoKGVudGl0eSkgPT4gTGF5b3V0Tm9kZS5nZXRFbnRpdHkoZW50aXR5LCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX0NvbHVtbk9yUm93X2NsaWVudCwgXCJmXCIpKSk7XG4gICAgICAgIH07XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkYih0aGlzLCBfQ29sdW1uT3JSb3dfY2xpZW50LCBjbGllbnQsIFwiZlwiKTtcbiAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB9XG59XG5sYXlvdXRFbnRpdGllcy5Db2x1bW5PclJvdyA9IENvbHVtbk9yUm93O1xuX0NvbHVtbk9yUm93X2NsaWVudCA9IG5ldyBXZWFrTWFwKCk7XG5cbnZhciBsYXlvdXRfY29uc3RhbnRzID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShsYXlvdXRfY29uc3RhbnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmxheW91dF9jb25zdGFudHMuREVGQVVMVF9MQVlPVVRfS0VZID0gbGF5b3V0X2NvbnN0YW50cy5MQVlPVVRfQ09OVFJPTExFUl9JRCA9IHZvaWQgMDtcbmxheW91dF9jb25zdGFudHMuTEFZT1VUX0NPTlRST0xMRVJfSUQgPSAnbGF5b3V0LWVudGl0aWVzJztcbi8vIFRPRE86IGV2ZW50dWFsbHkgZXhwb3J0IHRoaXMgc29tZWhvd1xubGF5b3V0X2NvbnN0YW50cy5ERUZBVUxUX0xBWU9VVF9LRVkgPSAnX19kZWZhdWx0X18nO1xuXG52YXIgbWFpbiA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkobWFpbiwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5tYWluLldlYkNvbnRlbnRzID0gdm9pZCAwO1xuY29uc3QgYmFzZV8xJGogPSBiYXNlO1xuY2xhc3MgV2ViQ29udGVudHMgZXh0ZW5kcyBiYXNlXzEkai5FbWl0dGVyQmFzZSB7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIGlkZW50aXR5IFRoZSBpZGVudGl0eSBvZiB0aGUge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgV2ViQ29udGVudHN9LlxuICAgICAqIEBwYXJhbSBlbnRpdHlUeXBlIFRoZSB0eXBlIG9mIHRoZSB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBXZWJDb250ZW50c30uXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iod2lyZSwgaWRlbnRpdHksIGVudGl0eVR5cGUpIHtcbiAgICAgICAgc3VwZXIod2lyZSwgZW50aXR5VHlwZSwgaWRlbnRpdHkudXVpZCwgaWRlbnRpdHkubmFtZSk7XG4gICAgICAgIHRoaXMuaWRlbnRpdHkgPSBpZGVudGl0eTtcbiAgICAgICAgdGhpcy5lbnRpdHlUeXBlID0gZW50aXR5VHlwZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0cyBhIGJhc2U2NCBlbmNvZGVkIGltYWdlIG9mIGFsbCBvciBwYXJ0IG9mIHRoZSBXZWJDb250ZW50cy5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25zIGZvciB0aGUgY2FwdHVyZVBhZ2UgY2FsbC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgdmlldyA9IGZpbi5WaWV3LmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICpcbiAgICAgKiAvLyBQTkcgaW1hZ2Ugb2YgYSBmdWxsIHZpc2libGUgVmlld1xuICAgICAqIGNvbnNvbGUubG9nKGF3YWl0IHZpZXcuY2FwdHVyZVBhZ2UoKSk7XG4gICAgICpcbiAgICAgKiAvLyBMb3ctcXVhbGl0eSBKUEVHIGltYWdlIG9mIGEgZGVmaW5lZCB2aXNpYmxlIGFyZWEgb2YgdGhlIHZpZXdcbiAgICAgKiBjb25zdCBvcHRpb25zID0ge1xuICAgICAqICAgICBhcmVhOiB7XG4gICAgICogICAgICAgICBoZWlnaHQ6IDEwMCxcbiAgICAgKiAgICAgICAgIHdpZHRoOiAxMDAsXG4gICAgICogICAgICAgICB4OiAxMCxcbiAgICAgKiAgICAgICAgIHk6IDEwLFxuICAgICAqICAgICB9LFxuICAgICAqICAgICBmb3JtYXQ6ICdqcGcnLFxuICAgICAqICAgICBxdWFsaXR5OiAyMFxuICAgICAqIH1cbiAgICAgKiBjb25zb2xlLmxvZyhhd2FpdCB2aWV3LmNhcHR1cmVQYWdlKG9wdGlvbnMpKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFdpbmRvdzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHduZCA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuICAgICAqXG4gICAgICogLy8gUE5HIGltYWdlIG9mIGEgZnVsbCB2aXNpYmxlIHdpbmRvd1xuICAgICAqIGNvbnNvbGUubG9nKGF3YWl0IHduZC5jYXB0dXJlUGFnZSgpKTtcbiAgICAgKlxuICAgICAqIC8vIExvdy1xdWFsaXR5IEpQRUcgaW1hZ2Ugb2YgYSBkZWZpbmVkIHZpc2libGUgYXJlYSBvZiB0aGUgd2luZG93XG4gICAgICogY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgKiAgICAgYXJlYToge1xuICAgICAqICAgICAgICAgaGVpZ2h0OiAxMDAsXG4gICAgICogICAgICAgICB3aWR0aDogMTAwLFxuICAgICAqICAgICAgICAgeDogMTAsXG4gICAgICogICAgICAgICB5OiAxMCxcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgZm9ybWF0OiAnanBnJyxcbiAgICAgKiAgICAgcXVhbGl0eTogMjBcbiAgICAgKiB9XG4gICAgICogY29uc29sZS5sb2coYXdhaXQgd25kLmNhcHR1cmVQYWdlKG9wdGlvbnMpKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBjYXB0dXJlUGFnZShvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignY2FwdHVyZS1wYWdlJywgeyBvcHRpb25zLCAuLi50aGlzLmlkZW50aXR5IH0pLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlcyBKYXZhc2NyaXB0IG9uIHRoZSBXZWJDb250ZW50cywgcmVzdHJpY3RlZCB0byBjb250ZW50cyB5b3Ugb3duIG9yIGNvbnRlbnRzIG93bmVkIGJ5XG4gICAgICogYXBwbGljYXRpb25zIHlvdSBoYXZlIGNyZWF0ZWQuXG4gICAgICogQHBhcmFtIGNvZGUgSmF2YVNjcmlwdCBjb2RlIHRvIGJlIGV4ZWN1dGVkIG9uIHRoZSB2aWV3LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gZXhlY3V0ZUphdmFTY3JpcHQoY29kZSkge1xuICAgICAqICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcud3JhcCh7dXVpZDogJ3V1aWQnLCBuYW1lOiAndmlldyBuYW1lJ30pO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgdmlldy5leGVjdXRlSmF2YVNjcmlwdChjb2RlKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBleGVjdXRlSmF2YVNjcmlwdChgY29uc29sZS5sb2coJ0hlbGxvLCBPcGVuZmluJylgKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdKYXZhc2NyaXB0IGV4Y3V0ZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gZXhlY3V0ZUphdmFTY3JpcHQoY29kZSkge1xuICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcbiAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG4gICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmV4ZWN1dGVKYXZhU2NyaXB0Lmh0bWwnLFxuICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcbiAgICAgKiAgICAgfSk7XG4gICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5leGVjdXRlSmF2YVNjcmlwdChjb2RlKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBleGVjdXRlSmF2YVNjcmlwdChgY29uc29sZS5sb2coJ0hlbGxvLCBPcGVuZmluJylgKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdKYXZhc2NyaXB0IGV4Y3V0ZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBleGVjdXRlSmF2YVNjcmlwdChjb2RlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmVcbiAgICAgICAgICAgIC5zZW5kQWN0aW9uKCdleGVjdXRlLWphdmFzY3JpcHQtaW4td2luZG93JywgeyAuLi50aGlzLmlkZW50aXR5LCBjb2RlIH0pXG4gICAgICAgICAgICAudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIFdlYkNvbnRlbnRzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0Wm9vbUxldmVsKCkge1xuICAgICAqICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcuZ2V0Q3VycmVudCgpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgdmlldy5nZXRab29tTGV2ZWwoKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBnZXRab29tTGV2ZWwoKS50aGVuKHpvb21MZXZlbCA9PiBjb25zb2xlLmxvZyh6b29tTGV2ZWwpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVXaW4oKSB7XG4gICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG4gICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcbiAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZ2V0Wm9vbUxldmVsLmh0bWwnLFxuICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcbiAgICAgKiAgICAgfSk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0Wm9vbUxldmVsKCkge1xuICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBjcmVhdGVXaW4oKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5nZXRab29tTGV2ZWwoKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBnZXRab29tTGV2ZWwoKS50aGVuKHpvb21MZXZlbCA9PiBjb25zb2xlLmxvZyh6b29tTGV2ZWwpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIGdldFpvb21MZXZlbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtem9vbS1sZXZlbCcsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSBXZWJDb250ZW50cy5cbiAgICAgKiBAcGFyYW0gbGV2ZWwgVGhlIHpvb20gbGV2ZWxcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNldFpvb21MZXZlbChudW1iZXIpIHtcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHZpZXcuc2V0Wm9vbUxldmVsKG51bWJlcik7XG4gICAgICogfVxuICAgICAqXG4gICAgICogc2V0Wm9vbUxldmVsKDQpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1NldHRpbmcgYSAgem9vbSBsZXZlbCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVXaW4oKSB7XG4gICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG4gICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcbiAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuc2V0Wm9vbUxldmVsLmh0bWwnLFxuICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcbiAgICAgKiAgICAgfSk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogYXN5bmMgZnVuY3Rpb24gc2V0Wm9vbUxldmVsKG51bWJlcikge1xuICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBjcmVhdGVXaW4oKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5zZXRab29tTGV2ZWwobnVtYmVyKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBzZXRab29tTGV2ZWwoNCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU2V0dGluZyBhICB6b29tIGxldmVsJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIGBXZWJDb250ZW50c2AgcmVmZXJzIHRvIHNoYXJlZCBmdW5jdGlvbmFsaXR5IGJldHdlZW4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gICAgICogV2UgZG8gbm90IGV4cG9zZSBhbiBleHBsaWNpdCBzdXBlcmNsYXNzIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHksIGJ1dCBpdCBkb2VzIGhhdmUgaXRzIG93blxuICAgICAqIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIGV2ZW50IG5hbWVzcGFjZX0uXG4gICAgICovXG4gICAgc2V0Wm9vbUxldmVsKGxldmVsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignc2V0LXpvb20tbGV2ZWwnLCB7IC4uLnRoaXMuaWRlbnRpdHksIGxldmVsIH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogTmF2aWdhdGVzIHRoZSBXZWJDb250ZW50cyB0byBhIHNwZWNpZmllZCBVUkwuXG4gICAgICpcbiAgICAgKiBOb3RlOiBUaGUgdXJsIG11c3QgY29udGFpbiB0aGUgcHJvdG9jb2wgcHJlZml4IHN1Y2ggYXMgaHR0cDovLyBvciBodHRwczovLy5cbiAgICAgKiBAcGFyYW0gdXJsIC0gVGhlIFVSTCB0byBuYXZpZ2F0ZSB0aGUgV2ViQ29udGVudHMgdG8uXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVWaWV3KCkge1xuICAgICAqICAgICBjb25zdCBtZSA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuICAgICAqICAgICByZXR1cm4gZmluLlZpZXcuY3JlYXRlKHtcbiAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZScsXG4gICAgICogICAgICAgICB0YXJnZXQ6IG1lLmlkZW50aXR5LFxuICAgICAqICAgICAgICAgYm91bmRzOiB7dG9wOiAxMCwgbGVmdDogMTAsIHdpZHRoOiAyMDAsIGhlaWdodDogMjAwfVxuICAgICAqICAgICB9KTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBjcmVhdGVWaWV3KClcbiAgICAgKiAgICAgLnRoZW4odmlldyA9PiB2aWV3Lm5hdmlnYXRlKCdodHRwczovL2V4YW1wbGUuY29tJykpXG4gICAgICogICAgIC50aGVuKCgpID0+IGNvbnNvbGUubG9nKCduYXZpZ2F0aW9uIGNvbXBsZXRlJykpXG4gICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBuYXZpZ2F0ZSgpIHtcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCB3aW4ubmF2aWdhdGUoJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cubmF2aWdhdGUuaHRtbCcpO1xuICAgICAqIH1cbiAgICAgKiBuYXZpZ2F0ZSgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ05hdmlnYXRlIHRvIHR1dG9yaWFsJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIG5hdmlnYXRlKHVybCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ25hdmlnYXRlLXdpbmRvdycsIHsgLi4udGhpcy5pZGVudGl0eSwgdXJsIH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogTmF2aWdhdGVzIHRoZSBXZWJDb250ZW50cyBiYWNrIG9uZSBwYWdlLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gbmF2aWdhdGVCYWNrKCkge1xuICAgICAqICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcud3JhcCh7IG5hbWU6ICd0ZXN0YXBwLXZpZXcnLCB1dWlkOiAndGVzdGFwcCcgfSk7XG4gICAgICogICAgIGF3YWl0IHZpZXcubmF2aWdhdGUoJ2h0dHBzOi8vd3d3Lmdvb2dsZS5jb20nKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHZpZXcubmF2aWdhdGVCYWNrKCk7XG4gICAgICogfVxuICAgICAqIG5hdmlnYXRlQmFjaygpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ05hdmlnYXRlZCBiYWNrJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFdpbmRvdzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIG5hdmlnYXRlQmFjaygpIHtcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy53cmFwKHsgbmFtZTogJ3Rlc3RhcHAnLCB1dWlkOiAndGVzdGFwcCcgfSk7XG4gICAgICogICAgIGF3YWl0IHdpbi5uYXZpZ2F0ZSgnaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbScpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLm5hdmlnYXRlQmFjaygpO1xuICAgICAqIH1cbiAgICAgKiBuYXZpZ2F0ZUJhY2soKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdOYXZpZ2F0ZWQgYmFjaycpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIG5hdmlnYXRlQmFjaygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCduYXZpZ2F0ZS13aW5kb3ctYmFjaycsIHsgLi4udGhpcy5pZGVudGl0eSB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE5hdmlnYXRlcyB0aGUgV2ViQ29udGVudHMgZm9yd2FyZCBvbmUgcGFnZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIG5hdmlnYXRlRm9yd2FyZCgpIHtcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbScpO1xuICAgICAqICAgICBhd2FpdCB2aWV3Lm5hdmlnYXRlQmFjaygpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgdmlldy5uYXZpZ2F0ZUZvcndhcmQoKTtcbiAgICAgKiB9XG4gICAgICogbmF2aWdhdGVGb3J3YXJkKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnTmF2aWdhdGVkIGZvcndhcmQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gbmF2aWdhdGVGb3J3YXJkKCkge1xuICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgYXdhaXQgd2luLm5hdmlnYXRlKCdodHRwczovL3d3dy5nb29nbGUuY29tJyk7XG4gICAgICogICAgIGF3YWl0IHdpbi5uYXZpZ2F0ZUJhY2soKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5uYXZpZ2F0ZUZvcndhcmQoKTtcbiAgICAgKiB9XG4gICAgICogbmF2aWdhdGVGb3J3YXJkKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnTmF2aWdhdGVkIGZvcndhcmQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBhc3luYyBuYXZpZ2F0ZUZvcndhcmQoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCduYXZpZ2F0ZS13aW5kb3ctZm9yd2FyZCcsIHsgLi4udGhpcy5pZGVudGl0eSB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3RvcHMgYW55IGN1cnJlbnQgbmF2aWdhdGlvbiB0aGUgV2ViQ29udGVudHMgaXMgcGVyZm9ybWluZy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIHN0b3BOYXZpZ2F0aW9uKCkge1xuICAgICAqICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcud3JhcCh7IG5hbWU6ICd0ZXN0YXBwLXZpZXcnLCB1dWlkOiAndGVzdGFwcCcgfSk7XG4gICAgICogICAgIGF3YWl0IHZpZXcubmF2aWdhdGUoJ2h0dHBzOi8vd3d3Lmdvb2dsZS5jb20nKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHZpZXcuc3RvcE5hdmlnYXRpb24oKTtcbiAgICAgKiB9XG4gICAgICogc3RvcE5hdmlnYXRpb24oKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCd5b3Ugc2hhbGwgbm90IG5hdmlnYXRlJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFdpbmRvdzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIHN0b3BOYXZpZ2F0aW9uKCkge1xuICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBmaW4uV2luZG93LndyYXAoeyBuYW1lOiAndGVzdGFwcCcsIHV1aWQ6ICd0ZXN0YXBwJyB9KTtcbiAgICAgKiAgICAgYXdhaXQgd2luLm5hdmlnYXRlKCdodHRwczovL3d3dy5nb29nbGUuY29tJyk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uc3RvcE5hdmlnYXRpb24oKTtcbiAgICAgKiB9XG4gICAgICogc3RvcE5hdmlnYXRpb24oKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCd5b3Ugc2hhbGwgbm90IG5hdmlnYXRlJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIGBXZWJDb250ZW50c2AgcmVmZXJzIHRvIHNoYXJlZCBmdW5jdGlvbmFsaXR5IGJldHdlZW4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gICAgICogV2UgZG8gbm90IGV4cG9zZSBhbiBleHBsaWNpdCBzdXBlcmNsYXNzIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHksIGJ1dCBpdCBkb2VzIGhhdmUgaXRzIG93blxuICAgICAqIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIGV2ZW50IG5hbWVzcGFjZX0uXG4gICAgICovXG4gICAgc3RvcE5hdmlnYXRpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignc3RvcC13aW5kb3ctbmF2aWdhdGlvbicsIHsgLi4udGhpcy5pZGVudGl0eSB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbG9hZHMgdGhlIFdlYkNvbnRlbnRzXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiByZWxvYWQoKSB7XG4gICAgICogXHRjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcuZ2V0Q3VycmVudCgpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgdmlldy5yZWxvYWQoKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiByZWxvYWQoKS50aGVuKCgpID0+IHtcbiAgICAgKiBcdFx0Y29uc29sZS5sb2coJ1JlbG9hZGVkIHZpZXcnKVxuICAgICAqIH0pLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFdpbmRvdzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIHJlbG9hZFdpbmRvdygpIHtcbiAgICAgKiBcdFx0Y29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcbiAgICAgKiBcdFx0XHRcdG5hbWU6ICdteUFwcCcsXG4gICAgICogXHRcdFx0XHR1dWlkOiAnYXBwLTEnLFxuICAgICAqIFx0XHRcdFx0dXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5yZWxvYWQuaHRtbCcsXG4gICAgICogXHRcdFx0XHRhdXRvU2hvdzogdHJ1ZVxuICAgICAqIFx0XHR9KTtcbiAgICAgKiBcdFx0Y29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLnJlbG9hZCgpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHJlbG9hZFdpbmRvdygpLnRoZW4oKCkgPT4ge1xuICAgICAqIFx0XHRjb25zb2xlLmxvZygnUmVsb2FkZWQgd2luZG93JylcbiAgICAgKiB9KS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIHJlbG9hZChpZ25vcmVDYWNoZSA9IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmVcbiAgICAgICAgICAgIC5zZW5kQWN0aW9uKCdyZWxvYWQtd2luZG93Jywge1xuICAgICAgICAgICAgaWdub3JlQ2FjaGUsXG4gICAgICAgICAgICAuLi50aGlzLmlkZW50aXR5XG4gICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBQcmludHMgdGhlIFdlYkNvbnRlbnRzLlxuICAgICAqIEBwYXJhbSBvcHRpb25zIFByaW50ZXIgT3B0aW9uc1xuICAgICAqXG4gICAgICogTm90ZTogV2hlbiBgc2lsZW50YCBpcyBzZXQgdG8gYHRydWVgLCB0aGUgQVBJIHdpbGwgcGljayB0aGUgc3lzdGVtJ3MgZGVmYXVsdCBwcmludGVyIGlmIGRldmljZU5hbWVcbiAgICAgKiBpcyBlbXB0eSBhbmQgdGhlIGRlZmF1bHQgc2V0dGluZ3MgZm9yIHByaW50aW5nLlxuICAgICAqXG4gICAgICogVXNlIHRoZSBDU1Mgc3R5bGUgYHBhZ2UtYnJlYWstYmVmb3JlOiBhbHdheXM7YCB0byBmb3JjZSBwcmludCB0byBhIG5ldyBwYWdlLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHZpZXcgPSBmaW4uVmlldy5nZXRDdXJyZW50U3luYygpO1xuICAgICAqXG4gICAgICogdmlldy5wcmludCh7IHNpbGVudDogZmFsc2UsIGRldmljZU5hbWU6ICdzeXN0ZW0tcHJpbnRlci1uYW1lJyB9KS50aGVuKCgpID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ3ByaW50IGNhbGwgaGFzIGJlZW4gc2VudCB0byB0aGUgc3lzdGVtJyk7XG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIHByaW50KG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3ByaW50JywgeyAuLi50aGlzLmlkZW50aXR5LCBvcHRpb25zIH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRmluZCBhbmQgaGlnaGxpZ2h0IHRleHQgb24gYSBwYWdlLlxuICAgICAqIEBwYXJhbSBzZWFyY2hUZXJtIFRlcm0gdG8gZmluZCBpbiBwYWdlXG4gICAgICogQHBhcmFtIG9wdGlvbnMgU2VhcmNoIG9wdGlvbnNcbiAgICAgKlxuICAgICAqIE5vdGU6IEJ5IGRlZmF1bHQsIGVhY2ggc3Vic2VxdWVudCBjYWxsIHdpbGwgaGlnaGxpZ2h0IHRoZSBuZXh0IHRleHQgdGhhdCBtYXRjaGVzIHRoZSBzZWFyY2ggdGVybS5cbiAgICAgKlxuICAgICAqIFJldHVybnMgYSBwcm9taXNlIHdpdGggdGhlIHJlc3VsdHMgZm9yIHRoZSByZXF1ZXN0LiBCeSBzdWJzY3JpYmluZyB0byB0aGVcbiAgICAgKiBmb3VuZC1pbi1wYWdlIGV2ZW50LCB5b3UgY2FuIGdldCB0aGUgcmVzdWx0cyBvZiB0aGlzIGNhbGwgYXMgd2VsbC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHZpZXcgPSBmaW4uVmlldy5nZXRDdXJyZW50U3luYygpO1xuICAgICAqXG4gICAgICogLy9CeSBzdWJzY3JpYmluZyB0byB0aGUgJ2ZvdW5kIGluIHBhZ2UnIGV2ZW50IHdlIGNhbiBnZXQgdGhlIHJlc3VsdHMgb2YgZWFjaCBmaW5kSW5QYWdlIGNhbGwgbWFkZS5cbiAgICAgKiB2aWV3LmFkZExpc3RlbmVyKCdmb3VuZC1pbi1wYWdlJywgKGV2ZW50KSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKGV2ZW50KTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIC8vIFRoZSBwcm9taXNlIGFsc28gcmV0dXJucyB0aGUgcmVzdWx0cyBmb3IgdGhlIHJlcXVlc3RcbiAgICAgKiB2aWV3LmZpbmRJblBhZ2UoJ2EnKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2cocmVzdWx0KVxuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3Qgd2luID0gZmluLldpbmRvdy5nZXRDdXJyZW50U3luYygpO1xuICAgICAqXG4gICAgICogLy9CeSBzdWJzY3JpYmluZyB0byB0aGUgJ2ZvdW5kIGluIHBhZ2UnIGV2ZW50IHdlIGNhbiBnZXQgdGhlIHJlc3VsdHMgb2YgZWFjaCBmaW5kSW5QYWdlIGNhbGwgbWFkZS5cbiAgICAgKiB3aW4uYWRkTGlzdGVuZXIoJ2ZvdW5kLWluLXBhZ2UnLCAoZXZlbnQpID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coZXZlbnQpO1xuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogLy8gVGhlIHByb21pc2UgYWxzbyByZXR1cm5zIHRoZSByZXN1bHRzIGZvciB0aGUgcmVxdWVzdFxuICAgICAqIHdpbi5maW5kSW5QYWdlKCdhJykudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKHJlc3VsdClcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIGBXZWJDb250ZW50c2AgcmVmZXJzIHRvIHNoYXJlZCBmdW5jdGlvbmFsaXR5IGJldHdlZW4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gICAgICogV2UgZG8gbm90IGV4cG9zZSBhbiBleHBsaWNpdCBzdXBlcmNsYXNzIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHksIGJ1dCBpdCBkb2VzIGhhdmUgaXRzIG93blxuICAgICAqIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIGV2ZW50IG5hbWVzcGFjZX0uXG4gICAgICovXG4gICAgZmluZEluUGFnZShzZWFyY2hUZXJtLCBvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmVcbiAgICAgICAgICAgIC5zZW5kQWN0aW9uKCdmaW5kLWluLXBhZ2UnLCB7IC4uLnRoaXMuaWRlbnRpdHksIHNlYXJjaFRlcm0sIG9wdGlvbnMgfSlcbiAgICAgICAgICAgIC50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3RvcCBhIHtAbGluayBWaWV3I2ZpbmRJblBhZ2UgZmluZEluUGFnZX0gY2FsbCBieSBzcGVjaWZ5aW5nIGFueSBvZiB0aGVzZSBhY3Rpb25zOlxuICAgICAqXG4gICAgICogKiBjbGVhclNlbGVjdGlvbiAtIENsZWFyIHRoZSBzZWxlY3Rpb24uXG4gICAgICogKiBrZWVwU2VsZWN0aW9uIC0gVHJhbnNsYXRlIHRoZSBzZWxlY3Rpb24gaW50byBhIG5vcm1hbCBzZWxlY3Rpb24uXG4gICAgICogKiBhY3RpdmF0ZVNlbGVjdGlvbiAtIEZvY3VzIGFuZCBjbGljayB0aGUgc2VsZWN0aW9uIG5vZGUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCB2aWV3ID0gZmluLlZpZXcuZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKlxuICAgICAqIHZpZXcuYWRkTGlzdGVuZXIoJ2ZvdW5kLWluLXBhZ2UnLCAoZXZlbnQpID0+IHtcbiAgICAgKiAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICogICAgICAgICB2aWV3LnN0b3BGaW5kSW5QYWdlKCdjbGVhclNlbGVjdGlvbicpO1xuICAgICAqICAgICB9LCA1MDAwKTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHZpZXcuZmluZEluUGFnZSgnYScpLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKHJlc3VsdHMpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3Qgd2luID0gZmluLldpbmRvdy5nZXRDdXJyZW50U3luYygpO1xuICAgICAqXG4gICAgICogd2luLmFkZExpc3RlbmVyKCdmb3VuZC1pbi1wYWdlJywgKGV2ZW50KSA9PiB7XG4gICAgICogICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAqICAgICAgICAgd2luLnN0b3BGaW5kSW5QYWdlKCdjbGVhclNlbGVjdGlvbicpO1xuICAgICAqICAgICB9LCA1MDAwKTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIHdpbi5maW5kSW5QYWdlKCdhJykudGhlbihyZXN1bHRzID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2cocmVzdWx0cyk7XG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIHN0b3BGaW5kSW5QYWdlKGFjdGlvbikge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3N0b3AtZmluZC1pbi1wYWdlJywgeyAuLi50aGlzLmlkZW50aXR5LCBhY3Rpb24gfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIGFycmF5IHdpdGggYWxsIHN5c3RlbSBwcmludGVyc1xuICAgICAqIEBkZXByZWNhdGVkIHVzZSBTeXN0ZW0uZ2V0UHJpbnRlcnMgaW5zdGVhZFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgdmlldyA9IGZpbi5WaWV3LmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICpcbiAgICAgKiB2aWV3LmdldFByaW50ZXJzKClcbiAgICAgKiAgICAgLnRoZW4oKHByaW50ZXJzKSA9PiB7XG4gICAgICogICAgICAgICBwcmludGVycy5mb3JFYWNoKChwcmludGVyKSA9PiB7XG4gICAgICogICAgICAgICAgICAgaWYgKHByaW50ZXIuaXNEZWZhdWx0KSB7XG4gICAgICogICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHByaW50ZXIpO1xuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgIH0pO1xuICAgICAqICAgICB9KVxuICAgICAqICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coZXJyKTtcbiAgICAgKiAgICAgfSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCB3aW4gPSBmaW4uV2luZG93LmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICpcbiAgICAgKiB3aW4uZ2V0UHJpbnRlcnMoKVxuICAgICAqICAgICAudGhlbigocHJpbnRlcnMpID0+IHtcbiAgICAgKiAgICAgICAgIHByaW50ZXJzLmZvckVhY2goKHByaW50ZXIpID0+IHtcbiAgICAgKiAgICAgICAgICAgICBpZiAocHJpbnRlci5pc0RlZmF1bHQpIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgY29uc29sZS5sb2cocHJpbnRlcik7XG4gICAgICogICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgfSk7XG4gICAgICogICAgIH0pXG4gICAgICogICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhlcnIpO1xuICAgICAqICAgICB9KTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIGBXZWJDb250ZW50c2AgcmVmZXJzIHRvIHNoYXJlZCBmdW5jdGlvbmFsaXR5IGJldHdlZW4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gICAgICogV2UgZG8gbm90IGV4cG9zZSBhbiBleHBsaWNpdCBzdXBlcmNsYXNzIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHksIGJ1dCBpdCBkb2VzIGhhdmUgaXRzIG93blxuICAgICAqIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIGV2ZW50IG5hbWVzcGFjZX0uXG4gICAgICovXG4gICAgZ2V0UHJpbnRlcnMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXByaW50ZXJzJywgeyAuLi50aGlzLmlkZW50aXR5IH0pLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHaXZlcyBmb2N1cyB0byB0aGUgV2ViQ29udGVudHMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gZm9jdXNXaW5kb3coKSB7XG4gICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG4gICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcbiAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZm9jdXMuaHRtbCcsXG4gICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuICAgICAqICAgICB9KTtcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmZvY3VzKCk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZm9jdXNXaW5kb3coKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdXaW5kb3cgZm9jdXNlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIGFzeW5jIGZvY3VzKHsgZW1pdFN5bnRoRm9jdXNlZCB9ID0geyBlbWl0U3ludGhGb2N1c2VkOiB0cnVlIH0pIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZvY3VzLXdpbmRvdycsIHsgZW1pdFN5bnRoRm9jdXNlZCwgLi4udGhpcy5pZGVudGl0eSB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2hvd3MgdGhlIENocm9taXVtIERldmVsb3BlciBUb29sc1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gc2hvd0RldmVsb3BlclRvb2xzKCkge1xuICAgICAqICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcuZ2V0Q3VycmVudCgpO1xuICAgICAqICAgICByZXR1cm4gdmlldy5zaG93RGV2ZWxvcGVyVG9vbHMoKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBzaG93RGV2ZWxvcGVydG9vbHMoKVxuICAgICAqIC50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTaG93aW5nIGRldiB0b29scycpKVxuICAgICAqIC5jYXRjaChlcnIgPT4gY29uc29sZS5lcnJvcihlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFdpbmRvdzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNob3dEZXZlbG9wZXJUb29scygpIHtcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG4gICAgICogICAgIHJldHVybiB3aW4uc2hvd0RldmVsb3BlclRvb2xzKCk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogc2hvd0RldmVsb3BlcnRvb2xzKClcbiAgICAgKiAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU2hvd2luZyBkZXYgdG9vbHMnKSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUuZXJyb3IoZXJyKSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIGFzeW5jIHNob3dEZXZlbG9wZXJUb29scygpIHtcbiAgICAgICAgLy8gTm90ZSB0aGlzIGhpdHMgdGhlIHN5c3RlbSBhY3Rpb24gbWFwIGluIGNvcmUgc3RhdGUgZm9yIGxlZ2FjeSByZWFzb25zLlxuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc2hvdy1kZXZlbG9wZXItdG9vbHMnLCB0aGlzLmlkZW50aXR5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBwcm9jZXNzIGluZm9ybWF0aW9uIGFzc29jaWF0ZWQgd2l0aCBhIFdlYkNvbnRlbnRzLlxuICAgICAqXG4gICAgICogTm90ZTogVGhpcyBpbmNsdWRlcyBhbnkgaWZyYW1lcyBhc3NvY2lhdGVkIHdpdGggdGhlIFdlYkNvbnRlbnRzXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgY29uc3QgcHJvY2Vzc0luZm8gPSBhd2FpdCB2aWV3LmdldFByb2Nlc3NJbmZvKCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG4gICAgICogICAgIGNvbnN0IHByb2Nlc3NJbmZvID0gYXdhaXQgd2luLmdldFByb2Nlc3NJbmZvKCk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIGFzeW5jIGdldFByb2Nlc3NJbmZvKCkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgZGF0YSB9IH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXByb2Nlc3MtaW5mbycsIHRoaXMuaWRlbnRpdHkpO1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGluZm9ybWF0aW9uIG9uIGFsbCBTaGFyZWQgV29ya2Vycy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcuY3JlYXRlKHtcbiAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZScsXG4gICAgICogICAgICAgICB0YXJnZXQ6IGZpbi5tZS5pZGVudGl0eSxcbiAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cbiAgICAgKiAgICAgfSk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9tZG4uZ2l0aHViLmlvL2RvbS1leGFtcGxlcy93ZWItd29ya2Vycy9zaW1wbGUtc2hhcmVkLXdvcmtlci8nKTtcbiAgICAgKlxuICAgICAqICAgICBjb25zdCBzaGFyZWRXb3JrZXJzID0gYXdhaXQgdmlldy5nZXRTaGFyZWRXb3JrZXJzKCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgY29uc3Qgd2luT3B0aW9uID0ge1xuICAgICAqICAgICAgICAgbmFtZTonY2hpbGQnLFxuICAgICAqICAgICAgICAgZGVmYXVsdFdpZHRoOiAzMDAsXG4gICAgICogICAgICAgICBkZWZhdWx0SGVpZ2h0OiAzMDAsXG4gICAgICogICAgICAgICB1cmw6ICdodHRwczovL21kbi5naXRodWIuaW8vZG9tLWV4YW1wbGVzL3dlYi13b3JrZXJzL3NpbXBsZS1zaGFyZWQtd29ya2VyLycsXG4gICAgICogICAgICAgICBmcmFtZTogdHJ1ZSxcbiAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG4gICAgICogICAgIH07XG4gICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuY3JlYXRlKHdpbk9wdGlvbik7XG4gICAgICogICAgIGNvbnN0IHNoYXJlZFdvcmtlcnMgPSBhd2FpdCB3aW4uZ2V0U2hhcmVkV29ya2VycygpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBhc3luYyBnZXRTaGFyZWRXb3JrZXJzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1zaGFyZWQtd29ya2VycycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBPcGVucyB0aGUgZGV2ZWxvcGVyIHRvb2xzIGZvciB0aGUgc2hhcmVkIHdvcmtlciBjb250ZXh0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogICAgIGNvbnN0IHZpZXcgPSBhd2FpdCBmaW4uVmlldy5jcmVhdGUoe1xuICAgICAqICAgICAgICAgbmFtZTogJ3ZpZXdOYW1lJyxcbiAgICAgKiAgICAgICAgIHRhcmdldDogZmluLm1lLmlkZW50aXR5LFxuICAgICAqICAgICAgICAgYm91bmRzOiB7dG9wOiAxMCwgbGVmdDogMTAsIHdpZHRoOiAyMDAsIGhlaWdodDogMjAwfVxuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCB2aWV3Lm5hdmlnYXRlKCdodHRwczovL21kbi5naXRodWIuaW8vZG9tLWV4YW1wbGVzL3dlYi13b3JrZXJzL3NpbXBsZS1zaGFyZWQtd29ya2VyLycpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHZpZXcuaW5zcGVjdFNoYXJlZFdvcmtlcigpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogRXhhbXBsZTpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBjb25zdCB3aW5PcHRpb24gPSB7XG4gICAgICogICAgICAgICBuYW1lOidjaGlsZCcsXG4gICAgICogICAgICAgICBkZWZhdWx0V2lkdGg6IDMwMCxcbiAgICAgKiAgICAgICAgIGRlZmF1bHRIZWlnaHQ6IDMwMCxcbiAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vbWRuLmdpdGh1Yi5pby9kb20tZXhhbXBsZXMvd2ViLXdvcmtlcnMvc2ltcGxlLXNoYXJlZC13b3JrZXIvJyxcbiAgICAgKiAgICAgICAgIGZyYW1lOiB0cnVlLFxuICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcbiAgICAgKiAgICAgfTtcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy5jcmVhdGUod2luT3B0aW9uKTtcbiAgICAgKiAgICAgYXdhaXQgd2luLmluc3BlY3RTaGFyZWRXb3JrZXIoKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIGBXZWJDb250ZW50c2AgcmVmZXJzIHRvIHNoYXJlZCBmdW5jdGlvbmFsaXR5IGJldHdlZW4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gICAgICogV2UgZG8gbm90IGV4cG9zZSBhbiBleHBsaWNpdCBzdXBlcmNsYXNzIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHksIGJ1dCBpdCBkb2VzIGhhdmUgaXRzIG93blxuICAgICAqIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIGV2ZW50IG5hbWVzcGFjZX0uXG4gICAgICovXG4gICAgYXN5bmMgaW5zcGVjdFNoYXJlZFdvcmtlcigpIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2luc3BlY3Qtc2hhcmVkLXdvcmtlcicsIHsgLi4udGhpcy5pZGVudGl0eSB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogSW5zcGVjdHMgdGhlIHNoYXJlZCB3b3JrZXIgYmFzZWQgb24gaXRzIElELlxuICAgICAqIEBwYXJhbSB3b3JrZXJJZCAtIFRoZSBpZCBvZiB0aGUgc2hhcmVkIHdvcmtlci5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcuY3JlYXRlKHtcbiAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZScsXG4gICAgICogICAgICAgICB0YXJnZXQ6IGZpbi5tZS5pZGVudGl0eSxcbiAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cbiAgICAgKiAgICAgfSk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9tZG4uZ2l0aHViLmlvL2RvbS1leGFtcGxlcy93ZWItd29ya2Vycy9zaW1wbGUtc2hhcmVkLXdvcmtlci8nKTtcbiAgICAgKlxuICAgICAqICAgICBjb25zdCBzaGFyZWRXb3JrZXJzID0gYXdhaXQgdmlldy5nZXRTaGFyZWRXb3JrZXJzKCk7XG4gICAgICogICAgIGF3YWl0IHZpZXcuaW5zcGVjdFNoYXJlZFdvcmtlckJ5SWQoc2hhcmVkV29ya2Vyc1swXS5pZCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgY29uc3Qgd2luT3B0aW9uID0ge1xuICAgICAqICAgICAgICAgbmFtZTonY2hpbGQnLFxuICAgICAqICAgICAgICAgZGVmYXVsdFdpZHRoOiAzMDAsXG4gICAgICogICAgICAgICBkZWZhdWx0SGVpZ2h0OiAzMDAsXG4gICAgICogICAgICAgICB1cmw6ICdodHRwczovL21kbi5naXRodWIuaW8vZG9tLWV4YW1wbGVzL3dlYi13b3JrZXJzL3NpbXBsZS1zaGFyZWQtd29ya2VyLycsXG4gICAgICogICAgICAgICBmcmFtZTogdHJ1ZSxcbiAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG4gICAgICogICAgIH07XG4gICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuY3JlYXRlKHdpbk9wdGlvbik7XG4gICAgICogICAgIGNvbnN0IHNoYXJlZFdvcmtlcnMgPSBhd2FpdCB3aW4uZ2V0U2hhcmVkV29ya2VycygpO1xuICAgICAqICAgICBhd2FpdCB3aW4uaW5zcGVjdFNoYXJlZFdvcmtlckJ5SWQoc2hhcmVkV29ya2Vyc1swXS5pZCk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIGFzeW5jIGluc3BlY3RTaGFyZWRXb3JrZXJCeUlkKHdvcmtlcklkKSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnNwZWN0LXNoYXJlZC13b3JrZXItYnktaWQnLCB7IC4uLnRoaXMuaWRlbnRpdHksIHdvcmtlcklkIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBPcGVucyB0aGUgZGV2ZWxvcGVyIHRvb2xzIGZvciB0aGUgc2VydmljZSB3b3JrZXIgY29udGV4dC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcuY3JlYXRlKHtcbiAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZScsXG4gICAgICogICAgICAgICB0YXJnZXQ6IGZpbi5tZS5pZGVudGl0eSxcbiAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cbiAgICAgKiAgICAgfSk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cDovL2dvb2dsZWNocm9tZS5naXRodWIuaW8vc2FtcGxlcy9zZXJ2aWNlLXdvcmtlci9iYXNpYy9pbmRleC5odG1sJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgdmlldy5pbnNwZWN0U2VydmljZVdvcmtlcigpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogICAgIGNvbnN0IHdpbk9wdGlvbiA9IHtcbiAgICAgKiAgICAgICAgIG5hbWU6J2NoaWxkJyxcbiAgICAgKiAgICAgICAgIGRlZmF1bHRXaWR0aDogMzAwLFxuICAgICAqICAgICAgICAgZGVmYXVsdEhlaWdodDogMzAwLFxuICAgICAqICAgICAgICAgdXJsOiAnaHR0cDovL2dvb2dsZWNocm9tZS5naXRodWIuaW8vc2FtcGxlcy9zZXJ2aWNlLXdvcmtlci9iYXNpYy9pbmRleC5odG1sJyxcbiAgICAgKiAgICAgICAgIGZyYW1lOiB0cnVlLFxuICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcbiAgICAgKiAgICAgfTtcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy5jcmVhdGUod2luT3B0aW9uKTtcbiAgICAgKiAgICAgYXdhaXQgd2luLmluc3BlY3RTZXJ2aWNlV29ya2VyKCk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIGFzeW5jIGluc3BlY3RTZXJ2aWNlV29ya2VyKCkge1xuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignaW5zcGVjdC1zZXJ2aWNlLXdvcmtlcicsIHsgLi4udGhpcy5pZGVudGl0eSB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2hvd3MgYSBwb3B1cCB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBOb3RlOiBJZiB0aGlzIFdlYkNvbnRlbnRzIGlzIGEgdmlldyBhbmQgaXRzIGF0dGFjaGVkIHdpbmRvdyBoYXMgYSBwb3B1cCBvcGVuLCB0aGlzIHdpbGwgY2xvc2UgaXQuXG4gICAgICpcbiAgICAgKiBTaG93cyBhIHBvcHVwIHdpbmRvdy4gSW5jbHVkaW5nIGEgYG5hbWVgIGluIGBvcHRpb25zYCB3aWxsIGF0dGVtcHQgdG8gc2hvdyBhbiBleGlzdGluZyB3aW5kb3cgYXMgYSBwb3B1cCwgaWZcbiAgICAgKiB0aGF0IHdpbmRvdyBkb2Vzbid0IGV4aXN0IG9yIG5vIGBuYW1lYCBpcyBpbmNsdWRlZCBhIHdpbmRvdyB3aWxsIGJlIGNyZWF0ZWQuIElmIHRoZSBjYWxsZXIgdmlldyBvciB0aGUgY2FsbGVyXG4gICAgICogdmlldydzIHBhcmVudCB3aW5kb3cgY3VycmVudGx5IGhhcyBhIHBvcHVwIHdpbmRvdyBvcGVuLCBjYWxsaW5nIGBzaG93UG9wdXBXaW5kb3dgIGFnYWluIHdpbGwgZGlzbWlzcyB0aGUgY3VycmVudGx5XG4gICAgICogb3BlbiBwb3B1cCB3aW5kb3cgYmVmb3JlIHNob3dpbmcgdGhlIG5ldyBwb3B1cCB3aW5kb3cuIEFsc28sIGlmIHRoZSBjYWxsZXIgdmlldyBpcyBkZXN0cm95ZWQgb3IgZGV0YWNoZWQsIHRoZSBwb3B1cFxuICAgICAqIHdpbGwgYmUgZGlzbWlzc2VkLlxuICAgICAqXG4gICAgICogTm90ZTogaW4gdGhlIGNhc2Ugd2hlcmUgdGhlIHdpbmRvdyBiZWluZyBzaG93biBhcyBhIHBvcHVwIG5lZWRzIHRvIGJlIGNyZWF0ZWQsIGl0IGlzIGEgY2hpbGQgb2YgdGhlIGNhbGxlciB2aWV3J3MgcGFyZW50IHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBDcmVhdGUgYW5kIHNob3cgYSBzaW5nbGUtdXNlIHBvcHVwIHdpbmRvdyB0aGF0IHJldHVybnMgYSBzaW5nbGUgcmVzdWx0IHRvIHRoZSBjYWxsZXIuIGBpbml0aWFsT3B0aW9uc2AgYWxsb3dzXG4gICAgICogdXMgdG8gcGFzcyB3aW5kb3cgb3B0aW9ucyB0byB0aGUgcG9wdXAgd2luZG93IHRoYXQgd2lsbCBiZSBjcmVhdGVkLiBgcmVzdWx0RGlzcGF0Y2hCZWhhdmlvcjogJ2Nsb3NlJ2AgZW5zdXJlc1xuICAgICAqIHRoYXQgb25jZSB0aGUgcG9wdXAgd2luZG93IGNhbGxzIGBkaXNwYXRjaFBvcHVwUmVzdWx0YCBpdCBpcyBjbG9zZWQuIGBibHVyQmVoYXZpb3I6ICdjbG9zZSdgIHdpbGwgeWllbGQgYSBkaXNtaXNzZWRcbiAgICAgKiByZXN1bHQgc2hvdWxkIHRoZSBwb3B1cCB3aW5kb3cgbG9zZSBmb2N1cy5cbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcmVzdWx0ID0gYXdhaXQgZmluLm1lLnNob3dQb3B1cFdpbmRvdyh7XG4gICAgICogICAgIGluaXRpYWxPcHRpb25zOiB7XG4gICAgICogICAgICAgICBmcmFtZTogZmFsc2VcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgdXJsOiAnPG15X3BvcHVwX3VybD4nLFxuICAgICAqICAgICByZXN1bHREaXNwYXRjaEJlaGF2aW9yOiAnY2xvc2UnLFxuICAgICAqICAgICBibHVyQmVoYXZpb3I6ICdjbG9zZScsXG4gICAgICogICAgIGZvY3VzOiB0cnVlLFxuICAgICAqICAgICBoZWlnaHQ6IDMwMCxcbiAgICAgKiAgICAgd2lkdGg6IDMwMCxcbiAgICAgKiAgICAgeDogMCxcbiAgICAgKiAgICAgeTogMFxuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogU2FtZSBhcyBhYm92ZSBidXQgdXNpbmcgYW4gZXhpc3Rpbmcgd2luZG93IGFzIGEgcG9wdXAgYnkgcmVmZXJlbmNpbmcgaXRzIGBuYW1lYDpcbiAgICAgKlxuICAgICAqIE5vdGU6IGlmIGEgd2luZG93IHdpdGggdGhlIGBuYW1lYCBwcm92aWRlZCBkb2Vzbid0IGV4aXN0LCBpdCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbi5tZS5zaG93UG9wdXBXaW5kb3coe1xuICAgICAqICAgICBpbml0aWFsT3B0aW9uczoge1xuICAgICAqICAgICAgICAgZnJhbWU6IHRydWVcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgbmFtZTogJ215LXBvcHVwJywgLy8gc2hvd3MgdGhlICdteS1wb3B1cCcgd2luZG93IGlmIGl0IGV4aXN0cywgb3RoZXJ3aXNlIGNyZWF0ZXMgaXRcbiAgICAgKiAgICAgdXJsOiAnPG15X3BvcHVwX3VybD4nLCAvLyBuYXZpZ2F0ZXMgdG8gdGhpcyB1cmwgaWYgaXQgZG9lc24ndCBtYXRjaCB0aGUgbG9jYXRpb24uaHJlZiBvZiB0aGUgJ215LXBvcHVwJyB3aW5kb3dcbiAgICAgKiAgICAgcmVzdWx0RGlzcGF0Y2hCZWhhdmlvcjogJ2Nsb3NlJyxcbiAgICAgKiAgICAgYmx1ckJlaGF2aW9yOiAnY2xvc2UnLFxuICAgICAqICAgICBmb2N1czogdHJ1ZSxcbiAgICAgKiAgICAgaGlkZU9uQ2xvc2U6IHRydWUsIC8vIHBlcnNpc3Qgd2luZG93IG9uICdkaXNtaXNzZWQnIHJlc3VsdCwgYWx0ZXJuYXRpdmVseSBjaGFuZ2Ugb25SZXN1bHREaXNwYXRjaCBhbmQgYmx1ckJlaGF2aW9yIHRvICdoaWRlJ1xuICAgICAqICAgICBoZWlnaHQ6IDMwMCxcbiAgICAgKiAgICAgd2lkdGg6IDMwMCxcbiAgICAgKiAgICAgeDogMCxcbiAgICAgKiAgICAgeTogMFxuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQ3JlYXRlIGFuZCBzaG93IGEgcG9wdXAgd2luZG93IHRoYXQgaXMgYWJsZSB0byByZXR1cm4gbXVsdGlwbGUgcmVzdWx0cyB0byB0aGUgY2FsbGVyIHZpYSBhbiBgb25Qb3B1cFJlc3VsdGAgY2FsbGJhY2suIEVhY2hcbiAgICAgKiB0aW1lIHRoZSBwb3B1cCB3aW5kb3cgY2FsbHMgYGRpc3BhdGNoUG9wdXBSZXN1bHRgLCB0aGUgY2FsbGJhY2sgd2lsbCBiZSBleGVjdXRlZCBvbiB0aGUgcmVzdWx0LiBPbmNlIHRoZSBwb3B1cCB3aW5kb3cgaXNcbiAgICAgKiBjbG9zZWQgb3IgaGlkZGVuLCB0aGUgYHNob3dQb3B1cFdpbmRvd2AgcHJvbWlzZSB3aWxsIHJlc29sdmUgd2l0aCBhIGBkaXNtaXNzZWRgIHJlc3VsdCB0aGF0IHdpbGwgaW5jbHVkZSB0aGUgbW9zdCByZWNlbnRseVxuICAgICAqIGRpc3BhdGNoZWQgcmVzdWx0IGFzIGBsYXN0RGlzcGF0Y2hSZXN1bHRgOlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwb3B1cFJlc3VsdENhbGxiYWNrID0gKHBheWxvYWQpID0+IHtcbiAgICAgKiAgICAgICAgaWYgKHBheWxvYWQucmVzdWx0ID09PSAnY2xpY2tlZCcpIHtcbiAgICAgKiAgICAgICAgICAgIGlmIChwYXlsb2FkLmRhdGEudG9waWMgPT09ICdjb2xvci1jaGFuZ2VkJykge1xuICAgICAqICAgICAgICAgICAgICAgIC8vIGRvIHNvbWV0aGluZyBsaWtlXG4gICAgICogICAgICAgICAgICAgICAgLy8gc2V0Q29sb3IocGF5bG9hZC5kYXRhLnZhbHVlKTtcbiAgICAgKiAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBhd2FpdCBmaW4ubWUuc2hvd1BvcHVwV2luZG93KHtcbiAgICAgKiAgICAgaW5pdGlhbE9wdGlvbnM6IHtcbiAgICAgKiAgICAgICAgIGZyYW1lOiBmYWxzZVxuICAgICAqICAgICB9LFxuICAgICAqICAgICB1cmw6ICc8bXlfcG9wdXBfdXJsPicsXG4gICAgICogICAgIHJlc3VsdERpc3BhdGNoQmVoYXZpb3I6ICdub25lJyxcbiAgICAgKiAgICAgYmx1ckJlaGF2aW9yOiAnY2xvc2UnLFxuICAgICAqICAgICBmb2N1czogdHJ1ZSxcbiAgICAgKiAgICAgaGVpZ2h0OiAzMDAsXG4gICAgICogICAgIHdpZHRoOiAzMDAsXG4gICAgICogICAgIHg6IDAsXG4gICAgICogICAgIHk6IDAsXG4gICAgICogICAgIG9uUG9wdXBSZXN1bHQ6IHBvcHVwUmVzdWx0Q2FsbGJhY2tcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFNhbWUgYXMgYWJvdmUgYnV0IHVzaW5nIGFuIGV4aXN0aW5nIHdpbmRvdyBhcyBhIHBvcHVwOlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwb3B1cFJlc3VsdENhbGxiYWNrID0gKHBheWxvYWQpID0+IHtcbiAgICAgKiAgICAgICAgaWYgKHBheWxvYWQucmVzdWx0ID09PSAnY2xpY2tlZCcpIHtcbiAgICAgKiAgICAgICAgICAgIGlmIChwYXlsb2FkLmRhdGEudG9waWMgPT09ICdjb2xvci1jaGFuZ2VkJykge1xuICAgICAqICAgICAgICAgICAgICAgIC8vIGRvIHNvbWV0aGluZyBsaWtlXG4gICAgICogICAgICAgICAgICAgICAgLy8gc2V0Q29sb3IocGF5bG9hZC5kYXRhLnZhbHVlKTtcbiAgICAgKiAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgfVxuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBhd2FpdCBmaW4ubWUuc2hvd1BvcHVwV2luZG93KHtcbiAgICAgKiAgICAgaW5pdGlhbE9wdGlvbnM6IHtcbiAgICAgKiAgICAgICAgIGZyYW1lOiBmYWxzZVxuICAgICAqICAgICB9LFxuICAgICAqICAgICBuYW1lOiAnbXktcG9wdXAnLCAvLyBzaG93cyB0aGUgJ215LXBvcHVwJyB3aW5kb3cgaWYgaXQgZXhpc3RzLCBvdGhlcndpc2UgY3JlYXRlcyBpdFxuICAgICAqICAgICB1cmw6ICc8bXlfcG9wdXBfdXJsPicsIC8vIG5hdmlnYXRlcyB0byB0aGlzIHVybCBpZiBpdCBkb2Vzbid0IG1hdGNoIHRoZSBsb2NhdGlvbi5ocmVmIG9mIHRoZSAnbXktcG9wdXAnIHdpbmRvd1xuICAgICAqICAgICByZXN1bHREaXNwYXRjaEJlaGF2aW9yOiAnbm9uZScsXG4gICAgICogICAgIGJsdXJCZWhhdmlvcjogJ2hpZGUnLFxuICAgICAqICAgICBmb2N1czogdHJ1ZSxcbiAgICAgKiAgICAgaGlkZU9uQ2xvc2U6IHRydWUsIC8vIHdlIGNhbiBqdXN0IHVzZSB0aGlzIG9yIHdlIGNhbiBjaGFuZ2UgYmx1ckJlaGF2aW9yIHRvICdoaWRlJ1xuICAgICAqICAgICBoZWlnaHQ6IDMwMCxcbiAgICAgKiAgICAgd2lkdGg6IDMwMCxcbiAgICAgKiAgICAgeDogMCxcbiAgICAgKiAgICAgeTogMCxcbiAgICAgKiAgICAgb25Qb3B1cFJlc3VsdDogcG9wdXBSZXN1bHRDYWxsYmFja1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQ3JlYXRlIG9yIHNob3cgYSBwb3B1cCB3aW5kb3cgdGhhdCBkaXNhYmxlcyB1c2VyIG1vdmVtZW50IChwb3NpdGlvbmluZyBhbmQgcmVzaXppbmcpIGluIHRoZSBjYWxsZXJcbiAgICAgKiB2aWV3J3MgcGFyZW50IHdpbmRvdyBieSB1c2luZyBgYmx1ckJlaGF2aW9yOiAnbW9kYWwnYDpcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcmVzdWx0ID0gYXdhaXQgZmluLm1lLnNob3dQb3B1cFdpbmRvdyh7XG4gICAgICogICAgIGluaXRpYWxPcHRpb25zOiB7XG4gICAgICogICAgICAgICBmcmFtZTogZmFsc2VcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgdXJsOiAnPG15X3BvcHVwX3VybD4nLFxuICAgICAqICAgICByZXN1bHREaXNwYXRjaEJlaGF2aW9yOiAnY2xvc2UnLFxuICAgICAqICAgICBibHVyQmVoYXZpb3I6ICdtb2RhbCcsXG4gICAgICogICAgIGZvY3VzOiB0cnVlLFxuICAgICAqICAgICBoZWlnaHQ6IDMwMCxcbiAgICAgKiAgICAgd2lkdGg6IDMwMCxcbiAgICAgKiAgICAgeDogMCxcbiAgICAgKiAgICAgeTogMFxuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQ3JlYXRlIGEgcG9wdXAgd2luZG93IGFzIGEgbW9kYWw6XG4gICAgICpcbiAgICAgKiBOb3RlOiBUaGUgb25seSB3YXkgdG8gZW5zdXJlIHRydWUgbW9kYWwgYmVoYXZpb3IgaXMgdG8gY3JlYXRlIHRoZSB3aW5kb3cgYmVpbmcgc2hvd24gYXMgYSBwb3B1cCB3aXRoIGFcbiAgICAgKiBgbW9kYWxQYXJlbnRJZGVudGl0eWAgdGhhdCB1c2VzIHRoZSBjYWxsZXIgdmlldydzIHBhcmVudCB3aW5kb3cgaWRlbnRpdHkuXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbi5tZS5zaG93UG9wdXBXaW5kb3coe1xuICAgICAqICAgICBpbml0aWFsT3B0aW9uczoge1xuICAgICAqICAgICAgICAgZnJhbWU6IGZhbHNlLFxuICAgICAqICAgICAgICAgbW9kYWxQYXJlbnRJZGVudGl0eTogZmluLm1lLmlkZW50aXR5XG4gICAgICogICAgIH0sXG4gICAgICogICAgIHVybDogJzxteV9wb3B1cF91cmw+JyxcbiAgICAgKiAgICAgcmVzdWx0RGlzcGF0Y2hCZWhhdmlvcjogJ2Nsb3NlJyxcbiAgICAgKiAgICAgYmx1ckJlaGF2aW9yOiAnbW9kYWwnLFxuICAgICAqICAgICBmb2N1czogdHJ1ZSxcbiAgICAgKiAgICAgaGVpZ2h0OiAzMDAsXG4gICAgICogICAgIHdpZHRoOiAzMDAsXG4gICAgICogICAgIHg6IDAsXG4gICAgICogICAgIHk6IDBcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFBhc3MgZGF0YSB0byBhIHBvcHVwIHdpbmRvdyB0aGF0IGlzIGF2YWlsYWJsZSB3aGVuIHRoZSBwb3B1cCBpcyBzaG93bi5cbiAgICAgKlxuICAgICAqIE5vdGU6IHRoaXMgaXMganVzdCBvbmUgZXhhbXBsZSBmb3IgYSB1c2Ugb2YgYGFkZGl0aW9uYWxPcHRpb25zYCwgaXQgY2FuIGJlIHVzZWQgdG8gdXBkYXRlIGFueSB1cGRhdGFibGVcbiAgICAgKiB3aW5kb3cgb3B0aW9ucyB3aGVuIGNyZWF0aW5nIG9yIHNob3dpbmcgYW4gZXhpc3Rpbmcgd2luZG93IGFzIGEgcG9wdXAuXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbi5tZS5zaG93UG9wdXBXaW5kb3coe1xuICAgICAqICAgICBhZGRpdGlvbmFsT3B0aW9uczoge1xuICAgICAqICAgICAgICAgY3VzdG9tRGF0YToge1xuICAgICAqICAgICAgICAgICAgIGZvbzogJ2JhcidcbiAgICAgKiAgICAgICAgIH1cbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgdXJsOiAnPG15X3BvcHVwX3VybD4nLFxuICAgICAqICAgICByZXN1bHREaXNwYXRjaEJlaGF2aW9yOiAnY2xvc2UnLFxuICAgICAqICAgICBibHVyQmVoYXZpb3I6ICdjbG9zZScsXG4gICAgICogICAgIGZvY3VzOiB0cnVlLFxuICAgICAqICAgICBoZWlnaHQ6IDMwMCxcbiAgICAgKiAgICAgd2lkdGg6IDMwMCxcbiAgICAgKiAgICAgeDogMCxcbiAgICAgKiAgICAgeTogMFxuICAgICAqIH0pO1xuICAgICAqXG4gICAgICogLy8gQWNjZXNzIGZyb20gdGhlIHBvcHVwIHdpbmRvdyBjb250ZXh0IGxpa2Ugc286XG4gICAgICogY29uc3QgeyBjdXN0b21EYXRhIH0gPSBhd2FpdCBmaW4ubWUuZ2V0T3B0aW9ucygpO1xuICAgICAqIGNvbnN0IHsgZm9vIH0gPSBjdXN0b21EYXRhO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogRXhlY3V0ZSBhIGNhbGxiYWNrIG9uIHRoZSBwb3B1cCdzIE9wZW5GaW4gd2luZG93IHdoZW4gdGhlIHBvcHVwIGlzIHNob3duOlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwb3B1cFdpbmRvd0NhbGxiYWNrID0gYXN5bmMgKHdpbikgPT4ge1xuICAgICAqICAgICBhd2FpdCB3aW4uZmxhc2goKTtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogY29uc3QgcmVzdWx0ID0gYXdhaXQgZmluLm1lLnNob3dQb3B1cFdpbmRvdyh7XG4gICAgICogICAgIHVybDogJzxteV9wb3B1cF91cmw+JyxcbiAgICAgKiAgICAgcmVzdWx0RGlzcGF0Y2hCZWhhdmlvcjogJ2Nsb3NlJyxcbiAgICAgKiAgICAgYmx1ckJlaGF2aW9yOiAnY2xvc2UnLFxuICAgICAqICAgICBmb2N1czogdHJ1ZSxcbiAgICAgKiAgICAgaGVpZ2h0OiAzMDAsXG4gICAgICogICAgIHdpZHRoOiAzMDAsXG4gICAgICogICAgIHg6IDAsXG4gICAgICogICAgIHk6IDAsXG4gICAgICogICAgIG9uUG9wdXBSZWFkeTogcG9wdXBXaW5kb3dDYWxsYmFjaztcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIGBXZWJDb250ZW50c2AgcmVmZXJzIHRvIHNoYXJlZCBmdW5jdGlvbmFsaXR5IGJldHdlZW4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gICAgICogV2UgZG8gbm90IGV4cG9zZSBhbiBleHBsaWNpdCBzdXBlcmNsYXNzIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHksIGJ1dCBpdCBkb2VzIGhhdmUgaXRzIG93blxuICAgICAqIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIGV2ZW50IG5hbWVzcGFjZX0uXG4gICAgICovXG4gICAgYXN5bmMgc2hvd1BvcHVwV2luZG93KG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oYCR7dGhpcy5lbnRpdHlUeXBlfS1zaG93LXBvcHVwLXdpbmRvd2AsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKG9wdGlvbnM/Lm9uUG9wdXBSZWFkeSkge1xuICAgICAgICAgICAgY29uc3QgcmVhZHlMaXN0ZW5lciA9IGFzeW5jICh7IHBvcHVwTmFtZSB9KSA9PiB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9wdXBXaW5kb3cgPSB0aGlzLmZpbi5XaW5kb3cud3JhcFN5bmMoeyB1dWlkOiB0aGlzLmZpbi5tZS51dWlkLCBuYW1lOiBwb3B1cE5hbWUgfSk7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IG9wdGlvbnMub25Qb3B1cFJlYWR5KHBvcHVwV2luZG93KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU29tZXRoaW5nIHdlbnQgd3JvbmcgZHVyaW5nIG9uUG9wdXBSZWFkeSBleGVjdXRpb246ICR7ZXJyb3J9YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIC8vIFRPRE86IGZpeCB0eXBpbmcgKGludGVybmFsKVxuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5vbmNlKCdwb3B1cC1yZWFkeScsIHJlYWR5TGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZDogdHJ5Q3JlYXRlUGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3RyeS1jcmVhdGUtcG9wdXAtd2luZG93Jywge1xuICAgICAgICAgICAgb3B0aW9uczoge1xuICAgICAgICAgICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgICAgICAgICAgLy8gSW50ZXJuYWwgdXNlIG9ubHkuXG4gICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgICAgIGhhc1Jlc3VsdENhbGxiYWNrOiAhIW9wdGlvbnM/Lm9uUG9wdXBSZXN1bHQsXG4gICAgICAgICAgICAgICAgaGFzUmVhZHlDYWxsYmFjazogISFvcHRpb25zPy5vblBvcHVwUmVhZHlcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAuLi50aGlzLmlkZW50aXR5XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB7IGRhdGE6IHsgd2lsbE9wZW4sIG9wdGlvbnM6IHBvcHVwT3B0aW9ucyB9IH0gPSB0cnlDcmVhdGVQYXlsb2FkO1xuICAgICAgICBpZiAod2lsbE9wZW4pIHtcbiAgICAgICAgICAgIC8vIFNvbHZlIHRoZSBpc3N1ZSB3aGVyZSBJbnRlcm9wIGluIGEgcG9wdXAgd2luZG93IHdpdGggbm9uIGNyb3NzLW9yaWdpbiB1cmwgaXMgbm90IHdvcmtpbmcoY29yZS0xMDc2KS5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZmluLldpbmRvdy5jcmVhdGUocG9wdXBPcHRpb25zLmluaXRpYWxPcHRpb25zKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBub3JtYWxpemVQb3B1cFJlc3VsdCA9IChwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IG5hbWUsIHV1aWQsIHJlc3VsdCwgZGF0YSB9ID0gcGF5bG9hZDtcbiAgICAgICAgICAgIGNvbnN0IHBvcHVwUmVzdWx0ID0ge1xuICAgICAgICAgICAgICAgIGlkZW50aXR5OiB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHV1aWRcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHJlc3VsdFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgcG9wdXBSZXN1bHQuZGF0YSA9IGRhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcG9wdXBSZXN1bHQ7XG4gICAgICAgIH07XG4gICAgICAgIGlmIChvcHRpb25zPy5vblBvcHVwUmVzdWx0KSB7XG4gICAgICAgICAgICBjb25zdCBkaXNwYXRjaFJlc3VsdExpc3RlbmVyID0gYXN5bmMgKHBheWxvYWQpID0+IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBvcHRpb25zLm9uUG9wdXBSZXN1bHQobm9ybWFsaXplUG9wdXBSZXN1bHQocGF5bG9hZCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHRlYXJkb3duTGlzdGVuZXIgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogZml4IHR5cGluZyAoaW50ZXJuYWwpXG4gICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucmVtb3ZlTGlzdGVuZXIoJ3BvcHVwLXJlc3VsdCcsIGRpc3BhdGNoUmVzdWx0TGlzdGVuZXIpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIC8vIFRPRE86IGZpeCB0eXBpbmcgKGludGVybmFsKVxuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5vbigncG9wdXAtcmVzdWx0JywgZGlzcGF0Y2hSZXN1bHRMaXN0ZW5lcik7XG4gICAgICAgICAgICAvLyBUT0RPOiBmaXggdHlwaW5nIChpbnRlcm5hbClcbiAgICAgICAgICAgIC8vIGhpbGFyaW91c2x5IHRoaXMgZG9lcyBub3QgbmVlZCBhIHRzLWV4cGVjdC1lcnJvciAtIHRoaXMgaXMgZ2FwIGluIHR5cGUgc291bmRuZXNzXG4gICAgICAgICAgICAvLyBzaG91bGQgaW52ZXN0aWdhdGUgLSBwcm9iYWJseSBkdWUgdG8gYHRlYXJkb3duTGlzdGVuZXJgIHRha2luZyBhIHZvaWQgYXJndW1lbnRcbiAgICAgICAgICAgIC8vIHdoaWNoIG1pZ2h0IHBsYXkgbmljZWx5IHdpdGggdGhlIGBuZXZlcmAgdHlwZT8gIGh1aC4uLlxuICAgICAgICAgICAgYXdhaXQgdGhpcy5vbmNlKCdwb3B1cC10ZWFyZG93bicsIHRlYXJkb3duTGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Nob3ctcG9wdXAtd2luZG93Jywge1xuICAgICAgICAgICAgb3B0aW9uczogcG9wdXBPcHRpb25zLFxuICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YTtcbiAgICB9XG59XG5tYWluLldlYkNvbnRlbnRzID0gV2ViQ29udGVudHM7XG5cbnZhciBoYXNSZXF1aXJlZEluc3RhbmNlJDI7XG5cbmZ1bmN0aW9uIHJlcXVpcmVJbnN0YW5jZSQyICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkSW5zdGFuY2UkMikgcmV0dXJuIEluc3RhbmNlJDU7XG5cdGhhc1JlcXVpcmVkSW5zdGFuY2UkMiA9IDE7XG5cdHZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcblx0ICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcblx0ICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuXHQgICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcblx0fTtcblx0dmFyIF9WaWV3X3Byb3ZpZGVyQ2hhbm5lbENsaWVudDtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KEluc3RhbmNlJDUsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRJbnN0YW5jZSQ1LlZpZXcgPSB2b2lkIDA7XG5cdGNvbnN0IHRyYW5zcG9ydF9lcnJvcnNfMSA9IHRyYW5zcG9ydEVycm9ycztcblx0Y29uc3QgbGF6eV8xID0gbGF6eTtcblx0Y29uc3QgbGF5b3V0X2VudGl0aWVzXzEgPSBsYXlvdXRFbnRpdGllcztcblx0Y29uc3QgbGF5b3V0X2NvbnN0YW50c18xID0gbGF5b3V0X2NvbnN0YW50cztcblx0Y29uc3QgbWFpbl8xID0gbWFpbjtcblx0Y29uc3Qgd2luZG93XzEgPSByZXF1aXJlV2luZG93KCk7XG5cdC8qKlxuXHQgKiBBIFZpZXcgY2FuIGJlIHVzZWQgdG8gZW1iZWQgYWRkaXRpb25hbCB3ZWIgY29udGVudCBpbnRvIGEgV2luZG93LlxuXHQgKiBJdCBpcyBsaWtlIGEgY2hpbGQgd2luZG93LCBleGNlcHQgaXQgaXMgcG9zaXRpb25lZCByZWxhdGl2ZSB0byBpdHMgb3duaW5nIHdpbmRvdy5cblx0ICogSXQgaGFzIHRoZSBhYmlsaXR5IHRvIGxpc3RlbiBmb3Ige0BsaW5rIE9wZW5GaW4uVmlld0V2ZW50cyBWaWV3LXNwZWNpZmljIGV2ZW50c30uXG5cdCAqXG5cdCAqIEJ5IGRlZmF1bHQsIGEgVmlldyB3aWxsIHRyeSB0byBzaGFyZSB0aGUgc2FtZSByZW5kZXJlciBwcm9jZXNzIGFzIG90aGVyIFZpZXdzIG93bmVkIGJ5IGl0cyBwYXJlbnQgQXBwbGljYXRpb24uXG5cdCAqIFRvIGNoYW5nZSB0aGF0IGJlaGF2aW9yLCBzZWUgdGhlIHByb2Nlc3NBZmZpbml0eSB7QGxpbmsgT3BlbkZpbi5WaWV3T3B0aW9ucyB2aWV3IG9wdGlvbn0uXG5cdCAqXG5cdCAqIEEgVmlldydzIGxpZmVjeWNsZSBpcyB0aWVkIHRvIGl0cyBvd25pbmcgd2luZG93IGFuZCBjYW4gYmUgcmUtYXR0YWNoZWQgdG8gYSBkaWZmZXJlbnQgd2luZG93IGF0IGFueSBwb2ludCBkdXJpbmcgaXRzIGxpZmVjeWNsZS5cblx0ICovXG5cdGNsYXNzIFZpZXcgZXh0ZW5kcyBtYWluXzEuV2ViQ29udGVudHMge1xuXHQgICAgLyoqXG5cdCAgICAgKiBAaW50ZXJuYWxcblx0ICAgICAqL1xuXHQgICAgY29uc3RydWN0b3Iod2lyZSwgaWRlbnRpdHkpIHtcblx0ICAgICAgICBzdXBlcih3aXJlLCBpZGVudGl0eSwgJ3ZpZXcnKTtcblx0ICAgICAgICB0aGlzLmlkZW50aXR5ID0gaWRlbnRpdHk7XG5cdCAgICAgICAgX1ZpZXdfcHJvdmlkZXJDaGFubmVsQ2xpZW50LnNldCh0aGlzLCBuZXcgbGF6eV8xLkxhenkoKCkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCBwbGF0Zm9ybSA9IHRoaXMuZmluLlBsYXRmb3JtLndyYXBTeW5jKHRoaXMuaWRlbnRpdHkpO1xuXHQgICAgICAgICAgICByZXR1cm4gcGxhdGZvcm0uZ2V0Q2xpZW50KCk7XG5cdCAgICAgICAgfSkpO1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIEF0dGFjaGVzIHRoZSBjdXJyZW50IHZpZXcgdG8gdGhlIGdpdmVuIHdpbmRvdyBpZGVudGl0eS5cblx0ICAgICAgICAgKiBJZGVudGl0eSBtdXN0IGJlIHRoZSBpZGVudGl0eSBvZiBhIHdpbmRvdyBpbiB0aGUgc2FtZSBhcHBsaWNhdGlvbi5cblx0ICAgICAgICAgKiBUaGlzIGRldGFjaGVzIHRoZSB2aWV3IGZyb20gaXRzIGN1cnJlbnQgd2luZG93LCBhbmQgc2V0cyB0aGUgdmlldyB0byBiZSBkZXN0cm95ZWQgd2hlbiBpdHMgbmV3IHdpbmRvdyBjbG9zZXMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogbGV0IHZpZXc7XG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlVmlldygpIHtcblx0ICAgICAgICAgKiAgICAgY29uc3QgbWUgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAgICAgKiAgICAgcmV0dXJuIGZpbi5WaWV3LmNyZWF0ZSh7XG5cdCAgICAgICAgICogICAgICAgICBuYW1lOiAndmlld05hbWVBdHRhY2gnLFxuXHQgICAgICAgICAqICAgICAgICAgdGFyZ2V0OiBtZS5pZGVudGl0eSxcblx0ICAgICAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cblx0ICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gYXR0YWNoVmlldygpIHtcblx0ICAgICAgICAgKiAgICAgdmlldyA9IGF3YWl0IGNyZWF0ZVZpZXcoKTtcblx0ICAgICAgICAgKiAgICAgY29uc29sZS5sb2coJ1ZpZXcgY3JlYXRlZC4nKTtcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBhd2FpdCB2aWV3Lm5hdmlnYXRlKCdodHRwczovL2dvb2dsZS5jb20nKTtcblx0ICAgICAgICAgKiAgICAgY29uc29sZS5sb2coJ1ZpZXcgbmF2aWdhdGVkIHRvIGdpdmVuIHVybC4nKTtcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBjb25zdCB3aW5PcHRpb24gPSB7XG5cdCAgICAgICAgICogICAgICAgICBuYW1lOid3aW5PcHRpb25OYW1lJyxcblx0ICAgICAgICAgKiAgICAgICAgIGRlZmF1bHRXaWR0aDogMzAwLFxuXHQgICAgICAgICAqICAgICAgICAgZGVmYXVsdEhlaWdodDogMzAwLFxuXHQgICAgICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5jcmVhdGUuaHRtbCcsXG5cdCAgICAgICAgICogICAgICAgICBmcmFtZTogdHJ1ZSxcblx0ICAgICAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgICAgICogICAgIH07XG5cdCAgICAgICAgICogICAgIGNvbnN0IG5ld1dpbmRvdyA9IGF3YWl0IGZpbi5XaW5kb3cuY3JlYXRlKHdpbk9wdGlvbik7XG5cdCAgICAgICAgICogICAgIHZpZXcuYXR0YWNoKG5ld1dpbmRvdy5pZGVudGl0eSk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogYXR0YWNoVmlldygpXG5cdCAgICAgICAgICogICAgIC50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdWaWV3IGF0dGFjaGVkIHRvIG5ldyB3aW5kb3cuJykpXG5cdCAgICAgICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgICAgICogYGBgXG5cdCAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHRoaXMuYXR0YWNoID0gYXN5bmMgKHRhcmdldCkgPT4ge1xuXHQgICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignYXR0YWNoLXZpZXcnLCB7IHRhcmdldCwgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIERlc3Ryb3lzIHRoZSBjdXJyZW50IHZpZXdcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICogYGBganNcblx0ICAgICAgICAgKiBjb25zdCB2aWV3ID0gZmluLlZpZXcud3JhcFN5bmMoeyB1dWlkOiAndmlld1V1aWQnLCBuYW1lOiAndmlld05hbWUnIH0pO1xuXHQgICAgICAgICAqIHZpZXcuZGVzdHJveSgpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLmRlc3Ryb3kgPSBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdkZXN0cm95LXZpZXcnLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgfTtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBTaG93cyB0aGUgY3VycmVudCB2aWV3IGlmIGl0IGlzIGN1cnJlbnRseSBoaWRkZW4uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogbGV0IHZpZXc7XG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlVmlldygpIHtcblx0ICAgICAgICAgKiAgICAgY29uc3QgbWUgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAgICAgKiAgICAgcmV0dXJuIGZpbi5WaWV3LmNyZWF0ZSh7XG5cdCAgICAgICAgICogICAgICAgICBuYW1lOiAndmlld05hbWVTaG93Jyxcblx0ICAgICAgICAgKiAgICAgICAgIHRhcmdldDogbWUuaWRlbnRpdHksXG5cdCAgICAgICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG5cdCAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIGhpZGVBbmRTaG93VmlldygpIHtcblx0ICAgICAgICAgKiAgICAgdmlldyA9IGF3YWl0IGNyZWF0ZVZpZXcoKTtcblx0ICAgICAgICAgKiAgICAgY29uc29sZS5sb2coJ1ZpZXcgY3JlYXRlZC4nKTtcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBhd2FpdCB2aWV3Lm5hdmlnYXRlKCdodHRwczovL2dvb2dsZS5jb20nKTtcblx0ICAgICAgICAgKiAgICAgY29uc29sZS5sb2coJ1ZpZXcgbmF2aWdhdGVkIHRvIGdpdmVuIHVybCBvcHRpb24uJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5oaWRlKCk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKFwiVmlldyBoaWRkZW4uXCIpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZpZXcuc2hvdygpO1xuXHQgICAgICAgICAqICAgICBjb25zb2xlLmxvZyhcIlZpZXcgc2hvd24uXCIpO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGhpZGVBbmRTaG93VmlldygpXG5cdCAgICAgICAgICogICAgIC50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdWaWV3IGhpZGRlbiBhbmQgc2hvd24uJykpXG5cdCAgICAgICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgICAgICogYGBgXG5cdCAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHRoaXMuc2hvdyA9IGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Nob3ctdmlldycsIHsgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFNldHMgdGhlIGJvdW5kcyAodG9wLCBsZWZ0LCB3aWR0aCwgaGVpZ2h0KSBvZiB0aGUgdmlldyByZWxhdGl2ZSB0byBpdHMgd2luZG93IGFuZCBzaG93cyBpdCBpZiBpdCBpcyBoaWRkZW4uXG5cdCAgICAgICAgICogVGhpcyBtZXRob2QgZW5zdXJlcyB0aGUgdmlldyBpcyBib3RoIHBvc2l0aW9uZWQgYW5kIHNob3dpbmcuIEl0IHdpbGwgcmVwb3NpdGlvbiBhIHZpc2libGUgdmlldyBhbmQgYm90aCBzaG93IGFuZCByZXBvc2l0aW9uIGEgaGlkZGVuIHZpZXcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmVtYXJrcyBWaWV3IHBvc2l0aW9uIGlzIHJlbGF0aXZlIHRvIHRoZSBib3VuZHMgb2YgdGhlIHdpbmRvdy5cblx0ICAgICAgICAgKiAoe3RvcDogMCwgbGVmdDogMH0gcmVwcmVzZW50cyB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSB3aW5kb3cpXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogbGV0IHZpZXc7XG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlVmlldygpIHtcblx0ICAgICAgICAgKiAgICAgY29uc3QgbWUgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAgICAgKiAgICAgcmV0dXJuIGZpbi5WaWV3LmNyZWF0ZSh7XG5cdCAgICAgICAgICogICAgICAgICBuYW1lOiAndmlld05hbWVTZXRCb3VuZHMnLFxuXHQgICAgICAgICAqICAgICAgICAgdGFyZ2V0OiBtZS5pZGVudGl0eSxcblx0ICAgICAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cblx0ICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gc2hvd1ZpZXdBdCgpIHtcblx0ICAgICAgICAgKiAgICAgdmlldyA9IGF3YWl0IGNyZWF0ZVZpZXcoKTtcblx0ICAgICAgICAgKiAgICAgY29uc29sZS5sb2coJ1ZpZXcgY3JlYXRlZC4nKTtcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBhd2FpdCB2aWV3Lm5hdmlnYXRlKCdodHRwczovL2dvb2dsZS5jb20nKTtcblx0ICAgICAgICAgKiAgICAgY29uc29sZS5sb2coJ1ZpZXcgbmF2aWdhdGVkIHRvIGdpdmVuIHVybC4nKTtcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBhd2FpdCB2aWV3LnNob3dBdCh7XG5cdCAgICAgICAgICogICAgICAgICB0b3A6IDEwMCxcblx0ICAgICAgICAgKiAgICAgICAgIGxlZnQ6IDEwMCxcblx0ICAgICAgICAgKiAgICAgICAgIHdpZHRoOiAzMDAsXG5cdCAgICAgICAgICogICAgICAgICBoZWlnaHQ6IDMwMFxuXHQgICAgICAgICAqICAgICB9LCB7XG5cdCAgICAgICAgICogICAgICAgYnJpbmdUb0Zyb250IDogdHJ1ZVxuXHQgICAgICAgICAqICAgICB9KTtcblx0ICAgICAgICAgKiB9XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBzaG93Vmlld0F0KClcblx0ICAgICAgICAgKiAgICAgLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1ZpZXcgc2V0IHRvIG5ldyBib3VuZHMgYW5kIHNob3duLicpKVxuXHQgICAgICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLnNob3dBdCA9IGFzeW5jIChib3VuZHMsIG9wdGlvbnMgPSB7fSkgPT4ge1xuXHQgICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc2hvdy12aWV3LWF0JywgeyBib3VuZHMsIC4uLnRoaXMuaWRlbnRpdHksIG9wdGlvbnMgfSk7XG5cdCAgICAgICAgfTtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBCcmluZ3MgdGhlIHNwZWNpZmllZCB2aWV3IHRvIHRoZSBmcm9udCBvZiBpdHMgY3VycmVudCB3aW5kb3cuIFRoaXMgZW5zdXJlcyB0aGUgdmlldyB3aWxsIGJlIHZpc2libGUgb24gdG9wIG9mIGFueSBvdGhlciB2aWV3c1xuXHQgICAgICAgICAqIHdoaWNoIGhhdmUgb3ZlcmxhcHBpbmcgYm91bmRzIHdpdGggaXQuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBQbGVhc2Ugbm90ZSwgdGhpcyBpcyBub3QgYSBwZXJtYW5lbnQgYWN0aW9uIC0gd2hlbiBhIG5ldyB2aWV3IGlzIGNyZWF0ZWQgb3IgYXR0YWNoZWQgdG8gdGhlIHdpbmRvdywgaXQgd2lsbCBkaXNwbGF5IG9uIHRvcCBvZiBhbGwgb3RoZXIgdmlld3Ncblx0ICAgICAgICAgKiBpbiB0aGUgd2luZG93IHRoYXQgc2hhcmUgYm91bmRzIHdpdGggaXQuXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy5icmluZ1RvRnJvbnQgPSBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdicmluZy12aWV3LXRvLWZyb250JywgeyAuLi50aGlzLmlkZW50aXR5IH0pO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogSGlkZXMgdGhlIGN1cnJlbnQgdmlldyBpZiBpdCBpcyBjdXJyZW50bHkgdmlzaWJsZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICogYGBganNcblx0ICAgICAgICAgKiBsZXQgdmlldztcblx0ICAgICAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVWaWV3KCkge1xuXHQgICAgICAgICAqICAgICBjb25zdCBtZSA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuXHQgICAgICAgICAqICAgICByZXR1cm4gZmluLlZpZXcuY3JlYXRlKHtcblx0ICAgICAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZUhpZGUnLFxuXHQgICAgICAgICAqICAgICAgICAgdGFyZ2V0OiBtZS5pZGVudGl0eSxcblx0ICAgICAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cblx0ICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gaGlkZVZpZXcoKSB7XG5cdCAgICAgICAgICogICAgIHZpZXcgPSBhd2FpdCBjcmVhdGVWaWV3KCk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IGNyZWF0ZWQuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9nb29nbGUuY29tJyk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IG5hdmlnYXRlZCB0byBnaXZlbiB1cmwuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5oaWRlKCk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogaGlkZVZpZXcoKVxuXHQgICAgICAgICAqICAgICAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnVmlldyBoaWRkZW4uJykpXG5cdCAgICAgICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgICAgICogYGBgXG5cdCAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHRoaXMuaGlkZSA9IGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2hpZGUtdmlldycsIHsgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFNldHMgdGhlIGJvdW5kcyAodG9wLCBsZWZ0LCB3aWR0aCwgaGVpZ2h0KSBvZiB0aGUgdmlldyByZWxhdGl2ZSB0byBpdHMgd2luZG93LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJlbWFya3MgVmlldyBwb3NpdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgYm91bmRzIG9mIHRoZSB3aW5kb3cuXG5cdCAgICAgICAgICogKHt0b3A6IDAsIGxlZnQ6IDB9IHJlcHJlc2VudHMgdGhlIHRvcCBsZWZ0IGNvcm5lciBvZiB0aGUgd2luZG93KVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKiBgYGBqc1xuXHQgICAgICAgICAqIGxldCB2aWV3O1xuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVZpZXcoKSB7XG5cdCAgICAgICAgICogICAgIGNvbnN0IG1lID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG5cdCAgICAgICAgICogICAgIHJldHVybiBmaW4uVmlldy5jcmVhdGUoe1xuXHQgICAgICAgICAqICAgICAgICAgbmFtZTogJ3ZpZXdOYW1lU2V0Qm91bmRzJyxcblx0ICAgICAgICAgKiAgICAgICAgIHRhcmdldDogbWUuaWRlbnRpdHksXG5cdCAgICAgICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG5cdCAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNldFZpZXdCb3VuZHMoKSB7XG5cdCAgICAgICAgICogICAgIHZpZXcgPSBhd2FpdCBjcmVhdGVWaWV3KCk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IGNyZWF0ZWQuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9nb29nbGUuY29tJyk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IG5hdmlnYXRlZCB0byBnaXZlbiB1cmwuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5zZXRCb3VuZHMoe1xuXHQgICAgICAgICAqICAgICAgICAgdG9wOiAxMDAsXG5cdCAgICAgICAgICogICAgICAgICBsZWZ0OiAxMDAsXG5cdCAgICAgICAgICogICAgICAgICB3aWR0aDogMzAwLFxuXHQgICAgICAgICAqICAgICAgICAgaGVpZ2h0OiAzMDBcblx0ICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogc2V0Vmlld0JvdW5kcygpXG5cdCAgICAgICAgICogICAgIC50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdWaWV3IHNldCB0byBuZXcgYm91bmRzLicpKVxuXHQgICAgICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLnNldEJvdW5kcyA9IGFzeW5jIChib3VuZHMpID0+IHtcblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NldC12aWV3LWJvdW5kcycsIHsgYm91bmRzLCAuLi50aGlzLmlkZW50aXR5IH0pO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogR2V0cyB0aGUgYm91bmRzICh0b3AsIGxlZnQsIHdpZHRoLCBoZWlnaHQpIG9mIHRoZSB2aWV3IHJlbGF0aXZlIHRvIGl0cyB3aW5kb3cuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmVtYXJrcyBWaWV3IHBvc2l0aW9uIGlzIHJlbGF0aXZlIHRvIHRoZSBib3VuZHMgb2YgdGhlIHdpbmRvdy5cblx0ICAgICAgICAgKiAoe3RvcDogMCwgbGVmdDogMH0gcmVwcmVzZW50cyB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSB3aW5kb3cpXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmNyZWF0ZSh7XG5cdCAgICAgICAgICogICAgIG5hbWU6ICd2aWV3TmFtZVNldEJvdW5kcycsXG5cdCAgICAgICAgICogICAgIHRhcmdldDogZmluLm1lLmlkZW50aXR5LFxuXHQgICAgICAgICAqICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG5cdCAgICAgICAgICogfSk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBhd2FpdCB2aWV3Lm5hdmlnYXRlKCdodHRwczovL2dvb2dsZS5jb20nKTtcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGF3YWl0IHZpZXcuc2V0Qm91bmRzKHtcblx0ICAgICAgICAgKiAgICAgdG9wOiAxMDAsXG5cdCAgICAgICAgICogICAgIGxlZnQ6IDEwMCxcblx0ICAgICAgICAgKiAgICAgd2lkdGg6IDMwMCxcblx0ICAgICAgICAgKiAgICAgaGVpZ2h0OiAzMDBcblx0ICAgICAgICAgKiB9KTtcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGNvbnNvbGUubG9nKGF3YWl0IHZpZXcuZ2V0Qm91bmRzKCkpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLmdldEJvdW5kcyA9IGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgYWNrID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC12aWV3LWJvdW5kcycsIHsgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgICAgICAgICAgcmV0dXJuIGFjay5wYXlsb2FkLmRhdGE7XG5cdCAgICAgICAgfTtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBHZXRzIHRoZSBWaWV3J3MgaW5mby5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICogYGBganNcblx0ICAgICAgICAgKiBsZXQgdmlldztcblx0ICAgICAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVWaWV3KCkge1xuXHQgICAgICAgICAqICAgICBjb25zdCBtZSA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuXHQgICAgICAgICAqICAgICByZXR1cm4gZmluLlZpZXcuY3JlYXRlKHtcblx0ICAgICAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZUdldEluZm8nLFxuXHQgICAgICAgICAqICAgICAgICAgdGFyZ2V0OiBtZS5pZGVudGl0eSxcblx0ICAgICAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cblx0ICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0Vmlld0luZm8oKSB7XG5cdCAgICAgICAgICogICAgIHZpZXcgPSBhd2FpdCBjcmVhdGVWaWV3KCk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IGNyZWF0ZWQuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9nb29nbGUuY29tJyk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IG5hdmlnYXRlZCB0byBnaXZlbiB1cmwuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgcmV0dXJuIHZpZXcuZ2V0SW5mbygpO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGdldFZpZXdJbmZvKClcblx0ICAgICAgICAgKiAgICAgLnRoZW4oKGluZm8pID0+IGNvbnNvbGUubG9nKCdWaWV3IGluZm8gZmV0Y2hlZC4nLCBpbmZvKSlcblx0ICAgICAgICAgKiAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAgICAgKiBgYGBcblx0ICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy5nZXRJbmZvID0gYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCBhY2sgPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXZpZXctaW5mbycsIHsgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgICAgICAgICAgcmV0dXJuIGFjay5wYXlsb2FkLmRhdGE7XG5cdCAgICAgICAgfTtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBSZXRyaWV2ZXMgdGhlIGxheW91dCBmb3IgdGhlIHdpbmRvdyB0aGUgdmlldyBpcyBhdHRhY2hlZCB0by5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICogYGBganNcblx0ICAgICAgICAgKiAgICAgLy9nZXQgdGhlIGN1cnJlbnQgVmlld1xuXHQgICAgICAgICAqICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcuZ2V0Q3VycmVudCgpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIC8vZ2V0IGEgcmVmZXJlbmNlIHRvIHRoZSBMYXlvdXQgZm9yIHRoZSBXaW5kb3cgdGhlIHZpZXcgaXMgcGFydCBvZlxuXHQgICAgICAgICAqICAgICBjb25zdCBsYXlvdXQgPSBhd2FpdCB2aWV3LmdldFBhcmVudExheW91dCgpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLmdldFBhcmVudExheW91dCA9IGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3ZpZXctZ2V0LXBhcmVudC1sYXlvdXQnLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSkuY2F0Y2goKCkgPT4ge1xuXHQgICAgICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICBjb25zdCBsYXlvdXRXaW5kb3cgPSBhd2FpdCB0aGlzLmdldEN1cnJlbnRXaW5kb3coKTtcblx0ICAgICAgICAgICAgbGV0IGxheW91dFdpbmRvd0lkZW50aXR5ID0gbGF5b3V0V2luZG93LmlkZW50aXR5O1xuXHQgICAgICAgICAgICAvLyBUT0RPOiBDT1JFLTE4NTcgLSB3aGVuIHdlIHRlYXJvdXQgYWN0aXZlIGxheW91dCBvciBkcmFnIGEgdmlldyBvdXQgb2YgYSB3aW5kb3csIHRoZSBhYm92ZSBpZGVudGl0eSBpbmNsdWRlcyB0aGUgd2hvbGUgd2luZG93IGluZm8uXG5cdCAgICAgICAgICAgIGlmIChsYXlvdXRXaW5kb3dJZGVudGl0eS5pZGVudGl0eSkge1xuXHQgICAgICAgICAgICAgICAgbGF5b3V0V2luZG93SWRlbnRpdHkgPSBsYXlvdXRXaW5kb3dJZGVudGl0eS5pZGVudGl0eTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgcHJvdmlkZXJDaGFubmVsQ2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfVmlld19wcm92aWRlckNoYW5uZWxDbGllbnQsIFwiZlwiKS5nZXRWYWx1ZSgpO1xuXHQgICAgICAgICAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgbGF5b3V0X2VudGl0aWVzXzEuTGF5b3V0Tm9kZS5uZXdMYXlvdXRFbnRpdGllc0NsaWVudChwcm92aWRlckNoYW5uZWxDbGllbnQsIGxheW91dF9jb25zdGFudHNfMS5MQVlPVVRfQ09OVFJPTExFUl9JRCwgbGF5b3V0V2luZG93SWRlbnRpdHkpO1xuXHQgICAgICAgICAgICAgICAgY29uc3QgbGF5b3V0SWRlbnRpdHkgPSBhd2FpdCBjbGllbnQuZ2V0TGF5b3V0SWRlbnRpdHlGb3JWaWV3T3JUaHJvdyh0aGlzLmlkZW50aXR5KTtcblx0ICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbi5QbGF0Zm9ybS5MYXlvdXQud3JhcChsYXlvdXRJZGVudGl0eSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgY2F0Y2ggKGUpIHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IGFsbG93ZWRFcnJvcnMgPSBbXG5cdCAgICAgICAgICAgICAgICAgICAgJ05vIGFjdGlvbiByZWdpc3RlcmVkIGF0IHRhcmdldCBmb3InLFxuXHQgICAgICAgICAgICAgICAgICAgICdnZXRMYXlvdXRJZGVudGl0eUZvclZpZXdPclRocm93IGlzIG5vdCBhIGZ1bmN0aW9uJ1xuXHQgICAgICAgICAgICAgICAgXTtcblx0ICAgICAgICAgICAgICAgIGlmICghYWxsb3dlZEVycm9ycy5zb21lKChtKSA9PiBlLm1lc3NhZ2UuaW5jbHVkZXMobSkpKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgdGhyb3cgZTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIC8vIGZhbGxiYWNrIGxvZ2ljIGZvciBtaXNzaW5nIGVuZHBvaW50XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5maW4uUGxhdGZvcm0uTGF5b3V0LndyYXAobGF5b3V0V2luZG93SWRlbnRpdHkpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfTtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBHZXRzIHRoZSBWaWV3J3Mgb3B0aW9ucy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICogYGBganNcblx0ICAgICAgICAgKiBsZXQgdmlldztcblx0ICAgICAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVWaWV3KCkge1xuXHQgICAgICAgICAqICAgICBjb25zdCBtZSA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuXHQgICAgICAgICAqICAgICByZXR1cm4gZmluLlZpZXcuY3JlYXRlKHtcblx0ICAgICAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZUdldE9wdGlvbnMnLFxuXHQgICAgICAgICAqICAgICAgICAgdGFyZ2V0OiBtZS5pZGVudGl0eSxcblx0ICAgICAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cblx0ICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0Vmlld09wdGlvbnMoKSB7XG5cdCAgICAgICAgICogICAgIHZpZXcgPSBhd2FpdCBjcmVhdGVWaWV3KCk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IGNyZWF0ZWQuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9nb29nbGUuY29tJyk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IG5hdmlnYXRlZCB0byBnaXZlbiB1cmwuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgY29uc3QgbWUgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAgICAgKiAgICAgdmlldyA9IGZpbi5WaWV3LndyYXBTeW5jKHsgdXVpZDogbWUuaWRlbnRpdHkudXVpZCwgbmFtZTogJ3ZpZXdOYW1lR2V0T3B0aW9ucycgfSk7XG5cdCAgICAgICAgICogICAgIHJldHVybiB2aWV3LmdldE9wdGlvbnMoKTtcblx0ICAgICAgICAgKiB9XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBnZXRWaWV3T3B0aW9ucygpXG5cdCAgICAgICAgICogICAgIC50aGVuKChpbmZvKSA9PiBjb25zb2xlLmxvZygnVmlldyBvcHRpb25zIGZldGNoZWQuJywgaW5mbykpXG5cdCAgICAgICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgICAgICogYGBgXG5cdCAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHRoaXMuZ2V0T3B0aW9ucyA9IGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtdmlldy1vcHRpb25zJywgeyAuLi50aGlzLmlkZW50aXR5IH0pLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogVXBkYXRlcyB0aGUgdmlldydzIG9wdGlvbnMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogbGV0IHZpZXc7XG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlVmlldygpIHtcblx0ICAgICAgICAgKiAgICAgY29uc3QgbWUgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAgICAgKiAgICAgcmV0dXJuIGZpbi5WaWV3LmNyZWF0ZSh7XG5cdCAgICAgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2dvb2dsZS5jb20nLFxuXHQgICAgICAgICAqICAgICAgICAgbmFtZTogJ3ZpZXdOYW1lVXBkYXRlT3B0aW9ucycsXG5cdCAgICAgICAgICogICAgICAgICB0YXJnZXQ6IG1lLmlkZW50aXR5LFxuXHQgICAgICAgICAqICAgICAgICAgYm91bmRzOiB7dG9wOiAxMCwgbGVmdDogMTAsIHdpZHRoOiAyMDAsIGhlaWdodDogMjAwfVxuXHQgICAgICAgICAqICAgICB9KTtcblx0ICAgICAgICAgKiB9XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBhc3luYyBmdW5jdGlvbiB1cGRhdGVWaWV3T3B0aW9ucygpIHtcblx0ICAgICAgICAgKiAgICAgdmlldyA9IGF3YWl0IGNyZWF0ZVZpZXcoKTtcblx0ICAgICAgICAgKiAgICAgY29uc29sZS5sb2coJ1ZpZXcgY3JlYXRlZC4nKTtcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBhd2FpdCB2aWV3Lm5hdmlnYXRlKCdodHRwczovL2dvb2dsZS5jb20nKTtcblx0ICAgICAgICAgKiAgICAgY29uc29sZS5sb2coJ1ZpZXcgbmF2aWdhdGVkIHRvIGdpdmVuIHVybCBvcHRpb24uJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgY29uc3QgbmV3T3B0aW9ucyA9IHsgYXV0b1Jlc2l6ZToge1xuXHQgICAgICAgICAqICAgICAgICAgd2lkdGg6IHRydWUsXG5cdCAgICAgICAgICogICAgICAgICBob3Jpem9udGFsOiB0cnVlXG5cdCAgICAgICAgICogICAgIH19O1xuXHQgICAgICAgICAqICAgICByZXR1cm4gdmlldy51cGRhdGVPcHRpb25zKG5ld09wdGlvbnMpO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIHVwZGF0ZVZpZXdPcHRpb25zKClcblx0ICAgICAgICAgKiAgICAgLnRoZW4ocGF5bG9hZCA9PiBjb25zb2xlLmxvZygnVmlldyBvcHRpb25zIHVwZGF0ZWQ6ICcsIHBheWxvYWQpKVxuXHQgICAgICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLnVwZGF0ZU9wdGlvbnMgPSBhc3luYyAob3B0aW9ucykgPT4ge1xuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3VwZGF0ZS12aWV3LW9wdGlvbnMnLCB7IG9wdGlvbnMsIC4uLnRoaXMuaWRlbnRpdHkgfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogUmV0cmlldmVzIHRoZSB3aW5kb3cgdGhlIHZpZXcgaXMgY3VycmVudGx5IGF0dGFjaGVkIHRvLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKiBgYGBqc1xuXHQgICAgICAgICAqIGNvbnN0IHZpZXcgPSBmaW4uVmlldy53cmFwU3luYyh7IHV1aWQ6ICd2aWV3VXVpZCcsIG5hbWU6ICd2aWV3TmFtZScgfSk7XG5cdCAgICAgICAgICogdmlldy5nZXRDdXJyZW50V2luZG93KClcblx0ICAgICAgICAgKiAgICAgLnRoZW4od2luID0+IGNvbnNvbGUubG9nKCdjdXJyZW50IHdpbmRvdycsIHdpbikpXG5cdCAgICAgICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7KVxuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLmdldEN1cnJlbnRXaW5kb3cgPSBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhIH0gfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtdmlldy13aW5kb3cnLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgICAgIHJldHVybiBuZXcgd2luZG93XzEuX1dpbmRvdyh0aGlzLndpcmUsIGRhdGEpO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogUmV0cmlldmVzIHRoZSBjdXJyZW50IHtAbGluayBPcGVuRmluLlRhYlN0YWNrfSBvZiB0aGUgdmlldyBpZiBpdCBiZWxvbmdzIHRvIG9uZS5cblx0ICAgICAgICAgKiBAcmV0dXJucyB0aGlzIHZpZXcgYmVsb25ncyB0by5cblx0ICAgICAgICAgKiBAdGhyb3dzIGlmIHRoaXMgdmlldyBkb2VzIG5vdCBiZWxvbmcgdG8gYSBUYWJTdGFjayBvciBpZiB0aGUgd2luZG93IGhhcyBiZWVuIGRlc3Ryb3llZC5cblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogaWYgKCFmaW4ubWUuaXNWaWV3KSB7XG5cdCAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3LicpO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRTdGFjaygpO1xuXHQgICAgICAgICAqIC8vIEFsdGVybmF0aXZlbHksIHlvdSBjYW4gd3JhcCBhbnkgdmlldyBhbmQgZ2V0IHRoZSBzdGFjayBmcm9tIHRoZXJlXG5cdCAgICAgICAgICogLy8gY29uc3Qgdmlld0Zyb21Tb21ld2hlcmUgPSBmaW4uVmlldy53cmFwU3luYyhzb21lVmlldy5pZGVudGl0eSk7XG5cdCAgICAgICAgICogLy8gY29uc3Qgc3RhY2sgPSBhd2FpdCB2aWV3RnJvbVNvbWV3aGVyZS5nZXRDdXJyZW50U3RhY2soKTtcblx0ICAgICAgICAgKiBjb25zdCB2aWV3cyA9IGF3YWl0IHN0YWNrLmdldFZpZXdzKCk7XG5cdCAgICAgICAgICogY29uc29sZS5sb2coYFN0YWNrIGNvbnRhaW5zICR7dmlld3MubGVuZ3RofSB2aWV3KHMpYCk7XG5cdCAgICAgICAgICogYGBgXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy5nZXRDdXJyZW50U3RhY2sgPSBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd2aWV3LWdldC1jdXJyZW50LXN0YWNrJykuY2F0Y2goKCkgPT4ge1xuXHQgICAgICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgbGF5b3V0V2luZG93ID0gYXdhaXQgdGhpcy5nZXRDdXJyZW50V2luZG93KCk7XG5cdCAgICAgICAgICAgICAgICBjb25zdCBwcm92aWRlckNoYW5uZWxDbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9WaWV3X3Byb3ZpZGVyQ2hhbm5lbENsaWVudCwgXCJmXCIpLmdldFZhbHVlKCk7XG5cdCAgICAgICAgICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBsYXlvdXRfZW50aXRpZXNfMS5MYXlvdXROb2RlLm5ld0xheW91dEVudGl0aWVzQ2xpZW50KHByb3ZpZGVyQ2hhbm5lbENsaWVudCwgbGF5b3V0X2NvbnN0YW50c18xLkxBWU9VVF9DT05UUk9MTEVSX0lELCBsYXlvdXRXaW5kb3cuaWRlbnRpdHkpO1xuXHQgICAgICAgICAgICAgICAgY29uc3Qgc3RhY2tEZWZpbml0aW9uID0gKGF3YWl0IGNsaWVudC5nZXRTdGFja0J5Vmlldyh0aGlzLmlkZW50aXR5KSk7XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gbGF5b3V0X2VudGl0aWVzXzEuTGF5b3V0Tm9kZS5nZXRFbnRpdHkoc3RhY2tEZWZpbml0aW9uLCBjbGllbnQpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICAgICAgdGhyb3cgbmV3IHRyYW5zcG9ydF9lcnJvcnNfMS5SdW50aW1lRXJyb3IoeyByZWFzb246ICdUaGlzIHZpZXcgZG9lcyBub3QgYmVsb25nIHRvIGEgc3RhY2suJywgZXJyb3IgfSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9O1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFRyaWdnZXJzIHRoZSBiZWZvcmUtdW5sb2FkIGhhbmRsZXIgZm9yIHRoZSBWaWV3LCBpZiBvbmUgaXMgc2V0LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJlbWFya3MgUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGhhbmRsZXIgaXMgdHJ5aW5nIHRvIHByZXZlbnQgdGhlIFZpZXcgZnJvbSB1bmxvYWRpbmcsIGFuZCBgZmFsc2VgIGlmIGl0IGlzbid0LlxuXHQgICAgICAgICAqIE9ubHkgZW5hYmxlZCB3aGVuIHNldHRpbmcgZW5hYmxlQmVmb3JlVW5sb2FkOiB0cnVlIGluIHlvdXIgVmlldyBvcHRpb25zLiBJZiB0aGlzIG9wdGlvbiBpcyBub3QgZW5hYmxlZCBpdCB3aWxsXG5cdCAgICAgICAgICogYWx3YXlzIHJldHVybiBmYWxzZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIFRoaXMgbWV0aG9kIGlzIHVzZWQgaW50ZXJuYWxseSBieSB0aGUgUGxhdGZvcm0gUHJvdmlkZXIgdG8gZGV0ZXJtaW5lIHRoZSBzdGF0dXMgb2YgZWFjaCBiZWZvcmUgdW5sb2FkIGhhbmRsZXIgaW4gVmlld3Mgd2hlbiBjbG9zaW5nIHRoZSBXaW5kb3cuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogYGBganNcblx0ICAgICAgICAgKiAvLyBmcm9tIGluc2lkZSBhIFZpZXcgY29udGV4dFxuXHQgICAgICAgICAqIGNvbnN0IHVubG9hZFByZXZlbnRlZCA9IGF3YWl0IGZpbi5tZS50cmlnZ2VyQmVmb3JlVW5sb2FkKCk7XG5cdCAgICAgICAgICogYGBgXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy50cmlnZ2VyQmVmb3JlVW5sb2FkID0gYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3RyaWdnZXItYmVmb3JlLXVubG9hZCcsIHsgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2UucGF5bG9hZC5kYXRhO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogKipOT1RFKio6IEludGVybmFsIHVzZSBvbmx5LlxuXHQgICAgICAgICAqIEF0dGFjaGVzIHRoaXMgdmlldyB0byBhbiBIVE1MIGVsZW1lbnQgaW4gdGhlIGN1cnJlbnQgY29udGV4dC4gVGhlIHZpZXcgd2lsbCByZXNpemUgcmVzcG9uc2l2ZWx5IHdoZW4gdGhlIGVsZW1lbnQgYm91bmRzIGNoYW5nZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICoqS25vd24gaXNzdWUqKjogVmlldy5iaW5kVG9FbGVtZW50IGRvZXMgbm90IHRyYWNrIHBvc2l0aW9uIGNoYW5nZXMsIGlmIHRoZSBlbGVtZW50IGhhcyBmaXhlZCBweCB3aWR0aCBhbmQgaGVpZ2h0IHZhbHVlcyBpdCBpcyBwb3NzaWJsZSBmb3IgdGhlIHZpZXcgdG8gbm90IHVwZGF0ZSByZXNwb25zaXZlbHkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAqKktub3duIGlzc3VlKio6IFdoZW4gVmlldy5iaW5kVG9FbGVtZW50IGlzIHVzZWQgb24gYSBlbGVtZW50IHRoYXQgdGFrZXMgdXAgdGhlIGVudGlyZSBwYWdlIGluIGEgcGxhdGZvcm0gd2luZG93LCB0aGUgYm91bmQgdmlldyB3aWxsIG5vdCByZXNwb25kIHJlc3BvbnNpdmVseSB3aGVuIHRoZSB3aW5kb3cgaXMgcmVzaXplZCB0byBiZSBzbWFsbGVyLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIGVsZW1lbnQgLSBIVE1MIGVsZW1lbnQgdG8gYXR0YWNoIHRoZSB2aWV3IHRvLlxuXHQgICAgICAgICAqIEByZXR1cm5zIC0gQ2xlYW51cCBmdW5jdGlvbiB0aGF0IHdpbGwgZGlzY29ubmVjdCB0aGUgZWxlbWVudCByZXNpemUgb2JzZXJ2ZXIuXG5cdCAgICAgICAgICogQGludGVybmFsXG5cdCAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICAgICAqIEByZW1hcmtzIFZpZXcgd2lsbCByZXNpemUgYWNjb3JkaW5nbHkgd2hlbiB0aGUgZWxlbWVudCBpcyByZXNpemVkLiBJZiB0aGUgZWxlbWVudCBpcyByZXBvc2l0aW9uZWQgaW4gdGhlIERPTSB0aGUgdmlldyB3aWxsIG5vdCBiZSByZXBvc2l0aW9uZWQsIHRvIGhhbmRsZSB0aGlzIGNhc2UgY2FsbCBgYmluZFRvRWxlbWVudGAgYWdhaW4gb25jZSB0aGUgZWxlbWVudCBjaGFuZ2VzIHBvc2l0aW9uLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKiBgYGBodG1sXG5cdCAgICAgICAgICogPGRpdiBpZD1cInZpZXctY29udGFpbmVyXCI+PC9kaXY+XG5cdCAgICAgICAgICogPHNjcmlwdD5cblx0ICAgICAgICAgKiAgICAgYXN5bmMgZnVuY3Rpb24gY3JlYXRlQW5kQXR0YWNoVmlldygpIHtcblx0ICAgICAgICAgKiAgICAgICAgIGNvbnN0IHVybCA9ICdodHRwczovL2V4YW1wbGUuY29tJztcblx0ICAgICAgICAgKiAgICAgICAgIGNvbnN0IGVsZW1lbnRJZCA9ICd2aWV3LWNvbnRhaW5lcic7XG5cdCAgICAgICAgICogICAgICAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZWxlbWVudElkKTtcblx0ICAgICAgICAgKiAgICAgICAgIGNvbnN0IHZpZXcgPSBhd2FpdCBmaW4uVmlldy5jcmVhdGUoe1xuXHQgICAgICAgICAqICAgICAgICAgICAgIG5hbWU6ICdteS12aWV3Jyxcblx0ICAgICAgICAgKiAgICAgICAgICAgICB1cmwsXG5cdCAgICAgICAgICogICAgICAgICAgICAgdGFyZ2V0OiBmaW4ubWUuaWRlbnRpdHlcblx0ICAgICAgICAgKiAgICAgICAgIH0pO1xuXHQgICAgICAgICAqICAgICAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSh1cmwpO1xuXHQgICAgICAgICAqICAgICAgICAgYXdhaXQgdmlldy5iaW5kVG9FbGVtZW50KGVsZW1lbnQpO1xuXHQgICAgICAgICAqICAgICB9XG5cdCAgICAgICAgICogICAgIGNyZWF0ZUFuZEF0dGFjaFZpZXcoKS5jYXRjaChjb25zb2xlLmVycm9yKTtcblx0ICAgICAgICAgKiA8L3NjcmlwdD5cblx0ICAgICAgICAgKiBgYGBcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLmJpbmRUb0VsZW1lbnQgPSBhc3luYyAoZWxlbWVudCkgPT4ge1xuXHQgICAgICAgICAgICBpZiAoIWVsZW1lbnQpIHtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRWxlbWVudCBub3QgZm91bmQuJyk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgY29uc3Qgb25DaGFuZ2UgPSBhc3luYyAoYm91bmRzKSA9PiB0aGlzLnNldEJvdW5kcyhib3VuZHMpO1xuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy53aXJlLmVudmlyb25tZW50Lm9ic2VydmVCb3VuZHMoZWxlbWVudCwgb25DaGFuZ2UpO1xuXHQgICAgICAgIH07XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEZvY3VzZXMgdGhlIHZpZXdcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IHZpZXcgPSBmaW4uVmlldy53cmFwU3luYyh7IHV1aWQ6ICd2aWV3VXVpZCcsIG5hbWU6ICd2aWV3TmFtZScgfSk7XG5cdCAgICAgKiBhd2FpdCB2aWV3LmZvY3VzKCk7XG5cdCAgICAgKiAvLyBkbyB0aGluZ3Mgd2l0aCB0aGUgZm9jdXNlZCB2aWV3XG5cdCAgICAgKiBgYGBcblx0ICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZm9jdXMoeyBlbWl0U3ludGhGb2N1c2VkIH0gPSB7IGVtaXRTeW50aEZvY3VzZWQ6IHRydWUgfSkge1xuXHQgICAgICAgIGNvbnN0IHdpbiA9IGF3YWl0IHRoaXMuZ2V0Q3VycmVudFdpbmRvdygpO1xuXHQgICAgICAgIGF3YWl0IHdpbi5mb2N1c2VkV2ViVmlld1dhc0NoYW5nZWQoKTtcblx0ICAgICAgICBhd2FpdCBzdXBlci5mb2N1cyh7IGVtaXRTeW50aEZvY3VzZWQgfSk7XG5cdCAgICB9XG5cdH1cblx0SW5zdGFuY2UkNS5WaWV3ID0gVmlldztcblx0X1ZpZXdfcHJvdmlkZXJDaGFubmVsQ2xpZW50ID0gbmV3IFdlYWtNYXAoKTtcblx0cmV0dXJuIEluc3RhbmNlJDU7XG59XG5cbnZhciBoYXNSZXF1aXJlZFZpZXc7XG5cbmZ1bmN0aW9uIHJlcXVpcmVWaWV3ICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkVmlldykgcmV0dXJuIHZpZXc7XG5cdGhhc1JlcXVpcmVkVmlldyA9IDE7XG5cdChmdW5jdGlvbiAoZXhwb3J0cykge1xuXHRcdHZhciBfX2NyZWF0ZUJpbmRpbmcgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHRcdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHRcdCAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XG5cdFx0ICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XG5cdFx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0XHQgICAgfVxuXHRcdCAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xuXHRcdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdFx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdFx0ICAgIG9bazJdID0gbVtrXTtcblx0XHR9KSk7XG5cdFx0dmFyIF9fZXhwb3J0U3RhciA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2V4cG9ydFN0YXIpIHx8IGZ1bmN0aW9uKG0sIGV4cG9ydHMpIHtcblx0XHQgICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChleHBvcnRzLCBwKSkgX19jcmVhdGVCaW5kaW5nKGV4cG9ydHMsIG0sIHApO1xuXHRcdH07XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRcdC8qKlxuXHRcdCAqIEVudHJ5IHBvaW50cyBmb3IgdGhlIE9wZW5GaW4gYFZpZXdgIEFQSSAoYGZpbi5WaWV3YCkuXG5cdFx0ICpcblx0XHQgKiAqIHtAbGluayBWaWV3TW9kdWxlfSBjb250YWlucyBzdGF0aWMgbWVtYmVycyBvZiB0aGUgYFZpZXdgIEFQSSwgYWNjZXNzaWJsZSB0aHJvdWdoIGBmaW4uVmlld2AuXG5cdFx0ICogKiB7QGxpbmsgVmlld30gZGVzY3JpYmVzIGFuIGluc3RhbmNlIG9mIGFuIE9wZW5GaW4gVmlldywgZS5nLiBhcyByZXR1cm5lZCBieSBgZmluLlZpZXcuZ2V0Q3VycmVudGAuXG5cdFx0ICpcblx0XHQgKiBUaGVzZSBhcmUgc2VwYXJhdGUgY29kZSBlbnRpdGllcywgYW5kIGFyZSBkb2N1bWVudGVkIHNlcGFyYXRlbHkuICBJbiB0aGUgW3ByZXZpb3VzIHZlcnNpb24gb2YgdGhlIEFQSSBkb2N1bWVudGF0aW9uXShodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC8zMi4xMTQuNzYuMTAvaW5kZXguaHRtbCksXG5cdFx0ICogYm90aCBvZiB0aGVzZSB3ZXJlIGRvY3VtZW50ZWQgb24gdGhlIHNhbWUgcGFnZS5cblx0XHQgKlxuXHRcdCAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuXHRcdCAqL1xuXHRcdF9fZXhwb3J0U3RhcihyZXF1aXJlRmFjdG9yeSQzKCksIGV4cG9ydHMpO1xuXHRcdF9fZXhwb3J0U3RhcihyZXF1aXJlSW5zdGFuY2UkMigpLCBleHBvcnRzKTsgXG5cdH0gKHZpZXcpKTtcblx0cmV0dXJuIHZpZXc7XG59XG5cbnZhciBoYXNSZXF1aXJlZEluc3RhbmNlJDE7XG5cbmZ1bmN0aW9uIHJlcXVpcmVJbnN0YW5jZSQxICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkSW5zdGFuY2UkMSkgcmV0dXJuIEluc3RhbmNlJDY7XG5cdGhhc1JlcXVpcmVkSW5zdGFuY2UkMSA9IDE7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShJbnN0YW5jZSQ2LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0SW5zdGFuY2UkNi5BcHBsaWNhdGlvbiA9IHZvaWQgMDtcblx0LyogZXNsaW50LWRpc2FibGUgaW1wb3J0L3ByZWZlci1kZWZhdWx0LWV4cG9ydCAqL1xuXHRjb25zdCBiYXNlXzEgPSBiYXNlO1xuXHRjb25zdCB3aW5kb3dfMSA9IHJlcXVpcmVXaW5kb3coKTtcblx0Y29uc3Qgdmlld18xID0gcmVxdWlyZVZpZXcoKTtcblx0LyoqXG5cdCAqIEFuIG9iamVjdCByZXByZXNlbnRpbmcgYW4gYXBwbGljYXRpb24uIEFsbG93cyB0aGUgZGV2ZWxvcGVyIHRvIGNyZWF0ZSxcblx0ICogZXhlY3V0ZSwgc2hvdy9jbG9zZSBhbiBhcHBsaWNhdGlvbiBhcyB3ZWxsIGFzIGxpc3RlbiB0byB7QGxpbmsgT3BlbkZpbi5BcHBsaWNhdGlvbkV2ZW50cyBhcHBsaWNhdGlvbiBldmVudHN9LlxuXHQgKi9cblx0Y2xhc3MgQXBwbGljYXRpb24gZXh0ZW5kcyBiYXNlXzEuRW1pdHRlckJhc2Uge1xuXHQgICAgLyoqXG5cdCAgICAgKiBAaW50ZXJuYWxcblx0ICAgICAqL1xuXHQgICAgY29uc3RydWN0b3Iod2lyZSwgaWRlbnRpdHkpIHtcblx0ICAgICAgICBzdXBlcih3aXJlLCAnYXBwbGljYXRpb24nLCBpZGVudGl0eS51dWlkKTtcblx0ICAgICAgICB0aGlzLmlkZW50aXR5ID0gaWRlbnRpdHk7XG5cdCAgICAgICAgdGhpcy53aW5kb3cgPSBuZXcgd2luZG93XzEuX1dpbmRvdyh0aGlzLndpcmUsIHtcblx0ICAgICAgICAgICAgdXVpZDogdGhpcy5pZGVudGl0eS51dWlkLFxuXHQgICAgICAgICAgICBuYW1lOiB0aGlzLmlkZW50aXR5LnV1aWRcblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIHdpbmRvd0xpc3RGcm9tSWRlbnRpdHlMaXN0KGlkZW50aXR5TGlzdCkge1xuXHQgICAgICAgIGNvbnN0IHdpbmRvd0xpc3QgPSBbXTtcblx0ICAgICAgICBpZGVudGl0eUxpc3QuZm9yRWFjaCgoaWRlbnRpdHkpID0+IHtcblx0ICAgICAgICAgICAgd2luZG93TGlzdC5wdXNoKG5ldyB3aW5kb3dfMS5fV2luZG93KHRoaXMud2lyZSwge1xuXHQgICAgICAgICAgICAgICAgdXVpZDogaWRlbnRpdHkudXVpZCxcblx0ICAgICAgICAgICAgICAgIG5hbWU6IGlkZW50aXR5Lm5hbWVcblx0ICAgICAgICAgICAgfSkpO1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiB3aW5kb3dMaXN0O1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBEZXRlcm1pbmVzIGlmIHRoZSBhcHBsaWNhdGlvbiBpcyBjdXJyZW50bHkgcnVubmluZy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBpc0FwcFJ1bm5pbmcoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmlzUnVubmluZygpO1xuXHQgICAgICogfVxuXHQgICAgICogaXNBcHBSdW5uaW5nKCkudGhlbihydW5uaW5nID0+IGNvbnNvbGUubG9nKGBDdXJyZW50IGFwcCBpcyBydW5uaW5nOiAke3J1bm5pbmd9YCkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBpc1J1bm5pbmcoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpcy1hcHBsaWNhdGlvbi1ydW5uaW5nJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIENsb3NlcyB0aGUgYXBwbGljYXRpb24gYW5kIGFueSBjaGlsZCB3aW5kb3dzIGNyZWF0ZWQgYnkgdGhlIGFwcGxpY2F0aW9uLlxuXHQgICAgICogQ2xlYW5zIHRoZSBhcHBsaWNhdGlvbiBmcm9tIHN0YXRlIHNvIGl0IGlzIG5vIGxvbmdlciBmb3VuZCBpbiBnZXRBbGxBcHBsaWNhdGlvbnMuXG5cdCAgICAgKiBAcGFyYW0gZm9yY2UgQ2xvc2Ugd2lsbCBiZSBwcmV2ZW50ZWQgZnJvbSBjbG9zaW5nIHdoZW4gZm9yY2UgaXMgZmFsc2UgYW5kXG5cdCAgICAgKiAg4oCYY2xvc2UtcmVxdWVzdGVk4oCZIGhhcyBiZWVuIHN1YnNjcmliZWQgdG8gZm9yIGFwcGxpY2F0aW9u4oCZcyBtYWluIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBjbG9zZUFwcCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhbGxBcHBzMSA9IGF3YWl0IGZpbi5TeXN0ZW0uZ2V0QWxsQXBwbGljYXRpb25zKCk7IC8vW3t1dWlkOiAnYXBwMScsIGlzUnVubmluZzogdHJ1ZX0sIHt1dWlkOiAnYXBwMicsIGlzUnVubmluZzogdHJ1ZX1dXG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLndyYXAoe3V1aWQ6ICdhcHAyJ30pO1xuXHQgICAgICogICAgIGF3YWl0IGFwcC5xdWl0KCk7XG5cdCAgICAgKiAgICAgY29uc3QgYWxsQXBwczIgPSBhd2FpdCBmaW4uU3lzdGVtLmdldEFsbEFwcGxpY2F0aW9ucygpOyAvL1t7dXVpZDogJ2FwcDEnLCBpc1J1bm5pbmc6IHRydWV9XVxuXHQgICAgICpcblx0ICAgICAqIH1cblx0ICAgICAqIGNsb3NlQXBwKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQXBwbGljYXRpb24gcXVpdCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgcXVpdChmb3JjZSA9IGZhbHNlKSB7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy5fY2xvc2UoZm9yY2UpO1xuXHQgICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZGVzdHJveS1hcHBsaWNhdGlvbicsIHsgZm9yY2UsIC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zdCBhY2NlcHRhYmxlRXJyb3JzID0gWydSZW1vdGUgY29ubmVjdGlvbiBoYXMgY2xvc2VkJywgJ0NvdWxkIG5vdCBsb2NhdGUgdGhlIHJlcXVlc3RlZCBhcHBsaWNhdGlvbiddO1xuXHQgICAgICAgICAgICBpZiAoIWFjY2VwdGFibGVFcnJvcnMuc29tZSgobXNnKSA9PiBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKG1zZykpKSB7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIGFzeW5jIF9jbG9zZShmb3JjZSA9IGZhbHNlKSB7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2Nsb3NlLWFwcGxpY2F0aW9uJywgeyBmb3JjZSwgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGlmICghZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnUmVtb3RlIGNvbm5lY3Rpb24gaGFzIGNsb3NlZCcpKSB7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQGRlcHJlY2F0ZWQgdXNlIEFwcGxpY2F0aW9uLnF1aXQgaW5zdGVhZFxuXHQgICAgICogQ2xvc2VzIHRoZSBhcHBsaWNhdGlvbiBhbmQgYW55IGNoaWxkIHdpbmRvd3MgY3JlYXRlZCBieSB0aGUgYXBwbGljYXRpb24uXG5cdCAgICAgKiBAcGFyYW0gZm9yY2UgLSBDbG9zZSB3aWxsIGJlIHByZXZlbnRlZCBmcm9tIGNsb3Npbmcgd2hlbiBmb3JjZSBpcyBmYWxzZSBhbmQg4oCYY2xvc2UtcmVxdWVzdGVk4oCZIGhhcyBiZWVuIHN1YnNjcmliZWQgdG8gZm9yIGFwcGxpY2F0aW9u4oCZcyBtYWluIHdpbmRvdy5cblx0ICAgICAqIEBwYXJhbSBjYWxsYmFjayAtIGNhbGxlZCBpZiB0aGUgbWV0aG9kIHN1Y2NlZWRzLlxuXHQgICAgICogQHBhcmFtIGVycm9yQ2FsbGJhY2sgLSBjYWxsZWQgaWYgdGhlIG1ldGhvZCBmYWlscy4gVGhlIHJlYXNvbiBmb3IgZmFpbHVyZSBpcyBwYXNzZWQgYXMgYW4gYXJndW1lbnQuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY2xvc2VBcHAoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmNsb3NlKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKiBjbG9zZUFwcCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0FwcGxpY2F0aW9uIGNsb3NlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgY2xvc2UoZm9yY2UgPSBmYWxzZSkge1xuXHQgICAgICAgIGNvbnNvbGUud2FybignRGVwcmVjYXRpb24gV2FybmluZzogQXBwbGljYXRpb24uY2xvc2UgaXMgZGVwcmVjYXRlZCBQbGVhc2UgdXNlIEFwcGxpY2F0aW9uLnF1aXQnKTtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignYXBwbGljYXRpb24tY2xvc2UnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gdGhpcy5fY2xvc2UoZm9yY2UpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXRyaWV2ZXMgYW4gYXJyYXkgb2Ygd3JhcHBlZCBmaW4uV2luZG93cyBmb3IgZWFjaCBvZiB0aGUgYXBwbGljYXRpb27igJlzIGNoaWxkIHdpbmRvd3MuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0Q2hpbGRXaW5kb3dzKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRDaGlsZFdpbmRvd3MoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRDaGlsZFdpbmRvd3MoKS50aGVuKGNoaWxkcmVuID0+IGNvbnNvbGUubG9nKGNoaWxkcmVuKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldENoaWxkV2luZG93cygpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1jaGlsZC13aW5kb3dzJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgaWRlbnRpdHlMaXN0ID0gW107XG5cdCAgICAgICAgICAgIHBheWxvYWQuZGF0YS5mb3JFYWNoKCh3aW5OYW1lKSA9PiB7XG5cdCAgICAgICAgICAgICAgICBpZGVudGl0eUxpc3QucHVzaCh7IHV1aWQ6IHRoaXMuaWRlbnRpdHkudXVpZCwgbmFtZTogd2luTmFtZSB9KTtcblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgIHJldHVybiB0aGlzLndpbmRvd0xpc3RGcm9tSWRlbnRpdHlMaXN0KGlkZW50aXR5TGlzdCk7XG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyB0aGUgSlNPTiBtYW5pZmVzdCB0aGF0IHdhcyB1c2VkIHRvIGNyZWF0ZSB0aGUgYXBwbGljYXRpb24uIEludm9rZXMgdGhlIGVycm9yIGNhbGxiYWNrXG5cdCAgICAgKiBpZiB0aGUgYXBwbGljYXRpb24gd2FzIG5vdCBjcmVhdGVkIGZyb20gYSBtYW5pZmVzdC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRNYW5pZmVzdCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0TWFuaWZlc3QoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRNYW5pZmVzdCgpLnRoZW4obWFuaWZlc3QgPT4gY29uc29sZS5sb2cobWFuaWZlc3QpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0TWFuaWZlc3QoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtYXBwbGljYXRpb24tbWFuaWZlc3QnLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIFVVSUQgb2YgdGhlIGFwcGxpY2F0aW9uIHRoYXQgbGF1bmNoZXMgdGhpcyBhcHBsaWNhdGlvbi4gSW52b2tlcyB0aGUgZXJyb3IgY2FsbGJhY2tcblx0ICAgICAqIGlmIHRoZSBhcHBsaWNhdGlvbiB3YXMgY3JlYXRlZCBmcm9tIGEgbWFuaWZlc3QuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0UGFyZW50VXVpZCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtQXBwbGljYXRpb24uZ2V0UGFyZW50VXVpZC5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFBhcmVudFV1aWQoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRQYXJlbnRVdWlkKCkudGhlbihwYXJlbnRVdWlkID0+IGNvbnNvbGUubG9nKHBhcmVudFV1aWQpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0UGFyZW50VXVpZCgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1wYXJlbnQtYXBwbGljYXRpb24nLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIGN1cnJlbnQgYXBwbGljYXRpb24ncyBzaG9ydGN1dCBjb25maWd1cmF0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFNob3J0Y3V0cygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24ud3JhcCh7IHV1aWQ6ICd0ZXN0YXBwJyB9KTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFNob3J0Y3V0cygpO1xuXHQgICAgICogfVxuXHQgICAgICogZ2V0U2hvcnRjdXRzKCkudGhlbihjb25maWcgPT4gY29uc29sZS5sb2coY29uZmlnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldFNob3J0Y3V0cygpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1zaG9ydGN1dHMnLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIGN1cnJlbnQgYXBwbGljYXRpb24ncyB2aWV3cy5cblx0ICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRWaWV3cygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0Vmlld3MoKTtcblx0ICAgICAqIH1cblx0ICAgICAqIGdldFZpZXdzKCkudGhlbih2aWV3cyA9PiBjb25zb2xlLmxvZyh2aWV3cykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRWaWV3cygpIHtcblx0ICAgICAgICBjb25zdCB7IHBheWxvYWQgfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdhcHBsaWNhdGlvbi1nZXQtdmlld3MnLCB0aGlzLmlkZW50aXR5KTtcblx0ICAgICAgICByZXR1cm4gcGF5bG9hZC5kYXRhLm1hcCgoaWQpID0+IG5ldyB2aWV3XzEuVmlldyh0aGlzLndpcmUsIGlkKSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQgem9vbSBsZXZlbCBvZiB0aGUgYXBwbGljYXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0Wm9vbUxldmVsKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRab29tTGV2ZWwoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRab29tTGV2ZWwoKS50aGVuKHpvb21MZXZlbCA9PiBjb25zb2xlLmxvZyh6b29tTGV2ZWwpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0Wm9vbUxldmVsKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWFwcGxpY2F0aW9uLXpvb20tbGV2ZWwnLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0dXJucyBhbiBpbnN0YW5jZSBvZiB0aGUgbWFpbiBXaW5kb3cgb2YgdGhlIGFwcGxpY2F0aW9uXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0V2luZG93KCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1BcHBsaWNhdGlvbi5nZXRXaW5kb3cuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRXaW5kb3coKS50aGVuKHdpbiA9PiB7XG5cdCAgICAgKiAgICAgd2luLnNob3dBdCgwLCA0MDApO1xuXHQgICAgICogICAgIHdpbi5mbGFzaCgpO1xuXHQgICAgICogfSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldFdpbmRvdygpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignYXBwbGljYXRpb24tZ2V0LXdpbmRvdycsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy53aW5kb3cpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBNYW51YWxseSByZWdpc3RlcnMgYSB1c2VyIHdpdGggdGhlIGxpY2Vuc2luZyBzZXJ2aWNlLiBUaGUgb25seSBkYXRhIHNlbnQgYnkgdGhpcyBjYWxsIGlzIHVzZXJOYW1lIGFuZCBhcHBOYW1lLlxuXHQgICAgICogQHBhcmFtIHVzZXJOYW1lIC0gdXNlcm5hbWUgdG8gYmUgcGFzc2VkIHRvIHRoZSBSVk0uXG5cdCAgICAgKiBAcGFyYW0gYXBwTmFtZSAtIGFwcCBuYW1lIHRvIGJlIHBhc3NlZCB0byB0aGUgUlZNLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHJlZ2lzdGVyVXNlcigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAucmVnaXN0ZXJVc2VyKCd1c2VyJywgJ215QXBwJyk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogcmVnaXN0ZXJVc2VyKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU3VjY2Vzc2Z1bGx5IHJlZ2lzdGVyZWQgdGhlIHVzZXInKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHJlZ2lzdGVyVXNlcih1c2VyTmFtZSwgYXBwTmFtZSkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigncmVnaXN0ZXItdXNlcicsIHsgdXNlck5hbWUsIGFwcE5hbWUsIC4uLnRoaXMuaWRlbnRpdHkgfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZW1vdmVzIHRoZSBhcHBsaWNhdGlvbuKAmXMgaWNvbiBmcm9tIHRoZSB0cmF5LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHJlbW92ZVRyYXlJY29uKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5yZW1vdmVUcmF5SWNvbigpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHJlbW92ZVRyYXlJY29uKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnUmVtb3ZlZCB0aGUgdHJheSBpY29uLicpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgcmVtb3ZlVHJheUljb24oKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdyZW1vdmUtdHJheS1pY29uJywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXN0YXJ0cyB0aGUgYXBwbGljYXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gcmVzdGFydEFwcCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAucmVzdGFydCgpO1xuXHQgICAgICogfVxuXHQgICAgICogcmVzdGFydEFwcCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0FwcGxpY2F0aW9uIHJlc3RhcnRlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgcmVzdGFydCgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Jlc3RhcnQtYXBwbGljYXRpb24nLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIERFUFJFQ0FURUQgbWV0aG9kIHRvIHJ1biB0aGUgYXBwbGljYXRpb24uXG5cdCAgICAgKiBOZWVkZWQgd2hlbiBzdGFydGluZyBhcHBsaWNhdGlvbiB2aWEge0BsaW5rIEFwcGxpY2F0aW9uLmNyZWF0ZX0sIGJ1dCBOT1QgbmVlZGVkIHdoZW4gc3RhcnRpbmcgdmlhIHtAbGluayBBcHBsaWNhdGlvbi5zdGFydH0uXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gcnVuKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5jcmVhdGUoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtQXBwbGljYXRpb24ucnVuLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGF3YWl0IGFwcC5ydW4oKTtcblx0ICAgICAqIH1cblx0ICAgICAqIHJ1bigpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0FwcGxpY2F0aW9uIGlzIHJ1bm5pbmcnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICogQGlnbm9yZVxuXHQgICAgICovXG5cdCAgICBydW4oKSB7XG5cdCAgICAgICAgY29uc29sZS53YXJuKCdEZXByZWNhdGlvbiBXYXJuaW5nOiBBcHBsaWNhdGlvbi5ydW4gaXMgZGVwcmVjYXRlZCBQbGVhc2UgdXNlIGZpbi5BcHBsaWNhdGlvbi5zdGFydCcpO1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdhcHBsaWNhdGlvbi1ydW4nLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gdGhpcy5fcnVuKCk7XG5cdCAgICB9XG5cdCAgICBfcnVuKG9wdHMgPSB7fSkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmVcblx0ICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ3J1bi1hcHBsaWNhdGlvbicsIHtcblx0ICAgICAgICAgICAgbWFuaWZlc3RVcmw6IHRoaXMuX21hbmlmZXN0VXJsLFxuXHQgICAgICAgICAgICBvcHRzLFxuXHQgICAgICAgICAgICAuLi50aGlzLmlkZW50aXR5XG5cdCAgICAgICAgfSlcblx0ICAgICAgICAgICAgLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogSW5zdHJ1Y3RzIHRoZSBSVk0gdG8gc2NoZWR1bGUgb25lIHJlc3RhcnQgb2YgdGhlIGFwcGxpY2F0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNjaGVkdWxlUmVzdGFydCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuc2NoZWR1bGVSZXN0YXJ0KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogc2NoZWR1bGVSZXN0YXJ0KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQXBwbGljYXRpb24gaXMgc2NoZWR1bGVkIHRvIHJlc3RhcnQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHNjaGVkdWxlUmVzdGFydCgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3JlbGF1bmNoLW9uLWNsb3NlJywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTZW5kcyBhIG1lc3NhZ2UgdG8gdGhlIFJWTSB0byB1cGxvYWQgdGhlIGFwcGxpY2F0aW9uJ3MgbG9ncy4gT24gc3VjY2Vzcyxcblx0ICAgICAqIGFuIG9iamVjdCBjb250YWluaW5nIGxvZ0lkIGlzIHJldHVybmVkLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNlbmRMb2coKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLnNlbmRBcHBsaWNhdGlvbkxvZygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHNlbmRMb2coKS50aGVuKGluZm8gPT4gY29uc29sZS5sb2coaW5mby5sb2dJZCkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBzZW5kQXBwbGljYXRpb25Mb2coKSB7XG5cdCAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc2VuZC1hcHBsaWNhdGlvbi1sb2cnLCB0aGlzLmlkZW50aXR5KTtcblx0ICAgICAgICByZXR1cm4gcGF5bG9hZC5kYXRhO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTZXRzIG9yIHJlbW92ZXMgYSBjdXN0b20gSnVtcExpc3QgZm9yIHRoZSBhcHBsaWNhdGlvbi4gT25seSBhcHBsaWNhYmxlIGluIFdpbmRvd3MgT1MuXG5cdCAgICAgKiBJZiBjYXRlZ29yaWVzIGlzIG51bGwgdGhlIHByZXZpb3VzbHkgc2V0IGN1c3RvbSBKdW1wTGlzdCAoaWYgYW55KSB3aWxsIGJlIHJlcGxhY2VkIGJ5IHRoZSBzdGFuZGFyZCBKdW1wTGlzdCBmb3IgdGhlIGFwcCAobWFuYWdlZCBieSBXaW5kb3dzKS5cblx0ICAgICAqXG5cdCAgICAgKiBOb3RlOiBJZiB0aGUgXCJuYW1lXCIgcHJvcGVydHkgaXMgb21pdHRlZCBpdCBkZWZhdWx0cyB0byBcInRhc2tzXCIuXG5cdCAgICAgKiBAcGFyYW0ganVtcExpc3RDYXRlZ29yaWVzIEFuIGFycmF5IG9mIEp1bXBMaXN0IENhdGVnb3JpZXMgdG8gcG9wdWxhdGUuIElmIG51bGwsIHJlbW92ZSBhbnkgZXhpc3RpbmcgSnVtcExpc3QgY29uZmlndXJhdGlvbiBhbmQgc2V0IHRvIFdpbmRvd3MgZGVmYXVsdC5cblx0ICAgICAqXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgSWYgY2F0ZWdvcmllcyBpcyBudWxsIHRoZSBwcmV2aW91c2x5IHNldCBjdXN0b20gSnVtcExpc3QgKGlmIGFueSkgd2lsbCBiZSByZXBsYWNlZCBieSB0aGUgc3RhbmRhcmQgSnVtcExpc3QgZm9yIHRoZSBhcHAgKG1hbmFnZWQgYnkgV2luZG93cykuXG5cdCAgICAgKlxuXHQgICAgICogVGhlIGJvdHRvbW1vc3QgaXRlbSBpbiB0aGUganVtcGxpc3Qgd2lsbCBhbHdheXMgYmUgYW4gaXRlbSBwb2ludGluZyB0byB0aGUgY3VycmVudCBhcHAuIEl0cyBuYW1lIGlzIHRha2VuIGZyb20gdGhlIG1hbmlmZXN0J3Ncblx0ICAgICAqICoqYCBzaG9ydGN1dC5uYW1lIGAqKiBhbmQgdXNlcyAqKmAgc2hvcnRjdXQuY29tcGFueSBgKiogYXMgYSBmYWxsYmFjay4gQ2xpY2tpbmcgdGhhdCBpdGVtIHdpbGwgbGF1bmNoIHRoZSBhcHAgZnJvbSBpdHMgY3VycmVudCBtYW5pZmVzdC5cblx0ICAgICAqXG5cdCAgICAgKiBOb3RlOiBJZiB0aGUgXCJuYW1lXCIgcHJvcGVydHkgaXMgb21pdHRlZCBpdCBkZWZhdWx0cyB0byBcInRhc2tzXCIuXG5cdCAgICAgKlxuXHQgICAgICogTm90ZTogV2luZG93IE9TIGNhY2hlcyBqdW1wbGlzdHMgaWNvbnMsIHRoZXJlZm9yZSBhbiBpY29uIGNoYW5nZSBtaWdodCBvbmx5IGJlIHZpc2libGUgYWZ0ZXIgdGhlIGNhY2hlIGlzIHJlbW92ZWQgb3IgdGhlXG5cdCAgICAgKiB1dWlkIG9yIHNob3J0Y3V0Lm5hbWUgaXMgY2hhbmdlZC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnRTeW5jKCk7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwTmFtZSA9ICdNeSBBcHAnO1xuXHQgICAgICogICAgIGNvbnN0IGp1bXBMaXN0Q29uZmlnID0gWyAvLyBhcnJheSBvZiBKdW1wTGlzdCBjYXRlZ29yaWVzXG5cdCAgICAgKiAgICAgICAgIHtcblx0ICAgICAqICAgICAgICAgICAgIC8vIGhhcyBubyBuYW1lIGFuZCBubyB0eXBlIHNvIGB0eXBlYCBpcyBhc3N1bWVkIHRvIGJlIFwidGFza3NcIlxuXHQgICAgICogICAgICAgICAgICAgaXRlbXM6IFsgLy8gYXJyYXkgb2YgSnVtcExpc3QgaXRlbXNcblx0ICAgICAqICAgICAgICAgICAgIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICB0eXBlOiAndGFzaycsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgdGl0bGU6IGBMYXVuY2ggJHthcHBOYW1lfWAsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IGBSdW5zICR7YXBwTmFtZX0gd2l0aCB0aGUgZGVmYXVsdCBjb25maWd1cmF0aW9uYCxcblx0ICAgICAqICAgICAgICAgICAgICAgICBkZWVwTGluazogJ2ZpbnM6Ly9wYXRoLnRvL2FwcC9tYW5pZmVzdC5qc29uJyxcblx0ICAgICAqICAgICAgICAgICAgICAgICBpY29uUGF0aDogJ2h0dHBzOi8vcGF0aC50by9hcHAvaWNvbi5pY28nLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGljb25JbmRleDogMFxuXHQgICAgICogICAgICAgICAgICAgfSxcblx0ICAgICAqICAgICAgICAgICAgIHsgdHlwZTogJ3NlcGFyYXRvcicgfSxcblx0ICAgICAqICAgICAgICAgICAgIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICB0eXBlOiAndGFzaycsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgdGl0bGU6IGBSZXN0b3JlICR7YXBwTmFtZX1gLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnUmVzdG9yZSB0byBsYXN0IGNvbmZpZ3VyYXRpb24nLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGRlZXBMaW5rOiAnZmluczovL3BhdGgudG8vYXBwL21hbmlmZXN0Lmpzb24/JCR1c2UtbGFzdC1jb25maWd1cmF0aW9uPXRydWUnLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGljb25QYXRoOiAnaHR0cHM6Ly9wYXRoLnRvL2FwcC9pY29uLmljbycsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgaWNvbkluZGV4OiAwXG5cdCAgICAgKiAgICAgICAgICAgICB9LFxuXHQgICAgICogICAgICAgICAgICAgXVxuXHQgICAgICogICAgICAgICB9LFxuXHQgICAgICogICAgICAgICB7XG5cdCAgICAgKiAgICAgICAgICAgICBuYW1lOiAnVG9vbHMnLFxuXHQgICAgICogICAgICAgICAgICAgaXRlbXM6IFsgLy8gYXJyYXkgb2YgSnVtcExpc3QgaXRlbXNcblx0ICAgICAqICAgICAgICAgICAgIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICB0eXBlOiAndGFzaycsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgdGl0bGU6ICdUb29sIEEnLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnUnVucyBUb29sIEEnLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGRlZXBMaW5rOiAnZmluczovL3BhdGgudG8vdG9vbC1hL21hbmlmZXN0Lmpzb24nLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGljb25QYXRoOiAnaHR0cHM6Ly9wYXRoLnRvL3Rvb2wtYS9pY29uLmljbycsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgaWNvbkluZGV4OiAwXG5cdCAgICAgKiAgICAgICAgICAgICB9LFxuXHQgICAgICogICAgICAgICAgICAge1xuXHQgICAgICogICAgICAgICAgICAgICAgIHR5cGU6ICd0YXNrJyxcblx0ICAgICAqICAgICAgICAgICAgICAgICB0aXRsZTogJ1Rvb2wgQicsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246ICdSdW5zIFRvb2wgQicsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgZGVlcExpbms6ICdmaW5zOi8vcGF0aC50by90b29sLWIvbWFuaWZlc3QuanNvbicsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgaWNvblBhdGg6ICdodHRwczovL3BhdGgudG8vdG9vbC1iL2ljb24uaWNvJyxcblx0ICAgICAqICAgICAgICAgICAgICAgICBpY29uSW5kZXg6IDBcblx0ICAgICAqICAgICAgICAgICAgIH1dXG5cdCAgICAgKiAgICAgICAgIH1cblx0ICAgICAqICAgICBdO1xuXHQgICAgICpcblx0ICAgICAqICAgICBhcHAuc2V0SnVtcExpc3QoanVtcExpc3RDb25maWcpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0p1bXBMaXN0IGFwcGxpZWQnKSkuY2F0Y2goZSA9PiBjb25zb2xlLmxvZyhgSnVtcExpc3QgZmFpbGVkIHRvIGFwcGx5OiAke2UudG9TdHJpbmcoKX1gKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqXG5cdCAgICAgKiBUbyBoYW5kbGUgZGVlcGxpbmsgYXJnczpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiAgICAgZnVuY3Rpb24gaGFuZGxlVXNlTGFzdENvbmZpZ3VyYXRpb24oKSB7XG5cdCAgICAgKiAgICAgICAgIC8vIHRoaXMgaGFuZGxlciBpcyBjYWxsZWQgd2hlbiB0aGUgYXBwIGlzIGJlaW5nIGxhdW5jaGVkXG5cdCAgICAgKiAgICAgICAgIGFwcC5vbigncnVuLXJlcXVlc3RlZCcsIGV2ZW50ID0+IHtcblx0ICAgICAqICAgICAgICAgICAgIGlmKGV2ZW50LnVzZXJBcHBDb25maWdBcmdzWyd1c2UtbGFzdC1jb25maWd1cmF0aW9uJ10pIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAvLyB5b3VyIGxvZ2ljIGhlcmVcblx0ICAgICAqICAgICAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgfSk7XG5cdCAgICAgKiAgICAgICAgIC8vIHRoaXMgaGFuZGxlciBpcyBjYWxsZWQgd2hlbiB0aGUgYXBwIHdhcyBhbHJlYWR5IHJ1bm5pbmcgd2hlbiB0aGUgbGF1bmNoIHdhcyByZXF1ZXN0ZWRcblx0ICAgICAqICAgICAgICAgZmluLmRlc2t0b3AubWFpbihmdW5jdGlvbihhcmdzKSB7XG5cdCAgICAgKiAgICAgICAgICAgICBpZihhcmdzICYmIGFyZ3NbJ3VzZS1sYXN0LWNvbmZpZ3VyYXRpb24nXSkge1xuXHQgICAgICogICAgICAgICAgICAgICAgIC8vIHlvdXIgbG9naWMgaGVyZVxuXHQgICAgICogICAgICAgICAgICAgfVxuXHQgICAgICogICAgICAgICB9KTtcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgc2V0SnVtcExpc3QoanVtcExpc3RDYXRlZ29yaWVzKSB7XG5cdCAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NldC1qdW1wLWxpc3QnLCB7IGNvbmZpZzoganVtcExpc3RDYXRlZ29yaWVzLCAuLi50aGlzLmlkZW50aXR5IH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBBZGRzIGEgY3VzdG9taXphYmxlIGljb24gaW4gdGhlIHN5c3RlbSB0cmF5LiAgVG8gbGlzdGVuIGZvciBhIGNsaWNrIG9uIHRoZSBpY29uIHVzZSB0aGUgYHRyYXktaWNvbi1jbGlja2VkYCBldmVudC5cblx0ICAgICAqIEBwYXJhbSBpY29uIEltYWdlIFVSTCBvciBiYXNlNjQgZW5jb2RlZCBzdHJpbmcgdG8gYmUgdXNlZCBhcyB0aGUgaWNvblxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IGltYWdlVXJsID0gXCJodHRwOi8vY2RuLm9wZW5maW4uY28vYXNzZXRzL3Rlc3RpbmcvaWNvbnMvY2lyY2xlZC1kaWdpdC1vbmUucG5nXCI7XG5cdCAgICAgKiBjb25zdCBiYXNlNjRFbmNvZGVkSW1hZ2UgPSBcImlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFBZ0FBQUFJQVFNQUFBRCt3U3pJQUFBQUJsQk1WRVhcXFxuXHQgICAgICogLy8vKy92NytqUTNZNUFBQUFEa2xFUVZRSTEyUDRBSVg4RUFnQUxnQUQvYU5wYnRFQUFBQUFTVVZPUks1Q1lJSVwiO1xuXHQgICAgICogY29uc3QgZGF0YVVSTCA9IFwiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFBVUFBQUFGQ0FZQUFBQ05ieWJsQUFBQUhFbEVRVlFJMTJQNC8vOC93MzhHSUFYRElCS0UwREhcXFxuXHQgICAgICogeGdsak5CQUFPOVRYTDBZNE9Id0FBQUFCSlJVNUVya0pnZ2c9PVwiO1xuXHQgICAgICpcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNldFRyYXlJY29uKGljb24pIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuc2V0VHJheUljb24oaWNvbik7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogLy8gdXNlIGltYWdlIHVybCB0byBzZXQgdHJheSBpY29uXG5cdCAgICAgKiBzZXRUcmF5SWNvbihpbWFnZVVybCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU2V0dGluZyB0cmF5IGljb24nKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICpcblx0ICAgICAqIC8vIHVzZSBiYXNlNjQgZW5jb2RlZCBzdHJpbmcgdG8gc2V0IHRyYXkgaWNvblxuXHQgICAgICogc2V0VHJheUljb24oYmFzZTY0RW5jb2RlZEltYWdlKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTZXR0aW5nIHRyYXkgaWNvbicpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKlxuXHQgICAgICogLy8gdXNlIGEgZGF0YVVSTCB0byBzZXQgdHJheSBpY29uXG5cdCAgICAgKiBzZXRUcmF5SWNvbihkYXRhVVJMKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTZXR0aW5nIHRyYXkgaWNvbicpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgc2V0VHJheUljb24oaWNvbikge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmVcblx0ICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ3NldC10cmF5LWljb24nLCB7XG5cdCAgICAgICAgICAgIGVuYWJsZWRJY29uOiBpY29uLFxuXHQgICAgICAgICAgICAuLi50aGlzLmlkZW50aXR5XG5cdCAgICAgICAgfSlcblx0ICAgICAgICAgICAgLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2V0cyBuZXcgYXBwbGljYXRpb24ncyBzaG9ydGN1dCBjb25maWd1cmF0aW9uLiBXaW5kb3dzIG9ubHkuXG5cdCAgICAgKiBAcGFyYW0gY29uZmlnIE5ldyBhcHBsaWNhdGlvbidzIHNob3J0Y3V0IGNvbmZpZ3VyYXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgQXBwbGljYXRpb24gaGFzIHRvIGJlIGxhdW5jaGVkIHdpdGggYSBtYW5pZmVzdCBhbmQgaGFzIHRvIGhhdmUgc2hvcnRjdXQgY29uZmlndXJhdGlvbiAoaWNvbiB1cmwsIG5hbWUsIGV0Yy4pIGluIGl0cyBtYW5pZmVzdFxuXHQgICAgICogdG8gYmUgYWJsZSB0byBjaGFuZ2Ugc2hvcnRjdXQgc3RhdGVzLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNldFNob3J0Y3V0cyhjb25maWcpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhcHAuc2V0U2hvcnRjdXRzKGNvbmZpZyk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogc2V0U2hvcnRjdXRzKHtcblx0ICAgICAqICAgICBkZXNrdG9wOiB0cnVlLFxuXHQgICAgICogICAgIHN0YXJ0TWVudTogZmFsc2UsXG5cdCAgICAgKiAgICAgc3lzdGVtU3RhcnR1cDogdHJ1ZVxuXHQgICAgICogfSkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU2hvcnRjdXRzIGFyZSBzZXQuJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBzZXRTaG9ydGN1dHMoY29uZmlnKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzZXQtc2hvcnRjdXRzJywgeyBkYXRhOiBjb25maWcsIC4uLnRoaXMuaWRlbnRpdHkgfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTZXRzIHRoZSBxdWVyeSBzdHJpbmcgaW4gYWxsIHNob3J0Y3V0cyBmb3IgdGhpcyBhcHAuIFJlcXVpcmVzIFJWTSA1LjUrLlxuXHQgICAgICogQHBhcmFtIHF1ZXJ5U3RyaW5nIFRoZSBuZXcgcXVlcnkgc3RyaW5nIGZvciB0aGlzIGFwcCdzIHNob3J0Y3V0cy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCBuZXdRdWVyeUFyZ3MgPSAnYXJnPXRydWUmYXJnMj1mYWxzZSc7XG5cdCAgICAgKiBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogdHJ5IHtcblx0ICAgICAqICAgICBhd2FpdCBhcHAuc2V0U2hvcnRjdXRRdWVyeVBhcmFtcyhuZXdRdWVyeUFyZ3MpO1xuXHQgICAgICogfSBjYXRjaChlcnIpIHtcblx0ICAgICAqICAgICBjb25zb2xlLmVycm9yKGVycilcblx0ICAgICAqIH1cblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBzZXRTaG9ydGN1dFF1ZXJ5UGFyYW1zKHF1ZXJ5U3RyaW5nKSB7XG5cdCAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NldC1zaG9ydGN1dC1xdWVyeS1hcmdzJywgeyBkYXRhOiBxdWVyeVN0cmluZywgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgYXBwbGljYXRpb24uIFRoZSBvcmlnaW5hbCBzaXplIGlzIDAgYW5kIGVhY2ggaW5jcmVtZW50IGFib3ZlIG9yIGJlbG93IHJlcHJlc2VudHMgem9vbWluZyAyMCVcblx0ICAgICAqIGxhcmdlciBvciBzbWFsbGVyIHRvIGRlZmF1bHQgbGltaXRzIG9mIDMwMCUgYW5kIDUwJSBvZiBvcmlnaW5hbCBzaXplLCByZXNwZWN0aXZlbHkuXG5cdCAgICAgKiBAcGFyYW0gbGV2ZWwgVGhlIHpvb20gbGV2ZWxcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBzZXRab29tTGV2ZWwobnVtYmVyKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLnNldFpvb21MZXZlbChudW1iZXIpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHNldFpvb21MZXZlbCg1KS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTZXR0aW5nIGEgIHpvb20gbGV2ZWwnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHNldFpvb21MZXZlbChsZXZlbCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignc2V0LWFwcGxpY2F0aW9uLXpvb20tbGV2ZWwnLCB7IGxldmVsLCAuLi50aGlzLmlkZW50aXR5IH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2V0cyBhIHVzZXJuYW1lIHRvIGNvcnJlbGF0ZSB3aXRoIEFwcCBMb2cgTWFuYWdlbWVudC5cblx0ICAgICAqIEBwYXJhbSB1c2VybmFtZSBVc2VybmFtZSB0byBjb3JyZWxhdGUgd2l0aCBBcHAncyBMb2cuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gc2V0QXBwTG9nVXNlcigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuc2V0QXBwTG9nVXNlcm5hbWUoJ3VzZXJuYW1lJyk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogc2V0QXBwTG9nVXNlcigpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1N1Y2Nlc3MnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICpcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBzZXRBcHBMb2dVc2VybmFtZSh1c2VybmFtZSkge1xuXHQgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzZXQtYXBwLWxvZy11c2VybmFtZScsIHsgZGF0YTogdXNlcm5hbWUsIC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc3lzdGVtIHRyYXkuIElmIHRoZSBzeXN0ZW0gdHJheSBpcyBub3Qgc2V0LCBpdCB3aWxsIHRocm93IGFuIGVycm9yIG1lc3NhZ2UuXG5cdCAgICAgKiBAcmVtYXJrcyBUaGUgb25seSBpbmZvcm1hdGlvbiBjdXJyZW50bHkgcmV0dXJuZWQgaXMgdGhlIHBvc2l0aW9uIGFuZCBkaW1lbnNpb25zLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFRyYXlJY29uSW5mbygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24ud3JhcCh7IHV1aWQ6ICd0ZXN0YXBwJyB9KTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFRyYXlJY29uSW5mbygpO1xuXHQgICAgICogfVxuXHQgICAgICogZ2V0VHJheUljb25JbmZvKCkudGhlbihpbmZvID0+IGNvbnNvbGUubG9nKGluZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0VHJheUljb25JbmZvKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXRyYXktaWNvbi1pbmZvJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIENoZWNrcyBpZiB0aGUgYXBwbGljYXRpb24gaGFzIGFuIGFzc29jaWF0ZWQgdHJheSBpY29uLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi53cmFwKHsgdXVpZDogJ3Rlc3RhcHAnIH0pO1xuXHQgICAgICogY29uc3QgaGFzVHJheUljb24gPSBhd2FpdCBhcHAuaGFzVHJheUljb24oKTtcblx0ICAgICAqIGNvbnNvbGUubG9nKGhhc1RyYXlJY29uKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBoYXNUcmF5SWNvbigpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2hhcy10cmF5LWljb24nLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQ2xvc2VzIHRoZSBhcHBsaWNhdGlvbiBieSB0ZXJtaW5hdGluZyBpdHMgcHJvY2Vzcy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiB0ZXJtaW5hdGVBcHAoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLnRlcm1pbmF0ZSgpO1xuXHQgICAgICogfVxuXHQgICAgICogdGVybWluYXRlQXBwKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQXBwbGljYXRpb24gdGVybWluYXRlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgdGVybWluYXRlKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigndGVybWluYXRlLWFwcGxpY2F0aW9uJywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBXYWl0cyBmb3IgYSBoYW5naW5nIGFwcGxpY2F0aW9uLiBUaGlzIG1ldGhvZCBjYW4gYmUgY2FsbGVkIGluIHJlc3BvbnNlIHRvIGFuIGFwcGxpY2F0aW9uXG5cdCAgICAgKiBcIm5vdC1yZXNwb25kaW5nXCIgdG8gYWxsb3cgdGhlIGFwcGxpY2F0aW9uIHRvIGNvbnRpbnVlIGFuZCB0byBnZW5lcmF0ZSBhbm90aGVyIFwibm90LXJlc3BvbmRpbmdcIlxuXHQgICAgICogbWVzc2FnZSBhZnRlciBhIGNlcnRhaW4gcGVyaW9kIG9mIHRpbWUuXG5cdCAgICAgKlxuXHQgICAgICogQGlnbm9yZVxuXHQgICAgICovXG5cdCAgICB3YWl0KCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignd2FpdC1mb3ItaHVuZy1hcHBsaWNhdGlvbicsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBhcHBsaWNhdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBJZiB0aGUgYXBwbGljYXRpb24gd2FzIG5vdCBsYXVuY2hlZCBmcm9tIGEgbWFuaWZlc3QsIHRoZSBjYWxsIHdpbGwgcmV0dXJuIHRoZSBjbG9zZXN0IHBhcmVudCBhcHBsaWNhdGlvbiBgbWFuaWZlc3RgXG5cdCAgICAgKiBhbmQgYG1hbmlmZXN0VXJsYC4gIGBpbml0aWFsT3B0aW9uc2Agc2hvd3MgdGhlIHBhcmFtZXRlcnMgdXNlZCB3aGVuIGxhdW5jaGVkIHByb2dyYW1tYXRpY2FsbHksIG9yIHRoZSBgc3RhcnR1cF9hcHBgIG9wdGlvbnNcblx0ICAgICAqIGlmIGxhdW5jaGVkIGZyb20gbWFuaWZlc3QuIFRoZSBgcGFyZW50VXVpZGAgd2lsbCBiZSB0aGUgdXVpZCBvZiB0aGUgaW1tZWRpYXRlIHBhcmVudCAoaWYgYXBwbGljYWJsZSkuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0SW5mbygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0SW5mbygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGdldEluZm8oKS50aGVuKGluZm8gPT4gY29uc29sZS5sb2coaW5mbykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRJbmZvKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWluZm8nLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIGFsbCBwcm9jZXNzIGluZm9ybWF0aW9uIGZvciBlbnRpdGllcyAod2luZG93cyBhbmQgdmlld3MpIGFzc29jaWF0ZWQgd2l0aCBhbiBhcHBsaWNhdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIGNvbnN0IHByb2Nlc3NJbmZvID0gYXdhaXQgYXBwLmdldFByb2Nlc3NJbmZvKCk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0UHJvY2Vzc0luZm8oKSB7XG5cdCAgICAgICAgY29uc3QgeyBwYXlsb2FkOiB7IGRhdGEgfSB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2FwcGxpY2F0aW9uLWdldC1wcm9jZXNzLWluZm8nLCB0aGlzLmlkZW50aXR5KTtcblx0ICAgICAgICByZXR1cm4gZGF0YTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2V0cyBmaWxlIGF1dG8gZG93bmxvYWQgbG9jYXRpb24uIEl0J3Mgb25seSBhbGxvd2VkIGluIHRoZSBzYW1lIGFwcGxpY2F0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIE5vdGU6IFRoaXMgbWV0aG9kIGlzIHJlc3RyaWN0ZWQgYnkgZGVmYXVsdCBhbmQgbXVzdCBiZSBlbmFibGVkIHZpYVxuXHQgICAgICogPGEgaHJlZj1cImh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvYXBpLXNlY3VyaXR5XCI+QVBJIHNlY3VyaXR5IHNldHRpbmdzPC9hPi5cblx0ICAgICAqIEBwYXJhbSBkb3dubG9hZExvY2F0aW9uIGZpbGUgYXV0byBkb3dubG9hZCBsb2NhdGlvblxuXHQgICAgICpcblx0ICAgICAqIEB0aHJvd3MgaWYgc2V0dGluZyBmaWxlIGF1dG8gZG93bmxvYWQgbG9jYXRpb24gb24gZGlmZmVyZW50IGFwcGxpY2F0aW9ucy5cblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IGRvd25sb2FkTG9jYXRpb24gPSAnQzpcXFxcZGV2XFxcXHRlbXAnO1xuXHQgICAgICogY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqIHRyeSB7XG5cdCAgICAgKiAgICAgYXdhaXQgYXBwLnNldEZpbGVEb3dubG9hZExvY2F0aW9uKGRvd25sb2FkTG9jYXRpb24pO1xuXHQgICAgICogICAgIGNvbnNvbGUubG9nKCdGaWxlIGRvd25sb2FkIGxvY2F0aW9uIGlzIHNldCcpO1xuXHQgICAgICogfSBjYXRjaChlcnIpIHtcblx0ICAgICAqICAgICBjb25zb2xlLmVycm9yKGVycilcblx0ICAgICAqIH1cblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBzZXRGaWxlRG93bmxvYWRMb2NhdGlvbihkb3dubG9hZExvY2F0aW9uKSB7XG5cdCAgICAgICAgY29uc3QgeyBuYW1lIH0gPSB0aGlzLndpcmUubWU7XG5cdCAgICAgICAgY29uc3QgZW50aXR5SWRlbnRpdHkgPSB7IHV1aWQ6IHRoaXMuaWRlbnRpdHkudXVpZCwgbmFtZSB9O1xuXHQgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzZXQtZmlsZS1kb3dubG9hZC1sb2NhdGlvbicsIHsgLi4uZW50aXR5SWRlbnRpdHksIGRvd25sb2FkTG9jYXRpb24gfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEdldHMgZmlsZSBhdXRvIGRvd25sb2FkIGxvY2F0aW9uLiBJdCdzIG9ubHkgYWxsb3dlZCBpbiB0aGUgc2FtZSBhcHBsaWNhdGlvbi4gSWYgZmlsZSBhdXRvIGRvd25sb2FkIGxvY2F0aW9uIGlzIG5vdCBzZXQsIGl0IHdpbGwgcmV0dXJuIHRoZSBkZWZhdWx0IGxvY2F0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIE5vdGU6IFRoaXMgbWV0aG9kIGlzIHJlc3RyaWN0ZWQgYnkgZGVmYXVsdCBhbmQgbXVzdCBiZSBlbmFibGVkIHZpYVxuXHQgICAgICogPGEgaHJlZj1cImh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvYXBpLXNlY3VyaXR5XCI+QVBJIHNlY3VyaXR5IHNldHRpbmdzPC9hPi5cblx0ICAgICAqXG5cdCAgICAgKiBAdGhyb3dzIGlmIGdldHRpbmcgZmlsZSBhdXRvIGRvd25sb2FkIGxvY2F0aW9uIG9uIGRpZmZlcmVudCBhcHBsaWNhdGlvbnMuXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogY29uc3QgZmlsZURvd25sb2FkRGlyID0gIGF3YWl0IGFwcC5nZXRGaWxlRG93bmxvYWRMb2NhdGlvbigpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldEZpbGVEb3dubG9hZExvY2F0aW9uKCkge1xuXHQgICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhIH0gfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtZmlsZS1kb3dubG9hZC1sb2NhdGlvbicsIHRoaXMuaWRlbnRpdHkpO1xuXHQgICAgICAgIHJldHVybiBkYXRhO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTaG93cyBhIG1lbnUgb24gdGhlIHRyYXkgaWNvbi4gVXNlIHdpdGggdHJheS1pY29uLWNsaWNrZWQgZXZlbnQuXG5cdCAgICAgKiBAcGFyYW0gb3B0aW9uc1xuXHQgICAgICogQHR5cGVQYXJhbSBEYXRhIFVzZXItZGVmaW5lZCBzaGFwZSBmb3IgZGF0YSByZXR1cm5lZCB1cG9uIG1lbnUgaXRlbSBjbGljay4gU2hvdWxkIGJlIGFcblx0ICAgICAqIFt1bmlvbl0oaHR0cHM6Ly93d3cudHlwZXNjcmlwdGxhbmcub3JnL2RvY3MvaGFuZGJvb2svMi9ldmVyeWRheS10eXBlcy5odG1sI3VuaW9uLXR5cGVzKVxuXHQgICAgICogb2YgYWxsIHBvc3NpYmxlIGRhdGEgc2hhcGVzIGZvciB0aGUgZW50aXJlIG1lbnUsIGFuZCB0aGUgY2xpY2sgaGFuZGxlciBzaG91bGQgcHJvY2Vzc1xuXHQgICAgICogdGhlc2Ugd2l0aCBhIFwicmVkdWNlclwiIHBhdHRlcm4uXG5cdCAgICAgKiBAdGhyb3dzIGlmIHRoZSBhcHBsaWNhdGlvbiBoYXMgbm8gdHJheSBpY29uIHNldFxuXHQgICAgICogQHRocm93cyBpZiB0aGUgc3lzdGVtIHRyYXkgaXMgY3VycmVudGx5IGhpZGRlblxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3QgaWNvblVybCA9ICdodHRwOi8vY2RuLm9wZW5maW4uY28vYXNzZXRzL3Rlc3RpbmcvaWNvbnMvY2lyY2xlZC1kaWdpdC1vbmUucG5nJztcblx0ICAgICAqIGNvbnN0IGFwcCA9IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50U3luYygpO1xuXHQgICAgICpcblx0ICAgICAqIGF3YWl0IGFwcC5zZXRUcmF5SWNvbihpY29uVXJsKTtcblx0ICAgICAqXG5cdCAgICAgKiBjb25zdCB0ZW1wbGF0ZSA9IFtcblx0ICAgICAqICB7XG5cdCAgICAgKiAgICBsYWJlbDogJ01lbnUgSXRlbSAxJyxcblx0ICAgICAqICAgIGRhdGE6ICdoZWxsbyBmcm9tIGl0ZW0gMSdcblx0ICAgICAqICB9LFxuXHQgICAgICogIHsgdHlwZTogJ3NlcGFyYXRvcicgfSxcblx0ICAgICAqICB7XG5cdCAgICAgKiAgICBsYWJlbDogJ01lbnUgSXRlbSAyJyxcblx0ICAgICAqICAgIHR5cGU6ICdjaGVja2JveCcsXG5cdCAgICAgKiAgICBjaGVja2VkOiB0cnVlLFxuXHQgICAgICogICAgZGF0YTogJ1RoZSB1c2VyIGNsaWNrZWQgdGhlIGNoZWNrYm94J1xuXHQgICAgICogIH0sXG5cdCAgICAgKiAge1xuXHQgICAgICogICAgbGFiZWw6ICdzZWUgbW9yZScsXG5cdCAgICAgKiAgICBlbmFibGVkOiBmYWxzZSxcblx0ICAgICAqICAgIHN1Ym1lbnU6IFtcblx0ICAgICAqICAgICAgeyBsYWJlbDogJ3N1Ym1lbnUgMScsIGRhdGE6ICdoZWxsbyBmcm9tIHN1Ym1lbnUnIH1cblx0ICAgICAqICAgIF1cblx0ICAgICAqICB9XG5cdCAgICAgKiBdO1xuXHQgICAgICpcblx0ICAgICAqIGFwcC5hZGRMaXN0ZW5lcigndHJheS1pY29uLWNsaWNrZWQnLCAoZXZlbnQpID0+IHtcblx0ICAgICAqICAgLy8gcmlnaHQtY2xpY2tcblx0ICAgICAqICAgaWYgKGV2ZW50LmJ1dHRvbiA9PT0gMikge1xuXHQgICAgICogICAgIGFwcC5zaG93VHJheUljb25Qb3B1cE1lbnUoeyB0ZW1wbGF0ZSB9KS50aGVuKHIgPT4ge1xuXHQgICAgICogICAgICAgaWYgKHIucmVzdWx0ID09PSAnY2xvc2VkJykge1xuXHQgICAgICogICAgICAgICBjb25zb2xlLmxvZygnbm90aGluZyBoYXBwZW5lZCcpO1xuXHQgICAgICogICAgICAgfSBlbHNlIHtcblx0ICAgICAqICAgICAgICAgY29uc29sZS5sb2coci5kYXRhKTtcblx0ICAgICAqICAgICAgIH1cblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgfVxuXHQgICAgICogfSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgc2hvd1RyYXlJY29uUG9wdXBNZW51KG9wdGlvbnMpIHtcblx0ICAgICAgICBjb25zdCB7IG5hbWUgfSA9IHRoaXMud2lyZS5tZTtcblx0ICAgICAgICBjb25zdCBlbnRpdHlJZGVudGl0eSA9IHsgdXVpZDogdGhpcy5pZGVudGl0eS51dWlkLCBuYW1lIH07XG5cdCAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc2hvdy10cmF5LWljb24tcG9wdXAtbWVudScsIHsgLi4uZW50aXR5SWRlbnRpdHksIG9wdGlvbnMgfSk7XG5cdCAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQ2xvc2VzIHRoZSB0cmF5IGljb24gbWVudS5cblx0ICAgICAqXG5cdCAgICAgKiBAdGhyb3dzIGlmIHRoZSBhcHBsaWNhdGlvbiBoYXMgbm8gdHJheSBpY29uIHNldFxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3QgYXBwID0gZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnRTeW5jKCk7XG5cdCAgICAgKlxuXHQgICAgICogYXdhaXQgYXBwLmNsb3NlVHJheUljb25Qb3B1cE1lbnUoKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBjbG9zZVRyYXlJY29uUG9wdXBNZW51KCkge1xuXHQgICAgICAgIGNvbnN0IHsgbmFtZSB9ID0gdGhpcy53aXJlLm1lO1xuXHQgICAgICAgIGNvbnN0IGVudGl0eUlkZW50aXR5ID0geyB1dWlkOiB0aGlzLmlkZW50aXR5LnV1aWQsIG5hbWUgfTtcblx0ICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignY2xvc2UtdHJheS1pY29uLXBvcHVwLW1lbnUnLCB7IC4uLmVudGl0eUlkZW50aXR5IH0pO1xuXHQgICAgfVxuXHR9XG5cdEluc3RhbmNlJDYuQXBwbGljYXRpb24gPSBBcHBsaWNhdGlvbjtcblx0cmV0dXJuIEluc3RhbmNlJDY7XG59XG5cbnZhciBoYXNSZXF1aXJlZEZhY3RvcnkkMjtcblxuZnVuY3Rpb24gcmVxdWlyZUZhY3RvcnkkMiAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEZhY3RvcnkkMikgcmV0dXJuIEZhY3RvcnkkNztcblx0aGFzUmVxdWlyZWRGYWN0b3J5JDIgPSAxO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoRmFjdG9yeSQ3LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0RmFjdG9yeSQ3LkFwcGxpY2F0aW9uTW9kdWxlID0gdm9pZCAwO1xuXHRjb25zdCBiYXNlXzEgPSBiYXNlO1xuXHRjb25zdCB2YWxpZGF0ZV8xID0gdmFsaWRhdGU7XG5cdGNvbnN0IEluc3RhbmNlXzEgPSByZXF1aXJlSW5zdGFuY2UkMSgpO1xuXHQvKipcblx0ICogU3RhdGljIG5hbWVzcGFjZSBmb3IgT3BlbkZpbiBBUEkgbWV0aG9kcyB0aGF0IGludGVyYWN0IHdpdGggdGhlIHtAbGluayBBcHBsaWNhdGlvbn0gY2xhc3MsIGF2YWlsYWJsZSB1bmRlciBgZmluLkFwcGxpY2F0aW9uYC5cblx0ICovXG5cdGNsYXNzIEFwcGxpY2F0aW9uTW9kdWxlIGV4dGVuZHMgYmFzZV8xLkJhc2Uge1xuXHQgICAgLyoqXG5cdCAgICAgKiBBc3luY2hyb25vdXNseSByZXR1cm5zIGFuIEFQSSBoYW5kbGUgZm9yIHRoZSBnaXZlbiBBcHBsaWNhdGlvbiBpZGVudGl0eS5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBXcmFwcGluZyBhbiBBcHBsaWNhdGlvbiBpZGVudGl0eSB0aGF0IGRvZXMgbm90IHlldCBleGlzdCB3aWxsICpub3QqIHRocm93IGFuIGVycm9yLCBhbmQgaW5zdGVhZFxuXHQgICAgICogcmV0dXJucyBhIHN0dWIgb2JqZWN0IHRoYXQgY2Fubm90IHlldCBwZXJmb3JtIHJlbmRlcmluZyB0YXNrcy4gVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBwbHVtYmluZyBldmVudGluZ1xuXHQgICAgICogZm9yIGFuIEFwcGxpY2F0aW9uIHRocm91Z2hvdXQgaXRzIGVudGlyZSBsaWZlY3ljbGUuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLkFwcGxpY2F0aW9uLndyYXAoeyB1dWlkOiAndGVzdGFwcCcgfSlcblx0ICAgICAqIC50aGVuKGFwcCA9PiBhcHAuaXNSdW5uaW5nKCkpXG5cdCAgICAgKiAudGhlbihydW5uaW5nID0+IGNvbnNvbGUubG9nKCdBcHBsaWNhdGlvbiBpcyBydW5uaW5nOiAnICsgcnVubmluZykpXG5cdCAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICovXG5cdCAgICBhc3luYyB3cmFwKGlkZW50aXR5KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3dyYXAtYXBwbGljYXRpb24nKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBlcnJvck1zZyA9ICgwLCB2YWxpZGF0ZV8xLnZhbGlkYXRlSWRlbnRpdHkpKGlkZW50aXR5KTtcblx0ICAgICAgICBpZiAoZXJyb3JNc2cpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTXNnKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIG5ldyBJbnN0YW5jZV8xLkFwcGxpY2F0aW9uKHRoaXMud2lyZSwgaWRlbnRpdHkpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTeW5jaHJvbm91c2x5IHJldHVybnMgYW4gQVBJIGhhbmRsZSBmb3IgdGhlIGdpdmVuIEFwcGxpY2F0aW9uIGlkZW50aXR5LlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFdyYXBwaW5nIGFuIEFwcGxpY2F0aW9uIGlkZW50aXR5IHRoYXQgZG9lcyBub3QgeWV0IGV4aXN0IHdpbGwgKm5vdCogdGhyb3cgYW4gZXJyb3IsIGFuZCBpbnN0ZWFkXG5cdCAgICAgKiByZXR1cm5zIGEgc3R1YiBvYmplY3QgdGhhdCBjYW5ub3QgeWV0IHBlcmZvcm0gcmVuZGVyaW5nIHRhc2tzLiBUaGlzIGNhbiBiZSB1c2VmdWwgZm9yIHBsdW1iaW5nIGV2ZW50aW5nXG5cdCAgICAgKiBmb3IgYW4gQXBsaWNhdGlvbiB0aHJvdWdob3V0IGl0cyBlbnRpcmUgbGlmZWN5Y2xlLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IGFwcCA9IGZpbi5BcHBsaWNhdGlvbi53cmFwU3luYyh7IHV1aWQ6ICd0ZXN0YXBwJyB9KTtcblx0ICAgICAqIGF3YWl0IGFwcC5jbG9zZSgpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICovXG5cdCAgICB3cmFwU3luYyhpZGVudGl0eSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd3cmFwLWFwcGxpY2F0aW9uLXN5bmMnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBlcnJvck1zZyA9ICgwLCB2YWxpZGF0ZV8xLnZhbGlkYXRlSWRlbnRpdHkpKGlkZW50aXR5KTtcblx0ICAgICAgICBpZiAoZXJyb3JNc2cpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTXNnKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIG5ldyBJbnN0YW5jZV8xLkFwcGxpY2F0aW9uKHRoaXMud2lyZSwgaWRlbnRpdHkpO1xuXHQgICAgfVxuXHQgICAgYXN5bmMgX2NyZWF0ZShhcHBPcHRpb25zKSB7XG5cdCAgICAgICAgLy8gc2V0IGRlZmF1bHRzOlxuXHQgICAgICAgIGlmIChhcHBPcHRpb25zLndhaXRGb3JQYWdlTG9hZCA9PT0gdW5kZWZpbmVkKSB7XG5cdCAgICAgICAgICAgIGFwcE9wdGlvbnMud2FpdEZvclBhZ2VMb2FkID0gZmFsc2U7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmIChhcHBPcHRpb25zLmF1dG9TaG93ID09PSB1bmRlZmluZWQgJiYgYXBwT3B0aW9ucy5pc1BsYXRmb3JtQ29udHJvbGxlciA9PT0gdW5kZWZpbmVkKSB7XG5cdCAgICAgICAgICAgIGFwcE9wdGlvbnMuYXV0b1Nob3cgPSB0cnVlO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignY3JlYXRlLWFwcGxpY2F0aW9uJywgYXBwT3B0aW9ucyk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud3JhcCh7IHV1aWQ6IGFwcE9wdGlvbnMudXVpZCB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogREVQUkVDQVRFRCBtZXRob2QgdG8gY3JlYXRlIGEgbmV3IEFwcGxpY2F0aW9uLiBVc2Uge0BsaW5rIEFwcGxpY2F0aW9uLkFwcGxpY2F0aW9uTW9kdWxlLnN0YXJ0IEFwcGxpY2F0aW9uLnN0YXJ0fSBpbnN0ZWFkLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUFwcCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uY3JlYXRlKHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0zJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLUFwcGxpY2F0aW9uLmNyZWF0ZS5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBhd2FpdCBhcHAucnVuKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogY3JlYXRlQXBwKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQXBwbGljYXRpb24gaXMgY3JlYXRlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqXG5cdCAgICAgKiBAaWdub3JlXG5cdCAgICAgKi9cblx0ICAgIGNyZWF0ZShhcHBPcHRpb25zKSB7XG5cdCAgICAgICAgY29uc29sZS53YXJuKCdEZXByZWNhdGlvbiBXYXJuaW5nOiBmaW4uQXBwbGljYXRpb24uY3JlYXRlIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgZmluLkFwcGxpY2F0aW9uLnN0YXJ0Jyk7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2FwcGxpY2F0aW9uLWNyZWF0ZScpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiB0aGlzLl9jcmVhdGUoYXBwT3B0aW9ucyk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIENyZWF0ZXMgYW5kIHN0YXJ0cyBhIG5ldyBBcHBsaWNhdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBzdGFydCgpIHtcblx0ICAgICAqICAgICByZXR1cm4gZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLUFwcGxpY2F0aW9uLnN0YXJ0Lmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogfVxuXHQgICAgICogc3RhcnQoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdBcHBsaWNhdGlvbiBpcyBydW5uaW5nJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgc3RhcnQoYXBwT3B0aW9ucykge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzdGFydC1hcHBsaWNhdGlvbicpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGFwcCA9IGF3YWl0IHRoaXMuX2NyZWF0ZShhcHBPcHRpb25zKTtcblx0ICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbigncnVuLWFwcGxpY2F0aW9uJywgeyB1dWlkOiBhcHBPcHRpb25zLnV1aWQgfSk7XG5cdCAgICAgICAgcmV0dXJuIGFwcDtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQXN5bmNocm9ub3VzbHkgc3RhcnRzIGEgYmF0Y2ggb2YgYXBwbGljYXRpb25zIGdpdmVuIGFuIGFycmF5IG9mIGFwcGxpY2F0aW9uIGlkZW50aWZpZXJzIGFuZCBtYW5pZmVzdFVybHMuXG5cdCAgICAgKiBSZXR1cm5zIG9uY2UgdGhlIFJWTSBpcyBmaW5pc2hlZCBhdHRlbXB0aW5nIHRvIGxhdW5jaCB0aGUgYXBwbGljYXRpb25zLlxuXHQgICAgICogQHBhcmFtIG9wdHMgLSBQYXJhbWV0ZXJzIHRoYXQgdGhlIFJWTSB3aWxsIHVzZS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKlxuXHQgICAgICogY29uc3QgYXBwbGljYXRpb25JbmZvQXJyYXkgPSBbXG5cdCAgICAgKiAgICAge1xuXHQgICAgICogICAgICAgICBcInV1aWRcIjogJ0FwcC0xJyxcblx0ICAgICAqICAgICAgICAgXCJtYW5pZmVzdFVybFwiOiAnaHR0cDovL2xvY2FsaG9zdDo1NTU1L2FwcDEuanNvbicsXG5cdCAgICAgKiAgICAgfSxcblx0ICAgICAqICAgICB7XG5cdCAgICAgKiAgICAgICAgIFwidXVpZFwiOiAnQXBwLTInLFxuXHQgICAgICogICAgICAgICBcIm1hbmlmZXN0VXJsXCI6ICdodHRwOi8vbG9jYWxob3N0OjU1NTUvYXBwMi5qc29uJyxcblx0ICAgICAqICAgICB9LFxuXHQgICAgICogICAgIHtcblx0ICAgICAqICAgICAgICAgXCJ1dWlkXCI6ICdBcHAtMycsXG5cdCAgICAgKiAgICAgICAgIFwibWFuaWZlc3RVcmxcIjogJ2h0dHA6Ly9sb2NhbGhvc3Q6NTU1NS9hcHAzLmpzb24nLFxuXHQgICAgICogICAgIH1cblx0ICAgICAqIF1cblx0ICAgICAqXG5cdCAgICAgKiBmaW4uQXBwbGljYXRpb24uc3RhcnRNYW55TWFuaWZlc3RzKGFwcGxpY2F0aW9uSW5mb0FycmF5KVxuXHQgICAgICogICAgIC50aGVuKCgpID0+IHtcblx0ICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ1JWTSBoYXMgZmluaXNoZWQgbGF1bmNoaW5nIHRoZSBhcHBsaWNhdGlvbiBsaXN0LicpO1xuXHQgICAgICogICAgIH0pXG5cdCAgICAgKiAgICAgLmNhdGNoKChlcnIpID0+IHtcblx0ICAgICAqICAgICAgICAgY29uc29sZS5sb2coZXJyKTtcblx0ICAgICAqICAgICB9KVxuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICovXG5cdCAgICBhc3luYyBzdGFydE1hbnlNYW5pZmVzdHMoYXBwbGljYXRpb25zLCBvcHRzKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdydW4tYXBwbGljYXRpb25zJywgeyBhcHBsaWNhdGlvbnMsIG9wdHMgfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBBc3luY2hyb25vdXNseSByZXR1cm5zIGFuIEFwcGxpY2F0aW9uIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIGN1cnJlbnQgYXBwbGljYXRpb25cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBpc0N1cnJlbnRBcHBSdW5uaW5nICgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhcHAuaXNSdW5uaW5nKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogaXNDdXJyZW50QXBwUnVubmluZygpLnRoZW4ocnVubmluZyA9PiB7XG5cdCAgICAgKiAgICAgY29uc29sZS5sb2coYEN1cnJlbnQgYXBwIGlzIHJ1bm5pbmc6ICR7cnVubmluZ31gKTtcblx0ICAgICAqIH0pLmNhdGNoKGVyciA9PiB7XG5cdCAgICAgKiAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuXHQgICAgICogfSk7XG5cdCAgICAgKlxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldEN1cnJlbnQoKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1jdXJyZW50LWFwcGxpY2F0aW9uJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud3JhcCh7IHV1aWQ6IHRoaXMud2lyZS5tZS51dWlkIH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTeW5jaHJvbm91c2x5IHJldHVybnMgYW4gQXBwbGljYXRpb24gb2JqZWN0IHRoYXQgcmVwcmVzZW50cyB0aGUgY3VycmVudCBhcHBsaWNhdGlvblxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGlzQ3VycmVudEFwcFJ1bm5pbmcgKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50U3luYygpO1xuXHQgICAgICogICAgIHJldHVybiBhcHAuaXNSdW5uaW5nKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogaXNDdXJyZW50QXBwUnVubmluZygpLnRoZW4ocnVubmluZyA9PiB7XG5cdCAgICAgKiAgICAgY29uc29sZS5sb2coYEN1cnJlbnQgYXBwIGlzIHJ1bm5pbmc6ICR7cnVubmluZ31gKTtcblx0ICAgICAqIH0pLmNhdGNoKGVyciA9PiB7XG5cdCAgICAgKiAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuXHQgICAgICogfSk7XG5cdCAgICAgKlxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldEN1cnJlbnRTeW5jKCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtY3VycmVudC1hcHBsaWNhdGlvbi1zeW5jJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud3JhcFN5bmMoeyB1dWlkOiB0aGlzLndpcmUubWUudXVpZCB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIGFwcGxpY2F0aW9uJ3MgbWFuaWZlc3QgYW5kIHJldHVybnMgYSBydW5uaW5nIGluc3RhbmNlIG9mIHRoZSBhcHBsaWNhdGlvbi5cblx0ICAgICAqIEBwYXJhbSBtYW5pZmVzdFVybCAtIFRoZSBVUkwgb2YgYXBwJ3MgbWFuaWZlc3QuXG5cdCAgICAgKiBAcGFyYW0gb3B0cyAtIFBhcmFtZXRlcnMgdGhhdCB0aGUgUlZNIHdpbGwgdXNlLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5BcHBsaWNhdGlvbi5zdGFydEZyb21NYW5pZmVzdCgnaHR0cDovL2xvY2FsaG9zdDo1NTU1L2FwcC5qc29uJykudGhlbihhcHAgPT4gY29uc29sZS5sb2coJ0FwcCBpcyBydW5uaW5nJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqXG5cdCAgICAgKiAvLyBGb3IgYSBsb2NhbCBtYW5pZmVzdCBmaWxlOlxuXHQgICAgICogZmluLkFwcGxpY2F0aW9uLnN0YXJ0RnJvbU1hbmlmZXN0KCdmaWxlOi8vL0M6L3NvbWVmb2xkZXIvYXBwLmpzb24nKS50aGVuKGFwcCA9PiBjb25zb2xlLmxvZygnQXBwIGlzIHJ1bm5pbmcnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHN0YXJ0RnJvbU1hbmlmZXN0KG1hbmlmZXN0VXJsLCBvcHRzKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2FwcGxpY2F0aW9uLXN0YXJ0LWZyb20tbWFuaWZlc3QnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBhcHAgPSBhd2FpdCB0aGlzLl9jcmVhdGVGcm9tTWFuaWZlc3QobWFuaWZlc3RVcmwpO1xuXHQgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgdXNpbmcgcHJpdmF0ZSBtZXRob2Qgd2l0aG91dCB3YXJuaW5nLlxuXHQgICAgICAgIGF3YWl0IGFwcC5fcnVuKG9wdHMpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVyc2NvcmUtZGFuZ2xlXG5cdCAgICAgICAgcmV0dXJuIGFwcDtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayBBcHBsaWNhdGlvbi5BcHBsaWNhdGlvbk1vZHVsZS5zdGFydEZyb21NYW5pZmVzdCBBcHBsaWNhdGlvbi5zdGFydEZyb21NYW5pZmVzdH0gaW5zdGVhZC5cblx0ICAgICAqIFJldHJpZXZlcyBhcHBsaWNhdGlvbidzIG1hbmlmZXN0IGFuZCByZXR1cm5zIGEgd3JhcHBlZCBhcHBsaWNhdGlvbi5cblx0ICAgICAqIEBwYXJhbSBtYW5pZmVzdFVybCAtIFRoZSBVUkwgb2YgYXBwJ3MgbWFuaWZlc3QuXG5cdCAgICAgKiBAcGFyYW0gY2FsbGJhY2sgLSBjYWxsZWQgaWYgdGhlIG1ldGhvZCBzdWNjZWVkcy5cblx0ICAgICAqIEBwYXJhbSBlcnJvckNhbGxiYWNrIC0gY2FsbGVkIGlmIHRoZSBtZXRob2QgZmFpbHMuIFRoZSByZWFzb24gZm9yIGZhaWx1cmUgaXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5BcHBsaWNhdGlvbi5jcmVhdGVGcm9tTWFuaWZlc3QoJ2h0dHA6Ly9sb2NhbGhvc3Q6NTU1NS9hcHAuanNvbicpLnRoZW4oYXBwID0+IGNvbnNvbGUubG9nKGFwcCkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICogQGlnbm9yZVxuXHQgICAgICovXG5cdCAgICBjcmVhdGVGcm9tTWFuaWZlc3QobWFuaWZlc3RVcmwpIHtcblx0ICAgICAgICBjb25zb2xlLndhcm4oJ0RlcHJlY2F0aW9uIFdhcm5pbmc6IGZpbi5BcHBsaWNhdGlvbi5jcmVhdGVGcm9tTWFuaWZlc3QgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBmaW4uQXBwbGljYXRpb24uc3RhcnRGcm9tTWFuaWZlc3QnKTtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignYXBwbGljYXRpb24tY3JlYXRlLWZyb20tbWFuaWZlc3QnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gdGhpcy5fY3JlYXRlRnJvbU1hbmlmZXN0KG1hbmlmZXN0VXJsKTtcblx0ICAgIH1cblx0ICAgIF9jcmVhdGVGcm9tTWFuaWZlc3QobWFuaWZlc3RVcmwpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlXG5cdCAgICAgICAgICAgIC5zZW5kQWN0aW9uKCdnZXQtYXBwbGljYXRpb24tbWFuaWZlc3QnLCB7IG1hbmlmZXN0VXJsIH0pXG5cdCAgICAgICAgICAgIC50aGVuKCh7IHBheWxvYWQgfSkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCB1dWlkID0gcGF5bG9hZC5kYXRhLnBsYXRmb3JtID8gcGF5bG9hZC5kYXRhLnBsYXRmb3JtLnV1aWQgOiBwYXlsb2FkLmRhdGEuc3RhcnR1cF9hcHAudXVpZDtcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXMud3JhcCh7IHV1aWQgfSk7XG5cdCAgICAgICAgfSlcblx0ICAgICAgICAgICAgLnRoZW4oKGFwcCkgPT4ge1xuXHQgICAgICAgICAgICBhcHAuX21hbmlmZXN0VXJsID0gbWFuaWZlc3RVcmw7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZXJzY29yZS1kYW5nbGVcblx0ICAgICAgICAgICAgcmV0dXJuIGFwcDtcblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0fVxuXHRGYWN0b3J5JDcuQXBwbGljYXRpb25Nb2R1bGUgPSBBcHBsaWNhdGlvbk1vZHVsZTtcblx0cmV0dXJuIEZhY3RvcnkkNztcbn1cblxudmFyIGhhc1JlcXVpcmVkQXBwbGljYXRpb247XG5cbmZ1bmN0aW9uIHJlcXVpcmVBcHBsaWNhdGlvbiAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEFwcGxpY2F0aW9uKSByZXR1cm4gYXBwbGljYXRpb247XG5cdGhhc1JlcXVpcmVkQXBwbGljYXRpb24gPSAxO1xuXHQoZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0XHR2YXIgX19jcmVhdGVCaW5kaW5nID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY3JlYXRlQmluZGluZykgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0XHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0XHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHRcdCAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xuXHRcdCAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XG5cdFx0ICAgIH1cblx0XHQgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcblx0XHR9KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHRcdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHRcdCAgICBvW2syXSA9IG1ba107XG5cdFx0fSkpO1xuXHRcdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdFx0ICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZXhwb3J0cywgcCkpIF9fY3JlYXRlQmluZGluZyhleHBvcnRzLCBtLCBwKTtcblx0XHR9O1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0XHQvKipcblx0XHQgKiBFbnRyeSBwb2ludHMgZm9yIHRoZSBPcGVuRmluIGBBcHBsaWNhdGlvbmAgQVBJIChgZmluLkFwcGxpY2F0aW9uYCkuXG5cdFx0ICpcblx0XHQgKiAqIHtAbGluayBBcHBsaWNhdGlvbk1vZHVsZX0gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBBcHBsaWNhdGlvbmAgQVBJLCBhY2Nlc3NpYmxlIHRocm91Z2ggYGZpbi5BcHBsaWNhdGlvbmAuXG5cdFx0ICogKiB7QGxpbmsgQXBwbGljYXRpb259IGRlc2NyaWJlcyBhbiBpbnN0YW5jZSBvZiBhbiBPcGVuRmluIEFwcGxpY2F0aW9uLCBlLmcuIGFzIHJldHVybmVkIGJ5IGBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudGAuXG5cdFx0ICpcblx0XHQgKiBUaGVzZSBhcmUgc2VwYXJhdGUgY29kZSBlbnRpdGllcywgYW5kIGFyZSBkb2N1bWVudGVkIHNlcGFyYXRlbHkuICBJbiB0aGUgW3ByZXZpb3VzIHZlcnNpb24gb2YgdGhlIEFQSSBkb2N1bWVudGF0aW9uXShodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC8zMi4xMTQuNzYuMTAvaW5kZXguaHRtbCksXG5cdFx0ICogYm90aCBvZiB0aGVzZSB3ZXJlIGRvY3VtZW50ZWQgb24gdGhlIHNhbWUgcGFnZS5cblx0XHQgKlxuXHRcdCAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuXHRcdCAqL1xuXHRcdF9fZXhwb3J0U3RhcihyZXF1aXJlRmFjdG9yeSQyKCksIGV4cG9ydHMpO1xuXHRcdF9fZXhwb3J0U3RhcihyZXF1aXJlSW5zdGFuY2UkMSgpLCBleHBvcnRzKTsgXG5cdH0gKGFwcGxpY2F0aW9uKSk7XG5cdHJldHVybiBhcHBsaWNhdGlvbjtcbn1cblxudmFyIHByb21pc2lmeVN1YnNjcmlwdGlvbiQxID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm9taXNpZnlTdWJzY3JpcHRpb24kMSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5wcm9taXNpZnlTdWJzY3JpcHRpb24kMS5wcm9taXNpZnlTdWJzY3JpcHRpb24gPSB2b2lkIDA7XG5jb25zdCBwcm9taXNpZnlTdWJzY3JpcHRpb24gPSBhc3luYyAoZW1pdHRlciwgZXZlbnROYW1lLCBwcmVkaWNhdGUgPSAoKSA9PiB0cnVlLCB0aW1lb3V0KSA9PiB7XG4gICAgbGV0IHJlc29sdmU7XG4gICAgbGV0IHJlamVjdDtcbiAgICBsZXQgdGltZXI7XG4gICAgY29uc3QgdmFsdWVQcm9taXNlID0gbmV3IFByb21pc2UoKHksIG4pID0+IHtcbiAgICAgICAgcmVzb2x2ZSA9IHk7XG4gICAgICAgIHJlamVjdCA9IG47XG4gICAgfSk7XG4gICAgY29uc3QgbGlzdGVuZXIgPSAoZSkgPT4ge1xuICAgICAgICBpZiAocHJlZGljYXRlKGUpKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICAgICAgcmVzb2x2ZShlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgYXdhaXQgZW1pdHRlci5vbihldmVudE5hbWUsIGxpc3RlbmVyKTtcbiAgICBpZiAodGltZW91dCkge1xuICAgICAgICB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4gcmVqZWN0KG5ldyBFcnJvcignZXZlbnQgdGltZWQgb3V0JykpLCB0aW1lb3V0KTtcbiAgICB9XG4gICAgdmFsdWVQcm9taXNlLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICBlbWl0dGVyLnJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSwgbGlzdGVuZXIpLmNhdGNoKCgpID0+IG51bGwpO1xuICAgIH0pO1xuICAgIHJldHVybiB7XG4gICAgICAgIGdldFZhbHVlOiAoKSA9PiB2YWx1ZVByb21pc2VcbiAgICB9O1xufTtcbnByb21pc2lmeVN1YnNjcmlwdGlvbiQxLnByb21pc2lmeVN1YnNjcmlwdGlvbiA9IHByb21pc2lmeVN1YnNjcmlwdGlvbjtcblxudmFyIGhhc1JlcXVpcmVkSW5zdGFuY2U7XG5cbmZ1bmN0aW9uIHJlcXVpcmVJbnN0YW5jZSAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEluc3RhbmNlKSByZXR1cm4gSW5zdGFuY2UkNztcblx0aGFzUmVxdWlyZWRJbnN0YW5jZSA9IDE7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShJbnN0YW5jZSQ3LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0SW5zdGFuY2UkNy5fV2luZG93ID0gdm9pZCAwO1xuXHQvKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvcHJlZmVyLWRlZmF1bHQtZXhwb3J0ICovXG5cdC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyAqL1xuXHQvKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5cdC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb24gKi9cblx0Y29uc3QgYXBwbGljYXRpb25fMSA9IHJlcXVpcmVBcHBsaWNhdGlvbigpO1xuXHRjb25zdCBtYWluXzEgPSBtYWluO1xuXHRjb25zdCB2aWV3XzEgPSByZXF1aXJlVmlldygpO1xuXHRjb25zdCB3YXJuaW5nc18xID0gd2FybmluZ3M7XG5cdGNvbnN0IHByb21pc2lmeVN1YnNjcmlwdGlvbl8xID0gcHJvbWlzaWZ5U3Vic2NyaXB0aW9uJDE7XG5cdC8qKlxuXHQgKiBBIGJhc2ljIHdpbmRvdyB0aGF0IHdyYXBzIGEgbmF0aXZlIEhUTUwgd2luZG93LiBQcm92aWRlcyBtb3JlIGZpbmUtZ3JhaW5lZFxuXHQgKiBjb250cm9sIG92ZXIgdGhlIHdpbmRvdyBzdGF0ZSBzdWNoIGFzIHRoZSBhYmlsaXR5IHRvIG1pbmltaXplLCBtYXhpbWl6ZSwgcmVzdG9yZSwgZXRjLlxuXHQgKiBCeSBkZWZhdWx0IGEgd2luZG93IGRvZXMgbm90IHNob3cgdXBvbiBpbnN0YW50aWF0aW9uOyBpbnN0ZWFkIHRoZSB3aW5kb3cncyBzaG93KCkgbWV0aG9kXG5cdCAqIG11c3QgYmUgaW52b2tlZCBtYW51YWxseS4gVGhlIG5ldyB3aW5kb3cgYXBwZWFycyBpbiB0aGUgc2FtZSBwcm9jZXNzIGFzIHRoZSBwYXJlbnQgd2luZG93LlxuXHQgKiBJdCBoYXMgdGhlIGFiaWxpdHkgdG8gbGlzdGVuIGZvciB7QGxpbmsgT3BlbkZpbi5XaW5kb3dFdmVudHMgd2luZG93IHNwZWNpZmljIGV2ZW50c30uXG5cdCAqL1xuXHQvLyBUaGUgd2luZG93LldpbmRvdyBuYW1lIGlzIHRha2VuXG5cdGNsYXNzIF9XaW5kb3cgZXh0ZW5kcyBtYWluXzEuV2ViQ29udGVudHMge1xuXHQgICAgLyoqXG5cdCAgICAgKiBAaW50ZXJuYWxcblx0ICAgICAqL1xuXHQgICAgY29uc3RydWN0b3Iod2lyZSwgaWRlbnRpdHkpIHtcblx0ICAgICAgICBzdXBlcih3aXJlLCBpZGVudGl0eSwgJ3dpbmRvdycpO1xuXHQgICAgfVxuXHQgICAgYXN5bmMgY3JlYXRlV2luZG93KG9wdGlvbnMpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignd2luZG93LWNyZWF0ZS13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBDT05TVFJVQ1RPUl9DQl9UT1BJQyA9ICdmaXJlLWNvbnN0cnVjdG9yLWNhbGxiYWNrJztcblx0ICAgICAgICBjb25zdCByZXNwb25zZVN1YnNjcmlwdGlvbiA9IGF3YWl0ICgwLCBwcm9taXNpZnlTdWJzY3JpcHRpb25fMS5wcm9taXNpZnlTdWJzY3JpcHRpb24pKHRoaXMsIENPTlNUUlVDVE9SX0NCX1RPUElDKTtcblx0ICAgICAgICAvLyBzZXQgZGVmYXVsdHM6XG5cdCAgICAgICAgaWYgKG9wdGlvbnMud2FpdEZvclBhZ2VMb2FkID09PSB1bmRlZmluZWQpIHtcblx0ICAgICAgICAgICAgb3B0aW9ucy53YWl0Rm9yUGFnZUxvYWQgPSBmYWxzZTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgaWYgKG9wdGlvbnMuYXV0b1Nob3cgPT09IHVuZGVmaW5lZCkge1xuXHQgICAgICAgICAgICBvcHRpb25zLmF1dG9TaG93ID0gdHJ1ZTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgKDAsIHdhcm5pbmdzXzEuaGFuZGxlRGVwcmVjYXRlZFdhcm5pbmdzKShvcHRpb25zKTtcblx0ICAgICAgICBjb25zdCB3aW5kb3dDcmVhdGlvbiA9IHRoaXMud2lyZS5lbnZpcm9ubWVudC5jcmVhdGVDaGlsZENvbnRlbnQoeyBlbnRpdHlUeXBlOiAnd2luZG93Jywgb3B0aW9ucyB9KTtcblx0ICAgICAgICBjb25zdCBbcmVzcG9uc2VdID0gYXdhaXQgUHJvbWlzZS5hbGwoW3Jlc3BvbnNlU3Vic2NyaXB0aW9uLmdldFZhbHVlKCksIHdpbmRvd0NyZWF0aW9uXSk7XG5cdCAgICAgICAgbGV0IGNiUGF5bG9hZDtcblx0ICAgICAgICBjb25zdCB7IHN1Y2Nlc3MgfSA9IHJlc3BvbnNlO1xuXHQgICAgICAgIGNvbnN0IHJlc3BvbnNlRGF0YSA9IHJlc3BvbnNlLmRhdGE7XG5cdCAgICAgICAgY29uc3QgeyBtZXNzYWdlIH0gPSByZXNwb25zZURhdGE7XG5cdCAgICAgICAgaWYgKHN1Y2Nlc3MpIHtcblx0ICAgICAgICAgICAgY2JQYXlsb2FkID0ge1xuXHQgICAgICAgICAgICAgICAgaHR0cFJlc3BvbnNlQ29kZTogcmVzcG9uc2VEYXRhLmh0dHBSZXNwb25zZUNvZGUsXG5cdCAgICAgICAgICAgICAgICBhcGlJbmplY3RlZDogcmVzcG9uc2VEYXRhLmFwaUluamVjdGVkXG5cdCAgICAgICAgICAgIH07XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICBjYlBheWxvYWQgPSB7XG5cdCAgICAgICAgICAgICAgICBtZXNzYWdlOiByZXNwb25zZURhdGEubWVzc2FnZSxcblx0ICAgICAgICAgICAgICAgIG5ldHdvcmtFcnJvckNvZGU6IHJlc3BvbnNlRGF0YS5uZXR3b3JrRXJyb3JDb2RlLFxuXHQgICAgICAgICAgICAgICAgc3RhY2s6IHJlc3BvbnNlRGF0YS5zdGFja1xuXHQgICAgICAgICAgICB9O1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjb25zdCBwYWdlUmVzb2x2ZSA9IHtcblx0ICAgICAgICAgICAgbWVzc2FnZSxcblx0ICAgICAgICAgICAgY2JQYXlsb2FkLFxuXHQgICAgICAgICAgICBzdWNjZXNzXG5cdCAgICAgICAgfTtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICAvLyB0aGlzIGlzIHRvIGVuZm9yY2UgYSA1LjAgY29udHJhY3QgdGhhdCB0aGUgY2hpbGQncyBtYWluIGZ1bmN0aW9uXG5cdCAgICAgICAgICAgIC8vIHdpbGwgbm90IGZpcmUgYmVmb3JlIHRoZSBwYXJlbnQncyBzdWNjZXNzIGNhbGxiYWNrIG9uIGNyZWF0aW9uLlxuXHQgICAgICAgICAgICAvLyBpZiB0aGUgY2hpbGQgd2luZG93IGlzIG5vdCBhY2Nlc3NpYmxlIChDT1JTKSB0aGlzIGNvbnRyYWN0IGRvZXNcblx0ICAgICAgICAgICAgLy8gbm90IGhvbGQuXG5cdCAgICAgICAgICAgIGNvbnN0IHdlYldpbmRvdyA9IHRoaXMuZ2V0V2ViV2luZG93KCk7XG5cdCAgICAgICAgICAgIHdlYldpbmRvdy5maW4uX19pbnRlcm5hbF8ub3BlbmVyU3VjY2Vzc0NCQ2FsbGVkKCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlKSB7XG5cdCAgICAgICAgICAgIC8vIGNvbW1vbiBmb3IgbWFpbiB3aW5kb3dzLCB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvci4gaGVyZSBqdXN0IHRvIGhhdmUgYSBkZWJ1ZyB0YXJnZXQuXG5cdCAgICAgICAgICAgIC8vIGNvbnNvbGUuZXJyb3IoZSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmIChwYWdlUmVzb2x2ZS5zdWNjZXNzKSB7XG5cdCAgICAgICAgICAgIHJldHVybiB0aGlzO1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QocGFnZVJlc29sdmUpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXRyaWV2ZXMgYW4gYXJyYXkgb2YgZnJhbWUgaW5mbyBvYmplY3RzIHJlcHJlc2VudGluZyB0aGUgbWFpbiBmcmFtZSBhbmQgYW55XG5cdCAgICAgKiBpZnJhbWVzIHRoYXQgYXJlIGN1cnJlbnRseSBvbiB0aGUgcGFnZS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldEFsbEZyYW1lcygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmdldEFsbEZyYW1lcy5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5nZXRBbGxGcmFtZXMoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRBbGxGcmFtZXMoKS50aGVuKGZyYW1lc0luZm8gPT4gY29uc29sZS5sb2coZnJhbWVzSW5mbykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRBbGxGcmFtZXMoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtYWxsLWZyYW1lcycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBHZXRzIHRoZSBjdXJyZW50IGJvdW5kcyAodG9wLCBib3R0b20sIHJpZ2h0LCBsZWZ0LCB3aWR0aCwgaGVpZ2h0KSBvZiB0aGUgd2luZG93LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0Qm91bmRzKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMycsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZ2V0Qm91bmRzLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmdldEJvdW5kcygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGdldEJvdW5kcygpLnRoZW4oYm91bmRzID0+IGNvbnNvbGUubG9nKGJvdW5kcykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRCb3VuZHMoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZVxuXHQgICAgICAgICAgICAuc2VuZEFjdGlvbignZ2V0LXdpbmRvdy1ib3VuZHMnLCB0aGlzLmlkZW50aXR5KVxuXHQgICAgICAgICAgICAudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIENlbnRlcnMgdGhlIHdpbmRvdyBvbiBpdHMgY3VycmVudCBzY3JlZW4uXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgRG9lcyBub3QgaGF2ZSBhbiBlZmZlY3Qgb24gbWluaW1pemVkIG9yIG1heGltaXplZCB3aW5kb3dzLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY2VudGVyV2luZG93KCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuY2VudGVyLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmNlbnRlcigpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGNlbnRlcldpbmRvdygpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1dpbmRvdyBjZW50ZXJlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqXG5cdCAgICAgKi9cblx0ICAgIGNlbnRlcigpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NlbnRlci13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlbW92ZXMgZm9jdXMgZnJvbSB0aGUgd2luZG93LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gYmx1cldpbmRvdygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmJsdXIuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uYmx1cigpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGJsdXJXaW5kb3coKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdCbHVyZWQgV2luZG93JykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBibHVyKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignYmx1ci13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEJyaW5ncyB0aGUgd2luZG93IHRvIHRoZSBmcm9udCBvZiB0aGUgd2luZG93IHN0YWNrLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gQnJpbmdXaW5kb3dUb0Zyb250KCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuYnJpbmdUb0Zyb250Lmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmJyaW5nVG9Gcm9udCgpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIEJyaW5nV2luZG93VG9Gcm9udCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1dpbmRvdyBpcyBpbiB0aGUgZnJvbnQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGJyaW5nVG9Gcm9udCgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2JyaW5nLXdpbmRvdy10by1mcm9udCcsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUGVyZm9ybXMgdGhlIHNwZWNpZmllZCB3aW5kb3cgdHJhbnNpdGlvbnMuXG5cdCAgICAgKiBAcGFyYW0gdHJhbnNpdGlvbnMgLSBEZXNjcmliZXMgdGhlIGFuaW1hdGlvbnMgdG8gcGVyZm9ybS4gU2VlIHRoZSB0dXRvcmlhbC5cblx0ICAgICAqIEBwYXJhbSBvcHRpb25zIC0gT3B0aW9ucyBmb3IgdGhlIGFuaW1hdGlvbi4gU2VlIHRoZSB0dXRvcmlhbC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBgXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBhbmltYXRlV2luZG93KCkge1xuXHQgICAgICogICAgIGNvbnN0IHRyYW5zaXRpb25zID0ge1xuXHQgICAgICogICAgICAgICBvcGFjaXR5OiB7XG5cdCAgICAgKiAgICAgICAgICAgICBvcGFjaXR5OiAwLjcsXG5cdCAgICAgKiAgICAgICAgICAgICBkdXJhdGlvbjogNTAwXG5cdCAgICAgKiAgICAgICAgIH0sXG5cdCAgICAgKiAgICAgICAgIHBvc2l0aW9uOiB7XG5cdCAgICAgKiAgICAgICAgICAgICB0b3A6IDEwMCxcblx0ICAgICAqICAgICAgICAgICAgIGxlZnQ6IDEwMCxcblx0ICAgICAqICAgICAgICAgICAgIGR1cmF0aW9uOiA1MDAsXG5cdCAgICAgKiAgICAgICAgICAgICByZWxhdGl2ZTogdHJ1ZVxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgfTtcblx0ICAgICAqICAgICBjb25zdCBvcHRpb25zID0ge1xuXHQgICAgICogICAgICAgICBpbnRlcnJ1cHQ6IHRydWUsXG5cdCAgICAgKiAgICAgICAgIHR3ZWVuOiAnZWFzZS1pbidcblx0ICAgICAqICAgICB9O1xuXHQgICAgICpcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gd2luLmFuaW1hdGUodHJhbnNpdGlvbnMsIG9wdGlvbnMpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGFuaW1hdGVXaW5kb3coKVxuXHQgICAgICogICAgIC50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdBbmltYXRpb24gZG9uZScpKVxuXHQgICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5lcnJvcihlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhbmltYXRlKHRyYW5zaXRpb25zLCBvcHRpb25zKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZVxuXHQgICAgICAgICAgICAuc2VuZEFjdGlvbignYW5pbWF0ZS13aW5kb3cnLCB7XG5cdCAgICAgICAgICAgIHRyYW5zaXRpb25zLFxuXHQgICAgICAgICAgICBvcHRpb25zLFxuXHQgICAgICAgICAgICAuLi50aGlzLmlkZW50aXR5XG5cdCAgICAgICAgfSlcblx0ICAgICAgICAgICAgLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogSGlkZXMgdGhlIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGhpZGVXaW5kb3coKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5oaWRlLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmhpZGUoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBoaWRlV2luZG93KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnV2luZG93IGlzIGhpZGRlbicpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgaGlkZSgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2hpZGUtd2luZG93JywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBjbG9zZXMgdGhlIHdpbmRvdyBhcHBsaWNhdGlvblxuXHQgICAgICogQHBhcmFtIGZvcmNlIENsb3NlIHdpbGwgYmUgcHJldmVudGVkIGZyb20gY2xvc2luZyB3aGVuIGZvcmNlIGlzIGZhbHNlIGFuZFxuXHQgICAgICogIOKAmGNsb3NlLXJlcXVlc3RlZOKAmSBoYXMgYmVlbiBzdWJzY3JpYmVkIHRvIGZvciBhcHBsaWNhdGlvbuKAmXMgbWFpbiB3aW5kb3cuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBjbG9zZVdpbmRvdygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTMnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmNsb3NlLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmNsb3NlKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogY2xvc2VXaW5kb3coKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdXaW5kb3cgY2xvc2VkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBjbG9zZShmb3JjZSA9IGZhbHNlKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjbG9zZS13aW5kb3cnLCB7IGZvcmNlLCAuLi50aGlzLmlkZW50aXR5IH0pLnRoZW4oKCkgPT4ge1xuXHQgICAgICAgICAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgbnVsbCk7XG5cdCAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdCAgICBmb2N1c2VkV2ViVmlld1dhc0NoYW5nZWQoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmb2N1c2VkLXdlYnZpZXctY2hhbmdlZCcsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0dXJucyB0aGUgbmF0aXZlIE9TIGxldmVsIElkLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIEluIFdpbmRvd3MsIGl0IHdpbGwgcmV0dXJuIHRoZSBXaW5kb3dzIFtoYW5kbGVdKGh0dHBzOi8vZG9jcy5taWNyb3NvZnQuY29tL2VuLXVzL3dpbmRvd3MvZGVza3RvcC9XaW5Qcm9nL3dpbmRvd3MtZGF0YS10eXBlcyNIV05EKS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFdpbmRvd05hdGl2ZUlkKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMycsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZ2V0TmF0aXZlSWQuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uZ2V0TmF0aXZlSWQoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRXaW5kb3dOYXRpdmVJZCgpLnRoZW4obmF0aXZlSWQgPT4gY29uc29sZS5sb2cobmF0aXZlSWQpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0TmF0aXZlSWQoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtd2luZG93LW5hdGl2ZS1pZCcsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXRyaWV2ZXMgd2luZG93J3MgYXR0YWNoZWQgdmlld3MuXG5cdCAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCB3aW4gPSBmaW4uV2luZG93LmdldEN1cnJlbnRTeW5jKCk7XG5cdCAgICAgKlxuXHQgICAgICogd2luLmdldEN1cnJlbnRWaWV3cygpXG5cdCAgICAgKiAgIC50aGVuKHZpZXdzID0+IGNvbnNvbGUubG9nKHZpZXdzKSlcblx0ICAgICAqICAgLmNhdGNoKGNvbnNvbGUuZXJyb3IpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldEN1cnJlbnRWaWV3cygpIHtcblx0ICAgICAgICBjb25zdCB7IHBheWxvYWQgfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCd3aW5kb3ctZ2V0LXZpZXdzJywgdGhpcy5pZGVudGl0eSk7XG5cdCAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YS5tYXAoKGlkKSA9PiBuZXcgdmlld18xLlZpZXcodGhpcy53aXJlLCBpZCkpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rIFdpbmRvdy5fV2luZG93LmRpc2FibGVVc2VyTW92ZW1lbnR9IGluc3RlYWQuXG5cdCAgICAgKi9cblx0ICAgIGRpc2FibGVGcmFtZSgpIHtcblx0ICAgICAgICBjb25zb2xlLndhcm4oJ0Z1bmN0aW9uIGlzIGRlcHJlY2F0ZWQ7IHVzZSBkaXNhYmxlVXNlck1vdmVtZW50IGluc3RlYWQuJyk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdkaXNhYmxlLXdpbmRvdy1mcmFtZScsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUHJldmVudHMgYSB1c2VyIGZyb20gY2hhbmdpbmcgYSB3aW5kb3cncyBzaXplL3Bvc2l0aW9uIHdoZW4gdXNpbmcgdGhlIHdpbmRvdydzIGZyYW1lLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZGlzYWJsZVVzZXJNb3ZlbWVudCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTMnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmRpc2FibGVGcmFtZS5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5kaXNhYmxlVXNlck1vdmVtZW50KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZGlzYWJsZVVzZXJNb3ZlbWVudCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1dpbmRvdyBpcyBkaXNhYmxlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZGlzYWJsZVVzZXJNb3ZlbWVudCgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2Rpc2FibGUtd2luZG93LWZyYW1lJywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rIFdpbmRvdy5fV2luZG93LmVuYWJsZVVzZXJNb3ZlbWVudH0gaW5zdGVhZC5cblx0ICAgICAqL1xuXHQgICAgZW5hYmxlRnJhbWUoKSB7XG5cdCAgICAgICAgY29uc29sZS53YXJuKCdGdW5jdGlvbiBpcyBkZXByZWNhdGVkOyB1c2UgZW5hYmxlVXNlck1vdmVtZW50IGluc3RlYWQuJyk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdlbmFibGUtd2luZG93LWZyYW1lJywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZS1lbmFibGVzIHVzZXIgY2hhbmdlcyB0byBhIHdpbmRvdydzIHNpemUvcG9zaXRpb24gd2hlbiB1c2luZyB0aGUgd2luZG93J3MgZnJhbWUuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBlbmFibGVVc2VyTW92ZW1lbnQoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0zJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5lbmFibGVGcmFtZS5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5lbmFibGVVc2VyTW92ZW1lbnQoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBlbmFibGVVc2VyTW92ZW1lbnQoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdXaW5kb3cgaXMgZW5hYmxlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZW5hYmxlVXNlck1vdmVtZW50KCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZW5hYmxlLXdpbmRvdy1mcmFtZScsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogRmxhc2hlcyB0aGUgd2luZG934oCZcyBmcmFtZSBhbmQgdGFza2JhciBpY29uIHVudGlsIHN0b3BGbGFzaGluZyBpcyBjYWxsZWQgb3IgdW50aWwgYSBmb2N1cyBldmVudCBpcyBmaXJlZC5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBPbiBtYWNPUyBmbGFzaCBvbmx5IHdvcmtzIG9uIGluYWN0aXZlIHdpbmRvd3MuXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHdpbmRvd0ZsYXNoKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZmxhc2guaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uZmxhc2goKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiB3aW5kb3dGbGFzaCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1dpbmRvdyBmbGFzaGluZycpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZmxhc2goKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmbGFzaC13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFN0b3BzIHRoZSB0YXNrYmFyIGljb24gZnJvbSBmbGFzaGluZy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHN0b3BXaW5kb3dGbGFzaGluZygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LnN0b3BGbGFzaGluZy5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5zdG9wRmxhc2hpbmcoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBzdG9wV2luZG93Rmxhc2hpbmcoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdBcHBsaWNhdGlvbiB3aW5kb3cgZmxhc2hpbmcnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHN0b3BGbGFzaGluZygpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3N0b3AtZmxhc2gtd2luZG93JywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBHZXRzIGFuIGluZm9ybWF0aW9uIG9iamVjdCBmb3IgdGhlIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldEluZm8oKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5nZXRJbmZvLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmdldEluZm8oKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRJbmZvKCkudGhlbihpbmZvID0+IGNvbnNvbGUubG9nKGluZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0SW5mbygpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC13aW5kb3ctaW5mbycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXRyaWV2ZXMgdGhlIHdpbmRvdydzIExheW91dFxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogICAgIC8vZ2V0IHRoZSBjdXJyZW50IHdpbmRvd1xuXHQgICAgICogICAgIGNvbnN0IHdpbmRvdyA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuXHQgICAgICpcblx0ICAgICAqICAgICAvL2dldCB0aGUgbGF5b3V0IGZvciB0aGUgd2luZG93XG5cdCAgICAgKiAgICAgY29uc3QgbGF5b3V0ID0gYXdhaXQgd2luZG93LmdldExheW91dCgpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldExheW91dChsYXlvdXRJZGVudGl0eSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd3aW5kb3ctZ2V0LWxheW91dCcsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IG9wdHMgPSBhd2FpdCB0aGlzLmdldE9wdGlvbnMoKTtcblx0ICAgICAgICBpZiAoIW9wdHMubGF5b3V0ICYmICFvcHRzLmxheW91dFNuYXBzaG90KSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignV2luZG93IGRvZXMgbm90IGhhdmUgYSBMYXlvdXQnKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuZmluLlBsYXRmb3JtLkxheW91dC53cmFwKGxheW91dElkZW50aXR5ID8/IHRoaXMuaWRlbnRpdHkpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBHZXRzIHRoZSBjdXJyZW50IHNldHRpbmdzIG9mIHRoZSB3aW5kb3cuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRXaW5kb3dPcHRpb25zKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZ2V0T3B0aW9ucy5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5nZXRPcHRpb25zKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0V2luZG93T3B0aW9ucygpLnRoZW4ob3B0cyA9PiBjb25zb2xlLmxvZyhvcHRzKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldE9wdGlvbnMoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtd2luZG93LW9wdGlvbnMnLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0cyB0aGUgcGFyZW50IGFwcGxpY2F0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0UGFyZW50QXBwbGljYXRpb24oKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5nZXRQYXJlbnRBcHBsaWNhdGlvbi5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5nZXRQYXJlbnRBcHBsaWNhdGlvbigpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGdldFBhcmVudEFwcGxpY2F0aW9uKCkudGhlbihwYXJlbnRBcHBsaWNhdGlvbiA9PiBjb25zb2xlLmxvZyhwYXJlbnRBcHBsaWNhdGlvbikpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRQYXJlbnRBcHBsaWNhdGlvbigpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignd2luZG93LWdldC1wYXJlbnQtYXBwbGljYXRpb24nLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBhcHBsaWNhdGlvbl8xLkFwcGxpY2F0aW9uKHRoaXMud2lyZSwgdGhpcy5pZGVudGl0eSkpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBHZXRzIHRoZSBwYXJlbnQgd2luZG93LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0UGFyZW50V2luZG93KCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZ2V0UGFyZW50V2luZG93Lmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmdldFBhcmVudFdpbmRvdygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGdldFBhcmVudFdpbmRvdygpLnRoZW4ocGFyZW50V2luZG93ID0+IGNvbnNvbGUubG9nKHBhcmVudFdpbmRvdykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRQYXJlbnRXaW5kb3coKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3dpbmRvdy1nZXQtcGFyZW50LXdpbmRvdycsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IGFwcGxpY2F0aW9uXzEuQXBwbGljYXRpb24odGhpcy53aXJlLCB0aGlzLmlkZW50aXR5KSkudGhlbigoYXBwKSA9PiBhcHAuZ2V0V2luZG93KCkpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiAqKipERVBSRUNBVEVEIC0gcGxlYXNlIHVzZSBXaW5kb3cuY2FwdHVyZVBhZ2UuKioqXG5cdCAgICAgKiBHZXRzIGEgYmFzZTY0IGVuY29kZWQgUE5HIGltYWdlIG9mIHRoZSB3aW5kb3cgb3IganVzdCBwYXJ0IGEgb2YgaXQuXG5cdCAgICAgKiBAcGFyYW0gYXJlYSBUaGUgYXJlYSBvZiB0aGUgd2luZG93IHRvIGJlIGNhcHR1cmVkLlxuXHQgICAgICogT21pdHRpbmcgaXQgd2lsbCBjYXB0dXJlIHRoZSB3aG9sZSB2aXNpYmxlIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgV2luZG93LmNhcHR1cmVQYWdlXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldFNuYXBzaG90KGFyZWEpIHtcblx0ICAgICAgICBjb25zdCByZXEgPSB7IGFyZWEsIC4uLnRoaXMuaWRlbnRpdHkgfTtcblx0ICAgICAgICBjb25zb2xlLndhcm4oJ1dpbmRvdy5nZXRTbmFwc2hvdCBoYXMgYmVlbiBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIFdpbmRvdy5jYXB0dXJlUGFnZScpO1xuXHQgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtd2luZG93LXNuYXBzaG90JywgcmVxKTtcblx0ICAgICAgICByZXR1cm4gcmVzLnBheWxvYWQuZGF0YTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0cyB0aGUgY3VycmVudCBzdGF0ZSAoXCJtaW5pbWl6ZWRcIiwgXCJtYXhpbWl6ZWRcIiwgb3IgXCJub3JtYWxcIikgb2YgdGhlIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFdpbmRvd1N0YXRlKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZ2V0U3RhdGUuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uZ2V0U3RhdGUoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRXaW5kb3dTdGF0ZSgpLnRoZW4od2luU3RhdGUgPT4gY29uc29sZS5sb2cod2luU3RhdGUpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0U3RhdGUoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtd2luZG93LXN0YXRlJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFByZXZpb3VzbHkgY2FsbGVkIGdldE5hdGl2ZVdpbmRvdy5cblx0ICAgICAqIFJldHVybnMgdGhlIFtXaW5kb3cgT2JqZWN0XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93KVxuXHQgICAgICogdGhhdCByZXByZXNlbnRzIHRoZSB3ZWIgY29udGV4dCBvZiB0aGUgdGFyZ2V0IHdpbmRvdy4gVGhpcyBpcyB0aGUgc2FtZSBvYmplY3QgdGhhdFxuXHQgICAgICogeW91IHdvdWxkIGdldCBmcm9tIGNhbGxpbmcgW3dpbmRvdy5vcGVuKCldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3cvb3BlbikgaW4gYSBzdGFuZGFyZCB3ZWIgY29udGV4dC5cblx0ICAgICAqIFRoZSB0YXJnZXQgd2luZG93IG5lZWRzIHRvIGJlIGluIHRoZSBzYW1lIGFwcGxpY2F0aW9uIGFzIHRoZSByZXF1ZXN0aW5nIHdpbmRvd1xuXHQgICAgICogYXMgd2VsbCBhcyBjb21wbHkgd2l0aCBbc2FtZS1vcmlnaW5dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL1NlY3VyaXR5L1NhbWUtb3JpZ2luX3BvbGljeSkgcG9saWN5IHJlcXVpcmVtZW50cy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogSW5qZWN0aW5nIGNvbnRlbnQgaW50byBhbiBlbXB0eSB3aW5kb3c6XG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIChhc3luYyAoKT0+IHtcblx0ICAgICAqICAgICB0cnkge1xuXHQgICAgICogICAgICAgICBjb25zdCB3aW5OYW1lID0gYGNoaWxkLXdpbmRvdy0ke0RhdGUubm93KCl9YDtcblx0ICAgICAqICAgICAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy5jcmVhdGUoe1xuXHQgICAgICogICAgICAgICAgICAgbmFtZTogd2luTmFtZSxcblx0ICAgICAqICAgICAgICAgICAgIHVybDogJ2Fib3V0OmJsYW5rJ1xuXHQgICAgICogICAgICAgICB9KTtcblx0ICAgICAqICAgICAgICAgd2luLmdldFdlYldpbmRvdygpLmRvY3VtZW50LndyaXRlKCc8aDE+SGVsbG8gV29ybGQ8L2gxPicpO1xuXHQgICAgICogICAgIH0gY2F0Y2ggKGVycikge1xuXHQgICAgICogICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG5cdCAgICAgKiAgICAgfVxuXHQgICAgICogfSkoKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqIENsb25pbmcgRE9NIGVsZW1lbnRzIGZyb20gdGhlIHBhcmVudCB3aW5kb3cgKGluIHRoaXMgZXhhbXBsZSB3ZSBjbG9uZSBhbiBgaDNgIGVsZW1lbnQgZnJvbSB0aGUgcGFyZW50IHdpbmRvdyk6XG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogKGFzeW5jICgpPT4ge1xuXHQgICAgICogICAgIHRyeSB7XG5cdCAgICAgKiAgICAgICAgIGNvbnN0IGN1cnJlbnRXaW5kb3cgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICAgICAgY29uc3QgcGFyZW50V2luZG93ID0gYXdhaXQgY3VycmVudFdpbmRvdy5nZXRQYXJlbnRXaW5kb3coKTtcblx0ICAgICAqICAgICAgICAgY29uc3QgY2xvbmVkSDMgPSBwYXJlbnRXaW5kb3cuZ2V0V2ViV2luZG93KCkuZG9jdW1lbnQucXVlcnlTZWxlY3RvcignaDMnKS5jbG9uZU5vZGUodHJ1ZSk7XG5cdCAgICAgKiAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kKGNsb25lZEgzKTtcblx0ICAgICAqXG5cdCAgICAgKiAgICAgfSBjYXRjaCAoZXJyKSB7XG5cdCAgICAgKiAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiB9KSgpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICogUmVuZGVyaW5nIG9uIGEgY2hpbGQgd2luZG93IHZpYSBhIGxpYnJhcnkgKGluIHRoaXMgZXhhbXBsZSB3ZSBhcmUgdXNpbmcgdGhlIFtsaXQtaHRtbF0oaHR0cHM6Ly9saXQtaHRtbC5wb2x5bWVyLXByb2plY3Qub3JnLylcblx0ICAgICAqIHRlbXBsYXRlIGxpYnJhcnkgdG8gcmVuZGVyIGNvbnRlbnQgb24gYSBibGFuayBjaGlsZCB3aW5kb3cuIFlvdSBhcmUgbm90IGdvaW5nIHRvIGJlIGFibGUgdG8gY29weSBwYXN0ZSB0aGlzIGV4YW1wbGUgd2l0aG91dFxuXHQgICAgICogY29uZmlndXJpbmcgdGhlIHByb2plY3QgY29ycmVjdGx5IGJ1dCB0aGlzIHdvdWxkIGRlbW9uc3RyYXRlIHNvbWUgdGVtcGxhdGluZyBvcHRpb25zIGF2YWlsYWJsZSk6XG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogKGFzeW5jICgpPT4ge1xuXHQgICAgICogICAgIHRyeSB7XG5cdCAgICAgKiAgICAgICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuY3JlYXRlKHtcblx0ICAgICAqICAgICAgICAgICAgIG5hbWU6IGBjaGlsZC13aW5kb3ctJHtEYXRlLm5vdygpfWAsXG5cdCAgICAgKiAgICAgICAgICAgICB1cmw6ICdhYm91dDpibGFuaydcblx0ICAgICAqICAgICAgICAgfSk7XG5cdCAgICAgKiAgICAgICAgIGNvbnN0IHRlbXBsYXRlID0gaHRtbGBcblx0ICAgICAqICAgICAgICAgICAgIDxkaXY+XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgPHNwYW4+Q2xpY2sgaGVyZTogPC9zcGFuPlxuXHQgICAgICogICAgICAgICAgICAgICAgIDxidXR0b24gQGNsaWNrPSR7KCk9PiBjb25zb2xlLmxvZygnSGVsbG8gV29ybGQhJyl9PmxvZyB0byB0aGUgY29uc29sZTwvYnV0dG9uPlxuXHQgICAgICogICAgICAgICAgICAgPC9kaXY+YDtcblx0ICAgICAqICAgICAgICAgcmVuZGVyKHRlbXBsYXRlLCB3aW4uZ2V0V2ViV2luZG93KCkuZG9jdW1lbnQuYm9keSk7XG5cdCAgICAgKlxuXHQgICAgICogICAgIH0gY2F0Y2ggKGVycikge1xuXHQgICAgICogICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG5cdCAgICAgKiAgICAgfVxuXHQgICAgICogfSkoKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRXZWJXaW5kb3coKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3dpbmRvdy1nZXQtd2ViLXdpbmRvdycsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuZW52aXJvbm1lbnQuZ2V0V2ViV2luZG93KHRoaXMuaWRlbnRpdHkpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBEZXRlcm1pbmVzIGlmIHRoZSB3aW5kb3cgaXMgYSBtYWluIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IHduZCA9IGZpbi5XaW5kb3cuZ2V0Q3VycmVudFN5bmMoKTtcblx0ICAgICAqIGNvbnN0IGlzTWFpblduZCA9IHduZC5pc01haW5XaW5kb3coKTtcblx0ICAgICAqIGNvbnNvbGUubG9nKCdJcyB0aGlzIGEgbWFpbiB3aW5kb3c/ICcgKyBpc01haW5XbmQpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGlzTWFpbldpbmRvdygpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignd2luZG93LWlzLW1haW4td2luZG93JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMubWUudXVpZCA9PT0gdGhpcy5tZS5uYW1lO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBEZXRlcm1pbmVzIGlmIHRoZSB3aW5kb3cgaXMgY3VycmVudGx5IHNob3dpbmcuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBpc1dpbmRvd1Nob3dpbmcoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5pc1Nob3dpbmcuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uaXNTaG93aW5nKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogaXNXaW5kb3dTaG93aW5nKCkudGhlbihib29sID0+IGNvbnNvbGUubG9nKGJvb2wpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgaXNTaG93aW5nKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignaXMtd2luZG93LXNob3dpbmcnLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogTWF4aW1pemVzIHRoZSB3aW5kb3dcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIG1heFdpbmRvdygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93Lm1heGltaXplLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLm1heGltaXplKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogbWF4V2luZG93KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnTWF4aW1pemVkIHdpbmRvdycpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgbWF4aW1pemUoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdtYXhpbWl6ZS13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIE1pbmltaXplcyB0aGUgd2luZG93LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gbWluV2luZG93KCkge1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4ubWluaW1pemUoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBtaW5XaW5kb3coKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdNaW5pbWl6ZWQgd2luZG93JykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBtaW5pbWl6ZSgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ21pbmltaXplLXdpbmRvdycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogTW92ZXMgdGhlIHdpbmRvdyBieSBhIHNwZWNpZmllZCBhbW91bnQuXG5cdCAgICAgKiBAcGFyYW0gZGVsdGFMZWZ0IFRoZSBjaGFuZ2UgaW4gdGhlIGxlZnQgcG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuXHQgICAgICogQHBhcmFtIGRlbHRhVG9wIFRoZSBjaGFuZ2UgaW4gdGhlIHRvcCBwb3NpdGlvbiBvZiB0aGUgd2luZG93XG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVXaW4oKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5tb3ZlQnkuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBtb3ZlQnkobGVmdCwgdG9wKSB7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgY3JlYXRlV2luKCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5tb3ZlQnkobGVmdCwgdG9wKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBtb3ZlQnkoNTgwLCAzMDApLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ01vdmVkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBtb3ZlQnkoZGVsdGFMZWZ0LCBkZWx0YVRvcCwgcG9zaXRpb25pbmdPcHRpb25zKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZVxuXHQgICAgICAgICAgICAuc2VuZEFjdGlvbignbW92ZS13aW5kb3ctYnknLCB7XG5cdCAgICAgICAgICAgIGRlbHRhTGVmdCxcblx0ICAgICAgICAgICAgZGVsdGFUb3AsXG5cdCAgICAgICAgICAgIHBvc2l0aW9uaW5nT3B0aW9ucyxcblx0ICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuXHQgICAgICAgIH0pXG5cdCAgICAgICAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIE1vdmVzIHRoZSB3aW5kb3cgdG8gYSBzcGVjaWZpZWQgbG9jYXRpb24uXG5cdCAgICAgKiBAcGFyYW0gbGVmdCBUaGUgbGVmdCBwb3NpdGlvbiBvZiB0aGUgd2luZG93XG5cdCAgICAgKiBAcGFyYW0gdG9wIFRoZSB0b3AgcG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cubW92ZVRvLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gbW92ZVRvKGxlZnQsIHRvcCkge1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGNyZWF0ZVdpbigpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4ubW92ZVRvKGxlZnQsIHRvcClcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBtb3ZlVG8oNTgwLCAzMDApLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ01vdmVkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKVxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIG1vdmVUbyhsZWZ0LCB0b3AsIHBvc2l0aW9uaW5nT3B0aW9ucykge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmVcblx0ICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ21vdmUtd2luZG93Jywge1xuXHQgICAgICAgICAgICBsZWZ0LFxuXHQgICAgICAgICAgICB0b3AsXG5cdCAgICAgICAgICAgIHBvc2l0aW9uaW5nT3B0aW9ucyxcblx0ICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuXHQgICAgICAgIH0pXG5cdCAgICAgICAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlc2l6ZXMgdGhlIHdpbmRvdyBieSBhIHNwZWNpZmllZCBhbW91bnQuXG5cdCAgICAgKiBAcGFyYW0gZGVsdGFXaWR0aCBUaGUgY2hhbmdlIGluIHRoZSB3aWR0aCBvZiB0aGUgd2luZG93XG5cdCAgICAgKiBAcGFyYW0gZGVsdGFIZWlnaHQgVGhlIGNoYW5nZSBpbiB0aGUgaGVpZ2h0IG9mIHRoZSB3aW5kb3dcblx0ICAgICAqIEBwYXJhbSBhbmNob3IgU3BlY2lmaWVzIGEgY29ybmVyIHRvIHJlbWFpbiBmaXhlZCBkdXJpbmcgdGhlIHJlc2l6ZS5cblx0ICAgICAqIENhbiB0YWtlIHRoZSB2YWx1ZXM6IFwidG9wLWxlZnRcIiwgXCJ0b3AtcmlnaHRcIiwgXCJib3R0b20tbGVmdFwiLCBvciBcImJvdHRvbS1yaWdodFwiLlxuXHQgICAgICogSWYgdW5kZWZpbmVkLCB0aGUgZGVmYXVsdCBpcyBcInRvcC1sZWZ0XCJcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LnJlc2l6ZUJ5Lmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gcmVzaXplQnkobGVmdCwgdG9wLCBhbmNob3IpIHtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBjcmVhdGVXaW4oKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLnJlc2l6ZUJ5KGxlZnQsIHRvcCwgYW5jaG9yKVxuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHJlc2l6ZUJ5KDU4MCwgMzAwLCAndG9wLXJpZ2h0JykudGhlbigoKSA9PiBjb25zb2xlLmxvZygnUmVzaXplZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgcmVzaXplQnkoZGVsdGFXaWR0aCwgZGVsdGFIZWlnaHQsIGFuY2hvciwgcG9zaXRpb25pbmdPcHRpb25zKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZVxuXHQgICAgICAgICAgICAuc2VuZEFjdGlvbigncmVzaXplLXdpbmRvdy1ieScsIHtcblx0ICAgICAgICAgICAgZGVsdGFXaWR0aDogTWF0aC5mbG9vcihkZWx0YVdpZHRoKSxcblx0ICAgICAgICAgICAgZGVsdGFIZWlnaHQ6IE1hdGguZmxvb3IoZGVsdGFIZWlnaHQpLFxuXHQgICAgICAgICAgICBhbmNob3IsXG5cdCAgICAgICAgICAgIHBvc2l0aW9uaW5nT3B0aW9ucyxcblx0ICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuXHQgICAgICAgIH0pXG5cdCAgICAgICAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlc2l6ZXMgdGhlIHdpbmRvdyB0byB0aGUgc3BlY2lmaWVkIGRpbWVuc2lvbnMuXG5cdCAgICAgKiBAcGFyYW0gd2lkdGggVGhlIGNoYW5nZSBpbiB0aGUgd2lkdGggb2YgdGhlIHdpbmRvd1xuXHQgICAgICogQHBhcmFtIGhlaWdodCBUaGUgY2hhbmdlIGluIHRoZSBoZWlnaHQgb2YgdGhlIHdpbmRvd1xuXHQgICAgICogQHBhcmFtIGFuY2hvciBTcGVjaWZpZXMgYSBjb3JuZXIgdG8gcmVtYWluIGZpeGVkIGR1cmluZyB0aGUgcmVzaXplLlxuXHQgICAgICogQ2FuIHRha2UgdGhlIHZhbHVlczogXCJ0b3AtbGVmdFwiLCBcInRvcC1yaWdodFwiLCBcImJvdHRvbS1sZWZ0XCIsIG9yIFwiYm90dG9tLXJpZ2h0XCIuXG5cdCAgICAgKiBJZiB1bmRlZmluZWQsIHRoZSBkZWZhdWx0IGlzIFwidG9wLWxlZnRcIlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cucmVzaXplVG8uaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiByZXNpemVUbyhsZWZ0LCB0b3AsIGFuY2hvcikge1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGNyZWF0ZVdpbigpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4ucmVzaXplVG8obGVmdCwgdG9wLCBhbmNob3IpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHJlc2l6ZVRvKDU4MCwgMzAwLCAndG9wLWxlZnQnKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdSZXNpemVkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICByZXNpemVUbyh3aWR0aCwgaGVpZ2h0LCBhbmNob3IsIHBvc2l0aW9uaW5nT3B0aW9ucykge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmVcblx0ICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ3Jlc2l6ZS13aW5kb3cnLCB7XG5cdCAgICAgICAgICAgIHdpZHRoOiBNYXRoLmZsb29yKHdpZHRoKSxcblx0ICAgICAgICAgICAgaGVpZ2h0OiBNYXRoLmZsb29yKGhlaWdodCksXG5cdCAgICAgICAgICAgIGFuY2hvcixcblx0ICAgICAgICAgICAgcG9zaXRpb25pbmdPcHRpb25zLFxuXHQgICAgICAgICAgICAuLi50aGlzLmlkZW50aXR5XG5cdCAgICAgICAgfSlcblx0ICAgICAgICAgICAgLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVzdG9yZXMgdGhlIHdpbmRvdyB0byBpdHMgbm9ybWFsIHN0YXRlIChpLmUuLCB1bm1pbmltaXplZCwgdW5tYXhpbWl6ZWQpLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cucmVzdG9yZS5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHJlc3RvcmUoKSB7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgY3JlYXRlV2luKCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5yZXN0b3JlKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogcmVzdG9yZSgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1Jlc3RvcmVkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICByZXN0b3JlKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigncmVzdG9yZS13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFdpbGwgYnJpbmcgdGhlIHdpbmRvdyB0byB0aGUgZnJvbnQgb2YgdGhlIGVudGlyZSBzdGFjayBhbmQgZ2l2ZSBpdCBmb2N1cy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LnNldEFzRm9yZWdyb3VuZC5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNldEFzRm9yZWdyb3VuZCgpIHtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBjcmVhdGVXaW4oKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLnNldEFzRm9yZWdyb3VuZCgpXG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogc2V0QXNGb3JlZ3JvdW5kKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnSW4gdGhlIGZvcmVncm91bmQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHNldEFzRm9yZWdyb3VuZCgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NldC1mb3JlZ3JvdW5kLXdpbmRvdycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2V0cyB0aGUgd2luZG93J3Mgc2l6ZSBhbmQgcG9zaXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVXaW4oKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5zZXRCb3VuZHMuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBzZXRCb3VuZHMoYm91bmRzKSB7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgY3JlYXRlV2luKCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5zZXRCb3VuZHMoYm91bmRzKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBzZXRCb3VuZHMoe1xuXHQgICAgICogICAgIGhlaWdodDogMTAwLFxuXHQgICAgICogICAgIHdpZHRoOiAyMDAsXG5cdCAgICAgKiAgICAgdG9wOiA0MDAsXG5cdCAgICAgKiAgICAgbGVmdDogNDAwXG5cdCAgICAgKiB9KS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdCb3VuZHMgc2V0IHRvIHdpbmRvdycpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgc2V0Qm91bmRzKGJvdW5kcywgcG9zaXRpb25pbmdPcHRpb25zKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZVxuXHQgICAgICAgICAgICAuc2VuZEFjdGlvbignc2V0LXdpbmRvdy1ib3VuZHMnLCB7IC4uLmJvdW5kcywgLi4udGhpcy5pZGVudGl0eSwgcG9zaXRpb25pbmdPcHRpb25zIH0pXG5cdCAgICAgICAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNob3dzIHRoZSB3aW5kb3cgaWYgaXQgaXMgaGlkZGVuLlxuXHQgICAgICogQHBhcmFtIGZvcmNlIFNob3cgd2lsbCBiZSBwcmV2ZW50ZWQgZnJvbSBzaG93aW5nIHdoZW4gZm9yY2UgaXMgZmFsc2UgYW5kXG5cdCAgICAgKiAg4oCYc2hvdy1yZXF1ZXN0ZWTigJkgaGFzIGJlZW4gc3Vic2NyaWJlZCB0byBmb3IgYXBwbGljYXRpb27igJlzIG1haW4gd2luZG93LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuc2hvdy5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IGZhbHNlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBzaG93KCkge1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGNyZWF0ZVdpbigpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uc2hvdygpXG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogc2hvdygpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1Nob3dpbmcnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHNob3coZm9yY2UgPSBmYWxzZSkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignc2hvdy13aW5kb3cnLCB7IGZvcmNlLCAuLi50aGlzLmlkZW50aXR5IH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2hvd3MgdGhlIHdpbmRvdyBpZiBpdCBpcyBoaWRkZW4gYXQgdGhlIHNwZWNpZmllZCBsb2NhdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gbGVmdCBUaGUgbGVmdCBwb3NpdGlvbiBvZiB0aGUgd2luZG93IGluIHBpeGVsc1xuXHQgICAgICogQHBhcmFtIHRvcCBUaGUgdG9wIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cgaW4gcGl4ZWxzXG5cdCAgICAgKiBAcGFyYW0gZm9yY2UgU2hvdyB3aWxsIGJlIHByZXZlbnRlZCBmcm9tIGNsb3Npbmcgd2hlbiBmb3JjZSBpcyBmYWxzZSBhbmRcblx0ICAgICAqIOKAmHNob3ctcmVxdWVzdGVk4oCZIGhhcyBiZWVuIHN1YnNjcmliZWQgdG8gZm9yIGFwcGxpY2F0aW9u4oCZcyBtYWluIHdpbmRvd1xuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuc2hvd0F0Lmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gc2hvd0F0KGxlZnQsIHRvcCkge1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGNyZWF0ZVdpbigpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uc2hvd0F0KGxlZnQsIHRvcClcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBzaG93QXQoNTgwLCAzMDApLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1Nob3dpbmcgYXQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHNob3dBdChsZWZ0LCB0b3AsIGZvcmNlID0gZmFsc2UpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlXG5cdCAgICAgICAgICAgIC5zZW5kQWN0aW9uKCdzaG93LWF0LXdpbmRvdycsIHtcblx0ICAgICAgICAgICAgZm9yY2UsXG5cdCAgICAgICAgICAgIGxlZnQ6IE1hdGguZmxvb3IobGVmdCksXG5cdCAgICAgICAgICAgIHRvcDogTWF0aC5mbG9vcih0b3ApLFxuXHQgICAgICAgICAgICAuLi50aGlzLmlkZW50aXR5XG5cdCAgICAgICAgfSlcblx0ICAgICAgICAgICAgLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2hvd3MgdGhlIENocm9taXVtIERldmVsb3BlciBUb29sc1xuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBXaW5kb3cuc2hvd0RldmVsb3BlclRvb2xzXG5cdCAgICAgKi9cblx0ICAgIC8qKlxuXHQgICAgICogVXBkYXRlcyB0aGUgd2luZG93IHVzaW5nIHRoZSBwYXNzZWQgb3B0aW9ucy5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBWYWx1ZXMgdGhhdCBhcmUgb2JqZWN0cyBhcmUgZGVlcC1tZXJnZWQsIG92ZXJ3cml0aW5nIG9ubHkgdGhlIHZhbHVlcyB0aGF0IGFyZSBwcm92aWRlZC5cblx0ICAgICAqIEBwYXJhbSBvcHRpb25zIENoYW5nZXMgYSB3aW5kb3cncyBvcHRpb25zIHRoYXQgd2VyZSBkZWZpbmVkIHVwb24gY3JlYXRpb24uIFNlZSB0dXRvcmlhbFxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gdXBkYXRlT3B0aW9ucygpIHtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gd2luLnVwZGF0ZU9wdGlvbnMoe21heFdpZHRoOiAxMDB9KTtcblx0ICAgICAqIH1cblx0ICAgICAqIHVwZGF0ZU9wdGlvbnMoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdvcHRpb25zIGlzIHVwZGF0ZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUuZXJyb3IoZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgdXBkYXRlT3B0aW9ucyhvcHRpb25zKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd1cGRhdGUtd2luZG93LW9wdGlvbnMnLCB7IG9wdGlvbnMsIC4uLnRoaXMuaWRlbnRpdHkgfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBQcm92aWRlcyBjcmVkZW50aWFscyB0byBhdXRoZW50aWNhdGlvbiByZXF1ZXN0c1xuXHQgICAgICogQHBhcmFtIHVzZXJOYW1lIHVzZXJOYW1lIHRvIHByb3ZpZGUgdG8gdGhlIGF1dGhlbnRpY2F0aW9uIGNoYWxsZW5nZVxuXHQgICAgICogQHBhcmFtIHBhc3N3b3JkIHBhc3N3b3JkIHRvIHByb3ZpZGUgdG8gdGhlIGF1dGhlbnRpY2F0aW9uIGNoYWxsZW5nZVxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLkFwcGxpY2F0aW9uLndyYXAoe3V1aWQ6ICdPcGVuZmluUE9DJ30pLnRoZW4oYXBwID0+IHtcblx0ICAgICAqICAgICBhcHAub24oJ3dpbmRvdy1hdXRoLXJlcXVlc3RlZCcsIGV2dCA9PiB7XG5cdCAgICAgKiAgICAgICAgIGxldCB3aW4gPSBmaW4uV2luZG93LndyYXAoeyB1dWlkOiBldnQudXVpZCwgbmFtZTogZXZ0Lm5hbWV9KTtcblx0ICAgICAqICAgICAgICAgd2luLmF1dGhlbnRpY2F0ZSgndXNlck5hbWUnLCAnUEBhc3N3MHJkJykudGhlbigoKT0+IGNvbnNvbGUubG9nKCdhdXRoZW50aWNhdGVkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGF1dGhlbnRpY2F0ZSh1c2VyTmFtZSwgcGFzc3dvcmQpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlXG5cdCAgICAgICAgICAgIC5zZW5kQWN0aW9uKCd3aW5kb3ctYXV0aGVudGljYXRlJywgeyB1c2VyTmFtZSwgcGFzc3dvcmQsIC4uLnRoaXMuaWRlbnRpdHkgfSlcblx0ICAgICAgICAgICAgLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2hvd3MgYSBtZW51IG9uIHRoZSB3aW5kb3cuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSB1c2VyIGhhcyBlaXRoZXIgc2VsZWN0ZWQgYW4gaXRlbSBvciBjbG9zZWQgdGhlIG1lbnUuIChUaGlzIG1heSB0YWtlIGxvbmdlciB0aGFuIG90aGVyIGFwaXMpLlxuXHQgICAgICogUmVzb2x2ZXMgdG8gYW4gb2JqZWN0IHdpdGggYHtyZXN1bHQ6ICdjbGlja2VkJywgZGF0YSB9YCB3aGVyZSBkYXRhIGlzIHRoZSBkYXRhIGZpZWxkIG9uIHRoZSBtZW51IGl0ZW0gY2xpY2tlZCwgb3IgYHtyZXN1bHQgJ2Nsb3NlZCd9YCB3aGVuIHRoZSB1c2VyIGRvZXNuJ3Qgc2VsZWN0IGFueXRoaW5nLlxuXHQgICAgICogQ2FsbGluZyB0aGlzIG1ldGhvZCB3aWxsIGNsb3NlIHByZXZpb3VzbHkgb3BlbmVkIG1lbnVzLlxuXHQgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICogQHBhcmFtIG9wdGlvbnNcblx0ICAgICAqIEB0eXBlUGFyYW0gRGF0YSBVc2VyLWRlZmluZWQgc2hhcGUgZm9yIGRhdGEgcmV0dXJuZWQgdXBvbiBtZW51IGl0ZW0gY2xpY2suICBTaG91bGQgYmUgYVxuXHQgICAgICogW3VuaW9uXShodHRwczovL3d3dy50eXBlc2NyaXB0bGFuZy5vcmcvZG9jcy9oYW5kYm9vay8yL2V2ZXJ5ZGF5LXR5cGVzLmh0bWwjdW5pb24tdHlwZXMpXG5cdCAgICAgKiBvZiBhbGwgcG9zc2libGUgZGF0YSBzaGFwZXMgZm9yIHRoZSBlbnRpcmUgbWVudSwgYW5kIHRoZSBjbGljayBoYW5kbGVyIHNob3VsZCBwcm9jZXNzXG5cdCAgICAgKiB0aGVzZSB3aXRoIGEgXCJyZWR1Y2VyXCIgcGF0dGVybi5cblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBUaGlzIGNvdWxkIGJlIHVzZWQgdG8gc2hvdyBhIGRyb3AgZG93biBtZW51IG92ZXIgdmlld3MgaW4gYSBwbGF0Zm9ybSB3aW5kb3c6XG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3QgdGVtcGxhdGUgPSBbXG5cdCAgICAgKiAgICAge1xuXHQgICAgICogICAgICAgICBsYWJlbDogJ01lbnUgSXRlbSAxJyxcblx0ICAgICAqICAgICAgICAgZGF0YTogJ2hlbGxvIGZyb20gaXRlbSAxJ1xuXHQgICAgICogICAgIH0sXG5cdCAgICAgKiAgICAgeyB0eXBlOiAnc2VwYXJhdG9yJyB9LFxuXHQgICAgICogICAgIHtcblx0ICAgICAqICAgICAgICAgbGFiZWw6ICdNZW51IEl0ZW0gMicsXG5cdCAgICAgKiAgICAgICAgIHR5cGU6ICdjaGVja2JveCcsXG5cdCAgICAgKiAgICAgICAgIGNoZWNrZWQ6IHRydWUsXG5cdCAgICAgKiAgICAgICAgIGRhdGE6ICdUaGUgdXNlciBjbGlja2VkIHRoZSBjaGVja2JveCdcblx0ICAgICAqICAgICB9LFxuXHQgICAgICogICAgIHtcblx0ICAgICAqICAgICAgICAgbGFiZWw6ICdzZWUgbW9yZScsXG5cdCAgICAgKiAgICAgICAgIGVuYWJsZWQ6IGZhbHNlLFxuXHQgICAgICogICAgICAgICBzdWJtZW51OiBbXG5cdCAgICAgKiAgICAgICAgICAgICB7IGxhYmVsOiAnc3VibWVudSAxJywgZGF0YTogJ2hlbGxvIGZyb20gc3VibWVudScgfVxuXHQgICAgICogICAgICAgICBdXG5cdCAgICAgKiAgICAgfVxuXHQgICAgICogXVxuXHQgICAgICogZmluLm1lLnNob3dQb3B1cE1lbnUoeyB0ZW1wbGF0ZSB9KS50aGVuKHIgPT4ge1xuXHQgICAgICogICAgIGlmIChyLnJlc3VsdCA9PT0gJ2Nsb3NlZCcpIHtcblx0ICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ25vdGhpbmcgaGFwcGVuZWQnKTtcblx0ICAgICAqICAgICB9IGVsc2Uge1xuXHQgICAgICogICAgICAgICBjb25zb2xlLmxvZyhyLmRhdGEpXG5cdCAgICAgKiAgICAgfVxuXHQgICAgICogfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqIE92ZXJyaWRpbmcgdGhlIGJ1aWx0IGluIGNvbnRleHQgbWVudSAobm90ZTogdGhhdCB0aGlzIGNhbiBiZSBkb25lIHBlciBlbGVtZW50IG9yIGRvY3VtZW50IHdpZGUpOlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgZSA9PiB7XG5cdCAgICAgKiAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHQgICAgICogICAgIGNvbnN0IHRlbXBsYXRlID0gW1xuXHQgICAgICogICAgICAgICB7XG5cdCAgICAgKiAgICAgICAgICAgICBsYWJlbDogJ01lbnUgSXRlbSAxJyxcblx0ICAgICAqICAgICAgICAgICAgIGRhdGE6ICdoZWxsbyBmcm9tIGl0ZW0gMSdcblx0ICAgICAqICAgICAgICAgfSxcblx0ICAgICAqICAgICAgICAgeyB0eXBlOiAnc2VwYXJhdG9yJyB9LFxuXHQgICAgICogICAgICAgICB7XG5cdCAgICAgKiAgICAgICAgICAgICBsYWJlbDogJ01lbnUgSXRlbSAyJyxcblx0ICAgICAqICAgICAgICAgICAgIHR5cGU6ICdjaGVja2JveCcsXG5cdCAgICAgKiAgICAgICAgICAgICBjaGVja2VkOiB0cnVlLFxuXHQgICAgICogICAgICAgICAgICAgZGF0YTogJ1RoZSB1c2VyIGNsaWNrZWQgdGhlIGNoZWNrYm94J1xuXHQgICAgICogICAgICAgICB9LFxuXHQgICAgICogICAgICAgICB7XG5cdCAgICAgKiAgICAgICAgICAgICBsYWJlbDogJ3NlZSBtb3JlJyxcblx0ICAgICAqICAgICAgICAgICAgIGVuYWJsZWQ6IGZhbHNlLFxuXHQgICAgICogICAgICAgICAgICAgc3VibWVudTogW1xuXHQgICAgICogICAgICAgICAgICAgICAgIHsgbGFiZWw6ICdzdWJtZW51IDEnLCBkYXRhOiAnaGVsbG8gZnJvbSBzdWJtZW51JyB9XG5cdCAgICAgKiAgICAgICAgICAgICBdXG5cdCAgICAgKiAgICAgICAgIH1cblx0ICAgICAqICAgICBdXG5cdCAgICAgKiAgICAgZmluLm1lLnNob3dQb3B1cE1lbnUoeyB0ZW1wbGF0ZSwgeDogZS54LCB5OiBlLnkgfSkudGhlbihyID0+IHtcblx0ICAgICAqICAgICAgICAgaWYgKHIucmVzdWx0ID09PSAnY2xvc2VkJykge1xuXHQgICAgICogICAgICAgICAgICAgY29uc29sZS5sb2coJ25vdGhpbmcgaGFwcGVuZWQnKTtcblx0ICAgICAqICAgICAgICAgfSBlbHNlIHtcblx0ICAgICAqICAgICAgICAgICAgIGNvbnNvbGUubG9nKHIuZGF0YSlcblx0ICAgICAqICAgICAgICAgfVxuXHQgICAgICogICAgIH0pXG5cdCAgICAgKiB9KVxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHNob3dQb3B1cE1lbnUob3B0aW9ucykge1xuXHQgICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Nob3ctcG9wdXAtbWVudScsIHsgb3B0aW9ucywgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgICAgICByZXR1cm4gcGF5bG9hZC5kYXRhO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBDbG9zZXMgdGhlIHdpbmRvdydzIHBvcHVwIG1lbnUsIGlmIG9uZSBleGlzdHMuXG5cdCAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgT25seSBvbmUgcG9wdXAgbWVudSB3aWxsIGV2ZXIgYmUgc2hvd2luZyBhdCBhIHRpbWUuIENhbGxpbmcgYHNob3dQb3B1cE1lbnVgIHdpbGwgYXV0b21hdGljYWxseSBjbG9zZVxuXHQgICAgICogYW55IGV4aXN0aW5nIHBvcHVwIG1lbnUuXG5cdCAgICAgKlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBUaGlzIGNvdWxkIGJlIHVzZWQgdG8gY2xvc2UgYSBwb3B1cCBtZW51IGlmIHRoZSB1c2VyJ3MgbW91c2UgbGVhdmVzIGFuIGVsZW1lbnQgZm9yIGV4YW1wbGUuXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGF3YWl0IGZpbi5tZS5jbG9zZVBvcHVwTWVudSgpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGNsb3NlUG9wdXBNZW51KCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignY2xvc2UtcG9wdXAtbWVudScsIHsgLi4udGhpcy5pZGVudGl0eSB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIERpc3BhdGNoIGEgcmVzdWx0IHRvIHRoZSBjYWxsZXIgb2YgYHNob3dQb3B1cFdpbmRvd2AuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgSWYgdGhpcyB3aW5kb3cgaXNuJ3QgY3VycmVudGx5IGJlaW5nIHNob3duIGFzIGEgcG9wdXAsIHRoaXMgY2FsbCB3aWxsIHNpbGVudGx5IGZhaWwuXG5cdCAgICAgKiBAcGFyYW0gZGF0YSBTZXJpYWxpemFibGUgZGF0YSB0byBzZW5kIHRvIHRoZSBjYWxsZXIgd2luZG93LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXdhaXQgZmluLm1lLmRpc3BhdGNoUG9wdXBSZXN1bHQoe1xuXHQgICAgICogICAgIGZvbzogJ2Jhcidcblx0ICAgICAqIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGRpc3BhdGNoUG9wdXBSZXN1bHQoZGF0YSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd3aW5kb3ctZGlzcGF0Y2gtcG9wdXAtcmVzdWx0JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2Rpc3BhdGNoLXBvcHVwLXJlc3VsdCcsIHsgZGF0YSwgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUHJpbnRzIHRoZSBjb250ZW50cyBvZiB0aGUgd2luZG93LlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBvcHRpb25zIENvbmZpZ3VyYXRpb24gZm9yIHRoZSBwcmludCB0YXNrLlxuXHQgICAgICogQHJlbWFya3MgV2hlbiBgc2lsZW50YCBpcyBzZXQgdG8gYHRydWVgLCB0aGUgQVBJIHdpbGwgcGljayB0aGUgc3lzdGVtJ3MgZGVmYXVsdCBwcmludGVyIGlmIGRldmljZU5hbWUgaXMgZW1wdHlcblx0ICAgICAqIGFuZCB0aGUgZGVmYXVsdCBzZXR0aW5ncyBmb3IgcHJpbnRpbmcuXG5cdCAgICAgKlxuXHQgICAgICogVXNlIHRoZSBDU1Mgc3R5bGUgYHBhZ2UtYnJlYWstYmVmb3JlOiBhbHdheXM7YCB0byBmb3JjZSBwcmludCB0byBhIG5ldyBwYWdlLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3Qgd2luID0gZmluLldpbmRvdy5nZXRDdXJyZW50U3luYygpO1xuXHQgICAgICpcblx0ICAgICAqIHdpbi5wcmludCh7IHNpbGVudDogZmFsc2UsIGRldmljZU5hbWU6ICdzeXN0ZW0tcHJpbnRlci1uYW1lJyB9KS50aGVuKCgpID0+IHtcblx0ICAgICAqICAgICBjb25zb2xlLmxvZygncHJpbnQgY2FsbCBoYXMgYmVlbiBzZW50IHRvIHRoZSBzeXN0ZW0nKTtcblx0ICAgICAqIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICogSWYgYSB3aW5kb3cgaGFzIGVtYmVkZGVkIHZpZXdzLCB0aG9zZSB2aWV3cyB3aWxsIG5vdCBwcmludCBieSBkZWZhdWx0LiAgVG8gcHJpbnQgYSB3aW5kb3cncyBjb250ZW50cyBpbmNsdWRpbmcgZW1iZWRkZWQgdmlld3MsXG5cdCAgICAgKiB1c2UgdGhlIGBjb250ZW50YCBvcHRpb246XG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IHdpbiA9IGZpbi5XaW5kb3cuZ2V0Q3VycmVudFN5bmMoKTtcblx0ICAgICAqXG5cdCAgICAgKiAvLyBQcmludCBlbWJlZGRlZCB2aWV3c1xuXHQgICAgICogd2luLnByaW50KHsgY29udGVudDogJ3ZpZXdzJyB9KTtcblx0ICAgICAqXG5cdCAgICAgKiAvLyBQcmludCBzY3JlZW5zaG90IG9mIGN1cnJlbnQgd2luZG93XG5cdCAgICAgKiB3aW4ucHJpbnQoeyBjb250ZW50OiAnc2NyZWVuc2hvdCcgfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqIFdoZW4gYGNvbnRlbnRgIGlzIHNldCB0byBgdmlld3NgLCB0aGUgZW1iZWRkZWQgdmlld3MgaW4gdGhlIHBsYXRmb3JtIHdpbmRvdyB3aWxsIGJlIGNvbmNhdGVuYXRlZCBhbmQgcHJpbnRlZCBhc1xuXHQgICAgICogaW5kaXZpZHVhbCBwYWdlcy4gIElmIGBpbmNsdWRlU2VsZmAgaXMgc2V0IHRvIGB0cnVlYCwgdGhlIHBsYXRmb3JtIHdpbmRvdyBpdHNlbGYgd2lsbCBiZSBwcmludGVkIGFzIHRoZSBmaXJzdFxuXHQgICAgICogcGFnZSAtIGJlIGF3YXJlIHRoYXQgdGhpcyBwYWdlIHdpbGwgKm5vdCogaW5jbHVkZSB0aGUgZW1iZWRkZWQgdmlld3MgLSBpdCB3aWxsIG9ubHkgaW5jbHVkZSB0aGUgY29udGVudHMgb2Zcblx0ICAgICAqIHRoZSBwbGF0Zm9ybSB3aW5kb3cgaXRzZWxmIChlLmcuIHRhYiBzdGFja3MpLCB3aXRoIGJsYW5rIHNwYWNlcyB3aGVyZSB0aGUgdmlldyBjb250ZW50cyB3b3VsZCBiZSBlbWJlZGRlZC5cblx0ICAgICAqXG5cdCAgICAgKiBEdWUgdG8gYSBrbm93biBpc3N1ZSwgdmlldyBjb250ZW50cyB0aGF0IGFyZSBub3QgdmlzaWJsZSBhdCB0aGUgdGltZSBgcHJpbnRgIGlzIGNhbGxlZCB3aWxsIG5vdCBhcHBlYXIgd2hlblxuXHQgICAgICogcHJpbnRpbmcgYGNvbnRlbnRzOiB2aWV3c2AuICBUaGlzIGluY2x1ZGVzIHZpZXdzIHRoYXQgYXJlIG9ic2N1cmVkIGJlaGluZCBvdGhlciBhY3RpdmUgVUkgZWxlbWVudHMuXG5cdCAgICAgKlxuXHQgICAgICogVG8gcHJpbnQgdGhlIHZpZXdzIGVtYmVkZGVkIGluIHRoZWlyIHBhZ2UgY29udGV4dCwgc2V0IGBjb250ZW50YCB0byBgc2NyZWVuc2hvdGAuXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHByaW50KG9wdGlvbnMgPSB7IGNvbnRlbnQ6ICdzZWxmJyB9KSB7XG5cdCAgICAgICAgc3dpdGNoIChvcHRpb25zLmNvbnRlbnQpIHtcblx0ICAgICAgICAgICAgY2FzZSB1bmRlZmluZWQ6XG5cdCAgICAgICAgICAgIGNhc2UgJ3NlbGYnOlxuXHQgICAgICAgICAgICAgICAgcmV0dXJuIHN1cGVyLnByaW50KG9wdGlvbnMpO1xuXHQgICAgICAgICAgICBjYXNlICdzY3JlZW5zaG90Jzpcblx0ICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigncHJpbnQtc2NyZWVuc2hvdCcsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgICAgICAgICAgY2FzZSAndmlld3MnOlxuXHQgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwcmludC12aWV3cycsIHsgLi4udGhpcy5pZGVudGl0eSwgb3B0aW9ucyB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICAgICAgICAgIGRlZmF1bHQ6XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0fVxuXHRJbnN0YW5jZSQ3Ll9XaW5kb3cgPSBfV2luZG93O1xuXHRyZXR1cm4gSW5zdGFuY2UkNztcbn1cblxudmFyIGhhc1JlcXVpcmVkRmFjdG9yeSQxO1xuXG5mdW5jdGlvbiByZXF1aXJlRmFjdG9yeSQxICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkRmFjdG9yeSQxKSByZXR1cm4gRmFjdG9yeSQ4O1xuXHRoYXNSZXF1aXJlZEZhY3RvcnkkMSA9IDE7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShGYWN0b3J5JDgsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRGYWN0b3J5JDguX1dpbmRvd01vZHVsZSA9IHZvaWQgMDtcblx0Y29uc3QgYmFzZV8xID0gYmFzZTtcblx0Y29uc3QgdmFsaWRhdGVfMSA9IHZhbGlkYXRlO1xuXHRjb25zdCBJbnN0YW5jZV8xID0gcmVxdWlyZUluc3RhbmNlKCk7XG5cdC8qKlxuXHQgKiBTdGF0aWMgbmFtZXNwYWNlIGZvciBPcGVuRmluIEFQSSBtZXRob2RzIHRoYXQgaW50ZXJhY3Qgd2l0aCB0aGUge0BsaW5rIF9XaW5kb3d9IGNsYXNzLCBhdmFpbGFibGUgdW5kZXIgYGZpbi5XaW5kb3dgLlxuXHQgKi9cblx0Y2xhc3MgX1dpbmRvd01vZHVsZSBleHRlbmRzIGJhc2VfMS5CYXNlIHtcblx0ICAgIC8qKlxuXHQgICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhbiBBUEkgaGFuZGxlIGZvciB0aGUgZ2l2ZW4gV2luZG93IGlkZW50aXR5LlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFdyYXBwaW5nIGEgV2luZG93IGlkZW50aXR5IHRoYXQgZG9lcyBub3QgeWV0IGV4aXN0IHdpbGwgKm5vdCogdGhyb3cgYW4gZXJyb3IsIGFuZCBpbnN0ZWFkXG5cdCAgICAgKiByZXR1cm5zIGEgc3R1YiBvYmplY3QgdGhhdCBjYW5ub3QgeWV0IHBlcmZvcm0gcmVuZGVyaW5nIHRhc2tzLiBUaGlzIGNhbiBiZSB1c2VmdWwgZm9yIHBsdW1iaW5nIGV2ZW50aW5nXG5cdCAgICAgKiBmb3IgYSBXaW5kb3cgdGhyb3VnaG91dCBpdHMgZW50aXJlIGxpZmVjeWNsZS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LndyYXAuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqIH1cblx0ICAgICAqIGNyZWF0ZVdpbigpLnRoZW4oKCkgPT4gZmluLldpbmRvdy53cmFwKHsgdXVpZDogJ2FwcC0xJywgbmFtZTogJ215QXBwJyB9KSlcblx0ICAgICAqIC50aGVuKHdpbiA9PiBjb25zb2xlLmxvZygnd3JhcHBlZCB3aW5kb3cnKSlcblx0ICAgICAqIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgd3JhcChpZGVudGl0eSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd3aW5kb3ctd3JhcCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGVycm9yTXNnID0gKDAsIHZhbGlkYXRlXzEudmFsaWRhdGVJZGVudGl0eSkoaWRlbnRpdHkpO1xuXHQgICAgICAgIGlmIChlcnJvck1zZykge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNc2cpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4gbmV3IEluc3RhbmNlXzEuX1dpbmRvdyh0aGlzLndpcmUsIGlkZW50aXR5KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGFuIEFQSSBoYW5kbGUgZm9yIHRoZSBnaXZlbiBXaW5kb3cgaWRlbnRpdHkuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgV3JhcHBpbmcgYSBXaW5kb3cgaWRlbnRpdHkgdGhhdCBkb2VzIG5vdCB5ZXQgZXhpc3Qgd2lsbCAqbm90KiB0aHJvdyBhbiBlcnJvciwgYW5kIGluc3RlYWRcblx0ICAgICAqIHJldHVybnMgYSBzdHViIG9iamVjdCB0aGF0IGNhbm5vdCB5ZXQgcGVyZm9ybSByZW5kZXJpbmcgdGFza3MuIFRoaXMgY2FuIGJlIHVzZWZ1bCBmb3IgcGx1bWJpbmcgZXZlbnRpbmdcblx0ICAgICAqIGZvciBhIFdpbmRvdyB0aHJvdWdob3V0IGl0cyBlbnRpcmUgbGlmZWN5Y2xlLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cud3JhcFN5bmMuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqIH1cblx0ICAgICAqIGF3YWl0IGNyZWF0ZVdpbigpO1xuXHQgICAgICogbGV0IHdpbiA9IGZpbi5XaW5kb3cud3JhcFN5bmMoeyB1dWlkOiAnYXBwLTEnLCBuYW1lOiAnbXlBcHAnIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHdyYXBTeW5jKGlkZW50aXR5KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3dpbmRvdy13cmFwLXN5bmMnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBlcnJvck1zZyA9ICgwLCB2YWxpZGF0ZV8xLnZhbGlkYXRlSWRlbnRpdHkpKGlkZW50aXR5KTtcblx0ICAgICAgICBpZiAoZXJyb3JNc2cpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTXNnKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIG5ldyBJbnN0YW5jZV8xLl9XaW5kb3codGhpcy53aXJlLCBpZGVudGl0eSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIENyZWF0ZXMgYSBuZXcgV2luZG93LlxuXHQgICAgICogQHBhcmFtIG9wdGlvbnMgLSBXaW5kb3cgY3JlYXRpb24gb3B0aW9uc1xuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luZG93KCkge1xuXHQgICAgICogICAgIGNvbnN0IHdpbk9wdGlvbiA9IHtcblx0ICAgICAqICAgICAgICAgbmFtZTonY2hpbGQnLFxuXHQgICAgICogICAgICAgICBkZWZhdWx0V2lkdGg6IDMwMCxcblx0ICAgICAqICAgICAgICAgZGVmYXVsdEhlaWdodDogMzAwLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmNyZWF0ZS5odG1sJyxcblx0ICAgICAqICAgICAgICAgZnJhbWU6IHRydWUsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgZmluLldpbmRvdy5jcmVhdGUod2luT3B0aW9uKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBjcmVhdGVXaW5kb3coKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdXaW5kb3cgaXMgY3JlYXRlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgY3JlYXRlKG9wdGlvbnMpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignY3JlYXRlLXdpbmRvdycpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IHdpbiA9IG5ldyBJbnN0YW5jZV8xLl9XaW5kb3codGhpcy53aXJlLCB7IHV1aWQ6IHRoaXMubWUudXVpZCwgbmFtZTogb3B0aW9ucy5uYW1lIH0pO1xuXHQgICAgICAgIHJldHVybiB3aW4uY3JlYXRlV2luZG93KG9wdGlvbnMpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBBc3luY2hyb25vdXNseSByZXR1cm5zIGEgV2luZG93IG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIGN1cnJlbnQgd2luZG93XG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBmaW4uV2luZG93LmdldEN1cnJlbnQoKVxuXHQgICAgICogLnRoZW4od25kID0+IGNvbnNvbGUubG9nKCdjdXJyZW50IHdpbmRvdycpKVxuXHQgICAgICogLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqXG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0Q3VycmVudCgpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWN1cnJlbnQtd2luZG93JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgaWYgKCF0aGlzLndpcmUubWUuaXNXaW5kb3cpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgYXJlIG5vdCBpbiBhIFdpbmRvdyBjb250ZXh0Jyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNvbnN0IHsgdXVpZCwgbmFtZSB9ID0gdGhpcy53aXJlLm1lO1xuXHQgICAgICAgIHJldHVybiB0aGlzLndyYXAoeyB1dWlkLCBuYW1lIH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTeW5jaHJvbm91c2x5IHJldHVybnMgYSBXaW5kb3cgb2JqZWN0IHRoYXQgcmVwcmVzZW50cyB0aGUgY3VycmVudCB3aW5kb3dcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IHduZCA9IGZpbi5XaW5kb3cuZ2V0Q3VycmVudFN5bmMoKTtcblx0ICAgICAqIGNvbnN0IGluZm8gPSBhd2FpdCB3bmQuZ2V0SW5mbygpO1xuXHQgICAgICogY29uc29sZS5sb2coaW5mbyk7XG5cdCAgICAgKlxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldEN1cnJlbnRTeW5jKCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtY3VycmVudC13aW5kb3ctc3luYycpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGlmICghdGhpcy53aXJlLm1lLmlzV2luZG93KSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IGFyZSBub3QgaW4gYSBXaW5kb3cgY29udGV4dCcpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IHRoaXMud2lyZS5tZTtcblx0ICAgICAgICByZXR1cm4gdGhpcy53cmFwU3luYyh7IHV1aWQsIG5hbWUgfSk7XG5cdCAgICB9XG5cdH1cblx0RmFjdG9yeSQ4Ll9XaW5kb3dNb2R1bGUgPSBfV2luZG93TW9kdWxlO1xuXHRyZXR1cm4gRmFjdG9yeSQ4O1xufVxuXG52YXIgaGFzUmVxdWlyZWRXaW5kb3c7XG5cbmZ1bmN0aW9uIHJlcXVpcmVXaW5kb3cgKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRXaW5kb3cpIHJldHVybiB3aW5kb3ckMTtcblx0aGFzUmVxdWlyZWRXaW5kb3cgPSAxO1xuXHQoZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0XHR2YXIgX19jcmVhdGVCaW5kaW5nID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY3JlYXRlQmluZGluZykgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0XHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0XHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHRcdCAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xuXHRcdCAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XG5cdFx0ICAgIH1cblx0XHQgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcblx0XHR9KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHRcdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHRcdCAgICBvW2syXSA9IG1ba107XG5cdFx0fSkpO1xuXHRcdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdFx0ICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZXhwb3J0cywgcCkpIF9fY3JlYXRlQmluZGluZyhleHBvcnRzLCBtLCBwKTtcblx0XHR9O1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0XHQvKipcblx0XHQgKiBFbnRyeSBwb2ludHMgZm9yIHRoZSBPcGVuRmluIGBXaW5kb3dgIEFQSSAoYGZpbi5XaW5kb3dgKS5cblx0XHQgKlxuXHRcdCAqICoge0BsaW5rIF9XaW5kb3dNb2R1bGV9IGNvbnRhaW5zIHN0YXRpYyBtZW1iZXJzIG9mIHRoZSBgV2luZG93YCBBUEksIGFjY2Vzc2libGUgdGhyb3VnaCBgZmluLldpbmRvd2AuXG5cdFx0ICogKiB7QGxpbmsgX1dpbmRvd30gZGVzY3JpYmVzIGFuIGluc3RhbmNlIG9mIGFuIE9wZW5GaW4gV2luZG93LCBlLmcuIGFzIHJldHVybmVkIGJ5IGBmaW4uV2luZG93LmdldEN1cnJlbnRgLlxuXHRcdCAqXG5cdFx0ICogVGhlc2UgYXJlIHNlcGFyYXRlIGNvZGUgZW50aXRpZXMsIGFuZCBhcmUgZG9jdW1lbnRlZCBzZXBhcmF0ZWx5LiAgSW4gdGhlIFtwcmV2aW91cyB2ZXJzaW9uIG9mIHRoZSBBUEkgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvMzIuMTE0Ljc2LjEwL2luZGV4Lmh0bWwpLFxuXHRcdCAqIGJvdGggb2YgdGhlc2Ugd2VyZSBkb2N1bWVudGVkIG9uIHRoZSBzYW1lIHBhZ2UuXG5cdFx0ICpcblx0XHQgKiBVbmRlcnNjb3JlIHByZWZpeGluZyBvZiBPcGVuRmluIHR5cGVzIHRoYXQgYWxpYXMgRE9NIGVudGl0aWVzIHdpbGwgYmUgZml4ZWQgaW4gYSBmdXR1cmUgdmVyc2lvbi5cblx0XHQgKlxuXHRcdCAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuXHRcdCAqL1xuXHRcdF9fZXhwb3J0U3RhcihyZXF1aXJlRmFjdG9yeSQxKCksIGV4cG9ydHMpO1xuXHRcdF9fZXhwb3J0U3RhcihyZXF1aXJlSW5zdGFuY2UoKSwgZXhwb3J0cyk7IFxuXHR9ICh3aW5kb3ckMSkpO1xuXHRyZXR1cm4gd2luZG93JDE7XG59XG5cbi8qKlxuICogRW50cnkgcG9pbnQgZm9yIHRoZSBPcGVuRmluIGBTeXN0ZW1gIEFQSSAoYGZpbi5TeXN0ZW1gKS5cbiAqXG4gKiAqIHtAbGluayBTeXN0ZW19IGNvbnRhaW5zIHN0YXRpYyBtZW1iZXJzIG9mIHRoZSBgU3lzdGVtYCBBUEkgKGF2YWlsYWJsZSB1bmRlciBgZmluLlN5c3RlbWApXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShzeXN0ZW0sIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuc3lzdGVtLlN5c3RlbSA9IHZvaWQgMDtcbmNvbnN0IGJhc2VfMSRpID0gYmFzZTtcbmNvbnN0IHRyYW5zcG9ydF9lcnJvcnNfMSQxID0gdHJhbnNwb3J0RXJyb3JzO1xuY29uc3Qgd2luZG93XzEgPSByZXF1aXJlV2luZG93KCk7XG5jb25zdCBldmVudHNfMSQ2ID0gcmVxdWlyZSQkMDtcbi8qKlxuICogQW4gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgY29yZSBvZiBPcGVuRmluIFJ1bnRpbWUuIEFsbG93cyB0aGUgZGV2ZWxvcGVyXG4gKiB0byBwZXJmb3JtIHN5c3RlbS1sZXZlbCBhY3Rpb25zLCBzdWNoIGFzIGFjY2Vzc2luZyBsb2dzLCB2aWV3aW5nIHByb2Nlc3NlcyxcbiAqIGNsZWFyaW5nIHRoZSBjYWNoZSBhbmQgZXhpdGluZyB0aGUgcnVudGltZSBhcyB3ZWxsIGFzIGxpc3RlbiB0byB7QGxpbmsgT3BlbkZpbi5TeXN0ZW1FdmVudHMgc3lzdGVtIGV2ZW50c30uXG4gKlxuICovXG5jbGFzcyBTeXN0ZW0gZXh0ZW5kcyBiYXNlXzEkaS5FbWl0dGVyQmFzZSB7XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iod2lyZSkge1xuICAgICAgICBzdXBlcih3aXJlLCAnc3lzdGVtJyk7XG4gICAgfVxuICAgIHNlbmRFeHRlcm5hbFByb2Nlc3NSZXF1ZXN0KGFjdGlvbiwgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZXhpdEV2ZW50S2V5ID0gJ2V4dGVybmFsLXByb2Nlc3MtZXhpdGVkJztcbiAgICAgICAgICAgIGxldCBwcm9jZXNzVXVpZDtcbiAgICAgICAgICAgIGxldCBleGl0UGF5bG9hZDtcbiAgICAgICAgICAgIGxldCBleHRlcm5hbFByb2Nlc3NFeGl0SGFuZGxlcjtcbiAgICAgICAgICAgIGxldCBvZldpbmRvdztcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5saXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGV4dGVybmFsUHJvY2Vzc0V4aXRIYW5kbGVyID0gKHBheWxvYWQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHBheWxvYWQgfHwge307XG4gICAgICAgICAgICAgICAgICAgIGV4aXRQYXlsb2FkID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdG9waWM6ICdleGl0ZWQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdXVpZDogZGF0YS5wcm9jZXNzVXVpZCB8fCAnJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4aXRDb2RlOiBkYXRhLmV4aXRDb2RlIHx8IDBcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb2Nlc3NVdWlkID09PSBwYXlsb2FkLnByb2Nlc3NVdWlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zLmxpc3RlbmVyKGV4aXRQYXlsb2FkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9mV2luZG93LnJlbW92ZUxpc3RlbmVyKGV4aXRFdmVudEtleSwgZXh0ZXJuYWxQcm9jZXNzRXhpdEhhbmRsZXIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAvLyB3aW5kb3cgY29uc3RydWN0b3IgZXhwZWN0cyB0aGUgbmFtZSBpcyBub3QgdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLndpcmUubWUubmFtZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndpcmUubWUubmFtZSA9IHRoaXMud2lyZS5tZS51dWlkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvZldpbmRvdyA9IG5ldyB3aW5kb3dfMS5fV2luZG93KHRoaXMud2lyZSwgdGhpcy53aXJlLm1lKTtcbiAgICAgICAgICAgICAgICBvZldpbmRvdy5vbihleGl0RXZlbnRLZXksIGV4dGVybmFsUHJvY2Vzc0V4aXRIYW5kbGVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2lyZVxuICAgICAgICAgICAgICAgIC5zZW5kQWN0aW9uKGFjdGlvbiwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICAudGhlbigoeyBwYXlsb2FkIH0pID0+IHtcbiAgICAgICAgICAgICAgICBwcm9jZXNzVXVpZCA9IHBheWxvYWQuZGF0YS51dWlkO1xuICAgICAgICAgICAgICAgIHJlc29sdmUocGF5bG9hZC5kYXRhKTtcbiAgICAgICAgICAgICAgICBpZiAoZXhpdFBheWxvYWQgJiYgcHJvY2Vzc1V1aWQgPT09IGV4aXRQYXlsb2FkLnV1aWQpIHtcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5saXN0ZW5lcihleGl0UGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgICAgIG9mV2luZG93LnJlbW92ZUxpc3RlbmVyKGV4aXRFdmVudEtleSwgZXh0ZXJuYWxQcm9jZXNzRXhpdEhhbmRsZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAob2ZXaW5kb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgb2ZXaW5kb3cucmVtb3ZlTGlzdGVuZXIoZXhpdEV2ZW50S2V5LCBleHRlcm5hbFByb2Nlc3NFeGl0SGFuZGxlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB2ZXJzaW9uIG9mIHRoZSBydW50aW1lLiBUaGUgdmVyc2lvbiBjb250YWlucyB0aGUgbWFqb3IsIG1pbm9yLFxuICAgICAqIGJ1aWxkIGFuZCByZXZpc2lvbiBudW1iZXJzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0VmVyc2lvbigpLnRoZW4odiA9PiBjb25zb2xlLmxvZyh2KSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldFZlcnNpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXZlcnNpb24nKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2xlYXJzIGNhY2hlZCBkYXRhIGNvbnRhaW5pbmcgYXBwbGljYXRpb24gcmVzb3VyY2VcbiAgICAgKiBmaWxlcyAoaW1hZ2VzLCBIVE1MLCBKYXZhU2NyaXB0IGZpbGVzKSwgY29va2llcywgYW5kIGl0ZW1zIHN0b3JlZCBpbiB0aGVcbiAgICAgKiBMb2NhbCBTdG9yYWdlLlxuICAgICAqIEBwYXJhbSBvcHRpb25zIC0gU2VlIGJlbG93IGZvciBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgRm9yIG1vcmUgaW5mb3JtYXRpb24gb24gdGhlIGFjY2VwdGVkIG9wdGlvbnMsIHNlZSB0aGUgZm9sbG93aW5nIHBhZ2VzOlxuICAgICAqICogY2FjaGU6IGJyb3dzaW5nIGRhdGEgY2FjaGUgZm9yIGh0bWwgZmlsZXMgYW5kIGltYWdlcyAoW2NhY2hpbmddKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUVFAvQ2FjaGluZykpXG4gICAgICogKiBjb29raWVzOiBicm93c2VyIFtjb29raWVzXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVFRQL0Nvb2tpZXMpXG4gICAgICogKiBsb2NhbFN0b3JhZ2U6IGJyb3dzZXIgZGF0YSB0aGF0IGNhbiBiZSB1c2VkIGFjcm9zcyBzZXNzaW9ucyAoW2xvY2FsIHN0b3JhZ2VdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3cvbG9jYWxTdG9yYWdlKSlcbiAgICAgKiAqIGFwcGNhY2hlOiBodG1sNSBbYXBwbGljYXRpb24gY2FjaGVdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvVXNpbmdfdGhlX2FwcGxpY2F0aW9uX2NhY2hlKVxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBjbGVhckNhY2hlT3B0aW9ucyA9IHtcbiAgICAgKiAgICAgYXBwY2FjaGU6IHRydWUsXG4gICAgICogICAgIGNhY2hlOiB0cnVlLFxuICAgICAqICAgICBjb29raWVzOiB0cnVlLFxuICAgICAqICAgICBsb2NhbFN0b3JhZ2U6IHRydWVcbiAgICAgKiB9O1xuICAgICAqIGZpbi5TeXN0ZW0uY2xlYXJDYWNoZShjbGVhckNhY2hlT3B0aW9ucykudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQ2FjaGUgY2xlYXJlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKi9cbiAgICBjbGVhckNhY2hlKG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjbGVhci1jYWNoZScsIG9wdGlvbnMpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2xlYXJzIGFsbCBjYWNoZWQgZGF0YSB3aGVuIE9wZW5GaW4gUnVudGltZSBleGl0cy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmRlbGV0ZUNhY2hlT25FeGl0KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnRGVsZXRlZCBDYWNoZScpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZGVsZXRlQ2FjaGVPbkV4aXQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZGVsZXRlLWNhY2hlLXJlcXVlc3QnKS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEV4aXRzIHRoZSBSdW50aW1lLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZXhpdCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ2V4aXQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGV4aXQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZXhpdC1kZXNrdG9wJykudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIGEgSlNPTiBtYW5pZmVzdCB1c2luZyB0aGUgYnJvd3NlciBwcm9jZXNzIGFuZCByZXR1cm5zIGEgSmF2YXNjcmlwdCBvYmplY3QuXG4gICAgICogQHBhcmFtIG1hbmlmZXN0VXJsIFRoZSBVUkwgb2YgdGhlIG1hbmlmZXN0IHRvIGZldGNoLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgZmluLlN5c3RlbS5mZXRjaE1hbmlmZXN0KCdodHRwczovL3d3dy5wYXRoLXRvLW1hbmlmZXN0LmNvbScpO1xuICAgICAqIGNvbnNvbGUubG9nKG1hbmlmZXN0KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBmZXRjaE1hbmlmZXN0KG1hbmlmZXN0VXJsKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhIH0gfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZXRjaC1tYW5pZmVzdCcsIHsgbWFuaWZlc3RVcmwgfSk7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgYW55IHVud3JpdHRlbiBjb29raWVzIGRhdGEgdG8gZGlzay5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmZsdXNoQ29va2llU3RvcmUoKVxuICAgICAqICAgICAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnc3VjY2VzcycpKVxuICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUuZXJyb3IoZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZmx1c2hDb29raWVTdG9yZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmbHVzaC1jb29raWUtc3RvcmUnKS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhbiBhcnJheSBvZiBkYXRhIChuYW1lLCBpZHMsIGJvdW5kcykgZm9yIGFsbCBhcHBsaWNhdGlvbiB3aW5kb3dzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0QWxsV2luZG93cygpLnRoZW4od2lucyA9PiBjb25zb2xlLmxvZyh3aW5zKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldEFsbFdpbmRvd3MoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWFsbC13aW5kb3dzJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhbiBhcnJheSBvZiBkYXRhIGZvciBhbGwgYXBwbGljYXRpb25zLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0QWxsQXBwbGljYXRpb25zKCkudGhlbihhcHBzID0+IGNvbnNvbGUubG9nKGFwcHMpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0QWxsQXBwbGljYXRpb25zKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1hbGwtYXBwbGljYXRpb25zJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgY29tbWFuZCBsaW5lIGFyZ3VtZW50IHN0cmluZyB0aGF0IHN0YXJ0ZWQgT3BlbkZpbiBSdW50aW1lLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0Q29tbWFuZExpbmVBcmd1bWVudHMoKS50aGVuKGFyZ3MgPT4gY29uc29sZS5sb2coYXJncykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRDb21tYW5kTGluZUFyZ3VtZW50cygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtY29tbWFuZC1saW5lLWFyZ3VtZW50cycpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIGNyYXNoIHJlcG9ydGVyLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0Q3Jhc2hSZXBvcnRlclN0YXRlKCkudGhlbihzdGF0ZSA9PiBjb25zb2xlLmxvZyhzdGF0ZSkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBnZXRDcmFzaFJlcG9ydGVyU3RhdGUoKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhOiB7IGRpYWdub3N0aWNNb2RlLCBpc1J1bm5pbmcgfSB9IH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWNyYXNoLXJlcG9ydGVyLXN0YXRlJyk7XG4gICAgICAgIGNvbnNvbGUud2FybignZGlhZ25vc3RpY01vZGUgcHJvcGVydHkgaXMgZGVwcmVjYXRlZC4gSXQgd2lsbCBiZSByZW1vdmVkIGluIGEgZnV0dXJlIHZlcnNpb24nKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC8vIGRpYWdub3N0aWNNb2RlIHdpbGwgYmUgcmVtb3ZlZCBpbiBhIGZ1dHVyZSB2ZXJzaW9uXG4gICAgICAgICAgICBkaWFnbm9zdGljTW9kZSxcbiAgICAgICAgICAgIGRpYWdub3N0aWNzTW9kZTogZGlhZ25vc3RpY01vZGUsXG4gICAgICAgICAgICBpc1J1bm5pbmdcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3RhcnQgdGhlIGNyYXNoIHJlcG9ydGVyIGlmIG5vdCBhbHJlYWR5IHJ1bm5pbmcuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBjb25maWd1cmUgY3Jhc2ggcmVwb3J0ZXJcbiAgICAgKlxuICAgICAqIEByZW1hcmtzIFlvdSBjYW4gb3B0aW9uYWxseSBzcGVjaWZ5IGBkaWFnbm9zdGljc01vZGVgIHRvIGhhdmUgdGhlIGxvZ3Mgc2VudCB0b1xuICAgICAqIE9wZW5GaW4gb24gcnVudGltZSBjbG9zZS4gKE5PVEU6IGBkaWFnbm9zdGljc01vZGVgIHdpbGwgdHVybiBvbiB2ZXJib3NlIGxvZ2dpbmcgYW5kIGRpc2FibGUgdGhlIHNhbmRib3hcbiAgICAgKiBmb3IgbmV3bHkgbGF1bmNoZWQgcmVuZGVyZXIgcHJvY2Vzc2VzLiBTZWUgaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5maW4uY28vb2YtZG9jcy9kb2NzL2RlYnVnZ2luZyNkaWFnbm9zdGljcy1tb2RlIGZvclxuICAgICAqIG1vcmUgZGV0YWlscy4pXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5zdGFydENyYXNoUmVwb3J0ZXIoe2RpYWdub3N0aWNzTW9kZTogdHJ1ZX0pLnRoZW4ocmVwb3J0ZXIgPT4gY29uc29sZS5sb2cocmVwb3J0ZXIpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgc3RhcnRDcmFzaFJlcG9ydGVyKG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3Qgb3B0cyA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IG5ld09wdHMgPSB7IC4uLm9wdHMsIGRpYWdub3N0aWNNb2RlOiBvcHRzLmRpYWdub3N0aWNzTW9kZSB8fCBvcHRzLmRpYWdub3N0aWNNb2RlIH07XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhOiB7IGRpYWdub3N0aWNNb2RlLCBpc1J1bm5pbmcgfSB9IH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc3RhcnQtY3Jhc2gtcmVwb3J0ZXInLCBuZXdPcHRzKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC8vIGRpYWdub3N0aWNNb2RlIHdpbGwgYmUgcmVtb3ZlZCBpbiBhIGZ1dHVyZSB2ZXJzaW9uXG4gICAgICAgICAgICBkaWFnbm9zdGljTW9kZSxcbiAgICAgICAgICAgIGRpYWdub3N0aWNzTW9kZTogZGlhZ25vc3RpY01vZGUsXG4gICAgICAgICAgICBpc1J1bm5pbmdcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGhleCBlbmNvZGVkIGhhc2ggb2YgdGhlIG1hY2hpbmUgaWQgYW5kIHRoZSBjdXJyZW50bHkgbG9nZ2VkIGluIHVzZXIgbmFtZS5cbiAgICAgKiBUaGlzIGlzIHRoZSByZWNvbW1lbmRlZCB3YXkgdG8gdW5pcXVlbHkgaWRlbnRpZnkgYSB1c2VyIC8gbWFjaGluZSBjb21iaW5hdGlvbi5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIEZvciBXaW5kb3dzIHN5c3RlbXMgdGhpcyBpcyBhIHNoYTI1NiBoYXNoIG9mIHRoZSBtYWNoaW5lIElEIHNldCBpbiB0aGUgcmVnaXN0cnkga2V5OlxuICAgICAqIGBIS0VZX0xPQ0FMX01BQ0hJTkVcXFNPRlRXQVJFXFxNaWNyb3NvZnRcXENyeXB0b2dyYXBoeVxcTWFjaGluZUd1aWRgIGFuZCBgVVNFUk5BTUVgLlxuICAgICAqXG4gICAgICogRm9yIE9TWCBzeXN0ZW1zLCBhIG5hdGl2ZS1sZXZlbCBjYWxsIGlzIHVzZWQgdG8gZ2V0IHRoZSBtYWNoaW5lIElELlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0VW5pcXVlVXNlcklkKCkudGhlbihpZCA9PiBjb25zb2xlLmxvZyhpZCkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRVbmlxdWVVc2VySWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXVuaXF1ZS11c2VyLWlkJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhIGZyYW1lIGluZm8gb2JqZWN0IGZvciB0aGUgdXVpZCBhbmQgbmFtZSBwYXNzZWQgaW5cbiAgICAgKiBAcGFyYW0gdXVpZCAtIFRoZSBVVUlEIG9mIHRoZSB0YXJnZXQuXG4gICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFyZ2V0LlxuICAgICAqXG4gICAgICogQHJlbWFya3MgVGhlIHBvc3NpYmxlIHR5cGVzIGFyZSAnd2luZG93JywgJ2lmcmFtZScsICdleHRlcm5hbCBjb25uZWN0aW9uJyBvciAndW5rbm93bicuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IGVudGl0eVV1aWQgPSAnT3BlbmZpblBPQyc7XG4gICAgICogY29uc3QgZW50aXR5TmFtZSA9ICc0MGM3NGI1ZC1lZDk4LTQwZjctODUzZi1lM2QzYzI2OTkxNzUnO1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0RW50aXR5SW5mbyhlbnRpdHlVdWlkLCBlbnRpdHlOYW1lKS50aGVuKGluZm8gPT4gY29uc29sZS5sb2coaW5mbykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKlxuICAgICAqIC8vIGV4YW1wbGUgaW5mbyBzaGFwZVxuICAgICAqIHtcbiAgICAgKiAgICAgXCJ1dWlkXCI6IFwiT3BlbmZpblBPQ1wiLFxuICAgICAqICAgICBcIm5hbWVcIjogXCI0MGM3NGI1ZC1lZDk4LTQwZjctODUzZi1lM2QzYzI2OTkxNzVcIixcbiAgICAgKiAgICAgXCJwYXJlbnRcIjoge1xuICAgICAqICAgICAgICAgXCJ1dWlkXCI6IFwiT3BlbmZpblBPQ1wiLFxuICAgICAqICAgICAgICAgXCJuYW1lXCI6IFwiT3BlbmZpblBPQ1wiXG4gICAgICogICAgIH0sXG4gICAgICogICAgIFwiZW50aXR5VHlwZVwiOiBcImlmcmFtZVwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldEVudGl0eUluZm8odXVpZCwgbmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1lbnRpdHktaW5mbycsIHsgdXVpZCwgbmFtZSB9KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgdmFsdWUgb2YgYSBnaXZlbiBlbnZpcm9ubWVudCB2YXJpYWJsZSBvbiB0aGUgY29tcHV0ZXIgb24gd2hpY2ggdGhlIHJ1bnRpbWUgaXMgaW5zdGFsbGVkXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRFbnZpcm9ubWVudFZhcmlhYmxlKCdIT01FJykudGhlbihlbnYgPT4gY29uc29sZS5sb2coZW52KSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldEVudmlyb25tZW50VmFyaWFibGUoZW52TmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlXG4gICAgICAgICAgICAuc2VuZEFjdGlvbignZ2V0LWVudmlyb25tZW50LXZhcmlhYmxlJywge1xuICAgICAgICAgICAgZW52aXJvbm1lbnRWYXJpYWJsZXM6IGVudk5hbWVcbiAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGN1cnJlbnRseSBmb2N1c2VkIFdpbmRvdy5cbiAgICAgKiBJZiBhIFZpZXcgY3VycmVudGx5IGhhcyBmb2N1cywgcmV0dXJucyB0aGUgaWRlbnRpdHkgb2YgVmlldydzIHBhcmVudCBXaW5kb3cuXG4gICAgICogVXNlIHtAbGluayBXaW5kb3cuX1dpbmRvdyNnZXRGb2N1c2VkQ29udGVudCBXaW5kb3cuZ2V0Rm9jdXNlZENvbnRlbnR9IHRvIGRpcmVjdGx5IGFjY2VzcyBjdXJyZW50bHkgZm9jdXNlZCBXaW5kb3cgb3IgVmlldy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldEZvY3VzZWRXaW5kb3coKS50aGVuKHdpbkluZm8gPT4gY29uc29sZS5sb2cod2luSW5mbykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRGb2N1c2VkV2luZG93KCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1mb2N1c2VkLXdpbmRvdycpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgY3VycmVudGx5IGZvY3VzZWQgY29udGVudC4gUmV0dXJucyBpZGVudGl0eSBvZiBlbnRpdHkgd2l0aCBgZW50aXR5VHlwZWAuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRGb2N1c2VkQ29udGVudCgpLnRoZW4oY29udGVudElkZW50aXR5ID0+IGNvbnNvbGUubG9nKGNvbnRlbnRJZGVudGl0eSkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRGb2N1c2VkQ29udGVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtZm9jdXNlZC1jb250ZW50JykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGdpdmVuIGFwcCdzIGNlcnRpZmljYXRpb24gc3RhdHVzXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgbWFuaWZlc3RVcmwgPSBcImh0dHA6Ly9sb2NhbGhvc3Q6MTIzNC9hcHAuanNvblwiXG4gICAgICogdHJ5IHtcbiAgICAgKiAgICAgY29uc3QgY2VydGlmaWNhdGlvbkluZm8gPSBhd2FpdCBmaW4uU3lzdGVtLmlzQXBwQ2VydGlmaWVkKG1hbmlmZXN0VXJsKTtcbiAgICAgKiB9IGNhdGNoKGVycikge1xuICAgICAqICAgICBjb25zb2xlLmVycm9yKGVycilcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgaXNBcHBDZXJ0aWZpZWQobWFuaWZlc3RVcmwpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkOiB7IGRhdGE6IHsgY2VydGlmaWVkSW5mbyB9IH0gfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpcy1hcHAtY2VydGlmaWVkJywgeyBtYW5pZmVzdFVybCB9KTtcbiAgICAgICAgcmV0dXJuIGNlcnRpZmllZEluZm87XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYW4gYXJyYXkgb2YgYWxsIHRoZSBpbnN0YWxsZWQgcnVudGltZSB2ZXJzaW9ucyBpbiBhbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRJbnN0YWxsZWRSdW50aW1lcygpLnRoZW4ocnVudGltZXMgPT4gY29uc29sZS5sb2cocnVudGltZXMpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgLy8gaW5jb21wYXRpYmxlIHdpdGggc3RhbmRhbG9uZSBub2RlIHByb2Nlc3MuXG4gICAgZ2V0SW5zdGFsbGVkUnVudGltZXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWluc3RhbGxlZC1ydW50aW1lcycpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEucnVudGltZXMpO1xuICAgIH1cbiAgICAvLyBpbmNvbXBhdGlibGUgd2l0aCBzdGFuZGFsb25lIG5vZGUgcHJvY2Vzcy5cbiAgICBhc3luYyBnZXRJbnN0YWxsZWRBcHBzKCkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgZGF0YTogeyBpbnN0YWxsZWRBcHBzIH0gfSB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1pbnN0YWxsZWQtYXBwcycpO1xuICAgICAgICByZXR1cm4gaW5zdGFsbGVkQXBwcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBjb250ZW50cyBvZiB0aGUgbG9nIHdpdGggdGhlIHNwZWNpZmllZCBmaWxlbmFtZS5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBBIG9iamVjdCB0aGF0IGlkIGRlZmluZWQgYnkgdGhlIEdldExvZ1JlcXVlc3RUeXBlIGludGVyZmFjZVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldExvZygpIHtcbiAgICAgKiAgICAgY29uc3QgbG9ncyA9IGF3YWl0IGZpbi5TeXN0ZW0uZ2V0TG9nTGlzdCgpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgZmluLlN5c3RlbS5nZXRMb2cobG9nc1swXSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZ2V0TG9nKCkudGhlbihsb2cgPT4gY29uc29sZS5sb2cobG9nKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldExvZyhvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigndmlldy1sb2cnLCBvcHRpb25zKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIHVuaXF1ZSBpZGVudGlmaWVyIChVVUlEKSBwcm92aWRlZCBieSB0aGUgbWFjaGluZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldE1hY2hpbmVJZCgpLnRoZW4oaWQgPT4gY29uc29sZS5sb2coaWQpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0TWFjaGluZUlkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1tYWNoaW5lLWlkJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG1pbmltdW0gKGluY2x1c2l2ZSkgbG9nZ2luZyBsZXZlbCB0aGF0IGlzIGN1cnJlbnRseSBiZWluZyB3cml0dGVuIHRvIHRoZSBsb2cuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRNaW5Mb2dMZXZlbCgpLnRoZW4obGV2ZWwgPT4gY29uc29sZS5sb2cobGV2ZWwpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0TWluTG9nTGV2ZWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LW1pbi1sb2ctbGV2ZWwnKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGFuIGFycmF5IGNvbnRhaW5pbmcgaW5mb3JtYXRpb24gZm9yIGVhY2ggbG9nIGZpbGUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRMb2dMaXN0KCkudGhlbihsb2dMaXN0ID0+IGNvbnNvbGUubG9nKGxvZ0xpc3QpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0TG9nTGlzdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdsaXN0LWxvZ3MnKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGFuIG9iamVjdCB0aGF0IGNvbnRhaW5zIGRhdGEgYWJvdXQgdGhlIG1vbml0b3Igc2V0dXAgb2YgdGhlXG4gICAgICogY29tcHV0ZXIgdGhhdCB0aGUgcnVudGltZSBpcyBydW5uaW5nIG9uLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0TW9uaXRvckluZm8oKS50aGVuKG1vbml0b3JJbmZvID0+IGNvbnNvbGUubG9nKG1vbml0b3JJbmZvKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldE1vbml0b3JJbmZvKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1tb25pdG9yLWluZm8nKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbW91c2UgaW4gdmlydHVhbCBzY3JlZW4gY29vcmRpbmF0ZXMgKGxlZnQsIHRvcCkuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRNb3VzZVBvc2l0aW9uKCkudGhlbihtb3VzZVBvc2l0aW9uID0+IGNvbnNvbGUubG9nKG1vdXNlUG9zaXRpb24pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0TW91c2VQb3NpdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtbW91c2UtcG9zaXRpb24nKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGFuIGFycmF5IG9mIGFsbCBvZiB0aGUgcnVudGltZSBwcm9jZXNzZXMgdGhhdCBhcmUgY3VycmVudGx5XG4gICAgICogcnVubmluZy4gRWFjaCBlbGVtZW50IGluIHRoZSBhcnJheSBpcyBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgdXVpZFxuICAgICAqIGFuZCB0aGUgbmFtZSBvZiB0aGUgYXBwbGljYXRpb24gdG8gd2hpY2ggdGhlIHByb2Nlc3MgYmVsb25ncy5cbiAgICAgKiBAZGVwcmVjYXRlZCBQbGVhc2UgdXNlIG91ciBuZXcgc2V0IG9mIHByb2Nlc3MgQVBJczpcbiAgICAgKiB7QGxpbmsgV2luZG93Ll9XaW5kb3cjZ2V0UHJvY2Vzc0luZm8gV2luZG93LmdldFByb2Nlc3NJbmZvfVxuICAgICAqIHtAbGluayBWaWV3LlZpZXcjZ2V0UHJvY2Vzc0luZm8gVmlldy5nZXRQcm9jZXNzSW5mb31cbiAgICAgKiB7QGxpbmsgQXBwbGljYXRpb24uQXBwbGljYXRpb24jZ2V0UHJvY2Vzc0luZm8gQXBwbGljYXRpb24uZ2V0UHJvY2Vzc0luZm99XG4gICAgICoge0BsaW5rIFN5c3RlbSNnZXRBbGxQcm9jZXNzSW5mbyBTeXN0ZW0uZ2V0QWxsUHJvY2Vzc0luZm99XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRQcm9jZXNzTGlzdCgpLnRoZW4oUHJvY2Vzc0xpc3QgPT4gY29uc29sZS5sb2coUHJvY2Vzc0xpc3QpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0UHJvY2Vzc0xpc3QoKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUud2FybignU3lzdGVtLmdldFByb2Nlc3NMaXN0IGhhcyBiZWVuIGRlcHJlY2F0ZWQuIFBsZWFzZSBjb25zaWRlciB1c2luZyBvdXIgbmV3IHByb2Nlc3MgQVBJczogV2luZG93LmdldFByb2Nlc3NJbmZvLCBWaWV3LmdldFByb2Nlc3NJbmZvLCBBcHBsaWNhdGlvbi5nZXRQcm9jZXNzSW5mbywgU3lzdGVtLmdldEFsbFByb2Nlc3NJbmZvJyk7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigncHJvY2Vzcy1zbmFwc2hvdCcpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYWxsIHByb2Nlc3MgaW5mb3JtYXRpb24uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBUaGlzIGluY2x1ZGVzIHRoZSBicm93c2VyIHByb2Nlc3MgYW5kIGV2ZXJ5IHByb2Nlc3MgYXNzb2NpYXRlZCB0byBhbGwgZW50aXRpZXMgKHdpbmRvd3MgYW5kIHZpZXdzKS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBhbGxQcm9jZXNzSW5mbyA9IGF3YWl0IGZpbi5TeXN0ZW0uZ2V0QWxsUHJvY2Vzc0luZm8oKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QWxsUHJvY2Vzc0luZm8oKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhIH0gfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtYWxsLXByb2Nlc3MtaW5mbycsIHRoaXMuaWRlbnRpdHkpO1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBQcm94eSBzZXR0aW5ncy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldFByb3h5U2V0dGluZ3MoKS50aGVuKFByb3h5U2V0dGluZyA9PiBjb25zb2xlLmxvZyhQcm94eVNldHRpbmcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICpcbiAgICAgKiAvL1RoaXMgcmVzcG9uc2UgaGFzIHRoZSBmb2xsb3dpbmcgc2hhcGU6XG4gICAgICoge1xuICAgICAqICAgICBjb25maWc6IHtcbiAgICAgKiAgICAgICAgIHByb3h5QWRkcmVzczogXCJwcm94eUFkZHJlc3NcIiwgLy90aGUgY29uZmlndXJlZCBQcm94eSBBZGRyZXNzXG4gICAgICogICAgICAgICBwcm94eVBvcnQ6IDAsIC8vdGhlIGNvbmZpZ3VyZWQgUHJveHkgcG9ydFxuICAgICAqICAgICAgICAgdHlwZTogXCJzeXN0ZW1cIiAvL1Byb3h5IFR5cGVcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgc3lzdGVtOiB7XG4gICAgICogICAgICAgICBhdXRvQ29uZmlnVXJsOiBcIlwiLFxuICAgICAqICAgICAgICAgYnlwYXNzOiBcIlwiLFxuICAgICAqICAgICAgICAgZW5hYmxlZDogZmFsc2UsXG4gICAgICogICAgICAgICBwcm94eTogXCJcIlxuICAgICAqICAgICB9XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldFByb3h5U2V0dGluZ3MoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXByb3h5LXNldHRpbmdzJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHJ1bm5pbmcgUnVudGltZSBpbiBhbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRSdW50aW1lSW5mbygpLnRoZW4oUnVudGltZUluZm8gPT4gY29uc29sZS5sb2coUnVudGltZUluZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0UnVudGltZUluZm8oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXJ1bnRpbWUtaW5mbycpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGluZm9ybWF0aW9uIGFib3V0IHRoZSBydW5uaW5nIFJWTSBpbiBhbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRSdm1JbmZvKCkudGhlbihSdm1JbmZvID0+IGNvbnNvbGUubG9nKFJ2bUluZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgLy8gaW5jb21wYXRpYmxlIHdpdGggc3RhbmRhbG9uZSBub2RlIHByb2Nlc3MuXG4gICAgZ2V0UnZtSW5mbygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtcnZtLWluZm8nKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGdlbmVyYWwgc3lzdGVtIGluZm9ybWF0aW9uLiBJZiB5b3UgbmVlZCBtb3JlIGRldGFpbGVkIGluZm9ybWF0aW9uIGFib3V0IHRoZVxuICAgICAqIE9TIGFuZCB0aGUgY3VycmVudGx5IGxvZ2dlZCBpbiB1c2VyLCB1c2UgYGZpbi5TeXN0ZW0uZ2V0T1NJbmZvKClgIGluc3RlYWQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRIb3N0U3BlY3MoKS50aGVuKHNwZWNzID0+IGNvbnNvbGUubG9nKHNwZWNzKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldEhvc3RTcGVjcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtaG9zdC1zcGVjcycpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIE9TIGFuZCB0aGUgY3VycmVudGx5IGxvZ2dlZCBpbiB1c2VyLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0T1NJbmZvKCkudGhlbihzcGVjcyA9PiBjb25zb2xlLmxvZyhzcGVjcykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRPU0luZm8oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LW9zLWluZm8nKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUnVucyBhbiBleGVjdXRhYmxlIG9yIGJhdGNoIGZpbGUuIEEgcGF0aCB0byB0aGUgZmlsZSBtdXN0IGJlIGluY2x1ZGVkIGluIG9wdGlvbnMuXG4gICAgICogPGJyPiBBIHV1aWQgbWF5IGJlIG9wdGlvbmFsbHkgcHJvdmlkZWQuIElmIG5vdCBwcm92aWRlZCwgT3BlbkZpbiB3aWxsIGNyZWF0ZSBhIHV1aWQgZm9yIHRoZSBuZXcgcHJvY2Vzcy5cbiAgICAgKiA8YnI+IE5vdGU6IFRoaXMgbWV0aG9kIGlzIHJlc3RyaWN0ZWQgYnkgZGVmYXVsdCBhbmQgbXVzdCBiZSBlbmFibGVkIHZpYVxuICAgICAqIDxhIGhyZWY9XCJodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9kb2NzL2FwaS1zZWN1cml0eVwiPkFQSSBzZWN1cml0eSBzZXR0aW5nczwvYT4uIEFsc28sIHRoaXMgYXBpIGhhcyBhbiBlbmhhbmNlZCBwZXJtaXNzaW9uIHNldCB0byBtYWtlIGl0IGxlc3MgZGFuZ2Vyb3VzLiBTbyBhcHBsaWNhdGlvbiBvd25lcnMgY2FuIG9ubHkgYWxsb3cgdG8gbGF1bmNoIHRoZSBhc3NldHMgb3duZWQgYnkgdGhlIGFwcGxpY2F0aW9uLCB0aGUgZW5hYmxlZCBkb3dubG9hZGVkIGZpbGVzIG9yIHRoZSByZXN0cmljdGVkIGV4ZWN1dGFibGVzLlxuICAgICAqIEBwYXJhbSBvcHRpb25zIEEgb2JqZWN0IHRoYXQgaXMgZGVmaW5lZCBpbiB0aGUgRXh0ZXJuYWxQcm9jZXNzUmVxdWVzdFR5cGUgaW50ZXJmYWNlXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBJZiBhbiB1bnVzZWQgVVVJRCBpcyBwcm92aWRlZCBpbiBvcHRpb25zLCBpdCB3aWxsIGJlIHVzZWQuIElmIG5vIFVVSUQgaXMgcHJvdmlkZWQsIE9wZW5GaW4gd2lsbCBhc3NpZ24gb25lLlxuICAgICAqIFRoaXMgYXBpIGhhcyBhbiBlbmhhbmNlZCBwZXJtaXNzaW9uIHNldCB0byBtYWtlIGl0IGxlc3MgZGFuZ2Vyb3VzLiBTbyBhcHBsaWNhdGlvbiBvd25lcnMgY2FuIG9ubHkgYWxsb3cgdG8gbGF1bmNoIHRoZVxuICAgICAqIGFzc2V0cyBvd25lZCBieSB0aGUgYXBwbGljYXRpb24sIHRoZSBlbmFibGVkIGRvd25sb2FkZWQgZmlsZXMgb3IgdGhlIHJlc3RyaWN0ZWQgZXhlY3V0YWJsZXMuXG4gICAgICpcbiAgICAgKiAqKk5vdGU6KiogU2luY2UgX2FwcEFzc2V0c18gcmVsaWVzIG9uIHRoZSBSVk0sIHdoaWNoIGlzIG1pc3Npbmcgb24gTUFDX09TLCAnYWxpYXMnIGlzIG5vdCBhdmFpbGFibGUuIEluc3RlYWQgcHJvdmlkZVxuICAgICAqIHRoZSBmdWxsIHBhdGggZS5nLiBfL0FwcGxpY2F0aW9ucy9DYWxjdWxhdG9yLmFwcC9Db250ZW50cy9NYWNPUy9DYWxjdWxhdG9yXy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogQmFzaWMgRXhhbXBsZTpcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKHtcbiAgICAgKiAgICAgcGF0aDogJ25vdGVwYWQnLFxuICAgICAqICAgICBhcmd1bWVudHM6ICcnLFxuICAgICAqICAgICBsaXN0ZW5lcjogZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ3RoZSBleGl0IGNvZGUnLCByZXN1bHQuZXhpdENvZGUpO1xuICAgICAqICAgICB9XG4gICAgICogfSkudGhlbihwcm9jZXNzSWRlbnRpdHkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhwcm9jZXNzSWRlbnRpdHkpO1xuICAgICAqIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coZXJyb3IpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogUHJvbWlzZSByZXNvbHV0aW9uOlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAvL1RoaXMgcmVzcG9uc2UgaGFzIHRoZSBmb2xsb3dpbmcgc2hhcGU6XG4gICAgICoge1xuICAgICAqICAgICB1dWlkOiBcIkZCM0U2RTM2LTA5NzYtNEMyQi05QTA5LUZCMkU1NEQyRjFCQlwiIC8vIFRoZSBtYXBwZWQgVVVJRCB3aGljaCBpZGVudGlmaWVzIHRoZSBsYXVuY2hlZCBwcm9jZXNzXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogTGlzdGVuZXIgY2FsbGJhY2s6XG4gICAgICogYGBganNcbiAgICAgKiAvL1RoaXMgcmVzcG9uc2UgaGFzIHRoZSBmb2xsb3dpbmcgc2hhcGU6XG4gICAgICoge1xuICAgICAqICAgICB0b3BpYzogXCJleGl0ZWRcIiwgLy8gT3IgXCJyZWxlYXNlZFwiIG9uIGEgY2FsbCB0byByZWxlYXNlRXh0ZXJuYWxQcm9jZXNzXG4gICAgICogICAgIHV1aWQ6IFwiRkIzRTZFMzYtMDk3Ni00QzJCLTlBMDktRkIyRTU0RDJGMUJCXCIsIC8vIFRoZSBtYXBwZWQgVVVJRCB3aGljaCBpZGVudGlmaWVzIHRoZSBsYXVuY2hlZCBwcm9jZXNzXG4gICAgICogICAgIGV4aXRDb2RlOiAwIC8vIFByb2Nlc3MgZXhpdCBjb2RlXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQnkgc3BlY2lmeWluZyBhIGxpZmV0aW1lLCBhbiBleHRlcm5hbCBwcm9jZXNzIGNhbiBsaXZlIGFzIGxvbmcgdGhlIHdpbmRvdy9hcHBsaWNhdGlvbiB0aGF0IGxhdW5jaGVkIGl0IG9yXG4gICAgICogcGVyc2lzdCBhZnRlciB0aGUgYXBwbGljYXRpb24gZXhpdHMuIFRoZSBkZWZhdWx0IHZhbHVlIGlzIG51bGwsIHdoaWNoIGlzIGVxdWl2YWxlbnQgdG8gJ3BlcnNpc3QnLCBtZWFuaW5nXG4gICAgICogdGhlIHByb2Nlc3MgbGl2ZXMgb24gYWZ0ZXIgdGhlIGFwcGxpY2F0aW9uIGV4aXRzOlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmxhdW5jaEV4dGVybmFsUHJvY2Vzcyh7XG4gICAgICogICAgIHBhdGg6ICdub3RlcGFkJyxcbiAgICAgKiAgICAgYXJndW1lbnRzOiAnJyxcbiAgICAgKiAgICAgbGlzdGVuZXI6IChyZXN1bHQpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCd0aGUgZXhpdCBjb2RlJywgcmVzdWx0LmV4aXRDb2RlKTtcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgbGlmZXRpbWU6ICd3aW5kb3cnXG4gICAgICogfSkudGhlbihwcm9jZXNzSWRlbnRpdHkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhwcm9jZXNzSWRlbnRpdHkpO1xuICAgICAqIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coZXJyb3IpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogTm90ZTogQSBwcm9jZXNzIHRoYXQgZXhpdHMgd2hlbiB0aGUgd2luZG93L2FwcGxpY2F0aW9uIGV4aXRzIGNhbm5vdCBiZSByZWxlYXNlZCB2aWEgZmluLmRlc2t0b3AuU3lzdGVtLnJlbGVhc2VFeHRlcm5hbFByb2Nlc3MuXG4gICAgICpcbiAgICAgKiBCeSBzcGVjaWZ5aW5nIGEgY3dkLCBpdCB3aWxsIHNldCBjdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5IHdoZW4gbGF1bmNoaW5nIGFuIGV4dGVybmFsIHByb2Nlc3M6XG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKHtcbiAgICAgKiAgICAgcGF0aDogJ2NtZC5leGUnLFxuICAgICAqICAgICBjd2Q6ICdjOlxcXFx0ZW1wJyxcbiAgICAgKiAgICAgYXJndW1lbnRzOiAnJyxcbiAgICAgKiAgICAgbGlzdGVuZXI6IChyZXN1bHQpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCd0aGUgZXhpdCBjb2RlJywgcmVzdWx0LmV4aXRDb2RlKTtcbiAgICAgKiAgICAgfVxuICAgICAqIH0pLnRoZW4ocHJvY2Vzc0lkZW50aXR5ID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2cocHJvY2Vzc0lkZW50aXR5KTtcbiAgICAgKiB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKGVycm9yKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEV4YW1wbGUgdXNpbmcgYW4gYWxpYXMgZnJvbSBhcHAuanNvbiBhcHBBc3NldHMgcHJvcGVydHk6XG4gICAgICpcbiAgICAgKiBgYGBqc29uXG4gICAgICogXCJhcHBBc3NldHNcIjogW1xuICAgICAqICAgICB7XG4gICAgICogICAgICAgICBcInNyY1wiOiBcImV4ZS56aXBcIixcbiAgICAgKiAgICAgICAgIFwiYWxpYXNcIjogXCJteUFwcFwiLFxuICAgICAqICAgICAgICAgXCJ2ZXJzaW9uXCI6IFwiNC4xMi44XCIsXG4gICAgICogICAgICAgICBcInRhcmdldFwiOiBcIm15QXBwLmV4ZVwiLFxuICAgICAqICAgICAgICAgXCJhcmdzXCI6IFwiYSBiIGMgZFwiXG4gICAgICogICAgIH0sXG4gICAgICogXVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAvLyAgV2hlbiBjYWxsZWQsIGlmIG5vIGFyZ3VtZW50cyBhcmUgcGFzc2VkIHRoZW4gdGhlIGFyZ3VtZW50cyAoaWYgYW55KVxuICAgICAqIC8vICBhcmUgdGFrZW4gZnJvbSB0aGUgJ2FwcC5qc29uJyBmaWxlLCBmcm9tIHRoZSAgJ2FyZ3MnIHBhcmFtZXRlclxuICAgICAqIC8vICBvZiB0aGUgJ2FwcEFzc2V0cycgT2JqZWN0IHdpdGggdGhlIHJlbGV2YW50ICdhbGlhcycuXG4gICAgICogZmluLlN5c3RlbS5sYXVuY2hFeHRlcm5hbFByb2Nlc3Moe1xuICAgICAqICAgICAvL0FkZGl0aW9uYWxseSBub3RlIHRoYXQgdGhlIGV4ZWN1dGFibGUgZm91bmQgaW4gdGhlIHppcCBmaWxlIHNwZWNpZmllZCBpbiBhcHBBc3NldHNcbiAgICAgKiAgICAgLy93aWxsIGRlZmF1bHQgdG8gdGhlIG9uZSBtZW50aW9uZWQgYnkgYXBwQXNzZXRzLnRhcmdldFxuICAgICAqICAgICAvL0lmIHRoZSB0aGUgcGF0aCBiZWxvdyByZWZlcnMgdG8gYSBzcGVjaWZpYyBwYXRoIGl0IHdpbGwgb3ZlcnJpZGUgdGhpcyBkZWZhdWx0XG4gICAgICogICAgIGFsaWFzOiAnbXlBcHAnLFxuICAgICAqICAgICBsaXN0ZW5lcjogKHJlc3VsdCkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ3RoZSBleGl0IGNvZGUnLCByZXN1bHQuZXhpdENvZGUpO1xuICAgICAqICAgICB9XG4gICAgICogfSkudGhlbihwcm9jZXNzSWRlbnRpdHkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhwcm9jZXNzSWRlbnRpdHkpO1xuICAgICAqIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coZXJyb3IpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogRXhhbXBsZSB1c2luZyBhbiBhbGlhcyBidXQgb3ZlcnJpZGluZyB0aGUgYXJndW1lbnRzOlxuICAgICAqXG4gICAgICogYGBganNvblxuICAgICAqIFwiYXBwQXNzZXRzXCI6IFtcbiAgICAgKiAgICAge1xuICAgICAqICAgICAgICAgXCJzcmNcIjogXCJleGUuemlwXCIsXG4gICAgICogICAgICAgICBcImFsaWFzXCI6IFwibXlBcHBcIixcbiAgICAgKiAgICAgICAgIFwidmVyc2lvblwiOiBcIjQuMTIuOFwiLFxuICAgICAqICAgICAgICAgXCJ0YXJnZXRcIjogXCJteUFwcC5leGVcIixcbiAgICAgKiAgICAgICAgIFwiYXJnc1wiOiBcImEgYiBjIGRcIlxuICAgICAqICAgICB9LFxuICAgICAqIF1cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogLy8gIElmICdhcmd1bWVudHMnIGlzIHBhc3NlZCBhcyBhIHBhcmFtZXRlciBpdCB0YWtlcyBwcmVjZWRlbmNlXG4gICAgICogLy8gIG92ZXIgYW55ICdhcmdzJyBzZXQgaW4gdGhlICdhcHAuanNvbicuXG4gICAgICogZmluLlN5c3RlbS5sYXVuY2hFeHRlcm5hbFByb2Nlc3Moe1xuICAgICAqICAgICBhbGlhczogJ215QXBwJyxcbiAgICAgKiAgICAgYXJndW1lbnRzOiAnZSBmIGcnLFxuICAgICAqICAgICBsaXN0ZW5lcjogKHJlc3VsdCkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ3RoZSBleGl0IGNvZGUnLCByZXN1bHQuZXhpdENvZGUpO1xuICAgICAqICAgICB9XG4gICAgICogfSkudGhlbihwcm9jZXNzSWRlbnRpdHkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhwcm9jZXNzSWRlbnRpdHkpO1xuICAgICAqIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coZXJyb3IpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogSXQgaXMgbm93IHBvc3NpYmxlIHRvIG9wdGlvbmFsbHkgcGVyZm9ybSBhbnkgY29tYmluYXRpb24gb2YgdGhlIGZvbGxvd2luZyBjZXJ0aWZpY2F0ZSBjaGVja3NcbiAgICAgKiBhZ2FpbnN0IGFuIGFic29sdXRlIHRhcmdldCB2aWEgYGZpbi5kZXNrdG9wLlN5c3RlbS5sYXVuY2hFeHRlcm5hbFByb2Nlc3MoKWA6XG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIFwiY2VydGlmaWNhdGVcIjoge1xuICAgICAqICAgICBcInNlcmlhbFwiOiBcIjNjIGE1IC4uLlwiLCAgICAgICAgICAgICAgICAgICAgICAgIC8vIEEgaGV4IHN0cmluZyB3aXRoIG9yIHdpdGhvdXQgc3BhY2VzXG4gICAgICogICAgIFwic3ViamVjdFwiOiBcIk89T3BlbkZpbiBJTkMuLCBMPU5ldyBZb3JrLCAuLi5cIiwgLy8gQW4gaW50ZXJuYWxseSB0b2tlbml6ZWQgYW5kIGNvbW1hIGRlbGltaXRlZCBzdHJpbmcgYWxsb3dpbmcgcGFydGlhbCBvciBmdWxsIGNoZWNrcyBvZiB0aGUgc3ViamVjdCBmaWVsZHNcbiAgICAgKiAgICAgXCJwdWJsaWNrZXlcIjogXCIzYyBhNSAuLi5cIiwgICAgICAgICAgICAgICAgICAgICAvLyBBIGhleCBzdHJpbmcgd2l0aCBvciB3aXRob3V0IHNwYWNlc1xuICAgICAqICAgICBcInRodW1icHJpbnRcIjogXCIzYyBhNSAuLi5cIiwgICAgICAgICAgICAgICAgICAgIC8vIEEgaGV4IHN0cmluZyB3aXRoIG9yIHdpdGhvdXQgc3BhY2VzXG4gICAgICogICAgIFwidHJ1c3RlZFwiOiB0cnVlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEEgYm9vbGVhbiBpbmRpY2F0aW5nIHRoYXQgdGhlIGNlcnRpZmljYXRlIGlzIHRydXN0ZWQgYW5kIG5vdCByZXZva2VkXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogUHJvdmlkaW5nIHRoaXMgaW5mb3JtYXRpb24gYXMgcGFydCBvZiB0aGUgZGVmYXVsdCBjb25maWd1cmF0aW9ucyBmb3IgYXNzZXRzIGluIGFuIGFwcGxpY2F0aW9uJ3MgbWFuaWZlc3RcbiAgICAgKiB3aWxsIGJlIGFkZGVkIGluIGEgZnV0dXJlIFJWTSB1cGRhdGU6XG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKHtcbiAgICAgKiAgICAgcGF0aDogJ0M6XFxcXFVzZXJzXFxcXEV4YW1wbGVVc2VyXFxcXEFwcERhdGFcXFxcTG9jYWxcXFxcT3BlbkZpblxcXFxPcGVuRmluUlZNLmV4ZScsXG4gICAgICogICAgIGFyZ3VtZW50czogJy0tdmVyc2lvbicsXG4gICAgICogICAgIGNlcnRpZmljYXRlOiB7XG4gICAgICogICAgICAgICB0cnVzdGVkOiB0cnVlLFxuICAgICAqICAgICAgICAgc3ViamVjdDogJ089T3BlbkZpbiBJTkMuLCBMPU5ldyBZb3JrLCBTPU5ZLCBDPVVTJyxcbiAgICAgKiAgICAgICAgIHRodW1icHJpbnQ6ICfigI4zYyBhNSAyOCAxOSA4MyAwNSBmZSA2OSA4OCBlNiA4ZiA0YiAzYSBhZiBjNSBjNSAxYiAwNyA4MCA1YidcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgbGlzdGVuZXI6IChyZXN1bHQpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCd0aGUgZXhpdCBjb2RlJywgcmVzdWx0LmV4aXRDb2RlKTtcbiAgICAgKiAgICAgfVxuICAgICAqIH0pLnRoZW4ocHJvY2Vzc0lkZW50aXR5ID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2cocHJvY2Vzc0lkZW50aXR5KTtcbiAgICAgKiB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKGVycm9yKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEl0IGlzIHBvc3NpYmxlIHRvIGxhdW5jaCBmaWxlcyB0aGF0IGhhdmUgYmVlbiBkb3dubG9hZGVkIGJ5IHRoZSB1c2VyIGJ5IGxpc3RlbmluZyB0byB0aGUgd2luZG93XG4gICAgICogYGZpbGUtZG93bmxvYWQtY29tcGxldGVkYCBldmVudCBhbmQgdXNpbmcgdGhlIGBmaWxlVXVpZGAgcHJvdmlkZWQgYnkgdGhlIGV2ZW50OlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCB3aW4gPSBmaW4uV2luZG93LmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogd2luLmFkZExpc3RlbmVyKCdmaWxlLWRvd25sb2FkLWNvbXBsZXRlZCcsIChldnQpID0+IHtcbiAgICAgKiAgICAgaWYgKGV2dC5zdGF0ZSA9PT0gJ2NvbXBsZXRlZCcpIHtcbiAgICAgKiAgICAgICAgIGZpbi5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKHtcbiAgICAgKiAgICAgICAgICAgICBmaWxlVXVpZDogZXZ0LmZpbGVVdWlkLFxuICAgICAqICAgICAgICAgICAgIGFyZ3VtZW50czogJycsXG4gICAgICogICAgICAgICAgICAgbGlzdGVuZXI6IChyZXN1bHQpID0+IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ3RoZSBleGl0IGNvZGUnLCByZXN1bHQuZXhpdENvZGUpO1xuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgIH0pLnRoZW4ocHJvY2Vzc0lkZW50aXR5ID0+IHtcbiAgICAgKiAgICAgICAgICAgICBjb25zb2xlLmxvZyhwcm9jZXNzSWRlbnRpdHkpO1xuICAgICAqICAgICAgICAgfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAqICAgICAgICAgICAgIGNvbnNvbGUubG9nKGVycm9yKTtcbiAgICAgKiAgICAgICAgIH0pO1xuICAgICAqICAgICB9XG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBMYXVuY2hpbmcgYXNzZXRzIHNwZWNpZmllZCBpbiB0aGUgYXBwIG1hbmlmZXN0OlxuICAgICAqXG4gICAgICogU2FtcGxlIGFwcEFzc2V0cyBzZWN0aW9uIGluIGFwcC5qc29uXG4gICAgICogYGBganNcbiAgICAgKiAgICAgXCJhcHBBc3NldHNcIjogW1xuICAgICAqICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgIFwic3JjXCI6IFwiaHR0cDovL2ZpbGVzYW1wbGVzLmNvbS9leGUuemlwXCIsXG4gICAgICogICAgICAgICAgICAgXCJhbGlhc1wiOiBcIm15QXBwXCIsXG4gICAgICogICAgICAgICAgICAgXCJ2ZXJzaW9uXCI6IFwiNC4xMi44XCIsXG4gICAgICogICAgICAgICAgICAgXCJ0YXJnZXRcIjogXCJteUFwcC5leGVcIixcbiAgICAgKiAgICAgICAgICAgICBcImFyZ3NcIjogXCJhIGIgYyBkXCJcbiAgICAgKiAgICAgICAgIH0sXG4gICAgICogICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgXCJzcmNcIjogXCJodHRwOi8vZXhhbXBsZXMuY29tL2V4ZS56aXBcIixcbiAgICAgKiAgICAgICAgICAgICBcImFsaWFzXCI6IFwibXlBcHAyXCIsXG4gICAgICogICAgICAgICAgICAgXCJ2ZXJzaW9uXCI6IFwiNS4xMi44XCIsXG4gICAgICogICAgICAgICAgICAgXCJ0YXJnZXRcIjogXCJteUFwcDIuZXhlXCIsXG4gICAgICogICAgICAgICAgICAgXCJhcmdzXCI6IFwiYSBiIGNcIlxuICAgICAqICAgICAgICAgfVxuICAgICAqICAgICBdXG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBUaGlzIHBlcm1pc3Npb24gYWxsb3dzIGZvciBsYXVuY2hpbmcgb2YgYWxsIGFzc2V0cyBzcGVjaWZpZWQgaW4gdGhlIGFib3ZlIGFwcEFzc2V0cyBzZWN0aW9uLiAoXCJteUFwcFwiIGFuZCBcIm15QXBwMlwiKTpcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogICAgIFwicGVybWlzc2lvbnNcIjoge1xuICAgICAqICAgICAgICBcIlN5c3RlbVwiOiB7XG4gICAgICogICAgICAgICAgICBcImxhdW5jaEV4dGVybmFsUHJvY2Vzc1wiOiB7XG4gICAgICogICAgICAgICAgICAgICAgIFwiZW5hYmxlZFwiOiB0cnVlLFxuICAgICAqICAgICAgICAgICAgICAgICBcImFzc2V0c1wiOiB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICBcImVuYWJsZWRcIjogdHJ1ZVxuICAgICAqICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgfVxuICAgICAqICAgICAgICB9XG4gICAgICogICAgIH1cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFRoaXMgcGVybWlzc2lvbiBhbGxvd3MgZm9yIGxhdW5jaGluZyBvZiBfb25seV8gdGhlIFwibXlBcHBcIiBhc3NldCBpbiB0aGUgYWJvdmUgYXBwQXNzZXRzIHNlY3Rpb24sIGFzIGRlZmluZWQgaW4gYHNyY1J1bGVzYDpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBcInBlcm1pc3Npb25zXCI6IHtcbiAgICAgKiAgICAgICAgXCJTeXN0ZW1cIjoge1xuICAgICAqICAgICAgICAgICAgXCJsYXVuY2hFeHRlcm5hbFByb2Nlc3NcIjoge1xuICAgICAqICAgICAgICAgICAgICAgICBcImVuYWJsZWRcIjogdHJ1ZSxcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJhc3NldHNcIjoge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgXCJlbmFibGVkXCI6IHRydWVcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIFwic3JjUnVsZXNcIjogW1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJtYXRjaFwiOiBbXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIio6Ly9maWxlc2FtcGxlcy5jb20vKlwiXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYmVoYXZpb3JcIjogXCJhbGxvd1wiXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwibWF0Y2hcIjogW1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI8YWxsX3VybHM+XCJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJiZWhhdmlvclwiOiBcImJsb2NrXCJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICBdXG4gICAgICogICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgIH1cbiAgICAgKiAgICAgfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogTGF1bmNoaW5nIGRvd25sb2FkZWQgZmlsZXM6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgXCJwZXJtaXNzaW9uc1wiOiB7XG4gICAgICogICAgICAgIFwiU3lzdGVtXCI6IHtcbiAgICAgKiAgICAgICAgICAgIFwibGF1bmNoRXh0ZXJuYWxQcm9jZXNzXCI6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJlbmFibGVkXCI6IHRydWUsXG4gICAgICogICAgICAgICAgICAgICAgIFwiZG93bmxvYWRzXCI6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIFwiZW5hYmxlZFwiOiB0cnVlXG4gICAgICogICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgIH1cbiAgICAgKiAgICAgfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogVGhpcyBwZXJtaXNzaW9uIGFsbG93cyB0byBsYXVuY2ggYWxsIHRoZSBleGVjdXRhYmxlczpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBcInBlcm1pc3Npb25zXCI6IHtcbiAgICAgKiAgICAgICAgXCJTeXN0ZW1cIjoge1xuICAgICAqICAgICAgICAgICAgXCJsYXVuY2hFeHRlcm5hbFByb2Nlc3NcIjoge1xuICAgICAqICAgICAgICAgICAgICAgICBcImVuYWJsZWRcIjogdHJ1ZSxcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJleGVjdXRhYmxlc1wiOiB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICBcImVuYWJsZWRcIjogdHJ1ZVxuICAgICAqICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgfVxuICAgICAqICAgICAgICB9XG4gICAgICogICAgIH1cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqXG4gICAgICogVGhpcyBwZXJtaXNzaW9uIG9ubHkgYWxsb3dzIGxhdW5jaGluZyBvZiBleGVjdXRhYmxlcyB3aG9zZSBmaWxlIHBhdGhzIG1hdGNoIHRoZSBjb3JyZXNwb25kaW5nIGBwYXRoUnVsZXNgOlxuICAgICAqIGBgYGpzXG4gICAgICogICAgIFwicGVybWlzc2lvbnNcIjoge1xuICAgICAqICAgICAgICBcIlN5c3RlbVwiOiB7XG4gICAgICogICAgICAgICAgICBcImxhdW5jaEV4dGVybmFsUHJvY2Vzc1wiOiB7XG4gICAgICogICAgICAgICAgICAgICAgIFwiZW5hYmxlZFwiOiB0cnVlLFxuICAgICAqICAgICAgICAgICAgICAgICBcImV4ZWN1dGFibGVzXCI6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIFwiZW5hYmxlZFwiOiB0cnVlXG4gICAgICogICAgICAgICAgICAgICAgICAgICBcInBhdGhSdWxlc1wiOiBbXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIm1hdGNoXCI6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiL1dpbmRvd3MvU3lzdGVtMzIvKi5leGVcIlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJlaGF2aW9yXCI6IFwiYWxsb3dcIlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIm1hdGNoXCI6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiKi5leGVcIlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJlaGF2aW9yXCI6IFwiYmxvY2tcIlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIF1cbiAgICAgKiAgICAgICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgfVxuICAgICAqICAgICB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgbGF1bmNoRXh0ZXJuYWxQcm9jZXNzKG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VuZEV4dGVybmFsUHJvY2Vzc1JlcXVlc3QoJ2xhdW5jaC1leHRlcm5hbC1wcm9jZXNzJywgb3B0aW9ucyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE1vbml0b3JzIGEgcnVubmluZyBwcm9jZXNzLiBBIHBpZCBmb3IgdGhlIHByb2Nlc3MgbXVzdCBiZSBpbmNsdWRlZCBpbiBvcHRpb25zLlxuICAgICAqIDxicj4gQSB1dWlkIG1heSBiZSBvcHRpb25hbGx5IHByb3ZpZGVkLiBJZiBub3QgcHJvdmlkZWQsIE9wZW5GaW4gd2lsbCBjcmVhdGUgYSB1dWlkIGZvciB0aGUgbmV3IHByb2Nlc3MuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBJZiBhbiB1bnVzZWQgdXVpZCBpcyBwcm92aWRlZCBpbiBvcHRpb25zLCBpdCB3aWxsIGJlIHVzZWQuIElmIG5vIHV1aWQgaXMgcHJvdmlkZWQsIE9wZWZpbkZpbiB3aWxsIGFzc2lnbiBhIHV1aWQuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ubW9uaXRvckV4dGVybmFsUHJvY2Vzcyh7XG4gICAgICogICAgIHBpZDogMTAyMDgsXG4gICAgICogICAgIHV1aWQ6ICdteS1leHRlcm5hbC1wcm9jZXNzJywgLy8gb3B0aW9uYWxcbiAgICAgKiAgICAgbGlzdGVuZXI6IGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCd0aGUgZXhpdCBjb2RlJywgcmVzdWx0LmV4aXRDb2RlKTtcbiAgICAgKiAgICAgfVxuICAgICAqIH0pLnRoZW4ocHJvY2Vzc0lkZW50aXR5ID0+IGNvbnNvbGUubG9nKHByb2Nlc3NJZGVudGl0eSkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBtb25pdG9yRXh0ZXJuYWxQcm9jZXNzKG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VuZEV4dGVybmFsUHJvY2Vzc1JlcXVlc3QoJ21vbml0b3ItZXh0ZXJuYWwtcHJvY2VzcycsIG9wdGlvbnMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgdGhlIHBhc3NlZCBtZXNzYWdlIGludG8gYm90aCB0aGUgbG9nIGZpbGUgYW5kIHRoZSBjb25zb2xlLlxuICAgICAqIEBwYXJhbSBsZXZlbCBUaGUgbG9nIGxldmVsIGZvciB0aGUgZW50cnkuIENhbiBiZSBlaXRoZXIgXCJpbmZvXCIsIFwid2FybmluZ1wiIG9yIFwiZXJyb3JcIlxuICAgICAqIEBwYXJhbSBtZXNzYWdlIFRoZSBsb2cgbWVzc2FnZSB0ZXh0XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5sb2coXCJpbmZvXCIsIFwiQW4gZXhhbXBsZSBsb2cgbWVzc2FnZVwiKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdMb2cgaW5mbyBtZXNzYWdlJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBsb2cobGV2ZWwsIG1lc3NhZ2UpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd3cml0ZS10by1sb2cnLCB7IGxldmVsLCBtZXNzYWdlIH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogT3BlbnMgdGhlIHBhc3NlZCBVUkwgaW4gdGhlIGRlZmF1bHQgd2ViIGJyb3dzZXIuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBJdCBvbmx5IHN1cHBvcnRzIGh0dHAocykgYW5kIGZpbihzKSBwcm90b2NvbHMgYnkgZGVmYXVsdC5cbiAgICAgKiBJbiBvcmRlciB0byB1c2Ugb3RoZXIgY3VzdG9tIHByb3RvY29scywgdGhleSBoYXZlIHRvIGJlIGVuYWJsZWQgdmlhXG4gICAgICogW0FQSSBzZWN1cml0eSBzZXR0aW5nc10oaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5maW4uY28vZG9jcy9hcGktc2VjdXJpdHkpLlxuICAgICAqIEZpbGUgcHJvdG9jb2wgYW5kIGZpbGUgcGF0aCBhcmUgbm90IHN1cHBvcnRlZC5cbiAgICAgKiBAcGFyYW0gdXJsIFRoZSBVUkwgdG8gb3BlblxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ub3BlblVybFdpdGhCcm93c2VyKCdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtU3lzdGVtLm9wZW5VcmxXaXRoQnJvd3Nlci5odG1sJylcbiAgICAgKiAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnT3BlbmVkIFVSTCcpKVxuICAgICAqIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBFeGFtcGxlIG9mIHBlcm1pc3Npb24gZGVmaW5pdGlvbiB0byBlbmFibGUgbm9uLWRlZmF1bHQgcHJvdG9jb2xzOlxuICAgICAqXG4gICAgICogTm90ZTogcGVybWlzc2lvbiBkZWZpbml0aW9uIHNob3VsZCBiZSBzcGVjaWZpZWQgaW4gYW4gYXBwIG1hbmlmZXN0IGZpbGUgaWYgdGhlcmUgaXMgbm8gRE9TIHNldHRpbmdzLlxuICAgICAqIE90aGVyd2lzZSBpdCBoYXMgdG8gYmUgc3BlY2lmaWVkIGluIGJvdGggRE9TIGFuZCBhcHAgbWFuaWZlc3QgZmlsZXMuXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBcInBlcm1pc3Npb25zXCI6IHtcbiAgICAgKiAgICAgICAgXCJTeXN0ZW1cIjoge1xuICAgICAqICAgICAgICAgICAgXCJvcGVuVXJsV2l0aEJyb3dzZXJcIjoge1xuICAgICAqICAgICAgICAgICAgICAgICBcImVuYWJsZWRcIjogdHJ1ZSxcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJwcm90b2NvbHNcIjogWyBcIm1zdGVhbXNcIiwgXCJzbGFja1wiXVxuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgfVxuICAgICAqICAgICB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgb3BlblVybFdpdGhCcm93c2VyKHVybCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ29wZW4tdXJsLXdpdGgtYnJvd3NlcicsIHsgdXJsIH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyByZWdpc3RyeSBlbnRyeSB1bmRlciB0aGUgSEtDVSByb290IFdpbmRvd3MgcmVnaXN0cnkga2V5IGlmIHRoZSBnaXZlbiBjdXN0b20gcHJvdG9jb2wgbmFtZSBkb2Vzbid0IGV4aXN0IG9yXG4gICAgICogb3ZlcndyaXRlcyB0aGUgZXhpc3RpbmcgcmVnaXN0cnkgZW50cnkgaWYgdGhlIGdpdmVuIGN1c3RvbSBwcm90b2NvbCBuYW1lIGFscmVhZHkgZXhpc3RzLlxuICAgICAqXG4gICAgICogTm90ZTogVGhpcyBtZXRob2QgaXMgcmVzdHJpY3RlZCBieSBkZWZhdWx0IGFuZCBtdXN0IGJlIGVuYWJsZWQgdmlhXG4gICAgICoge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvYXBpLXNlY3VyaXR5IEFQSSBzZWN1cml0eSBzZXR0aW5nc30uIEl0IHJlcXVpcmVzIFJWTSAxMiBvciBoaWdoZXIgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqXG4gICAgICogQHJlbWFya3MgVGhlc2UgcHJvdG9jb2xzIGFyZSByZXNlcnZlZCBhbmQgY2Fubm90IGJlIHJlZ2lzdGVyZWQ6XG4gICAgICogLSBmaW5cbiAgICAgKiAtIGZpbnNcbiAgICAgKiAtIG9wZW5maW5cbiAgICAgKiAtIFVSSSBTY2hlbWVzIHJlZ2lzdGVyZWQgd2l0aCB7QGxpbmsgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGlzdF9vZl9VUklfc2NoZW1lcyNPZmZpY2lhbF9JQU5BLXJlZ2lzdGVyZWRfc2NoZW1lcyBJQU5BfVxuICAgICAqXG4gICAgICogQHRocm93cyBpZiBhIGdpdmVuIGN1c3RvbSBwcm90b2NvbCBmYWlsZWQgdG8gYmUgcmVnaXN0ZXJlZC5cbiAgICAgKiBAdGhyb3dzIGlmIGEgbWFuaWZlc3QgVVJMIGNvbnRhaW5zIHRoZSAnJTEnIHN0cmluZy5cbiAgICAgKiBAdGhyb3dzIGlmIGEgbWFuaWZlc3QgVVJMIGNvbnRhaW5zIGEgcXVlcnkgc3RyaW5nIHBhcmFtZXRlciB3aGljaCBuYW1lIGVxdWFscyB0byB0aGUgUHJvdG9jb2wgTGF1bmNoIFJlcXVlc3QgUGFyYW1ldGVyIE5hbWUuXG4gICAgICogQHRocm93cyBpZiB0aGUgZnVsbCBsZW5ndGggb2YgdGhlIGNvbW1hbmQgc3RyaW5nIHRoYXQgaXMgdG8gYmUgd3JpdHRlbiB0byB0aGUgcmVnaXN0cnkgZXhjZWVkcyAyMDQ4IGJ5dGVzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ucmVnaXN0ZXJDdXN0b21Qcm90b2NvbCh7cHJvdG9jb2xOYW1lOidwcm90b2NvbDEnfSkudGhlbihjb25zb2xlLmxvZykuY2F0Y2goY29uc29sZS5lcnJvcik7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgcmVnaXN0ZXJDdXN0b21Qcm90b2NvbChvcHRpb25zKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucyAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTXVzdCBwcm92aWRlIGFuIG9iamVjdCB3aXRoIGEgYHByb3RvY29sTmFtZWAgcHJvcGVydHkgaGF2aW5nIGEgc3RyaW5nIHZhbHVlLicpO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdyZWdpc3Rlci1jdXN0b20tcHJvdG9jb2wnLCBvcHRpb25zKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgcmVnaXN0cnkgZW50cnkgZm9yIGEgZ2l2ZW4gY3VzdG9tIHByb3RvY29sLlxuICAgICAqXG4gICAgICogTm90ZTogVGhpcyBtZXRob2QgaXMgcmVzdHJpY3RlZCBieSBkZWZhdWx0IGFuZCBtdXN0IGJlIGVuYWJsZWQgdmlhXG4gICAgICoge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvYXBpLXNlY3VyaXR5IEFQSSBzZWN1cml0eSBzZXR0aW5nc30uIEl0IHJlcXVpcmVzIFJWTSAxMiBvciBoaWdoZXIgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqXG4gICAgICogQHJlbWFya3MgVGhlc2UgcHJvdG9jb2xzIGFyZSByZXNlcnZlZCBhbmQgY2Fubm90IGJlIHVucmVnaXN0ZXJlZDpcbiAgICAgKiAtIGZpblxuICAgICAqIC0gZmluc1xuICAgICAqIC0gb3BlbmZpblxuICAgICAqIC0gVVJJIFNjaGVtZXMgcmVnaXN0ZXJlZCB3aXRoIHtAbGluayBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaXN0X29mX1VSSV9zY2hlbWVzI09mZmljaWFsX0lBTkEtcmVnaXN0ZXJlZF9zY2hlbWVzIElBTkF9XG4gICAgICpcbiAgICAgKiBAdGhyb3dzIGlmIGEgcHJvdG9jb2wgZW50cnkgZmFpbGVkIHRvIGJlIHJlbW92ZWQgaW4gcmVnaXN0cnkuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogYXdhaXQgZmluLlN5c3RlbS51bnJlZ2lzdGVyQ3VzdG9tUHJvdG9jb2woJ3Byb3RvY29sMScpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHVucmVnaXN0ZXJDdXN0b21Qcm90b2NvbChwcm90b2NvbE5hbWUpIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3VucmVnaXN0ZXItY3VzdG9tLXByb3RvY29sJywgeyBwcm90b2NvbE5hbWUgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgcmVnaXN0cmF0aW9uIHN0YXRlIGZvciBhIGdpdmVuIGN1c3RvbSBwcm90b2NvbC5cbiAgICAgKlxuICAgICAqIE5vdGU6IFRoaXMgbWV0aG9kIGlzIHJlc3RyaWN0ZWQgYnkgZGVmYXVsdCBhbmQgbXVzdCBiZSBlbmFibGVkIHZpYVxuICAgICAqIHtAbGluayBodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9kb2NzL2FwaS1zZWN1cml0eSBBUEkgc2VjdXJpdHkgc2V0dGluZ3N9LiBJdCByZXF1aXJlcyBSVk0gMTIgb3IgaGlnaGVyIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBUaGVzZSBwcm90b2NvbHMgYXJlIHJlc2VydmVkIGFuZCBjYW5ub3QgZ2V0IHN0YXRlcyBmb3IgdGhlbTpcbiAgICAgKiAtIGZpblxuICAgICAqIC0gZmluc1xuICAgICAqIC0gb3BlbmZpblxuICAgICAqIC0gVVJJIFNjaGVtZXMgcmVnaXN0ZXJlZCB3aXRoIHtAbGluayBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaXN0X29mX1VSSV9zY2hlbWVzI09mZmljaWFsX0lBTkEtcmVnaXN0ZXJlZF9zY2hlbWVzIElBTkF9XG4gICAgICpcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwcm90b2NvbFN0YXRlID0gYXdhaXQgZmluLlN5c3RlbS5nZXRDdXN0b21Qcm90b2NvbFN0YXRlKCdwcm90b2NvbDEnKTtcbiAgICAgKi9cbiAgICBhc3luYyBnZXRDdXN0b21Qcm90b2NvbFN0YXRlKHByb3RvY29sTmFtZSkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1jdXN0b20tcHJvdG9jb2wtc3RhdGUnLCB7IHByb3RvY29sTmFtZSB9KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyB0aGUgcHJvY2VzcyBlbnRyeSBmb3IgdGhlIHBhc3NlZCBVVUlEIG9idGFpbmVkIGZyb20gYSBwcmlvciBjYWxsXG4gICAgICogb2YgZmluLlN5c3RlbS5sYXVuY2hFeHRlcm5hbFByb2Nlc3MoKS5cbiAgICAgKiBAcGFyYW0gdXVpZCBUaGUgVVVJRCBmb3IgYSBwcm9jZXNzIG9idGFpbmVkIGZyb20gYSBwcmlvciBjYWxsIHRvIGZpbi5kZXNrdG9wLlN5c3RlbS5sYXVuY2hFeHRlcm5hbFByb2Nlc3MoKVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKHtcbiAgICAgKiAgICAgcGF0aDogXCJub3RlcGFkXCIsXG4gICAgICogICAgIGxpc3RlbmVyOiBmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhcIlRoZSBleGl0IGNvZGVcIiwgcmVzdWx0LmV4aXRDb2RlKTtcbiAgICAgKiAgICAgfVxuICAgICAqIH0pXG4gICAgICogLnRoZW4oaWRlbnRpdHkgPT4gZmluLlN5c3RlbS5yZWxlYXNlRXh0ZXJuYWxQcm9jZXNzKGlkZW50aXR5LnV1aWQpKVxuICAgICAqIC50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdQcm9jZXNzIGhhcyBiZWVuIHVubWFwcGVkIScpKVxuICAgICAqIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcmVsZWFzZUV4dGVybmFsUHJvY2Vzcyh1dWlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigncmVsZWFzZS1leHRlcm5hbC1wcm9jZXNzJywgeyB1dWlkIH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2hvd3MgdGhlIENocm9taXVtIERldmVsb3BlciBUb29scyBmb3IgdGhlIHNwZWNpZmllZCB3aW5kb3dcbiAgICAgKiBAcGFyYW0gaWRlbnRpdHkgVGhpcyBpcyBhIG9iamVjdCB0aGF0IGlzIGRlZmluZWQgYnkgdGhlIElkZW50aXR5IGludGVyZmFjZVxuICAgICAqXG4gICAgICogQHR1dG9yaWFsIFN5c3RlbS5zaG93RGV2ZWxvcGVyVG9vbHNcbiAgICAgKi9cbiAgICBzaG93RGV2ZWxvcGVyVG9vbHMoaWRlbnRpdHkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzaG93LWRldmVsb3Blci10b29scycsIGlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEF0dGVtcHQgdG8gY2xvc2UgYW4gZXh0ZXJuYWwgcHJvY2Vzcy4gVGhlIHByb2Nlc3Mgd2lsbCBiZSB0ZXJtaW5hdGVkIGlmIGl0XG4gICAgICogaGFzIG5vdCBjbG9zZWQgYWZ0ZXIgdGhlIGVsYXBzZWQgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuXG4gICAgICpcbiAgICAgKiBOb3RlOiBUaGlzIG1ldGhvZCBpcyByZXN0cmljdGVkIGJ5IGRlZmF1bHQgYW5kIG11c3QgYmUgZW5hYmxlZCB2aWFcbiAgICAgKiA8YSBocmVmPVwiaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5maW4uY28vZG9jcy9hcGktc2VjdXJpdHlcIj5BUEkgc2VjdXJpdHkgc2V0dGluZ3M8L2E+LlxuICAgICAqIEBwYXJhbSBvcHRpb25zIEEgb2JqZWN0IGRlZmluZWQgaW4gdGhlIFRlcm1pbmF0ZUV4dGVybmFsUmVxdWVzdFR5cGUgaW50ZXJmYWNlXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5sYXVuY2hFeHRlcm5hbFByb2Nlc3Moe1xuICAgICAqICAgICBwYXRoOiBcIm5vdGVwYWRcIixcbiAgICAgKiAgICAgbGlzdGVuZXI6IGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKFwiVGhlIGV4aXQgY29kZVwiLCByZXN1bHQuZXhpdENvZGUpO1xuICAgICAqICAgICB9XG4gICAgICogfSlcbiAgICAgKiAudGhlbihpZGVudGl0eSA9PiBmaW4uU3lzdGVtLnRlcm1pbmF0ZUV4dGVybmFsUHJvY2Vzcyh7dXVpZDogaWRlbnRpdHkudXVpZCwgdGltZW91dDoyMDAwLCBraWxsVHJlZTogZmFsc2V9KSlcbiAgICAgKiAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnVGVybWluYXRlIHRoZSBwcm9jZXNzJykpXG4gICAgICogLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICB0ZXJtaW5hdGVFeHRlcm5hbFByb2Nlc3Mob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Rlcm1pbmF0ZS1leHRlcm5hbC1wcm9jZXNzJywgb3B0aW9ucykudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIE9wZW5GaW4gUnVudGltZSBQcm94eSBzZXR0aW5ncy5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBBIGNvbmZpZyBvYmplY3QgZGVmaW5lZCBpbiB0aGUgUHJveHlDb25maWcgaW50ZXJmYWNlXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS51cGRhdGVQcm94eVNldHRpbmdzKHtwcm94eUFkZHJlc3M6JzEyNy4wLjAuMScsIHByb3h5UG9ydDo4MDgwLCB0eXBlOidodHRwJ30pXG4gICAgICogLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1VwZGF0ZSBwcm94eSBzdWNjZXNzZnVsbHknKSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUuZXJyb3IoZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgdXBkYXRlUHJveHlTZXR0aW5ncyhvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigndXBkYXRlLXByb3h5Jywgb3B0aW9ucykudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBEb3dubG9hZHMgdGhlIGdpdmVuIGFwcGxpY2F0aW9uIGFzc2V0LlxuICAgICAqXG4gICAgICogTm90ZTogVGhpcyBtZXRob2QgaXMgcmVzdHJpY3RlZCBieSBkZWZhdWx0IGFuZCBtdXN0IGJlIGVuYWJsZWQgdmlhXG4gICAgICogPGEgaHJlZj1cImh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvYXBpLXNlY3VyaXR5XCI+QVBJIHNlY3VyaXR5IHNldHRpbmdzPC9hPi5cbiAgICAgKiBAcGFyYW0gYXBwQXNzZXQgQXBwIGFzc2V0IG9iamVjdFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIGRvd25sb2FkQXNzZXQoKSB7XG4gICAgICogICAgIGNvbnN0IGFwcEFzc2V0ID0ge1xuICAgICAqICAgICAgICAgc3JjOiBgJHsgbG9jYXRpb24ub3JpZ2luIH0vYXNzZXRzLnppcGAsXG4gICAgICogICAgICAgICBhbGlhczogJ2RpckFwcCcsXG4gICAgICogICAgICAgICB2ZXJzaW9uOiAnMS4yMy4yNCcsXG4gICAgICogICAgICAgICB0YXJnZXQ6ICdhc3NldHMvcnVuLmJhdCdcbiAgICAgKiAgICAgfTtcbiAgICAgKlxuICAgICAqICAgICByZXR1cm4gZmluLlN5c3RlbS5kb3dubG9hZEFzc2V0KGFwcEFzc2V0LCAocHJvZ3Jlc3MgPT4ge1xuICAgICAqICAgICAvL1ByaW50IHByb2dyZXNzIGFzIHdlIGRvd25sb2FkIHRoZSBhc3NldC5cbiAgICAgKiAgICAgICAgIGNvbnN0IGRvd25sb2FkZWRQZXJjZW50ID0gTWF0aC5mbG9vcigocHJvZ3Jlc3MuZG93bmxvYWRlZEJ5dGVzIC8gcHJvZ3Jlc3MudG90YWxCeXRlcykgKiAxMDApO1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coYERvd25sb2FkZWQgJHtkb3dubG9hZGVkUGVyY2VudH0lYCk7XG4gICAgICogICAgIH0pKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBkb3dubG9hZEFzc2V0KClcbiAgICAgKiAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU3VjY2VzcycpKVxuICAgICAqIC5jYXRjaChlcnIgPT4gY29uc29sZS5lcnJvcihlcnIpKTtcbiAgICAgKlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIC8vIGluY29tcGF0aWJsZSB3aXRoIHN0YW5kYWxvbmUgbm9kZSBwcm9jZXNzLlxuICAgIGFzeW5jIGRvd25sb2FkQXNzZXQoYXBwQXNzZXQsIHByb2dyZXNzTGlzdGVuZXIpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9leHBsaWNpdC1mdW5jdGlvbi1yZXR1cm4tdHlwZSwgQHR5cGVzY3JpcHQtZXNsaW50L25vLWVtcHR5LWZ1bmN0aW9uXG4gICAgICAgIGNvbnN0IG5vb3AgPSAoKSA9PiB7IH07XG4gICAgICAgIGxldCByZXNvbHZlID0gbm9vcDtcbiAgICAgICAgbGV0IHJlamVjdCA9IG5vb3A7XG4gICAgICAgIGNvbnN0IGRvd25sb2FkQ29tcGxldGVQcm9taXNlID0gbmV3IFByb21pc2UoKHksIG4pID0+IHtcbiAgICAgICAgICAgIHJlc29sdmUgPSB5O1xuICAgICAgICAgICAgcmVqZWN0ID0gbjtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIG5vZGUuanMgZW52aXJvbm1lbnQgbm90IHN1cHBvcnRlZFxuICAgICAgICBpZiAodGhpcy53aXJlLmVudmlyb25tZW50LnR5cGUgIT09ICdvcGVuZmluJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IHRyYW5zcG9ydF9lcnJvcnNfMSQxLk5vdFN1cHBvcnRlZEVycm9yKCdkb3dubG9hZEFzc2V0IG9ubHkgc3VwcG9ydGVkIGluIGFuIE9wZW5GaW4gUmVuZGVyIHByb2Nlc3MnKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjYWxsU2l0ZSA9IHRyYW5zcG9ydF9lcnJvcnNfMSQxLlJ1bnRpbWVFcnJvci5nZXRDYWxsU2l0ZSgpO1xuICAgICAgICBjb25zdCBkb3dubG9hZElkID0gdGhpcy53aXJlLmVudmlyb25tZW50LmdldE5leHRNZXNzYWdlSWQoKS50b1N0cmluZygpO1xuICAgICAgICBjb25zdCBkbFByb2dyZXNzS2V5ID0gYGFzc2V0LWRvd25sb2FkLXByb2dyZXNzLSR7ZG93bmxvYWRJZH1gO1xuICAgICAgICBjb25zdCBkbEVycm9yS2V5ID0gYGFzc2V0LWRvd25sb2FkLWVycm9yLSR7ZG93bmxvYWRJZH1gO1xuICAgICAgICBjb25zdCBkbENvbXBsZXRlS2V5ID0gYGFzc2V0LWRvd25sb2FkLWNvbXBsZXRlLSR7ZG93bmxvYWRJZH1gO1xuICAgICAgICBjb25zdCBkbFByb2dyZXNzID0gKHByb2dyZXNzKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwID0ge1xuICAgICAgICAgICAgICAgIGRvd25sb2FkZWRCeXRlczogcHJvZ3Jlc3MuZG93bmxvYWRlZEJ5dGVzLFxuICAgICAgICAgICAgICAgIHRvdGFsQnl0ZXM6IHByb2dyZXNzLnRvdGFsQnl0ZXNcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBwcm9ncmVzc0xpc3RlbmVyKHApO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBjbGVhbkxpc3RlbmVycyA9ICgpID0+IHtcbiAgICAgICAgICAgIC8vIFRPRE86IGZpeCBpbnRlcm5hbCB0eXBlc1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihkbFByb2dyZXNzS2V5LCBkbFByb2dyZXNzKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZGxFcnJvciA9IChwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICBjbGVhbkxpc3RlbmVycygpO1xuICAgICAgICAgICAgY29uc3QgeyByZWFzb24sIGVycjogZXJyb3IgfSA9IHBheWxvYWQ7XG4gICAgICAgICAgICByZWplY3QobmV3IHRyYW5zcG9ydF9lcnJvcnNfMSQxLlJ1bnRpbWVFcnJvcih7IHJlYXNvbiwgZXJyb3IgfSwgY2FsbFNpdGUpKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZGxDb21wbGV0ZSA9ICgpID0+IHtcbiAgICAgICAgICAgIGNsZWFuTGlzdGVuZXJzKCk7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH07XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgIC8vIFRPRE86IGZpeCBpbnRlcm5hbCB0eXBlc1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgdGhpcy5vbihkbFByb2dyZXNzS2V5LCBkbFByb2dyZXNzKSxcbiAgICAgICAgICAgIC8vIFRPRE86IGZpeCBpbnRlcm5hbCB0eXBlc1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgdGhpcy5vbmNlKGRsRXJyb3JLZXksIGRsRXJyb3IpLFxuICAgICAgICAgICAgLy8gVE9ETzogZml4IGludGVybmFsIHR5cGVzXG4gICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgICAgICB0aGlzLm9uY2UoZGxDb21wbGV0ZUtleSwgZGxDb21wbGV0ZSlcbiAgICAgICAgXSk7XG4gICAgICAgIGNvbnN0IGRvd25sb2FkT3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oYXBwQXNzZXQsIHsgZG93bmxvYWRJZCB9KTtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2Rvd25sb2FkLWFzc2V0JywgZG93bmxvYWRPcHRpb25zKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICBjbGVhbkxpc3RlbmVycygpO1xuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGRvd25sb2FkQ29tcGxldGVQcm9taXNlO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBEb3dubG9hZHMgYSB2ZXJzaW9uIG9mIHRoZSBydW50aW1lLlxuICAgICAqIEBwYXJhbSBvcHRpb25zIC0gRG93bmxvYWQgb3B0aW9ucy5cbiAgICAgKiBAcGFyYW0gcHJvZ3Jlc3NMaXN0ZW5lciAtIGNhbGxlZCBhcyB0aGUgcnVudGltZSBpcyBkb3dubG9hZGVkIHdpdGggcHJvZ3Jlc3MgaW5mb3JtYXRpb24uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBPbmx5IHN1cHBvcnRlZCBpbiBhbiBPcGVuRmluIFJlbmRlciBwcm9jZXNzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIHZhciBkb3dubG9hZE9wdGlvbnMgPSB7XG4gICAgICogICAgIC8vU3BlY2lmaWMgdmVyc2lvbiBudW1iZXIgcmVxdWlyZWQsIGlmIGdpdmVuIGEgcmVsZWFzZSBjaGFubmVsIHRoZSBjYWxsIHdpbGwgcHJvZHVjZSBhbiBlcnJvci5cbiAgICAgKiAgICAgdmVyc2lvbjogJzkuNjEuMzAuMSdcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogZnVuY3Rpb24gb25Qcm9ncmVzcyhwcm9ncmVzcykge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhgJHtNYXRoLmZsb29yKChwcm9ncmVzcy5kb3dubG9hZGVkQnl0ZXMgLyBwcm9ncmVzcy50b3RhbEJ5dGVzKSAqIDEwMCl9JWApO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGZpbi5TeXN0ZW0uZG93bmxvYWRSdW50aW1lKGRvd25sb2FkT3B0aW9ucywgb25Qcm9ncmVzcykudGhlbigoKSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdEb3dubG9hZCBjb21wbGV0ZScpO1xuICAgICAqIH0pLmNhdGNoKGVyciA9PiAgICB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKGBEb3dubG9hZCBGYWlsZWQsIHdlIGNvdWxkIHJldHJ5OiAke2Vyci5tZXNzYWdlfWApO1xuICAgICAqICAgICBjb25zb2xlLmxvZyhlcnIpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGRvd25sb2FkUnVudGltZShvcHRpb25zLCBwcm9ncmVzc0xpc3RlbmVyKSB7XG4gICAgICAgIGNvbnN0IGNhbGxzaXRlcyA9IHRyYW5zcG9ydF9lcnJvcnNfMSQxLlJ1bnRpbWVFcnJvci5nZXRDYWxsU2l0ZSgpO1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgLy8gbm9kZS5qcyBlbnZpcm9ubWVudCBub3Qgc3VwcG9ydGVkXG4gICAgICAgICAgICBpZiAodGhpcy53aXJlLmVudmlyb25tZW50LnR5cGUgIT09ICdvcGVuZmluJykge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgdHJhbnNwb3J0X2Vycm9yc18xJDEuTm90U3VwcG9ydGVkRXJyb3IoJ2Rvd25sb2FkUnVudGltZSBvbmx5IHN1cHBvcnRlZCBpbiBhbiBPcGVuRmluIFJlbmRlciBwcm9jZXNzJykpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGRvd25sb2FkSWQgPSB0aGlzLndpcmUuZW52aXJvbm1lbnQuZ2V0TmV4dE1lc3NhZ2VJZCgpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBjb25zdCBkbFByb2dyZXNzS2V5ID0gYHJ1bnRpbWUtZG93bmxvYWQtcHJvZ3Jlc3MtJHtkb3dubG9hZElkfWA7XG4gICAgICAgICAgICBjb25zdCBkbEVycm9yS2V5ID0gYHJ1bnRpbWUtZG93bmxvYWQtZXJyb3ItJHtkb3dubG9hZElkfWA7XG4gICAgICAgICAgICBjb25zdCBkbENvbXBsZXRlS2V5ID0gYHJ1bnRpbWUtZG93bmxvYWQtY29tcGxldGUtJHtkb3dubG9hZElkfWA7XG4gICAgICAgICAgICBjb25zdCBkbFByb2dyZXNzID0gKHByb2dyZXNzKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcCA9IHtcbiAgICAgICAgICAgICAgICAgICAgZG93bmxvYWRlZEJ5dGVzOiBwcm9ncmVzcy5kb3dubG9hZGVkQnl0ZXMsXG4gICAgICAgICAgICAgICAgICAgIHRvdGFsQnl0ZXM6IHByb2dyZXNzLnRvdGFsQnl0ZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHByb2dyZXNzTGlzdGVuZXIocCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgY2xlYW5MaXN0ZW5lcnMgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogZml4IGludGVybmFsIHR5cGVzXG4gICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZGxQcm9ncmVzc0tleSwgZGxQcm9ncmVzcyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgZGxFcnJvciA9IChwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICAgICAgY2xlYW5MaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgICAgICBjb25zdCB7IHJlYXNvbiwgZXJyOiBlcnJvciB9ID0gcGF5bG9hZDtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IHRyYW5zcG9ydF9lcnJvcnNfMSQxLlJ1bnRpbWVFcnJvcih7IHJlYXNvbiwgZXJyb3IgfSwgY2FsbHNpdGVzKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgZGxDb21wbGV0ZSA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjbGVhbkxpc3RlbmVycygpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvLyBUT0RPOiBmaXggaW50ZXJuYWwgdHlwZXNcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgIHRoaXMub24oZGxQcm9ncmVzc0tleSwgZGxQcm9ncmVzcyk7XG4gICAgICAgICAgICAvLyBUT0RPOiBmaXggaW50ZXJuYWwgdHlwZXNcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgIHRoaXMub25jZShkbEVycm9yS2V5LCBkbEVycm9yKTtcbiAgICAgICAgICAgIC8vIFRPRE86IGZpeCBpbnRlcm5hbCB0eXBlc1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgdGhpcy5vbmNlKGRsQ29tcGxldGVLZXksIGRsQ29tcGxldGUpO1xuICAgICAgICAgICAgY29uc3QgZG93bmxvYWRPcHRpb25zID0gT2JqZWN0LmFzc2lnbihvcHRpb25zLCB7IGRvd25sb2FkSWQgfSk7XG4gICAgICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZG93bmxvYWQtcnVudGltZScsIGRvd25sb2FkT3B0aW9ucykuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGNsZWFuTGlzdGVuZXJzKCk7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERvd25sb2FkIHByZWxvYWQgc2NyaXB0cyBmcm9tIGdpdmVuIFVSTHNcbiAgICAgKiBAcGFyYW0gc2NyaXB0cyAtIFVSTHMgb2YgcHJlbG9hZCBzY3JpcHRzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHNjcmlwdHMgPSBbXG4gICAgICogICAgIHsgdXJsOiAnaHR0cDovLy4uLi9wcmVsb2FkLmpzJyB9LFxuICAgICAqICAgICB7IHVybDogJ2h0dHA6Ly8uLi4vcHJlbG9hZDIuanMnIH1cbiAgICAgKiBdO1xuICAgICAqXG4gICAgICogZmluLlN5c3RlbS5kb3dubG9hZFByZWxvYWRTY3JpcHRzKHNjcmlwdHMpLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICogICAgIHJlc3VsdHMuZm9yRWFjaCgoe3VybCwgc3VjY2VzcywgZXJyb3J9KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhgVVJMOiAke3VybH1gKTtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKGBTdWNjZXNzOiAke3N1Y2Nlc3N9YCk7XG4gICAgICogICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgKiAgICAgICAgICAgICBjb25zb2xlLmxvZyhgRXJyb3I6ICR7ZXJyb3J9YCk7XG4gICAgICogICAgICAgICB9XG4gICAgICogICAgIH0pO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGRvd25sb2FkUHJlbG9hZFNjcmlwdHMoc2NyaXB0cykge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2Rvd25sb2FkLXByZWxvYWQtc2NyaXB0cycsIHsgc2NyaXB0cyB9KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGFuIGFycmF5IG9mIGRhdGEgKG5hbWUsIGlkcywgYm91bmRzKSBmb3IgYWxsIGFwcGxpY2F0aW9uIHdpbmRvd3MuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRBbGxFeHRlcm5hbEFwcGxpY2F0aW9ucygpXG4gICAgICogLnRoZW4oZXh0ZXJuYWxBcHBzID0+IGNvbnNvbGUubG9nKCdUb3RhbCBleHRlcm5hbCBhcHBzOiAnICsgZXh0ZXJuYWxBcHBzLmxlbmd0aCkpXG4gICAgICogLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRBbGxFeHRlcm5hbEFwcGxpY2F0aW9ucygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtYWxsLWV4dGVybmFsLWFwcGxpY2F0aW9ucycpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYXBwIGFzc2V0IGluZm9ybWF0aW9uLlxuICAgICAqIEBwYXJhbSBvcHRpb25zXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRBcHBBc3NldEluZm8oe2FsaWFzOidwcm9jZXhwJ30pLnRoZW4oYXNzZXRJbmZvID0+IGNvbnNvbGUubG9nKGFzc2V0SW5mbykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRBcHBBc3NldEluZm8ob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1hcHAtYXNzZXQtaW5mbycsIG9wdGlvbnMpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgYWRkaXRpb25hbCBpbmZvIG9mIGNvb2tpZXMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRDb29raWVzKHtuYW1lOiAnbXlDb29raWUnfSkudGhlbihjb29raWVzID0+IGNvbnNvbGUubG9nKGNvb2tpZXMpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0Q29va2llcyhvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHVybCA9IHRoaXMud2lyZS5lbnZpcm9ubWVudC5nZXRVcmwoKTtcbiAgICAgICAgY29uc3QgbmV3T3B0aW9ucyA9IE9iamVjdC5hc3NpZ24ob3B0aW9ucywgeyB1cmwgfSk7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWNvb2tpZXMnLCBuZXdPcHRpb25zKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBtaW5pbXVtIGxvZyBsZXZlbCBhYm92ZSB3aGljaCBsb2dzIHdpbGwgYmUgd3JpdHRlbiB0byB0aGUgT3BlbkZpbiBsb2dcbiAgICAgKiBAcGFyYW0gVGhlIG1pbmltdW0gbGV2ZWwgKGluY2x1c2l2ZSkgYWJvdmUgd2hpY2ggYWxsIGNhbGxzIHRvIGxvZyB3aWxsIGJlIHdyaXR0ZW5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLnNldE1pbkxvZ0xldmVsKFwidmVyYm9zZVwiKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKFwibG9nIGxldmVsIGlzIHNldCB0byB2ZXJib3NlXCIpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgc2V0TWluTG9nTGV2ZWwobGV2ZWwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzZXQtbWluLWxvZy1sZXZlbCcsIHsgbGV2ZWwgfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIFVVSUQgb2YgdGhlIGNvbXB1dGVyIG9uIHdoaWNoIHRoZSBydW50aW1lIGlzIGluc3RhbGxlZFxuICAgICAqIEBwYXJhbSB1dWlkIFRoZSB1dWlkIG9mIHRoZSBydW5uaW5nIGFwcGxpY2F0aW9uXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5yZXNvbHZlVXVpZCgnT3BlbmZpblBPQycpLnRoZW4oZW50aXR5ID0+IGNvbnNvbGUubG9nKGVudGl0eSkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICByZXNvbHZlVXVpZCh1dWlkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmVcbiAgICAgICAgICAgIC5zZW5kQWN0aW9uKCdyZXNvbHZlLXV1aWQnLCB7XG4gICAgICAgICAgICBlbnRpdHlLZXk6IHV1aWRcbiAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGFuIGFycmF5IG9mIGRhdGEgZm9yIGFsbCBleHRlcm5hbCBhcHBsaWNhdGlvbnNcbiAgICAgKiBAcGFyYW0gcmVxdWVzdGluZ0lkZW50aXR5IFRoaXMgb2JqZWN0IGlzIGRlc2NyaWJlZCBpbiB0aGUgSWRlbnRpdHkgdHlwZWRlZlxuICAgICAqIEBwYXJhbSBkYXRhIEFueSBkYXRhIHR5cGUgdG8gcGFzcyB0byB0aGUgbWV0aG9kXG4gICAgICpcbiAgICAgKiBAaWdub3JlXG4gICAgICovXG4gICAgZXhlY3V0ZU9uUmVtb3RlKHJlcXVlc3RpbmdJZGVudGl0eSwgZGF0YSkge1xuICAgICAgICBkYXRhLnJlcXVlc3RpbmdJZGVudGl0eSA9IHJlcXVlc3RpbmdJZGVudGl0eTtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5mZXJyeUFjdGlvbihkYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVhZHMgdGhlIHNwZWNpZmVkIHZhbHVlIGZyb20gdGhlIHJlZ2lzdHJ5LlxuICAgICAqIEByZW1hcmtzIFRoaXMgbWV0aG9kIGlzIHJlc3RyaWN0ZWQgYnkgZGVmYXVsdCBhbmQgbXVzdCBiZSBlbmFibGVkIHZpYVxuICAgICAqIFtBUEkgc2VjdXJpdHkgc2V0dGluZ3NdKGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvYXBpLXNlY3VyaXR5KS5cbiAgICAgKiBAcGFyYW0gcm9vdEtleSAtIFRoZSByZWdpc3RyeSByb290IGtleS5cbiAgICAgKiBAcGFyYW0gc3Via2V5IC0gVGhlIHJlZ2lzdHJ5IGtleS5cbiAgICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgcmVnaXN0cnkgdmFsdWUgbmFtZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLnJlYWRSZWdpc3RyeVZhbHVlKFwiSEtFWV9MT0NBTF9NQUNISU5FXCIsIFwiSEFSRFdBUkVcXFxcREVTQ1JJUFRJT05cXFxcU3lzdGVtXCIsIFwiQm9vdEFyY2hpdGVjdHVyZVwiKS50aGVuKHZhbCA9PiBjb25zb2xlLmxvZyh2YWwpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBTZWUge0BsaW5rIGh0dHBzOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvd2luZG93cy9kZXNrdG9wL21zNjgxMzgyKHY9dnMuODUpLmFzcHggaGVyZX0gZm9yIFdpbmRvdydzIGVycm9yIGNvZGUgZGVmaW5pdGlvbnMuXG4gICAgICpcbiAgICAgKiBFeGFtcGxlIHBheWxvYWRzIG9mIGRpZmZlcmVudCByZWdpc3RyeSB0eXBlczpcbiAgICAgKlxuICAgICAqIFNlZSBsaXN0IG9mIHR5cGVzIHtAbGluayBodHRwczovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L3dpbmRvd3MvZGVza3RvcC9tczcyNDg4NCh2PXZzLjg1KS5hc3B4IGhlcmV9LlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAvLyBSRUdfRFdPUkRcbiAgICAgKiB7XG4gICAgICogICAgIGRhdGE6IDEsXG4gICAgICogICAgIHJvb3RLZXk6IFwiSEtFWV9MT0NBTF9NQUNISU5FXCIsXG4gICAgICogICAgIHN1YmtleTogXCJGb29cXEJhclwiLFxuICAgICAqICAgICB0eXBlOiBcIlJFR19EV09SRFwiLFxuICAgICAqICAgICB2YWx1ZTogXCJCYXpcIlxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIC8vIFJFR19RV09SRFxuICAgICAqIHtcbiAgICAgKiAgICAgZGF0YTogMTMxMDgxNDY2NzEzMzQxMTIsXG4gICAgICogICAgIHJvb3RLZXk6IFwiSEtFWV9MT0NBTF9NQUNISU5FXCIsXG4gICAgICogICAgIHN1YmtleTogXCJGb29cXEJhclwiLFxuICAgICAqICAgICB0eXBlOiBcIlJFR19RV09SRFwiLFxuICAgICAqICAgICB2YWx1ZTogXCJCYXpcIlxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIC8vIFJFR19TWlxuICAgICAqIHtcbiAgICAgKiAgICAgZGF0YTogXCJGb29CYXJCYXpcIixcbiAgICAgKiAgICAgcm9vdEtleTogXCJIS0VZX0xPQ0FMX01BQ0hJTkVcIixcbiAgICAgKiAgICAgc3Via2V5OiBcIkZvb1xcQmFyXCIsXG4gICAgICogICAgIHR5cGU6IFwiUkVHX1NaXCIsXG4gICAgICogICAgIHZhbHVlOiBcIkJhelwiXG4gICAgICogfVxuICAgICAqXG4gICAgICogLy8gUkVHX0VYUEFORF9TWlxuICAgICAqIHtcbiAgICAgKiAgICAgZGF0YTogXCJDOlxcVXNlclxcSm9obkRvZVxcQXBwRGF0YVxcTG9jYWxcIixcbiAgICAgKiAgICAgcm9vdEtleTogXCJIS0VZX0NVUlJFTlRfVVNFUlwiLFxuICAgICAqICAgICBzdWJrZXk6IFwiRm9vXFxCYXJcIixcbiAgICAgKiAgICAgdHlwZTogXCJSRUdfRVhQQU5EX1NaXCIsXG4gICAgICogICAgIHZhbHVlOiBcIkJhelwiXG4gICAgICogfVxuICAgICAqXG4gICAgICogLy8gUkVHX01VTFRJX1NaXG4gICAgICoge1xuICAgICAqICAgICBkYXRhOiBbXG4gICAgICogICAgICAgICBcIkZvb1wiLFxuICAgICAqICAgICAgICAgXCJCYXJcIixcbiAgICAgKiAgICAgICAgIFwiQmF6XCJcbiAgICAgKiAgICAgXSxcbiAgICAgKiAgICAgcm9vdEtleTogXCJIS0VZX0NVUlJFTlRfVVNFUlwiLFxuICAgICAqICAgICBzdWJrZXk6IFwiRm9vXFxCYXJcIixcbiAgICAgKiAgICAgdHlwZTogXCJSRUdfTVVMVElfU1pcIixcbiAgICAgKiAgICAgdmFsdWU6IFwiQmF6XCJcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiAvLyBSRUdfQklOQVJZXG4gICAgICoge1xuICAgICAqICAgICBkYXRhOiB7XG4gICAgICogICAgICAgICBkYXRhOiBbXG4gICAgICogICAgICAgICAgICAgMjU1LFxuICAgICAqICAgICAgICAgICAgIDI1NSxcbiAgICAgKiAgICAgICAgICAgICAwLFxuICAgICAqICAgICAgICAgICAgIDQzLFxuICAgICAqICAgICAgICAgICAgIDU1LFxuICAgICAqICAgICAgICAgICAgIDAsXG4gICAgICogICAgICAgICAgICAgMCxcbiAgICAgKiAgICAgICAgICAgICAyNTUsXG4gICAgICogICAgICAgICAgICAgMjU1XG4gICAgICogICAgICAgICBdLFxuICAgICAqICAgICAgICAgdHlwZTogXCJCdWZmZXJcIlxuICAgICAqICAgICB9LFxuICAgICAqICAgICByb290S2V5OiBcIkhLRVlfQ1VSUkVOVF9VU0VSXCIsXG4gICAgICogICAgIHN1YmtleTogXCJGb29cXEJhclwiLFxuICAgICAqICAgICB0eXBlOiBcIlJFR19CSU5BUllcIixcbiAgICAgKiAgICAgdmFsdWU6IFwiQmF6XCJcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcmVhZFJlZ2lzdHJ5VmFsdWUocm9vdEtleSwgc3Via2V5LCB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlXG4gICAgICAgICAgICAuc2VuZEFjdGlvbigncmVhZC1yZWdpc3RyeS12YWx1ZScsIHtcbiAgICAgICAgICAgIHJvb3RLZXksXG4gICAgICAgICAgICBzdWJrZXksXG4gICAgICAgICAgICB2YWx1ZVxuICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGNhbGwgd2lsbCByZWdpc3RlciBhIHVuaXF1ZSBpZCBhbmQgcHJvZHVjZSBhIHRva2VuLlxuICAgICAqIFRoZSB0b2tlbiBjYW4gYmUgdXNlZCB0byBicm9rZXIgYW4gZXh0ZXJuYWwgY29ubmVjdGlvbi5cbiAgICAgKiBAcGFyYW0gdXVpZCAtIEEgVVVJRCBmb3IgdGhlIHJlbW90ZSBjb25uZWN0aW9uLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ucmVnaXN0ZXJFeHRlcm5hbENvbm5lY3Rpb24oXCJyZW1vdGUtY29ubmVjdGlvbi11dWlkXCIpLnRoZW4oY29ubiA9PiBjb25zb2xlLmxvZyhjb25uKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqXG4gICAgICpcbiAgICAgKiAvLyBvYmplY3QgY29tZXMgYmFjayB3aXRoXG4gICAgICogLy8gICAgIHRva2VuOiBcIjA0ODlFQUM1LTY0MDQtNEYwRC05OTNCLTkyQkI4RUFCNDQ1RFwiLCAvLyB0aGlzIHdpbGwgYmUgdW5pcXVlIGVhY2ggdGltZVxuICAgICAqIC8vICAgICB1dWlkOiBcInJlbW90ZS1jb25uZWN0aW9uLXV1aWRcIlxuICAgICAqXG4gICAgICogYGBgXG4gICAgICovXG4gICAgcmVnaXN0ZXJFeHRlcm5hbENvbm5lY3Rpb24odXVpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3JlZ2lzdGVyLWV4dGVybmFsLWNvbm5lY3Rpb24nLCB7IHV1aWQgfSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGpzb24gYmxvYiBmb3VuZCBpbiB0aGUgW2Rlc2t0b3Agb3duZXIgc2V0dGluZ3NdKGh0dHBzOi8vb3BlbmZpbi5jby9kb2N1bWVudGF0aW9uL2Rlc2t0b3Atb3duZXItc2V0dGluZ3MvKVxuICAgICAqIGZvciB0aGUgc3BlY2lmaWVkIHNlcnZpY2UuXG4gICAgICogQHBhcmFtIHNlcnZpY2VJZGVudGlmaWVyIEFuIG9iamVjdCBjb250YWluaW5nIGEgbmFtZSBrZXkgdGhhdCBpZGVudGlmaWVzIHRoZSBzZXJ2aWNlLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgTW9yZSBpbmZvcm1hdGlvbiBhYm91dCBkZXNrdG9wIHNlcnZpY2VzIGNhbiBiZSBmb3VuZCBbaGVyZV0oaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5maW4uY28vZG9jcy9kZXNrdG9wLXNlcnZpY2VzKS5cbiAgICAgKiBUaGlzIGNhbGwgd2lsbCByZWplY3QgaWYgdGhlIGRlc2t0b3Agb3duZXIgc2V0dGluZ3MgZmlsZSBpcyBub3QgcHJlc2VudCwgbm90IGNvcnJlY3RseSBmb3JtYXR0ZWQsIG9yIGlmIHRoZSBzZXJ2aWNlIHJlcXVlc3RlZCBpcyBub3QgY29uZmlndXJlZCBvciBjb25maWd1cmVkIGluY29ycmVjdGx5LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIC8vIEhlcmUgd2UgYXJlIHVzaW5nIHRoZSBbbGF5b3V0c10oaHR0cHM6Ly9naXRodWIuY29tL0hhZG91a2VuSU8vbGF5b3V0cy1zZXJ2aWNlKSBzZXJ2aWNlLlxuICAgICAqIGZpbi5TeXN0ZW0uZ2V0U2VydmljZUNvbmZpZ3VyYXRpb24oe25hbWU6J2xheW91dHMnfSkudGhlbihjb25zb2xlLmxvZykuY2F0Y2goY29uc29sZS5lcnJvcik7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZ2V0U2VydmljZUNvbmZpZ3VyYXRpb24oc2VydmljZUlkZW50aWZpZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzZXJ2aWNlSWRlbnRpZmllci5uYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNdXN0IHByb3ZpZGUgYW4gb2JqZWN0IHdpdGggYSBgbmFtZWAgcHJvcGVydHkgaGF2aW5nIGEgc3RyaW5nIHZhbHVlJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyBuYW1lIH0gPSBzZXJ2aWNlSWRlbnRpZmllcjtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtc2VydmljZS1jb25maWd1cmF0aW9uJywgeyBuYW1lIH0pLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICBhc3luYyBnZXRTeXN0ZW1BcHBDb25maWcobmFtZSkge1xuICAgICAgICBpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ011c3QgcHJvdmlkZSBhIHN0cmluZyB2YWx1ZSBmb3IgbmFtZSBvZiBzeXN0ZW0gYXBwJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtc3lzdGVtLWFwcC1jb25maWd1cmF0aW9uJywgeyBuYW1lIH0pLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgYSBzeXN0ZW0gc2h1dGRvd24gaGFuZGxlciBzbyB1c2VyIGNhbiBkbyBzb21lIGNsZWFudXAgYmVmb3JlIHN5c3RlbSBpcyBzaHV0dGluZyBkb3duLlxuICAgICAqIEByZW1hcmtzIE9uY2Ugc3lzdGVtIHNodXRkb3duIHN0YXJ0cywgeW91IGFyZSB1bmFibGUgdG8gY2FuY2VsIGl0LlxuICAgICAqIEBwYXJhbSBoYW5kbGVyIHN5c3RlbSBzaHV0ZG93biBoYW5kbGVyXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5yZWdpc3RlclNodXRkb3duSGFuZGxlcigoc2h1dGRvd25FdmVudCkgPT4ge1xuICAgICAqICAgICAgICAgLy8gc2F2ZSBzdGF0ZSBvciBjbGVhbnVwXG4gICAgICogICAgICAgICBjb25zb2xlLmxvZygnZG8gc29tZSBjbGVhbnVwIGJlZm9yZSBzaHV0ZG93bicpO1xuICAgICAqICAgICAgICAgLy8gTm90aWZ5IGFwcCBpcyByZWFkeSBmb3IgdGVybWluYXRpb24uXG4gICAgICogICAgICAgICBzaHV0ZG93bkV2ZW50LnByb2NlZWQoKTtcbiAgICAgKiB9KVxuICAgICAqIC50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTaHV0ZG93biBoYW5kbGVyIHJlZ2lzdGVyZWQhJykpXG4gICAgICogLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICovXG4gICAgYXN5bmMgcmVnaXN0ZXJTaHV0ZG93bkhhbmRsZXIoaGFuZGxlcikge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignc3lzdGVtLXJlZ2lzdGVyLXNodXRkb3duLWhhbmRsZXInKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBTeXN0ZW1TaHV0ZG93bkV2ZW50TmFtZSA9ICdzeXN0ZW0tc2h1dGRvd24nO1xuICAgICAgICBjb25zdCBTeXN0ZW1TaHV0ZG93bkhhbmRsZWRFdmVudE5hbWUgPSAnc3lzdGVtLXNodXRkb3duLWhhbmRsZWQnO1xuICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IHRoaXMud2lyZS5tZTtcbiAgICAgICAgY29uc3Qgc2h1dGRvd25IYW5kbGVyID0gKHBheWxvYWQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHByb2NlZWQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gbm90aWZ5IGNvcmUgdGhhdCB0aGUgYXBwIGlzIHJlYWR5IGZvciBzaHV0ZG93blxuICAgICAgICAgICAgICAgIHRoaXMud2lyZS5lbnZpcm9ubWVudC5yYWlzZUV2ZW50KGBhcHBsaWNhdGlvbi8ke1N5c3RlbVNodXRkb3duSGFuZGxlZEV2ZW50TmFtZX1gLCB7XG4gICAgICAgICAgICAgICAgICAgIHV1aWQsXG4gICAgICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHRvcGljOiAnYXBwbGljYXRpb24nXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaGFuZGxlcih7IHByb2NlZWQgfSk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMub24oU3lzdGVtU2h1dGRvd25FdmVudE5hbWUsIHNodXRkb3duSGFuZGxlcik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNpZ25hbHMgdGhlIFJWTSB0byBwZXJmb3JtIGEgaGVhbHRoIGNoZWNrIGFuZCByZXR1cm5zIHRoZSByZXN1bHRzIGFzIGpzb24uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBSZXF1aXJlcyBSVk0gNS41K1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIHRyeSB7XG4gICAgICogICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBmaW4uU3lzdGVtLnJ1blJ2bUhlYWx0aENoZWNrKCk7XG4gICAgICogICAgIGNvbnNvbGUubG9nKHJlc3VsdHMpO1xuICAgICAqIH0gY2F0Y2goZSkge1xuICAgICAqICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcnVuUnZtSGVhbHRoQ2hlY2soKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigncnVuLXJ2bS1oZWFsdGgtY2hlY2snKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogTGF1bmNoIGFwcGxpY2F0aW9uIHVzaW5nIGEgbWFuaWZlc3QgVVJML3BhdGguIEl0IGRpZmZlcnMgZnJvbSBBcHBsaWNhdGlvbi5zdGFydEZyb21NYW5pZmVzdCBpbiB0aGF0IHRoaXMgQVBJIGNhbiBhY2NlcHQgYSBtYW5pZmVzdCB1c2luZyB0aGUgZmluIHByb3RvY29sLlxuICAgICAqIEBwYXJhbSBtYW5pZmVzdFVybCAtIFRoZSBtYW5pZmVzdCdzIFVSTCBvciBwYXRoLlxuICAgICAqIEBwYXJhbSBvcHRzIC0gUGFyYW1ldGVycyB0aGF0IHRoZSBSVk0gd2lsbCB1c2UuXG4gICAgICpcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICogQHJlbWFya3MgU3VwcG9ydHMgcHJvdG9jb2xzIGh0dHAvcyBhbmQgZmluL3MsIGFuZCBhbHNvIGEgbG9jYWwgcGF0aC5cbiAgICAgKlxuICAgICAqIE5vdGU6IFRoaXMgQVBJIGlzIFdpbmRvd3Mgb25seS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBUaGlzIEFQSSBjYW4gaGFuZGxlIG1vc3QgbWFuaWZlc3QgdHlwZXMuIFNvbWUgZXhhbXBsZXMgYmVsb3cuXG4gICAgICpcbiAgICAgKiBUcmFkaXRpb25hbDpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgZmluLlN5c3RlbS5sYXVuY2hNYW5pZmVzdChcbiAgICAgKiAgICdodHRwczovL2RlbW9hcHBkaXJlY3Rvcnkub3BlbmYuaW4vZGVza3RvcC9jb25maWcvYXBwcy9PcGVuRmluL0hlbGxvT3BlbkZpbi9hcHAuanNvbicpO1xuICAgICAqIGNvbnNvbGUubG9nKG1hbmlmZXN0KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFBsYXRmb3JtOlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgbWFuaWZlc3QgPSBhd2FpdCBmaW4uU3lzdGVtLmxhdW5jaE1hbmlmZXN0KCdodHRwczovL29wZW5maW4uZ2l0aHViLmlvL3BsYXRmb3JtLWFwaS1wcm9qZWN0LXNlZWQvcHVibGljLmpzb24nKTtcbiAgICAgKiBjb25zb2xlLmxvZyhtYW5pZmVzdCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBMYXVuY2hpbmcgdHJhZGl0aW9uYWwgbWFuaWZlc3QgaW50byBhIHBsYXRmb3JtOlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgbWFuaWZlc3QgPSBhd2FpdCBmaW4uU3lzdGVtLmxhdW5jaE1hbmlmZXN0KFxuICAgICAqICAgJ2h0dHBzOi8vb3BlbmZpbi5naXRodWIuaW8vcGxhdGZvcm0tYXBpLXByb2plY3Qtc2VlZC9wdWJsaWMuanNvbj9cXFxuICAgICAqICAgJCRhcHBNYW5pZmVzdFVybD1odHRwczovL2RlbW9hcHBkaXJlY3Rvcnkub3BlbmYuaW4vZGVza3RvcC9jb25maWcvXFxcbiAgICAgKiAgIGFwcHMvT3BlbkZpbi9IZWxsb09wZW5GaW4vYXBwLmpzb24nKTtcbiAgICAgKiBjb25zb2xlLmxvZyhtYW5pZmVzdCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBMYXVuY2hpbmcgd2l0aCBSVk0gb3B0aW9uczpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgZmluLlN5c3RlbS5sYXVuY2hNYW5pZmVzdCgnaHR0cHM6Ly9vcGVuZmluLmdpdGh1Yi5pby9wbGF0Zm9ybS1hcGktcHJvamVjdC1zZWVkL3B1YmxpYy5qc29uJyxcbiAgICAgKiAgICAgeyBub1VpOiB0cnVlLCB1c2VyQXBwQ29uZmlnQXJnczogeyBhYmM6ICcxMjMnLCB4eXo6ICc3ODknIH0gfSk7XG4gICAgICogY29uc29sZS5sb2cobWFuaWZlc3QpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogTG9jYWwgUGF0aDpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IG1hbmlmZXN0ID0gIGF3YWl0IGZpbi5TeXN0ZW0ubGF1bmNoTWFuaWZlc3QoJ2ZpbGU6Ly9jOlxcXFxwYXRoXFxcXHRvXFxcXG1hbmlmZXN0XFxcXGZpbGUuanNvbicpO1xuICAgICAqIGNvbnNvbGUubG9nKG1hbmlmZXN0KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIExhdW5jaGluZyB3aXRoIFJWTSAnc3Vic2NyaWJlJyBvcHRpb246XG4gICAgICpcbiAgICAgKiBUaGlzIG9wdGlvbiBhbGxvd3MgdXNlcnMgdG8gc3Vic2NyaWJlIHRvIGFwcCB2ZXJzaW9uIHJlc29sdmVyIGV2ZW50cyB3aGVuXG4gICAgICogY2FsbGluZyBsYXVuY2hNYW5pZmVzdCB3aXRoIGZhbGxiYWNrTWFuaWZlc3RzIHNwZWNpZmllZC5cbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5sYXVuY2hNYW5pZmVzdCgnZmluczovL3N5c3RlbS1hcHBzL25vdGlmaWNhdGlvbnMvYXBwLmpzb24nLCB7IHN1YnNjcmliZTogKGxhdW5jaCkgPT4ge1xuICAgICAqIFx0XHRsYXVuY2gub24oJ2FwcC12ZXJzaW9uLXByb2dyZXNzJywgKHByb2dyZXNzKSA9PiB7XG4gICAgICogXHRcdFx0Y29uc29sZS5sb2coXCJUcnlpbmcgbWFuaWZlc3QgXCIgKyBwcm9ncmVzcy5tYW5pZmVzdClcbiAgICAgKiBcdFx0fSk7XG4gICAgICpcbiAgICAgKiBcdFx0bGF1bmNoLm9uKCdydW50aW1lLXN0YXR1cycsIChzdGF0dXMpID0+IHtcbiAgICAgKiBcdFx0XHRjb25zb2xlLmxvZyhcIlJ1bnRpbWUgc3RhdHVzOiBcIiArIEpTT04uc3RyaW5naWZ5KHN0YXR1cykpO1xuICAgICAqIFx0XHR9KTtcbiAgICAgKlxuICAgICAqIFx0XHQvLyBSVk0gaGFzIHN1Y2Nlc3NmdWxseSBmb3VuZCB0aGUgdGFyZ2V0IHJ1bnRpbWUgdmVyc2lvblxuICAgICAqIFx0XHRsYXVuY2gub24oJ2FwcC12ZXJzaW9uLWNvbXBsZXRlJywgKGNvbXBsZXRlKSA9PiB7XG4gICAgICogXHRcdFx0Y29uc29sZS5sb2coXCJQYXJlbnQgYXBwIFwiICsgY29tcGxldGUuc3JjTWFuaWZlc3QgKyBcIiByZXNvbHZlZCB0byBcIiArIGNvbXBsZXRlLm1hbmlmZXN0KTtcbiAgICAgKiBcdFx0XHRsYXVuY2gucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgICogXHRcdH0pO1xuICAgICAqXG4gICAgICogXHRcdC8vIFJWTSBmYWlsZWQgdG8gZmluZCBhbiBhdmFpbGFibGUgcnVudGltZSB2ZXJzaW9uXG4gICAgICogXHRcdGxhdW5jaC5vbignYXBwLXZlcnNpb24tZXJyb3InLCAoZXJyb3IpID0+IHtcbiAgICAgKiBcdFx0XHRjb25zb2xlLmxvZyhcIkZhaWxlZCB0byByZXNvbHZlIFwiICsgZXJyb3Iuc3JjTWFuaWZlc3QgKyBcIiBmcm9tIHRoZSBmYWxsYmFja01hbmlmZXN0c1wiKTtcbiAgICAgKiBcdFx0XHRsYXVuY2gucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgICogXHRcdH0pO1xuICAgICAqIFx0fVxuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGxhdW5jaE1hbmlmZXN0KG1hbmlmZXN0VXJsLCBvcHRzID0ge30pIHtcbiAgICAgICAgY29uc3QgeyBzdWJzY3JpYmUsIC4uLl9zZW5kT3B0cyB9ID0gb3B0cztcbiAgICAgICAgY29uc3Qgc2VuZE9wdHMgPSBfc2VuZE9wdHM7XG4gICAgICAgIGlmIChzdWJzY3JpYmUpIHtcbiAgICAgICAgICAgIGNvbnN0IGxhdW5jaEVtaXR0ZXIgPSBuZXcgZXZlbnRzXzEkNi5FdmVudEVtaXR0ZXIoKTtcbiAgICAgICAgICAgIHN1YnNjcmliZShsYXVuY2hFbWl0dGVyKTtcbiAgICAgICAgICAgIGNvbnN0IEFwcFZlcnNpb25Qcm9ncmVzc0V2ZW50TmFtZSA9ICdhcHAtdmVyc2lvbi1wcm9ncmVzcyc7XG4gICAgICAgICAgICBjb25zdCBSdW50aW1lU3RhdHVzRXZlbnROYW1lID0gJ3J1bnRpbWUtc3RhdHVzJztcbiAgICAgICAgICAgIGNvbnN0IEFwcFZlcnNpb25Db21wbGV0ZUV2ZW50TmFtZSA9ICdhcHAtdmVyc2lvbi1jb21wbGV0ZSc7XG4gICAgICAgICAgICBjb25zdCBBcHBWZXJzaW9uRXJyb3JFdmVudE5hbWUgPSAnYXBwLXZlcnNpb24tZXJyb3InO1xuICAgICAgICAgICAgLy8gYWRkIGlkIHRvIGF2b2lkIG11bHRpcGxlIGFwaSBjYWxscyBnZXR0aW5nIGR1cGxpY2F0ZWQgZXZlbnRzXG4gICAgICAgICAgICBjb25zdCBpZCA9IHRoaXMud2lyZS5lbnZpcm9ubWVudC5nZXROZXh0TWVzc2FnZUlkKCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgIHNlbmRPcHRzLmFwcFZlcnNpb25JZCA9IGlkO1xuICAgICAgICAgICAgY29uc3Qgc3VwcG9ydGVkRXZlbnRzID0gW1xuICAgICAgICAgICAgICAgIEFwcFZlcnNpb25Db21wbGV0ZUV2ZW50TmFtZSxcbiAgICAgICAgICAgICAgICBBcHBWZXJzaW9uUHJvZ3Jlc3NFdmVudE5hbWUsXG4gICAgICAgICAgICAgICAgUnVudGltZVN0YXR1c0V2ZW50TmFtZSxcbiAgICAgICAgICAgICAgICBBcHBWZXJzaW9uRXJyb3JFdmVudE5hbWVcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zdCBjbGVhbkV2ZW50UGF5bG9hZCA9IChwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gV2UgbmVlZCB0byBkbyB0eXBlIGNhc3RpbmdzIGJlbG93IHRvIG1ha2Ugc3VyZSB0aGUgcmV0dXJuIHR5cGUgaXMgY29ycmVjdC5cbiAgICAgICAgICAgICAgICBjb25zdCB7IGFwcFZlcnNpb25JZCwgdG9waWMsIHR5cGU6IHR5cGVXaXRoSWQsIC4uLnJlc3QgfSA9IHBheWxvYWQ7XG4gICAgICAgICAgICAgICAgY29uc3QgdHlwZSA9IHN1cHBvcnRlZEV2ZW50cy5maW5kKCh4KSA9PiB0eXBlV2l0aElkLmluY2x1ZGVzKHgpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAuLi5yZXN0LFxuICAgICAgICAgICAgICAgICAgICB0eXBlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBhcHBWZXJzaW9uTGlzdGVuZXIgPSAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNsZWFuUGF5bG9hZCA9IGNsZWFuRXZlbnRQYXlsb2FkKHBheWxvYWQpO1xuICAgICAgICAgICAgICAgIGxhdW5jaEVtaXR0ZXIuZW1pdChjbGVhblBheWxvYWQudHlwZSwgY2xlYW5QYXlsb2FkKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCByZW1vdmVBbGxMaXN0ZW5lcnMgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihgJHtBcHBWZXJzaW9uUHJvZ3Jlc3NFdmVudE5hbWV9LiR7aWR9YCwgYXBwVmVyc2lvbkxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGAke1J1bnRpbWVTdGF0dXNFdmVudE5hbWV9LiR7aWR9YCwgYXBwVmVyc2lvbkxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGAke0FwcFZlcnNpb25Db21wbGV0ZUV2ZW50TmFtZX0uJHtpZH1gLCBhcHBWZXJzaW9uTGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoYCR7QXBwVmVyc2lvbkVycm9yRXZlbnROYW1lfS4ke2lkfWAsIGFwcFZlcnNpb25MaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihgJHtBcHBWZXJzaW9uQ29tcGxldGVFdmVudE5hbWV9LiR7aWR9YCwgcmVtb3ZlQWxsTGlzdGVuZXJzKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGAke0FwcFZlcnNpb25FcnJvckV2ZW50TmFtZX0uJHtpZH1gLCByZW1vdmVBbGxMaXN0ZW5lcnMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgICAgICAgICB0aGlzLm9uKGAke0FwcFZlcnNpb25Qcm9ncmVzc0V2ZW50TmFtZX0uJHtpZH1gLCBhcHBWZXJzaW9uTGlzdGVuZXIpLFxuICAgICAgICAgICAgICAgIHRoaXMub24oYCR7UnVudGltZVN0YXR1c0V2ZW50TmFtZX0uJHtpZH1gLCBhcHBWZXJzaW9uTGlzdGVuZXIpLFxuICAgICAgICAgICAgICAgIHRoaXMub25jZShgJHtBcHBWZXJzaW9uQ29tcGxldGVFdmVudE5hbWV9LiR7aWR9YCwgYXBwVmVyc2lvbkxpc3RlbmVyKSxcbiAgICAgICAgICAgICAgICB0aGlzLm9uY2UoYCR7QXBwVmVyc2lvbkVycm9yRXZlbnROYW1lfS4ke2lkfWAsIGFwcFZlcnNpb25MaXN0ZW5lciksXG4gICAgICAgICAgICAgICAgdGhpcy5vbmNlKGAke0FwcFZlcnNpb25Db21wbGV0ZUV2ZW50TmFtZX0uJHtpZH1gLCByZW1vdmVBbGxMaXN0ZW5lcnMpLFxuICAgICAgICAgICAgICAgIHRoaXMub25jZShgJHtBcHBWZXJzaW9uRXJyb3JFdmVudE5hbWV9LiR7aWR9YCwgcmVtb3ZlQWxsTGlzdGVuZXJzKVxuICAgICAgICAgICAgXSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignbGF1bmNoLW1hbmlmZXN0Jywge1xuICAgICAgICAgICAgbWFuaWZlc3RVcmwsXG4gICAgICAgICAgICBvcHRzOiBzZW5kT3B0c1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnBheWxvYWQuZGF0YS5tYW5pZmVzdDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUXVlcnkgcGVybWlzc2lvbiBvZiBhIHNlY3VyZWQgYXBpIGluIGN1cnJlbnQgY29udGV4dC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBhcGlOYW1lIC0gVGhlIGZ1bGwgbmFtZSBvZiBhIHNlY3VyZWQgQVBJLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgSWYgYSBmdW5jdGlvbiBoYXMgYSBzdHJ1Y3R1cmVkIHBlcm1pc3Npb24gdmFsdWUsIHRoZSB2YWx1ZSBvZiBgZ3JhbnRlZGAgd2lsbCByZWZsZWN0IHRoZSBgZW5hYmxlZGAga2V5XG4gICAgICogb2YgdGhlIGNhbGwncyBwZXJtaXNzaW9ucyBsaXRlcmFsLiAgSW4gdGhpcyBjYXNlLCAqcGVybWlzc2lvbiBtYXkgc3RpbGwgYmUgZGVuaWVkIHRvIGEgY2FsbCogcGVuZGluZyBhcmd1bWVudHMgb3Igb3RoZXJcbiAgICAgKiBydW50aW1lIHN0YXRlLiAgVGhpcyBpcyBpbmRpY2F0ZWQgd2l0aCBgc3RhdGU6IHVuYXZhaWxhYmxlYC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLnF1ZXJ5UGVybWlzc2lvbkZvckN1cnJlbnRDb250ZXh0KCdTeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzJykudGhlbihyZXN1bHQgPT4gY29uc29sZS5sb2cocmVzdWx0KSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqXG4gICAgICogLy9UaGlzIHJlc3BvbnNlIGhhcyB0aGUgZm9sbG93aW5nIHNoYXBlOlxuICAgICAqIHtcbiAgICAgKiAgICBwZXJtaXNzaW9uOiAnU3lzdGVtLmxhdW5jaEV4dGVybmFsUHJvY2VzcycsIC8vIGFwaSBmdWxsIG5hbWVcbiAgICAgKiAgICBzdGF0ZTogJ2dyYW50ZWQnLCAvLyBzdGF0ZSBvZiBwZXJtaXNzaW9uXG4gICAgICogICAgZ3JhbnRlZDogdHJ1ZVxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBxdWVyeVBlcm1pc3Npb25Gb3JDdXJyZW50Q29udGV4dChhcGlOYW1lKSB7XG4gICAgICAgIGNvbnN0IGlkZW50aXR5ID0geyB1dWlkOiB0aGlzLndpcmUubWUudXVpZCwgbmFtZTogdGhpcy53aXJlLm1lLm5hbWUgfTtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbigncXVlcnktcGVybWlzc2lvbi1mb3ItY3VycmVudC1jb250ZXh0Jywge1xuICAgICAgICAgICAgYXBpTmFtZSxcbiAgICAgICAgICAgIGlkZW50aXR5XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzcG9uc2UucGF5bG9hZC5kYXRhO1xuICAgIH1cbiAgICAvLyBOb3QgZG9jdW1lbnRpbmcsIGludGVybmFsIHVzZSBvbmx5LlxuICAgIGFzeW5jIGVuYWJsZU5hdGl2ZVdpbmRvd0ludGVncmF0aW9uUHJvdmlkZXIocGVybWlzc2lvbnMpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZW5hYmxlLW5hdGl2ZS13aW5kb3ctaW50ZWdyYXRpb24tcHJvdmlkZXInLCB7IHBlcm1pc3Npb25zIH0pO1xuICAgICAgICByZXR1cm4gcGF5bG9hZC5kYXRhO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiAoSW50ZXJuYWwpIFJlZ2lzdGVyIHRoZSB1c2FnZSBvZiBhIGNvbXBvbmVudCB3aXRoIGEgcGxhdGZvcm1cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9iamVjdCB3aXRoIGRhdGEgYW5kIHR5cGVcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiByZWdpc3RlclVzYWdlKCkge1xuICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uU3lzdGVtLmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGZpbi5TeXN0ZW0ucmVnaXN0ZXJVc2FnZSh7XG4gICAgICogICAgICAgICB0eXBlOiAnd29ya3NwYWNlLWxpY2Vuc2luZycsXG4gICAgICogICAgICAgICAvLyBleGFtcGxlIHZhbHVlcyBmb3IgdGhlIGZvbGxvd2luZyBkYXRhIG9iamVjdFxuICAgICAqICAgICAgICAgZGF0YToge1xuICAgICAqICAgICAgICAgICAgIGFwaVZlcnNpb246ICcxLjAnLFxuICAgICAqICAgICAgICAgICAgIGNvbXBvbmVudE5hbWU6ICdob21lJyxcbiAgICAgKiAgICAgICAgICAgICBjb21wb25lbnRWZXJzaW9uOiAnMS4wJyxcbiAgICAgKiAgICAgICAgICAgICBhbGxvd2VkOiB0cnVlLFxuICAgICAqICAgICAgICAgICAgIHJlamVjdGlvbkNvZGU6ICcnXG4gICAgICogICAgICAgICB9XG4gICAgICogICAgIH0pO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHJlZ2lzdGVyVXNhZ2UoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTdWNjZXNzZnVsbHkgcmVnaXN0ZXJlZCBjb21wb25lbnQgYXBwbGljYXRpb24nKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHJlZ2lzdGVyVXNhZ2UoeyBkYXRhLCB0eXBlIH0pIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3JlZ2lzdGVyLXVzYWdlJywgeyBkYXRhLCB0eXBlIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIGFycmF5IHdpdGggYWxsIHByaW50ZXJzIG9mIHRoZSBjYWxsZXIgYW5kIG5vdCBhbGwgdGhlIHByaW50ZXJzIG9uIHRoZSBkZXNrdG9wLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0UHJpbnRlcnMoKVxuICAgICAqICAgICAudGhlbigocHJpbnRlcnMpID0+IHtcbiAgICAgKiAgICAgICAgIHByaW50ZXJzLmZvckVhY2goKHByaW50ZXIpID0+IHtcbiAgICAgKiAgICAgICAgICAgICBpZiAocHJpbnRlci5pc0RlZmF1bHQpIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgY29uc29sZS5sb2cocHJpbnRlcik7XG4gICAgICogICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgfSk7XG4gICAgICogICAgIH0pXG4gICAgICogICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhlcnIpO1xuICAgICAqICAgICB9KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBnZXRQcmludGVycygpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc3lzdGVtLWdldC1wcmludGVycycpO1xuICAgICAgICByZXR1cm4gcGF5bG9hZC5kYXRhO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBVcGRhdGVzIFByb2Nlc3MgTG9nZ2luZyB2YWx1ZXM6IHBlcmlvZGljIGludGVydmFsIGFuZCBvdXRsaWVyIGRldGVjdGlvbiBlbnRyaWVzIGFuZCBpbnRlcnZhbC5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBQcm9jZXNzIExvZ2dpbmcgdXBkYXRhYmxlIG9wdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBXaGVuIGVuYWJsaW5nIHZlcmJvc2UgbW9kZSwgYWRkaXRpb25hbCBwcm9jZXNzIGluZm9ybWF0aW9uIGlzIGxvZ2dlZCB0byB0aGUgZGVidWcubG9nOlxuICAgICAqXG4gICAgICogMS4gUGVyaW9kaWNhbGx5IHByb2Nlc3MgdXNhZ2UgKG1lbW9yeSwgY3B1LCBldGMpIHdpbGwgYmUgbG9nZ2VkIGZvciBlYWNoIFBJRCBhbG9uZyB3aXRoIHRoZSB3aW5kb3dzLCB2aWV3cyBhbmRcbiAgICAgKiBpZnJhbWVzIHRoYXQgYmVsb25nIHRvIHRoZW0uIFRoZSBkZWZhdWx0IGlzIGV2ZXJ5IDMwIHNlY29uZHMuIFVwZGF0YWJsZSBieSBwYXNzaW5nIHRoZSBpbnRlcnZhbCBvcHRpb24uXG4gICAgICogMi4gV2hlbiBXaW5kb3dzIGFuZCBWaWV3cyBhcmUgY3JlYXRlZCBvciBuYXZpZ2F0ZWQgdGhlIFBJRCB0aGV5IGJlbG9uZyB0byBhbmQgdGhlaXIgb3B0aW9ucyB3aWxsIGJlIGxvZ2dlZC5cbiAgICAgKiAzLiBXaGVuIFdpbmRvd3MgYW5kIFZpZXdzIGFyZSBkZXN0cm95ZWQgdGhlaXIgbGFzdCBrbm93biBwcm9jZXNzIHVzYWdlIHdpbGwgYmUgbG9nZ2VkLlxuICAgICAqIDQuIFdoZW5ldmVyIGFuIG91dGxpZXIgbWVtb3J5IHVzYWdlIGlzIGRldGVjdGVkIGl0IHdpbGwgYmUgbG9nZ2VkLiBCeSBkZWZhdWx0LCBvbiBhbiBpbnRlcnZhbCBvZiA1IHNlY29uZHMgd2Ugd2lsbFxuICAgICAqIGNvbGxlY3QgcHJvY2VzcyB1c2FnZSBmb3IgYWxsIFBJRHMgYW5kIHdoZW4gMTQ0IHN1Y2ggZW50cmllcyBhcmUgY29sbGVjdGVkLCB3ZSB3aWxsIHN0YXJ0IGFuYWx5emluZyB0aGUgZGF0YSBmb3IgYW55XG4gICAgICogcG9zc2libGUgb3V0bGllcnMgaW4gdGhlIGZvbGxvd2luZyBlbnRyaWVzLiBUaGUgaW50ZXJ2YWwgYW5kIG1heGltdW0gbnVtYmVyIG9mIGVudHJpZXMgc3RvcmVkIGluIHRoZSBydW5uaW5nIGJ1ZmZlclxuICAgICAqIGNhbiBiZSB1cGRhdGFibGUgYnkgcGFzc2luZyB0aGUgb3V0bGllckRldGVjdGlvbi5pbnRlcnZhbCBhbmQgb3V0bGllckRldGVjdGlvbi5lbnRyaWVzIG9wdGlvbnMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBhd2FpdCBmaW4uU3lzdGVtLnVwZGF0ZVByb2Nlc3NMb2dnaW5nT3B0aW9ucyh7XG4gICAgICogICAgIGludGVydmFsOiAxMCxcbiAgICAgKiAgICAgb3V0bGllckRldGVjdGlvbjoge1xuICAgICAqICAgICAgICAgaW50ZXJ2YWw6IDE1LFxuICAgICAqICAgICAgICAgZW50cmllczogMjAwXG4gICAgICogICAgIH1cbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyB1cGRhdGVQcm9jZXNzTG9nZ2luZ09wdGlvbnMob3B0aW9ucykge1xuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc3lzdGVtLXVwZGF0ZS1wcm9jZXNzLWxvZ2dpbmctb3B0aW9ucycsIHsgb3B0aW9ucyB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBkb21haW4gc2V0dGluZ3MgZm9yIHRoZSBjdXJyZW50IGFwcGxpY2F0aW9uLlxuICAgICAqIEluaXRpYWwgc2V0dGluZ3MgYXJlIGNvbmZpZ3VyZWQgd2l0aCB0aGUgZGVmYXVsdERvbWFpblNldHRpbmdzIGFwcGxpY2F0aW9uIG9wdGlvbiB2aWEgbWFuaWZlc3QuXG4gICAgICogRG9tYWluIHNldHRpbmdzIGNhbiBiZSBvdmVyd3JpdHRlbiBkdXJpbmcgcnVudGltZSB3aXRoIFN5c3RlbS5zZXREb21haW5TZXR0aW5ncy5cbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgZG9tYWluU2V0dGluZ3MgPSBhd2FpdCBmaW4uU3lzdGVtLmdldERvbWFpblNldHRpbmdzKCk7XG4gICAgICogLy8ge1xuICAgICAqIC8vICAgICBcInJ1bGVzXCI6IFtcbiAgICAgKiAvLyAgICAgICAgIHtcbiAgICAgKiAvLyAgICAgICAgICAgICBcIm1hdGNoXCI6IFtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgXCJodHRwczovL29wZW5maW4uY29cIlxuICAgICAqIC8vICAgICAgICAgICAgIF0sXG4gICAgICogLy8gICAgICAgICAgICAgXCJvcHRpb25zXCI6IHtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgXCJkb3dubG9hZFNldHRpbmdzXCI6IHtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgIFwicnVsZXNcIjogW1xuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJtYXRjaFwiOiBbXG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIjxhbGxfdXJscz5cIlxuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJlaGF2aW9yXCI6IFwicHJvbXB0XCJcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICBdXG4gICAgICogLy8gICAgICAgICAgICAgICAgIH1cbiAgICAgKiAvLyAgICAgICAgICAgICB9XG4gICAgICogLy8gICAgICAgICB9XG4gICAgICogLy8gICAgIF1cbiAgICAgKiAvLyB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZ2V0RG9tYWluU2V0dGluZ3MoKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhIH0gfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtZG9tYWluLXNldHRpbmdzJywgdGhpcy5pZGVudGl0eSk7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBkb21haW4gc2V0dGluZ3MgZm9yIHRoZSBjdXJyZW50IGFwcGxpY2F0aW9uLlxuICAgICAqIEBwYXJhbSBkb21haW5TZXR0aW5ncyAtIGRvbWFpbiBzZXR0aW5ncyBvYmplY3RcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgZG9tYWluU2V0dGluZ3MgPSBhd2FpdCBmaW4uU3lzdGVtLmdldERvbWFpblNldHRpbmdzKCk7XG4gICAgICogLy8ge1xuICAgICAqIC8vICAgICBcInJ1bGVzXCI6IFtcbiAgICAgKiAvLyAgICAgICAgIHtcbiAgICAgKiAvLyAgICAgICAgICAgICBcIm1hdGNoXCI6IFtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgXCJodHRwczovL29wZW5maW4uY29cIlxuICAgICAqIC8vICAgICAgICAgICAgIF0sXG4gICAgICogLy8gICAgICAgICAgICAgXCJvcHRpb25zXCI6IHtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgXCJkb3dubG9hZFNldHRpbmdzXCI6IHtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgIFwicnVsZXNcIjogW1xuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJtYXRjaFwiOiBbXG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIjxhbGxfdXJscz5cIlxuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJlaGF2aW9yXCI6IFwicHJvbXB0XCJcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICBdXG4gICAgICogLy8gICAgICAgICAgICAgICAgIH1cbiAgICAgKiAvLyAgICAgICAgICAgICB9XG4gICAgICogLy8gICAgICAgICB9XG4gICAgICogLy8gICAgIF1cbiAgICAgKiAvLyB9XG4gICAgICpcbiAgICAgKiAvLyBWYWxpZCBydWxlIGJlaGF2aW9ycyBhcmUgJ3Byb21wdCcgYW5kICduby1wcm9tcHQnXG4gICAgICogZG9tYWluU2V0dGluZ3MucnVsZXNbMF0ub3B0aW9ucy5kb3dubG9hZFNldHRpbmdzLnJ1bGVzWzBdLmJlaGF2aW9yID0gJ25vLXByb21wdCc7XG4gICAgICpcbiAgICAgKiBhd2FpdCBmaW4uU3lzdGVtLnNldERvbWFpblNldHRpbmdzKGRvbWFpblNldHRpbmdzKTtcbiAgICAgKlxuICAgICAqIGNvbnN0IG5ld0RvbWFpblNldHRpbmdzID0gYXdhaXQgZmluLlN5c3RlbS5nZXREb21haW5TZXR0aW5ncygpO1xuICAgICAqIC8vIHtcbiAgICAgKiAvLyAgICAgXCJydWxlc1wiOiBbXG4gICAgICogLy8gICAgICAgICB7XG4gICAgICogLy8gICAgICAgICAgICAgXCJtYXRjaFwiOiBbXG4gICAgICogLy8gICAgICAgICAgICAgICAgIFwiaHR0cHM6Ly9vcGVuZmluLmNvXCJcbiAgICAgKiAvLyAgICAgICAgICAgICBdLFxuICAgICAqIC8vICAgICAgICAgICAgIFwib3B0aW9uc1wiOiB7XG4gICAgICogLy8gICAgICAgICAgICAgICAgIFwiZG93bmxvYWRTZXR0aW5nc1wiOiB7XG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICBcInJ1bGVzXCI6IFtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwibWF0Y2hcIjogW1xuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI8YWxsX3VybHM+XCJcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJiZWhhdmlvclwiOiBcIm5vLXByb21wdFwiXG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAqIC8vICAgICAgICAgICAgICAgICB9XG4gICAgICogLy8gICAgICAgICAgICAgfVxuICAgICAqIC8vICAgICAgICAgfVxuICAgICAqIC8vICAgICBdXG4gICAgICogLy8gfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHNldERvbWFpblNldHRpbmdzKGRvbWFpblNldHRpbmdzKSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzZXQtZG9tYWluLXNldHRpbmdzJywgeyBkb21haW5TZXR0aW5ncywgLi4udGhpcy5pZGVudGl0eSB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQXR0ZW1wdHMgdG8gaW5zdGFsbCBhbmQgZW5hYmxlIGV4dGVuc2lvbnMgZm9yIHRoZSBzZWN1cml0eSByZWFsbS4gIFVzZXJzIG1heSB3YW50IHRvIGNhbGwgdGhpcyBmdW5jdGlvbiBpbiByZXNwb25zZVxuICAgICAqIHRvIGFuIGBleHRlbnNpb25zLWluc3RhbGwtZmFpbGVkYCBldmVudC4gIE9ubHkgZXh0ZW5zaW9ucyBhbGxvd2VkIGJ5IGV2ZXJ5IGFwcGxpY2F0aW9uIG9uIHRoZSBjdXJyZW50IHNlY3VyaXR5IHJlYWxtXG4gICAgICogd2lsbCBiZSBpbnN0YWxsZWQvZW5hYmxlZC5cbiAgICAgKi9cbiAgICBhc3luYyByZWZyZXNoRXh0ZW5zaW9ucygpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbigncmVmcmVzaC1leHRlbnNpb25zJyk7XG4gICAgICAgIHJldHVybiBwYXlsb2FkLmRhdGE7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGN1cnJlbnRseS1pbnN0YWxsZWRcbiAgICAgKi9cbiAgICBhc3luYyBnZXRJbnN0YWxsZWRFeHRlbnNpb25zKCkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQgfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtaW5zdGFsbGVkLWV4dGVuc2lvbnMnKTtcbiAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YTtcbiAgICB9XG59XG5zeXN0ZW0uU3lzdGVtID0gU3lzdGVtO1xuXG52YXIgaW50ZXJhcHBidXMgPSB7fTtcblxudmFyIHJlZkNvdW50ZXIgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHJlZkNvdW50ZXIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xucmVmQ291bnRlci5SZWZDb3VudGVyID0gdm9pZCAwO1xuY2xhc3MgUmVmQ291bnRlciB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMudG9waWNSZWZNYXAgPSBuZXcgTWFwKCk7XG4gICAgfVxuICAgIC8vIHJldHVybnMgdGhlIHJlZiBjb3VudCBhZnRlciBpbmNyZW1lbnRpbmdcbiAgICBpbmNSZWZDb3VudChrZXkpIHtcbiAgICAgICAgY29uc3QgcmVmQ291bnQgPSB0aGlzLnRvcGljUmVmTWFwLmdldChrZXkpO1xuICAgICAgICBsZXQgcmV0dXJuQ291bnQ7XG4gICAgICAgIGlmICghcmVmQ291bnQpIHtcbiAgICAgICAgICAgIHRoaXMudG9waWNSZWZNYXAuc2V0KGtleSwgMSk7XG4gICAgICAgICAgICByZXR1cm5Db3VudCA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBuZXdSZWZDb3VudCA9IHJlZkNvdW50ICsgMTtcbiAgICAgICAgICAgIHJldHVybkNvdW50ID0gbmV3UmVmQ291bnQ7XG4gICAgICAgICAgICB0aGlzLnRvcGljUmVmTWFwLnNldChrZXksIG5ld1JlZkNvdW50KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuQ291bnQ7XG4gICAgfVxuICAgIC8vIHJldHVybnMgdGhlIHJlZiBjb3VudCBhZnRlciBkZWNyZW1lbnRpbmcsIG9yIC0xIGlmIHRoZSBrZXkgYWxyZWFkeSBoYWQgbm8gcmVmZXJlbmNlc1xuICAgIGRlY1JlZkNvdW50KGtleSkge1xuICAgICAgICBjb25zdCByZWZDb3VudCA9IHRoaXMudG9waWNSZWZNYXAuZ2V0KGtleSk7XG4gICAgICAgIGxldCByZXR1cm5Db3VudDtcbiAgICAgICAgaWYgKHJlZkNvdW50KSB7XG4gICAgICAgICAgICBjb25zdCBuZXdSZWZDb3VudCA9IHJlZkNvdW50IC0gMTtcbiAgICAgICAgICAgIHRoaXMudG9waWNSZWZNYXAuc2V0KGtleSwgbmV3UmVmQ291bnQpO1xuICAgICAgICAgICAgcmV0dXJuQ291bnQgPSBuZXdSZWZDb3VudDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybkNvdW50ID0gLTE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJldHVybkNvdW50O1xuICAgIH1cbiAgICAvLyBFeGVjdXRlIGZpcnN0QWN0aW9uIGlmIGl0IGlzIHRoZSBmaXJzdCBzdWNoIHJlZiwgZWxzZSBleGVjdXRlIG5vbkZpcnN0QWN0aW9uLlxuICAgIC8vIEluIGVpdGhlciBjYXNlIHRoZSByZXR1cm4gdmFsdWUgaXMgdGhhdCBvZiB0aGUgYWN0aW9uIGV4ZWN1dGVkXG4gICAgYWN0T25GaXJzdChrZXksIGZpcnN0QWN0aW9uLCBub25GaXJzdEFjdGlvbikge1xuICAgICAgICBjb25zdCBudW1SZWZzID0gdGhpcy5pbmNSZWZDb3VudChrZXkpO1xuICAgICAgICBjb25zdCBpc0ZpcnN0UmVmID0gbnVtUmVmcyA9PT0gMTtcbiAgICAgICAgcmV0dXJuIGlzRmlyc3RSZWYgPyBmaXJzdEFjdGlvbigpIDogbm9uRmlyc3RBY3Rpb24oKTtcbiAgICB9XG4gICAgLy8gRXhlY3V0ZSBsYXN0QWN0aW9uIGlmIGl0IGlzIHRoZSBmaXJzdCBzdWNoIHJlZiwgZWxzZSBleGVjdXRlIG5vbkxhc3RBY3Rpb24uXG4gICAgLy8gSW4gZWl0aGVyIGNhc2UgdGhlIHJldHVybiB2YWx1ZSBpcyB0aGF0IG9mIHRoZSBhY3Rpb24gZXhlY3V0ZWRcbiAgICBhY3RPbkxhc3Qoa2V5LCBsYXN0QWN0aW9uLCBub25MYXN0QWN0aW9uKSB7XG4gICAgICAgIGNvbnN0IG51bVJlZnMgPSB0aGlzLmRlY1JlZkNvdW50KGtleSk7XG4gICAgICAgIGNvbnN0IGlzTGFzdFJlZiA9IG51bVJlZnMgPT09IDA7XG4gICAgICAgIHJldHVybiBpc0xhc3RSZWYgPyBsYXN0QWN0aW9uKCkgOiBub25MYXN0QWN0aW9uKCk7XG4gICAgfVxufVxucmVmQ291bnRlci5SZWZDb3VudGVyID0gUmVmQ291bnRlcjtcblxudmFyIGNoYW5uZWwkMSA9IHt9O1xuXG52YXIgY2xpZW50ID0ge307XG5cbnZhciBjaGFubmVsID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShjaGFubmVsLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNoYW5uZWwuQ2hhbm5lbEJhc2UgPSBjaGFubmVsLlByb3RlY3RlZEl0ZW1zID0gdm9pZCAwO1xuY29uc3QgcmVzdWx0T3JQYXlsb2FkID0gKGZ1bmMpID0+IGFzeW5jICh0b3BpYywgcGF5bG9hZCwgc2VuZGVySWRlbnRpdHkpID0+IHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBmdW5jKHRvcGljLCBwYXlsb2FkLCBzZW5kZXJJZGVudGl0eSk7XG4gICAgcmV0dXJuIHJlcyA9PT0gdW5kZWZpbmVkID8gcGF5bG9hZCA6IHJlcztcbn07XG5jbGFzcyBQcm90ZWN0ZWRJdGVtcyB7XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZWxlc3MtY29uc3RydWN0b3JcbiAgICBjb25zdHJ1Y3Rvcihwcm92aWRlcklkZW50aXR5LCBjbG9zZSkge1xuICAgICAgICB0aGlzLnByb3ZpZGVySWRlbnRpdHkgPSBwcm92aWRlcklkZW50aXR5O1xuICAgICAgICB0aGlzLmNsb3NlID0gY2xvc2U7XG4gICAgfVxufVxuY2hhbm5lbC5Qcm90ZWN0ZWRJdGVtcyA9IFByb3RlY3RlZEl0ZW1zO1xuY2xhc3MgQ2hhbm5lbEJhc2Uge1xuICAgIHN0YXRpYyBkZWZhdWx0QWN0aW9uKHRvcGljKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gYWN0aW9uIHJlZ2lzdGVyZWQgYXQgdGFyZ2V0IGZvciAke3RvcGljfWApO1xuICAgIH1cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zID0gbmV3IE1hcCgpO1xuICAgIH1cbiAgICBhc3luYyBwcm9jZXNzQWN0aW9uKHRvcGljLCBwYXlsb2FkLCBzZW5kZXJJZGVudGl0eSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgbWFpbkFjdGlvbiA9IHRoaXMuc3Vic2NyaXB0aW9ucy5oYXModG9waWMpXG4gICAgICAgICAgICAgICAgPyB0aGlzLnN1YnNjcmlwdGlvbnMuZ2V0KHRvcGljKVxuICAgICAgICAgICAgICAgIDogKGN1cnJlbnRQYXlsb2FkLCBpZCkgPT4gKHRoaXMuZGVmYXVsdEFjdGlvbiA/PyBDaGFubmVsQmFzZS5kZWZhdWx0QWN0aW9uKSh0b3BpYywgY3VycmVudFBheWxvYWQsIGlkKTtcbiAgICAgICAgICAgIGNvbnN0IHByZUFjdGlvblByb2Nlc3NlZCA9IHRoaXMucHJlQWN0aW9uID8gYXdhaXQgdGhpcy5wcmVBY3Rpb24odG9waWMsIHBheWxvYWQsIHNlbmRlcklkZW50aXR5KSA6IHBheWxvYWQ7XG4gICAgICAgICAgICBjb25zdCBhY3Rpb25Qcm9jZXNzZWQgPSBhd2FpdCBtYWluQWN0aW9uKHByZUFjdGlvblByb2Nlc3NlZCwgc2VuZGVySWRlbnRpdHkpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucG9zdEFjdGlvbiA/IGF3YWl0IHRoaXMucG9zdEFjdGlvbih0b3BpYywgYWN0aW9uUHJvY2Vzc2VkLCBzZW5kZXJJZGVudGl0eSkgOiBhY3Rpb25Qcm9jZXNzZWQ7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmVycm9yTWlkZGxld2FyZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmVycm9yTWlkZGxld2FyZSh0b3BpYywgZSwgc2VuZGVySWRlbnRpdHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBtaWRkbGV3YXJlIHRoYXQgZmlyZXMgYmVmb3JlIHRoZSBhY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZnVuY1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIENoYW5uZWwgUHJvdmlkZXI6XG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgcHJvdmlkZXIucmVnaXN0ZXIoJ3Byb3ZpZGVyLWFjdGlvbicsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2cocGF5bG9hZCwgaWRlbnRpdHkpO1xuICAgICAqICAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgICBlY2hvOiBwYXlsb2FkXG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqICAgICBwcm92aWRlci5iZWZvcmVBY3Rpb24oKGFjdGlvbiwgcGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgIC8vVGhlIHBheWxvYWQgY2FuIGJlIGFsdGVyZWQgaGVyZSBiZWZvcmUgaGFuZGxpbmcgdGhlIGFjdGlvbi5cbiAgICAgKiAgICAgICAgIHBheWxvYWQucmVjZWl2ZWQgPSBEYXRlLm5vdygpO1xuICAgICAqICAgICAgICAgcmV0dXJuIHBheWxvYWQ7XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIENoYW5uZWwgQ2xpZW50OlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3QoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgY2xpZW50LnJlZ2lzdGVyKCdjbGllbnQtYWN0aW9uJywgKHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhwYXlsb2FkLCBpZGVudGl0eSk7XG4gICAgICogICAgICAgICByZXR1cm4ge1xuICAgICAqICAgICAgICAgICAgIGVjaG86IHBheWxvYWRcbiAgICAgKiAgICAgICAgIH07XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogICAgIGNsaWVudC5iZWZvcmVBY3Rpb24oKGFjdGlvbiwgcGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgIC8vVGhlIHBheWxvYWQgY2FuIGJlIGFsdGVyZWQgaGVyZSBiZWZvcmUgaGFuZGxpbmcgdGhlIGFjdGlvbi5cbiAgICAgKiAgICAgICAgIHBheWxvYWQucmVjZWl2ZWQgPSBEYXRlLm5vdygpO1xuICAgICAqICAgICAgICAgcmV0dXJuIHBheWxvYWQ7XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyUmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ3Byb3ZpZGVyLWFjdGlvbicsIHsgbWVzc2FnZTogJ0hlbGxvIEZyb20gdGhlIGNsaWVudCcgfSk7XG4gICAgICogICAgIGNvbnNvbGUubG9nKHByb3ZpZGVyUmVzcG9uc2UpO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYmVmb3JlQWN0aW9uKGZ1bmMpIHtcbiAgICAgICAgaWYgKHRoaXMucHJlQWN0aW9uKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FscmVhZHkgcmVnaXN0ZXJlZCBiZWZvcmVBY3Rpb24gbWlkZGxld2FyZScpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucHJlQWN0aW9uID0gcmVzdWx0T3JQYXlsb2FkKGZ1bmMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhbiBlcnJvciBoYW5kbGVyLiBUaGlzIGlzIGNhbGxlZCBiZWZvcmUgcmVzcG9uZGluZyBvbiBhbnkgZXJyb3IuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZnVuY1xuICAgICAqXG4gICAgICogQ2hhbm5lbCBQcm92aWRlcjpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZSgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgICBwcm92aWRlci5yZWdpc3RlcigncHJvdmlkZXItYWN0aW9uJywgKHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhwYXlsb2FkKTtcbiAgICAgKiAgICAgICAgIHRocm93IG5ldyBFcnJvcignQWN0aW9uIGVycm9yJyk7XG4gICAgICogICAgICAgICByZXR1cm4ge1xuICAgICAqICAgICAgICAgICAgIGVjaG86IHBheWxvYWRcbiAgICAgKiAgICAgICAgIH07XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogICAgIHByb3ZpZGVyLm9uRXJyb3IoKGFjdGlvbiwgZXJyb3IsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZygndW5jYXVnaHQgRXhjZXB0aW9uIGluIGFjdGlvbjonLCBhY3Rpb24pO1xuICAgICAqICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIENoYW5uZWwgQ2xpZW50OlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3QoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgY2xpZW50LnJlZ2lzdGVyKCdjbGllbnQtYWN0aW9uJywgKHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhwYXlsb2FkKTtcbiAgICAgKiAgICAgICAgIHRocm93IG5ldyBFcnJvcignQWN0aW9uIGVycm9yJyk7XG4gICAgICogICAgICAgICByZXR1cm4ge1xuICAgICAqICAgICAgICAgICAgIGVjaG86IHBheWxvYWRcbiAgICAgKiAgICAgICAgIH07XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogICAgIGNsaWVudC5vbkVycm9yKChhY3Rpb24sIGVycm9yLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ3VuY2F1Z2h0IEV4Y2VwdGlvbiBpbiBhY3Rpb246JywgYWN0aW9uKTtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAqICAgICB9KTtcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIG9uRXJyb3IoZnVuYykge1xuICAgICAgICBpZiAodGhpcy5lcnJvck1pZGRsZXdhcmUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQWxyZWFkeSByZWdpc3RlcmVkIGVycm9yIG1pZGRsZXdhcmUnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmVycm9yTWlkZGxld2FyZSA9IGZ1bmM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIG1pZGRsZXdhcmUgdGhhdCBmaXJlcyBhZnRlciB0aGUgYWN0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZ1bmNcbiAgICAgKlxuICAgICAqIEByZW1hcmtzIElmIHRoZSBhY3Rpb24gZG9lcyBub3QgcmV0dXJuIHRoZSBwYXlsb2FkLCB0aGVuIHRoZSBhZnRlckFjdGlvbiB3aWxsIG5vdCBoYXZlIGFjY2VzcyB0byB0aGUgcGF5bG9hZCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogQ2hhbm5lbCBQcm92aWRlcjpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZSgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCBwcm92aWRlci5yZWdpc3RlcigncHJvdmlkZXItYWN0aW9uJywgKHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICByZXR1cm4ge1xuICAgICAqICAgICAgICAgICAgIGVjaG86IHBheWxvYWRcbiAgICAgKiAgICAgICAgIH07XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHByb3ZpZGVyLmFmdGVyQWN0aW9uKChhY3Rpb24sIHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICAvL3RoZSBwYXlsb2FkIGNhbiBiZSBhbHRlcmVkIGhlcmUgYWZ0ZXIgaGFuZGxpbmcgdGhlIGFjdGlvbiBidXQgYmVmb3JlIHNlbmRpbmcgYW4gYWNrbm93bGVkZ2VtZW50LlxuICAgICAqICAgICAgICAgcGF5bG9hZC5zZW50ID0gZGF0ZS5ub3coKTtcbiAgICAgKiAgICAgICAgIHJldHVybiBwYXlsb2FkO1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBDaGFubmVsIENsaWVudDpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IGNsaWVudC5yZWdpc3RlcignY2xpZW50LWFjdGlvbicsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgICBlY2hvOiBwYXlsb2FkXG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCBjbGllbnQuYWZ0ZXJBY3Rpb24oKGFjdGlvbiwgcGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgIC8vdGhlIHBheWxvYWQgY2FuIGJlIGFsdGVyZWQgaGVyZSBhZnRlciBoYW5kbGluZyB0aGUgYWN0aW9uIGJ1dCBiZWZvcmUgc2VuZGluZyBhbiBhY2tub3dsZWRnZW1lbnQuXG4gICAgICogICAgICAgICBwYXlsb2FkLnNlbnQgPSBkYXRlLm5vdygpO1xuICAgICAqICAgICAgICAgcmV0dXJuIHBheWxvYWQ7XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhZnRlckFjdGlvbihmdW5jKSB7XG4gICAgICAgIGlmICh0aGlzLnBvc3RBY3Rpb24pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQWxyZWFkeSByZWdpc3RlcmVkIGFmdGVyQWN0aW9uIG1pZGRsZXdhcmUnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnBvc3RBY3Rpb24gPSByZXN1bHRPclBheWxvYWQoZnVuYyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbW92ZSBhbiBhY3Rpb24gYnkgYWN0aW9uIG5hbWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYWN0aW9uXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgcHJvdmlkZXIucmVnaXN0ZXIoJ3Byb3ZpZGVyLWFjdGlvbicsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2cocGF5bG9hZCk7XG4gICAgICogICAgICAgICByZXR1cm4ge1xuICAgICAqICAgICAgICAgICAgIGVjaG86IHBheWxvYWRcbiAgICAgKiAgICAgICAgIH07XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHByb3ZpZGVyLnJlbW92ZSgncHJvdmlkZXItYWN0aW9uJyk7XG4gICAgICpcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHJlbW92ZShhY3Rpb24pIHtcbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLmRlbGV0ZShhY3Rpb24pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgYSBkZWZhdWx0IGFjdGlvbi4gVGhpcyBpcyB1c2VkIGFueSB0aW1lIGFuIGFjdGlvbiB0aGF0IGhhcyBub3QgYmVlbiByZWdpc3RlcmVkIGlzIGludm9rZWQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogQ2hhbm5lbCBQcm92aWRlcjpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZSgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCBwcm92aWRlci5zZXREZWZhdWx0QWN0aW9uKChhY3Rpb24sIHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhgQ2xpZW50IHdpdGggaWRlbnRpdHkgJHtKU09OLnN0cmluZ2lmeShpZGVudGl0eSl9IGhhcyBhdHRlbXB0ZWQgdG8gZGlzcGF0Y2ggdW5yZWdpc3RlcmVkIGFjdGlvbjogJHthY3Rpb259LmApO1xuICAgICAqXG4gICAgICogICAgICAgICByZXR1cm4ge1xuICAgICAqICAgICAgICAgICAgIGVjaG86IHBheWxvYWRcbiAgICAgKiAgICAgICAgIH07XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIENoYW5uZWwgQ2xpZW50OlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3QoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgY2xpZW50LnNldERlZmF1bHRBY3Rpb24oKGFjdGlvbiwgcGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKGBQcm92aWRlciB3aXRoIGlkZW50aXR5ICR7SlNPTi5zdHJpbmdpZnkoaWRlbnRpdHkpfSBoYXMgYXR0ZW1wdGVkIHRvIGRpc3BhdGNoIHVucmVnaXN0ZXJlZCBhY3Rpb246ICR7YWN0aW9ufS5gKTtcbiAgICAgKlxuICAgICAqICAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgICBlY2hvOiBwYXlsb2FkXG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICogQHBhcmFtIGZ1bmNcbiAgICAgKi9cbiAgICBzZXREZWZhdWx0QWN0aW9uKGZ1bmMpIHtcbiAgICAgICAgaWYgKHRoaXMuZGVmYXVsdEFjdGlvbikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkZWZhdWx0IGFjdGlvbiBjYW4gb25seSBiZSBzZXQgb25jZScpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kZWZhdWx0QWN0aW9uID0gZnVuYztcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhbiBhY3Rpb24gdG8gYmUgY2FsbGVkIGJ5IGRpc3BhdGNoaW5nIGZyb20gYW55IGNoYW5uZWxDbGllbnQgb3IgY2hhbm5lbFByb3ZpZGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHRvcGljXG4gICAgICogQHBhcmFtIGxpc3RlbmVyXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBUaGUgcmV0dXJuIHZhbHVlIHdpbGwgYmUgc2VudCBiYWNrIGFzIGFuIGFja25vd2xlZGdlbWVudCB0byB0aGUgb3JpZ2luYWwgY2FsbGVyLiBZb3UgY2FuIHRocm93IGFuXG4gICAgICogZXJyb3IgdG8gc2VuZCBhIG5lZ2F0aXZlLWFja25vd2xlZGdlbWVudCBhbmQgdGhlIGVycm9yIHdpbGwgcmVqZWN0IHRoZSBwcm9taXNlIHJldHVybmVkIHRvIHRoZSBzZW5kZXIgYnkgdGhlXG4gICAgICogZGlzcGF0Y2ggY2FsbC4gIE9uY2UgYSBsaXN0ZW5lciBpcyByZWdpc3RlcmVkIGZvciBhIHBhcnRpY3VsYXIgYWN0aW9uLCBpdCBzdGF5cyBpbiBwbGFjZSByZWNlaXZpbmcgYW5kIHJlc3BvbmRpbmdcbiAgICAgKiB0byBpbmNvbWluZyBtZXNzYWdlcyB1bnRpbCBpdCBpcyByZW1vdmVkLiAgVGhpcyBtZXNzYWdpbmcgbWVjaGFuaXNtIHdvcmtzIGV4YWN0bHkgdGhlIHNhbWUgd2hlbiBtZXNzYWdlcyBhcmVcbiAgICAgKiBkaXNwYXRjaGVkIGZyb20gdGhlIHByb3ZpZGVyIHRvIGEgY2xpZW50LiAgSG93ZXZlciwgdGhlIHByb3ZpZGVyIGhhcyBhbiBhZGRpdGlvbmFsIHB1Ymxpc2ggbWV0aG9kIHRoYXQgc2VuZHMgbWVzc2FnZXNcbiAgICAgKiB0byBhbGwgY29ubmVjdGVkIGNsaWVudHMuXG4gICAgICpcbiAgICAgKiBCZWNhdXNlIG11bHRpcGxlIGNsaWVudHMgY2FuIHNoYXJlIHRoZSBzYW1lIGBuYW1lYCBhbmQgYHV1aWRgLCBpbiBvcmRlciB0byBkaXN0aW5ndWlzaCBiZXR3ZWVuIGluZGl2aWR1YWwgY2xpZW50cyxcbiAgICAgKiB0aGUgYGlkZW50aXR5YCBhcmd1bWVudCBpbiBhIHByb3ZpZGVyJ3MgcmVnaXN0ZXJlZCBhY3Rpb24gY2FsbGJhY2sgY29udGFpbnMgYW4gYGVuZHBvaW50SWRgIHByb3BlcnR5LiBXaGVuIGRpc3BhdGNoaW5nXG4gICAgICogZnJvbSBhIHByb3ZpZGVyIHRvIGEgY2xpZW50LCB0aGUgYGVuZHBvaW50SWRgIHByb3BlcnR5IG11c3QgYmUgcHJvdmlkZWQgaW4gb3JkZXIgdG8gc2VuZCBhbiBhY3Rpb24gdG8gYSBzcGVjaWZpYyBjbGllbnQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogQ2hhbm5lbCBQcm92aWRlcjpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZSgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCBwcm92aWRlci5yZWdpc3RlcigncHJvdmlkZXItYWN0aW9uJywgKHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgIGNvbnNvbGUubG9nKCdBY3Rpb24gZGlzcGF0Y2hlZCBieSBjbGllbnQ6ICcsIGlkZW50aXR5KTtcbiAgICAgKiAgICAgICAgY29uc29sZS5sb2coJ1BheWxvYWQgc2VudCBpbiBkaXNwYXRjaDogJywgcGF5bG9hZCk7XG4gICAgICpcbiAgICAgKiAgICAgICAgcmV0dXJuIHsgZWNobzogcGF5bG9hZCB9O1xuICAgICAqICAgIH0pO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBDaGFubmVsIENsaWVudDpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IGNsaWVudC5yZWdpc3RlcignY2xpZW50LWFjdGlvbicsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICBjb25zb2xlLmxvZygnQWN0aW9uIGRpc3BhdGNoZWQgYnkgY2xpZW50OiAnLCBpZGVudGl0eSk7XG4gICAgICogICAgICAgIGNvbnNvbGUubG9nKCdQYXlsb2FkIHNlbnQgaW4gZGlzcGF0Y2g6ICcsIHBheWxvYWQpO1xuICAgICAqXG4gICAgICogICAgICAgIHJldHVybiB7IGVjaG86IHBheWxvYWQgfTtcbiAgICAgKiAgICB9KTtcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHJlZ2lzdGVyKHRvcGljLCBsaXN0ZW5lcikge1xuICAgICAgICBpZiAodGhpcy5zdWJzY3JpcHRpb25zLmhhcyh0b3BpYykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU3Vic2NyaXB0aW9uIGFscmVhZHkgcmVnaXN0ZXJlZCBmb3IgYWN0aW9uOiAke3RvcGljfS4gVW5zdWJzY3JpYmUgYmVmb3JlIGFkZGluZyBuZXcgc3Vic2NyaXB0aW9uYCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnN1YnNjcmlwdGlvbnMuc2V0KHRvcGljLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbn1cbmNoYW5uZWwuQ2hhbm5lbEJhc2UgPSBDaGFubmVsQmFzZTtcblxudmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkYSA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcbn07XG52YXIgX0NoYW5uZWxDbGllbnRfcHJvdGVjdGVkT2JqLCBfQ2hhbm5lbENsaWVudF9zdHJhdGVneSwgX0NoYW5uZWxDbGllbnRfY2xvc2U7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoY2xpZW50LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNsaWVudC5DaGFubmVsQ2xpZW50ID0gdm9pZCAwO1xuY29uc3QgY2hhbm5lbF8xJDEgPSBjaGFubmVsO1xuY29uc3QgY2hhbm5lbENsaWVudHNCeUVuZHBvaW50SWQgPSBuZXcgTWFwKCk7XG4vKipcbiAqIEluc3RhbmNlIGNyZWF0ZWQgdG8gZW5hYmxlIHVzZSBvZiBhIGNoYW5uZWwgYXMgYSBjbGllbnQuICBBbGxvd3MgZm9yIGNvbW11bmljYXRpb24gd2l0aCB0aGVcbiAqIHtAbGluayBDaGFubmVsUHJvdmlkZXIgQ2hhbm5lbFByb3ZpZGVyfSBieSBpbnZva2luZyBhbiBhY3Rpb24gb24gdGhlXG4gKiBwcm92aWRlciB2aWEge0BsaW5rIENoYW5uZWxDbGllbnQjZGlzcGF0Y2ggZGlzcGF0Y2h9IGFuZCB0byBsaXN0ZW4gZm9yIGNvbW11bmljYXRpb25cbiAqIGZyb20gdGhlIHByb3ZpZGVyIGJ5IHJlZ2lzdGVyaW5nIGFuIGFjdGlvbiB2aWEge0BsaW5rIENoYW5uZWxDbGllbnQjcmVnaXN0ZXIgcmVnaXN0ZXJ9LlxuICpcbiAqICMjIyBTeW5jaHJvbm91cyBNZXRob2RzOlxuICogICoge0BsaW5rIENoYW5uZWxDbGllbnQjb25EaXNjb25uZWN0aW9uIG9uRGlzY29ubmVjdGlvbihsaXN0ZW5lcil9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbENsaWVudCNyZWdpc3RlciByZWdpc3RlcihhY3Rpb24sIGxpc3RlbmVyKX1cbiAqICAqIHtAbGluayBDaGFubmVsQ2xpZW50I3JlbW92ZSByZW1vdmUoYWN0aW9uKX1cbiAqXG4gKiAjIyMgQXN5bmNocm9ub3VzIE1ldGhvZHM6XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbENsaWVudCNkaXNjb25uZWN0IGRpc2Nvbm5lY3QoKX1cbiAqICAqIHtAbGluayBDaGFubmVsQ2xpZW50I2Rpc3BhdGNoIGRpc3BhdGNoKGFjdGlvbiwgcGF5bG9hZCl9XG4gKlxuICogIyMjIE1pZGRsZXdhcmU6XG4gKiBNaWRkbGV3YXJlIGZ1bmN0aW9ucyByZWNlaXZlIHRoZSBmb2xsb3dpbmcgYXJndW1lbnRzOiAoYWN0aW9uLCBwYXlsb2FkLCBzZW5kZXJJZCkuXG4gKiBUaGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBtaWRkbGV3YXJlIGZ1bmN0aW9uIHdpbGwgYmUgcGFzc2VkIG9uIGFzIHRoZSBwYXlsb2FkIGZyb20gYmVmb3JlQWN0aW9uLCB0byB0aGUgYWN0aW9uIGxpc3RlbmVyLCB0byBhZnRlckFjdGlvblxuICogdW5sZXNzIGl0IGlzIHVuZGVmaW5lZCwgaW4gd2hpY2ggY2FzZSB0aGUgb3JpZ2luYWwgcGF5bG9hZCBpcyB1c2VkLiAgTWlkZGxld2FyZSBjYW4gYmUgdXNlZCBmb3Igc2lkZSBlZmZlY3RzLlxuICogICoge0BsaW5rIENoYW5uZWxDbGllbnQjc2V0RGVmYXVsdEFjdGlvbiBzZXREZWZhdWx0QWN0aW9uKG1pZGRsZXdhcmUpfVxuICogICoge0BsaW5rIENoYW5uZWxDbGllbnQjb25FcnJvciBvbkVycm9yKG1pZGRsZXdhcmUpfVxuICogICoge0BsaW5rIENoYW5uZWxDbGllbnQjYmVmb3JlQWN0aW9uIGJlZm9yZUFjdGlvbihtaWRkbGV3YXJlKX1cbiAqICAqIHtAbGluayBDaGFubmVsQ2xpZW50I2FmdGVyQWN0aW9uIGFmdGVyQWN0aW9uKG1pZGRsZXdhcmUpfVxuICovXG5jbGFzcyBDaGFubmVsQ2xpZW50IGV4dGVuZHMgY2hhbm5lbF8xJDEuQ2hhbm5lbEJhc2Uge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIHN0YXRpYyBjbG9zZUNoYW5uZWxCeUVuZHBvaW50SWQoaWQpIHtcbiAgICAgICAgY29uc3QgY2hhbm5lbCA9IGNoYW5uZWxDbGllbnRzQnlFbmRwb2ludElkLmdldChpZCk7XG4gICAgICAgIGlmIChjaGFubmVsKSB7XG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGMoY2hhbm5lbCwgX0NoYW5uZWxDbGllbnRfY2xvc2UsIFwiZlwiKS5jYWxsKGNoYW5uZWwpO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqIGNsb3NlcyB0aGUgY29ycmVzcG9uZGluZyBjaGFubmVsIGFuZCBpbnZva2VzIHRoZSBkaXNjb25uZWN0IGxpc3RlbmVyIGlmIGFuIGV2ZW50IHBheWxvYWQgaXMgcGFzc2VkLlxuICAgICAqL1xuICAgIHN0YXRpYyBoYW5kbGVQcm92aWRlckRpc2Nvbm5lY3QoZXZlbnRQYXlsb2FkKSB7XG4gICAgICAgIGZvciAoY29uc3QgY2hhbm5lbENsaWVudCBvZiBjaGFubmVsQ2xpZW50c0J5RW5kcG9pbnRJZC52YWx1ZXMoKSkge1xuICAgICAgICAgICAgaWYgKGNoYW5uZWxDbGllbnQucHJvdmlkZXJJZGVudGl0eS5jaGFubmVsSWQgPT09IGV2ZW50UGF5bG9hZC5jaGFubmVsSWQpIHtcbiAgICAgICAgICAgICAgICBjaGFubmVsQ2xpZW50LmRpc2Nvbm5lY3RMaXN0ZW5lcihldmVudFBheWxvYWQpO1xuICAgICAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYyhjaGFubmVsQ2xpZW50LCBfQ2hhbm5lbENsaWVudF9jbG9zZSwgXCJmXCIpLmNhbGwoY2hhbm5lbENsaWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iocm91dGluZ0luZm8sIGNsb3NlLCBzdHJhdGVneSkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICBfQ2hhbm5lbENsaWVudF9wcm90ZWN0ZWRPYmouc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIF9DaGFubmVsQ2xpZW50X3N0cmF0ZWd5LnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICAvLyBuZWVkcyB0byBiZSBib3VuZDtcbiAgICAgICAgdGhpcy5wcm9jZXNzQWN0aW9uID0gKGFjdGlvbiwgcGF5bG9hZCwgc2VuZGVySWRlbnRpdHkpID0+IHN1cGVyLnByb2Nlc3NBY3Rpb24oYWN0aW9uLCBwYXlsb2FkLCBzZW5kZXJJZGVudGl0eSk7XG4gICAgICAgIF9DaGFubmVsQ2xpZW50X2Nsb3NlLnNldCh0aGlzLCAoKSA9PiB7XG4gICAgICAgICAgICBjaGFubmVsQ2xpZW50c0J5RW5kcG9pbnRJZC5kZWxldGUodGhpcy5lbmRwb2ludElkKTtcbiAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYyh0aGlzLCBfQ2hhbm5lbENsaWVudF9zdHJhdGVneSwgXCJmXCIpLmNsb3NlKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JGEodGhpcywgX0NoYW5uZWxDbGllbnRfcHJvdGVjdGVkT2JqLCBuZXcgY2hhbm5lbF8xJDEuUHJvdGVjdGVkSXRlbXMocm91dGluZ0luZm8sIGNsb3NlKSwgXCJmXCIpO1xuICAgICAgICB0aGlzLmRpc2Nvbm5lY3RMaXN0ZW5lciA9ICgpID0+IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5lbmRwb2ludElkID0gcm91dGluZ0luZm8uZW5kcG9pbnRJZDtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCRhKHRoaXMsIF9DaGFubmVsQ2xpZW50X3N0cmF0ZWd5LCBzdHJhdGVneSwgXCJmXCIpO1xuICAgICAgICBjaGFubmVsQ2xpZW50c0J5RW5kcG9pbnRJZC5zZXQodGhpcy5lbmRwb2ludElkLCB0aGlzKTtcbiAgICAgICAgc3RyYXRlZ3kucmVjZWl2ZSh0aGlzLnByb2Nlc3NBY3Rpb24pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBhIHJlYWQtb25seSBwcm92aWRlciBpZGVudGl0eVxuICAgICAqL1xuICAgIGdldCBwcm92aWRlcklkZW50aXR5KCkge1xuICAgICAgICBjb25zdCBwcm90ZWN0ZWRPYmogPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGModGhpcywgX0NoYW5uZWxDbGllbnRfcHJvdGVjdGVkT2JqLCBcImZcIik7XG4gICAgICAgIHJldHVybiBwcm90ZWN0ZWRPYmoucHJvdmlkZXJJZGVudGl0eTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRGlzcGF0Y2ggdGhlIGdpdmVuIGFjdGlvbiB0byB0aGUgY2hhbm5lbCBwcm92aWRlci4gUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSByZXNwb25zZSBmcm9tXG4gICAgICogdGhlIHByb3ZpZGVyIGZvciB0aGF0IGFjdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBhY3Rpb25cbiAgICAgKiBAcGFyYW0gcGF5bG9hZFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3QoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgY2xpZW50LnJlZ2lzdGVyKCdjbGllbnQtYWN0aW9uJywgKHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhwYXlsb2FkLCBpZGVudGl0eSk7XG4gICAgICogICAgICAgICByZXR1cm4ge1xuICAgICAqICAgICAgICAgICAgIGVjaG86IHBheWxvYWRcbiAgICAgKiAgICAgICAgIH07XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyUmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ3Byb3ZpZGVyLWFjdGlvbicsIHsgbWVzc2FnZTogJ0hlbGxvIEZyb20gdGhlIGNsaWVudCd9KTtcbiAgICAgKiAgICAgY29uc29sZS5sb2cocHJvdmlkZXJSZXNwb25zZSk7XG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBkaXNwYXRjaChhY3Rpb24sIHBheWxvYWQpIHtcbiAgICAgICAgaWYgKF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYyh0aGlzLCBfQ2hhbm5lbENsaWVudF9zdHJhdGVneSwgXCJmXCIpLmlzRW5kcG9pbnRDb25uZWN0ZWQodGhpcy5wcm92aWRlcklkZW50aXR5LmNoYW5uZWxJZCkpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGModGhpcywgX0NoYW5uZWxDbGllbnRfc3RyYXRlZ3ksIFwiZlwiKS5zZW5kKHRoaXMucHJvdmlkZXJJZGVudGl0eS5jaGFubmVsSWQsIGFjdGlvbiwgcGF5bG9hZCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgY2xpZW50IHlvdSBhcmUgdHJ5aW5nIHRvIGRpc3BhdGNoIGZyb20gaXMgZGlzY29ubmVjdGVkIGZyb20gdGhlIHRhcmdldCBwcm92aWRlci4nKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYSBsaXN0ZW5lciB0aGF0IGlzIGNhbGxlZCBvbiBwcm92aWRlciBkaXNjb25uZWN0aW9uLiBJdCBpcyBwYXNzZWQgdGhlIGRpc2Nvbm5lY3Rpb24gZXZlbnQgb2YgdGhlXG4gICAgICogZGlzY29ubmVjdGluZyBwcm92aWRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBsaXN0ZW5lclxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3QoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgY2xpZW50Lm9uRGlzY29ubmVjdGlvbihldnQgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ1Byb3ZpZGVyIGRpc2Nvbm5lY3RlZCcsIGB1dWlkOiAke2V2dC51dWlkfSwgbmFtZTogJHtldnQubmFtZX1gKTtcbiAgICAgKiAgICAgfSk7XG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBvbkRpc2Nvbm5lY3Rpb24obGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0TGlzdGVuZXIgPSAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcihwYXlsb2FkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoaWxlIGNhbGxpbmcgdGhlIG9uRGlzY29ubmVjdGlvbiBjYWxsYmFjazogJHtlcnIubWVzc2FnZX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzY29ubmVjdExpc3RlbmVyID0gKCkgPT4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBEaXNjb25uZWN0cyB0aGUgY2xpZW50IGZyb20gdGhlIGNoYW5uZWwuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY29ubmVjdCgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCBjbGllbnQuZGlzY29ubmVjdCgpO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZGlzY29ubmVjdCgpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5zZW5kRGlzY29ubmVjdEFjdGlvbigpO1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGModGhpcywgX0NoYW5uZWxDbGllbnRfY2xvc2UsIFwiZlwiKS5jYWxsKHRoaXMpO1xuICAgIH1cbiAgICBhc3luYyBzZW5kRGlzY29ubmVjdEFjdGlvbigpIHtcbiAgICAgICAgY29uc3QgcHJvdGVjdGVkT2JqID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCRjKHRoaXMsIF9DaGFubmVsQ2xpZW50X3Byb3RlY3RlZE9iaiwgXCJmXCIpO1xuICAgICAgICBhd2FpdCBwcm90ZWN0ZWRPYmouY2xvc2UoKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICogV3JpdGluZyB0aGlzIGFzIGEgc3RhdGljIHRvIGtlZXAgY29kZSB0b2dldGhlciwgYnV0IGluIGVudmlyb25tZW50cyB3aXRoIGEgd2lyZSwgdGhpcyB3aWxsIGJlIERJJ2QgaW50byB0aGUgcHJvdGVjdGVkT2JqZWN0IGNsYXNzIGFzIGNsb3NlLlxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyB3aXJlQ2xvc2Uod2lyZSwgcHJvdmlkZXJJZGVudGl0eSwgZW5kcG9pbnRJZCkge1xuICAgICAgICBjb25zdCB7IGNoYW5uZWxOYW1lLCB1dWlkLCBuYW1lIH0gPSBwcm92aWRlcklkZW50aXR5O1xuICAgICAgICBhd2FpdCB3aXJlLnNlbmRBY3Rpb24oJ2Rpc2Nvbm5lY3QtZnJvbS1jaGFubmVsJywge1xuICAgICAgICAgICAgY2hhbm5lbE5hbWUsXG4gICAgICAgICAgICB1dWlkLFxuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIGVuZHBvaW50SWRcbiAgICAgICAgfSk7XG4gICAgfVxufVxuY2xpZW50LkNoYW5uZWxDbGllbnQgPSBDaGFubmVsQ2xpZW50O1xuX0NoYW5uZWxDbGllbnRfcHJvdGVjdGVkT2JqID0gbmV3IFdlYWtNYXAoKSwgX0NoYW5uZWxDbGllbnRfc3RyYXRlZ3kgPSBuZXcgV2Vha01hcCgpLCBfQ2hhbm5lbENsaWVudF9jbG9zZSA9IG5ldyBXZWFrTWFwKCk7XG5cbnZhciBjb25uZWN0aW9uTWFuYWdlciA9IHt9O1xuXG52YXIgZXhoYXVzdGl2ZSA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhoYXVzdGl2ZSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leGhhdXN0aXZlLmV4aGF1c3RpdmVDaGVjayA9IHZvaWQgMDtcbmZ1bmN0aW9uIGV4aGF1c3RpdmVDaGVjayh2YWx1ZSwgYWxsb3dlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgdmFsdWU6ICR7dmFsdWV9JHthbGxvd2VkID8gYFxcbiBTdXBwb3J0ZWQgdmFsdWVzIGFyZTogJHthbGxvd2VkLmpvaW4oJycpfWAgOiAnJ31gKTtcbn1cbmV4aGF1c3RpdmUuZXhoYXVzdGl2ZUNoZWNrID0gZXhoYXVzdGl2ZUNoZWNrO1xuXG52YXIgc3RyYXRlZ3kkMyA9IHt9O1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ5ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xufTtcbnZhciBfQ2xhc3NpY1N0cmF0ZWd5X3dpcmUsIF9DbGFzc2ljU3RyYXRlZ3lfZW5kcG9pbnRJZGVudGl0eU1hcCwgX0NsYXNzaWNTdHJhdGVneV9wZW5kaW5nTWVzc2FnZXNCeUVuZHBvaW50SWQ7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoc3RyYXRlZ3kkMywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5zdHJhdGVneSQzLkNsYXNzaWNJbmZvID0gc3RyYXRlZ3kkMy5DbGFzc2ljU3RyYXRlZ3kgPSB2b2lkIDA7XG4vKlxuVGhpcyBpcyB1c2VkIHRvIGFic3RyYWN0IG91dCBpcGMgbWVzc2FnaW5nIGZyb20gdGhlIGNoYW5uZWxzIGltcGxlbWVudGF0aW9uLiBJdCBpcyBvbmx5IGNvbmNlcm5lZCB3aXRoIHNlbmRpbmcgbWVzc2FnZXMgYW5kIHJlZ2lzdHJhdGlvbiB3aXRoIHRoZSBNZXNzYWdlUmVjZWl2ZXJcbiovXG5jbGFzcyBDbGFzc2ljU3RyYXRlZ3kge1xuICAgIGNvbnN0cnVjdG9yKHdpcmUsIG1lc3NhZ2VSZWNlaXZlciwgZW5kcG9pbnRJZCwgLy8gUHJvdmlkZXIgZW5kcG9pbnRJZCBpcyBjaGFubmVsSWRcbiAgICBwcm92aWRlcklkZW50aXR5KSB7XG4gICAgICAgIHRoaXMubWVzc2FnZVJlY2VpdmVyID0gbWVzc2FnZVJlY2VpdmVyO1xuICAgICAgICB0aGlzLmVuZHBvaW50SWQgPSBlbmRwb2ludElkO1xuICAgICAgICB0aGlzLnByb3ZpZGVySWRlbnRpdHkgPSBwcm92aWRlcklkZW50aXR5O1xuICAgICAgICBfQ2xhc3NpY1N0cmF0ZWd5X3dpcmUuc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIC8vIFN0b3JlIGZ1bGwgZW5kcG9pbnRJZGVudGl0eSBieSBlbmRwb2ludElkIG9mIGFsbCBrbm93biBlbmRwb2ludHMgZm9yIHRoaXMgc3RyYXRlZ3kgaW5zdGFuY2UuXG4gICAgICAgIC8vIChjbGllbnRzIHdpbGwgb25seSBoYXZlIDE6IHRoZSBwcm92aWRlciwgdGhlIHByb3ZpZGVyIHdpbGwgaGF2ZSBhbGwgY2xpZW50cylcbiAgICAgICAgX0NsYXNzaWNTdHJhdGVneV9lbmRwb2ludElkZW50aXR5TWFwLnNldCh0aGlzLCBuZXcgTWFwKCkpO1xuICAgICAgICAvLyBTdG9yZSBhIHNldCBvZiBjYW5jZWxsYWJsZSBwcm9taXNlcyB0byBiZSBhYmxlIHRvIHJlamVjdCB0aGVtIHdoZW4gY2xpZW50XG4gICAgICAgIC8vIGNvbm5lY3Rpb24gcHJvYmxlbXMgb2NjdXJcbiAgICAgICAgX0NsYXNzaWNTdHJhdGVneV9wZW5kaW5nTWVzc2FnZXNCeUVuZHBvaW50SWQuc2V0KHRoaXMsIG5ldyBNYXApO1xuICAgICAgICB0aGlzLnNlbmQgPSBhc3luYyAoZW5kcG9pbnRJZCwgYWN0aW9uLCBwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0byA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYih0aGlzLCBfQ2xhc3NpY1N0cmF0ZWd5X2VuZHBvaW50SWRlbnRpdHlNYXAsIFwiZlwiKS5nZXQoZW5kcG9pbnRJZCk7XG4gICAgICAgICAgICBpZiAoIXRvKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgbG9jYXRlIHJvdXRpbmcgaW5mbyBmb3IgZW5kcG9pbnQgJHtlbmRwb2ludElkfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gYXMgY2FzdGluZyB0byBhbnkgYmVjYXVzZSB0eXBlc2NyaXB0IGNvbXBsYWlucy4gVGhlIGZvbGxvd2luZyBpcyBvbmx5IHJlbGV2YW50IGlmIHRoaXMgaXMgYSBsb2NhbGx5IHNldCBlbmRwb2ludElkIG9uIGEgQ2xpZW50SWRlbnRpdHkuXG4gICAgICAgICAgICAvLyBXZSBkZWxldGUgdGhlc2UgcHJvcGVydGllcyB0byBub3QgY2hhbmdlIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LlxuICAgICAgICAgICAgY29uc3QgY2xlYW5JZCA9IHsgLi4udG8gfTtcbiAgICAgICAgICAgIGlmIChjbGVhbklkLmlzTG9jYWxFbmRwb2ludElkKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGNsZWFuSWQuZW5kcG9pbnRJZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRlbGV0ZSBjbGVhbklkLmlzTG9jYWxFbmRwb2ludElkO1xuICAgICAgICAgICAgLy8gZ3JhYiB0aGUgcHJvbWlzZSBiZWZvcmUgYXdhaXRpbmcgaXQgdG8gc2F2ZSBpbiBvdXIgcGVuZGluZyBtZXNzYWdlcyBtYXBcbiAgICAgICAgICAgIGNvbnN0IHAgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGIodGhpcywgX0NsYXNzaWNTdHJhdGVneV93aXJlLCBcImZcIilcbiAgICAgICAgICAgICAgICAuc2VuZEFjdGlvbignc2VuZC1jaGFubmVsLW1lc3NhZ2UnLCB7XG4gICAgICAgICAgICAgICAgLi4uY2xlYW5JZCxcbiAgICAgICAgICAgICAgICBwcm92aWRlcklkZW50aXR5OiB0aGlzLnByb3ZpZGVySWRlbnRpdHksXG4gICAgICAgICAgICAgICAgYWN0aW9uLFxuICAgICAgICAgICAgICAgIHBheWxvYWRcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRiKHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfcGVuZGluZ01lc3NhZ2VzQnlFbmRwb2ludElkLCBcImZcIikuZ2V0KGVuZHBvaW50SWQpPy5hZGQocCk7XG4gICAgICAgICAgICBjb25zdCByYXcgPSBhd2FpdCBwLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvci5tZXNzYWdlKTtcbiAgICAgICAgICAgIH0pLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIGNsZWFuIHVwIHRoZSBwZW5kaW5nIHByb21pc2VcbiAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGIodGhpcywgX0NsYXNzaWNTdHJhdGVneV9wZW5kaW5nTWVzc2FnZXNCeUVuZHBvaW50SWQsIFwiZlwiKS5nZXQoZW5kcG9pbnRJZCk/LmRlbGV0ZShwKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHJhdy5wYXlsb2FkLmRhdGEucmVzdWx0O1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNsb3NlID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5tZXNzYWdlUmVjZWl2ZXIucmVtb3ZlRW5kcG9pbnQodGhpcy5wcm92aWRlcklkZW50aXR5LmNoYW5uZWxJZCwgdGhpcy5lbmRwb2ludElkKTtcbiAgICAgICAgICAgIFsuLi5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGIodGhpcywgX0NsYXNzaWNTdHJhdGVneV9lbmRwb2ludElkZW50aXR5TWFwLCBcImZcIikua2V5cygpXS5mb3JFYWNoKChpZCkgPT4gdGhpcy5jbG9zZUVuZHBvaW50KGlkKSk7XG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDkodGhpcywgX0NsYXNzaWNTdHJhdGVneV9lbmRwb2ludElkZW50aXR5TWFwLCBuZXcgTWFwKCksIFwiZlwiKTtcbiAgICAgICAgfTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ5KHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfd2lyZSwgd2lyZSwgXCJmXCIpO1xuICAgIH1cbiAgICBvbkVuZHBvaW50RGlzY29ubmVjdChlbmRwb2ludElkLCBsaXN0ZW5lcikge1xuICAgICAgICAvLyBOZXZlciBmaXJlcyBmb3IgJ2NsYXNzaWMnLlxuICAgIH1cbiAgICByZWNlaXZlKGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMubWVzc2FnZVJlY2VpdmVyLmFkZEVuZHBvaW50KGxpc3RlbmVyLCB0aGlzLnByb3ZpZGVySWRlbnRpdHkuY2hhbm5lbElkLCB0aGlzLmVuZHBvaW50SWQpO1xuICAgIH1cbiAgICBhc3luYyBjbG9zZUVuZHBvaW50KGVuZHBvaW50SWQpIHtcbiAgICAgICAgY29uc3QgaWQgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGIodGhpcywgX0NsYXNzaWNTdHJhdGVneV9lbmRwb2ludElkZW50aXR5TWFwLCBcImZcIikuZ2V0KGVuZHBvaW50SWQpO1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGIodGhpcywgX0NsYXNzaWNTdHJhdGVneV9lbmRwb2ludElkZW50aXR5TWFwLCBcImZcIikuZGVsZXRlKGVuZHBvaW50SWQpO1xuICAgICAgICBjb25zdCBwZW5kaW5nU2V0ID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCRiKHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfcGVuZGluZ01lc3NhZ2VzQnlFbmRwb2ludElkLCBcImZcIikuZ2V0KGVuZHBvaW50SWQpO1xuICAgICAgICBwZW5kaW5nU2V0Py5mb3JFYWNoKChwKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBlcnJvck1zZyA9IGBDaGFubmVsIGNvbm5lY3Rpb24gd2l0aCBpZGVudGl0eSB1dWlkOiAke2lkPy51dWlkfSAvIG5hbWU6ICR7aWQ/Lm5hbWV9IC8gZW5kcG9pbnRJZDogJHtlbmRwb2ludElkfSBubyBsb25nZXIgY29ubmVjdGVkLmA7XG4gICAgICAgICAgICBwLmNhbmNlbChuZXcgRXJyb3IoZXJyb3JNc2cpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGlzRW5kcG9pbnRDb25uZWN0ZWQoZW5kcG9pbnRJZCkge1xuICAgICAgICByZXR1cm4gX19jbGFzc1ByaXZhdGVGaWVsZEdldCRiKHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfZW5kcG9pbnRJZGVudGl0eU1hcCwgXCJmXCIpLmhhcyhlbmRwb2ludElkKTtcbiAgICB9XG4gICAgYWRkRW5kcG9pbnQoZW5kcG9pbnRJZCwgcGF5bG9hZCkge1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGIodGhpcywgX0NsYXNzaWNTdHJhdGVneV9lbmRwb2ludElkZW50aXR5TWFwLCBcImZcIikuc2V0KGVuZHBvaW50SWQsIHBheWxvYWQuZW5kcG9pbnRJZGVudGl0eSk7XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYih0aGlzLCBfQ2xhc3NpY1N0cmF0ZWd5X3BlbmRpbmdNZXNzYWdlc0J5RW5kcG9pbnRJZCwgXCJmXCIpLnNldChlbmRwb2ludElkLCBuZXcgU2V0KCkpO1xuICAgIH1cbiAgICBpc1ZhbGlkRW5kcG9pbnRQYXlsb2FkKHBheWxvYWQpIHtcbiAgICAgICAgcmV0dXJuICh0eXBlb2YgcGF5bG9hZD8uZW5kcG9pbnRJZGVudGl0eT8uZW5kcG9pbnRJZCA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgICAgIHR5cGVvZiBwYXlsb2FkPy5lbmRwb2ludElkZW50aXR5Py5jaGFubmVsSWQgPT09ICdzdHJpbmcnKTtcbiAgICB9XG59XG5zdHJhdGVneSQzLkNsYXNzaWNTdHJhdGVneSA9IENsYXNzaWNTdHJhdGVneTtcbl9DbGFzc2ljU3RyYXRlZ3lfd2lyZSA9IG5ldyBXZWFrTWFwKCksIF9DbGFzc2ljU3RyYXRlZ3lfZW5kcG9pbnRJZGVudGl0eU1hcCA9IG5ldyBXZWFrTWFwKCksIF9DbGFzc2ljU3RyYXRlZ3lfcGVuZGluZ01lc3NhZ2VzQnlFbmRwb2ludElkID0gbmV3IFdlYWtNYXAoKTtcbi8vIEFyYml0cmFyaWx5IHN0YXJ0aW5nIGF0IDUgdG8gbGVhdmUgdGhlIGRvb3Igb3BlbiB0byBiYWNrZmlsbGluZyBwcmUgZW5kcG9pbnRJZCBldGMuXG5zdHJhdGVneSQzLkNsYXNzaWNJbmZvID0geyB2ZXJzaW9uOiA1LCBtaW5pbXVtVmVyc2lvbjogMCwgdHlwZTogJ2NsYXNzaWMnIH07XG5cbnZhciBzdHJhdGVneSQyID0ge307XG5cbnZhciBlbmRwb2ludCA9IHt9O1xuXG52YXIgZXJyb3JzID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShlcnJvcnMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXJyb3JzLmVycm9yVG9QT0pPID0gdm9pZCAwO1xuZnVuY3Rpb24gZXJyb3JUb1BPSk8oZXJyb3IpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBzdGFjazogZXJyb3Iuc3RhY2ssXG4gICAgICAgIG5hbWU6IGVycm9yLm5hbWUsXG4gICAgICAgIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2UsXG4gICAgICAgIC8vIHN1cHBvcnQgdGhlIGNhc2Ugd2hlcmUgc3RhY2sgaXMgZW1wdHkgb3IgbWlzc2luZ1xuICAgICAgICB0b1N0cmluZzogKCkgPT4gZXJyb3Iuc3RhY2sgfHwgZXJyb3IudG9TdHJpbmcoKVxuICAgIH07XG59XG5lcnJvcnMuZXJyb3JUb1BPSk8gPSBlcnJvclRvUE9KTztcblxudmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYSA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkOCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcbn07XG52YXIgX1JUQ0VuZHBvaW50X3Byb2Nlc3NBY3Rpb24sIF9SVENFbmRwb2ludF9kaXNjb25uZWN0TGlzdGVuZXI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZW5kcG9pbnQsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZW5kcG9pbnQuUlRDRW5kcG9pbnQgPSB2b2lkIDA7XG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi9cbmNvbnN0IGVycm9yc18xJDEgPSBlcnJvcnM7XG4vKlxuVGhpcyBoYW5kbGVzIHNlbmRpbmcgUlRDIG1lc3NhZ2VzIGJldHdlZW4gUlRDIGNvbm5lY3Rpb25zIG92ZXIgdGhlIHJlcXVlc3QgYW5kIHJlc3BvbnNlIGRhdGEgY2hhbm5lbHMuXG4qL1xuY2xhc3MgUlRDRW5kcG9pbnQge1xuICAgIHN0YXRpYyBpc1ZhbGlkRW5kcG9pbnRQYXlsb2FkKHBheWxvYWQpIHtcbiAgICAgICAgY29uc3QgaXNPYmplY3QgPSAoeCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyAmJiB4ICE9PSBudWxsO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAvLyBUT0RPIGluIGZhY3RvcnkgUFI6XG4gICAgICAgIC8vIHBheWxvYWQudHlwZSA9PT0gJ3J0YycgJiZcbiAgICAgICAgaXNPYmplY3QocGF5bG9hZCkgJiZcbiAgICAgICAgICAgIGlzT2JqZWN0KHBheWxvYWQuZW5kcG9pbnRJZGVudGl0eSkgJiZcbiAgICAgICAgICAgIGlzT2JqZWN0KHBheWxvYWQucnRjKSAmJlxuICAgICAgICAgICAgdHlwZW9mIHBheWxvYWQuZW5kcG9pbnRJZGVudGl0eS5lbmRwb2ludElkID09PSAnc3RyaW5nJyk7XG4gICAgfVxuICAgIGNvbnN0cnVjdG9yKHsgcnRjLCBlbmRwb2ludElkZW50aXR5IH0pIHtcbiAgICAgICAgdGhpcy5yZXNwb25zZU1hcCA9IG5ldyBNYXAoKTtcbiAgICAgICAgX1JUQ0VuZHBvaW50X3Byb2Nlc3NBY3Rpb24uc2V0KHRoaXMsIG51bGwpO1xuICAgICAgICBfUlRDRW5kcG9pbnRfZGlzY29ubmVjdExpc3RlbmVyLnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb25TdGF0ZUNoYW5nZUhhbmRsZXIgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLnJ0Yy5ydGNDbGllbnQuY29ubmVjdGlvblN0YXRlICE9PSAnY29ubmVjdGVkJykge1xuICAgICAgICAgICAgICAgIHRoaXMucnRjLnJ0Y0NsaWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCB0aGlzLmNvbm5lY3Rpb25TdGF0ZUNoYW5nZUhhbmRsZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICBpZiAoX19jbGFzc1ByaXZhdGVGaWVsZEdldCRhKHRoaXMsIF9SVENFbmRwb2ludF9kaXNjb25uZWN0TGlzdGVuZXIsIFwiZlwiKSkge1xuICAgICAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGEodGhpcywgX1JUQ0VuZHBvaW50X2Rpc2Nvbm5lY3RMaXN0ZW5lciwgXCJmXCIpLmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB0aGlzLnNlbmQgPSBhc3luYyAoYWN0aW9uLCBwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlSWQgPSBgbWVzc2FnZS0ke01hdGgucmFuZG9tKCl9YDtcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZU1hcC5zZXQobWVzc2FnZUlkLCB7IHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdGhpcy5ydGMuY2hhbm5lbHMucmVxdWVzdC5zZW5kKEpTT04uc3RyaW5naWZ5KHsgYWN0aW9uLCBwYXlsb2FkLCBtZXNzYWdlSWQgfSkpO1xuICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY2xvc2UgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlc3BvbnNlTWFwLmZvckVhY2goKHJlc3BvbnNlKSA9PiByZXNwb25zZS5yZWplY3QoJ0Nvbm5lY3Rpb24gaGFzIGNsb3NlZC4nKSk7XG4gICAgICAgICAgICB0aGlzLnJlc3BvbnNlTWFwID0gbmV3IE1hcCgpO1xuICAgICAgICAgICAgdGhpcy5ydGMuY2hhbm5lbHMucmVxdWVzdC5jbG9zZSgpO1xuICAgICAgICAgICAgdGhpcy5ydGMuY2hhbm5lbHMucmVzcG9uc2UuY2xvc2UoKTtcbiAgICAgICAgICAgIHRoaXMucnRjLnJ0Y0NsaWVudC5jbG9zZSgpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnJ0YyA9IHJ0YztcbiAgICAgICAgdGhpcy5lbmRwb2ludElkZW50aXR5ID0gZW5kcG9pbnRJZGVudGl0eTtcbiAgICAgICAgdGhpcy5ydGMuY2hhbm5lbHMucmVzcG9uc2UuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIChlKSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBkYXRhIH0gPSBlO1xuICAgICAgICAgICAgaWYgKGUuZGF0YSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgZGF0YSA9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShlLmRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgeyBtZXNzYWdlSWQsIHBheWxvYWQsIHN1Y2Nlc3MsIGVycm9yIH0gPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICAgICAgY29uc3QgeyByZXNvbHZlLCByZWplY3QgfSA9IHRoaXMucmVzcG9uc2VNYXAuZ2V0KG1lc3NhZ2VJZCkgPz8ge307XG4gICAgICAgICAgICBpZiAocmVzb2x2ZSAmJiByZWplY3QpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlTWFwLmRlbGV0ZShtZXNzYWdlSWQpO1xuICAgICAgICAgICAgICAgIGlmIChzdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUocGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdDb3VsZCBub3QgZmluZCBpZCBpbiByZXNwb25zZU1hcC4nKTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucnRjLmNoYW5uZWxzLnJlcXVlc3QuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGFzeW5jIChlKSA9PiB7XG4gICAgICAgICAgICBsZXQgeyBkYXRhIH0gPSBlO1xuICAgICAgICAgICAgaWYgKGUuZGF0YSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgZGF0YSA9IG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZShlLmRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgeyBtZXNzYWdlSWQsIGFjdGlvbiwgcGF5bG9hZCB9ID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgICAgIGlmIChfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGEodGhpcywgX1JUQ0VuZHBvaW50X3Byb2Nlc3NBY3Rpb24sIFwiZlwiKSkge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYSh0aGlzLCBfUlRDRW5kcG9pbnRfcHJvY2Vzc0FjdGlvbiwgXCJmXCIpLmNhbGwodGhpcywgYWN0aW9uLCBwYXlsb2FkLCBlbmRwb2ludElkZW50aXR5KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ydGMuY2hhbm5lbHMucmVzcG9uc2Uuc2VuZChKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXlsb2FkOiByZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzOiB0cnVlXG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIFJUQ0RhdGFDaGFubmVsIGlzIG9wZW4gYmVmb3JlIHNlbmRpbmcsIGVycm9yIGdldHMgc3dhbGxvd2VkIGhlcmUgaW4gdGhlIGNhc2Ugd2hlcmVcbiAgICAgICAgICAgICAgICAgICAgLy8gY2xpZW50IGRpc3BhdGNoZWQgdGhlbiBjbG9zZWQgb3IgZGlzY29ubmVjdGVkIGJlZm9yZSB0aGUgZGlzcGF0Y2ggcmVzb2x2ZXMuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnJ0Yy5jaGFubmVscy5yZXNwb25zZS5yZWFkeVN0YXRlID09PSAnb3BlbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucnRjLmNoYW5uZWxzLnJlc3BvbnNlLnNlbmQoSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcjogKDAsIGVycm9yc18xJDEuZXJyb3JUb1BPSk8pKGVycm9yKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzOiBmYWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIFJUQ0RhdGFDaGFubmVsIGlzIG9wZW4gZm9yIHNhbWUgcmVhc29uIGFzIGNhdGNoIGJsb2NrIGFib3ZlLlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpcy5ydGMuY2hhbm5lbHMucmVzcG9uc2UucmVhZHlTdGF0ZSA9PT0gJ29wZW4nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ydGMuY2hhbm5lbHMucmVzcG9uc2Uuc2VuZChKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VJZCxcbiAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiAnQ29ubmVjdGlvbiBub3QgcmVhZHkuJ1xuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucnRjLnJ0Y0NsaWVudC5hZGRFdmVudExpc3RlbmVyKCdjb25uZWN0aW9uc3RhdGVjaGFuZ2UnLCB0aGlzLmNvbm5lY3Rpb25TdGF0ZUNoYW5nZUhhbmRsZXIpO1xuICAgICAgICAvLyBEaXNjb25uZWN0IGlmIGRhdGEgY2hhbm5lbHMgY2xvc2UgdW5leHBlY3RlZGx5LCBlLmcuIGNhbiBoYXBwZW4gZHVlIHRvIG1lc3NhZ2Ugc2l6ZSA+IH4yNTVrQiAoUlRDUGVlckNvbm5lY3Rpb24uc2N0cC5tYXhNZXNzYWdlU2l6ZUxpbWl0OiAyNjIxNDQpXG4gICAgICAgIE9iamVjdC52YWx1ZXModGhpcy5ydGMuY2hhbm5lbHMpLmZvckVhY2goKGRhdGFjaGFubmVsKSA9PiB7XG4gICAgICAgICAgICBkYXRhY2hhbm5lbC5vbmNsb3NlID0gKGUpID0+IHtcbiAgICAgICAgICAgICAgICBbLi4udGhpcy5yZXNwb25zZU1hcC52YWx1ZXMoKV0uZm9yRWFjaCgocHJvbWlzZSkgPT4gcHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCdSVENEYXRhQ2hhbm5lbCBjbG9zZWQgdW5leHBlY3RlZGx5LCB0aGlzIGlzIG1vc3QgY29tbW9ubHkgY2F1c2VkIGJ5IG1lc3NhZ2Ugc2l6ZS4gTm90ZTogUlRDIENoYW5uZWxzIGhhdmUgYSBtZXNzYWdlIHNpemUgbGltaXQgb2YgfjI1NWtCLicpKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIGlmIChfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGEodGhpcywgX1JUQ0VuZHBvaW50X2Rpc2Nvbm5lY3RMaXN0ZW5lciwgXCJmXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYSh0aGlzLCBfUlRDRW5kcG9pbnRfZGlzY29ubmVjdExpc3RlbmVyLCBcImZcIikuY2FsbCh0aGlzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgb25EaXNjb25uZWN0KGxpc3RlbmVyKSB7XG4gICAgICAgIGlmICghX19jbGFzc1ByaXZhdGVGaWVsZEdldCRhKHRoaXMsIF9SVENFbmRwb2ludF9kaXNjb25uZWN0TGlzdGVuZXIsIFwiZlwiKSkge1xuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ4KHRoaXMsIF9SVENFbmRwb2ludF9kaXNjb25uZWN0TGlzdGVuZXIsIGxpc3RlbmVyLCBcImZcIik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JUQ0VuZHBvaW50IGRpc2Nvbm5lY3RMaXN0ZW5lciBjYW5ub3QgYmUgc2V0IHR3aWNlLicpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJlY2VpdmUobGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYSh0aGlzLCBfUlRDRW5kcG9pbnRfcHJvY2Vzc0FjdGlvbiwgXCJmXCIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBoYXZlIGFscmVhZHkgc2V0IGEgbGlzdGVuZXIgZm9yIHRoaXMgUlRDIEVuZHBvaW50LicpO1xuICAgICAgICB9XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkOCh0aGlzLCBfUlRDRW5kcG9pbnRfcHJvY2Vzc0FjdGlvbiwgbGlzdGVuZXIsIFwiZlwiKTtcbiAgICB9XG4gICAgZ2V0IGNvbm5lY3RlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucnRjLnJ0Y0NsaWVudC5jb25uZWN0aW9uU3RhdGUgPT09ICdjb25uZWN0ZWQnO1xuICAgIH1cbn1cbmVuZHBvaW50LlJUQ0VuZHBvaW50ID0gUlRDRW5kcG9pbnQ7XG5fUlRDRW5kcG9pbnRfcHJvY2Vzc0FjdGlvbiA9IG5ldyBXZWFrTWFwKCksIF9SVENFbmRwb2ludF9kaXNjb25uZWN0TGlzdGVuZXIgPSBuZXcgV2Vha01hcCgpO1xuXG52YXIgc3RyYXRlZ3kkMSA9IHt9O1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcbn07XG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ3ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufTtcbnZhciBfRW5kcG9pbnRTdHJhdGVneV9wcm9jZXNzQWN0aW9uLCBfRW5kcG9pbnRTdHJhdGVneV9lbmRwb2ludE1hcCwgX0VuZHBvaW50U3RyYXRlZ3lfY29ubmVjdGVkO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KHN0cmF0ZWd5JDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuc3RyYXRlZ3kkMS5FbmRwb2ludFN0cmF0ZWd5ID0gdm9pZCAwO1xuY2xhc3MgRW5kcG9pbnRTdHJhdGVneSB7XG4gICAgLy8gTmVlZCB0byBwYXNzIGluIHZhbGlkYXRlIGVuZHBvaW50IHNlcGFyYXRlbHkgZnJvbSBjb25zdHJ1Y3RvciBiZWNhdXNlIHRzIGludGVyZmFjZXMgZG9uJ3QgZG8gd2VsbCB3aXRoIHN0YXRpYyBtZXRob2RzXG4gICAgY29uc3RydWN0b3IoRW5kcG9pbnRUeXBlLCB2YWxpZGF0ZUVuZHBvaW50LCBTdHJhdGVneU5hbWUpIHtcbiAgICAgICAgdGhpcy5FbmRwb2ludFR5cGUgPSBFbmRwb2ludFR5cGU7XG4gICAgICAgIHRoaXMuU3RyYXRlZ3lOYW1lID0gU3RyYXRlZ3lOYW1lO1xuICAgICAgICBfRW5kcG9pbnRTdHJhdGVneV9wcm9jZXNzQWN0aW9uLnNldCh0aGlzLCBudWxsKTtcbiAgICAgICAgX0VuZHBvaW50U3RyYXRlZ3lfZW5kcG9pbnRNYXAuc2V0KHRoaXMsIG5ldyBNYXAoKSk7XG4gICAgICAgIF9FbmRwb2ludFN0cmF0ZWd5X2Nvbm5lY3RlZC5zZXQodGhpcywgdHJ1ZSk7XG4gICAgICAgIHRoaXMuc2VuZCA9IGFzeW5jIChlbmRwb2ludElkLCBhY3Rpb24sIHBheWxvYWQpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEVuZHBvaW50QnlJZChlbmRwb2ludElkKS5zZW5kKGFjdGlvbiwgcGF5bG9hZCk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY2xvc2UgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X2Nvbm5lY3RlZCwgXCJmXCIpKSB7XG4gICAgICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X2VuZHBvaW50TWFwLCBcImZcIikuZm9yRWFjaCgoZW5kcG9pbnQpID0+IGVuZHBvaW50LmNsb3NlKCkpO1xuICAgICAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkNyh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9lbmRwb2ludE1hcCwgbmV3IE1hcCgpLCBcImZcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDcodGhpcywgX0VuZHBvaW50U3RyYXRlZ3lfY29ubmVjdGVkLCBmYWxzZSwgXCJmXCIpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmlzVmFsaWRFbmRwb2ludFBheWxvYWQgPSB2YWxpZGF0ZUVuZHBvaW50O1xuICAgIH1cbiAgICBvbkVuZHBvaW50RGlzY29ubmVjdChlbmRwb2ludElkLCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLmdldEVuZHBvaW50QnlJZChlbmRwb2ludElkKS5vbkRpc2Nvbm5lY3QobGlzdGVuZXIpO1xuICAgIH1cbiAgICByZWNlaXZlKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmIChfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDkodGhpcywgX0VuZHBvaW50U3RyYXRlZ3lfcHJvY2Vzc0FjdGlvbiwgXCJmXCIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFlvdSBoYXZlIGFscmVhZHkgc2V0IGEgbGlzdGVuZXIgZm9yIHRoaXMgJHt0aGlzLlN0cmF0ZWd5TmFtZX0gU3RyYXRlZ3lgKTtcbiAgICAgICAgfVxuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDcodGhpcywgX0VuZHBvaW50U3RyYXRlZ3lfcHJvY2Vzc0FjdGlvbiwgbGlzdGVuZXIsIFwiZlwiKTtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X2VuZHBvaW50TWFwLCBcImZcIikuZm9yRWFjaCgoZW5kcG9pbnQpID0+IGVuZHBvaW50LnJlY2VpdmUoX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X3Byb2Nlc3NBY3Rpb24sIFwiZlwiKSkpO1xuICAgIH1cbiAgICBnZXRFbmRwb2ludEJ5SWQoZW5kcG9pbnRJZCkge1xuICAgICAgICBjb25zdCBlbmRwb2ludCA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9lbmRwb2ludE1hcCwgXCJmXCIpLmdldChlbmRwb2ludElkKTtcbiAgICAgICAgaWYgKCFlbmRwb2ludCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDbGllbnQgd2l0aCBlbmRwb2ludCBpZCAke2VuZHBvaW50SWR9IGlzIG5vdCBjb25uZWN0ZWRgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZW5kcG9pbnQ7XG4gICAgfVxuICAgIGdldCBjb25uZWN0ZWQoKSB7XG4gICAgICAgIHJldHVybiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDkodGhpcywgX0VuZHBvaW50U3RyYXRlZ3lfY29ubmVjdGVkLCBcImZcIik7XG4gICAgfVxuICAgIGlzRW5kcG9pbnRDb25uZWN0ZWQoZW5kcG9pbnRJZCkge1xuICAgICAgICByZXR1cm4gX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X2VuZHBvaW50TWFwLCBcImZcIikuaGFzKGVuZHBvaW50SWQpO1xuICAgIH1cbiAgICBhZGRFbmRwb2ludChlbmRwb2ludElkLCBwYXlsb2FkKSB7XG4gICAgICAgIGlmICghX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X2Nvbm5lY3RlZCwgXCJmXCIpKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYEFkZGluZyBlbmRwb2ludCB0byBkaXNjb25uZWN0ZWQgJHt0aGlzLlN0cmF0ZWd5TmFtZX0gU3RyYXRlZ3lgKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjbGllbnRTdHJhdCA9IG5ldyB0aGlzLkVuZHBvaW50VHlwZShwYXlsb2FkKTtcbiAgICAgICAgaWYgKF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9wcm9jZXNzQWN0aW9uLCBcImZcIikpIHtcbiAgICAgICAgICAgIGNsaWVudFN0cmF0LnJlY2VpdmUoX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X3Byb2Nlc3NBY3Rpb24sIFwiZlwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X2VuZHBvaW50TWFwLCBcImZcIikuc2V0KGVuZHBvaW50SWQsIGNsaWVudFN0cmF0KTtcbiAgICB9XG4gICAgYXN5bmMgY2xvc2VFbmRwb2ludChlbmRwb2ludElkKSB7XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9lbmRwb2ludE1hcCwgXCJmXCIpLmRlbGV0ZShlbmRwb2ludElkKTtcbiAgICB9XG59XG5zdHJhdGVneSQxLkVuZHBvaW50U3RyYXRlZ3kgPSBFbmRwb2ludFN0cmF0ZWd5O1xuX0VuZHBvaW50U3RyYXRlZ3lfcHJvY2Vzc0FjdGlvbiA9IG5ldyBXZWFrTWFwKCksIF9FbmRwb2ludFN0cmF0ZWd5X2VuZHBvaW50TWFwID0gbmV3IFdlYWtNYXAoKSwgX0VuZHBvaW50U3RyYXRlZ3lfY29ubmVjdGVkID0gbmV3IFdlYWtNYXAoKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHN0cmF0ZWd5JDIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuc3RyYXRlZ3kkMi5SVENJbmZvID0gc3RyYXRlZ3kkMi5SVENTdHJhdGVneSA9IHZvaWQgMDtcbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyAqL1xuLyogZXNsaW50LWRpc2FibGUgY2xhc3MtbWV0aG9kcy11c2UtdGhpcyAqL1xuY29uc3QgZW5kcG9pbnRfMSA9IGVuZHBvaW50O1xuY29uc3Qgc3RyYXRlZ3lfMSQxID0gc3RyYXRlZ3kkMTtcbi8qXG5UaGlzIGlzIHVzZWQgdG8gYWJzdHJhY3Qgb3V0IHJ0YyBtZXNzYWdpbmcgZnJvbSB0aGUgY2hhbm5lbHMgaW1wbGVtZW50YXRpb24gdXNpbmcgUlRDRW5kcG9pbnRzLlxuKi9cbmNsYXNzIFJUQ1N0cmF0ZWd5IGV4dGVuZHMgc3RyYXRlZ3lfMSQxLkVuZHBvaW50U3RyYXRlZ3kge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcihlbmRwb2ludF8xLlJUQ0VuZHBvaW50LCBlbmRwb2ludF8xLlJUQ0VuZHBvaW50LmlzVmFsaWRFbmRwb2ludFBheWxvYWQsICdSVEMnKTtcbiAgICB9XG59XG5zdHJhdGVneSQyLlJUQ1N0cmF0ZWd5ID0gUlRDU3RyYXRlZ3k7XG5zdHJhdGVneSQyLlJUQ0luZm8gPSB7IHZlcnNpb246IDIsIG1pbmltdW1WZXJzaW9uOiAwLCB0eXBlOiAncnRjJyB9O1xuXG52YXIgaWNlTWFuYWdlciA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoaWNlTWFuYWdlciwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5pY2VNYW5hZ2VyLlJUQ0lDRU1hbmFnZXIgPSB2b2lkIDA7XG5jb25zdCBiYXNlXzEkaCA9IGJhc2U7XG4vKlxuU2luZ2xldG9uIHRoYXQgZmFjaWxpdGF0ZXMgT2ZmZXIgYW5kIEFuc3dlciBleGNoYW5nZSByZXF1aXJlZCBmb3IgZXN0YWJsaXNoaW5nIFJUQyBjb25uZWN0aW9ucy5cbiovXG5jbGFzcyBSVENJQ0VNYW5hZ2VyIGV4dGVuZHMgYmFzZV8xJGguRW1pdHRlckJhc2Uge1xuICAgIGNvbnN0cnVjdG9yKHdpcmUpIHtcbiAgICAgICAgc3VwZXIod2lyZSwgJ2NoYW5uZWwnKTtcbiAgICAgICAgdGhpcy5lbnN1cmVDaGFubmVsT3BlbmVkID0gKGNoYW5uZWwpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNoYW5uZWwucmVhZHlTdGF0ZSA9PT0gJ29wZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY2hhbm5lbC5yZWFkeVN0YXRlID09PSAnY29ubmVjdGluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGlzdGVuZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGFubmVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ29wZW4nLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGNoYW5uZWwuYWRkRXZlbnRMaXN0ZW5lcignb3BlbicsIGxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ1RoaXMgQ2hhbm5lbCBoYXMgYWxyZWFkeSBjbG9zZWQnKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIHN0YXRpYyBjcmVhdGVEYXRhQ2hhbm5lbFByb21pc2UobGFiZWwsIHJ0Y0NsaWVudCkge1xuICAgICAgICBsZXQgcmVzb2x2ZXI7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZXIgPSByZXNvbHZlO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgbGlzdGVuZXIgPSAoZSkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgb3Blbkxpc3RlbmVyID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGUuY2hhbm5lbC5yZW1vdmVFdmVudExpc3RlbmVyKCdvcGVuJywgb3Blbkxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlcihlLmNoYW5uZWwpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChlLmNoYW5uZWwubGFiZWwgPT09IGxhYmVsKSB7XG4gICAgICAgICAgICAgICAgZS5jaGFubmVsLmFkZEV2ZW50TGlzdGVuZXIoJ29wZW4nLCBvcGVuTGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgIHJ0Y0NsaWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdkYXRhY2hhbm5lbCcsIGxpc3RlbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgcnRjQ2xpZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RhdGFjaGFubmVsJywgbGlzdGVuZXIpO1xuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9XG4gICAgYXN5bmMgbGlzdGVuRm9yUHJvdmlkZXJJY2UocnRjQ29ubmVjdGlvbklkLCBsaXN0ZW5lcikge1xuICAgICAgICBhd2FpdCB0aGlzLm9uKHRoaXMuY3JlYXRlUHJvdmlkZXJFdmVudE5hbWUocnRjQ29ubmVjdGlvbklkKSwgbGlzdGVuZXIsIHsgdGltZXN0YW1wOiBEYXRlLm5vdygpIH0pO1xuICAgIH1cbiAgICBhc3luYyByYWlzZVByb3ZpZGVySWNlKHJ0Y0Nvbm5lY3Rpb25JZCwgcGF5bG9hZCkge1xuICAgICAgICBhd2FpdCB0aGlzLndpcmUuZW52aXJvbm1lbnQucmFpc2VFdmVudCh0aGlzLmNyZWF0ZVJvdXRlU3RyaW5nKHRoaXMuY3JlYXRlUHJvdmlkZXJFdmVudE5hbWUocnRjQ29ubmVjdGlvbklkKSksIHBheWxvYWQpO1xuICAgIH1cbiAgICBhc3luYyBsaXN0ZW5Gb3JDbGllbnRJY2UocnRjQ29ubmVjdGlvbklkLCBsaXN0ZW5lcikge1xuICAgICAgICBhd2FpdCB0aGlzLm9uKHRoaXMuY3JlYXRlQ2xpZW50RXZlbnROYW1lKHJ0Y0Nvbm5lY3Rpb25JZCksIGxpc3RlbmVyLCB7IHRpbWVzdGFtcDogRGF0ZS5ub3coKSB9KTtcbiAgICB9XG4gICAgYXN5bmMgcmFpc2VDbGllbnRJY2UocnRjQ29ubmVjdGlvbklkLCBwYXlsb2FkKSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5lbnZpcm9ubWVudC5yYWlzZUV2ZW50KHRoaXMuY3JlYXRlUm91dGVTdHJpbmcodGhpcy5jcmVhdGVDbGllbnRFdmVudE5hbWUocnRjQ29ubmVjdGlvbklkKSksIHBheWxvYWQpO1xuICAgIH1cbiAgICBjbGVhbnVwSWNlTGlzdGVuZXJzKHJ0Y0Nvbm5lY3Rpb25JZCkge1xuICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyh0aGlzLmNyZWF0ZUNsaWVudEV2ZW50TmFtZShydGNDb25uZWN0aW9uSWQpKTtcbiAgICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnModGhpcy5jcmVhdGVQcm92aWRlckV2ZW50TmFtZShydGNDb25uZWN0aW9uSWQpKTtcbiAgICB9XG4gICAgY3JlYXRlQ2xpZW50RXZlbnROYW1lKHJ0Y0Nvbm5lY3Rpb25JZCkge1xuICAgICAgICByZXR1cm4gYGljZS1jbGllbnQtJHtydGNDb25uZWN0aW9uSWR9YDtcbiAgICB9XG4gICAgY3JlYXRlUHJvdmlkZXJFdmVudE5hbWUocnRjQ29ubmVjdGlvbklkKSB7XG4gICAgICAgIHJldHVybiBgaWNlLXByb3ZpZGVyLSR7cnRjQ29ubmVjdGlvbklkfWA7XG4gICAgfVxuICAgIGNyZWF0ZVJvdXRlU3RyaW5nKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGBjaGFubmVsLyR7bmFtZX1gO1xuICAgIH1cbiAgICBjcmVhdGVSdGNQZWVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLmVudmlyb25tZW50LmdldFJ0Y1BlZXIoKTtcbiAgICB9XG4gICAgYXN5bmMgc3RhcnRDbGllbnRPZmZlcigpIHtcbiAgICAgICAgLy8gVE9ETyByZXBsYWNlIHdpdGggcmVhbCBndWlkLlxuICAgICAgICBjb25zdCBydGNDb25uZWN0aW9uSWQgPSBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKCk7XG4gICAgICAgIGNvbnN0IHJ0Y0NsaWVudCA9IHRoaXMuY3JlYXRlUnRjUGVlcigpO1xuICAgICAgICBydGNDbGllbnQuYWRkRXZlbnRMaXN0ZW5lcignaWNlY2FuZGlkYXRlJywgYXN5bmMgKGUpID0+IHtcbiAgICAgICAgICAgIGlmIChlLmNhbmRpZGF0ZSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucmFpc2VDbGllbnRJY2UocnRjQ29ubmVjdGlvbklkLCB7IGNhbmRpZGF0ZTogZS5jYW5kaWRhdGU/LnRvSlNPTigpIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgdGhpcy5saXN0ZW5Gb3JQcm92aWRlckljZShydGNDb25uZWN0aW9uSWQsIGFzeW5jIChwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBydGNDbGllbnQuYWRkSWNlQ2FuZGlkYXRlKHBheWxvYWQuY2FuZGlkYXRlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNoYW5uZWxzID0ge1xuICAgICAgICAgICAgcmVxdWVzdDogcnRjQ2xpZW50LmNyZWF0ZURhdGFDaGFubmVsKCdyZXF1ZXN0JyksXG4gICAgICAgICAgICByZXNwb25zZTogcnRjQ2xpZW50LmNyZWF0ZURhdGFDaGFubmVsKCdyZXNwb25zZScpXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IG9mZmVyID0gYXdhaXQgcnRjQ2xpZW50LmNyZWF0ZU9mZmVyKCk7XG4gICAgICAgIGF3YWl0IHJ0Y0NsaWVudC5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcbiAgICAgICAgY29uc3QgY2hhbm5lbHNPcGVuZWQgPSBQcm9taXNlLmFsbChbY2hhbm5lbHMucmVxdWVzdCwgY2hhbm5lbHMucmVzcG9uc2VdLm1hcCh0aGlzLmVuc3VyZUNoYW5uZWxPcGVuZWQpKS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICAgIHJldHVybiB7IHJ0Y0NsaWVudCwgY2hhbm5lbHMsIG9mZmVyLCBydGNDb25uZWN0aW9uSWQsIGNoYW5uZWxzT3BlbmVkIH07XG4gICAgfVxuICAgIGFzeW5jIGZpbmlzaENsaWVudE9mZmVyKHJ0Y0NsaWVudCwgYW5zd2VyLCBwcm92aWRlclJlYWR5KSB7XG4gICAgICAgIGF3YWl0IHJ0Y0NsaWVudC5zZXRSZW1vdGVEZXNjcmlwdGlvbihhbnN3ZXIpO1xuICAgICAgICBhd2FpdCBwcm92aWRlclJlYWR5O1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgYXN5bmMgY3JlYXRlUHJvdmlkZXJBbnN3ZXIocnRjQ29ubmVjdGlvbklkLCBvZmZlcikge1xuICAgICAgICBjb25zdCBydGNDbGllbnQgPSB0aGlzLmNyZWF0ZVJ0Y1BlZXIoKTtcbiAgICAgICAgY29uc3QgcmVxdWVzdENoYW5uZWxQcm9taXNlID0gUlRDSUNFTWFuYWdlci5jcmVhdGVEYXRhQ2hhbm5lbFByb21pc2UoJ3JlcXVlc3QnLCBydGNDbGllbnQpO1xuICAgICAgICBjb25zdCByZXNwb25zZUNoYW5uZWxQcm9taXNlID0gUlRDSUNFTWFuYWdlci5jcmVhdGVEYXRhQ2hhbm5lbFByb21pc2UoJ3Jlc3BvbnNlJywgcnRjQ2xpZW50KTtcbiAgICAgICAgcnRjQ2xpZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2ljZWNhbmRpZGF0ZScsIGFzeW5jIChlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZS5jYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJhaXNlUHJvdmlkZXJJY2UocnRjQ29ubmVjdGlvbklkLCB7IGNhbmRpZGF0ZTogZS5jYW5kaWRhdGU/LnRvSlNPTigpIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgdGhpcy5saXN0ZW5Gb3JDbGllbnRJY2UocnRjQ29ubmVjdGlvbklkLCBhc3luYyAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgcnRjQ2xpZW50LmFkZEljZUNhbmRpZGF0ZShwYXlsb2FkLmNhbmRpZGF0ZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBhd2FpdCBydGNDbGllbnQuc2V0UmVtb3RlRGVzY3JpcHRpb24ob2ZmZXIpO1xuICAgICAgICBjb25zdCBhbnN3ZXIgPSBhd2FpdCBydGNDbGllbnQuY3JlYXRlQW5zd2VyKCk7XG4gICAgICAgIGF3YWl0IHJ0Y0NsaWVudC5zZXRMb2NhbERlc2NyaXB0aW9uKGFuc3dlcik7XG4gICAgICAgIGNvbnN0IGNoYW5uZWxzID0gUHJvbWlzZS5hbGwoW3JlcXVlc3RDaGFubmVsUHJvbWlzZSwgcmVzcG9uc2VDaGFubmVsUHJvbWlzZV0pLnRoZW4oKFtyZXF1ZXN0LCByZXNwb25zZV0pID0+IHtcbiAgICAgICAgICAgIC8vIENsZWFuIHVwIGljZSBldmVudHMuXG4gICAgICAgICAgICB0aGlzLmNsZWFudXBJY2VMaXN0ZW5lcnMocnRjQ29ubmVjdGlvbklkKTtcbiAgICAgICAgICAgIHJldHVybiB7IHJlcXVlc3QsIHJlc3BvbnNlIH07XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcnRjQ2xpZW50LFxuICAgICAgICAgICAgYW5zd2VyLFxuICAgICAgICAgICAgY2hhbm5lbHNcbiAgICAgICAgfTtcbiAgICB9XG59XG5pY2VNYW5hZ2VyLlJUQ0lDRU1hbmFnZXIgPSBSVENJQ0VNYW5hZ2VyO1xuXG52YXIgcHJvdmlkZXIgPSB7fTtcblxudmFyIHJ1bnRpbWVWZXJzaW9uaW5nID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShydW50aW1lVmVyc2lvbmluZywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5ydW50aW1lVmVyc2lvbmluZy5ydW50aW1lVXVpZE1lZXRzTWluaW11bVJ1bnRpbWVWZXJzaW9uID0gcnVudGltZVZlcnNpb25pbmcucGFyc2VSdW50aW1lVXVpZCA9IHJ1bnRpbWVWZXJzaW9uaW5nLm1lZXRzTWluaW11bVJ1bnRpbWVWZXJzaW9uID0gdm9pZCAwO1xuZnVuY3Rpb24gdk51bSh4KSB7XG4gICAgcmV0dXJuIFsuLi54LnNwbGl0KCcuJykucmV2ZXJzZSgpLmVudHJpZXMoKV0ucmVkdWNlKChwLCBbaSwgdl0pID0+IHAgKyArdiAqIDEwMDAwICoqIGksIDApO1xufVxuLypcbiAgQ29tcGFyZXMgcnVudGltZSB2ZXJzaW9ucyB0byBzZWUgaWYgdGhlIGN1cnJlbnQgcnVudGltZSBtZWV0cyB5b3VyIGRlc2lyZWQgbWluaW11bS5cbiovXG5mdW5jdGlvbiBtZWV0c01pbmltdW1SdW50aW1lVmVyc2lvbihjdXJyZW50VmVyc2lvbiwgbWluVmVyc2lvbikge1xuICAgIGNvbnN0IGN1cnJlbnRWZXJzaW9uUGFyc2VkID0gdk51bShjdXJyZW50VmVyc2lvbik7XG4gICAgY29uc3QgbWluVmVyc2lvblBhcnNlZCA9IHZOdW0obWluVmVyc2lvbik7XG4gICAgcmV0dXJuIGN1cnJlbnRWZXJzaW9uUGFyc2VkID49IG1pblZlcnNpb25QYXJzZWQ7XG59XG5ydW50aW1lVmVyc2lvbmluZy5tZWV0c01pbmltdW1SdW50aW1lVmVyc2lvbiA9IG1lZXRzTWluaW11bVJ1bnRpbWVWZXJzaW9uO1xuLy8gU3RyaXBzIHRoZSBwb3J0IGluZm8gZnJvbSB0aGUgcnVudGltZVV1aWQsIGxlYXZpbmcganVzdCB0aGUgcnVudGltZSB2ZXJzaW9uLlxuZnVuY3Rpb24gcGFyc2VSdW50aW1lVXVpZChydW50aW1lVXVpZCkge1xuICAgIHJldHVybiBydW50aW1lVXVpZC5zcGxpdCgnLycpWzBdO1xufVxucnVudGltZVZlcnNpb25pbmcucGFyc2VSdW50aW1lVXVpZCA9IHBhcnNlUnVudGltZVV1aWQ7XG5mdW5jdGlvbiBydW50aW1lVXVpZE1lZXRzTWluaW11bVJ1bnRpbWVWZXJzaW9uKHJ1bnRpbWVVdWlkLCBtaW5WZXJzaW9uKSB7XG4gICAgY29uc3QgcnVudGltZVZlcnNpb24gPSBwYXJzZVJ1bnRpbWVVdWlkKHJ1bnRpbWVVdWlkKTtcbiAgICByZXR1cm4gbWVldHNNaW5pbXVtUnVudGltZVZlcnNpb24ocnVudGltZVZlcnNpb24sIG1pblZlcnNpb24pO1xufVxucnVudGltZVZlcnNpb25pbmcucnVudGltZVV1aWRNZWV0c01pbmltdW1SdW50aW1lVmVyc2lvbiA9IHJ1bnRpbWVVdWlkTWVldHNNaW5pbXVtUnVudGltZVZlcnNpb247XG5cbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDggPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDYgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XG59O1xudmFyIF9DaGFubmVsUHJvdmlkZXJfY29ubmVjdGlvbnMsIF9DaGFubmVsUHJvdmlkZXJfcHJvdGVjdGVkT2JqLCBfQ2hhbm5lbFByb3ZpZGVyX3N0cmF0ZWd5LCBfQ2hhbm5lbFByb3ZpZGVyX3JlbW92ZUVuZHBvaW50LCBfQ2hhbm5lbFByb3ZpZGVyX2Nsb3NlO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3ZpZGVyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnByb3ZpZGVyLkNoYW5uZWxQcm92aWRlciA9IHZvaWQgMDtcbmNvbnN0IGNoYW5uZWxfMSA9IGNoYW5uZWw7XG5jb25zdCBydW50aW1lVmVyc2lvbmluZ18xID0gcnVudGltZVZlcnNpb25pbmc7XG4vKipcbiAqIEluc3RhbmNlIGNyZWF0ZWQgdG8gZW5hYmxlIHVzZSBvZiBhIGNoYW5uZWwgYXMgYSBwcm92aWRlci4gQWxsb3dzIGZvciBjb21tdW5pY2F0aW9uIHdpdGggdGhlIHtAbGluayBDaGFubmVsQ2xpZW50IENoYW5uZWxDbGllbnRzfSBieSBpbnZva2luZyBhbiBhY3Rpb24gb25cbiAqIGEgc2luZ2xlIGNsaWVudCB2aWEge0BsaW5rIENoYW5uZWxQcm92aWRlciNkaXNwYXRjaCBkaXNwYXRjaH0gb3IgYWxsIGNsaWVudHMgdmlhIHtAbGluayBDaGFubmVsUHJvdmlkZXIjcHVibGlzaCBwdWJsaXNofVxuICogYW5kIHRvIGxpc3RlbiBmb3IgY29tbXVuaWNhdGlvbiBmcm9tIGNsaWVudHMgYnkgcmVnaXN0ZXJpbmcgYW4gYWN0aW9uIHZpYSB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI3JlZ2lzdGVyIHJlZ2lzdGVyfS5cbiAqXG4gKiAjIyMgU3luY2hyb25vdXMgTWV0aG9kczpcbiAqICAqIHtAbGluayBDaGFubmVsUHJvdmlkZXIjb25Db25uZWN0aW9uIG9uQ29ubmVjdGlvbihsaXN0ZW5lcil9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI29uRGlzY29ubmVjdGlvbiBvbkRpc2Nvbm5lY3Rpb24obGlzdGVuZXIpfVxuICogICoge0BsaW5rIENoYW5uZWxQcm92aWRlciNwdWJsaXNoIHB1Ymxpc2goYWN0aW9uLCBwYXlsb2FkKX1cbiAqICAqIHtAbGluayBDaGFubmVsUHJvdmlkZXIjcmVnaXN0ZXIgcmVnaXN0ZXIoYWN0aW9uLCBsaXN0ZW5lcil9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI3JlbW92ZSByZW1vdmUoYWN0aW9uKX1cbiAqXG4gKiAjIyMgQXN5bmNocm9ub3VzIE1ldGhvZHM6XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI2Rlc3Ryb3kgZGVzdHJveSgpfVxuICogICoge0BsaW5rIENoYW5uZWxQcm92aWRlciNkaXNwYXRjaCBkaXNwYXRjaCh0bywgYWN0aW9uLCBwYXlsb2FkKX1cbiAqICAqIHtAbGluayBDaGFubmVsUHJvdmlkZXIjZ2V0QWxsQ2xpZW50SW5mbyBnZXRBbGxDbGllbnRJbmZvKCl9XG4gKlxuICogIyMjIE1pZGRsZXdhcmU6XG4gKiBNaWRkbGV3YXJlIGZ1bmN0aW9ucyByZWNlaXZlIHRoZSBmb2xsb3dpbmcgYXJndW1lbnRzOiAoYWN0aW9uLCBwYXlsb2FkLCBzZW5kZXJJZCkuXG4gKiBUaGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBtaWRkbGV3YXJlIGZ1bmN0aW9uIHdpbGwgYmUgcGFzc2VkIG9uIGFzIHRoZSBwYXlsb2FkIGZyb20gYmVmb3JlQWN0aW9uLCB0byB0aGUgYWN0aW9uIGxpc3RlbmVyLCB0byBhZnRlckFjdGlvblxuICogdW5sZXNzIGl0IGlzIHVuZGVmaW5lZCwgaW4gd2hpY2ggY2FzZSB0aGUgbW9zdCByZWNlbnRseSBkZWZpbmVkIHBheWxvYWQgaXMgdXNlZC4gIE1pZGRsZXdhcmUgY2FuIGJlIHVzZWQgZm9yIHNpZGUgZWZmZWN0cy5cbiAqICAqIHtAbGluayBDaGFubmVsUHJvdmlkZXIjc2V0RGVmYXVsdEFjdGlvbiBzZXREZWZhdWx0QWN0aW9uKG1pZGRsZXdhcmUpfVxuICogICoge0BsaW5rIENoYW5uZWxQcm92aWRlciNvbkVycm9yIG9uRXJyb3IobWlkZGxld2FyZSl9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI2JlZm9yZUFjdGlvbiBiZWZvcmVBY3Rpb24obWlkZGxld2FyZSl9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI2FmdGVyQWN0aW9uIGFmdGVyQWN0aW9uKG1pZGRsZXdhcmUpfVxuICovXG5jbGFzcyBDaGFubmVsUHJvdmlkZXIgZXh0ZW5kcyBjaGFubmVsXzEuQ2hhbm5lbEJhc2Uge1xuICAgIC8qKlxuICAgICAqIGEgcmVhZC1vbmx5IGFycmF5IGNvbnRhaW5pbmcgYWxsIHRoZSBpZGVudGl0aWVzIG9mIGNvbm5lY3RpbmcgY2xpZW50cy5cbiAgICAgKi9cbiAgICBnZXQgY29ubmVjdGlvbnMoKSB7XG4gICAgICAgIHJldHVybiBbLi4uX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ4KHRoaXMsIF9DaGFubmVsUHJvdmlkZXJfY29ubmVjdGlvbnMsIFwiZlwiKV07XG4gICAgfVxuICAgIHN0YXRpYyBoYW5kbGVDbGllbnREaXNjb25uZWN0aW9uKGNoYW5uZWwsIHBheWxvYWQpIHtcbiAgICAgICAgY29uc3QgcmVtb3ZlQnlJZCA9IGNoYW5uZWwuY29ubmVjdGlvbnMuZmluZCgoaWRlbnRpdHkpID0+IGlkZW50aXR5LmVuZHBvaW50SWQgPT09IHBheWxvYWQuZW5kcG9pbnRJZCk7XG4gICAgICAgIGlmIChyZW1vdmVCeUlkKSB7XG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDgoY2hhbm5lbCwgX0NoYW5uZWxQcm92aWRlcl9yZW1vdmVFbmRwb2ludCwgXCJmXCIpLmNhbGwoY2hhbm5lbCwgcmVtb3ZlQnlJZCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBtdWx0aXBsZVJlbW92ZXMgPSBjaGFubmVsLmNvbm5lY3Rpb25zLmZpbHRlcigoaWRlbnRpdHkpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWRlbnRpdHkudXVpZCA9PT0gcGF5bG9hZC51dWlkICYmIGlkZW50aXR5Lm5hbWUgPT09IHBheWxvYWQubmFtZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgbXVsdGlwbGVSZW1vdmVzLmZvckVhY2goX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ4KGNoYW5uZWwsIF9DaGFubmVsUHJvdmlkZXJfcmVtb3ZlRW5kcG9pbnQsIFwiZlwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgY2hhbm5lbC5kaXNjb25uZWN0TGlzdGVuZXIocGF5bG9hZCk7XG4gICAgfVxuICAgIHN0YXRpYyBzZXRQcm92aWRlclJlbW92YWwocHJvdmlkZXIsIHJlbW92ZSkge1xuICAgICAgICBDaGFubmVsUHJvdmlkZXIucmVtb3ZhbE1hcC5zZXQocHJvdmlkZXIsIHJlbW92ZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByb3ZpZGVySWRlbnRpdHksIGNsb3NlLCBzdHJhdGVneSkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICBfQ2hhbm5lbFByb3ZpZGVyX2Nvbm5lY3Rpb25zLnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICBfQ2hhbm5lbFByb3ZpZGVyX3Byb3RlY3RlZE9iai5zZXQodGhpcywgdm9pZCAwKTtcbiAgICAgICAgX0NoYW5uZWxQcm92aWRlcl9zdHJhdGVneS5zZXQodGhpcywgdm9pZCAwKTtcbiAgICAgICAgX0NoYW5uZWxQcm92aWRlcl9yZW1vdmVFbmRwb2ludC5zZXQodGhpcywgKGlkZW50aXR5KSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZW1haW5pbmdDb25uZWN0aW9ucyA9IHRoaXMuY29ubmVjdGlvbnMuZmlsdGVyKChjbGllbnRJZGVudGl0eSkgPT4gY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCAhPT0gaWRlbnRpdHkuZW5kcG9pbnRJZCk7XG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDgodGhpcywgX0NoYW5uZWxQcm92aWRlcl9zdHJhdGVneSwgXCJmXCIpLmNsb3NlRW5kcG9pbnQoaWRlbnRpdHkuZW5kcG9pbnRJZCk7XG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDYodGhpcywgX0NoYW5uZWxQcm92aWRlcl9jb25uZWN0aW9ucywgcmVtYWluaW5nQ29ubmVjdGlvbnMsIFwiZlwiKTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIE11c3QgYmUgYm91bmQuXG4gICAgICAgIHRoaXMucHJvY2Vzc0FjdGlvbiA9IGFzeW5jIChhY3Rpb24sIHBheWxvYWQsIHNlbmRlcklkZW50aXR5KSA9PiB7XG4gICAgICAgICAgICBpZiAoQ2hhbm5lbFByb3ZpZGVyLmNsaWVudElzTXVsdGlSdW50aW1lKHNlbmRlcklkZW50aXR5KSAmJlxuICAgICAgICAgICAgICAgICEoMCwgcnVudGltZVZlcnNpb25pbmdfMS5ydW50aW1lVXVpZE1lZXRzTWluaW11bVJ1bnRpbWVWZXJzaW9uKShzZW5kZXJJZGVudGl0eS5ydW50aW1lVXVpZCwgJzE4Ljg3LjU2LjAnKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlTXVsdGlSdW50aW1lTGVnYWN5Q2xpZW50KHNlbmRlcklkZW50aXR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuY2hlY2tGb3JDbGllbnRDb25uZWN0aW9uKHNlbmRlcklkZW50aXR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzdXBlci5wcm9jZXNzQWN0aW9uKGFjdGlvbiwgcGF5bG9hZCwgc2VuZGVySWRlbnRpdHkpO1xuICAgICAgICB9O1xuICAgICAgICBfQ2hhbm5lbFByb3ZpZGVyX2Nsb3NlLnNldCh0aGlzLCAoKSA9PiB7XG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDgodGhpcywgX0NoYW5uZWxQcm92aWRlcl9zdHJhdGVneSwgXCJmXCIpLmNsb3NlKCk7XG4gICAgICAgICAgICBjb25zdCByZW1vdmUgPSBDaGFubmVsUHJvdmlkZXIucmVtb3ZhbE1hcC5nZXQodGhpcyk7XG4gICAgICAgICAgICBpZiAocmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgcmVtb3ZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDYodGhpcywgX0NoYW5uZWxQcm92aWRlcl9wcm90ZWN0ZWRPYmosIG5ldyBjaGFubmVsXzEuUHJvdGVjdGVkSXRlbXMocHJvdmlkZXJJZGVudGl0eSwgY2xvc2UpLCBcImZcIik7XG4gICAgICAgIHRoaXMuY29ubmVjdExpc3RlbmVyID0gKCkgPT4gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLmRpc2Nvbm5lY3RMaXN0ZW5lciA9ICgpID0+IHVuZGVmaW5lZDtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ2KHRoaXMsIF9DaGFubmVsUHJvdmlkZXJfY29ubmVjdGlvbnMsIFtdLCBcImZcIik7XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkNih0aGlzLCBfQ2hhbm5lbFByb3ZpZGVyX3N0cmF0ZWd5LCBzdHJhdGVneSwgXCJmXCIpO1xuICAgICAgICBzdHJhdGVneS5yZWNlaXZlKHRoaXMucHJvY2Vzc0FjdGlvbik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERpc3BhdGNoIGFuIGFjdGlvbiB0byBhIHNwZWNpZmllZCBjbGllbnQuIFJldHVybnMgYSBwcm9taXNlIGZvciB0aGUgcmVzdWx0IG9mIGV4ZWN1dGluZyB0aGF0IGFjdGlvbiBvbiB0aGUgY2xpZW50IHNpZGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdG8gLSBJZGVudGl0eSBvZiB0aGUgdGFyZ2V0IGNsaWVudC5cbiAgICAgKiBAcGFyYW0gYWN0aW9uIC0gTmFtZSBvZiB0aGUgYWN0aW9uIHRvIGJlIGludm9rZWQgYnkgdGhlIGNsaWVudC5cbiAgICAgKiBAcGFyYW0gcGF5bG9hZCAtIFBheWxvYWQgdG8gYmUgc2VudCBhbG9uZyB3aXRoIHRoZSBhY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqXG4gICAgICogQmVjYXVzZSBtdWx0aXBsZSBjbGllbnRzIGNhbiBzaGFyZSB0aGUgc2FtZSBgbmFtZWAgYW5kIGB1dWlkYCwgd2hlbiBkaXNwYXRjaGluZyBmcm9tIGEgcHJvdmlkZXIgdG8gYSBjbGllbnQsXG4gICAgICogdGhlIGBpZGVudGl0eWAgeW91IHByb3ZpZGUgbXVzdCBpbmNsdWRlIHRoZSBjbGllbnQncyB1bmlxdWUgYGVuZHBvaW50SWRgIHByb3BlcnR5LiBUaGlzIGBlbmRwb2ludElkYCBpc1xuICAgICAqIHBhc3NlZCB0byB0aGUgcHJvdmlkZXIgaW4gYm90aCB0aGUgYFByb3ZpZGVyLm9uQ29ubmVjdGlvbmAgY2FsbGJhY2sgYW5kIGluIGFueSByZWdpc3RlcmVkIGFjdGlvbiBjYWxsYmFja3MuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgcHJvdmlkZXIucmVnaXN0ZXIoJ3Byb3ZpZGVyLWFjdGlvbicsIGFzeW5jIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2cocGF5bG9hZCwgaWRlbnRpdHkpO1xuICAgICAqICAgICAgICAgcmV0dXJuIGF3YWl0IHByb3ZpZGVyLmRpc3BhdGNoKGlkZW50aXR5LCAnY2xpZW50LWFjdGlvbicsICdIZWxsbywgV29ybGQhJyk7XG4gICAgICogICAgIH0pO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZGlzcGF0Y2godG8sIGFjdGlvbiwgcGF5bG9hZCkge1xuICAgICAgICBjb25zdCBlbmRwb2ludElkID0gdG8uZW5kcG9pbnRJZCA/PyB0aGlzLmdldEVuZHBvaW50SWRGb3JPcGVuRmluSWQodG8sIGFjdGlvbik7XG4gICAgICAgIGlmIChlbmRwb2ludElkICYmIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOCh0aGlzLCBfQ2hhbm5lbFByb3ZpZGVyX3N0cmF0ZWd5LCBcImZcIikuaXNFbmRwb2ludENvbm5lY3RlZChlbmRwb2ludElkKSkge1xuICAgICAgICAgICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOCh0aGlzLCBfQ2hhbm5lbFByb3ZpZGVyX3N0cmF0ZWd5LCBcImZcIikuc2VuZChlbmRwb2ludElkLCBhY3Rpb24sIHBheWxvYWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoYENsaWVudCBjb25uZWN0aW9uIHdpdGggaWRlbnRpdHkgdXVpZDogJHt0by51dWlkfSAvIG5hbWU6ICR7dG8ubmFtZX0gLyBlbmRwb2ludElkOiAke2VuZHBvaW50SWR9IG5vIGxvbmdlciBjb25uZWN0ZWQuYCkpO1xuICAgIH1cbiAgICBhc3luYyBwcm9jZXNzQ29ubmVjdGlvbihzZW5kZXJJZCwgcGF5bG9hZCkge1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDgodGhpcywgX0NoYW5uZWxQcm92aWRlcl9jb25uZWN0aW9ucywgXCJmXCIpLnB1c2goc2VuZGVySWQpO1xuICAgICAgICByZXR1cm4gdGhpcy5jb25uZWN0TGlzdGVuZXIoc2VuZGVySWQsIHBheWxvYWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoIGFuIGFjdGlvbiBhbmQgcGF5bG9hZCB0byBldmVyeSBjb25uZWN0ZWQgY2xpZW50LlxuICAgICAqIFN5bmNocm9ub3VzbHkgcmV0dXJucyBhbiBhcnJheSBvZiBwcm9taXNlcyBmb3IgZWFjaCBhY3Rpb24gKHNlZSBkaXNwYXRjaCkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYWN0aW9uXG4gICAgICogQHBhcmFtIHBheWxvYWRcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgcHJvdmlkZXIucmVnaXN0ZXIoJ3Byb3ZpZGVyLWFjdGlvbicsIGFzeW5jIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2cocGF5bG9hZCwgaWRlbnRpdHkpO1xuICAgICAqICAgICAgICAgcmV0dXJuIGF3YWl0IFByb21pc2UuYWxsKHByb3ZpZGVyLnB1Ymxpc2goJ2NsaWVudC1hY3Rpb24nLCB7IG1lc3NhZ2U6ICdCcm9hZGNhc3QgZnJvbSBwcm92aWRlcid9KSk7XG4gICAgICogICAgIH0pO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcHVibGlzaChhY3Rpb24sIHBheWxvYWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvbnMubWFwKCh0bykgPT4gX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ4KHRoaXMsIF9DaGFubmVsUHJvdmlkZXJfc3RyYXRlZ3ksIFwiZlwiKS5zZW5kKHRvLmVuZHBvaW50SWQsIGFjdGlvbiwgcGF5bG9hZCkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhIGxpc3RlbmVyIHRoYXQgaXMgY2FsbGVkIG9uIGV2ZXJ5IG5ldyBjbGllbnQgY29ubmVjdGlvbi5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIEl0IGlzIHBhc3NlZCB0aGUgaWRlbnRpdHkgb2YgdGhlIGNvbm5lY3RpbmcgY2xpZW50IGFuZCBhIHBheWxvYWQgaWYgaXQgd2FzIHByb3ZpZGVkIHRvIENoYW5uZWwuY29ubmVjdC5cbiAgICAgKiBJZiB5b3Ugd2lzaCB0byByZWplY3QgdGhlIGNvbm5lY3Rpb24sIHRocm93IGFuIGVycm9yLiBCZSBzdXJlIHRvIHN5bmNocm9ub3VzbHkgcHJvdmlkZSBhbiBvbkNvbm5lY3Rpb24gdXBvbiByZWNlaXB0IG9mXG4gICAgICogdGhlIGNoYW5uZWxQcm92aWRlciB0byBlbnN1cmUgYWxsIHBvdGVudGlhbCBjbGllbnQgY29ubmVjdGlvbnMgYXJlIGNhdWdodCBieSB0aGUgbGlzdGVuZXIuXG4gICAgICpcbiAgICAgKiBCZWNhdXNlIG11bHRpcGxlIGNsaWVudHMgY2FuIGV4aXN0IGF0IHRoZSBzYW1lIGBuYW1lYCBhbmQgYHV1aWRgLCBpbiBvcmRlciB0byBkaXN0aW5ndWlzaCBiZXR3ZWVuIGluZGl2aWR1YWwgY2xpZW50cyxcbiAgICAgKiB0aGUgYGlkZW50aXR5YCBhcmd1bWVudCBpbiBhIHByb3ZpZGVyJ3MgYG9uQ29ubmVjdGlvbmAgY2FsbGJhY2sgY29udGFpbnMgYW4gYGVuZHBvaW50SWRgIHByb3BlcnR5LiBXaGVuIGRpc3BhdGNoaW5nIGZyb20gYVxuICAgICAqIHByb3ZpZGVyIHRvIGEgY2xpZW50LCB0aGUgYGVuZHBvaW50SWRgIHByb3BlcnR5IG11c3QgYmUgcHJvdmlkZWQgaW4gb3JkZXIgdG8gc2VuZCBhbiBhY3Rpb24gdG8gYSBzcGVjaWZpYyBjbGllbnQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBwcm92aWRlciA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY3JlYXRlKCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIHByb3ZpZGVyLm9uQ29ubmVjdGlvbihpZGVudGl0eSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZygnQ2xpZW50IGNvbm5lY3RlZCcsIGlkZW50aXR5KTtcbiAgICAgKiAgICAgfSk7XG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFJlamVjdCBjb25uZWN0aW9uOlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBwcm92aWRlciA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY3JlYXRlKCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIHByb3ZpZGVyLm9uQ29ubmVjdGlvbihpZGVudGl0eSA9PiB7XG4gICAgICogICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nvbm5lY3Rpb24gUmVqZWN0ZWQnKTtcbiAgICAgKiAgICAgfSk7XG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcGFyYW0gbGlzdGVuZXJcbiAgICAgKi9cbiAgICBvbkNvbm5lY3Rpb24obGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5jb25uZWN0TGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYSBsaXN0ZW5lciB0aGF0IGlzIGNhbGxlZCBvbiBjbGllbnQgZGlzY29ubmVjdGlvbi4gSXQgaXMgcGFzc2VkIHRoZSBkaXNjb25uZWN0aW9uIGV2ZW50IG9mIHRoZSBkaXNjb25uZWN0aW5nXG4gICAgICogY2xpZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIGxpc3RlbmVyXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgcHJvdmlkZXIub25EaXNjb25uZWN0aW9uKGV2dCA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZygnQ2xpZW50IGRpc2Nvbm5lY3RlZCcsIGB1dWlkOiAke2V2dC51dWlkfSwgbmFtZTogJHtldnQubmFtZX1gKTtcbiAgICAgKiAgICAgfSk7XG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBvbkRpc2Nvbm5lY3Rpb24obGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0TGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRGVzdHJveSB0aGUgY2hhbm5lbCwgcmFpc2VzIGBkaXNjb25uZWN0ZWRgIGV2ZW50cyBvbiBhbGwgY29ubmVjdGVkIGNoYW5uZWwgY2xpZW50cy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZSgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCBwcm92aWRlci5kZXN0cm95KCk7XG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBkZXN0cm95KCkge1xuICAgICAgICBjb25zdCBwcm90ZWN0ZWRPYmogPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDgodGhpcywgX0NoYW5uZWxQcm92aWRlcl9wcm90ZWN0ZWRPYmosIFwiZlwiKTtcbiAgICAgICAgcHJvdGVjdGVkT2JqLnByb3ZpZGVySWRlbnRpdHk7XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkNih0aGlzLCBfQ2hhbm5lbFByb3ZpZGVyX2Nvbm5lY3Rpb25zLCBbXSwgXCJmXCIpO1xuICAgICAgICBhd2FpdCBwcm90ZWN0ZWRPYmouY2xvc2UoKTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ4KHRoaXMsIF9DaGFubmVsUHJvdmlkZXJfY2xvc2UsIFwiZlwiKS5jYWxsKHRoaXMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIGFycmF5IHdpdGggaW5mbyBvbiBldmVyeSBDbGllbnQgY29ubmVjdGVkIHRvIHRoZSBQcm92aWRlclxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZSgnb3BlbmZpbicpO1xuICAgICAqIGNvbnN0IGNsaWVudCA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY29ubmVjdCgnb3BlbmZpbicpO1xuICAgICAqIGNvbnN0IGNsaWVudEluZm8gPSBhd2FpdCBwcm92aWRlci5nZXRBbGxDbGllbnRJbmZvKCk7XG4gICAgICpcbiAgICAgKiBjb25zb2xlLmxvZyhjbGllbnRJbmZvKTtcbiAgICAgKlxuICAgICAqIC8vIFtcbiAgICAgKiAvLyAgICB7XG4gICAgICogLy8gICAgICAgIFwidXVpZFwiOiBcIm9wZW5maW5cIixcbiAgICAgKiAvLyAgICAgICAgXCJuYW1lXCI6IFwib3BlbmZpbi12aWV3XCIsXG4gICAgICogLy8gICAgICAgIFwiZW5kcG9pbnRJZFwiOiBcIjZkNGM3Y2E4LTRhNzQtNDYzNC04N2Y4LTc2MDU1ODIyOTYxM1wiLFxuICAgICAqIC8vICAgICAgICBcImVudGl0eVR5cGVcIjogXCJ2aWV3XCIsXG4gICAgICogLy8gICAgICAgIFwidXJsXCI6IFwiaHR0cHM6Ly9vcGVuZmluLmNvXCJcbiAgICAgKiAvLyAgICB9LFxuICAgICAqIC8vICAgIHtcbiAgICAgKiAvLyAgICAgICAgXCJ1dWlkXCI6IFwib3BlbmZpbjJcIixcbiAgICAgKiAvLyAgICAgICAgXCJuYW1lXCI6IFwib3BlbmZpbi12aWV3MlwiLFxuICAgICAqIC8vICAgICAgICBcImVuZHBvaW50SWRcIjogXCI0ejVkOGFiOS0yYjgxLTM2OTEtOTFleC0xNDIxNzkzODI1MTFcIixcbiAgICAgKiAvLyAgICAgICAgXCJlbnRpdHlUeXBlXCI6IFwidmlld1wiLFxuICAgICAqIC8vICAgICAgICBcInVybFwiOiBcImh0dHBzOi8vZXhhbXBsZS5jb21cIlxuICAgICAqIC8vICAgIH1cbiAgICAgKiAvL11cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBnZXRBbGxDbGllbnRJbmZvKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25uZWN0aW9ucy5tYXAoKGNsaWVudEluZm8pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgdXVpZCwgbmFtZSwgZW5kcG9pbnRJZCwgZW50aXR5VHlwZSwgY29ubmVjdGlvblVybCB9ID0gY2xpZW50SW5mbztcbiAgICAgICAgICAgIHJldHVybiB7IHV1aWQsIG5hbWUsIGVuZHBvaW50SWQsIGVudGl0eVR5cGUsIGNvbm5lY3Rpb25VcmwgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGNoZWNrRm9yQ2xpZW50Q29ubmVjdGlvbihjbGllbnRJZGVudGl0eSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNDbGllbnRDb25uZWN0ZWQoY2xpZW50SWRlbnRpdHkpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoaXMgYWN0aW9uIHdhcyBzZW50IGZyb20gYSBjbGllbnQgdGhhdCBpcyBub3QgY29ubmVjdGVkIHRvIHRoZSBwcm92aWRlci5cbiAgICAgICAgICAgICAgICAgICAgQ2xpZW50IElkZW50aXR5OiB7dXVpZDogJHtjbGllbnRJZGVudGl0eS51dWlkfSwgbmFtZTogJHtjbGllbnRJZGVudGl0eS5uYW1lfSwgZW5kcG9pbnRJZDogJHtjbGllbnRJZGVudGl0eS5lbmRwb2ludElkfX1gKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpc0NsaWVudENvbm5lY3RlZChjbGllbnRJZGVudGl0eSkge1xuICAgICAgICBpZiAoQ2hhbm5lbFByb3ZpZGVyLmNsaWVudElkZW50aXR5SW5jbHVkZXNFbmRwb2ludElkKGNsaWVudElkZW50aXR5KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvbnMuc29tZSgoaWRlbnRpdHkpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIC8vIE1pZ2h0IGJlIHJlZHVuZGFudCB0byBjaGVjayBmb3IgdXVpZCBhbmQgbmFtZSBoZXJlIGFmdGVyIHdlIGdldCBhbiBlbmRwb2ludElkIG1hdGNoLCBidXQganVzdCBpbiBjYXNlXG4gICAgICAgICAgICAgICAgaWRlbnRpdHkuZW5kcG9pbnRJZCA9PT0gY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCAmJlxuICAgICAgICAgICAgICAgICAgICBpZGVudGl0eS51dWlkID09PSBjbGllbnRJZGVudGl0eS51dWlkICYmXG4gICAgICAgICAgICAgICAgICAgIGlkZW50aXR5Lm5hbWUgPT09IGNsaWVudElkZW50aXR5Lm5hbWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuaXNMZWdhY3lDbGllbnRDb25uZWN0ZWQoY2xpZW50SWRlbnRpdHkpO1xuICAgIH1cbiAgICBpc0xlZ2FjeUNsaWVudENvbm5lY3RlZChjbGllbnRJZGVudGl0eSkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25uZWN0aW9ucy5zb21lKChpZGVudGl0eSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGlkZW50aXR5LnV1aWQgPT09IGNsaWVudElkZW50aXR5LnV1aWQgJiYgaWRlbnRpdHkubmFtZSA9PT0gY2xpZW50SWRlbnRpdHkubmFtZTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGhhbmRsZU11bHRpUnVudGltZUxlZ2FjeUNsaWVudChzZW5kZXJJZGVudGl0eSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNMZWdhY3lDbGllbnRDb25uZWN0ZWQoc2VuZGVySWRlbnRpdHkpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoaXMgYWN0aW9uIHdhcyBzZW50IGZyb20gYSBjbGllbnQgdGhhdCBpcyBub3QgY29ubmVjdGVkIHRvIHRoZSBwcm92aWRlci4gQ2xpZW50IElkZW50aXR5OlxuICAgICAgICAgICAgICAgICAgICB7dXVpZDogJHtzZW5kZXJJZGVudGl0eS51dWlkfSwgbmFtZTogJHtzZW5kZXJJZGVudGl0eS5uYW1lfSwgZW5kcG9pbnRJZDogJHtzZW5kZXJJZGVudGl0eS5lbmRwb2ludElkfX1gKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXRFbmRwb2ludElkRm9yT3BlbkZpbklkKGNsaWVudElkZW50aXR5LCBhY3Rpb24pIHtcbiAgICAgICAgY29uc3QgbWF0Y2hpbmdDb25uZWN0aW9ucyA9IHRoaXMuY29ubmVjdGlvbnMuZmlsdGVyKChjKSA9PiBjLm5hbWUgPT09IGNsaWVudElkZW50aXR5Lm5hbWUgJiYgYy51dWlkID09PSBjbGllbnRJZGVudGl0eS51dWlkKTtcbiAgICAgICAgaWYgKG1hdGNoaW5nQ29ubmVjdGlvbnMubGVuZ3RoID49IDIpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb3RlY3RlZE9iaiA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOCh0aGlzLCBfQ2hhbm5lbFByb3ZpZGVyX3Byb3RlY3RlZE9iaiwgXCJmXCIpO1xuICAgICAgICAgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSBjbGllbnRJZGVudGl0eTtcbiAgICAgICAgICAgIGNvbnN0IHByb3ZpZGVyVXVpZCA9IHByb3RlY3RlZE9iaj8ucHJvdmlkZXJJZGVudGl0eS51dWlkO1xuICAgICAgICAgICAgY29uc3QgcHJvdmlkZXJOYW1lID0gcHJvdGVjdGVkT2JqPy5wcm92aWRlcklkZW50aXR5Lm5hbWU7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICAgICAgY29uc29sZS53YXJuKGBXQVJOSU5HOiBEaXNwYXRjaCBjYWxsIG1heSBoYXZlIHVuaW50ZW5kZWQgcmVzdWx0cy4gVGhlIFwidG9cIiBhcmd1bWVudCBvZiB5b3VyIGRpc3BhdGNoIGNhbGwgaXMgbWlzc2luZyB0aGVcbiAgICAgICAgICAgICAgICBcImVuZHBvaW50SWRcIiBwYXJhbWV0ZXIuIFRoZSBpZGVudGl0eSB5b3UgYXJlIGRpc3BhdGNoaW5nIHRvICh7dXVpZDogJHt1dWlkfSwgbmFtZTogJHtuYW1lfX0pXG4gICAgICAgICAgICAgICAgaGFzIG11bHRpcGxlIGNoYW5uZWxDbGllbnRzIGZvciB0aGlzIGNoYW5uZWwuIFlvdXIgZGlzcGF0Y2hlZCBhY3Rpb246ICgke2FjdGlvbn0pIGZyb20gdGhlIHByb3ZpZGVyOlxuICAgICAgICAgICAgICAgICh7dXVpZDogJHtwcm92aWRlclV1aWR9LCBuYW1lOiAke3Byb3ZpZGVyTmFtZX19KSB3aWxsIG9ubHkgYmUgcHJvY2Vzc2VkIGJ5IHRoZSBtb3N0IHJlY2VudGx5LWNyZWF0ZWQgY2xpZW50LmApO1xuICAgICAgICB9XG4gICAgICAgIC8vIFBvcCB0byByZXR1cm4gdGhlIG1vc3QgcmVjZW50bHkgY3JlYXRlZCBlbmRwb2ludElkLlxuICAgICAgICByZXR1cm4gbWF0Y2hpbmdDb25uZWN0aW9ucy5wb3AoKT8uZW5kcG9pbnRJZDtcbiAgICB9XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcbiAgICBzdGF0aWMgY2xpZW50SWRlbnRpdHlJbmNsdWRlc0VuZHBvaW50SWQoc3Vic2NyaXB0aW9uSWRlbnRpdHkpIHtcbiAgICAgICAgcmV0dXJuIHN1YnNjcmlwdGlvbklkZW50aXR5LmVuZHBvaW50SWQgIT09IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcbiAgICBzdGF0aWMgY2xpZW50SXNNdWx0aVJ1bnRpbWUoc3Vic2NyaXB0aW9uSWRlbnRpdHkpIHtcbiAgICAgICAgcmV0dXJuIHN1YnNjcmlwdGlvbklkZW50aXR5LnJ1bnRpbWVVdWlkICE9PSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHN0YXRpYyBhc3luYyB3aXJlQ2xvc2Uod2lyZSwgY2hhbm5lbE5hbWUpIHtcbiAgICAgICAgYXdhaXQgd2lyZS5zZW5kQWN0aW9uKCdkZXN0cm95LWNoYW5uZWwnLCB7IGNoYW5uZWxOYW1lIH0pO1xuICAgIH1cbn1cbnByb3ZpZGVyLkNoYW5uZWxQcm92aWRlciA9IENoYW5uZWxQcm92aWRlcjtcbl9DaGFubmVsUHJvdmlkZXJfY29ubmVjdGlvbnMgPSBuZXcgV2Vha01hcCgpLCBfQ2hhbm5lbFByb3ZpZGVyX3Byb3RlY3RlZE9iaiA9IG5ldyBXZWFrTWFwKCksIF9DaGFubmVsUHJvdmlkZXJfc3RyYXRlZ3kgPSBuZXcgV2Vha01hcCgpLCBfQ2hhbm5lbFByb3ZpZGVyX3JlbW92ZUVuZHBvaW50ID0gbmV3IFdlYWtNYXAoKSwgX0NoYW5uZWxQcm92aWRlcl9jbG9zZSA9IG5ldyBXZWFrTWFwKCk7XG4vLyBUaGUgZm9sbG93aW5nIGxpbmUgc2hvdWxkIGJlIGNoYW5nZWQgZm9sbG93aW5nIGEgdHlwZXNjcmlwdCB1cGRhdGUuXG4vLyBzdGF0aWMgI3JlbW92YWxNYXAgPSBuZXcgV2Vha01hcDxDaGFubmVsUHJvdmlkZXIsIEZ1bmN0aW9uPigpO1xuQ2hhbm5lbFByb3ZpZGVyLnJlbW92YWxNYXAgPSBuZXcgV2Vha01hcCgpO1xuXG52YXIgbWVzc2FnZVJlY2VpdmVyID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShtZXNzYWdlUmVjZWl2ZXIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xubWVzc2FnZVJlY2VpdmVyLk1lc3NhZ2VSZWNlaXZlciA9IHZvaWQgMDtcbmNvbnN0IGNsaWVudF8xJDEgPSBjbGllbnQ7XG5jb25zdCBiYXNlXzEkZyA9IGJhc2U7XG4vKlxuVGhpcyBpcyBhIHNpbmdsZXRvbiAocGVyIGZpbiBvYmplY3QpIHRhc2tlZCB3aXRoIHJvdXRpbmcgbWVzc2FnZXMgY29taW5nIG9mZiB0aGUgaXBjIHRvIHRoZSBjb3JyZWN0IGVuZHBvaW50LlxuSXQgbmVlZHMgdG8gYmUgYSBzaW5nbGV0b24gYmVjYXVzZSB0aGVyZSBjYW4gb25seSBiZSBvbmUgcGVyIHdpcmUuIEl0IHRyYWNrcyBib3RoIGNsaWVudHMgYW5kIHByb3ZpZGVycycgcHJvY2Vzc0FjdGlvbiBwYXNzZWQgaW4gdmlhIHRoZSBzdHJhdGVneS5cbklmIGZ1bmN0aW9uYWxpdHkgaXMgbm90IGFib3V0IHJlY2VpdmluZyBtZXNzYWdlcywgaXQgZG9lcyBub3QgYmVsb25nIGhlcmUuXG4qL1xuY2xhc3MgTWVzc2FnZVJlY2VpdmVyIGV4dGVuZHMgYmFzZV8xJGcuQmFzZSB7XG4gICAgY29uc3RydWN0b3Iod2lyZSkge1xuICAgICAgICBzdXBlcih3aXJlKTtcbiAgICAgICAgdGhpcy5vbm1lc3NhZ2UgPSAobXNnKSA9PiB7XG4gICAgICAgICAgICBpZiAobXNnLmFjdGlvbiA9PT0gJ3Byb2Nlc3MtY2hhbm5lbC1tZXNzYWdlJykge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc0NoYW5uZWxNZXNzYWdlKG1zZyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZW5kcG9pbnRNYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMubGF0ZXN0RW5kcG9pbnRJZEJ5Q2hhbm5lbElkID0gbmV3IE1hcCgpO1xuICAgICAgICB3aXJlLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIodGhpcy5vbm1lc3NhZ2UuYmluZCh0aGlzKSk7XG4gICAgfVxuICAgIGFzeW5jIHByb2Nlc3NDaGFubmVsTWVzc2FnZShtc2cpIHtcbiAgICAgICAgY29uc3QgeyBzZW5kZXJJZGVudGl0eSwgcHJvdmlkZXJJZGVudGl0eSwgYWN0aW9uLCBhY2tUb1NlbmRlciwgcGF5bG9hZCwgaW50ZW5kZWRUYXJnZXRJZGVudGl0eSB9ID0gbXNnLnBheWxvYWQ7XG4gICAgICAgIGNvbnN0IGtleSA9IGludGVuZGVkVGFyZ2V0SWRlbnRpdHkuY2hhbm5lbElkID8/IC8vIFRoZSByZWNpcGllbnQgaXMgYSBwcm92aWRlclxuICAgICAgICAgICAgaW50ZW5kZWRUYXJnZXRJZGVudGl0eS5lbmRwb2ludElkID8/IC8vIFRoZSByZWNpcGllbnQgaXMgYSBjbGllbnRcbiAgICAgICAgICAgIHRoaXMubGF0ZXN0RW5kcG9pbnRJZEJ5Q2hhbm5lbElkLmdldChwcm92aWRlcklkZW50aXR5LmNoYW5uZWxJZCk7IC8vIE5vIGVuZHBvaW50SWQgd2FzIHBhc3NlZCwgbWFrZSBiZXN0IGF0dGVtcHRcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IHRoaXMuZW5kcG9pbnRNYXAuZ2V0KGtleSk7XG4gICAgICAgIGlmICghaGFuZGxlcikge1xuICAgICAgICAgICAgYWNrVG9TZW5kZXIucGF5bG9hZC5zdWNjZXNzID0gZmFsc2U7XG4gICAgICAgICAgICBhY2tUb1NlbmRlci5wYXlsb2FkLnJlYXNvbiA9IGBDbGllbnQgY29ubmVjdGlvbiB3aXRoIGlkZW50aXR5IHV1aWQ6ICR7dGhpcy53aXJlLm1lLnV1aWR9IC8gbmFtZTogJHt0aGlzLndpcmUubWUubmFtZX0gLyBlbmRwb2ludElkOiAke2tleX0gbm8gbG9uZ2VyIGNvbm5lY3RlZC5gO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kUmF3KGFja1RvU2VuZGVyKTtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgaGFuZGxlcihhY3Rpb24sIHBheWxvYWQsIHNlbmRlcklkZW50aXR5KTtcbiAgICAgICAgICAgIGFja1RvU2VuZGVyLnBheWxvYWQucGF5bG9hZCA9IGFja1RvU2VuZGVyLnBheWxvYWQucGF5bG9hZCB8fCB7fTtcbiAgICAgICAgICAgIGFja1RvU2VuZGVyLnBheWxvYWQucGF5bG9hZC5yZXN1bHQgPSByZXM7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRSYXcoYWNrVG9TZW5kZXIpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBhY2tUb1NlbmRlci5wYXlsb2FkLnN1Y2Nlc3MgPSBmYWxzZTtcbiAgICAgICAgICAgIGFja1RvU2VuZGVyLnBheWxvYWQucmVhc29uID0gZS5tZXNzYWdlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kUmF3KGFja1RvU2VuZGVyKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBhZGRFbmRwb2ludChoYW5kbGVyLCBjaGFubmVsSWQsIGVuZHBvaW50SWQpIHtcbiAgICAgICAgdGhpcy5lbmRwb2ludE1hcC5zZXQoZW5kcG9pbnRJZCwgaGFuZGxlcik7XG4gICAgICAgIC8vIFByb3ZpZGVycyBoYXZlIHRoZSBzYW1lIGVuZHBvaW50SWQgYW5kIGNoYW5uZWxJZC5cbiAgICAgICAgLy8gVGhpcyBpcyBvbmx5IHVzZWQgd2hlbiBjbGllbnRzIGFyZSByZWNlaXZpbmcgbWVzc2FnZXMgZnJvbSBwcm92aWRlcnMsIHNvIHdlIHNob3VsZG4ndCBzYXZlIHByb3ZpZGVyIGVuZHBvaW50SWQgaGVyZS5cbiAgICAgICAgaWYgKGNoYW5uZWxJZCAhPT0gZW5kcG9pbnRJZCkge1xuICAgICAgICAgICAgdGhpcy5sYXRlc3RFbmRwb2ludElkQnlDaGFubmVsSWQuc2V0KGNoYW5uZWxJZCwgZW5kcG9pbnRJZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVtb3ZlRW5kcG9pbnQoY2hhbm5lbElkLCBlbmRwb2ludElkKSB7XG4gICAgICAgIHRoaXMuZW5kcG9pbnRNYXAuZGVsZXRlKGVuZHBvaW50SWQpO1xuICAgICAgICBpZiAodGhpcy5sYXRlc3RFbmRwb2ludElkQnlDaGFubmVsSWQuZ2V0KGNoYW5uZWxJZCkgPT09IGVuZHBvaW50SWQpIHtcbiAgICAgICAgICAgIHRoaXMubGF0ZXN0RW5kcG9pbnRJZEJ5Q2hhbm5lbElkLmRlbGV0ZShjaGFubmVsSWQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNoZWNrRm9yUHJldmlvdXNDbGllbnRDb25uZWN0aW9uKGNoYW5uZWxJZCkge1xuICAgICAgICBjb25zdCBlbmRwb2ludElkRnJvbVByZXZpb3VzQ29ubmVjdGlvbiA9IHRoaXMubGF0ZXN0RW5kcG9pbnRJZEJ5Q2hhbm5lbElkLmdldChjaGFubmVsSWQpO1xuICAgICAgICBpZiAoZW5kcG9pbnRJZEZyb21QcmV2aW91c0Nvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIC8vIE5vdCBjb252aW5jZWQgYnkgdGhpcyB3YXkgb2YgZG9pbmcgdGhpbmdzLCBidXQgcHVzaGluZyB1cCBmb3Igbm93LlxuICAgICAgICAgICAgY2xpZW50XzEkMS5DaGFubmVsQ2xpZW50LmNsb3NlQ2hhbm5lbEJ5RW5kcG9pbnRJZChlbmRwb2ludElkRnJvbVByZXZpb3VzQ29ubmVjdGlvbik7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3UgaGF2ZSBjcmVhdGVkIGEgc2Vjb25kIGNvbm5lY3Rpb24gdG8gYW4gb2xkZXIgcHJvdmlkZXIuIEZpcnN0IGNvbm5lY3Rpb24gaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIHRoZSBjbGllbnRNYXAnKTtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ0lmIHRoZSBwcm92aWRlciBjYWxscyBwdWJsaXNoKCksIHlvdSBtYXkgcmVjZWl2ZSBtdWx0aXBsZSBtZXNzYWdlcy4nKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbm1lc3NhZ2VSZWNlaXZlci5NZXNzYWdlUmVjZWl2ZXIgPSBNZXNzYWdlUmVjZWl2ZXI7XG5cbnZhciBwcm90b2NvbE1hbmFnZXIgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHByb3RvY29sTWFuYWdlciwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5wcm90b2NvbE1hbmFnZXIuUHJvdG9jb2xNYW5hZ2VyID0gdm9pZCAwO1xuLypcblRoaXMgc2hvdWxkIGJlIGFnbm9zdGljIG9mIGFueSBhY3R1YWwgb3BlbmZpbiBjb2RlIHRvIGJlIHVuaXQgdGVzdGFibGUuXG5EZXBlbmRlbmNpZXMgb24gdGhlIGFjdHVhbCBzcmF0ZWdpZXMgc2hvdWxkIGJlIGhhbmRsZWQgaW4gQ29ubmVjdGlvbk1hbmFnZXJcbiovXG5jbGFzcyBQcm90b2NvbE1hbmFnZXIge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11c2VsZXNzLWNvbnN0cnVjdG9yXG4gICAgY29uc3RydWN0b3IoUHJvdG9jb2xzSW5QcmVmZXJlbmNlT3JkZXIpIHtcbiAgICAgICAgdGhpcy5Qcm90b2NvbHNJblByZWZlcmVuY2VPcmRlciA9IFByb3RvY29sc0luUHJlZmVyZW5jZU9yZGVyO1xuICAgICAgICB0aGlzLkRlZmF1bHRDbGllbnRQcm90b2NvbHMgPSBbJ2NsYXNzaWMnXTtcbiAgICAgICAgdGhpcy5EZWZhdWx0UHJvdmlkZXJQcm90b2NvbHMgPSBbJ2NsYXNzaWMnXTtcbiAgICAgICAgdGhpcy5nZXRDbGllbnRQcm90b2NvbHMgPSAocHJvdG9jb2xzKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdXBwb3J0ZWQgPSBwcm90b2NvbHNcbiAgICAgICAgICAgICAgICA/IHRoaXMuUHJvdG9jb2xzSW5QcmVmZXJlbmNlT3JkZXIuZmlsdGVyKCh4KSA9PiBwcm90b2NvbHMuaW5jbHVkZXMoeCkpXG4gICAgICAgICAgICAgICAgOiB0aGlzLkRlZmF1bHRDbGllbnRQcm90b2NvbHM7XG4gICAgICAgICAgICBpZiAoIXN1cHBvcnRlZC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIHZhbGlkIHByb3RvY29scyB3ZXJlIHBhc3NlZCBpbi4gQWNjZXB0ZWQgdmFsdWVzIGFyZTogJHt0aGlzLlByb3RvY29sc0luUHJlZmVyZW5jZU9yZGVyLmpvaW4oJywgJyl9LmApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN1cHBvcnRlZDtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5nZXRQcm92aWRlclByb3RvY29scyA9IChwcm90b2NvbHMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN1cHBvcnRlZCA9IHByb3RvY29sc1xuICAgICAgICAgICAgICAgID8gdGhpcy5Qcm90b2NvbHNJblByZWZlcmVuY2VPcmRlci5maWx0ZXIoKHgpID0+IHByb3RvY29scy5pbmNsdWRlcyh4KSlcbiAgICAgICAgICAgICAgICA6IHRoaXMuRGVmYXVsdFByb3ZpZGVyUHJvdG9jb2xzO1xuICAgICAgICAgICAgaWYgKCFzdXBwb3J0ZWQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyB2YWxpZCBwcm90b2NvbHMgd2VyZSBwYXNzZWQgaW4uIEFjY2VwdGVkIHZhbHVlcyBhcmU6ICR7dGhpcy5Qcm90b2NvbHNJblByZWZlcmVuY2VPcmRlci5qb2luKCcsICcpfS5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzdXBwb3J0ZWQ7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0Q29tcGF0aWJsZVByb3RvY29scyA9IChwcm92aWRlclByb3RvY29scywgY2xpZW50T2ZmZXIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN1cHBvcnRlZCA9IGNsaWVudE9mZmVyLnN1cHBvcnRlZFByb3RvY29scy5maWx0ZXIoKGNsaWVudFByb3RvY29sKSA9PiBwcm92aWRlclByb3RvY29scy5zb21lKChwcm92aWRlclByb3RvY29sKSA9PiBwcm92aWRlclByb3RvY29sLnR5cGUgPT09IGNsaWVudFByb3RvY29sLnR5cGUgJiZcbiAgICAgICAgICAgICAgICBjbGllbnRQcm90b2NvbC52ZXJzaW9uID49IHByb3ZpZGVyUHJvdG9jb2wubWluaW11bVZlcnNpb24gJiZcbiAgICAgICAgICAgICAgICBwcm92aWRlclByb3RvY29sLnZlcnNpb24gPj0gKGNsaWVudFByb3RvY29sLm1pbmltdW1WZXJzaW9uID8/IDApKSk7XG4gICAgICAgICAgICByZXR1cm4gc3VwcG9ydGVkLnNsaWNlKDAsIGNsaWVudE9mZmVyLm1heFByb3RvY29scyk7XG4gICAgICAgIH07XG4gICAgfVxufVxucHJvdG9jb2xNYW5hZ2VyLlByb3RvY29sTWFuYWdlciA9IFByb3RvY29sTWFuYWdlcjtcblxudmFyIHN0cmF0ZWd5ID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShzdHJhdGVneSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jbGFzcyBDb21iaW5lZFN0cmF0ZWd5IHtcbiAgICAvLyBNYWtpbmcgdGhpcyBhIHN0YXRpYyBtZXRob2QgYmVjYXVzZSB0aGUgY29uc3RydWN0b3IgY2FuJ3QgYmUgdHlwZWQuXG4gICAgLy8gT3RoZXJ3aXNlIGl0IHdpbGwgZXJyb3Igd2hlbiBjYWxsaW5nIGFkZEVuZHBvaW50IGJ1dCBJJ2QgcmF0aGVyIHRoZSB3aG9sZSBpbnN0YW5jZSBiZSB0eXBlZCBhcyBuZXZlci5cbiAgICBzdGF0aWMgY29tYmluZShhLCBiKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29tYmluZWRTdHJhdGVneShhLCBiKTtcbiAgICB9XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZWxlc3MtY29uc3RydWN0b3JcbiAgICBjb25zdHJ1Y3RvcihwcmltYXJ5LCBzZWNvbmRhcnkpIHtcbiAgICAgICAgdGhpcy5wcmltYXJ5ID0gcHJpbWFyeTtcbiAgICAgICAgdGhpcy5zZWNvbmRhcnkgPSBzZWNvbmRhcnk7XG4gICAgfVxuICAgIG9uRW5kcG9pbnREaXNjb25uZWN0KGVuZHBvaW50SWQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMucHJpbWFyeS5vbkVuZHBvaW50RGlzY29ubmVjdChlbmRwb2ludElkLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuc2Vjb25kYXJ5LmlzRW5kcG9pbnRDb25uZWN0ZWQoZW5kcG9pbnRJZCkpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5zZWNvbmRhcnkub25FbmRwb2ludERpc2Nvbm5lY3QoZW5kcG9pbnRJZCwgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnByaW1hcnkuaXNFbmRwb2ludENvbm5lY3RlZChlbmRwb2ludElkKSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpc1ZhbGlkRW5kcG9pbnRQYXlsb2FkKHBheWxvYWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJpbWFyeS5pc1ZhbGlkRW5kcG9pbnRQYXlsb2FkKHBheWxvYWQpIHx8IHRoaXMuc2Vjb25kYXJ5LmlzVmFsaWRFbmRwb2ludFBheWxvYWQocGF5bG9hZCk7XG4gICAgfVxuICAgIGFzeW5jIGNsb3NlRW5kcG9pbnQoZW5kcG9pbnRJZCkge1xuICAgICAgICBhd2FpdCB0aGlzLnByaW1hcnkuY2xvc2VFbmRwb2ludChlbmRwb2ludElkKTtcbiAgICAgICAgYXdhaXQgdGhpcy5zZWNvbmRhcnkuY2xvc2VFbmRwb2ludChlbmRwb2ludElkKTtcbiAgICB9XG4gICAgaXNFbmRwb2ludENvbm5lY3RlZChlbmRwb2ludCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wcmltYXJ5LmlzRW5kcG9pbnRDb25uZWN0ZWQoZW5kcG9pbnQpIHx8IHRoaXMuc2Vjb25kYXJ5LmlzRW5kcG9pbnRDb25uZWN0ZWQoZW5kcG9pbnQpO1xuICAgIH1cbiAgICBhc3luYyBhZGRFbmRwb2ludChlbmRwb2ludCwgcGF5bG9hZCkge1xuICAgICAgICBpZiAodGhpcy5wcmltYXJ5LmlzVmFsaWRFbmRwb2ludFBheWxvYWQocGF5bG9hZCkpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucHJpbWFyeS5hZGRFbmRwb2ludChlbmRwb2ludCwgcGF5bG9hZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc2Vjb25kYXJ5LmlzVmFsaWRFbmRwb2ludFBheWxvYWQocGF5bG9hZCkpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc2Vjb25kYXJ5LmFkZEVuZHBvaW50KGVuZHBvaW50LCBwYXlsb2FkKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZWNlaXZlKGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMucHJpbWFyeS5yZWNlaXZlKGxpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5zZWNvbmRhcnkucmVjZWl2ZShsaXN0ZW5lcik7XG4gICAgfVxuICAgIHNlbmQoZW5kcG9pbnRJZCwgYWN0aW9uLCBwYXlsb2FkKSB7XG4gICAgICAgIGlmICh0aGlzLnByaW1hcnkuaXNFbmRwb2ludENvbm5lY3RlZChlbmRwb2ludElkKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJpbWFyeS5zZW5kKGVuZHBvaW50SWQsIGFjdGlvbiwgcGF5bG9hZCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc2Vjb25kYXJ5LnNlbmQoZW5kcG9pbnRJZCwgYWN0aW9uLCBwYXlsb2FkKTtcbiAgICB9XG4gICAgYXN5bmMgY2xvc2UoKSB7XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFt0aGlzLnByaW1hcnkuY2xvc2UoKSwgdGhpcy5zZWNvbmRhcnkuY2xvc2UoKV0pO1xuICAgIH1cbn1cbnN0cmF0ZWd5LmRlZmF1bHQgPSBDb21iaW5lZFN0cmF0ZWd5O1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ1ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDcgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xufTtcbnZhciBfX2ltcG9ydERlZmF1bHQkMSA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2ltcG9ydERlZmF1bHQpIHx8IGZ1bmN0aW9uIChtb2QpIHtcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IFwiZGVmYXVsdFwiOiBtb2QgfTtcbn07XG52YXIgX0Nvbm5lY3Rpb25NYW5hZ2VyX21lc3NhZ2VSZWNlaXZlciwgX0Nvbm5lY3Rpb25NYW5hZ2VyX3J0Y0Nvbm5lY3Rpb25NYW5hZ2VyO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvbm5lY3Rpb25NYW5hZ2VyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbm5lY3Rpb25NYW5hZ2VyLkNvbm5lY3Rpb25NYW5hZ2VyID0gdm9pZCAwO1xuY29uc3QgZXhoYXVzdGl2ZV8xID0gZXhoYXVzdGl2ZTtcbmNvbnN0IGJhc2VfMSRmID0gYmFzZTtcbmNvbnN0IHN0cmF0ZWd5XzEgPSBzdHJhdGVneSQzO1xuY29uc3Qgc3RyYXRlZ3lfMiA9IHN0cmF0ZWd5JDI7XG5jb25zdCBpY2VfbWFuYWdlcl8xID0gaWNlTWFuYWdlcjtcbmNvbnN0IHByb3ZpZGVyXzEkMSA9IHByb3ZpZGVyO1xuY29uc3QgbWVzc2FnZV9yZWNlaXZlcl8xID0gbWVzc2FnZVJlY2VpdmVyO1xuY29uc3QgcHJvdG9jb2xfbWFuYWdlcl8xID0gcHJvdG9jb2xNYW5hZ2VyO1xuY29uc3Qgc3RyYXRlZ3lfMyA9IF9faW1wb3J0RGVmYXVsdCQxKHN0cmF0ZWd5KTtcbmNsYXNzIENvbm5lY3Rpb25NYW5hZ2VyIGV4dGVuZHMgYmFzZV8xJGYuQmFzZSB7XG4gICAgc3RhdGljIGdldFByb3RvY29sT3B0aW9uc0Zyb21TdHJpbmdzKHByb3RvY29scykge1xuICAgICAgICByZXR1cm4gcHJvdG9jb2xzLm1hcCgocHJvdG9jb2wpID0+IHtcbiAgICAgICAgICAgIHN3aXRjaCAocHJvdG9jb2wpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdydGMnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyYXRlZ3lfMi5SVENJbmZvO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NsYXNzaWMnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyYXRlZ3lfMS5DbGFzc2ljSW5mbztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIGV4aGF1c3RpdmVfMS5leGhhdXN0aXZlQ2hlY2spKHByb3RvY29sLCBbJ3J0YycsICdjbGFzc2ljJ10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgY29uc3RydWN0b3Iod2lyZSkge1xuICAgICAgICBzdXBlcih3aXJlKTtcbiAgICAgICAgX0Nvbm5lY3Rpb25NYW5hZ2VyX21lc3NhZ2VSZWNlaXZlci5zZXQodGhpcywgdm9pZCAwKTtcbiAgICAgICAgX0Nvbm5lY3Rpb25NYW5hZ2VyX3J0Y0Nvbm5lY3Rpb25NYW5hZ2VyLnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICB0aGlzLnJlbW92ZUNoYW5uZWxGcm9tUHJvdmlkZXJNYXAgPSAoY2hhbm5lbElkKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnByb3ZpZGVyTWFwLmRlbGV0ZShjaGFubmVsSWQpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLm9ubWVzc2FnZSA9IChtc2cpID0+IHtcbiAgICAgICAgICAgIGlmIChtc2cuYWN0aW9uID09PSAncHJvY2Vzcy1jaGFubmVsLWNvbm5lY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzQ2hhbm5lbENvbm5lY3Rpb24obXNnKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5wcm92aWRlck1hcCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5wcm90b2NvbE1hbmFnZXIgPSBuZXcgcHJvdG9jb2xfbWFuYWdlcl8xLlByb3RvY29sTWFuYWdlcih0aGlzLndpcmUuZW52aXJvbm1lbnQudHlwZSA9PT0gJ25vZGUnID8gWydjbGFzc2ljJ10gOiBbJ3J0YycsICdjbGFzc2ljJ10pO1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDUodGhpcywgX0Nvbm5lY3Rpb25NYW5hZ2VyX21lc3NhZ2VSZWNlaXZlciwgbmV3IG1lc3NhZ2VfcmVjZWl2ZXJfMS5NZXNzYWdlUmVjZWl2ZXIod2lyZSksIFwiZlwiKTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ1KHRoaXMsIF9Db25uZWN0aW9uTWFuYWdlcl9ydGNDb25uZWN0aW9uTWFuYWdlciwgbmV3IGljZV9tYW5hZ2VyXzEuUlRDSUNFTWFuYWdlcih3aXJlKSwgXCJmXCIpO1xuICAgICAgICB3aXJlLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIodGhpcy5vbm1lc3NhZ2UuYmluZCh0aGlzKSk7XG4gICAgfVxuICAgIGNyZWF0ZVByb3ZpZGVyKG9wdGlvbnMsIHByb3ZpZGVySWRlbnRpdHkpIHtcbiAgICAgICAgY29uc3Qgb3B0cyA9IE9iamVjdC5hc3NpZ24odGhpcy53aXJlLmVudmlyb25tZW50LmdldERlZmF1bHRDaGFubmVsT3B0aW9ucygpLmNyZWF0ZSwgb3B0aW9ucyB8fCB7fSk7XG4gICAgICAgIGNvbnN0IHByb3RvY29scyA9IHRoaXMucHJvdG9jb2xNYW5hZ2VyLmdldFByb3ZpZGVyUHJvdG9jb2xzKG9wdHM/LnByb3RvY29scyk7XG4gICAgICAgIGNvbnN0IGNyZWF0ZVNpbmdsZVN0cmF0ZWd5ID0gKHN0cmF0VHlwZSkgPT4ge1xuICAgICAgICAgICAgc3dpdGNoIChzdHJhdFR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdydGMnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IHN0cmF0ZWd5XzIuUlRDU3RyYXRlZ3koKTtcbiAgICAgICAgICAgICAgICBjYXNlICdjbGFzc2ljJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBzdHJhdGVneV8xLkNsYXNzaWNTdHJhdGVneSh0aGlzLndpcmUsIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNyh0aGlzLCBfQ29ubmVjdGlvbk1hbmFnZXJfbWVzc2FnZVJlY2VpdmVyLCBcImZcIiksIFxuICAgICAgICAgICAgICAgICAgICAvLyBQcm92aWRlcnMgZG8gbm90IGhhdmUgYW4gZW5kcG9pbnRJZCwgdXNlIGNoYW5uZWxJZCBhcyBlbmRwb2ludElkIGluIHRoZSBzdHJhdGVneS5cbiAgICAgICAgICAgICAgICAgICAgcHJvdmlkZXJJZGVudGl0eS5jaGFubmVsSWQsIHByb3ZpZGVySWRlbnRpdHkpO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoMCwgZXhoYXVzdGl2ZV8xLmV4aGF1c3RpdmVDaGVjaykoc3RyYXRUeXBlLCBbJ3J0YycsICdjbGFzc2ljJ10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBzdHJhdGVnaWVzID0gcHJvdG9jb2xzLm1hcChjcmVhdGVTaW5nbGVTdHJhdGVneSk7XG4gICAgICAgIGxldCBzdHJhdGVneTtcbiAgICAgICAgaWYgKHN0cmF0ZWdpZXMubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgICBjb25zdCBbYSwgYl0gPSBzdHJhdGVnaWVzO1xuICAgICAgICAgICAgc3RyYXRlZ3kgPSBzdHJhdGVneV8zLmRlZmF1bHQuY29tYmluZShhLCBiKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChzdHJhdGVnaWVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgW3N0cmF0ZWd5XSA9IHN0cmF0ZWdpZXM7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBTaG91bGQgYmUgaW1wb3NzaWJsZS5cbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZmFpbGVkIHRvIGNvbWJpbmUgc3RyYXRlZ2llcycpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoYW5uZWwgPSBuZXcgcHJvdmlkZXJfMSQxLkNoYW5uZWxQcm92aWRlcihwcm92aWRlcklkZW50aXR5LCAoKSA9PiBwcm92aWRlcl8xJDEuQ2hhbm5lbFByb3ZpZGVyLndpcmVDbG9zZSh0aGlzLndpcmUsIHByb3ZpZGVySWRlbnRpdHkuY2hhbm5lbE5hbWUpLCBzdHJhdGVneSk7XG4gICAgICAgIGNvbnN0IGtleSA9IHByb3ZpZGVySWRlbnRpdHkuY2hhbm5lbElkO1xuICAgICAgICB0aGlzLnByb3ZpZGVyTWFwLnNldChrZXksIHtcbiAgICAgICAgICAgIHByb3ZpZGVyOiBjaGFubmVsLFxuICAgICAgICAgICAgc3RyYXRlZ3ksXG4gICAgICAgICAgICBzdXBwb3J0ZWRQcm90b2NvbHM6IENvbm5lY3Rpb25NYW5hZ2VyLmdldFByb3RvY29sT3B0aW9uc0Zyb21TdHJpbmdzKHByb3RvY29scylcbiAgICAgICAgfSk7XG4gICAgICAgIHByb3ZpZGVyXzEkMS5DaGFubmVsUHJvdmlkZXIuc2V0UHJvdmlkZXJSZW1vdmFsKGNoYW5uZWwsIHRoaXMucmVtb3ZlQ2hhbm5lbEZyb21Qcm92aWRlck1hcC5iaW5kKHRoaXMpKTtcbiAgICAgICAgcmV0dXJuIGNoYW5uZWw7XG4gICAgfVxuICAgIGFzeW5jIGNyZWF0ZUNsaWVudE9mZmVyKG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgcHJvdG9jb2xzID0gdGhpcy5wcm90b2NvbE1hbmFnZXIuZ2V0Q2xpZW50UHJvdG9jb2xzKG9wdGlvbnM/LnByb3RvY29scyk7XG4gICAgICAgIGxldCBydGNQYWNrZXQ7XG4gICAgICAgIGNvbnN0IHN1cHBvcnRlZFByb3RvY29scyA9IGF3YWl0IFByb21pc2UuYWxsKHByb3RvY29scy5tYXAoYXN5bmMgKHR5cGUpID0+IHtcbiAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3J0Yyc6IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeyBydGNDbGllbnQsIGNoYW5uZWxzLCBvZmZlciwgcnRjQ29ubmVjdGlvbklkLCBjaGFubmVsc09wZW5lZCB9ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ3KHRoaXMsIF9Db25uZWN0aW9uTWFuYWdlcl9ydGNDb25uZWN0aW9uTWFuYWdlciwgXCJmXCIpLnN0YXJ0Q2xpZW50T2ZmZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgcnRjUGFja2V0ID0geyBydGNDbGllbnQsIGNoYW5uZWxzLCBjaGFubmVsc09wZW5lZCB9O1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3J0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uOiBzdHJhdGVneV8yLlJUQ0luZm8udmVyc2lvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHBheWxvYWQ6IHsgb2ZmZXIsIHJ0Y0Nvbm5lY3Rpb25JZCB9XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhc2UgJ2NsYXNzaWMnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4geyB0eXBlOiAnY2xhc3NpYycsIHZlcnNpb246IHN0cmF0ZWd5XzEuQ2xhc3NpY0luZm8udmVyc2lvbiB9O1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoMCwgZXhoYXVzdGl2ZV8xLmV4aGF1c3RpdmVDaGVjaykodHlwZSwgWydydGMnLCAnY2xhc3NpYyddKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb2ZmZXI6IHtcbiAgICAgICAgICAgICAgICBzdXBwb3J0ZWRQcm90b2NvbHMsXG4gICAgICAgICAgICAgICAgbWF4UHJvdG9jb2xzOiAyXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcnRjOiBydGNQYWNrZXRcbiAgICAgICAgfTtcbiAgICB9XG4gICAgYXN5bmMgY3JlYXRlQ2xpZW50U3RyYXRlZ3kocnRjUGFja2V0LCByb3V0aW5nSW5mbykge1xuICAgICAgICBpZiAoIXJvdXRpbmdJbmZvLmVuZHBvaW50SWQpIHtcbiAgICAgICAgICAgIHJvdXRpbmdJbmZvLmVuZHBvaW50SWQgPSB0aGlzLndpcmUuZW52aXJvbm1lbnQuZ2V0TmV4dE1lc3NhZ2VJZCgpO1xuICAgICAgICAgICAgLy8gRm9yIE5ldyBDbGllbnRzIGNvbm5lY3RpbmcgdG8gT2xkIFByb3ZpZGVycy4gVG8gcHJldmVudCBtdWx0aS1kaXNwYXRjaGluZyBhbmQgcHVibGlzaGluZywgd2UgZGVsZXRlIHByZXZpb3VzbHktY29ubmVjdGVkXG4gICAgICAgICAgICAvLyBjbGllbnRzIHRoYXQgYXJlIGluIHRoZSBzYW1lIGNvbnRleHQgYXMgdGhlIG5ld2x5LWNvbm5lY3RlZCBjbGllbnQuXG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDcodGhpcywgX0Nvbm5lY3Rpb25NYW5hZ2VyX21lc3NhZ2VSZWNlaXZlciwgXCJmXCIpLmNoZWNrRm9yUHJldmlvdXNDbGllbnRDb25uZWN0aW9uKHJvdXRpbmdJbmZvLmNoYW5uZWxJZCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYW5zd2VyID0gcm91dGluZ0luZm8uYW5zd2VyID8/IHtcbiAgICAgICAgICAgIHN1cHBvcnRlZFByb3RvY29sczogW3sgdHlwZTogJ2NsYXNzaWMnLCB2ZXJzaW9uOiAxIH1dXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGNyZWF0ZVN0cmF0ZWd5RnJvbUFuc3dlciA9IGFzeW5jIChwcm90b2NvbCkgPT4ge1xuICAgICAgICAgICAgaWYgKHByb3RvY29sLnR5cGUgPT09ICdydGMnICYmIHJ0Y1BhY2tldCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNyh0aGlzLCBfQ29ubmVjdGlvbk1hbmFnZXJfcnRjQ29ubmVjdGlvbk1hbmFnZXIsIFwiZlwiKS5maW5pc2hDbGllbnRPZmZlcihydGNQYWNrZXQucnRjQ2xpZW50LCBwcm90b2NvbC5wYXlsb2FkLmFuc3dlciwgcnRjUGFja2V0LmNoYW5uZWxzT3BlbmVkKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IHN0cmF0ZWd5XzIuUlRDU3RyYXRlZ3koKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwcm90b2NvbC50eXBlID09PSAnY2xhc3NpYycpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IHN0cmF0ZWd5XzEuQ2xhc3NpY1N0cmF0ZWd5KHRoaXMud2lyZSwgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ3KHRoaXMsIF9Db25uZWN0aW9uTWFuYWdlcl9tZXNzYWdlUmVjZWl2ZXIsIFwiZlwiKSwgcm91dGluZ0luZm8uZW5kcG9pbnRJZCwgcm91dGluZ0luZm8pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGFsbFByb3RvY29scyA9IChhd2FpdCBQcm9taXNlLmFsbChhbnN3ZXIuc3VwcG9ydGVkUHJvdG9jb2xzLm1hcChjcmVhdGVTdHJhdGVneUZyb21BbnN3ZXIpKSkuZmlsdGVyKCh4KSA9PiB4ICE9PSBudWxsKTtcbiAgICAgICAgLy8gQ2xlYW4gdXAgbG9naWMgaWYgcHJvdmlkZXIgZGlkbid0IHN1cHBvcnQgcnRjLlxuICAgICAgICBpZiAocnRjUGFja2V0ICYmICFhbGxQcm90b2NvbHMuc29tZSgoeCkgPT4geCBpbnN0YW5jZW9mIHN0cmF0ZWd5XzIuUlRDU3RyYXRlZ3kpKSB7XG4gICAgICAgICAgICBpZiAocnRjUGFja2V0KSB7XG4gICAgICAgICAgICAgICAgcnRjUGFja2V0LnJ0Y0NsaWVudC5jbG9zZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGxldCBzdHJhdGVneTtcbiAgICAgICAgaWYgKGFsbFByb3RvY29scy5sZW5ndGggPj0gMikge1xuICAgICAgICAgICAgc3RyYXRlZ3kgPSBzdHJhdGVneV8zLmRlZmF1bHQuY29tYmluZShhbGxQcm90b2NvbHNbMF0sIGFsbFByb3RvY29sc1sxXSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoYWxsUHJvdG9jb2xzLmxlbmd0aCkge1xuICAgICAgICAgICAgW3N0cmF0ZWd5XSA9IGFsbFByb3RvY29scztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNob3VsZCBiZSBpbXBvc3NpYmxlLlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjb21wYXRpYmxlIHByb3RvY29scycpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGFzIGNhc3RpbmcgcnRjUGFja2V0IGJlY2F1c2Ugd2Ugd29uJ3QgaGF2ZSBhbiBydGNTdHJhdGVneSBpZiBydGNQYWNrZXQgaXMgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBlbmRwb2ludFBheWxvYWQgPSB7IGVuZHBvaW50SWRlbnRpdHk6IHJvdXRpbmdJbmZvLCBydGM6IHJ0Y1BhY2tldCB9O1xuICAgICAgICBzdHJhdGVneS5hZGRFbmRwb2ludChyb3V0aW5nSW5mby5jaGFubmVsSWQsIGVuZHBvaW50UGF5bG9hZCk7XG4gICAgICAgIHJldHVybiBzdHJhdGVneTtcbiAgICB9XG4gICAgYXN5bmMgcHJvY2Vzc0NoYW5uZWxDb25uZWN0aW9uKG1zZykge1xuICAgICAgICBjb25zdCB7IGNsaWVudElkZW50aXR5LCBwcm92aWRlcklkZW50aXR5LCBhY2tUb1NlbmRlciwgcGF5bG9hZCwgb2ZmZXI6IGNsaWVudE9mZmVyIH0gPSBtc2cucGF5bG9hZDtcbiAgICAgICAgaWYgKCFjbGllbnRJZGVudGl0eS5lbmRwb2ludElkKSB7XG4gICAgICAgICAgICAvLyBTaG91bGQgYmUgcG9seWZpbGxlZCBieSBjb3JlIGJ1dCBub3QgaW4gY2FzZXMgb2Ygbm9kZSBjb25uZWN0aW5nIHRvIGFuIG9sZCBydW50aW1lLlxuICAgICAgICAgICAgY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCA9IHRoaXMud2lyZS5lbnZpcm9ubWVudC5nZXROZXh0TWVzc2FnZUlkKCk7XG4gICAgICAgICAgICBjbGllbnRJZGVudGl0eS5pc0xvY2FsRW5kcG9pbnRJZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjbGllbnRJZGVudGl0eS5pc0xvY2FsRW5kcG9pbnRJZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGtleSA9IHByb3ZpZGVySWRlbnRpdHkuY2hhbm5lbElkO1xuICAgICAgICBjb25zdCBidXMgPSB0aGlzLnByb3ZpZGVyTWFwLmdldChrZXkpO1xuICAgICAgICBpZiAoIWJ1cykge1xuICAgICAgICAgICAgYWNrVG9TZW5kZXIucGF5bG9hZC5zdWNjZXNzID0gZmFsc2U7XG4gICAgICAgICAgICBhY2tUb1NlbmRlci5wYXlsb2FkLnJlYXNvbiA9IGBDaGFubmVsIFwiJHtwcm92aWRlcklkZW50aXR5LmNoYW5uZWxOYW1lfVwiIGhhcyBiZWVuIGRlc3Ryb3llZC5gO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kUmF3KGFja1RvU2VuZGVyKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IHByb3ZpZGVyLCBzdHJhdGVneSwgc3VwcG9ydGVkUHJvdG9jb2xzIH0gPSBidXM7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoIShwcm92aWRlciBpbnN0YW5jZW9mIHByb3ZpZGVyXzEkMS5DaGFubmVsUHJvdmlkZXIpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoJ0Nhbm5vdCBjb25uZWN0IHRvIGEgY2hhbm5lbCBjbGllbnQnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG9mZmVyID0gY2xpZW50T2ZmZXIgPz8ge1xuICAgICAgICAgICAgICAgIHN1cHBvcnRlZFByb3RvY29sczogW3sgdHlwZTogJ2NsYXNzaWMnLCB2ZXJzaW9uOiAxIH1dLFxuICAgICAgICAgICAgICAgIG1heFByb3RvY29sczogMVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IG92ZXJsYXBwaW5nUHJvdG9jb2xzID0gdGhpcy5wcm90b2NvbE1hbmFnZXIuZ2V0Q29tcGF0aWJsZVByb3RvY29scyhzdXBwb3J0ZWRQcm90b2NvbHMsIG9mZmVyKTtcbiAgICAgICAgICAgIGlmICghb3ZlcmxhcHBpbmdQcm90b2NvbHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGlzIHByb3ZpZGVyIGRvZXMgbm90IHN1cHBvcnQgYW55IG9mIHRoZSBvZmZlcmVkIHByb3RvY29scy4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHByb3ZpZGVyLnByb2Nlc3NDb25uZWN0aW9uKGNsaWVudElkZW50aXR5LCBwYXlsb2FkKTtcbiAgICAgICAgICAgIGFja1RvU2VuZGVyLnBheWxvYWQucGF5bG9hZCA9IGFja1RvU2VuZGVyLnBheWxvYWQucGF5bG9hZCB8fCB7fTtcbiAgICAgICAgICAgIC8vIExvb3AgdGhyb3VnaCBhbGwgc3VwcG9ydGVkIHByb3RvY29scyBhbmQgYWNjdW11bGF0ZSB0aGVtIGludG8gdGhlIGFuc3dlclxuICAgICAgICAgICAgLy8gYWRkRW5kcG9pbnQgaXMgdHJpY2t5IGJ1dCB3ZSBuZWVkIHRvIHdhaXQgZm9yIGNoYW5uZWwgcmVzb2x1dGlvbiBiZWZvcmUgYWRkaW5nIHRoZSBlbmRwb2ludC5cbiAgICAgICAgICAgIGxldCBjbGllbnRBbnN3ZXIgPSB7XG4gICAgICAgICAgICAgICAgc3VwcG9ydGVkUHJvdG9jb2xzOiBbXSxcbiAgICAgICAgICAgICAgICBlbmRwb2ludFBheWxvYWRQcm9taXNlOiBQcm9taXNlLnJlc29sdmUoeyBlbmRwb2ludElkZW50aXR5OiBjbGllbnRJZGVudGl0eSB9KVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNsaWVudEFuc3dlciA9IGF3YWl0IG92ZXJsYXBwaW5nUHJvdG9jb2xzLnJlZHVjZShhc3luYyAoYWNjdW1QLCBwcm90b2NvbFRvVXNlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgYW5zd2VyID0gYXdhaXQgYWNjdW1QO1xuICAgICAgICAgICAgICAgIGlmIChwcm90b2NvbFRvVXNlLnR5cGUgPT09ICdydGMnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgYW5zd2VyOiBydGNBbnN3ZXIsIHJ0Y0NsaWVudCwgY2hhbm5lbHMgfSA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNyh0aGlzLCBfQ29ubmVjdGlvbk1hbmFnZXJfcnRjQ29ubmVjdGlvbk1hbmFnZXIsIFwiZlwiKS5jcmVhdGVQcm92aWRlckFuc3dlcihwcm90b2NvbFRvVXNlLnBheWxvYWQucnRjQ29ubmVjdGlvbklkLCBwcm90b2NvbFRvVXNlLnBheWxvYWQub2ZmZXIpO1xuICAgICAgICAgICAgICAgICAgICBhbnN3ZXIuc3VwcG9ydGVkUHJvdG9jb2xzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3J0YycsXG4gICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uOiBzdHJhdGVneV8yLlJUQ0luZm8udmVyc2lvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbnN3ZXI6IHJ0Y0Fuc3dlclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgYW5zd2VyLmVuZHBvaW50UGF5bG9hZFByb21pc2UgPSBhbnN3ZXIuZW5kcG9pbnRQYXlsb2FkUHJvbWlzZS50aGVuKChlbmRwb2ludFBheWxvYWQpID0+IGNoYW5uZWxzLnRoZW4oKHJlc29sdmVkQ2hhbm5lbHMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uZW5kcG9pbnRQYXlsb2FkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ0Yzoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBydGNDbGllbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYW5uZWxzOiByZXNvbHZlZENoYW5uZWxzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYW5zd2VyLnN1cHBvcnRlZFByb3RvY29scy5wdXNoKHsgdHlwZTogJ2NsYXNzaWMnLCB2ZXJzaW9uOiBzdHJhdGVneV8xLkNsYXNzaWNJbmZvLnZlcnNpb24gfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBhbnN3ZXI7XG4gICAgICAgICAgICB9LCBQcm9taXNlLnJlc29sdmUoY2xpZW50QW5zd2VyKSk7XG4gICAgICAgICAgICAvLyBOZWVkIHRvIGFzIGNhc3QgaGVyZS5cbiAgICAgICAgICAgIGNsaWVudEFuc3dlci5lbmRwb2ludFBheWxvYWRQcm9taXNlLnRoZW4oKGVuZHBvaW50UGF5bG9hZCkgPT4gc3RyYXRlZ3kuYWRkRW5kcG9pbnQoY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCwgZW5kcG9pbnRQYXlsb2FkKSk7XG4gICAgICAgICAgICBhY2tUb1NlbmRlci5wYXlsb2FkLnBheWxvYWQucmVzdWx0ID0gcmVzO1xuICAgICAgICAgICAgYWNrVG9TZW5kZXIucGF5bG9hZC5wYXlsb2FkLmFuc3dlciA9IGNsaWVudEFuc3dlcjtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZFJhdyhhY2tUb1NlbmRlcik7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGFja1RvU2VuZGVyLnBheWxvYWQuc3VjY2VzcyA9IGZhbHNlO1xuICAgICAgICAgICAgYWNrVG9TZW5kZXIucGF5bG9hZC5yZWFzb24gPSBlLm1lc3NhZ2U7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRSYXcoYWNrVG9TZW5kZXIpO1xuICAgICAgICB9XG4gICAgfVxufVxuY29ubmVjdGlvbk1hbmFnZXIuQ29ubmVjdGlvbk1hbmFnZXIgPSBDb25uZWN0aW9uTWFuYWdlcjtcbl9Db25uZWN0aW9uTWFuYWdlcl9tZXNzYWdlUmVjZWl2ZXIgPSBuZXcgV2Vha01hcCgpLCBfQ29ubmVjdGlvbk1hbmFnZXJfcnRjQ29ubmVjdGlvbk1hbmFnZXIgPSBuZXcgV2Vha01hcCgpO1xuXG4vKipcbiAqIEVudHJ5IHBvaW50cyBmb3IgdGhlIGBDaGFubmVsYCBzdWJzZXQgb2YgdGhlIGBJbnRlckFwcGxpY2F0aW9uQnVzYCBBUEkgKGBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsYCkuXG4gKlxuICogKiB7QGxpbmsgQ2hhbm5lbH0gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBDaGFubmVsYCBBUEksIGFjY2Vzc2libGUgdGhyb3VnaCBgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbGAuXG4gKiAqIHtAbGluayBPcGVuRmluLkNoYW5uZWxDbGllbnR9IGRlc2NyaWJlcyBhIGNsaWVudCBvZiBhIGNoYW5uZWwsIGUuZy4gYXMgcmV0dXJuZWQgYnkgYGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY29ubmVjdGAuXG4gKiAqIHtAbGluayBPcGVuRmluLkNoYW5uZWxQcm92aWRlcn0gZGVzY3JpYmVzIGEgcHJvdmlkZXIgb2YgYSBjaGFubmVsLCBlLmcuIGFzIHJldHVybmVkIGJ5IGBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZWAuXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XG59O1xudmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNiA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9DaGFubmVsX2Nvbm5lY3Rpb25NYW5hZ2VyLCBfQ2hhbm5lbF9pbnRlcm5hbEVtaXR0ZXIsIF9DaGFubmVsX3JlYWR5VG9Db25uZWN0O1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGNoYW5uZWwkMSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jaGFubmVsJDEuQ2hhbm5lbCA9IHZvaWQgMDtcbi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cbmNvbnN0IGV2ZW50c18xJDUgPSByZXF1aXJlJCQwO1xuY29uc3QgbGF6eV8xJDEgPSBsYXp5O1xuY29uc3QgYmFzZV8xJGUgPSBiYXNlO1xuY29uc3QgY2xpZW50XzEgPSBjbGllbnQ7XG5jb25zdCBjb25uZWN0aW9uX21hbmFnZXJfMSA9IGNvbm5lY3Rpb25NYW5hZ2VyO1xuY29uc3QgcHJvdmlkZXJfMSA9IHByb3ZpZGVyO1xuZnVuY3Rpb24gcmV0cnlEZWxheShjb3VudCkge1xuICAgIGNvbnN0IGludGVydmFsID0gNTAwOyAvLyBiYXNlIGRlbGF5XG4gICAgY29uc3Qgc3RlcHMgPSAxMDsgLy8gSG93IG1hbnkgcmV0cmllcyB0byBkbyBiZWZvcmUgaW5jcmVtZW50aW5nIHRoZSBkZWxheVxuICAgIGNvbnN0IGJhc2UgPSAyOyAvLyBIb3cgbXVjaCB0byBtdWx0aXBseSB0aGUgcHJldmlvdXMgZGVsYXkgYnlcbiAgICBjb25zdCBtYXggPSAzMDAwMDsgLy8gbWF4IGRlbGF5XG4gICAgY29uc3Qgc3RlcCA9IE1hdGguZmxvb3IoY291bnQgLyBzdGVwcyk7XG4gICAgY29uc3QgZGVsYXkgPSBNYXRoLm1pbihtYXgsIGludGVydmFsICogYmFzZSAqKiBzdGVwKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgfSwgZGVsYXkpO1xuICAgIH0pO1xufVxuLyoqXG4gKiBUaGUgQ2hhbm5lbCBBUEkgYWxsb3dzIGFuIE9wZW5GaW4gYXBwbGljYXRpb24gdG8gY3JlYXRlIGEgY2hhbm5lbCBhcyBhIHtAbGluayBDaGFubmVsUHJvdmlkZXIgQ2hhbm5lbFByb3ZpZGVyfSxcbiAqIG9yIGNvbm5lY3QgdG8gYSBjaGFubmVsIGFzIGEge0BsaW5rIENoYW5uZWxDbGllbnQgQ2hhbm5lbENsaWVudH0uXG4gKiBAcmVtYXJrcyBUaGUgXCJoYW5kc2hha2VcIiBiZXR3ZWVuIHRoZSBjb21tdW5pY2F0aW9uIHBhcnRuZXJzIGlzXG4gKiBzaW1wbGlmaWVkIHdoZW4gdXNpbmcgYSBjaGFubmVsLiAgQSByZXF1ZXN0IHRvIGNvbm5lY3QgdG8gYSBjaGFubmVsIGFzIGEgY2xpZW50IHdpbGwgcmV0dXJuIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIGlmL3doZW4gdGhlIGNoYW5uZWwgaGFzIGJlZW4gY3JlYXRlZC4gQm90aCB0aGVcbiAqIHByb3ZpZGVyIGFuZCBjbGllbnQgY2FuIGRpc3BhdGNoIGFjdGlvbnMgdGhhdCBoYXZlIGJlZW4gcmVnaXN0ZXJlZCBvbiB0aGVpciBvcHBvc2l0ZXMsIGFuZCBkaXNwYXRjaCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggYSBwYXlsb2FkIGZyb20gdGhlIG90aGVyXG4gKiBjb21tdW5pY2F0aW9uIHBhcnRpY2lwYW50LiBUaGVyZSBjYW4gYmUgb25seSBvbmUgcHJvdmlkZXIgcGVyIGNoYW5uZWwsIGJ1dCBtYW55IGNsaWVudHMuICBWZXJzaW9uIGA5LjYxLjM1LipgIG9yIGxhdGVyIGlzIHJlcXVpcmVkIGZvciBib3RoIGNvbW11bmljYXRpb24gcGFydG5lcnMuXG4gKlxuICogQXN5bmNocm9ub3VzIE1ldGhvZHM6XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbC5jcmVhdGUgY3JlYXRlKGNoYW5uZWxOYW1lLCBvcHRpb25zKX1cbiAqICAqIHtAbGluayBDaGFubmVsLmNvbm5lY3QgY29ubmVjdChjaGFubmVsTmFtZSwgb3B0aW9ucyl9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbC5vbkNoYW5uZWxDb25uZWN0IG9uQ2hhbm5lbENvbm5lY3QobGlzdGVuZXIpfVxuICogICoge0BsaW5rIENoYW5uZWwub25DaGFubmVsRGlzY29ubmVjdCBvbkNoYW5uZWxEaXNjb25uZWN0KGxpc3RlbmVyKX1cbiAqL1xuY2xhc3MgQ2hhbm5lbCBleHRlbmRzIGJhc2VfMSRlLkVtaXR0ZXJCYXNlIHtcbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih3aXJlKSB7XG4gICAgICAgIHN1cGVyKHdpcmUsICdjaGFubmVsJyk7XG4gICAgICAgIF9DaGFubmVsX2Nvbm5lY3Rpb25NYW5hZ2VyLnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICBfQ2hhbm5lbF9pbnRlcm5hbEVtaXR0ZXIuc2V0KHRoaXMsIG5ldyBldmVudHNfMSQ1LkV2ZW50RW1pdHRlcigpKTtcbiAgICAgICAgLy8gT3BlbkZpbiBBUEkgaGFzIG5vdCBiZWVuIGluamVjdGVkIGF0IGNvbnN0cnVjdGlvbiB0aW1lLCAqbXVzdCogd2FpdCBmb3IgQVBJIHRvIGJlIHJlYWR5LlxuICAgICAgICBfQ2hhbm5lbF9yZWFkeVRvQ29ubmVjdC5zZXQodGhpcywgbmV3IGxhenlfMSQxLkFzeW5jUmV0cnlhYmxlTGF6eShhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgdGhpcy5vbignZGlzY29ubmVjdGVkJywgKGV2ZW50UGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjbGllbnRfMS5DaGFubmVsQ2xpZW50LmhhbmRsZVByb3ZpZGVyRGlzY29ubmVjdChldmVudFBheWxvYWQpO1xuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIHRoaXMub24oJ2Nvbm5lY3RlZCcsICguLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNih0aGlzLCBfQ2hhbm5lbF9pbnRlcm5hbEVtaXR0ZXIsIFwiZlwiKS5lbWl0KCdjb25uZWN0ZWQnLCAuLi5hcmdzKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgXSkuY2F0Y2goKCkgPT4gbmV3IEVycm9yKCdlcnJvciBzZXR0aW5nIHVwIGNoYW5uZWwgY29ubmVjdGlvbiBsaXN0ZW5lcnMnKSk7XG4gICAgICAgIH0pKTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ0KHRoaXMsIF9DaGFubmVsX2Nvbm5lY3Rpb25NYW5hZ2VyLCBuZXcgY29ubmVjdGlvbl9tYW5hZ2VyXzEuQ29ubmVjdGlvbk1hbmFnZXIod2lyZSksIFwiZlwiKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBhc3luYyBnZXRBbGxDaGFubmVscygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtYWxsLWNoYW5uZWxzJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIExpc3RlbnMgZm9yIGNoYW5uZWwgY29ubmVjdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbGlzdGVuZXIgLSBjYWxsYmFjayB0byBleGVjdXRlLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgbGlzdGVuZXIgPSAoY2hhbm5lbFBheWxvYWQpID0+IGNvbnNvbGUubG9nKGNoYW5uZWxQYXlsb2FkKTsgLy8gc2VlIHJldHVybiB2YWx1ZSBiZWxvd1xuICAgICAqXG4gICAgICogZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5vbkNoYW5uZWxDb25uZWN0KGxpc3RlbmVyKTtcbiAgICAgKlxuICAgICAqIC8vIGV4YW1wbGUgc2hhcGVcbiAgICAgKiB7XG4gICAgICogICAgIFwidG9waWNcIjogXCJjaGFubmVsXCIsXG4gICAgICogICAgIFwidHlwZVwiOiBcImNvbm5lY3RlZFwiLFxuICAgICAqICAgICBcInV1aWRcIjogXCJPcGVuZmluUE9DXCIsXG4gICAgICogICAgIFwibmFtZVwiOiBcIk9wZW5maW5QT0NcIixcbiAgICAgKiAgICAgXCJjaGFubmVsTmFtZVwiOiBcImNvdW50ZXJcIixcbiAgICAgKiAgICAgXCJjaGFubmVsSWRcIjogXCJPcGVuZmluUE9DL09wZW5maW5QT0MvY291bnRlclwiXG4gICAgICogfVxuICAgICAqXG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgb25DaGFubmVsQ29ubmVjdChsaXN0ZW5lcikge1xuICAgICAgICBhd2FpdCB0aGlzLm9uKCdjb25uZWN0ZWQnLCBsaXN0ZW5lcik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIExpc3RlbiBmb3IgY2hhbm5lbCBkaXNjb25uZWN0aW9ucy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBsaXN0ZW5lciAtIGNhbGxiYWNrIHRvIGV4ZWN1dGUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBsaXN0ZW5lciA9IChjaGFubmVsUGF5bG9hZCkgPT4gY29uc29sZS5sb2coY2hhbm5lbFBheWxvYWQpOyAvLyBzZWUgcmV0dXJuIHZhbHVlIGJlbG93XG4gICAgICpcbiAgICAgKiBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLm9uQ2hhbm5lbERpc2Nvbm5lY3QobGlzdGVuZXIpO1xuICAgICAqXG4gICAgICogLy8gZXhhbXBsZSBzaGFwZVxuICAgICAqIHtcbiAgICAgKiAgICAgXCJ0b3BpY1wiOiBcImNoYW5uZWxcIixcbiAgICAgKiAgICAgXCJ0eXBlXCI6IFwiZGlzY29ubmVjdGVkXCIsXG4gICAgICogICAgIFwidXVpZFwiOiBcIk9wZW5maW5QT0NcIixcbiAgICAgKiAgICAgXCJuYW1lXCI6IFwiT3BlbmZpblBPQ1wiLFxuICAgICAqICAgICBcImNoYW5uZWxOYW1lXCI6IFwiY291bnRlclwiLFxuICAgICAqICAgICBcImNoYW5uZWxJZFwiOiBcIk9wZW5maW5QT0MvT3BlbmZpblBPQy9jb3VudGVyXCJcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBvbkNoYW5uZWxEaXNjb25uZWN0KGxpc3RlbmVyKSB7XG4gICAgICAgIGF3YWl0IHRoaXMub24oJ2Rpc2Nvbm5lY3RlZCcsIGxpc3RlbmVyKTtcbiAgICB9XG4gICAgYXN5bmMgc2FmZUNvbm5lY3QoY2hhbm5lbE5hbWUsIHNob3VsZFdhaXQsIGNvbm5lY3RQYXlsb2FkKSB7XG4gICAgICAgIGNvbnN0IHJldHJ5SW5mbyA9IHsgY291bnQ6IDAgfTtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tYXdhaXQtaW4tbG9vcCwgbm8tY29uc3RhbnQtY29uZGl0aW9uICovXG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIC8vIHNldHVwIGEgbGlzdGVuZXIgYW5kIGEgY29ubmVjdGVkIHByb21pc2UgdG8gYXdhaXQgaW4gY2FzZSB3ZSBjb25uZWN0IGJlZm9yZSB0aGUgY2hhbm5lbCBpcyByZWFkeVxuICAgICAgICAgICAgbGV0IGNvbm5lY3RlZExpc3RlbmVyID0gKCkgPT4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgY29uc3QgY29ubmVjdGVkUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29ubmVjdGVkTGlzdGVuZXIgPSAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hhbm5lbE5hbWUgPT09IHBheWxvYWQuY2hhbm5lbE5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNih0aGlzLCBfQ2hhbm5lbF9pbnRlcm5hbEVtaXR0ZXIsIFwiZlwiKS5vbignY29ubmVjdGVkJywgY29ubmVjdGVkTGlzdGVuZXIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmIChyZXRyeUluZm8uY291bnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdhaXQgYmVmb3JlIHJldHJ5aW5nXG4gICAgICAgICAgICAgICAgICAgIC8vIERlbGF5IHJldHVybnMgZmFsc2UgY29ubmVjdGVkUHJvbWlzZSByZXR1cm5zIHRydWUgc28gd2UgY2FuIGtub3cgaWYgYSByZXRyeSBpcyBkdWUgdG8gY29ubmVjdGVkIGV2ZW50XG4gICAgICAgICAgICAgICAgICAgIHJldHJ5SW5mby5nb3RDb25uZWN0ZWRFdmVudCA9IGF3YWl0IFByb21pc2UucmFjZShbcmV0cnlEZWxheShyZXRyeUluZm8uY291bnQpLCBjb25uZWN0ZWRQcm9taXNlXSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjb25uZWN0LXRvLWNoYW5uZWwnLCB7IC4uLmNvbm5lY3RQYXlsb2FkLCByZXRyeUluZm8gfSk7XG4gICAgICAgICAgICAgICAgICAgIC8vIGxvZyBvbmx5IGlmIHRoZXJlIHdhcyBhIHJldHJ5XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBTdWNjZXNzZnVsbHkgY29ubmVjdGVkIHRvIGNoYW5uZWxOYW1lOiAke2NoYW5uZWxOYW1lfWApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0LnBheWxvYWQuZGF0YTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gU2VuZCByZXRyeUluZm8gdG8gdGhlIGNvcmUgZm9yIGRlYnVnIGxvZyBpbmNsdXNpb25cbiAgICAgICAgICAgICAgICBjb25zdCBzZW50TWVzc2FnZVByb21pc2UgPSB0aGlzLndpcmUuc2VuZEFjdGlvbignY29ubmVjdC10by1jaGFubmVsJywgY29ubmVjdFBheWxvYWQpO1xuICAgICAgICAgICAgICAgIC8vIFNhdmUgbWVzc2FnZUlkIGZyb20gdGhlIGZpcnN0IGNvbm5lY3Rpb24gYXR0ZW1wdFxuICAgICAgICAgICAgICAgIHJldHJ5SW5mby5vcmlnaW5hbE1lc3NhZ2VJZCA9IHNlbnRNZXNzYWdlUHJvbWlzZS5tZXNzYWdlSWQ7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2VudE1lc3NhZ2VQcm9taXNlO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQucGF5bG9hZC5kYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFlcnJvci5tZXNzYWdlLmluY2x1ZGVzKCdpbnRlcm5hbC1uYWNrJykpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTm90IGFuIGludGVybmFsIG5hY2ssIGJyZWFrIHRoZSBsb29wXG4gICAgICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoc2hvdWxkV2FpdCAmJiByZXRyeUluZm8uY291bnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gc3RhcnQgd2FpdGluZyBvbiB0aGUgbmV4dCBpdGVyYXRpb24sIHdhcm4gdGhlIHVzZXJcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBObyBjaGFubmVsIGZvdW5kIGZvciBjaGFubmVsTmFtZTogJHtjaGFubmVsTmFtZX0uIFdhaXRpbmcgZm9yIGNvbm5lY3Rpb24uLi5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICByZXRyeUluZm8uY291bnQgKz0gMTtcbiAgICAgICAgICAgICAgICAvLyBpbiBjYXNlIG9mIG90aGVyIGVycm9ycywgcmVtb3ZlIG91ciBsaXN0ZW5lclxuICAgICAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNih0aGlzLCBfQ2hhbm5lbF9pbnRlcm5hbEVtaXR0ZXIsIFwiZlwiKS5yZW1vdmVMaXN0ZW5lcignY29ubmVjdGVkJywgY29ubmVjdGVkTGlzdGVuZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IHdoaWxlIChzaG91bGRXYWl0KTsgLy8gSWYgd2UncmUgd2FpdGluZyB3ZSByZXRyeSB0aGUgYWJvdmUgbG9vcFxuICAgICAgICAvLyBTaG91bGQgd2FpdCB3YXMgZmFsc2UsIG5vIGNoYW5uZWwgd2FzIGZvdW5kLlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGNoYW5uZWwgZm91bmQgZm9yIGNoYW5uZWxOYW1lOiAke2NoYW5uZWxOYW1lfS5gKTtcbiAgICAgICAgLyogZXNsaW50LWVuYWJsZSBuby1hd2FpdC1pbi1sb29wLCBuby1jb25zdGFudC1jb25kaXRpb24gKi9cbiAgICB9XG4gICAgLyoqXG4gICAgICogQ29ubmVjdCB0byBhIGNoYW5uZWwuIElmIHlvdSB3aXNoIHRvIHNlbmQgYSBwYXlsb2FkIHRvIHRoZSBwcm92aWRlciwgYWRkIGEgcGF5bG9hZCBwcm9wZXJ0eSB0byB0aGUgb3B0aW9ucyBhcmd1bWVudC5cbiAgICAgKiBFWFBFUklNRU5UQUw6IHBhc3MgeyBwcm90b2NvbHM6IFsncnRjJ10gfSBhcyBvcHRpb25zIHRvIG9wdC1pbiB0byBIaWdoIFRocm91Z2hwdXQgQ2hhbm5lbHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gY2hhbm5lbE5hbWUgLSBOYW1lIG9mIHRoZSB0YXJnZXQgY2hhbm5lbC5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIENvbm5lY3Rpb24gb3B0aW9ucy5cbiAgICAgKiBAcmV0dXJucyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggYW4gaW5zdGFuY2Ugb2Yge0BsaW5rIENoYW5uZWxDbGllbnQgQ2hhbm5lbENsaWVudH0uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBUaGUgY29ubmVjdGlvbiByZXF1ZXN0IHdpbGwgYmUgcm91dGVkIHRvIHRoZSBjaGFubmVsUHJvdmlkZXIgaWYvd2hlbiB0aGUgY2hhbm5lbCBpcyBjcmVhdGVkLiAgSWYgdGhlIGNvbm5lY3RcbiAgICAgKiByZXF1ZXN0IGlzIHNlbnQgcHJpb3IgdG8gY3JlYXRpb24sIHRoZSBwcm9taXNlIHdpbGwgbm90IHJlc29sdmUgb3IgcmVqZWN0IHVudGlsIHRoZSBjaGFubmVsIGlzIGNyZWF0ZWQgYnkgYSBjaGFubmVsUHJvdmlkZXJcbiAgICAgKiAod2hldGhlciBvciBub3QgdG8gd2FpdCBmb3IgY3JlYXRpb24gaXMgY29uZmlndXJhYmxlIGluIHRoZSBjb25uZWN0T3B0aW9ucykuXG4gICAgICpcbiAgICAgKiBUaGUgY29ubmVjdCBjYWxsIHJldHVybnMgYSBwcm9taXNlIHRoYXQgd2lsbCByZXNvbHZlIHdpdGggYSBjaGFubmVsQ2xpZW50IGJ1cyBpZiBhY2NlcHRlZCBieSB0aGUgY2hhbm5lbFByb3ZpZGVyLCBvciByZWplY3QgaWZcbiAgICAgKiB0aGUgY2hhbm5lbFByb3ZpZGVyIHRocm93cyBhbiBlcnJvciB0byByZWplY3QgdGhlIGNvbm5lY3Rpb24uIFRoaXMgYnVzIGNhbiBjb21tdW5pY2F0ZSB3aXRoIHRoZSBQcm92aWRlciwgYnV0IG5vdCB0byBvdGhlclxuICAgICAqIGNsaWVudHMgb24gdGhlIGNoYW5uZWwuIFVzaW5nIHRoZSBidXMsIHRoZSBjaGFubmVsQ2xpZW50IGNhbiByZWdpc3RlciBhY3Rpb25zIGFuZCBtaWRkbGV3YXJlLiBDaGFubmVsIGxpZmVjeWNsZSBjYW4gYWxzbyBiZVxuICAgICAqIGhhbmRsZWQgd2l0aCBhbiBvbkRpc2Nvbm5lY3Rpb24gbGlzdGVuZXIuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBtYWtlQ2xpZW50KGNoYW5uZWxOYW1lKSB7XG4gICAgICogICAgLy8gQSBwYXlsb2FkIGNhbiBiZSBzZW50IGFsb25nIHdpdGggY2hhbm5lbCBjb25uZWN0aW9uIHJlcXVlc3RzIHRvIGhlbHAgd2l0aCBhdXRoZW50aWNhdGlvblxuICAgICAqICAgIGNvbnN0IGNvbm5lY3RQYXlsb2FkID0geyBwYXlsb2FkOiAndG9rZW4nIH07XG4gICAgICpcbiAgICAgKiAgICAvLyBJZiB0aGUgY2hhbm5lbCBoYXMgYmVlbiBjcmVhdGVkIHRoaXMgcmVxdWVzdCB3aWxsIGJlIHNlbnQgdG8gdGhlIHByb3ZpZGVyLiAgSWYgbm90LCB0aGVcbiAgICAgKiAgICAvLyBwcm9taXNlIHdpbGwgbm90IGJlIHJlc29sdmVkIG9yIHJlamVjdGVkIHVudGlsIHRoZSBjaGFubmVsIGhhcyBiZWVuIGNyZWF0ZWQuXG4gICAgICogICAgY29uc3QgY2xpZW50QnVzID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KGNoYW5uZWxOYW1lLCBjb25uZWN0UGF5bG9hZCk7XG4gICAgICpcbiAgICAgKiAgICBjbGllbnRCdXMub25EaXNjb25uZWN0aW9uKGNoYW5uZWxJbmZvID0+IHtcbiAgICAgKiAgICAgICAgLy8gaGFuZGxlIHRoZSBjaGFubmVsIGxpZmVjeWNsZSBoZXJlIC0gd2UgY2FuIGNvbm5lY3QgYWdhaW4gd2hpY2ggd2lsbCByZXR1cm4gYSBwcm9taXNlXG4gICAgICogICAgICAgIC8vIHRoYXQgd2lsbCByZXNvbHZlIGlmL3doZW4gdGhlIGNoYW5uZWwgaXMgcmUtY3JlYXRlZC5cbiAgICAgKiAgICAgICAgbWFrZUNsaWVudChjaGFubmVsSW5mby5jaGFubmVsTmFtZSk7XG4gICAgICogICAgfSlcbiAgICAgKlxuICAgICAqICAgIGNsaWVudEJ1cy5yZWdpc3RlcigndG9waWMnLCAocGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgLy8gcmVnaXN0ZXIgYSBjYWxsYmFjayBmb3IgYSB0b3BpYyB0byB3aGljaCB0aGUgY2hhbm5lbCBwcm92aWRlciBjYW4gZGlzcGF0Y2ggYW4gYWN0aW9uXG4gICAgICogICAgICAgIGNvbnNvbGUubG9nKCdBY3Rpb24gZGlzcGF0Y2hlZCBieSBwcm92aWRlcjogJywgSlNPTi5zdHJpbmdpZnkoaWRlbnRpdHkpKTtcbiAgICAgKiAgICAgICAgY29uc29sZS5sb2coJ1BheWxvYWQgc2VudCBpbiBkaXNwYXRjaDogJywgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xuICAgICAqICAgICAgICByZXR1cm4ge1xuICAgICAqICAgICAgICAgICAgZWNobzogcGF5bG9hZFxuICAgICAqICAgICAgICB9O1xuICAgICAqICAgIH0pO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIG1ha2VDbGllbnQoJ2NoYW5uZWxOYW1lJylcbiAgICAgKiAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQ29ubmVjdGVkJykpXG4gICAgICogLmNhdGNoKGNvbnNvbGUuZXJyb3IpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGNvbm5lY3QoY2hhbm5lbE5hbWUsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICAvLyBNYWtlIHN1cmUgd2UgZG9uJ3QgY29ubmVjdCBiZWZvcmUgbGlzdGVuZXJzIGFyZSBzZXQgdXBcbiAgICAgICAgLy8gVGhpcyBhbHNvIGVycm9ycyBpZiB3ZSdyZSBub3QgaW4gT3BlbkZpbiwgZW5zdXJpbmcgd2UgZG9uJ3QgcnVuIHVubmVjZXNzYXJ5IGNvZGVcbiAgICAgICAgYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ2KHRoaXMsIF9DaGFubmVsX3JlYWR5VG9Db25uZWN0LCBcImZcIikuZ2V0VmFsdWUoKTtcbiAgICAgICAgaWYgKCFjaGFubmVsTmFtZSB8fCB0eXBlb2YgY2hhbm5lbE5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BsZWFzZSBwcm92aWRlIGEgY2hhbm5lbE5hbWUgc3RyaW5nIHRvIGNvbm5lY3QgdG8gYSBjaGFubmVsLicpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG9wdHMgPSB7IHdhaXQ6IHRydWUsIC4uLnRoaXMud2lyZS5lbnZpcm9ubWVudC5nZXREZWZhdWx0Q2hhbm5lbE9wdGlvbnMoKS5jb25uZWN0LCAuLi5vcHRpb25zIH07XG4gICAgICAgIGNvbnN0IHsgb2ZmZXIsIHJ0YzogcnRjUGFja2V0IH0gPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDYodGhpcywgX0NoYW5uZWxfY29ubmVjdGlvbk1hbmFnZXIsIFwiZlwiKS5jcmVhdGVDbGllbnRPZmZlcihvcHRzKTtcbiAgICAgICAgbGV0IGNvbm5lY3Rpb25Vcmw7XG4gICAgICAgIGlmICh0aGlzLmZpbi5tZS5pc0ZyYW1lIHx8IHRoaXMuZmluLm1lLmlzVmlldyB8fCB0aGlzLmZpbi5tZS5pc1dpbmRvdykge1xuICAgICAgICAgICAgY29ubmVjdGlvblVybCA9IChhd2FpdCB0aGlzLmZpbi5tZS5nZXRJbmZvKCkpLnVybDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb25uZWN0UGF5bG9hZCA9IHtcbiAgICAgICAgICAgIGNoYW5uZWxOYW1lLFxuICAgICAgICAgICAgLi4ub3B0cyxcbiAgICAgICAgICAgIG9mZmVyLFxuICAgICAgICAgICAgY29ubmVjdGlvblVybFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCByb3V0aW5nSW5mbyA9IGF3YWl0IHRoaXMuc2FmZUNvbm5lY3QoY2hhbm5lbE5hbWUsIG9wdHMud2FpdCwgY29ubmVjdFBheWxvYWQpO1xuICAgICAgICBjb25zdCBzdHJhdGVneSA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNih0aGlzLCBfQ2hhbm5lbF9jb25uZWN0aW9uTWFuYWdlciwgXCJmXCIpLmNyZWF0ZUNsaWVudFN0cmF0ZWd5KHJ0Y1BhY2tldCwgcm91dGluZ0luZm8pO1xuICAgICAgICBjb25zdCBjaGFubmVsID0gbmV3IGNsaWVudF8xLkNoYW5uZWxDbGllbnQocm91dGluZ0luZm8sICgpID0+IGNsaWVudF8xLkNoYW5uZWxDbGllbnQud2lyZUNsb3NlKHRoaXMud2lyZSwgcm91dGluZ0luZm8sIHJvdXRpbmdJbmZvLmVuZHBvaW50SWQpLCBzdHJhdGVneSk7XG4gICAgICAgIC8vIEl0IGlzIHRoZSBjbGllbnQncyByZXNwb25zaWJpbGl0eSB0byBoYW5kbGUgZW5kcG9pbnQgZGlzY29ubmVjdGlvbiB0byB0aGUgcHJvdmlkZXIuXG4gICAgICAgIC8vIElmIHRoZSBlbmRwb2ludCBkaWVzLCB0aGUgY2xpZW50IHdpbGwgZm9yY2UgYSBkaXNjb25uZWN0aW9uIHRocm91Z2ggdGhlIGNvcmUuXG4gICAgICAgIC8vIFRoZSBwcm92aWRlciBkb2VzIG5vdCBjYXJlIGFib3V0IGVuZHBvaW50IGRpc2Nvbm5lY3Rpb24uXG4gICAgICAgIHN0cmF0ZWd5Lm9uRW5kcG9pbnREaXNjb25uZWN0KHJvdXRpbmdJbmZvLmNoYW5uZWxJZCwgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBjaGFubmVsLnNlbmREaXNjb25uZWN0QWN0aW9uKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFNvbWV0aGluZyB3ZW50IHdyb25nIGR1cmluZyBkaXNjb25uZWN0IGZvciBjbGllbnQgd2l0aCB1dWlkOiAke3JvdXRpbmdJbmZvLnV1aWR9IC8gbmFtZTogJHtyb3V0aW5nSW5mby5uYW1lfSAvIGVuZHBvaW50SWQ6ICR7cm91dGluZ0luZm8uZW5kcG9pbnRJZH0uYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICBjbGllbnRfMS5DaGFubmVsQ2xpZW50LmhhbmRsZVByb3ZpZGVyRGlzY29ubmVjdChyb3V0aW5nSW5mbyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY2hhbm5lbDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgbmV3IGNoYW5uZWwuXG4gICAgICogWW91IG11c3QgcHJvdmlkZSBhIHVuaXF1ZSBjaGFubmVsTmFtZS4gSWYgYSBjaGFubmVsTmFtZSBpcyBub3QgcHJvdmlkZWQsIG9yIGl0IGlzIG5vdCB1bmlxdWUsIHRoZSBjcmVhdGlvbiB3aWxsIGZhaWwuXG4gICAgICogRVhQRVJJTUVOVEFMOiBwYXNzIHsgcHJvdG9jb2xzOiBbJ3J0YyddIH0gYXMgb3B0aW9ucyB0byBvcHQtaW4gdG8gSGlnaCBUaHJvdWdocHV0IENoYW5uZWxzLlxuICAgICAqXG4gICAgICogQHBhcmFtIGNoYW5uZWxOYW1lIC0gTmFtZSBvZiB0aGUgY2hhbm5lbCB0byBiZSBjcmVhdGVkLlxuICAgICAqIEBwYXJhbSBvcHRpb25zIC0gQ3JlYXRpb24gb3B0aW9ucy5cbiAgICAgKiBAcmV0dXJucyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggYW4gaW5zdGFuY2Ugb2Yge0BsaW5rIENoYW5uZWxQcm92aWRlciBDaGFubmVsUHJvdmlkZXJ9LlxuICAgICAqXG4gICAgICogQHJlbWFya3MgSWYgc3VjY2Vzc2Z1bCwgdGhlIGNyZWF0ZSBtZXRob2QgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBpbnN0YW5jZSBvZiB0aGUgY2hhbm5lbFByb3ZpZGVyIGJ1cy4gVGhlIGNhbGxlclxuICAgICAqIHRoZW4gYmVjb21lcyB0aGUg4oCcY2hhbm5lbCBwcm92aWRlcuKAnSBhbmQgY2FuIHVzZSB0aGUgY2hhbm5lbFByb3ZpZGVyIGJ1cyB0byByZWdpc3RlciBhY3Rpb25zIGFuZCBtaWRkbGV3YXJlLlxuICAgICAqXG4gICAgICogVGhlIGNhbGxlciBjYW4gYWxzbyBzZXQgYW4gb25Db25uZWN0aW9uIGFuZC9vciBvbkRpc2Nvbm5lY3Rpb24gbGlzdGVuZXIgdGhhdCB3aWxsIGV4ZWN1dGUgb24gYW55IG5ldyBjaGFubmVsXG4gICAgICogY29ubmVjdGlvbi9kaXNjb25uZWN0aW9uIGF0dGVtcHQgZnJvbSBhIGNoYW5uZWwgY2xpZW50LiBUbyByZWplY3QgYSBjb25uZWN0aW9uLCBzaW1wbHkgdGhyb3cgYW4gZXJyb3IgaW4gdGhlXG4gICAgICogb25Db25uZWN0aW9uIGxpc3RlbmVyLiAgVGhlIGRlZmF1bHQgYmVoYXZpb3IgaXMgdG8gYWNjZXB0IGFsbCBuZXcgY29ubmVjdGlvbnMuXG4gICAgICpcbiAgICAgKiBBIG1hcCBvZiBjbGllbnQgY29ubmVjdGlvbnMgaXMgdXBkYXRlZCBhdXRvbWF0aWNhbGx5IG9uIGNsaWVudCBjb25uZWN0aW9uIGFuZCBkaXNjb25uZWN0aW9uIGFuZCBzYXZlZCBpbiB0aGVcbiAgICAgKiBbcmVhZC1vbmx5XSBgY29ubmVjdGlvbnNgIHByb3BlcnR5IG9uIHRoZSBjaGFubmVsUHJvdmlkZXIgYnVzLiAgVGhlIGNoYW5uZWwgd2lsbCBleGlzdCB1bnRpbCB0aGUgcHJvdmlkZXJcbiAgICAgKiBkZXN0cm95cyBpdCBvciBkaXNjb25uZWN0cyBieSBjbG9zaW5nIG9yIGRlc3Ryb3lpbmcgdGhlIGNvbnRleHQgKG5hdmlnYXRpbmcgb3IgcmVsb2FkaW5nKS4gVG8gc2V0dXAgYSBjaGFubmVsXG4gICAgICogYXMgYSBjaGFubmVsUHJvdmlkZXIsIGNhbGwgYENoYW5uZWwuY3JlYXRlYCB3aXRoIGEgdW5pcXVlIGNoYW5uZWwgbmFtZS4gQSBtYXAgb2YgY2xpZW50IGNvbm5lY3Rpb25zIGlzIHVwZGF0ZWRcbiAgICAgKiBhdXRvbWF0aWNhbGx5IG9uIGNsaWVudCBjb25uZWN0aW9uIGFuZCBkaXNjb25uZWN0aW9uLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgIC8vIGVudGl0eSBjcmVhdGVzIGEgY2hhbm5lbCBhbmQgYmVjb21lcyB0aGUgY2hhbm5lbFByb3ZpZGVyXG4gICAgICogICAgY29uc3QgcHJvdmlkZXJCdXMgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZSgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgIHByb3ZpZGVyQnVzLm9uQ29ubmVjdGlvbigoaWRlbnRpdHksIHBheWxvYWQpID0+IHtcbiAgICAgKiAgICAgICAgLy8gY2FuIHJlamVjdCBhIGNvbm5lY3Rpb24gaGVyZSBieSB0aHJvd2luZyBhbiBlcnJvclxuICAgICAqICAgICAgICBjb25zb2xlLmxvZygnQ2xpZW50IGNvbm5lY3Rpb24gcmVxdWVzdCBpZGVudGl0eTogJywgSlNPTi5zdHJpbmdpZnkoaWRlbnRpdHkpKTtcbiAgICAgKiAgICAgICAgY29uc29sZS5sb2coJ0NsaWVudCBjb25uZWN0aW9uIHJlcXVlc3QgcGF5bG9hZDogJywgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xuICAgICAqICAgIH0pO1xuICAgICAqXG4gICAgICogICAgcHJvdmlkZXJCdXMucmVnaXN0ZXIoJ3RvcGljJywgKHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgIC8vIHJlZ2lzdGVyIGEgY2FsbGJhY2sgZm9yIGEgJ3RvcGljJyB0byB3aGljaCBjbGllbnRzIGNhbiBkaXNwYXRjaCBhbiBhY3Rpb25cbiAgICAgKiAgICAgICAgY29uc29sZS5sb2coJ0FjdGlvbiBkaXNwYXRjaGVkIGJ5IGNsaWVudDogJywgSlNPTi5zdHJpbmdpZnkoaWRlbnRpdHkpKTtcbiAgICAgKiAgICAgICAgY29uc29sZS5sb2coJ1BheWxvYWQgc2VudCBpbiBkaXNwYXRjaDogJywgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xuICAgICAqICAgICAgICByZXR1cm4ge1xuICAgICAqICAgICAgICAgICAgZWNobzogcGF5bG9hZFxuICAgICAqICAgICAgICB9O1xuICAgICAqICAgIH0pO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgY3JlYXRlKGNoYW5uZWxOYW1lLCBvcHRpb25zKSB7XG4gICAgICAgIGlmICghY2hhbm5lbE5hbWUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGxlYXNlIHByb3ZpZGUgYSBjaGFubmVsTmFtZSB0byBjcmVhdGUgYSBjaGFubmVsJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyBwYXlsb2FkOiB7IGRhdGE6IHByb3ZpZGVySWRlbnRpdHkgfSB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NyZWF0ZS1jaGFubmVsJywgeyBjaGFubmVsTmFtZSB9KTtcbiAgICAgICAgY29uc3QgY2hhbm5lbCA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNih0aGlzLCBfQ2hhbm5lbF9jb25uZWN0aW9uTWFuYWdlciwgXCJmXCIpLmNyZWF0ZVByb3ZpZGVyKG9wdGlvbnMsIHByb3ZpZGVySWRlbnRpdHkpO1xuICAgICAgICAvLyBUT0RPOiBmaXggdHlwaW5nIChpbnRlcm5hbClcbiAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICB0aGlzLm9uKCdjbGllbnQtZGlzY29ubmVjdGVkJywgKGV2ZW50UGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgaWYgKGV2ZW50UGF5bG9hZC5jaGFubmVsTmFtZSA9PT0gY2hhbm5lbE5hbWUpIHtcbiAgICAgICAgICAgICAgICBwcm92aWRlcl8xLkNoYW5uZWxQcm92aWRlci5oYW5kbGVDbGllbnREaXNjb25uZWN0aW9uKGNoYW5uZWwsIGV2ZW50UGF5bG9hZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gY2hhbm5lbDtcbiAgICB9XG59XG5jaGFubmVsJDEuQ2hhbm5lbCA9IENoYW5uZWw7XG5fQ2hhbm5lbF9jb25uZWN0aW9uTWFuYWdlciA9IG5ldyBXZWFrTWFwKCksIF9DaGFubmVsX2ludGVybmFsRW1pdHRlciA9IG5ldyBXZWFrTWFwKCksIF9DaGFubmVsX3JlYWR5VG9Db25uZWN0ID0gbmV3IFdlYWtNYXAoKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGludGVyYXBwYnVzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmludGVyYXBwYnVzLkludGVyQXBwUGF5bG9hZCA9IGludGVyYXBwYnVzLkludGVyQXBwbGljYXRpb25CdXMgPSB2b2lkIDA7XG4vKipcbiAqIEVudHJ5IHBvaW50IGZvciB0aGUgT3BlbkZpbiBgSW50ZXJBcHBsaWNhdGlvbkJ1c2AgQVBJIChgZmluLkludGVyQXBwbGljYXRpb25CdXNgKS5cbiAqXG4gKiAqIHtAbGluayBJbnRlckFwcGxpY2F0aW9uQnVzfSBjb250YWlucyBzdGF0aWMgbWVtYmVycyBvZiB0aGUgYEludGVyQXBwbGljYXRpb25CdXNgIEFQSSwgYWNjZXNzaWJsZSB0aHJvdWdoIGBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1c2AuXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cbmNvbnN0IGV2ZW50c18xJDQgPSByZXF1aXJlJCQwO1xuY29uc3QgYmFzZV8xJGQgPSBiYXNlO1xuY29uc3QgcmVmX2NvdW50ZXJfMSA9IHJlZkNvdW50ZXI7XG5jb25zdCBpbmRleF8xJDIgPSBjaGFubmVsJDE7XG5jb25zdCB2YWxpZGF0ZV8xJDMgPSB2YWxpZGF0ZTtcbi8qKlxuICogQSBtZXNzYWdpbmcgYnVzIHRoYXQgYWxsb3dzIGZvciBwdWIvc3ViIG1lc3NhZ2luZyBiZXR3ZWVuIGRpZmZlcmVudCBhcHBsaWNhdGlvbnMuXG4gKlxuICovXG5jbGFzcyBJbnRlckFwcGxpY2F0aW9uQnVzIGV4dGVuZHMgYmFzZV8xJGQuQmFzZSB7XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iod2lyZSkge1xuICAgICAgICBzdXBlcih3aXJlKTtcbiAgICAgICAgdGhpcy5ldmVudHMgPSB7XG4gICAgICAgICAgICBzdWJzY3JpYmVyQWRkZWQ6ICdzdWJzY3JpYmVyLWFkZGVkJyxcbiAgICAgICAgICAgIHN1YnNjcmliZXJSZW1vdmVkOiAnc3Vic2NyaWJlci1yZW1vdmVkJ1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnJlZkNvdW50ZXIgPSBuZXcgcmVmX2NvdW50ZXJfMS5SZWZDb3VudGVyKCk7XG4gICAgICAgIHRoaXMuQ2hhbm5lbCA9IG5ldyBpbmRleF8xJDIuQ2hhbm5lbCh3aXJlKTtcbiAgICAgICAgdGhpcy5lbWl0dGVyID0gbmV3IGV2ZW50c18xJDQuRXZlbnRFbWl0dGVyKCk7XG4gICAgICAgIHdpcmUucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcih0aGlzLm9ubWVzc2FnZS5iaW5kKHRoaXMpKTtcbiAgICAgICAgdGhpcy5vbiA9IHRoaXMuZW1pdHRlci5vbi5iaW5kKHRoaXMuZW1pdHRlcik7XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzID0gdGhpcy5lbWl0dGVyLnJlbW92ZUFsbExpc3RlbmVycy5iaW5kKHRoaXMuZW1pdHRlcik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFB1Ymxpc2hlcyBhIG1lc3NhZ2UgdG8gYWxsIGFwcGxpY2F0aW9ucyBydW5uaW5nIG9uIE9wZW5GaW4gUnVudGltZSB0aGF0XG4gICAgICogYXJlIHN1YnNjcmliZWQgdG8gdGhlIHNwZWNpZmllZCB0b3BpYy5cbiAgICAgKiBAcGFyYW0gdG9waWMgVGhlIHRvcGljIG9uIHdoaWNoIHRoZSBtZXNzYWdlIGlzIHNlbnRcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSBUaGUgbWVzc2FnZSB0byBiZSBwdWJsaXNoZWQuIENhbiBiZSBlaXRoZXIgYSBwcmltaXRpdmVcbiAgICAgKiBkYXRhIHR5cGUgKHN0cmluZywgbnVtYmVyLCBvciBib29sZWFuKSBvciBjb21wb3NpdGUgZGF0YSB0eXBlIChvYmplY3QsIGFycmF5KVxuICAgICAqIHRoYXQgaXMgY29tcG9zZWQgb2Ygb3RoZXIgcHJpbWl0aXZlIG9yIGNvbXBvc2l0ZSBkYXRhIHR5cGVzXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkludGVyQXBwbGljYXRpb25CdXMucHVibGlzaCgndG9waWMnLCAnaGVsbG8nKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdQdWJsaXNoZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHB1Ymxpc2godG9waWMsIG1lc3NhZ2UpIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3B1Ymxpc2gtbWVzc2FnZScsIHtcbiAgICAgICAgICAgIHRvcGljLFxuICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgIHNvdXJjZVdpbmRvd05hbWU6IHRoaXMubWUubmFtZVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2VuZHMgYSBtZXNzYWdlIHRvIGEgc3BlY2lmaWMgYXBwbGljYXRpb24gb24gYSBzcGVjaWZpYyB0b3BpYy5cbiAgICAgKiBAcGFyYW0gZGVzdGluYXRpb24gVGhlIGlkZW50aXR5IG9mIHRoZSBhcHBsaWNhdGlvbiB0byB3aGljaCB0aGUgbWVzc2FnZSBpcyBzZW50XG4gICAgICogQHBhcmFtIHRvcGljIFRoZSB0b3BpYyBvbiB3aGljaCB0aGUgbWVzc2FnZSBpcyBzZW50XG4gICAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gYmUgc2VudC4gQ2FuIGJlIGVpdGhlciBhIHByaW1pdGl2ZSBkYXRhXG4gICAgICogdHlwZSAoc3RyaW5nLCBudW1iZXIsIG9yIGJvb2xlYW4pIG9yIGNvbXBvc2l0ZSBkYXRhIHR5cGUgKG9iamVjdCwgYXJyYXkpIHRoYXRcbiAgICAgKiBpcyBjb21wb3NlZCBvZiBvdGhlciBwcmltaXRpdmUgb3IgY29tcG9zaXRlIGRhdGEgdHlwZXNcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5zZW5kKGZpbi5tZSwgJ3RvcGljJywgJ0hlbGxvIHRoZXJlIScpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ01lc3NhZ2Ugc2VudCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgc2VuZChkZXN0aW5hdGlvbiwgdG9waWMsIG1lc3NhZ2UpIHtcbiAgICAgICAgY29uc3QgZXJyb3JNc2cgPSAoMCwgdmFsaWRhdGVfMSQzLnZhbGlkYXRlSWRlbnRpdHkpKGRlc3RpbmF0aW9uKTtcbiAgICAgICAgaWYgKGVycm9yTXNnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNc2cpO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzZW5kLW1lc3NhZ2UnLCB7XG4gICAgICAgICAgICBkZXN0aW5hdGlvblV1aWQ6IGRlc3RpbmF0aW9uLnV1aWQsXG4gICAgICAgICAgICBkZXN0aW5hdGlvbldpbmRvd05hbWU6IGRlc3RpbmF0aW9uLm5hbWUsXG4gICAgICAgICAgICB0b3BpYyxcbiAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICBzb3VyY2VXaW5kb3dOYW1lOiB0aGlzLm1lLm5hbWVcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN1YnNjcmliZXMgdG8gbWVzc2FnZXMgZnJvbSB0aGUgc3BlY2lmaWVkIGFwcGxpY2F0aW9uIG9uIHRoZSBzcGVjaWZpZWQgdG9waWMuXG4gICAgICogQHBhcmFtIHNvdXJjZSBUaGlzIG9iamVjdCBpcyBkZXNjcmliZWQgaW4gdGhlIElkZW50aXR5IGluIHRoZSB0eXBlZGVmXG4gICAgICogQHBhcmFtIHRvcGljIFRoZSB0b3BpYyBvbiB3aGljaCB0aGUgbWVzc2FnZSBpcyBzZW50XG4gICAgICogQHBhcmFtIGxpc3RlbmVyIEEgZnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiBhIG1lc3NhZ2UgaGFzXG4gICAgICogYmVlbiByZWNlaXZlZC4gSXQgaXMgcGFzc2VkIHRoZSBtZXNzYWdlLCB1dWlkIGFuZCBuYW1lIG9mIHRoZSBzZW5kaW5nIGFwcGxpY2F0aW9uLlxuICAgICAqIFRoZSBtZXNzYWdlIGNhbiBiZSBlaXRoZXIgYSBwcmltaXRpdmUgZGF0YSB0eXBlIChzdHJpbmcsIG51bWJlciwgb3IgYm9vbGVhbikgb3JcbiAgICAgKiBjb21wb3NpdGUgZGF0YSB0eXBlIChvYmplY3QsIGFycmF5KSB0aGF0IGlzIGNvbXBvc2VkIG9mIG90aGVyIHByaW1pdGl2ZSBvciBjb21wb3NpdGVcbiAgICAgKiBkYXRhIHR5cGVzXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogLy8gc3Vic2NyaWJlIHRvIGEgc3BlY2lmaWVkIGFwcGxpY2F0aW9uXG4gICAgICogZmluLkludGVyQXBwbGljYXRpb25CdXMuc3Vic2NyaWJlKGZpbi5tZSwgJ3RvcGljJywgc3ViX21zZyA9PiBjb25zb2xlLmxvZyhzdWJfbXNnKSkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU3Vic2NyaWJlZCB0byB0aGUgc3BlY2lmaWVkIGFwcGxpY2F0aW9uJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKlxuICAgICAqIC8vIHN1YnNjcmliZSB0byB3aWxkY2FyZFxuICAgICAqIGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLnN1YnNjcmliZSh7IHV1aWQ6ICcqJyB9LCAndG9waWMnLCBzdWJfbXNnID0+IGNvbnNvbGUubG9nKHN1Yl9tc2cpKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTdWJzY3JpYmVkIHRvIConKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHN1YnNjcmliZShzb3VyY2UsIHRvcGljLCBsaXN0ZW5lcikge1xuICAgICAgICBjb25zdCBzdWJLZXkgPSB0aGlzLmNyZWF0ZVN1YnNjcmlwdGlvbktleShzb3VyY2UudXVpZCwgc291cmNlLm5hbWUgfHwgJyonLCB0b3BpYyk7XG4gICAgICAgIGNvbnN0IHNlbmRTdWJzY3JpcHRpb24gPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc3Vic2NyaWJlJywge1xuICAgICAgICAgICAgICAgIHNvdXJjZVV1aWQ6IHNvdXJjZS51dWlkLFxuICAgICAgICAgICAgICAgIHNvdXJjZVdpbmRvd05hbWU6IHNvdXJjZS5uYW1lIHx8ICcqJyxcbiAgICAgICAgICAgICAgICB0b3BpYyxcbiAgICAgICAgICAgICAgICBkZXN0aW5hdGlvbldpbmRvd05hbWU6IHRoaXMubWUubmFtZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGFscmVhZHlTdWJzY3JpYmVkID0gKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmVtaXR0ZXIub24oc3ViS2V5LCBsaXN0ZW5lcik7XG4gICAgICAgIHJldHVybiB0aGlzLnJlZkNvdW50ZXIuYWN0T25GaXJzdChzdWJLZXksIHNlbmRTdWJzY3JpcHRpb24sIGFscmVhZHlTdWJzY3JpYmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVW5zdWJzY3JpYmVzIHRvIG1lc3NhZ2VzIGZyb20gdGhlIHNwZWNpZmllZCBhcHBsaWNhdGlvbiBvbiB0aGUgc3BlY2lmaWVkIHRvcGljLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgSWYgeW91IGFyZSBsaXN0ZW5pbmcgdG8gYWxsIGFwcHMgb24gYSB0b3BpYywgKGkuZSB5b3UgcGFzc2VkIGB7IHV1aWQ6JyonIH1gIHRvIHRoZSBzdWJzY3JpYmUgZnVuY3Rpb24pXG4gICAgICogdGhlbiB5b3UgbmVlZCB0byBwYXNzIGB7IHV1aWQ6JyonIH1gIHRvIHVuc3Vic2NyaWJlIGFzIHdlbGwuIElmIHlvdSBhcmUgbGlzdGVuaW5nIHRvIGEgc3BlY2lmaWMgYXBwbGljYXRpb24sXG4gICAgICogKGkuZSB5b3UgcGFzc2VkIGB7IHV1aWQ6J3NvbWVfYXBwJyB9YCB0byB0aGUgc3Vic2NyaWJlIGZ1bmN0aW9uKSB0aGVuIHlvdSBuZWVkIHRvIHByb3ZpZGUgdGhlIHNhbWUgaWRlbnRpZmllciB0b1xuICAgICAqIHVuc3Vic2NyaWJlLCB1bnN1YnNjcmliaW5nIHRvIGAqYCBvbiB0aGF0IHNhbWUgdG9waWMgd2lsbCBub3QgdW5ob29rIHlvdXIgaW5pdGlhbCBsaXN0ZW5lciBvdGhlcndpc2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc291cmNlIFRoaXMgb2JqZWN0IGlzIGRlc2NyaWJlZCBpbiB0aGUgSWRlbnRpdHkgaW4gdGhlIHR5cGVkZWZcbiAgICAgKiBAcGFyYW0gdG9waWMgVGhlIHRvcGljIG9uIHdoaWNoIHRoZSBtZXNzYWdlIGlzIHNlbnRcbiAgICAgKiBAcGFyYW0gbGlzdGVuZXIgQSBjYWxsYmFjayBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgd2l0aCBzdWJzY3JpYmUoKVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IGxpc3RlbmVyID0gY29uc29sZS5sb2c7XG4gICAgICpcbiAgICAgKiAvLyBJZiBhbnkgYXBwbGljYXRpb24gcHVibGlzaGVzIGEgbWVzc2FnZSBvbiB0b3BpYyBgZm9vYCwgb3VyIGxpc3RlbmVyIHdpbGwgYmUgY2FsbGVkLlxuICAgICAqIGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLnN1YnNjcmliZSh7IHV1aWQ6JyonIH0sICdmb28nLCBsaXN0ZW5lcilcbiAgICAgKlxuICAgICAqIC8vIFdoZW4geW91IHdhbnQgdG8gdW5zdWJzY3JpYmUsIHlvdSBuZWVkIHRvIHNwZWNpZnkgdGhlIHV1aWQgb2YgdGhlIGFwcCB5b3UnZCBsaWtlIHRvXG4gICAgICogLy8gdW5zdWJzY3JpYmUgZnJvbSAob3IgYCpgKSBhbmQgcHJvdmlkZSB0aGUgc2FtZSBmdW5jdGlvbiB5b3UgZ2F2ZSB0aGUgc3Vic2NyaWJlIGZ1bmN0aW9uXG4gICAgICogYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMudW5zdWJzY3JpYmUoeyB1dWlkOicqJyB9LCAnZm9vJywgbGlzdGVuZXIpXG4gICAgICogYGBgXG4gICAgICovXG4gICAgdW5zdWJzY3JpYmUoc291cmNlLCB0b3BpYywgbGlzdGVuZXIpIHtcbiAgICAgICAgY29uc3Qgc291cmNlV2luZG93TmFtZSA9IHNvdXJjZS5uYW1lIHx8ICcqJztcbiAgICAgICAgY29uc3Qgc3ViS2V5ID0gdGhpcy5jcmVhdGVTdWJzY3JpcHRpb25LZXkoc291cmNlLnV1aWQsIHNvdXJjZVdpbmRvd05hbWUsIHRvcGljKTtcbiAgICAgICAgY29uc3Qgc2VuZFVuc3Vic2NyaXB0aW9uID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Vuc3Vic2NyaWJlJywge1xuICAgICAgICAgICAgICAgIHNvdXJjZVV1aWQ6IHNvdXJjZS51dWlkLFxuICAgICAgICAgICAgICAgIHNvdXJjZVdpbmRvd05hbWUsXG4gICAgICAgICAgICAgICAgdG9waWMsXG4gICAgICAgICAgICAgICAgZGVzdGluYXRpb25XaW5kb3dOYW1lOiB0aGlzLm1lLm5hbWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBkb250U2VuZFVuc3Vic2NyaXB0aW9uID0gKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyKSA9PiByKS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihzdWJLZXksIGxpc3RlbmVyKTtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVmQ291bnRlci5hY3RPbkxhc3Qoc3ViS2V5LCBzZW5kVW5zdWJzY3JpcHRpb24sIGRvbnRTZW5kVW5zdWJzY3JpcHRpb24pO1xuICAgIH1cbiAgICBwcm9jZXNzTWVzc2FnZShtZXNzYWdlKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBtZXNzYWdlOiBwYXlsb2FkTWVzc2FnZSwgc291cmNlV2luZG93TmFtZSwgc291cmNlVXVpZCwgdG9waWMgfSB9ID0gbWVzc2FnZTtcbiAgICAgICAgY29uc3Qga2V5cyA9IFtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlU3Vic2NyaXB0aW9uS2V5KHNvdXJjZVV1aWQsIHNvdXJjZVdpbmRvd05hbWUsIHRvcGljKSxcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlU3Vic2NyaXB0aW9uS2V5KHNvdXJjZVV1aWQsICcqJywgdG9waWMpLFxuICAgICAgICAgICAgdGhpcy5jcmVhdGVTdWJzY3JpcHRpb25LZXkoJyonLCAnKicsIHRvcGljKVxuICAgICAgICBdO1xuICAgICAgICBjb25zdCBpZE9mU2VuZGVyID0geyB1dWlkOiBzb3VyY2VVdWlkLCBuYW1lOiBzb3VyY2VXaW5kb3dOYW1lIH07XG4gICAgICAgIGtleXMuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVtaXR0ZXIuZW1pdChrZXksIHBheWxvYWRNZXNzYWdlLCBpZE9mU2VuZGVyKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGVtaXRTdWJzY3JpdmVyRXZlbnQodHlwZSwgbWVzc2FnZSkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgdGFyZ2V0TmFtZTogbmFtZSwgdXVpZCwgdG9waWMgfSB9ID0gbWVzc2FnZTtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHsgbmFtZSwgdXVpZCwgdG9waWMgfTtcbiAgICAgICAgdGhpcy5lbWl0dGVyLmVtaXQodHlwZSwgcGF5bG9hZCk7XG4gICAgfVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG4gICAgY3JlYXRlU3Vic2NyaXB0aW9uS2V5KHV1aWQsIG5hbWUsIHRvcGljKSB7XG4gICAgICAgIGNvbnN0IG4gPSBuYW1lIHx8ICcqJztcbiAgICAgICAgaWYgKCEodXVpZCAmJiBuICYmIHRvcGljKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHV1aWQsIG5hbWUsIG9yIHRvcGljIHN0cmluZycpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjcmVhdGVLZXkodXVpZCwgbiwgdG9waWMpO1xuICAgIH1cbiAgICBvbm1lc3NhZ2UobWVzc2FnZSkge1xuICAgICAgICBjb25zdCB7IGFjdGlvbiB9ID0gbWVzc2FnZTtcbiAgICAgICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgICAgIGNhc2UgJ3Byb2Nlc3MtbWVzc2FnZSc6XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzTWVzc2FnZShtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgdGhpcy5ldmVudHMuc3Vic2NyaWJlckFkZGVkOlxuICAgICAgICAgICAgICAgIHRoaXMuZW1pdFN1YnNjcml2ZXJFdmVudCh0aGlzLmV2ZW50cy5zdWJzY3JpYmVyQWRkZWQsIG1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSB0aGlzLmV2ZW50cy5zdWJzY3JpYmVyUmVtb3ZlZDpcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRTdWJzY3JpdmVyRXZlbnQodGhpcy5ldmVudHMuc3Vic2NyaWJlclJlbW92ZWQsIG1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn1cbmludGVyYXBwYnVzLkludGVyQXBwbGljYXRpb25CdXMgPSBJbnRlckFwcGxpY2F0aW9uQnVzO1xuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuY2xhc3MgSW50ZXJBcHBQYXlsb2FkIHtcbn1cbmludGVyYXBwYnVzLkludGVyQXBwUGF5bG9hZCA9IEludGVyQXBwUGF5bG9hZDtcbmZ1bmN0aW9uIGNyZWF0ZUtleSguLi50b0hhc2gpIHtcbiAgICByZXR1cm4gdG9IYXNoXG4gICAgICAgIC5tYXAoKGl0ZW0pID0+IHtcbiAgICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGAke2l0ZW19YCkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICAgIH0pXG4gICAgICAgIC5qb2luKCcvJyk7XG59XG5cbnZhciBjbGlwYm9hcmQgPSB7fTtcblxuLyoqXG4gKiBFbnRyeSBwb2ludCBmb3IgdGhlIE9wZW5GaW4gYENsaXBib2FyZGAgQVBJIChgZmluLkNsaXBib2FyZGApLlxuICpcbiAqICoge0BsaW5rIENsaXBib2FyZH0gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBDbGlwYm9hcmRgIEFQSSwgYWNjZXNzaWJsZSB0aHJvdWdoIGBmaW4uQ2xpcGJvYXJkYC5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGNsaXBib2FyZCwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jbGlwYm9hcmQuQ2xpcGJvYXJkID0gdm9pZCAwO1xuY29uc3QgYmFzZV8xJGMgPSBiYXNlO1xuLyoqXG4gKiBUaGUgQ2xpcGJvYXJkIEFQSSBhbGxvd3MgcmVhZGluZyBhbmQgd3JpdGluZyB0byB0aGUgY2xpcGJvYXJkIGluIG11bHRpcGxlIGZvcm1hdHMuXG4gKlxuICovXG5jbGFzcyBDbGlwYm9hcmQgZXh0ZW5kcyBiYXNlXzEkYy5CYXNlIHtcbiAgICAvKipcbiAgICAgKiBXcml0ZXMgZGF0YSBpbnRvIHRoZSBjbGlwYm9hcmQgYXMgcGxhaW4gdGV4dFxuICAgICAqIEBwYXJhbSB3cml0ZU9iaiBUaGUgb2JqZWN0IGZvciB3cml0aW5nIGRhdGEgaW50byB0aGUgY2xpcGJvYXJkXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkNsaXBib2FyZC53cml0ZVRleHQoe1xuICAgICAqICAgICBkYXRhOiAnaGVsbG8sIHdvcmxkJ1xuICAgICAqIH0pLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1RleHQgT24gY2xpcGJvYXJkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyB3cml0ZVRleHQod3JpdGVPYmopIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NsaXBib2FyZC13cml0ZS10ZXh0Jywgd3JpdGVPYmopO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWFkIHRoZSBjb250ZW50IG9mIHRoZSBjbGlwYm9hcmQgYXMgcGxhaW4gdGV4dFxuICAgICAqIEBwYXJhbSB0eXBlIENsaXBib2FyZCBUeXBlIGRlZmF1bHRzIHRvICdjbGlwYm9hcmQnLCB1c2UgJ3NlbGVjdGlvbicgZm9yIGxpbnV4XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkNsaXBib2FyZC5yZWFkVGV4dCgpLnRoZW4odGV4dCA9PiBjb25zb2xlLmxvZyh0ZXh0KSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHJlYWRUZXh0KHR5cGUpIHtcbiAgICAgICAgLy8gTk9URTogV2hlbiB3ZSBzdGFydCBzdXBwb3J0aW5nIGxpbnV4LCB3ZSBjb3VsZCBkZXRlY3QgdGhlIE9TIGFuZCBjaG9vc2UgJ3NlbGVjdGlvbicgYXV0b21hdGljYWxseSBmb3IgdGhlIHVzZXJcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignY2xpcGJvYXJkLXJlYWQtdGV4dCcsIHsgdHlwZSB9KTtcbiAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogV3JpdGVzIGRhdGEgaW50byB0aGUgY2xpcGJvYXJkIGFzIGFuIEltYWdlXG4gICAgICogQHBhcmFtIHdyaXRlUmVxdWVzdCBUaGUgb2JqZWN0IHRvIHdyaXRlIGFuIGltYWdlIHRvIHRoZSBjbGlwYm9hcmRcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uQ2xpcGJvYXJkLndyaXRlSW1hZ2Uoe1xuICAgICAqICAgLy8gcmF3IGJhc2U2NCBzdHJpbmcsIG9yIGRhdGFVUkwgb2YgZWl0aGVyIGRhdGE6aW1hZ2UvcG5nIG9yIGRhdGE6aW1hZ2UvanBlZyB0eXBlXG4gICAgICogICBpbWFnZTogJy4uLidcbiAgICAgKiB9KS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdJbWFnZSB3cml0dGVuIHRvIGNsaXBib2FyZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgd3JpdGVJbWFnZSh3cml0ZVJlcXVlc3QpIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NsaXBib2FyZC13cml0ZS1pbWFnZScsIHdyaXRlUmVxdWVzdCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlYWQgdGhlIGNvbnRlbnQgb2YgdGhlIGNsaXBib2FyZCBhcyBhIGJhc2U2NCBzdHJpbmcgb3IgYSBkYXRhVVJMIGJhc2VkIG9uIHRoZSBpbnB1dCBwYXJhbWV0ZXIgJ2Zvcm1hdCcsIGRlZmF1bHRzIHRvICdkYXRhVVJMJ1xuICAgICAqIEBwYXJhbSByZWFkUmVxdWVzdCBDbGlwYm9hcmQgUmVhZCBJbWFnZSByZXF1ZXN0IHdpdGggZm9ybWF0dGluZyBvcHRpb25zXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogLy8gc2VlIFRTIHR5cGU6IE9wZW5GaW4uSW1hZ2VGb3JtYXRPcHRpb25zXG4gICAgICpcbiAgICAgKiBjb25zdCBwbmdPckRhdGFVUkxPckJtcE9wdGlvbnMgPSB7XG4gICAgICogICAgIGZvcm1hdDogJ3BuZycsIC8vIGNhbiBiZTogJ3BuZycgfCAnZGF0YVVSTCcgfCAnYm1wJ1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBjb25zdCBqcGdPcHRpb25zID0ge1xuICAgICAqICAgICBmb3JtYXQ6ICdqcGcnLFxuICAgICAqICAgICBxdWFsaXR5OiA4MCAvLyBvcHRpb25hbCwgaWYgb21pdHRlZCBkZWZhdWx0cyB0byAxMDBcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogZmluLkNsaXBib2FyZC5yZWFkSW1hZ2UocG5nT3JEYXRhVVJMT3JCbXBPcHRpb25zKVxuICAgICAqICAgICAudGhlbihpbWFnZSA9PiBjb25zb2xlLmxvZygnSW1hZ2UgcmVhZCBmcm9tIGNsaXBib2FyZCBhcyBQTkcsIERhdGFVUkwgb3IgQk1QJywgaW1hZ2UpKVxuICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqXG4gICAgICogZmluLkNsaXBib2FyZC5yZWFkSW1hZ2UoanBnT3B0aW9ucylcbiAgICAgKiAgICAgLnRoZW4oaW1hZ2UgPT4gY29uc29sZS5sb2coJ0ltYWdlIHJlYWQgZnJvbSBjbGlwYm9hcmQgYXMgSlBHJywgaW1hZ2UpKVxuICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqXG4gICAgICogLy8gZGVmYXVsdHMgdG8ge2Zvcm1hdDogJ2RhdGFVUkwnfVxuICAgICAqIGZpbi5DbGlwYm9hcmQucmVhZEltYWdlKClcbiAgICAgKiAgICAgLnRoZW4oaW1hZ2UgPT4gY29uc29sZS5sb2coJ0ltYWdlIHJlYWQgZnJvbSBjbGlwYm9hcmQgYXMgRGF0YVVSTCcsIGltYWdlKSlcbiAgICAgKiAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHJlYWRJbWFnZShyZWFkUmVxdWVzdCA9IHsgZm9ybWF0OiAnZGF0YVVSTCcgfSkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQgfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjbGlwYm9hcmQtcmVhZC1pbWFnZScsIHJlYWRSZXF1ZXN0KTtcbiAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogV3JpdGVzIGRhdGEgaW50byB0aGUgY2xpcGJvYXJkIGFzIEh0bWxcbiAgICAgKiBAcGFyYW0gd3JpdGVPYmogVGhlIG9iamVjdCBmb3Igd3JpdGluZyBkYXRhIGludG8gdGhlIGNsaXBib2FyZFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5DbGlwYm9hcmQud3JpdGVIdG1sKHtcbiAgICAgKiAgICAgICAgIGRhdGE6ICc8aDE+SGVsbG8sIFdvcmxkITwvaDE+J1xuICAgICAqIH0pLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0hUTUwgT24gY2xpcGJvYXJkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyB3cml0ZUh0bWwod3JpdGVPYmopIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NsaXBib2FyZC13cml0ZS1odG1sJywgd3JpdGVPYmopO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWFkIHRoZSBjb250ZW50IG9mIHRoZSBjbGlwYm9hcmQgYXMgSHRtbFxuICAgICAqIEBwYXJhbSB0eXBlIENsaXBib2FyZCBUeXBlIGRlZmF1bHRzIHRvICdjbGlwYm9hcmQnLCB1c2UgJ3NlbGVjdGlvbicgZm9yIGxpbnV4XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkNsaXBib2FyZC5yZWFkSHRtbCgpLnRoZW4oaHRtbCA9PiBjb25zb2xlLmxvZyhodG1sKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHJlYWRIdG1sKHR5cGUpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignY2xpcGJvYXJkLXJlYWQtaHRtbCcsIHsgdHlwZSB9KTtcbiAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogV3JpdGVzIGRhdGEgaW50byB0aGUgY2xpcGJvYXJkIGFzIFJ0ZlxuICAgICAqIEBwYXJhbSB3cml0ZU9iaiBUaGUgb2JqZWN0IGZvciB3cml0aW5nIGRhdGEgaW50byB0aGUgY2xpcGJvYXJkXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkNsaXBib2FyZC53cml0ZVJ0Zih7XG4gICAgICogICAgICAgICBkYXRhOiAnc29tZSB0ZXh0IGdvZXMgaGVyZSdcbiAgICAgKiB9KS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdSVEYgT24gY2xpcGJvYXJkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyB3cml0ZVJ0Zih3cml0ZU9iaikge1xuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignY2xpcGJvYXJkLXdyaXRlLXJ0ZicsIHdyaXRlT2JqKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVhZCB0aGUgY29udGVudCBvZiB0aGUgY2xpcGJvYXJkIGFzIFJ0ZlxuICAgICAqIEBwYXJhbSB0eXBlIENsaXBib2FyZCBUeXBlIGRlZmF1bHRzIHRvICdjbGlwYm9hcmQnLCB1c2UgJ3NlbGVjdGlvbicgZm9yIGxpbnV4XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCB3cml0ZU9iaiA9IHtcbiAgICAgKiAgICAgZGF0YTogJ3NvbWUgdGV4dCBnb2VzIGhlcmUnXG4gICAgICogfTtcbiAgICAgKiBhc3luYyBmdW5jdGlvbiByZWFkUnRmKCkge1xuICAgICAqICAgICBhd2FpdCBmaW4uQ2xpcGJvYXJkLndyaXRlUnRmKHdyaXRlT2JqKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGZpbi5DbGlwYm9hcmQucmVhZFJ0ZigpO1xuICAgICAqIH1cbiAgICAgKiByZWFkUnRmKCkudGhlbihydGYgPT4gY29uc29sZS5sb2cocnRmKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHJlYWRSdGYodHlwZSkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQgfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjbGlwYm9hcmQtcmVhZC1ydGYnLCB7IHR5cGUgfSk7XG4gICAgICAgIHJldHVybiBwYXlsb2FkLmRhdGE7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBkYXRhIGludG8gdGhlIGNsaXBib2FyZFxuICAgICAqIEBwYXJhbSB3cml0ZU9iaiBUaGUgb2JqZWN0IGZvciB3cml0aW5nIGRhdGEgaW50byB0aGUgY2xpcGJvYXJkXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkNsaXBib2FyZC53cml0ZSh7XG4gICAgICogICBkYXRhOiB7XG4gICAgICogICAgIHRleHQ6ICdhJyxcbiAgICAgKiAgICAgaHRtbDogJ2InLFxuICAgICAqICAgICBydGY6ICdjJyxcbiAgICAgKiAgICAgLy8gQ2FuIGJlIGVpdGhlciBhIGJhc2U2NCBzdHJpbmcsIG9yIGEgRGF0YVVSTCBzdHJpbmcuIElmIHVzaW5nIERhdGFVUkwsIHRoZVxuICAgICAqICAgICAvLyBzdXBwb3J0ZWQgZm9ybWF0cyBhcmUgYGRhdGE6aW1hZ2UvcG5nWztiYXNlNjRdLGAgYW5kIGBkYXRhOmltYWdlL2pwZWdbO2Jhc2U2NF0sYC5cbiAgICAgKiAgICAgLy8gVXNpbmcgb3RoZXIgaW1hZ2UvPGZvcm1hdD4gRGF0YVVSTHMgd2lsbCB0aHJvdyBhbiBFcnJvci5cbiAgICAgKiAgICAgaW1hZ2U6ICcuLi4nXG4gICAgICogICB9XG4gICAgICogfSkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnd3JpdGUgZGF0YSBpbnRvIGNsaXBib2FyZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgd3JpdGUod3JpdGVPYmopIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NsaXBib2FyZC13cml0ZScsIHdyaXRlT2JqKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVhZHMgYXZhaWxhYmxlIGZvcm1hdHMgZm9yIHRoZSBjbGlwYm9hcmQgdHlwZVxuICAgICAqIEBwYXJhbSB0eXBlIENsaXBib2FyZCBUeXBlIGRlZmF1bHRzIHRvICdjbGlwYm9hcmQnLCB1c2UgJ3NlbGVjdGlvbicgZm9yIGxpbnV4XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkNsaXBib2FyZC5nZXRBdmFpbGFibGVGb3JtYXRzKCkudGhlbihmb3JtYXRzID0+IGNvbnNvbGUubG9nKGZvcm1hdHMpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QXZhaWxhYmxlRm9ybWF0cyh0eXBlKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NsaXBib2FyZC1yZWFkLWZvcm1hdHMnLCB7IHR5cGUgfSk7XG4gICAgICAgIHJldHVybiBwYXlsb2FkLmRhdGE7XG4gICAgfVxufVxuY2xpcGJvYXJkLkNsaXBib2FyZCA9IENsaXBib2FyZDtcblxudmFyIGV4dGVybmFsQXBwbGljYXRpb24gPSB7fTtcblxudmFyIEZhY3RvcnkkNSA9IHt9O1xuXG52YXIgSW5zdGFuY2UkNCA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoSW5zdGFuY2UkNCwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5JbnN0YW5jZSQ0LkV4dGVybmFsQXBwbGljYXRpb24gPSB2b2lkIDA7XG4vKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvcHJlZmVyLWRlZmF1bHQtZXhwb3J0ICovXG5jb25zdCBiYXNlXzEkYiA9IGJhc2U7XG4vKipcbiAqIEFuIEV4dGVybmFsQXBwbGljYXRpb24gb2JqZWN0IHJlcHJlc2VudGluZyBuYXRpdmUgbGFuZ3VhZ2UgYWRhcHRlciBjb25uZWN0aW9ucyB0byB0aGUgcnVudGltZS4gQWxsb3dzXG4gKiB0aGUgZGV2ZWxvcGVyIHRvIGxpc3RlbiB0byB7QGxpbmsgT3BlbkZpbi5FeHRlcm5hbEFwcGxpY2F0aW9uRXZlbnRzIGV4dGVybmFsIGFwcGxpY2F0aW9uIGV2ZW50c30uXG4gKiBEaXNjb3Zlcnkgb2YgY29ubmVjdGlvbnMgaXMgcHJvdmlkZWQgYnkge0BsaW5rIFN5c3RlbS5TeXN0ZW0uZ2V0QWxsRXh0ZXJuYWxBcHBsaWNhdGlvbnMgZ2V0QWxsRXh0ZXJuYWxBcHBsaWNhdGlvbnN9LjwvYT5cbiAqXG4gKiBQcm9jZXNzZXMgdGhhdCBjYW4gYmUgd3JhcHBlZCBhcyBgRXh0ZXJuYWxBcHBsaWNhdGlvbmBzIGluY2x1ZGUgdGhlIGZvbGxvd2luZzpcbiAqIC0gUHJvY2Vzc2VzIHdoaWNoIGhhdmUgY29ubmVjdGVkIHRvIGFuIE9wZW5GaW4gcnVudGltZSB2aWEgYW4gYWRhcHRlclxuICogLSBQcm9jZXNzZXMgc3RhcnRlZCB2aWEgYFN5c3RlbS5sYXVuY2hFeHRlcm5hbEFwcGxpY2F0aW9uYFxuICogLSBQcm9jZXNzZXMgbW9uaXRvcmVkIHZpYSBgU3lzdGVtLm1vbml0b3JFeHRlcm5hbFByb2Nlc3NgXG4gKi9cbmNsYXNzIEV4dGVybmFsQXBwbGljYXRpb24gZXh0ZW5kcyBiYXNlXzEkYi5FbWl0dGVyQmFzZSB7XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iod2lyZSwgaWRlbnRpdHkpIHtcbiAgICAgICAgc3VwZXIod2lyZSwgJ2V4dGVybmFsLWFwcGxpY2F0aW9uJywgaWRlbnRpdHkudXVpZCk7XG4gICAgICAgIHRoaXMuaWRlbnRpdHkgPSBpZGVudGl0eTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBleHRlcm5hbCBhcHBsaWNhdGlvbi5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRJbmZvKCkge1xuICAgICAqICAgICBjb25zdCBleHRBcHAgPSBhd2FpdCBmaW4uRXh0ZXJuYWxBcHBsaWNhdGlvbi53cmFwKCdqYXZhQXBwLXV1aWQnKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGV4dEFwcC5nZXRJbmZvKCk7XG4gICAgICogfVxuICAgICAqIGdldEluZm8oKS50aGVuKGluZm8gPT4gY29uc29sZS5sb2coaW5mbykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRJbmZvKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1leHRlcm5hbC1hcHBsaWNhdGlvbi1pbmZvJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxufVxuSW5zdGFuY2UkNC5FeHRlcm5hbEFwcGxpY2F0aW9uID0gRXh0ZXJuYWxBcHBsaWNhdGlvbjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KEZhY3RvcnkkNSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5GYWN0b3J5JDUuRXh0ZXJuYWxBcHBsaWNhdGlvbk1vZHVsZSA9IHZvaWQgMDtcbmNvbnN0IGJhc2VfMSRhID0gYmFzZTtcbmNvbnN0IEluc3RhbmNlXzEkNCA9IEluc3RhbmNlJDQ7XG4vKipcbiAqIFN0YXRpYyBuYW1lc3BhY2UgZm9yIE9wZW5GaW4gQVBJIG1ldGhvZHMgdGhhdCBpbnRlcmFjdCB3aXRoIHRoZSB7QGxpbmsgRXh0ZXJuYWxBcHBsaWNhdGlvbn0gY2xhc3MsIGF2YWlsYWJsZSB1bmRlciBgZmluLkV4dGVybmFsQXBwbGljYXRpb25gLlxuICovXG5jbGFzcyBFeHRlcm5hbEFwcGxpY2F0aW9uTW9kdWxlIGV4dGVuZHMgYmFzZV8xJGEuQmFzZSB7XG4gICAgLyoqXG4gICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhbiBFeHRlcm5hbCBBcHBsaWNhdGlvbiBvYmplY3QgdGhhdCByZXByZXNlbnRzIGFuIGV4dGVybmFsIGFwcGxpY2F0aW9uLlxuICAgICAqIDxicj5JdCBpcyBwb3NzaWJsZSB0byB3cmFwIGEgcHJvY2VzcyB0aGF0IGRvZXMgbm90IHlldCBleGlzdCwgKGZvciBleGFtcGxlLCB0byBsaXN0ZW4gZm9yIHN0YXJ0dXAtcmVsYXRlZCBldmVudHMpXG4gICAgICogcHJvdmlkZWQgaXRzIHV1aWQgaXMgYWxyZWFkeSBrbm93bi5cbiAgICAgKiBAcGFyYW0gdXVpZCBUaGUgVVVJRCBvZiB0aGUgZXh0ZXJuYWwgYXBwbGljYXRpb24gdG8gYmUgd3JhcHBlZFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5FeHRlcm5hbEFwcGxpY2F0aW9uLndyYXAoJ2phdmFBcHAtdXVpZCcpO1xuICAgICAqIC50aGVuKGV4dEFwcCA9PiBjb25zb2xlLmxvZygnd3JhcHBlZCBleHRlcm5hbCBhcHBsaWNhdGlvbicpKVxuICAgICAqIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgd3JhcCh1dWlkKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdleHRlcm5hbC1hcHBsaWNhdGlvbi13cmFwJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXcgSW5zdGFuY2VfMSQ0LkV4dGVybmFsQXBwbGljYXRpb24odGhpcy53aXJlLCB7IHV1aWQgfSkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTeW5jaHJvbm91c2x5IHJldHVybnMgYW4gRXh0ZXJuYWwgQXBwbGljYXRpb24gb2JqZWN0IHRoYXQgcmVwcmVzZW50cyBhbiBleHRlcm5hbCBhcHBsaWNhdGlvbi5cbiAgICAgKiA8YnI+SXQgaXMgcG9zc2libGUgdG8gd3JhcCBhIHByb2Nlc3MgdGhhdCBkb2VzIG5vdCB5ZXQgZXhpc3QsIChmb3IgZXhhbXBsZSwgdG8gbGlzdGVuIGZvciBzdGFydHVwLXJlbGF0ZWQgZXZlbnRzKVxuICAgICAqIHByb3ZpZGVkIGl0cyB1dWlkIGlzIGFscmVhZHkga25vd24uXG4gICAgICogQHBhcmFtIHV1aWQgVGhlIFVVSUQgb2YgdGhlIGV4dGVybmFsIGFwcGxpY2F0aW9uIHRvIGJlIHdyYXBwZWRcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBleHRBcHAgPSBmaW4uRXh0ZXJuYWxBcHBsaWNhdGlvbi53cmFwU3luYygnamF2YUFwcC11dWlkJyk7XG4gICAgICogY29uc3QgaW5mbyA9IGF3YWl0IGV4dEFwcC5nZXRJbmZvKCk7XG4gICAgICogY29uc29sZS5sb2coaW5mbyk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgd3JhcFN5bmModXVpZCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZXh0ZXJuYWwtYXBwbGljYXRpb24td3JhcC1zeW5jJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnN0YW5jZV8xJDQuRXh0ZXJuYWxBcHBsaWNhdGlvbih0aGlzLndpcmUsIHsgdXVpZCB9KTtcbiAgICB9XG59XG5GYWN0b3J5JDUuRXh0ZXJuYWxBcHBsaWNhdGlvbk1vZHVsZSA9IEV4dGVybmFsQXBwbGljYXRpb25Nb2R1bGU7XG5cbihmdW5jdGlvbiAoZXhwb3J0cykge1xuXHR2YXIgX19jcmVhdGVCaW5kaW5nID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY3JlYXRlQmluZGluZykgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdCAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XG5cdCAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xuXHQgICAgICBkZXNjID0geyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbVtrXTsgfSB9O1xuXHQgICAgfVxuXHQgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcblx0fSkgOiAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdCAgICBvW2syXSA9IG1ba107XG5cdH0pKTtcblx0dmFyIF9fZXhwb3J0U3RhciA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2V4cG9ydFN0YXIpIHx8IGZ1bmN0aW9uKG0sIGV4cG9ydHMpIHtcblx0ICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZXhwb3J0cywgcCkpIF9fY3JlYXRlQmluZGluZyhleHBvcnRzLCBtLCBwKTtcblx0fTtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHQvKipcblx0ICogRW50cnkgcG9pbnRzIGZvciB0aGUgT3BlbkZpbiBgRXh0ZXJuYWxBcHBsaWNhdGlvbmAgQVBJIChgZmluLkV4dGVybmFsQXBwbGljYXRpb25gKS5cblx0ICpcblx0ICogKiB7QGxpbmsgRXh0ZXJuYWxBcHBsaWNhdGlvbk1vZHVsZX0gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBFeHRlcm5hbEFwcGxpY2F0aW9uYCB0eXBlLCBhY2Nlc3NpYmxlIHRocm91Z2ggYGZpbi5FeHRlcm5hbEFwcGxpY2F0aW9uYC5cblx0ICogKiB7QGxpbmsgRXh0ZXJuYWxBcHBsaWNhdGlvbn0gZGVzY3JpYmVzIGFuIGluc3RhbmNlIG9mIGFuIE9wZW5GaW4gRXh0ZXJuYWxBcHBsaWNhdGlvbiwgZS5nLiBhcyByZXR1cm5lZCBieSBgZmluLkV4dGVybmFsQXBwbGljYXRpb24uZ2V0Q3VycmVudGAuXG5cdCAqXG5cdCAqIFRoZXNlIGFyZSBzZXBhcmF0ZSBjb2RlIGVudGl0aWVzLCBhbmQgYXJlIGRvY3VtZW50ZWQgc2VwYXJhdGVseS4gIEluIHRoZSBbcHJldmlvdXMgdmVyc2lvbiBvZiB0aGUgQVBJIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0LzMyLjExNC43Ni4xMC9pbmRleC5odG1sKSxcblx0ICogYm90aCBvZiB0aGVzZSB3ZXJlIGRvY3VtZW50ZWQgb24gdGhlIHNhbWUgcGFnZS5cblx0ICpcblx0ICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG5cdCAqL1xuXHRfX2V4cG9ydFN0YXIoRmFjdG9yeSQ1LCBleHBvcnRzKTtcblx0X19leHBvcnRTdGFyKEluc3RhbmNlJDQsIGV4cG9ydHMpOyBcbn0gKGV4dGVybmFsQXBwbGljYXRpb24pKTtcblxudmFyIGZyYW1lID0ge307XG5cbnZhciBGYWN0b3J5JDQgPSB7fTtcblxudmFyIEluc3RhbmNlJDMgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KEluc3RhbmNlJDMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuSW5zdGFuY2UkMy5fRnJhbWUgPSB2b2lkIDA7XG4vKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvcHJlZmVyLWRlZmF1bHQtZXhwb3J0ICovXG5jb25zdCBiYXNlXzEkOSA9IGJhc2U7XG4vKipcbiAqIEFuIGlmcmFtZSByZXByZXNlbnRzIGFuIGVtYmVkZGVkIEhUTUwgcGFnZSB3aXRoaW4gYSBwYXJlbnQgSFRNTCBwYWdlLiBCZWNhdXNlIHRoaXMgZW1iZWRkZWQgcGFnZVxuICogaGFzIGl0cyBvd24gRE9NIGFuZCBnbG9iYWwgSlMgY29udGV4dCAod2hpY2ggbWF5IG9yIG1heSBub3QgYmUgbGlua2VkIHRvIHRoYXQgb2YgdGhlIHBhcmVudCBkZXBlbmRpbmdcbiAqIG9uIGlmIGl0IGlzIGNvbnNpZGVyZWQgb3V0IG9mIHRoZSByb290IGRvbWFpbiBvciBub3QpLCBpdCByZXByZXNlbnRzIGEgdW5pcXVlIGVuZHBvaW50IGFzIGFuIE9wZW5GaW5cbiAqIGNvbm5lY3Rpb24uIElmcmFtZXMgbWF5IGJlIGdlbmVyYXRlZCBkeW5hbWljYWxseSwgb3IgYmUgcHJlc2VudCBvbiBpbml0aWFsIHBhZ2UgbG9hZCBhbmQgZWFjaCBub24tQ09SU1xuICogaWZyYW1lIGhhcyB0aGUgT3BlbkZpbiBBUEkgaW5qZWN0ZWQgYnkgZGVmYXVsdC4gSXQgaXMgcG9zc2libGUgdG8gb3B0IGludG8gY3Jvc3Mtb3JpZ2luIGlmcmFtZXMgaGF2aW5nXG4gKiB0aGUgQVBJIGJ5IHNldHRpbmcgYXBpLmlmcmFtZS5jcm9zc09yaWdpbkluamVjdGlvbiB0byB0cnVlIGluIGEgd2luZG93J3Mgb3B0aW9ucy4gVG8gYmxvY2sgYWxsIGlmcmFtZXNcbiAqIGZyb20gZ2V0dGluZyB0aGUgQVBJIGluamVjdGVkIHlvdSBjYW4gc2V0IGFwaS5mcmFtZS5zYW1lT3JpZ2luSW5qZWN0aW9uXG4gKiB0byBmYWxzZSA8YSBocmVmPVwiV2luZG93Lmh0bWwjfm9wdGlvbnNcIiB0YXJnZXQ9XCJfYmxhbmtcIj4oe0BsaW5rIE9wZW5GaW4uV2luZG93Q3JlYXRpb25PcHRpb25zIHNlZSBXaW5kb3cgT3B0aW9uc30pPC9hPi5cbiAqXG4gKiBUbyBiZSBhYmxlIHRvIGRpcmVjdGx5IGFkZHJlc3MgdGhpcyBjb250ZXh0IGZvciBldmVudGluZyBhbmQgbWVzc2FnaW5nIHB1cnBvc2VzLCBpdCBuZWVkcyBhXG4gKiB1bmlxdWUgdXVpZCBuYW1lIHBhaXJpbmcuIEZvciBPcGVuRmluIGFwcGxpY2F0aW9ucyBhbmQgd2luZG93cyB0aGlzIGlzIHByb3ZpZGVkIHZpYSBhIGNvbmZpZ3VyYXRpb25cbiAqIG9iamVjdCBpbiB0aGUgZm9ybSBvZiBhIG1hbmlmZXN0IFVSTCBvciBvcHRpb25zIG9iamVjdCwgYnV0IHRoZXJlIGlzIG5vIGNvbmZpZ3VyYXRpb24gb2JqZWN0IGZvciBpZnJhbWVzLlxuICogSnVzdCBhcyBhIGNhbGwgdG8gd2luZG93Lm9wZW4gb3V0c2lkZSBvZiBvdXIgV2luZG93IEFQSSByZXR1cm5zIGEgbmV3IHdpbmRvdyB3aXRoIGEgcmFuZG9tIEdVSUQgYXNzaWduZWRcbiAqIGZvciB0aGUgbmFtZSwgZWFjaCBpZnJhbWUgdGhhdCBoYXMgdGhlIEFQSSBpbmplY3RlZCB3aWxsIGJlIGFzc2lnbmVkIGEgR1VJRCBhcyBpdHMgbmFtZSwgdGhlIFVVSUQgd2lsbCBiZVxuICogdGhlIHNhbWUgYXMgdGhlIHBhcmVudCB3aW5kb3cncy5cbiAqXG4gKiBUaGUgZmluLkZyYW1lIG5hbWVzcGFjZSByZXByZXNlbnRzIGEgd2F5IHRvIGludGVyYWN0IHdpdGggYGlmcmFtZXNgIGFuZCBmYWNpbGl0YXRlcyB0aGUgZGlzY292ZXJ5IG9mIGN1cnJlbnQgY29udGV4dFxuICogKGlmcmFtZSBvciBtYWluIHdpbmRvdykgYXMgd2VsbCBhcyB0aGUgYWJpbGl0eSB0byBsaXN0ZW4gZm9yIHtAbGluayBPcGVuRmluLkZyYW1lRXZlbnRzIGZyYW1lLXNwZWNpZmljIGV2ZW50c30uXG4gKi9cbmNsYXNzIF9GcmFtZSBleHRlbmRzIGJhc2VfMSQ5LkVtaXR0ZXJCYXNlIHtcbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih3aXJlLCBpZGVudGl0eSkge1xuICAgICAgICBzdXBlcih3aXJlLCAnZnJhbWUnLCBpZGVudGl0eS51dWlkLCBpZGVudGl0eS5uYW1lKTtcbiAgICAgICAgdGhpcy5pZGVudGl0eSA9IGlkZW50aXR5O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgZnJhbWUgaW5mbyBvYmplY3QgZm9yIHRoZSByZXByZXNlbnRlZCBmcmFtZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRJbmZvKCkge1xuICAgICAqICAgICBjb25zdCBmcm0gPSBhd2FpdCBmaW4uRnJhbWUuZ2V0Q3VycmVudCgpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgZnJtLmdldEluZm8oKTtcbiAgICAgKiB9XG4gICAgICogZ2V0SW5mbygpLnRoZW4oaW5mbyA9PiBjb25zb2xlLmxvZyhpbmZvKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldEluZm8oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWZyYW1lLWluZm8nLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGZyYW1lIGluZm8gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgd2luZG93IHRoYXQgdGhlIHJlZmVyZW5jZWQgaWZyYW1lIGlzXG4gICAgICogY3VycmVudGx5IGVtYmVkZGVkIGluLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgSWYgdGhlIGZyYW1lIGlzIGVtYmVkZGVkIGluIGEgdmlldywgdGhpcyB3aWxsIHJldHVybiBhbiBpbnZhbGlkIHN0dWIgd2l0aCBlbXB0eSBmaWVsZHMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0UGFyZW50V2luZG93KCkge1xuICAgICAqICAgICBjb25zdCBmcm0gPSBhd2FpdCBmaW4uRnJhbWUuZ2V0Q3VycmVudCgpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgZnJtLmdldFBhcmVudFdpbmRvdygpO1xuICAgICAqIH1cbiAgICAgKiBnZXRQYXJlbnRXaW5kb3coKS50aGVuKHdpbkluZm8gPT4gY29uc29sZS5sb2cod2luSW5mbykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRQYXJlbnRXaW5kb3coKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXBhcmVudC13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG59XG5JbnN0YW5jZSQzLl9GcmFtZSA9IF9GcmFtZTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KEZhY3RvcnkkNCwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5GYWN0b3J5JDQuX0ZyYW1lTW9kdWxlID0gdm9pZCAwO1xuY29uc3QgYmFzZV8xJDggPSBiYXNlO1xuY29uc3QgdmFsaWRhdGVfMSQyID0gdmFsaWRhdGU7XG5jb25zdCBJbnN0YW5jZV8xJDMgPSBJbnN0YW5jZSQzO1xuLyoqXG4gKiBTdGF0aWMgbmFtZXNwYWNlIGZvciBPcGVuRmluIEFQSSBtZXRob2RzIHRoYXQgaW50ZXJhY3Qgd2l0aCB0aGUge0BsaW5rIF9GcmFtZX0gY2xhc3MsIGF2YWlsYWJsZSB1bmRlciBgZmluLkZyYW1lYC5cbiAqL1xuY2xhc3MgX0ZyYW1lTW9kdWxlIGV4dGVuZHMgYmFzZV8xJDguQmFzZSB7XG4gICAgLyoqXG4gICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhbiBBUEkgaGFuZGxlIGZvciB0aGUgZ2l2ZW4gRnJhbWUgaWRlbnRpdHkuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBXcmFwcGluZyBhIEZyYW1lIGlkZW50aXR5IHRoYXQgZG9lcyBub3QgeWV0IGV4aXN0IHdpbGwgKm5vdCogdGhyb3cgYW4gZXJyb3IsIGFuZCBpbnN0ZWFkXG4gICAgICogcmV0dXJucyBhIHN0dWIgb2JqZWN0IHRoYXQgY2Fubm90IHlldCBwZXJmb3JtIHJlbmRlcmluZyB0YXNrcy4gVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBwbHVtYmluZyBldmVudGluZ1xuICAgICAqIGZvciBhIEZyYW1lIHRocm91Z2hvdXQgaXRzIGVudGlyZSBsaWZlY3ljbGUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkZyYW1lLndyYXAoeyB1dWlkOiAndGVzdEZyYW1lJywgbmFtZTogJ3Rlc3RGcmFtZScgfSlcbiAgICAgKiAudGhlbihmcm0gPT4gY29uc29sZS5sb2coJ3dyYXBwZWQgZnJhbWUnKSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHdyYXAoaWRlbnRpdHkpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZyYW1lLXdyYXAnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBlcnJvck1zZyA9ICgwLCB2YWxpZGF0ZV8xJDIudmFsaWRhdGVJZGVudGl0eSkoaWRlbnRpdHkpO1xuICAgICAgICBpZiAoZXJyb3JNc2cpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvck1zZyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBJbnN0YW5jZV8xJDMuX0ZyYW1lKHRoaXMud2lyZSwgaWRlbnRpdHkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTeW5jaHJvbm91c2x5IHJldHVybnMgYW4gQVBJIGhhbmRsZSBmb3IgdGhlIGdpdmVuIEZyYW1lIGlkZW50aXR5LlxuICAgICAqXG4gICAgICogQHJlbWFya3MgV3JhcHBpbmcgYSBGcmFtZSBpZGVudGl0eSB0aGF0IGRvZXMgbm90IHlldCBleGlzdCB3aWxsICpub3QqIHRocm93IGFuIGVycm9yLCBhbmQgaW5zdGVhZFxuICAgICAqIHJldHVybnMgYSBzdHViIG9iamVjdCB0aGF0IGNhbm5vdCB5ZXQgcGVyZm9ybSByZW5kZXJpbmcgdGFza3MuIFRoaXMgY2FuIGJlIHVzZWZ1bCBmb3IgcGx1bWJpbmcgZXZlbnRpbmdcbiAgICAgKiBmb3IgYSBGcmFtZSB0aHJvdWdob3V0IGl0cyBlbnRpcmUgbGlmZWN5Y2xlLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IGZybSA9IGZpbi5GcmFtZS53cmFwU3luYyh7IHV1aWQ6ICd0ZXN0RnJhbWUnLCBuYW1lOiAndGVzdEZyYW1lJyB9KTtcbiAgICAgKiBjb25zdCBpbmZvID0gYXdhaXQgZnJtLmdldEluZm8oKTtcbiAgICAgKiBjb25zb2xlLmxvZyhpbmZvKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICB3cmFwU3luYyhpZGVudGl0eSkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZnJhbWUtd3JhcC1zeW5jJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgZXJyb3JNc2cgPSAoMCwgdmFsaWRhdGVfMSQyLnZhbGlkYXRlSWRlbnRpdHkpKGlkZW50aXR5KTtcbiAgICAgICAgaWYgKGVycm9yTXNnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNc2cpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMSQzLl9GcmFtZSh0aGlzLndpcmUsIGlkZW50aXR5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGUgY3VycmVudCBmcmFtZVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5GcmFtZS5nZXRDdXJyZW50KClcbiAgICAgKiAudGhlbihmcm0gPT4gY29uc29sZS5sb2coJ2N1cnJlbnQgZnJhbWUnKSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldEN1cnJlbnQoKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmcmFtZS1nZXQtY3VycmVudCcpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IEluc3RhbmNlXzEkMy5fRnJhbWUodGhpcy53aXJlLCB0aGlzLndpcmUuZW52aXJvbm1lbnQuZ2V0Q3VycmVudEVudGl0eUlkZW50aXR5KCkpKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoZSBjdXJyZW50IGZyYW1lXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgZnJtID0gZmluLkZyYW1lLmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogY29uc3QgaW5mbyA9IGF3YWl0IGZybS5nZXRJbmZvKCk7XG4gICAgICogY29uc29sZS5sb2coaW5mbyk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0Q3VycmVudFN5bmMoKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmcmFtZS1nZXQtY3VycmVudC1zeW5jJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnN0YW5jZV8xJDMuX0ZyYW1lKHRoaXMud2lyZSwgdGhpcy53aXJlLmVudmlyb25tZW50LmdldEN1cnJlbnRFbnRpdHlJZGVudGl0eSgpKTtcbiAgICB9XG59XG5GYWN0b3J5JDQuX0ZyYW1lTW9kdWxlID0gX0ZyYW1lTW9kdWxlO1xuXG4oZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0LyoqXG5cdCAqIEVudHJ5IHBvaW50cyBmb3IgdGhlIE9wZW5GaW4gYEZyYW1lYCBBUEkgKGBmaW4uRnJhbWVgKS5cblx0ICpcblx0ICogKiB7QGxpbmsgX0ZyYW1lTW9kdWxlfSBjb250YWlucyBzdGF0aWMgbWVtYmVycyBvZiB0aGUgYEZyYW1lYCBBUEksIGFjY2Vzc2libGUgdGhyb3VnaCBgZmluLkZyYW1lYC5cblx0ICogKiB7QGxpbmsgX0ZyYW1lfSBkZXNjcmliZXMgYW4gaW5zdGFuY2Ugb2YgYW4gT3BlbkZpbiBGcmFtZSwgZS5nLiBhcyByZXR1cm5lZCBieSBgZmluLkZyYW1lLmdldEN1cnJlbnRgLlxuXHQgKlxuXHQgKiBUaGVzZSBhcmUgc2VwYXJhdGUgY29kZSBlbnRpdGllcywgYW5kIGFyZSBkb2N1bWVudGVkIHNlcGFyYXRlbHkuIEluIHRoZSBbcHJldmlvdXMgdmVyc2lvbiBvZiB0aGUgQVBJIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0LzMyLjExNC43Ni4xMC9pbmRleC5odG1sKSxcblx0ICogYm90aCBvZiB0aGVzZSB3ZXJlIGRvY3VtZW50ZWQgb24gdGhlIHNhbWUgcGFnZS5cblx0ICpcblx0ICogVW5kZXJzY29yZSBwcmVmaXhpbmcgb2YgT3BlbkZpbiB0eXBlcyB0aGF0IGFsaWFzIERPTSBlbnRpdGllcyB3aWxsIGJlIGZpeGVkIGluIGEgZnV0dXJlIHZlcnNpb24uXG5cdCAqXG5cdCAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuXHQgKi9cblx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0ICAgIH1cblx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgb1trMl0gPSBtW2tdO1xuXHR9KSk7XG5cdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0X19leHBvcnRTdGFyKEZhY3RvcnkkNCwgZXhwb3J0cyk7XG5cdF9fZXhwb3J0U3RhcihJbnN0YW5jZSQzLCBleHBvcnRzKTsgXG59IChmcmFtZSkpO1xuXG52YXIgZ2xvYmFsSG90a2V5ID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShnbG9iYWxIb3RrZXksIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZ2xvYmFsSG90a2V5Lkdsb2JhbEhvdGtleSA9IHZvaWQgMDtcbmNvbnN0IGJhc2VfMSQ3ID0gYmFzZTtcbi8qKlxuICogVGhlIEdsb2JhbEhvdGtleSBtb2R1bGUgY2FuIHJlZ2lzdGVyL3VucmVnaXN0ZXIgYSBnbG9iYWwgaG90a2V5cy5cbiAqXG4gKi9cbmNsYXNzIEdsb2JhbEhvdGtleSBleHRlbmRzIGJhc2VfMSQ3LkVtaXR0ZXJCYXNlIHtcbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih3aXJlKSB7XG4gICAgICAgIHN1cGVyKHdpcmUsICdnbG9iYWwtaG90a2V5Jyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyBhIGdsb2JhbCBob3RrZXkgd2l0aCB0aGUgb3BlcmF0aW5nIHN5c3RlbS5cbiAgICAgKiBAcGFyYW0gaG90a2V5IGEgaG90a2V5IHN0cmluZ1xuICAgICAqIEBwYXJhbSBsaXN0ZW5lciBjYWxsZWQgd2hlbiB0aGUgcmVnaXN0ZXJlZCBob3RrZXkgaXMgcHJlc3NlZCBieSB0aGUgdXNlci5cbiAgICAgKiBAdGhyb3dzIElmIHRoZSBgaG90a2V5YCBpcyByZXNlcnZlZCwgc2VlIGxpc3QgYmVsb3cuXG4gICAgICogQHRocm93cyBpZiB0aGUgYGhvdGtleWAgaXMgYWxyZWFkeSByZWdpc3RlcmVkIGJ5IGFub3RoZXIgYXBwbGljYXRpb24uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBUaGUgYGhvdGtleWAgcGFyYW1ldGVyIGV4cGVjdHMgYW4gZWxlY3Ryb24gY29tcGF0aWJsZSBbYWNjZWxlcmF0b3JdKGh0dHBzOi8vZ2l0aHViLmNvbS9lbGVjdHJvbi9lbGVjdHJvbi9ibG9iL21hc3Rlci9kb2NzL2FwaS9hY2NlbGVyYXRvci5tZCkgYW5kIHRoZSBgbGlzdGVuZXJgIHdpbGwgYmUgY2FsbGVkIGlmIHRoZSBgaG90a2V5YCBpcyBwcmVzc2VkIGJ5IHRoZSB1c2VyLlxuICAgICAqIElmIHN1Y2Nlc3NmdWxsLCB0aGUgaG90a2V5IHdpbGwgYmUgJ2NsYWltZWQnIGJ5IHRoZSBhcHBsaWNhdGlvbiwgbWVhbmluZyB0aGF0IHRoaXMgcmVnaXN0ZXIgY2FsbCBjYW4gYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIGZyb20gd2l0aGluIHRoZSBzYW1lIGFwcGxpY2F0aW9uIGJ1dCB3aWxsIGZhaWwgaWYgYW5vdGhlciBhcHBsaWNhdGlvbiBoYXMgcmVnaXN0ZXJlZCB0aGUgaG90a2V5LlxuICAgICAqIDxicj5UaGUgcmVnaXN0ZXIgY2FsbCB3aWxsIGZhaWwgaWYgZ2l2ZW4gYW55IG9mIHRoZXNlIHJlc2VydmVkIEhvdGtleXM6XG4gICAgICogKiBgQ29tbWFuZE9yQ29udHJvbCswYFxuICAgICAqICogYENvbW1hbmRPckNvbnRyb2wrPWBcbiAgICAgKiAqIGBDb21tYW5kT3JDb250cm9sK1BsdXNgXG4gICAgICogKiBgQ29tbWFuZE9yQ29udHJvbCstYFxuICAgICAqICogYENvbW1hbmRPckNvbnRyb2wrX2BcbiAgICAgKiAqIGBDb21tYW5kT3JDb250cm9sK1NoaWZ0K0lgXG4gICAgICogKiBgRjVgXG4gICAgICogKiBgQ29tbWFuZE9yQ29udHJvbCtSYFxuICAgICAqICogYFNoaWZ0K0Y1YFxuICAgICAqICogYENvbW1hbmRPckNvbnRyb2wrU2hpZnQrUmBcbiAgICAgKlxuICAgICAqIFJhaXNlcyB0aGUgYHJlZ2lzdGVyZWRgIGV2ZW50LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IGhvdGtleSA9ICdDb21tYW5kT3JDb250cm9sK1gnO1xuICAgICAqXG4gICAgICogZmluLkdsb2JhbEhvdGtleS5yZWdpc3Rlcihob3RrZXksICgpID0+IHtcbiAgICAgKiBjb25zb2xlLmxvZyhgJHtob3RrZXl9IHByZXNzZWRgKTtcbiAgICAgKiB9KVxuICAgICAqIC50aGVuKCgpID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ1N1Y2Nlc3MnKTtcbiAgICAgKiB9KVxuICAgICAqIC5jYXRjaChlcnIgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnRXJyb3IgcmVnaXN0ZXJpbmcgdGhlIGhvdGtleScsIGVycik7XG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgcmVnaXN0ZXIoaG90a2V5LCBsaXN0ZW5lcikge1xuICAgICAgICAvLyBUT0RPOiBmaXggdHlwaW5nIChob3RrZXkgZXZlbnRzIGFyZSBub3QgdHlwZWQpXG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgYXdhaXQgdGhpcy5vbihob3RrZXksIGxpc3RlbmVyKTtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dsb2JhbC1ob3RrZXktcmVnaXN0ZXInLCB7IGhvdGtleSB9KTtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVW5yZWdpc3RlcnMgYSBnbG9iYWwgaG90a2V5IHdpdGggdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gICAgICogQHBhcmFtIGhvdGtleSBhIGhvdGtleSBzdHJpbmdcbiAgICAgKlxuICAgICAqIEByZW1hcmtzIFRoaXMgbWV0aG9kIHdpbGwgdW5yZWdpc3RlciBhbGwgZXhpc3RpbmcgcmVnaXN0cmF0aW9ucyBvZiB0aGUgaG90a2V5IHdpdGhpbiB0aGUgYXBwbGljYXRpb24uXG4gICAgICogUmFpc2VzIHRoZSBgdW5yZWdpc3RlcmVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBob3RrZXkgPSAnQ29tbWFuZE9yQ29udHJvbCtYJztcbiAgICAgKlxuICAgICAqIGZpbi5HbG9iYWxIb3RrZXkudW5yZWdpc3Rlcihob3RrZXkpXG4gICAgICogLnRoZW4oKCkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnU3VjY2VzcycpO1xuICAgICAqIH0pXG4gICAgICogLmNhdGNoKGVyciA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdFcnJvciB1bnJlZ2lzdGVyaW5nIHRoZSBob3RrZXknLCBlcnIpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHVucmVnaXN0ZXIoaG90a2V5KSB7XG4gICAgICAgIC8vIFRPRE86IGZpeCB0eXBpbmcgKGhvdGtleSBldmVudHMgYXJlIG5vdCB0eXBlZClcbiAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICBhd2FpdCB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhob3RrZXkpO1xuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2xvYmFsLWhvdGtleS11bnJlZ2lzdGVyJywgeyBob3RrZXkgfSk7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFVucmVnaXN0ZXJzIGFsbCBnbG9iYWwgaG90a2V5cyBmb3IgdGhlIGN1cnJlbnQgYXBwbGljYXRpb24uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBSYWlzZXMgdGhlIGB1bnJlZ2lzdGVyZWRgIGV2ZW50IGZvciBlYWNoIGhvdGtleSB1bnJlZ2lzdGVyZWQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkdsb2JhbEhvdGtleS51bnJlZ2lzdGVyQWxsKClcbiAgICAgKiAudGhlbigoKSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdTdWNjZXNzJyk7XG4gICAgICogfSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ0Vycm9yIHVucmVnaXN0ZXJpbmcgYWxsIGhvdGtleXMgZm9yIHRoaXMgYXBwbGljYXRpb24nLCBlcnIpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHVucmVnaXN0ZXJBbGwoKSB7XG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHRoaXMuZXZlbnROYW1lcygpXG4gICAgICAgICAgICAuZmlsdGVyKChuYW1lKSA9PiAhKG5hbWUgPT09ICdyZWdpc3RlcmVkJyB8fCBuYW1lID09PSAndW5yZWdpc3RlcmVkJykpXG4gICAgICAgICAgICAvLyBUT0RPOiBmaXggdHlwaW5nIChob3RrZXkgZXZlbnRzIGFyZSBub3QgdHlwZWQpXG4gICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgICAgICAubWFwKChuYW1lKSA9PiB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhuYW1lKSkpO1xuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2xvYmFsLWhvdGtleS11bnJlZ2lzdGVyLWFsbCcsIHt9KTtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGlmIGEgZ2l2ZW4gaG90a2V5IGhhcyBiZWVuIHJlZ2lzdGVyZWQgYnkgYW4gYXBwbGljYXRpb24gd2l0aGluIHRoZSBjdXJyZW50IHJ1bnRpbWUuXG4gICAgICogQHBhcmFtIGhvdGtleSBhIGhvdGtleSBzdHJpbmdcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBob3RrZXkgPSAnQ29tbWFuZE9yQ29udHJvbCtYJztcbiAgICAgKlxuICAgICAqIGZpbi5HbG9iYWxIb3RrZXkuaXNSZWdpc3RlcmVkKGhvdGtleSlcbiAgICAgKiAudGhlbigocmVnaXN0ZXJlZCkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhgaG90a2V5ICR7aG90a2V5fSBpcyByZWdpc3RlcmVkID8gJHtyZWdpc3RlcmVkfWApO1xuICAgICAqIH0pXG4gICAgICogLmNhdGNoKGVyciA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdFcnJvciB1bnJlZ2lzdGVyaW5nIHRoZSBob3RrZXknLCBlcnIpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGlzUmVnaXN0ZXJlZChob3RrZXkpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkOiB7IGRhdGEgfSB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dsb2JhbC1ob3RrZXktaXMtcmVnaXN0ZXJlZCcsIHsgaG90a2V5IH0pO1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG59XG5nbG9iYWxIb3RrZXkuR2xvYmFsSG90a2V5ID0gR2xvYmFsSG90a2V5O1xuXG52YXIgcGxhdGZvcm0gPSB7fTtcblxudmFyIEZhY3RvcnkkMyA9IHt9O1xuXG52YXIgSW5zdGFuY2UkMiA9IHt9O1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ1ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcbn07XG52YXIgX1BsYXRmb3JtX2Nvbm5lY3RUb1Byb3ZpZGVyO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KEluc3RhbmNlJDIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuSW5zdGFuY2UkMi5QbGF0Zm9ybSA9IHZvaWQgMDtcbi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9wcmVmZXItZGVmYXVsdC1leHBvcnQsIG5vLXVuZGVmICovXG5jb25zdCBiYXNlXzEkNiA9IGJhc2U7XG5jb25zdCB2YWxpZGF0ZV8xJDEgPSB2YWxpZGF0ZTtcbi8vIFJldXNlIGNsaWVudHMgdG8gYXZvaWQgb3ZlcndyaXRpbmcgYWxyZWFkeS1yZWdpc3RlcmVkIGNsaWVudCBpbiBwcm92aWRlclxuY29uc3QgY2xpZW50TWFwID0gbmV3IE1hcCgpO1xuLyoqIE1hbmFnZXMgdGhlIGxpZmUgY3ljbGUgb2Ygd2luZG93cyBhbmQgdmlld3MgaW4gdGhlIGFwcGxpY2F0aW9uLlxuICpcbiAqIEVuYWJsZXMgdGFraW5nIHNuYXBzaG90cyBvZiBpdHNlbGYgYW5kIGFwcGx5aW5nIHRoZW0gdG8gcmVzdG9yZSBhIHByZXZpb3VzIGNvbmZpZ3VyYXRpb25cbiAqIGFzIHdlbGwgYXMgbGlzdGVuIHRvIHtAbGluayBPcGVuRmluLlBsYXRmb3JtRXZlbnRzIHBsYXRmb3JtIGV2ZW50c30uXG4gKi9cbmNsYXNzIFBsYXRmb3JtIGV4dGVuZHMgYmFzZV8xJDYuRW1pdHRlckJhc2Uge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zaGFkb3dcbiAgICBjb25zdHJ1Y3RvcihpZGVudGl0eSwgY2hhbm5lbCkge1xuICAgICAgICAvLyB3ZSBwaWdneWJhY2sgb2ZmIG9mIGFwcGxpY2F0aW9uIGV2ZW50IGVtaXR0ZXIgYmVjYXVzZSBmcm9tIHRoZSBjb3JlJ3MgcGVyc3BlY3RpdmUgcGxhdGZvcm0gaXMganVzdCBhbiBhcHAuXG4gICAgICAgIHN1cGVyKGNoYW5uZWwud2lyZSwgJ2FwcGxpY2F0aW9uJywgaWRlbnRpdHkudXVpZCk7XG4gICAgICAgIHRoaXMuZ2V0Q2xpZW50ID0gKGlkZW50aXR5KSA9PiB7XG4gICAgICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tZ2V0LWNsaWVudCcsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldCA9IGlkZW50aXR5IHx8IHRoaXMuaWRlbnRpdHk7XG4gICAgICAgICAgICBjb25zdCB7IHV1aWQgfSA9IHRhcmdldDtcbiAgICAgICAgICAgIGlmICghY2xpZW50TWFwLmhhcyh1dWlkKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNsaWVudFByb21pc2UgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDUodGhpcywgX1BsYXRmb3JtX2Nvbm5lY3RUb1Byb3ZpZGVyLCBcImZcIikuY2FsbCh0aGlzLCB1dWlkKTtcbiAgICAgICAgICAgICAgICBjbGllbnRNYXAuc2V0KHV1aWQsIGNsaWVudFByb21pc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gd2Ugc2V0IGl0IGFib3ZlXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICAgICAgcmV0dXJuIGNsaWVudE1hcC5nZXQodXVpZCk7XG4gICAgICAgIH07XG4gICAgICAgIF9QbGF0Zm9ybV9jb25uZWN0VG9Qcm92aWRlci5zZXQodGhpcywgYXN5bmMgKHV1aWQpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2hhbm5lbE5hbWUgPSBgY3VzdG9tLWZyYW1lLSR7dXVpZH1gO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuX2NoYW5uZWwuY29ubmVjdChjaGFubmVsTmFtZSwgeyB3YWl0OiBmYWxzZSB9KTtcbiAgICAgICAgICAgICAgICBjbGllbnQub25EaXNjb25uZWN0aW9uKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY2xpZW50TWFwLmRlbGV0ZSh1dWlkKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2xpZW50O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBjbGllbnRNYXAuZGVsZXRlKHV1aWQpO1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIHRhcmdldGVkIFBsYXRmb3JtIGlzIG5vdCBjdXJyZW50bHkgcnVubmluZy4gTGlzdGVuIGZvciBhcHBsaWNhdGlvbi1zdGFydGVkIGV2ZW50IGZvciB0aGUgZ2l2ZW4gVXVpZC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAZGVwcmVjYXRlZCAocmVuYW1lZClcbiAgICAgICAgICogQGlnbm9yZVxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5sYXVuY2hMZWdhY3lNYW5pZmVzdCA9IHRoaXMubGF1bmNoQ29udGVudE1hbmlmZXN0O1xuICAgICAgICBjb25zdCBlcnJvck1zZyA9ICgwLCB2YWxpZGF0ZV8xJDEudmFsaWRhdGVJZGVudGl0eSkoaWRlbnRpdHkpO1xuICAgICAgICBpZiAoZXJyb3JNc2cpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvck1zZyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fY2hhbm5lbCA9IGNoYW5uZWw7XG4gICAgICAgIHRoaXMuaWRlbnRpdHkgPSB7IHV1aWQ6IGlkZW50aXR5LnV1aWQgfTtcbiAgICAgICAgdGhpcy5MYXlvdXQgPSB0aGlzLmZpbi5QbGF0Zm9ybS5MYXlvdXQ7XG4gICAgICAgIHRoaXMuQXBwbGljYXRpb24gPSB0aGlzLmZpbi5BcHBsaWNhdGlvbi53cmFwU3luYyh0aGlzLmlkZW50aXR5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyB2aWV3IGFuZCBhdHRhY2hlcyBpdCB0byBhIHNwZWNpZmllZCB0YXJnZXQgd2luZG93LlxuICAgICAqIEBwYXJhbSB2aWV3T3B0aW9ucyBWaWV3IGNyZWF0aW9uIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0gdGFyZ2V0IFRoZSB3aW5kb3cgdG8gd2hpY2ggdGhlIG5ldyB2aWV3IGlzIHRvIGJlIGF0dGFjaGVkLiBJZiBubyB0YXJnZXQsIGNyZWF0ZSBhIHZpZXcgaW4gYSBuZXcgd2luZG93LlxuICAgICAqIEBwYXJhbSB0YXJnZXRWaWV3IElmIHByb3ZpZGVkLCB0aGUgbmV3IHZpZXcgd2lsbCBiZSBhZGRlZCB0byB0aGUgc2FtZSB0YWJzdHJpcCBhcyB0YXJnZXRWaWV3LlxuICAgICAqXG4gICAgICogQHJlbWFya3MgSWYgdGhlIHZpZXcgYWxyZWFkeSBleGlzdHMsIHdpbGwgcmVwYXJlbnQgdGhlIHZpZXcgdG8gdGhlIG5ldyB0YXJnZXQuIFlvdSBkbyBub3QgbmVlZCB0byBzZXQgYSBuYW1lIGZvciBhIFZpZXcuXG4gICAgICogVmlld3MgdGhhdCBhcmUgbm90IHBhc3NlZCBhIG5hbWUgZ2V0IGEgcmFuZG9tbHkgZ2VuZXJhdGVkIG9uZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBsZXQgd2luZG93SWRlbnRpdHk7XG4gICAgICogaWYgKGZpbi5tZS5pc1dpbmRvdykge1xuICAgICAqICAgICB3aW5kb3dJZGVudGl0eSA9IGZpbi5tZS5pZGVudGl0eTtcbiAgICAgKiB9IGVsc2UgaWYgKGZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSAoYXdhaXQgZmluLm1lLmdldEN1cnJlbnRXaW5kb3coKSkuaWRlbnRpdHk7XG4gICAgICogfSBlbHNlIHtcbiAgICAgKiAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgcnVubmluZyBpbiBhIHBsYXRmb3JtIFZpZXcgb3IgV2luZG93Jyk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKlxuICAgICAqIHBsYXRmb3JtLmNyZWF0ZVZpZXcoe1xuICAgICAqICAgICBuYW1lOiAndGVzdF92aWV3JyxcbiAgICAgKiAgICAgdXJsOiAnaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5maW4uY28vZG9jcy9wbGF0Zm9ybS1hcGknXG4gICAgICogfSwgd2luZG93SWRlbnRpdHkpLnRoZW4oY29uc29sZS5sb2cpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogUmVwYXJlbnRpbmcgYSB2aWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogbGV0IHdpbmRvd0lkZW50aXR5O1xuICAgICAqIGlmIChmaW4ubWUuaXNXaW5kb3cpIHtcbiAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSBmaW4ubWUuaWRlbnRpdHk7XG4gICAgICogfSBlbHNlIGlmIChmaW4ubWUuaXNWaWV3KSB7XG4gICAgICogICAgIHdpbmRvd0lkZW50aXR5ID0gKGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50V2luZG93KCkpLmlkZW50aXR5O1xuICAgICAqIH0gZWxzZSB7XG4gICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3IG9yIFdpbmRvdycpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGxldCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIGxldCB2aWV3T3B0aW9ucyA9IHtcbiAgICAgKiAgICAgbmFtZTogJ2V4YW1wbGVfdmlldycsXG4gICAgICogICAgIHVybDogJ2h0dHBzOi8vZXhhbXBsZS5jb20nXG4gICAgICogfTtcbiAgICAgKiAvLyBhIG5ldyB2aWV3IHdpbGwgbm93IHNob3cgaW4gdGhlIGN1cnJlbnQgd2luZG93XG4gICAgICogYXdhaXQgcGxhdGZvcm0uY3JlYXRlVmlldyh2aWV3T3B0aW9ucywgd2luZG93SWRlbnRpdHkpO1xuICAgICAqXG4gICAgICogY29uc3QgdmlldyA9IGZpbi5WaWV3LndyYXBTeW5jKHsgdXVpZDogd2luZG93SWRlbnRpdHkudXVpZCwgbmFtZTogJ3lhaG9vX3ZpZXcnIH0pO1xuICAgICAqIC8vIHJlcGFyZW50IGBleGFtcGxlX3ZpZXdgIHdoZW4gYSB2aWV3IGluIHRoZSBuZXcgd2luZG93IGlzIHNob3duXG4gICAgICogdmlldy5vbignc2hvd24nLCBhc3luYyAoKSA9PiB7XG4gICAgICogICAgIGxldCB2aWV3SWRlbnRpdHkgPSB7IHV1aWQ6IHdpbmRvd0lkZW50aXR5LnV1aWQsIG5hbWU6ICdleGFtcGxlX3ZpZXcnfTtcbiAgICAgKiAgICAgbGV0IHRhcmdldCA9IHt1dWlkOiB3aW5kb3dJZGVudGl0eS51dWlkLCBuYW1lOiAndGVzdF93aW4nfTtcbiAgICAgKiAgICAgcGxhdGZvcm0uY3JlYXRlVmlldyh2aWV3T3B0aW9ucywgdGFyZ2V0KTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIC8vIGNyZWF0ZSBhIG5ldyB3aW5kb3dcbiAgICAgKiBhd2FpdCBwbGF0Zm9ybS5jcmVhdGVXaW5kb3coe1xuICAgICAqICAgICBuYW1lOiBcInRlc3Rfd2luXCIsXG4gICAgICogICAgIGxheW91dDoge1xuICAgICAqICAgICAgICAgY29udGVudDogW1xuICAgICAqICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgdHlwZTogJ3N0YWNrJyxcbiAgICAgKiAgICAgICAgICAgICAgICAgY29udGVudDogW1xuICAgICAqICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjb21wb25lbnQnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudE5hbWU6ICd2aWV3JyxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRTdGF0ZToge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAneWFob29fdmlldycsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogJ2h0dHBzOi8veWFob28uY29tJ1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgXVxuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgIF1cbiAgICAgKiAgICAgfVxuICAgICAqIH0pLnRoZW4oY29uc29sZS5sb2cpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGNyZWF0ZVZpZXcodmlld09wdGlvbnMsIHRhcmdldCwgdGFyZ2V0Vmlldykge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tY3JlYXRlLXZpZXcnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC5kaXNwYXRjaCgnY3JlYXRlLXZpZXcnLCB7XG4gICAgICAgICAgICB0YXJnZXQsXG4gICAgICAgICAgICBvcHRzOiB2aWV3T3B0aW9ucyxcbiAgICAgICAgICAgIHRhcmdldFZpZXdcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghcmVzcG9uc2UgfHwgKDAsIHZhbGlkYXRlXzEkMS52YWxpZGF0ZUlkZW50aXR5KShyZXNwb25zZS5pZGVudGl0eSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgV2hlbiBvdmVyd3JpdGluZyB0aGUgY3JlYXRlVmlldyBjYWxsLCBwbGVhc2UgcmV0dXJuIGFuIG9iamVjdCB0aGF0IGhhcyBhIHZhbGlkICdpZGVudGl0eScgcHJvcGVydHk6ICR7SlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpfWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmZpbi5WaWV3LndyYXBTeW5jKHJlc3BvbnNlLmlkZW50aXR5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBXaW5kb3cuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgV2luZG93IGNyZWF0aW9uIG9wdGlvbnNcbiAgICAgKlxuICAgICAqIEByZW1hcmtzIFRoZXJlIGFyZSB0d28gV2luZG93IHR5cGVzIGF0IHlvdXIgZGlzcG9zYWwgd2hpbGUgdXNpbmcgT3BlbkZpbiBQbGF0Zm9ybXMgLSBEZWZhdWx0IFdpbmRvdyBhbmQgQ3VzdG9tIFdpbmRvdy5cbiAgICAgKlxuICAgICAqIFRoZSBEZWZhdWx0IFdpbmRvdyB1c2VzIHRoZSBzdGFuZGFyZCBPcGVuRmluIFdpbmRvdyBVSS4gSXQgY29udGFpbnMgdGhlIHN0YW5kYXJkIGNsb3NlLCBtYXhpbWl6ZSBhbmQgbWluaW1pemUgYnV0dG9ucyxcbiAgICAgKiBhbmQgd2lsbCBhdXRvbWF0aWNhbGx5IHJlbmRlciB0aGUgV2luZG93J3MgbGF5b3V0IGlmIG9uZSBpcyBzcGVjaWZpZWQuXG4gICAgICpcbiAgICAgKiBGb3IgZGVlcGVyIGN1c3RvbWl6YXRpb24sIHlvdSBjYW4gYnJpbmcgeW91ciBvd24gV2luZG93IGNvZGUgaW50byBhIFBsYXRmb3JtLiBUaGlzIGlzIGNhbGxlZCBhIEN1c3RvbSBXaW5kb3cuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICpcbiAgICAgKiBUaGUgZXhhbXBsZSBiZWxvdyB3aWxsIGNyZWF0ZSBhIERlZmF1bHQgV2luZG93IHdoaWNoIHVzZXMgT3BlbkZpbiBkZWZhdWx0IFdpbmRvdyBVSS48YnI+XG4gICAgICogVGhlIFdpbmRvdyBjb250YWlucyB0d28gVmlld3MgaW4gYSBzdGFjayBMYXlvdXQ6XG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gZmluLlBsYXRmb3JtLmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogcGxhdGZvcm0uY3JlYXRlV2luZG93KHtcbiAgICAgKiAgICAgbGF5b3V0OiB7XG4gICAgICogICAgICAgICBjb250ZW50OiBbXG4gICAgICogICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICB0eXBlOiAnc3RhY2snLFxuICAgICAqICAgICAgICAgICAgICAgICBjb250ZW50OiBbXG4gICAgICogICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2NvbXBvbmVudCcsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50TmFtZTogJ3ZpZXcnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudFN0YXRlOiB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICd0ZXN0X3ZpZXdfMScsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L2NhbmFyeS9QbGF0Zm9ybS5odG1sJ1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICogICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2NvbXBvbmVudCcsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50TmFtZTogJ3ZpZXcnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudFN0YXRlOiB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICd0ZXN0X3ZpZXdfMicsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L2NhbmFyeS9QbGF0Zm9ybS5odG1sJ1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgXVxuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgIF1cbiAgICAgKiAgICAgfVxuICAgICAqIH0pLnRoZW4oY29uc29sZS5sb2cpO1xuICAgICAqIGBgYFxuICAgICAqIFRoZSBEZWZhdWx0IFdpbmRvdydzIGRlc2lnbiBjYW4gYmUgY3VzdG9taXplZCBieSBzcGVjaWZ5aW5nIHRoZSBgc3R5bGVzaGVldFVybGAgcHJvcGVydHkgaW4gdGhlIG1hbmlmZXN0OlxuICAgICAqXG4gICAgICogYGBganNvblxuICAgICAqIHtcbiAgICAgKiAgICAgcGxhdGZvcm06IHtcbiAgICAgKiAgICAgICAgIGRlZmF1bHRXaW5kb3dPcHRpb25zOiB7XG4gICAgICogICAgICAgICAgICAgc3R5bGVzaGVldFVybDogJ3NvbWUtdXJsLmNzcycsXG4gICAgICogICAgICAgICAgICAgLi4uXG4gICAgICogICAgICAgICB9XG4gICAgICogICAgIH1cbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICogRm9yIGEgbGlzdCBvZiBjb21tb24gTGF5b3V0IENTUyBjbGFzc2VzIHlvdSBjYW4gb3ZlcnJpZGUgaW4geW91ciBjdXN0b20gc3R5bGVzaGVldCwgc2VlIDxhIGhyZWY9XCJ0dXRvcmlhbC1sYXlvdXRTdHlsZXMuaHRtbFwiPlVzZWZ1bCBMYXlvdXQgQ1NTIENsYXNzZXM8L2E+XG4gICAgICoqXG4gICAgICogVG8gc3BlY2lmeSBhIFBsYXRmb3JtIEN1c3RvbSBXaW5kb3csIHByb3ZpZGUgYSBgdXJsYCBwcm9wZXJ0eSB3aGVuIGNyZWF0aW5nIGEgV2luZG93LlxuICAgICAqIElmIHlvdSBpbnRlbmQgdG8gcmVuZGVyIGEgTGF5b3V0IGluIHlvdXIgQ3VzdG9tIFdpbmRvdywgeW91IG11c3QgYWxzbyBzcGVjaWZ5IGFuIGBIVE1MRWxlbWVudGAgdGhhdCB0aGUgTGF5b3V0IHdpbGwgaW5qZWN0IGludG8gYW5kIHNldCBpdHMgYGlkYCBwcm9wZXJ0eSB0byBgXCJsYXlvdXQtY29udGFpbmVyXCJgLlxuICAgICAqXG4gICAgICogVGhlIGV4YW1wbGUgYmVsb3cgd2lsbCBjcmVhdGUgYSBQbGF0Zm9ybSBDdXN0b20gV2luZG93OlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAgICAgLy8gaW4gYW4gT3BlbkZpbiBhcHA6XG4gICAgICogICAgIGNvbnN0IHBsYXRmb3JtID0gZmluLlBsYXRmb3JtLmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogICAgIGNvbnN0IHdpbmRvd0NvbmZpZyA9XG4gICAgICogICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgdXJsOiBcImh0dHBzOi8vd3d3Lm15LWRvbWFpbi5jb20vbXktY3VzdG9tLXdpbmRvdy5odG1sXCIsIC8vIGhlcmUgd2UgcG9pbnQgdG8gd2hlcmUgdGhlIEN1c3RvbSBGcmFtZSBpcyBob3N0ZWQuXG4gICAgICogICAgICAgICAgICAgbGF5b3V0OiB7XG4gICAgICogICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcInN0YWNrXCIsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDogW1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBcImNvbXBvbmVudFwiLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50TmFtZTogXCJ2aWV3XCIsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRTdGF0ZToge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IFwiYXBwICMxXCIsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiBcImh0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L2NhbmFyeS9QbGF0Zm9ybS5odG1sXCJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJjb21wb25lbnRcIixcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudE5hbWU6IFwidmlld1wiLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50U3RhdGU6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiBcImFwcCAjMlwiLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogXCJodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9jYW5hcnkvUGxhdGZvcm0uaHRtbFwiXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBdXG4gICAgICogICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgIF1cbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICBwbGF0Zm9ybS5jcmVhdGVXaW5kb3cod2luZG93Q29uZmlnKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEhlcmUncyBhbiBleGFtcGxlIG9mIGEgbWluaW1hbGlzdCBDdXN0b20gUGxhdGZvcm0gV2luZG93IGltcGxlbWVudGF0aW9uOlxuICAgICAqIGBgYGh0bWxcbiAgICAgKiA8aHRtbD5cbiAgICAgKiAgICAgPGhlYWQ+XG4gICAgICogICAgICAgICA8bWV0YSBjaGFyc2V0PVwidXRmLThcIj5cbiAgICAgKiAgICAgICAgIDxtZXRhIG5hbWU9XCJ2aWV3cG9ydFwiIGNvbnRlbnQ9XCJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MVwiPlxuICAgICAqICAgICAgICAgPGxpbmsgcmVsPVwic3R5bGVzaGVldFwiIHR5cGU9XCJ0ZXh0L2Nzc1wiIGhyZWY9XCIuL3N0eWxlcy5jc3NcIj5cbiAgICAgKiAgICAgPC9oZWFkPlxuICAgICAqICAgICA8Ym9keT5cbiAgICAgKiAgICAgICAgIDxkaXYgaWQ9XCJvZi1mcmFtZS1tYWluXCI+XG4gICAgICogICAgICAgICAgICAgPGRpdiBpZD1cInRpdGxlLWJhclwiPlxuICAgICAqICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGl0bGUtYmFyLWRyYWdnYWJsZVwiPlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgPGRpdiBpZD1cInRpdGxlXCI+IFRoaXMgaXMgYSBjdXN0b20gZnJhbWUhIDwvZGl2PlxuICAgICAqICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgKiAgICAgICAgICAgICAgICAgPGRpdiBpZD1cImJ1dHRvbnMtd3JhcHBlclwiPlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJ1dHRvblwiIGlkPVwibWluaW1pemUtYnV0dG9uXCI+PC9kaXY+XG4gICAgICogICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYnV0dG9uXCIgaWQ9XCJleHBhbmQtYnV0dG9uXCI+PC9kaXY+XG4gICAgICogICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYnV0dG9uXCIgaWQ9XCJjbG9zZS1idXR0b25cIj48L2Rpdj5cbiAgICAgKiAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICogICAgICAgICAgICAgPC9kaXY+XG4gICAgICogICAgICAgICAgICAgPGRpdiBpZD1cImxheW91dC1jb250YWluZXJcIj48L2Rpdj4gPCEtLSBPcGVuRmluIGxheW91dCB3b3VsZCBiZSBpbmplY3RlZCBoZXJlIC0tPlxuICAgICAqICAgICAgICAgICAgIDxzY3JpcHQgc3JjPVwiLi9jdXN0b20tZnJhbWUuanNcIj48L3NjcmlwdD5cbiAgICAgKiAgICAgICAgIDwvZGl2PlxuICAgICAqICAgICA8L2JvZHk+XG4gICAgICogPC9odG1sPlxuICAgICAqIGBgYFxuICAgICAqIFlvdXIgQ3VzdG9tIFdpbmRvdyBjYW4gdXNlIGluLWRvbWFpbiByZXNvdXJjZXMgZm9yIGZ1cnRoZXIgY3VzdG9taXphdGlvbiAoc3VjaCBhcyBDU1MsIHNjcmlwdHMsIGV0Yy4pLjxicj5cbiAgICAgKiBGb3IgYSBsaXN0IG9mIGNvbW1vbiBMYXlvdXQgQ1NTIGNsYXNzZXMgeW91IGNhbiBvdmVycmlkZSBpbiB5b3VyIHN0eWxlc2hlZXQsIHNlZSA8YSBocmVmPVwidHV0b3JpYWwtbGF5b3V0U3R5bGVzLmh0bWxcIj5Vc2VmdWwgTGF5b3V0IENTUyBDbGFzc2VzPC9hPlxuICAgICAqXG4gICAgICogVGhlIGV4YW1wbGUgYWJvdmUgd2lsbCByZXF1aXJlIHRoZSBgYm9keWAgZWxlbWVudCB0byBoYXZlIGBoZWlnaHQ6IDEwMCU7YCBzZXQgaW4gb3JkZXIgdG8gcmVuZGVyIHRoZSBsYXlvdXQgY29ycmVjdGx5LlxuICAgICAqL1xuICAgIGFzeW5jIGNyZWF0ZVdpbmRvdyhvcHRpb25zKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwbGF0Zm9ybS1jcmVhdGUtd2luZG93JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcbiAgICAgICAgaWYgKCFvcHRpb25zLnJlYXNvbikge1xuICAgICAgICAgICAgb3B0aW9ucy5yZWFzb24gPSAnYXBpLWNhbGwnO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdjcmVhdGUtdmlldy1jb250YWluZXInLCBvcHRpb25zKTtcbiAgICAgICAgaWYgKCFyZXNwb25zZSB8fCAoMCwgdmFsaWRhdGVfMSQxLnZhbGlkYXRlSWRlbnRpdHkpKHJlc3BvbnNlLmlkZW50aXR5KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBXaGVuIG92ZXJ3cml0aW5nIHRoZSBjcmVhdGVXaW5kb3cgY2FsbCwgcGxlYXNlIHJldHVybiBhbiBvYmplY3QgdGhhdCBoYXMgYSB2YWxpZCAnaWRlbnRpdHknIHByb3BlcnR5OiAke0pTT04uc3RyaW5naWZ5KHJlc3BvbnNlKX1gKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IGlkZW50aXR5IH0gPSByZXNwb25zZTtcbiAgICAgICAgY29uc3QgcmVzID0gdGhpcy5maW4uV2luZG93LndyYXBTeW5jKGlkZW50aXR5KTtcbiAgICAgICAgLy8gd2UgYWRkIHRoZSBpZGVudGl0eSBhdCB0aGUgdG9wIGxldmVsIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbiAgICAgICAgcmVzLm5hbWUgPSBpZGVudGl0eS5uYW1lO1xuICAgICAgICByZXMudXVpZCA9IGlkZW50aXR5LnV1aWQ7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENsb3NlcyBjdXJyZW50IHBsYXRmb3JtLCBhbGwgaXRzIHdpbmRvd3MsIGFuZCB0aGVpciB2aWV3cy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50KCk7XG4gICAgICogcGxhdGZvcm0ucXVpdCgpO1xuICAgICAqIC8vIEFsbCB3aW5kb3dzL3ZpZXdzIGluIGN1cnJlbnQgbGF5b3V0IHBsYXRmb3JtIHdpbGwgY2xvc2UgYW5kIHBsYXRmb3JtIHdpbGwgc2h1dCBkb3duXG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgcXVpdCgpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLXF1aXQnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xuICAgICAgICByZXR1cm4gY2xpZW50LmRpc3BhdGNoKCdxdWl0Jyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENsb3NlcyBhIHNwZWNpZmllZCB2aWV3IGluIGEgdGFyZ2V0IHdpbmRvdy5cbiAgICAgKiBAcGFyYW0gdmlld0lkZW50aXR5IFZpZXcgaWRlbnRpdHlcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBsZXQgd2luZG93SWRlbnRpdHk7XG4gICAgICogaWYgKGZpbi5tZS5pc1dpbmRvdykge1xuICAgICAqICAgICB3aW5kb3dJZGVudGl0eSA9IGZpbi5tZS5pZGVudGl0eTtcbiAgICAgKiB9IGVsc2UgaWYgKGZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSAoYXdhaXQgZmluLm1lLmdldEN1cnJlbnRXaW5kb3coKSkuaWRlbnRpdHk7XG4gICAgICogfSBlbHNlIHtcbiAgICAgKiAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgcnVubmluZyBpbiBhIHBsYXRmb3JtIFZpZXcgb3IgV2luZG93Jyk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogY29uc3Qgdmlld09wdGlvbnMgPSB7XG4gICAgICogICAgIG5hbWU6ICd0ZXN0X3ZpZXcnLFxuICAgICAqICAgICB1cmw6ICdodHRwczovL2V4YW1wbGUuY29tJ1xuICAgICAqIH07XG4gICAgICpcbiAgICAgKiBmdW5jdGlvbiBzbGVlcChtcykge1xuICAgICAqICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudCgpO1xuICAgICAqXG4gICAgICogYXdhaXQgcGxhdGZvcm0uY3JlYXRlVmlldyh2aWV3T3B0aW9ucywgd2luZG93SWRlbnRpdHkpO1xuICAgICAqIC8vIGEgbmV3IHZpZXcgd2lsbCBub3cgc2hvdyBpbiB0aGUgY3VycmVudCB3aW5kb3dcbiAgICAgKlxuICAgICAqIGF3YWl0IHNsZWVwKDUwMDApO1xuICAgICAqXG4gICAgICogY29uc3Qgdmlld0lkZW50aXR5ID0geyB1dWlkOiB3aW5kb3dJZGVudGl0eS51dWlkLCBuYW1lOiAndGVzdF92aWV3J307XG4gICAgICogcGxhdGZvcm0uY2xvc2VWaWV3KHZpZXdJZGVudGl0eSk7XG4gICAgICogLy8gdGhlIHZpZXcgd2lsbCBub3cgY2xvc2VcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBjbG9zZVZpZXcodmlld0lkZW50aXR5KSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwbGF0Zm9ybS1jbG9zZS12aWV3JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcbiAgICAgICAgYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdjbG9zZS12aWV3Jywge1xuICAgICAgICAgICAgdmlldzogdmlld0lkZW50aXR5XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiAqKipERVBSRUNBVEVEIC0gcGxlYXNlIHVzZSB7QGxpbmsgUGxhdGZvcm0uY3JlYXRlVmlldyBQbGF0Zm9ybS5jcmVhdGVWaWV3fS4qKipcbiAgICAgKiBSZXBhcmVudHMgYSBzcGVjaWZpZWQgdmlldyBpbiBhIG5ldyB0YXJnZXQgd2luZG93LlxuICAgICAqIEBwYXJhbSB2aWV3SWRlbnRpdHkgVmlldyBpZGVudGl0eVxuICAgICAqIEBwYXJhbSB0YXJnZXQgbmV3IG93bmVyIHdpbmRvdyBpZGVudGl0eVxuICAgICAqXG4gICAgICovXG4gICAgYXN5bmMgcmVwYXJlbnRWaWV3KHZpZXdJZGVudGl0eSwgdGFyZ2V0KSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUud2FybignUGxhdGZvcm0ucmVwYXJlbnRWaWV3IGhhcyBiZWVuIGRlcHJlY2F0ZWQsIHBsZWFzZSB1c2UgUGxhdGZvcm0uY3JlYXRlVmlldycpO1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tcmVwYXJlbnQtdmlldycsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRWaWV3SWRlbnRpdHkgPSB7XG4gICAgICAgICAgICAuLi52aWV3SWRlbnRpdHksXG4gICAgICAgICAgICB1dWlkOiB2aWV3SWRlbnRpdHkudXVpZCA/PyB0aGlzLmlkZW50aXR5LnV1aWRcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgdmlldyA9IGF3YWl0IHRoaXMuZmluLlZpZXcud3JhcChub3JtYWxpemVkVmlld0lkZW50aXR5KTtcbiAgICAgICAgY29uc3Qgdmlld09wdGlvbnMgPSBhd2FpdCB2aWV3LmdldE9wdGlvbnMoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlVmlldyh2aWV3T3B0aW9ucywgdGFyZ2V0KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIHNuYXBzaG90IG9mIHRoZSBwbGF0Zm9ybSBpbiBpdHMgY3VycmVudCBzdGF0ZS4gWW91IGNhbiBwYXNzIHRoZSByZXR1cm5pbmcgb2JqZWN0IHRvXG4gICAgICogW1BsYXRmb3JtLmFwcGx5U25hcHNob3Rde0BsaW5rIFBsYXRmb3JtI2FwcGx5U25hcHNob3R9IHRvIGxhdW5jaCBpdC5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIFRoZSBzbmFwc2hvdCB3aWxsIGluY2x1ZGUgZGV0YWlscyBzdWNoIGFzIGFuIFtJU08gZm9ybWF0XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9JU09fODYwMSlcbiAgICAgKiB0aW1lc3RhbXAgb2Ygd2hlbiB0aGUgc25hcHNob3Qgd2FzIHRha2VuLCBPcGVuRmluIHJ1bnRpbWUgdmVyc2lvbiB0aGUgcGxhdGZvcm0gaXMgcnVubmluZyBvbiwgbW9uaXRvciBpbmZvcm1hdGlvblxuICAgICAqIGFuZCB0aGUgbGlzdCBvZiBjdXJyZW50bHkgcnVubmluZyB3aW5kb3dzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLmdldEN1cnJlbnQoKTtcbiAgICAgKiBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHBsYXRmb3JtLmdldFNuYXBzaG90KCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZ2V0U25hcHNob3QoKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwbGF0Zm9ybS1nZXQtc25hcHNob3QnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xuICAgICAgICByZXR1cm4gY2xpZW50LmRpc3BhdGNoKCdnZXQtc25hcHNob3QnKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogKipOT1RFKio6IEludGVybmFsIHVzZSBvbmx5LiBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbWFuYWdlIHRoZSBzdGF0ZSBvZiBpbmRpdmlkdWFsIHZpZXdzLlxuICAgICAqXG4gICAgICogUmV0dXJucyBhIHNuYXBzaG90IG9mIGEgc2luZ2xlIHZpZXcncyBvcHRpb25zIGluIGl0cyBjdXJyZW50IHN0YXRlLlxuICAgICAqXG4gICAgICogQ2FuIGJlIHVzZWQgdG8gcmVzdG9yZSBhIHZpZXcgdG8gYSBwcmV2aW91cyBzdGF0ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB2aWV3SWRlbnRpdHkgVmlldyBpZGVudGl0eVxuICAgICAqXG4gICAgICogQGludGVybmFsXG4gICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAqIEByZW1hcmtzIFRoaXMgc2xpY2Ugb2Ygc25hcHNob3Qgc3RhdGUgaXMgZXF1aXZhbGVudCB0byB3aGF0IGlzIHN0b3JlZCBhcyBgY29tcG9uZW50U3RhdGVgIGZvciB2aWV3c1xuICAgICAqIHdoZW4gY2FwdHVyaW5nIHBsYXRmb3JtIHN0YXRlIHVzaW5nIFtQbGF0Zm9ybS5nZXRTbmFwc2hvdF17QGxpbmsgUGxhdGZvcm0jZ2V0U25hcHNob3R9LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLmdldEN1cnJlbnQoKTtcbiAgICAgKiBjb25zdCB1cmwgPSAnaHR0cHM6Ly9nb29nbGUuY29tJztcbiAgICAgKiBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcuY3JlYXRlKHsgbmFtZTogJ215LXZpZXcnLCB0YXJnZXQ6IGZpbi5tZS5pZGVudGl0eSwgdXJsIH0pO1xuICAgICAqXG4gICAgICogYXdhaXQgdmlldy5uYXZpZ2F0ZSh1cmwpO1xuICAgICAqXG4gICAgICogY29uc3Qgdmlld1N0YXRlID0gYXdhaXQgcGxhdGZvcm0uZ2V0Vmlld1NuYXBzaG90KHZpZXcuaWRlbnRpdHkpO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2codmlld1N0YXRlKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBnZXRWaWV3U25hcHNob3Qodmlld0lkZW50aXR5KSB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XG4gICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2dldC12aWV3LXNuYXBzaG90JywgeyB2aWV3SWRlbnRpdHkgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBzbmFwc2hvdCB0byBhIHJ1bm5pbmcgUGxhdGZvcm0uXG4gICAgICogUmVxdWVzdGVkIHNuYXBzaG90IG11c3QgYmUgYSB2YWxpZCBTbmFwc2hvdCBvYmplY3QsIG9yIGEgdXJsIG9yIGZpbGVwYXRoIHRvIHN1Y2ggYW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQ2FuIG9wdGlvbmFsbHkgY2xvc2UgZXhpc3Rpbmcgd2luZG93cyBhbmQgb3ZlcndyaXRlIGN1cnJlbnQgcGxhdGZvcm0gc3RhdGUgd2l0aCB0aGF0IG9mIGEgc25hcHNob3QuXG4gICAgICpcbiAgICAgKiBUaGUgZnVuY3Rpb24gYWNjZXB0cyBlaXRoZXIgYSBzbmFwc2hvdCB0YWtlbiB1c2luZyB7QGxpbmsgUGxhdGZvcm0jZ2V0U25hcHNob3QgZ2V0U25hcHNob3R9LFxuICAgICAqIG9yIGEgdXJsIG9yIGZpbGVwYXRoIHRvIGEgc25hcHNob3QgSlNPTiBvYmplY3QuXG4gICAgICogQHBhcmFtIHJlcXVlc3RlZFNuYXBzaG90IFNuYXBzaG90IHRvIGFwcGx5LCBvciBhIHVybCBvciBmaWxlcGF0aC5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25hbCBwYXJhbWV0ZXJzIHRvIHNwZWNpZnkgd2hldGhlciBleGlzdGluZyB3aW5kb3dzIHNob3VsZCBiZSBjbG9zZWQuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBXaWxsIGNyZWF0ZSBhbnkgd2luZG93cyBhbmQgdmlld3MgdGhhdCBhcmUgbm90IHJ1bm5pbmcgYnV0IGFyZSBwYXNzZWQgaW4gdGhlIHNuYXBzaG90IG9iamVjdC4gQW55IFZpZXdcbiAgICAgKiBzcGVjaWZpZWQgaW4gdGhlIHNuYXBzaG90IGlzIGFzc2lnbmVkIGEgcmFuZG9tbHkgZ2VuZXJhdGVkIG5hbWUgdG8gYXZvaWQgY29sbGlzaW9ucy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiAvLyBHZXQgYSB3cmFwcGVkIGxheW91dCBwbGF0Zm9ybSBpbnN0YW5jZVxuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLmdldEN1cnJlbnQoKTtcbiAgICAgKlxuICAgICAqIGNvbnN0IHNuYXBzaG90ID0ge1xuICAgICAqICAgICB3aW5kb3dzOiBbXG4gICAgICogICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgbGF5b3V0OiB7XG4gICAgICogICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnc3RhY2snLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2NvbXBvbmVudCcsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnROYW1lOiAndmlldycsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRTdGF0ZToge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICdjb21wb25lbnRfWCcsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly93d3cub3BlbmZpbi5jbydcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2NvbXBvbmVudCcsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnROYW1lOiAndmlldycsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRTdGF0ZToge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICdjb21wb25lbnRfWScsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9lbWJlZC13ZWIvY2hhcnQuaHRtbCdcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIF1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgXVxuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgIH1cbiAgICAgKiAgICAgXVxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHBsYXRmb3JtLmFwcGx5U25hcHNob3Qoc25hcHNob3QpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogSW4gcGxhY2Ugb2YgYSBzbmFwc2hvdCBvYmplY3QsIGBhcHBseVNuYXBzaG90YCBjYW4gdGFrZSBhIHVybCBvciBmaWxlcGF0aCBhbmQgdG8gcmV0cmlldmUgYSBKU09OIHNuYXBzaG90LlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50KCk7XG4gICAgICogcGxhdGZvcm0uYXBwbHlTbmFwc2hvdCgnaHR0cHM6Ly9hcGkuanNvbmJpbi5pby9iLzVlNmY5MDNlZjQzMzFlNjgxZmMxMjMxZC8xJyk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBPcHRpb25hbGx5LCBgYXBwbHlTbmFwc2hvdGAgY2FuIGNsb3NlIGV4aXN0aW5nIHdpbmRvd3MgYW5kIHJlc3RvcmUgYSBQbGF0Zm9ybSB0byBhIHByZXZpb3VzbHkgc2F2ZWQgc3RhdGUuXG4gICAgICogVGhpcyBpcyBhY2NvbXBsaXNoZWQgYnkgcHJvdmlkaW5nIGB7IGNsb3NlRXhpc3RpbmdXaW5kb3dzOiB0cnVlIH1gIGFzIGFuIG9wdGlvbi5cbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogLy8gR2V0IGEgd3JhcHBlZCBsYXlvdXQgcGxhdGZvcm0gaW5zdGFuY2VcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50KCk7XG4gICAgICpcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBhZGRWaWV3VG9XaW5kb3cod2luSWQpIHtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHBsYXRmb3JtLmNyZWF0ZVZpZXcoe1xuICAgICAqICAgICAgICAgbmFtZTogJ3Rlc3Rfdmlld18zJyxcbiAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vb3BlbmZpbi5jbydcbiAgICAgKiAgICAgfSwgd2luSWQpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbmRvd1dpdGhUd29WaWV3cygpIHtcbiAgICAgKiAgICAgY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudCgpO1xuICAgICAqXG4gICAgICogICAgIHJldHVybiBwbGF0Zm9ybS5jcmVhdGVXaW5kb3coe1xuICAgICAqICAgICAgICAgbGF5b3V0OiB7XG4gICAgICogICAgICAgICAgICAgY29udGVudDogW1xuICAgICAqICAgICAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICB0eXBlOiAnc3RhY2snLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgY29udGVudDogW1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2NvbXBvbmVudCcsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudE5hbWU6ICd2aWV3JyxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50U3RhdGU6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICd0ZXN0X3ZpZXdfMScsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmw6ICdodHRwczovL2V4YW1wbGUuY29tJ1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjb21wb25lbnQnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnROYW1lOiAndmlldycsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudFN0YXRlOiB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAndGVzdF92aWV3XzInLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly95YWhvby5jb20nXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICBdXG4gICAgICogICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICBdXG4gICAgICogICAgICAgICB9XG4gICAgICogICAgIH0pO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGNvbnN0IHdpbiA9IGF3YWl0IGNyZWF0ZVdpbmRvd1dpdGhUd29WaWV3cygpO1xuICAgICAqIC8vIC4uLiB5b3Ugd2lsbCBub3cgc2VlIGEgbmV3IHdpbmRvdyB3aXRoIHR3byB2aWV3cyBpbiBpdFxuICAgICAqXG4gICAgICogLy8gd2UgdGFrZSBhIHNuYXBzaG90IG9mIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBhcHAsIGJlZm9yZSBjaGFuZ2luZyBpdFxuICAgICAqIGNvbnN0IHNuYXBzaG90T2ZJbml0aWFsQXBwU3RhdGUgPSBhd2FpdCBwbGF0Zm9ybS5nZXRTbmFwc2hvdCgpO1xuICAgICAqXG4gICAgICogLy8gbm93IGxldCdzIGNoYW5nZSB0aGUgc3RhdGUgb2YgdGhlIGFwcDpcbiAgICAgKiBhd2FpdCBhZGRWaWV3VG9XaW5kb3cod2luLmlkZW50aXR5KTtcbiAgICAgKiAvLyAuLi4gdGhlIHdpbmRvdyBub3cgaGFzIHRocmVlIHZpZXdzIGluIGl0XG4gICAgICpcbiAgICAgKiBhd2FpdCBwbGF0Zm9ybS5hcHBseVNuYXBzaG90KHNuYXBzaG90T2ZJbml0aWFsQXBwU3RhdGUsIHsgY2xvc2VFeGlzdGluZ1dpbmRvd3M6IHRydWUgfSk7XG4gICAgICogLy8gLi4uIHRoZSB3aW5kb3cgd2lsbCByZXZlcnQgdG8gcHJldmlvdXMgc3RhdGUsIHdpdGgganVzdCB0d28gdmlld3NcbiAgICAgKlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGFwcGx5U25hcHNob3QocmVxdWVzdGVkU25hcHNob3QsIG9wdGlvbnMpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLWFwcGx5LXNuYXBzaG90JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgZXJyTXNnID0gJ1JlcXVlc3RlZCBzbmFwc2hvdCBtdXN0IGJlIGEgdmFsaWQgU25hcHNob3Qgb2JqZWN0LCBvciBhIHVybCBvciBmaWxlcGF0aCB0byBzdWNoIGFuIG9iamVjdC4nO1xuICAgICAgICBsZXQgc25hcHNob3Q7XG4gICAgICAgIGlmICh0eXBlb2YgcmVxdWVzdGVkU25hcHNob3QgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBGZXRjaCBhbmQgcGFyc2Ugc25hcHNob3RcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLl9jaGFubmVsLndpcmUuc2VuZEFjdGlvbignZ2V0LWFwcGxpY2F0aW9uLW1hbmlmZXN0Jywge1xuICAgICAgICAgICAgICAgICAgICBtYW5pZmVzdFVybDogcmVxdWVzdGVkU25hcHNob3RcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICBzbmFwc2hvdCA9IHJlc3BvbnNlLnBheWxvYWQuZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXJyTXNnfTogJHtlcnJ9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBzbmFwc2hvdCA9IHJlcXVlc3RlZFNuYXBzaG90O1xuICAgICAgICB9XG4gICAgICAgIGlmICghc25hcHNob3Qud2luZG93cykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVyck1zZyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcbiAgICAgICAgYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdhcHBseS1zbmFwc2hvdCcsIHtcbiAgICAgICAgICAgIHNuYXBzaG90LFxuICAgICAgICAgICAgb3B0aW9uc1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEZldGNoZXMgYSBKU09OIG1hbmlmZXN0IHVzaW5nIHRoZSBicm93c2VyIHByb2Nlc3MgYW5kIHJldHVybnMgYSBKYXZhc2NyaXB0IG9iamVjdC5cbiAgICAgKiBDYW4gYmUgb3ZlcndyaXR0ZW4gdXNpbmcge0BsaW5rIFBsYXRmb3JtLlBsYXRmb3JtTW9kdWxlLmluaXQgUGxhdGZvcm0uaW5pdH0uXG4gICAgICogQHBhcmFtIG1hbmlmZXN0VXJsIFRoZSBVUkwgb2YgdGhlIG1hbmlmZXN0IHRvIGZldGNoLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgQ2FuIGJlIG92ZXJ3cml0dGVuIHVzaW5nIHtAbGluayBQbGF0Zm9ybSNpbml0IFBsYXRmb3JtLmluaXR9LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKiBjb25zdCBtYW5pZmVzdCA9IGF3YWl0IHBsYXRmb3JtLmZldGNoTWFuaWZlc3QoJ2h0dHBzOi8vd3d3LnBhdGgtdG8tbWFuaWZlc3QuY29tL2FwcC5qc29uJyk7XG4gICAgICogY29uc29sZS5sb2cobWFuaWZlc3QpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGZldGNoTWFuaWZlc3QobWFuaWZlc3RVcmwpIHtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcbiAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgncGxhdGZvcm0tZmV0Y2gtbWFuaWZlc3QnLCB7IG1hbmlmZXN0VXJsIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYSBtYW5pZmVzdCBieSB1cmwgYW5kIGxhdW5jaGVzIGEgbGVnYWN5IGFwcGxpY2F0aW9uIG1hbmlmZXN0IG9yIHNuYXBzaG90IGludG8gdGhlIHBsYXRmb3JtLiAgUmV0dXJucyBhIHByb21pc2UgdGhhdFxuICAgICAqIHJlc29sdmVzIHRvIHRoZSB3cmFwcGVkIFBsYXRmb3JtLlxuICAgICAqIEBwYXJhbSBtYW5pZmVzdFVybCAtIFRoZSBVUkwgb2YgdGhlIG1hbmlmZXN0IHRoYXQgd2lsbCBiZSBsYXVuY2hlZCBpbnRvIHRoZSBwbGF0Zm9ybS4gIElmIHRoaXMgYXBwIG1hbmlmZXN0XG4gICAgICogY29udGFpbnMgYSBzbmFwc2hvdCwgdGhhdCB3aWxsIGJlIGxhdW5jaGVkIGludG8gdGhlIHBsYXRmb3JtLiAgSWYgbm90LCB0aGUgYXBwbGljYXRpb24gZGVzY3JpYmVkIGluIHN0YXJ0dXBfYXBwIG9wdGlvbnNcbiAgICAgKiB3aWxsIGJlIGxhdW5jaGVkIGludG8gdGhlIHBsYXRmb3JtLiBUaGUgYXBwbGljYWJsZSBzdGFydHVwX2FwcCBvcHRpb25zIHdpbGwgYmVjb21lIHtAbGluayBPcGVuRmluLlZpZXdDcmVhdGlvbk9wdGlvbnMgVmlldyBPcHRpb25zfS5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIElmIHRoZSBhcHAgbWFuaWZlc3QgY29udGFpbnMgYSBzbmFwc2hvdCwgdGhhdCB3aWxsIGJlIGxhdW5jaGVkIGludG8gdGhlIHBsYXRmb3JtLiAgSWYgbm90LCB0aGVcbiAgICAgKiBhcHBsaWNhdGlvbiBkZXNjcmliZWQgaW4gc3RhcnR1cF9hcHAgb3B0aW9ucyB3aWxsIGJlIGxhdW5jaGVkIGludG8gdGhlIHBsYXRmb3JtIGFzIGEgd2luZG93IHdpdGggYSBzaW5nbGUgdmlldy5cbiAgICAgKiBUaGUgYXBwbGljYWJsZSBzdGFydHVwX2FwcCBvcHRpb25zIHdpbGwgYmVjb21lIFZpZXcgT3B0aW9ucy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiB0cnkge1xuICAgICAqICAgICBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqICAgICBhd2FpdCBwbGF0Zm9ybS5sYXVuY2hDb250ZW50TWFuaWZlc3QoJ2h0dHA6Ly9sb2NhbGhvc3Q6NTU1NS9hcHAuanNvbicpO1xuICAgICAqICAgICBjb25zb2xlLmxvZyhgY29udGVudCBsYXVuY2hlZCBzdWNjZXNzZnVsbHkgaW50byBwbGF0Zm9ybWApO1xuICAgICAqIH0gY2F0Y2goZSkge1xuICAgICAqICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAqIH1cbiAgICAgKiAvLyBGb3IgYSBsb2NhbCBtYW5pZmVzdCBmaWxlOlxuICAgICAqIHRyeSB7XG4gICAgICogICAgIGNvbnN0IHBsYXRmb3JtID0gZmluLlBsYXRmb3JtLmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogICAgIHBsYXRmb3JtLmxhdW5jaENvbnRlbnRNYW5pZmVzdCgnZmlsZTovLy9DOi9zb21lZm9sZGVyL2FwcC5qc29uJyk7XG4gICAgICogICAgIGNvbnNvbGUubG9nKGBjb250ZW50IGxhdW5jaGVkIHN1Y2Nlc3NmdWxseSBpbnRvIHBsYXRmb3JtYCk7XG4gICAgICogfSBjYXRjaChlKSB7XG4gICAgICogICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEBleHBlcmltZW50YWxcbiAgICAgKi9cbiAgICBhc3luYyBsYXVuY2hDb250ZW50TWFuaWZlc3QobWFuaWZlc3RVcmwpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLWxhdW5jaC1jb250ZW50LW1hbmlmZXN0JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xuICAgICAgICBjb25zdCBtYW5pZmVzdCA9IGF3YWl0IHRoaXMuZmV0Y2hNYW5pZmVzdChtYW5pZmVzdFVybCk7XG4gICAgICAgIGNsaWVudC5kaXNwYXRjaCgnbGF1bmNoLWludG8tcGxhdGZvcm0nLCB7IG1hbmlmZXN0LCBtYW5pZmVzdFVybCB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgY29udGV4dCBvZiBhIGhvc3Qgd2luZG93LiBUaGUgY29udGV4dCB3aWxsIGJlIGF2YWlsYWJsZSB0byB0aGUgd2luZG93IGl0c2VsZiwgYW5kIHRvIGl0cyBjaGlsZCBWaWV3cy4gSXQgd2lsbCBiZSBzYXZlZCBpbiBhbnkgcGxhdGZvcm0gc25hcHNob3RzLlxuICAgICAqIEl0IGNhbiBiZSByZXRyaWV2ZWQgdXNpbmcge0BsaW5rIFBsYXRmb3JtI2dldFdpbmRvd0NvbnRleHQgZ2V0V2luZG93Q29udGV4dH0uXG4gICAgICogQHBhcmFtIGNvbnRleHQgLSBBIGZpZWxkIHdoZXJlIHNlcmlhbGl6YWJsZSBjb250ZXh0IGRhdGEgY2FuIGJlIHN0b3JlZCB0byBiZSBzYXZlZCBpbiBwbGF0Zm9ybSBzbmFwc2hvdHMuXG4gICAgICogQHBhcmFtIHRhcmdldCAtIEEgdGFyZ2V0IHdpbmRvdyBvciB2aWV3IG1heSBvcHRpb25hbGx5IGJlIHByb3ZpZGVkLiBJZiBubyB0YXJnZXQgaXMgcHJvdmlkZWQsIHRoZSB1cGRhdGUgd2lsbCBiZSBhcHBsaWVkXG4gICAgICogdG8gdGhlIGN1cnJlbnQgd2luZG93IChpZiBjYWxsZWQgZnJvbSBhIFdpbmRvdykgb3IgdGhlIGN1cnJlbnQgaG9zdCB3aW5kb3cgKGlmIGNhbGxlZCBmcm9tIGEgVmlldykuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBUaGUgY29udGV4dCBkYXRhIG11c3QgYmUgc2VyaWFsaXphYmxlLiAgVGhpcyBjYW4gb25seSBiZSBjYWxsZWQgZnJvbSBhIHdpbmRvdyBvciB2aWV3IHRoYXQgaGFzIGJlZW4gbGF1bmNoZWQgaW50byBhXG4gICAgICogcGxhdGZvcm0uXG4gICAgICogVGhpcyBtZXRob2QgY2FuIGJlIGNhbGxlZCBmcm9tIHRoZSB3aW5kb3cgaXRzZWxmLCBvciBmcm9tIGFueSBjaGlsZCB2aWV3LiBDb250ZXh0IGRhdGEgaXMgc2hhcmVkIGJ5IGFsbFxuICAgICAqIGVudGl0aWVzIHdpdGhpbiBhIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogU2V0dGluZyBvd24gY29udGV4dDpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gZmluLlBsYXRmb3JtLmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogY29uc3QgY29udGV4dERhdGEgPSB7XG4gICAgICogICAgIHNlY3VyaXR5OiAnU1RPQ0snLFxuICAgICAqICAgICBjdXJyZW50VmlldzogJ2RldGFpbGVkJ1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGF3YWl0IHBsYXRmb3JtLnNldFdpbmRvd0NvbnRleHQoY29udGV4dERhdGEpO1xuICAgICAqIC8vIENvbnRleHQgb2YgY3VycmVudCB3aW5kb3cgaXMgbm93IHNldCB0byBgY29udGV4dERhdGFgXG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBTZXR0aW5nIHRoZSBjb250ZXh0IG9mIGFub3RoZXIgd2luZG93IG9yIHZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIGNvbnN0IGNvbnRleHREYXRhID0ge1xuICAgICAqICAgICBzZWN1cml0eTogJ1NUT0NLJyxcbiAgICAgKiAgICAgY3VycmVudFZpZXc6ICdkZXRhaWxlZCdcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBjb25zdCB3aW5kb3dPclZpZXdJZGVudGl0eSA9IHsgdXVpZDogZmluLm1lLnV1aWQsIG5hbWU6ICduYW1lT2ZXaW5kb3dPclZpZXcnIH07XG4gICAgICogYXdhaXQgcGxhdGZvcm0uc2V0V2luZG93Q29udGV4dChjb250ZXh0RGF0YSwgd2luZG93T3JWaWV3SWRlbnRpdHkpO1xuICAgICAqIC8vIENvbnRleHQgb2YgdGhlIHRhcmdldCB3aW5kb3cgb3IgdmlldyBpcyBub3cgc2V0IHRvIGBjb250ZXh0RGF0YWBcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEEgdmlldyBjYW4gbGlzdGVuIHRvIGNoYW5nZXMgdG8gaXRzIGhvc3Qgd2luZG93J3MgY29udGV4dCBieSBsaXN0ZW5pbmcgdG8gdGhlIGBob3N0LWNvbnRleHQtY2hhbmdlZGAgZXZlbnQuXG4gICAgICogVGhpcyBldmVudCB3aWxsIGZpcmUgd2hlbiBhIGhvc3Qgd2luZG93J3MgY29udGV4dCBpcyB1cGRhdGVkIG9yIHdoZW4gdGhlIHZpZXcgaXMgcmVwYXJlbnRlZCB0byBhIG5ldyB3aW5kb3c6XG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIC8vIEZyb20gYSB2aWV3XG4gICAgICogY29uc3QgY29udGV4dENoYW5nZUhhbmRsZXIgPSAoeyBjb250ZXh0IH0pID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ0hvc3Qgd2luZG93XFwncyBjb250ZXh0IGhhcyBjaGFuZ2VkLiBOZXcgY29udGV4dCBkYXRhOicsIGNvbnRleHQpO1xuICAgICAqICAgICAvLyByZWFjdCB0byBuZXcgY29udGV4dCBkYXRhIGhlcmVcbiAgICAgKiB9XG4gICAgICogYXdhaXQgZmluLm1lLm9uKCdob3N0LWNvbnRleHQtY2hhbmdlZCcsIGNvbnRleHRDaGFuZ2VIYW5kbGVyKTtcbiAgICAgKlxuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogY29uc3QgY29udGV4dERhdGEgPSB7XG4gICAgICogICAgIHNlY3VyaXR5OiAnU1RPQ0snLFxuICAgICAqICAgICBjdXJyZW50VmlldzogJ2RldGFpbGVkJ1xuICAgICAqIH1cbiAgICAgKiBwbGF0Zm9ybS5zZXRXaW5kb3dDb250ZXh0KGNvbnRleHREYXRhKSAvLyBjb250ZXh0Q2hhbmdlSGFuZGxlciB3aWxsIGxvZyB0aGUgbmV3IGNvbnRleHRcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFRvIGxpc3RlbiB0byBhIHdpbmRvdydzIGNvbnRleHQgdXBkYXRlcywgdXNlIHRoZSBgY29udGV4dC1jaGFuZ2VkYCBldmVudDpcbiAgICAgKiBgYGBqc1xuICAgICAqIC8vIEZyb20gYSB3aW5kb3dcbiAgICAgKiBjb25zdCBjb250ZXh0Q2hhbmdlSGFuZGxlciA9ICh7IGNvbnRleHQgfSkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnVGhpcyB3aW5kb3dcXCdzIGNvbnRleHQgaGFzIGNoYW5nZWQuIE5ldyBjb250ZXh0IGRhdGE6JywgY29udGV4dCk7XG4gICAgICogICAgIC8vIHJlYWN0IHRvIG5ldyBjb250ZXh0IGRhdGEgaGVyZVxuICAgICAqIH1cbiAgICAgKiBhd2FpdCBmaW4ubWUub24oJ2NvbnRleHQtY2hhbmdlZCcsIGNvbnRleHRDaGFuZ2VIYW5kbGVyKTtcbiAgICAgKlxuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogY29uc3QgY29udGV4dERhdGEgPSB7XG4gICAgICogICAgIHNlY3VyaXR5OiAnU1RPQ0snLFxuICAgICAqICAgICBjdXJyZW50VmlldzogJ2RldGFpbGVkJ1xuICAgICAqIH1cbiAgICAgKiBwbGF0Zm9ybS5zZXRXaW5kb3dDb250ZXh0KGNvbnRleHREYXRhKSAvLyBjb250ZXh0Q2hhbmdlSGFuZGxlciB3aWxsIGxvZyB0aGUgbmV3IGNvbnRleHRcbiAgICAgKiBgYGBcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICovXG4gICAgYXN5bmMgc2V0V2luZG93Q29udGV4dChjb250ZXh0ID0ge30sIHRhcmdldCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tc2V0LXdpbmRvdy1jb250ZXh0JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCFjb250ZXh0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BsZWFzZSBwcm92aWRlIGEgc2VyaWFsaXphYmxlIG9iamVjdCBvciBzdHJpbmcgdG8gc2V0IHRoZSBjb250ZXh0LicpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XG4gICAgICAgIGNvbnN0IHsgZW50aXR5VHlwZSB9ID0gdGFyZ2V0ID8gYXdhaXQgdGhpcy5maW4uU3lzdGVtLmdldEVudGl0eUluZm8odGFyZ2V0LnV1aWQsIHRhcmdldC5uYW1lKSA6IHRoaXMuZmluLm1lO1xuICAgICAgICBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ3NldC13aW5kb3ctY29udGV4dCcsIHtcbiAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgICBlbnRpdHlUeXBlLFxuICAgICAgICAgICAgdGFyZ2V0OiB0YXJnZXQgfHwgeyB1dWlkOiB0aGlzLmZpbi5tZS51dWlkLCBuYW1lOiB0aGlzLmZpbi5tZS5uYW1lIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY29udGV4dCBjb250ZXh0IG9mIGEgaG9zdCB3aW5kb3cgdGhhdCB3YXMgcHJldmlvdXNseSBzZXQgdXNpbmcge0BsaW5rIFBsYXRmb3JtI3NldFdpbmRvd0NvbnRleHQgc2V0V2luZG93Q29udGV4dH0uXG4gICAgICogVGhlIGNvbnRleHQgd2lsbCBiZSBzYXZlZCBpbiBhbnkgcGxhdGZvcm0gc25hcHNob3RzLiAgUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgY29udGV4dC5cbiAgICAgKiBAcGFyYW0gdGFyZ2V0IC0gQSB0YXJnZXQgd2luZG93IG9yIHZpZXcgbWF5IG9wdGlvbmFsbHkgYmUgcHJvdmlkZWQuIElmIG5vIHRhcmdldCBpcyBwcm92aWRlZCwgdGFyZ2V0IHdpbGwgYmVcbiAgICAgKiB0aGUgY3VycmVudCB3aW5kb3cgKGlmIGNhbGxlZCBmcm9tIGEgV2luZG93KSBvciB0aGUgY3VycmVudCBob3N0IHdpbmRvdyAoaWYgY2FsbGVkIGZyb20gYSBWaWV3KS5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIFRoaXMgbWV0aG9kIGNhbiBiZSBjYWxsZWQgZnJvbSB0aGUgd2luZG93IGl0c2VsZiwgb3IgZnJvbSBhbnkgY2hpbGQgdmlldy4gQ29udGV4dCBkYXRhIGlzIHNoYXJlZFxuICAgICAqIGJ5IGFsbCBlbnRpdGllcyB3aXRoaW4gYSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogUmV0cmlldmluZyBjb250ZXh0IGZyb20gY3VycmVudCB3aW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIGNvbnN0IGN1c3RvbUNvbnRleHQgPSB7IGFuc3dlcjogNDIgfTtcbiAgICAgKiBhd2FpdCBwbGF0Zm9ybS5zZXRXaW5kb3dDb250ZXh0KGN1c3RvbUNvbnRleHQpO1xuICAgICAqXG4gICAgICogY29uc3QgbXlDb250ZXh0ID0gYXdhaXQgcGxhdGZvcm0uZ2V0V2luZG93Q29udGV4dCgpO1xuICAgICAqIGNvbnNvbGUubG9nKG15Q29udGV4dCk7IC8vIHsgYW5zd2VyOiA0MiB9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBSZXRyaWV2aW5nIHRoZSBjb250ZXh0IG9mIGFub3RoZXIgd2luZG93IG9yIHZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqXG4gICAgICogY29uc3Qgd2luZG93T3JWaWV3SWRlbnRpdHkgPSB7IHV1aWQ6IGZpbi5tZS51dWlkLCBuYW1lOiAnbmFtZU9mV2luZG93T3JWaWV3JyB9O1xuICAgICAqXG4gICAgICogY29uc3QgdGFyZ2V0V2luZG93Q29udGV4dCA9IGF3YWl0IHBsYXRmb3JtLmdldFdpbmRvd0NvbnRleHQod2luZG93T3JWaWV3SWRlbnRpdHkpO1xuICAgICAqIGNvbnNvbGUubG9nKHRhcmdldFdpbmRvd0NvbnRleHQpOyAvLyBjb250ZXh0IG9mIHRhcmdldCB3aW5kb3dcbiAgICAgKiBgYGBcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICovXG4gICAgYXN5bmMgZ2V0V2luZG93Q29udGV4dCh0YXJnZXQpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLWdldC13aW5kb3ctY29udGV4dCcsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XG4gICAgICAgIGNvbnN0IHsgZW50aXR5VHlwZSB9ID0gdGFyZ2V0ID8gYXdhaXQgdGhpcy5maW4uU3lzdGVtLmdldEVudGl0eUluZm8odGFyZ2V0LnV1aWQsIHRhcmdldC5uYW1lKSA6IHRoaXMuZmluLm1lO1xuICAgICAgICByZXR1cm4gY2xpZW50LmRpc3BhdGNoKCdnZXQtd2luZG93LWNvbnRleHQnLCB7XG4gICAgICAgICAgICB0YXJnZXQ6IHRhcmdldCB8fCB7IHV1aWQ6IHRoaXMuZmluLm1lLnV1aWQsIG5hbWU6IHRoaXMuZmluLm1lLm5hbWUgfSxcbiAgICAgICAgICAgIGVudGl0eVR5cGVcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENsb3NlcyBhIHdpbmRvdy4gSWYgZW5hYmxlQmVmb3JlVW5sb2FkIGlzIGVuYWJsZWQgaW4gdGhlIFBsYXRmb3JtIG9wdGlvbnMsIGFueSBiZWZvcmV1bmxvYWQgaGFuZGxlciBzZXQgb24gVmlld3Mgd2lsbCBmaXJlXG4gICAgICogVGhpcyBiZWhhdmlvciBjYW4gYmUgZGlzYWJsZWQgYnkgc2V0dGluZyBza2lwQmVmb3JlVW5sb2FkIHRvIGZhbHNlIGluIHRoZSBvcHRpb25zIHBhcmFtZXRlci5cbiAgICAgKiBAcGFyYW0gd2luSWRcbiAgICAgKiBAcGFyYW0gb3B0aW9uc1xuICAgICAqXG4gICAgICogQHJlbWFya3MgVGhpcyBtZXRob2Qgd29ya3MgYnkgc2V0dGluZyBhIGBjbG9zZS1yZXF1ZXN0ZWRgIGhhbmRsZXIgb24gdGhlIFBsYXRmb3JtIFdpbmRvdy4gSWYgeW91IGhhdmUgeW91ciBvd24gYGNsb3NlLXJlcXVlc3RlZGAgaGFuZGxlciBzZXQgb24gdGhlIFBsYXRmb3JtIFdpbmRvdyBhcyB3ZWxsLFxuICAgICAqIGl0IGlzIHJlY29tbWVuZGVkIHRvIG1vdmUgdGhhdCBsb2dpYyBvdmVyIHRvIHRoZSBbUGxhdGZvcm1Qcm92aWRlci5jbG9zZVdpbmRvd117QGxpbmsgUGxhdGZvcm1Qcm92aWRlciNjbG9zZVdpbmRvd30gb3ZlcnJpZGUgdG8gZW5zdXJlIGl0IHJ1bnMgd2hlbiB0aGUgV2luZG93IGNsb3Nlcy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIC8vIENsb3NlIHRoZSBjdXJyZW50IFdpbmRvdyBpbnNpZGUgYSBXaW5kb3cgY29udGV4dFxuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLmdldEN1cnJlbnQoKTtcbiAgICAgKiBwbGF0Zm9ybS5jbG9zZVdpbmRvdyhmaW4ubWUuaWRlbnRpdHkpO1xuICAgICAqXG4gICAgICogLy8gQ2xvc2UgdGhlIFdpbmRvdyBmcm9tIGluc2lkZSBhIFZpZXcgY29udGV4dFxuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLmdldEN1cnJlbnQoKTtcbiAgICAgKiBjb25zdCBwYXJlbnRXaW5kb3cgPSBhd2FpdCBmaW4ubWUuZ2V0Q3VycmVudFdpbmRvdygpO1xuICAgICAqIHBsYXRmb3JtLmNsb3NlV2luZG93KHBhcmVudFdpbmRvdy5pZGVudGl0eSk7XG4gICAgICpcbiAgICAgKiAvLyBDbG9zZSB0aGUgV2luZG93IGFuZCBkbyBub3QgZmlyZSB0aGUgYmVmb3JlIHVubG9hZCBoYW5kbGVyIG9uIFZpZXdzXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudCgpO1xuICAgICAqIHBsYXRmb3JtLmNsb3NlV2luZG93KGZpbi5tZS5pZGVudGl0eSwgeyBza2lwQmVmb3JlVW5sb2FkOiB0cnVlIH0pO1xuICAgICAqIGBgYFxuICAgICAqIEBleHBlcmltZW50YWxcbiAgICAgKi9cbiAgICBhc3luYyBjbG9zZVdpbmRvdyh3aW5kb3dJZCwgb3B0aW9ucyA9IHsgc2tpcEJlZm9yZVVubG9hZDogZmFsc2UgfSkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tY2xvc2Utd2luZG93JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcbiAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnY2xvc2Utd2luZG93JywgeyB3aW5kb3dJZCwgb3B0aW9ucyB9KTtcbiAgICB9XG59XG5JbnN0YW5jZSQyLlBsYXRmb3JtID0gUGxhdGZvcm07XG5fUGxhdGZvcm1fY29ubmVjdFRvUHJvdmlkZXIgPSBuZXcgV2Vha01hcCgpO1xuXG52YXIgbGF5b3V0ID0ge307XG5cbnZhciBGYWN0b3J5JDIgPSB7fTtcblxudmFyIEluc3RhbmNlJDEgPSB7fTtcblxudmFyIGNvbW1vblV0aWxzID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb21tb25VdGlscywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb21tb25VdGlscy5vdmVycmlkZUZyb21Db21wb3NhYmxlcyA9IGNvbW1vblV0aWxzLmlzVmFsaWRQcmVzZXRUeXBlID0gdm9pZCAwO1xuZnVuY3Rpb24gaXNWYWxpZFByZXNldFR5cGUodHlwZSkge1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlICdjb2x1bW5zJzpcbiAgICAgICAgY2FzZSAnZ3JpZCc6XG4gICAgICAgIGNhc2UgJ3Jvd3MnOlxuICAgICAgICBjYXNlICd0YWJzJzpcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cbmNvbW1vblV0aWxzLmlzVmFsaWRQcmVzZXRUeXBlID0gaXNWYWxpZFByZXNldFR5cGU7XG5mdW5jdGlvbiBvdmVycmlkZUZyb21Db21wb3NhYmxlcyguLi5vdmVycmlkZXMpIHtcbiAgICByZXR1cm4gKGJhc2UpID0+IG92ZXJyaWRlcy5yZWR1Y2VSaWdodCgocCwgYykgPT4gKGIpID0+IGMocChiKSksICh4KSA9PiB4KShiYXNlKTtcbn1cbmNvbW1vblV0aWxzLm92ZXJyaWRlRnJvbUNvbXBvc2FibGVzID0gb3ZlcnJpZGVGcm9tQ29tcG9zYWJsZXM7XG5jb21tb25VdGlscy5kZWZhdWx0ID0geyBpc1ZhbGlkUHJlc2V0VHlwZSB9O1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcbn07XG52YXIgX0xheW91dF9sYXlvdXRDbGllbnQ7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoSW5zdGFuY2UkMSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5JbnN0YW5jZSQxLkxheW91dCA9IHZvaWQgMDtcbmNvbnN0IGxhenlfMSA9IGxhenk7XG5jb25zdCB2YWxpZGF0ZV8xID0gdmFsaWRhdGU7XG5jb25zdCBiYXNlXzEkNSA9IGJhc2U7XG5jb25zdCBjb21tb25fdXRpbHNfMSA9IGNvbW1vblV0aWxzO1xuY29uc3QgbGF5b3V0X2VudGl0aWVzXzEgPSBsYXlvdXRFbnRpdGllcztcbmNvbnN0IGxheW91dF9jb25zdGFudHNfMSQxID0gbGF5b3V0X2NvbnN0YW50cztcbi8qKlxuICpcbiAqIExheW91dHMgZ2l2ZSBhcHAgcHJvdmlkZXJzIHRoZSBhYmlsaXR5IHRvIGVtYmVkIG11bHRpcGxlIHZpZXdzIGluIGEgc2luZ2xlIHdpbmRvdy4gVGhlIExheW91dCBuYW1lc3BhY2VcbiAqIGVuYWJsZXMgdGhlIGluaXRpYWxpemF0aW9uIGFuZCBtYW5pcHVsYXRpb24gb2YgYSB3aW5kb3cncyBMYXlvdXQuIEEgTGF5b3V0IHdpbGxcbiAqIGVtaXQgZXZlbnRzIGxvY2FsbHkgb24gdGhlIERPTSBlbGVtZW50IHJlcHJlc2VudGluZyB0aGUgbGF5b3V0LWNvbnRhaW5lci5cbiAqXG4gKlxuICogIyMjIExheW91dC5ET01FdmVudHNcbiAqXG4gKiBXaGVuIGEgTGF5b3V0IGlzIGNyZWF0ZWQsIGl0IGVtaXRzIGV2ZW50cyBvbnRvIHRoZSBET00gZWxlbWVudCByZXByZXNlbnRpbmcgdGhlIExheW91dCBjb250YWluZXIuXG4gKiBUaGlzIExheW91dCBjb250YWluZXIgaXMgdGhlIERPTSBlbGVtZW50IHJlZmVyZW5jZWQgYnkgY29udGFpbmVySWQgaW4ge0BsaW5rIExheW91dC5MYXlvdXRNb2R1bGUjaW5pdCBMYXlvdXQuaW5pdH0uXG4gKiBZb3UgY2FuIHVzZSB0aGUgYnVpbHQtaW4gZXZlbnQgZW1pdHRlciB0byBsaXN0ZW4gdG8gdGhlc2UgZXZlbnRzIHVzaW5nIFthZGRFdmVudExpc3RlbmVyXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRXZlbnRUYXJnZXQvYWRkRXZlbnRMaXN0ZW5lcikuXG4gKiBUaGUgZXZlbnRzIGFyZSBlbWl0dGVkIHN5bmNocm9ub3VzbHkgYW5kIG9ubHkgaW4gdGhlIHByb2Nlc3Mgd2hlcmUgdGhlIExheW91dCBleGlzdHMuXG4gKiBBbnkgdmFsdWVzIHJldHVybmVkIGJ5IHRoZSBjYWxsZWQgbGlzdGVuZXJzIGFyZSBpZ25vcmVkIGFuZCB3aWxsIGJlIGRpc2NhcmRlZC5cbiAqIElmIHRoZSB0YXJnZXQgRE9NIGVsZW1lbnQgaXMgZGVzdHJveWVkLCBhbnkgZXZlbnRzIHRoYXQgaGF2ZSBiZWVuIHNldCB1cCBvbiB0aGF0IGVsZW1lbnQgd2lsbCBiZSBkZXN0cm95ZWQuXG4gKlxuICogQHJlbWFya3MgVGhlIGJ1aWx0LWluIGV2ZW50IGVtaXR0ZXIgaXMgbm90IGFuIE9wZW5GaW4gZXZlbnQgZW1pdHRlciBzbyBpdCBkb2Vzbid0IHNoYXJlIHByb3BhZ2F0aW9uIHNlbWFudGljcy5cbiAqXG4gKiAjIyMjIHtAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRXZlbnRUYXJnZXQvYWRkRXZlbnRMaXN0ZW5lciBhZGRFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyIFssIG9wdGlvbnNdKTt9XG4gKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICogQGV4YW1wbGVcbiAqIGBgYGpzXG4gKiBjb25zdCBteUxheW91dENvbnRhaW5lciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdsYXlvdXQtY29udGFpbmVyJyk7XG4gKlxuICogbXlMYXlvdXRDb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcigndGFiLWNyZWF0ZWQnLCBmdW5jdGlvbihldmVudCkge1xuICogICAgICBjb25zdCB7IHRhYlNlbGVjdG9yIH0gPSBldmVudC5kZXRhaWw7XG4gKiAgICAgIGNvbnN0IHRhYkVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YWJTZWxlY3Rvcik7XG4gKiAgICAgIGNvbnN0IGV4aXN0aW5nQ29sb3IgPSB0YWJFbGVtZW50LnN0eWxlLmJhY2tncm91bmRDb2xvcjtcbiAqICAgICAgdGFiRWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBcInJlZFwiO1xuICogICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAqICAgICAgICAgIHRhYkVsZW1lbnQuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gZXhpc3RpbmdDb2xvcjtcbiAqICAgICAgfSwgMjAwMCk7XG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqICMjIyMge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9FdmVudFRhcmdldC9yZW1vdmVFdmVudExpc3RlbmVyIHJlbW92ZUV2ZW50TGlzdGVuZXIodHlwZSwgbGlzdGVuZXIgWywgb3B0aW9uc10pO31cbiAqIEFkZHMgYSBsaXN0ZW5lciB0byB0aGUgZW5kIG9mIHRoZSBsaXN0ZW5lcnMgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gKiBAZXhhbXBsZVxuICogYGBganNcbiAqIGNvbnN0IG15TGF5b3V0Q29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2xheW91dC1jb250YWluZXInKTtcbiAqXG4gKiBjb25zdCBsaXN0ZW5lciA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gKiAgICAgY29uc29sZS5sb2coZXZlbnQuZGV0YWlsKTtcbiAqICAgICBjb25zb2xlLmxvZygnY29udGFpbmVyLWNyZWF0ZWQgZXZlbnQgZmlyZWQgb25jZSwgcmVtb3ZpbmcgbGlzdGVuZXInKTtcbiAqICAgICBteUxheW91dENvbnRhaW5lci5yZW1vdmVFdmVudExpc3RlbmVyKCdjb250YWluZXItY3JlYXRlZCcsIGxpc3RlbmVyKTtcbiAqIH07XG4gKlxuICogbXlMYXlvdXRDb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcignY29udGFpbmVyLWNyZWF0ZWQnLCBsaXN0ZW5lcik7XG4gKiBgYGBcbiAqXG4gKiAjIyMgU3VwcG9ydGVkIGV2ZW50IHR5cGVzIGFyZTpcbiAqXG4gKiAqIHRhYi1jcmVhdGVkXG4gKiAqIGNvbnRhaW5lci1jcmVhdGVkXG4gKiAqIGxheW91dC1zdGF0ZS1jaGFuZ2VkXG4gKiAqIHRhYi1jbG9zZWRcbiAqICogdGFiLWRyb3BwZWRcbiAqXG4gKiAjIyMgTGF5b3V0IERPTSBOb2RlIEV2ZW50c1xuICpcbiAqICMjIyMgdGFiLWNyZWF0ZWRcbiAqIEdlbmVyYXRlZCB3aGVuIGEgdGFiIGlzIGNyZWF0ZWQuICBBcyBhIHVzZXIgZHJhZ3MgYW5kIGRyb3BzIHRhYnMgd2l0aGluIHdpbmRvdywgbmV3IHRhYnMgYXJlIGNyZWF0ZWQuICBBIHNpbmdsZSB2aWV3IG1heSBoYXZlIG11bHRpcGxlIHRhYnMgY3JlYXRlZCBhbmQgZGVzdHJveWVkIGR1cmluZyBpdHMgbGlmZXRpbWUgYXR0YWNoZWQgdG8gYSBzaW5nbGUgd2luZG93LlxuICogYGBganNcbiAqIC8vIFRoZSByZXNwb25zZSBoYXMgdGhlIGZvbGxvd2luZyBzaGFwZSBpbiBldmVudC5kZXRhaWw6XG4gKiB7XG4gKiAgICAgY29udGFpbmVyU2VsZWN0b3I6IFwiY29udGFpbmVyLWNvbXBvbmVudF9BXCIsXG4gKiAgICAgbmFtZTogXCJjb21wb25lbnRfQVwiLFxuICogICAgIHRhYlNlbGVjdG9yOiBcInRhYi1jb21wb25lbnRfQVwiLFxuICogICAgIHRvcGljOiBcIm9wZW5maW4tRE9NLWV2ZW50XCIsXG4gKiAgICAgdHlwZTogXCJ0YWItY3JlYXRlZFwiLFxuICogICAgIHV1aWQ6IFwiT3BlbkZpbiBQT0NcIlxuICogfVxuICogYGBgXG4gKlxuICogIyMjIyBjb250YWluZXItY3JlYXRlZFxuICogR2VuZXJhdGVkIHdoZW4gYSBjb250YWluZXIgaXMgY3JlYXRlZC4gIEEgc2luZ2xlIHZpZXcgd2lsbCBoYXZlIG9ubHkgb25lIGNvbnRhaW5lciBkdXJpbmcgaXRzIGxpZmV0aW1lIGF0dGFjaGVkIHRvIGEgc2luZ2xlIHdpbmRvdyBhbmQgdGhlIGNvbnRhaW5lcidzIGxpZmVjeWNsZSBpcyB0aWVkIHRvIHRoZSB2aWV3LiAgVG8gZGlzY292ZXIgd2hlbiB0aGUgY29udGFpbmVyIGlzIGRlc3Ryb3llZCwgcGxlYXNlIGxpc3RlbiB0byB2aWV3LWRldGFjaGVkIGV2ZW50LlxuICogYGBganNcbiAqIC8vIFRoZSByZXNwb25zZSBoYXMgdGhlIGZvbGxvd2luZyBzaGFwZSBpbiBldmVudC5kZXRhaWw6XG4gKiB7XG4gKiAgICAgY29udGFpbmVyU2VsZWN0b3I6IFwiY29udGFpbmVyLWNvbXBvbmVudF9BXCIsXG4gKiAgICAgbmFtZTogXCJjb21wb25lbnRfQVwiLFxuICogICAgIHRhYlNlbGVjdG9yOiBcInRhYi1jb21wb25lbnRfQVwiLFxuICogICAgIHRvcGljOiBcIm9wZW5maW4tRE9NLWV2ZW50XCIsXG4gKiAgICAgdHlwZTogXCJjb250YWluZXItY3JlYXRlZFwiLFxuICogICAgIHV1aWQ6IFwiT3BlbkZpbiBQT0NcIlxuICogfVxuICogYGBgXG4gKlxuICogIyMjIGxheW91dC1zdGF0ZS1jaGFuZ2VkXG4gKiBHZW5lcmF0ZWQgd2hlbiB0aGUgc3RhdGUgb2YgdGhlIGxheW91dCBjaGFuZ2VzIGluIGFueSB3YXksIHN1Y2ggYXMgYSB2aWV3IGFkZGVkL3JlbW92ZWQvcmVwbGFjZWQuIE5vdGUgdGhhdCB0aGlzIGV2ZW50IGNhbiBmaXJlIGZyZXF1ZW50bHkgYXMgdGhlIHVuZGVybHlpbmcgbGF5b3V0IGNhbiBjaGFuZ2UgbXVsdGlwbGUgY29tcG9uZW50cyBmcm9tIGFsbCBraW5kcyBvZiBjaGFuZ2VzIChyZXNpemluZyBmb3IgZXhhbXBsZSkuIEdpdmVuIHRoaXMsIGl0IGlzIHJlY29tbWVuZGVkIHRvIGRlYm91bmNlIHRoaXMgZXZlbnQgYW5kIHRoZW4geW91IGNhbiB1c2UgdGhlIHtAbGluayBMYXlvdXQjZ2V0Q29uZmlnIExheW91dC5nZXRDb25maWd9IEFQSSB0byByZXRyaWV2ZSB0aGUgbW9zdCB1cC10by1kYXRlIHN0YXRlLlxuICogYGBganNcbiAqIC8vIFRoZSByZXNwb25zZSBoYXMgdGhlIGZvbGxvd2luZyBzaGFwZSBpbiBldmVudC5kZXRhaWxcbiAqIHtcbiAqICAgICBjb250YWluZXJTZWxlY3RvcjogXCJjb250YWluZXItY29tcG9uZW50X0FcIixcbiAqICAgICBuYW1lOiBcImNvbXBvbmVudF9BXCIsXG4gKiAgICAgdGFiU2VsZWN0b3I6IFwidGFiLWNvbXBvbmVudF9BXCIsXG4gKiAgICAgdG9waWM6IFwib3BlbmZpbi1ET00tZXZlbnRcIixcbiAqICAgICB0eXBlOiBcImxheW91dC1zdGF0ZS1jaGFuZ2VkXCIsXG4gKiAgICAgdXVpZDogXCJPcGVuRmluIFBPQ1wiXG4gKiB9XG4gKiBgYGBcbiAqXG4gKiAjIyMjIHRhYi1jbG9zZWRcbiAqIEdlbmVyYXRlZCB3aGVuIGEgdGFiIGlzIGNsb3NlZC5cbiAqIGBgYGpzXG4gKiAvLyBUaGUgcmVzcG9uc2UgaGFzIHRoZSBmb2xsb3dpbmcgc2hhcGUgaW4gZXZlbnQuZGV0YWlsOlxuICoge1xuICogICAgIGNvbnRhaW5lclNlbGVjdG9yOiBcImNvbnRhaW5lci1jb21wb25lbnRfQVwiLFxuICogICAgIG5hbWU6IFwiY29tcG9uZW50X0FcIixcbiAqICAgICB0YWJTZWxlY3RvcjogXCJ0YWItY29tcG9uZW50X0FcIixcbiAqICAgICB0b3BpYzogXCJvcGVuZmluLURPTS1ldmVudFwiLFxuICogICAgIHR5cGU6IFwidGFiLWNsb3NlZFwiLFxuICogICAgIHV1aWQ6IFwiT3BlbkZpbiBQT0NcIixcbiAqICAgICB1cmw6IFwiaHR0cDovL29wZW5maW4uY29cIiAgIC8vIFRoZSB1cmwgb2YgdGhlIHZpZXcgdGhhdCB3YXMgY2xvc2VkLlxuICogfVxuICogYGBgXG4gKlxuICogIyMjIyB0YWItZHJvcHBlZFxuICogR2VuZXJhdGVkIHdoZW4gYSB0YWIgaXMgZHJvcHBlZC5cbiAqIGBgYGpzXG4gKiAvLyBUaGUgcmVzcG9uc2UgaGFzIHRoZSBmb2xsb3dpbmcgc2hhcGUgaW4gZXZlbnQuZGV0YWlsOlxuICoge1xuICogICAgIGNvbnRhaW5lclNlbGVjdG9yOiBcImNvbnRhaW5lci1jb21wb25lbnRfQVwiLFxuICogICAgIG5hbWU6IFwiY29tcG9uZW50X0FcIixcbiAqICAgICB0YWJTZWxlY3RvcjogXCJ0YWItY29tcG9uZW50X0FcIixcbiAqICAgICB0b3BpYzogXCJvcGVuZmluLURPTS1ldmVudFwiLFxuICogICAgIHR5cGU6IFwidGFiLWRyb3BwZWRcIixcbiAqICAgICB1dWlkOiBcIk9wZW5GaW4gUE9DXCIsXG4gKiAgICAgdXJsOiBcImh0dHA6Ly9vcGVuZmluLmNvXCIgICAgLy8gVGhlIHVybCBvZiB0aGUgdmlldyBsaW5rZWQgdG8gdGhlIGRyb3BwZWQgdGFiLlxuICogfVxuICogYGBgXG4gKi9cbmNsYXNzIExheW91dCBleHRlbmRzIGJhc2VfMSQ1LkJhc2Uge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zaGFkb3dcbiAgICBjb25zdHJ1Y3RvcihpZGVudGl0eSwgd2lyZSkge1xuICAgICAgICBzdXBlcih3aXJlKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBpbnRlcm5hbFxuICAgICAgICAgKiBMYXppbHkgY29uc3RydWN0ZWQge0BsaW5rIExheW91dEVudGl0aWVzQ2xpZW50fSBib3VuZCB0byB0aGlzIHBsYXRmb3JtJ3MgY2xpZW50IGFuZCBpZGVudGl0eVxuICAgICAgICAgKiBUaGUgY2xpZW50IGlzIGZvciB7QGxpbmsgTGF5b3V0RW50aXRpZXNDb250cm9sbGVyfVxuICAgICAgICAgKi9cbiAgICAgICAgX0xheW91dF9sYXlvdXRDbGllbnQuc2V0KHRoaXMsIG5ldyBsYXp5XzEuTGF6eShhc3luYyAoKSA9PiBsYXlvdXRfZW50aXRpZXNfMS5MYXlvdXROb2RlLm5ld0xheW91dEVudGl0aWVzQ2xpZW50KGF3YWl0IHRoaXMucGxhdGZvcm0uZ2V0Q2xpZW50KCksIGxheW91dF9jb25zdGFudHNfMSQxLkxBWU9VVF9DT05UUk9MTEVSX0lELCB0aGlzLmlkZW50aXR5KSkpO1xuICAgICAgICAvKipcbiAgICAgICAgICogUmVwbGFjZXMgYSBQbGF0Zm9ybSB3aW5kb3cncyBsYXlvdXQgd2l0aCBhIG5ldyBsYXlvdXQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZW1hcmtzIEFueSB2aWV3cyB0aGF0IHdlcmUgaW4gdGhlIG9sZCBsYXlvdXQgYnV0IG5vdCB0aGUgbmV3IGxheW91dCB3aWxsIGJlIGRlc3Ryb3llZC4gVmlld3Mgd2lsbCBiZSBhc3NpZ25lZCBhIHJhbmRvbWx5IGdlbmVyYXRlZCBuYW1lIHRvIGF2b2lkIGNvbGxpc2lvbnMuXG4gICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAqIGBgYGpzXG4gICAgICAgICAqIGxldCB3aW5kb3dJZGVudGl0eTtcbiAgICAgICAgICogaWYgKGZpbi5tZS5pc1dpbmRvdykge1xuICAgICAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSBmaW4ubWUuaWRlbnRpdHk7XG4gICAgICAgICAqIH0gZWxzZSBpZiAoZmluLm1lLmlzVmlldykge1xuICAgICAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSAoYXdhaXQgZmluLm1lLmdldEN1cnJlbnRXaW5kb3coKSkuaWRlbnRpdHk7XG4gICAgICAgICAqIH0gZWxzZSB7XG4gICAgICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldyBvciBXaW5kb3cnKTtcbiAgICAgICAgICogfVxuICAgICAgICAgKlxuICAgICAgICAgKiBjb25zdCBsYXlvdXQgPSBmaW4uUGxhdGZvcm0uTGF5b3V0LndyYXBTeW5jKHdpbmRvd0lkZW50aXR5KTtcbiAgICAgICAgICpcbiAgICAgICAgICogY29uc3QgbmV3TGF5b3V0ID0ge1xuICAgICAgICAgKiAgICAgY29udGVudDogW1xuICAgICAgICAgKiAgICAgICAgIHtcbiAgICAgICAgICogICAgICAgICAgICAgdHlwZTogJ3N0YWNrJyxcbiAgICAgICAgICogICAgICAgICAgICAgY29udGVudDogW1xuICAgICAgICAgKiAgICAgICAgICAgICAgICAge1xuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjb21wb25lbnQnLFxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudE5hbWU6ICd2aWV3JyxcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRTdGF0ZToge1xuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAnbmV3X2NvbXBvbmVudF9BMScsXG4gICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NBZmZpbml0eTogJ3BzXzEnLFxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB1cmw6ICdodHRwczovL3d3dy5leGFtcGxlLmNvbSdcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAqICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgKiAgICAgICAgICAgICAgICAge1xuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjb21wb25lbnQnLFxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudE5hbWU6ICd2aWV3JyxcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRTdGF0ZToge1xuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAnbmV3X2NvbXBvbmVudF9BMicsXG4gICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZW1iZWQtd2ViL2NoYXJ0Lmh0bWwnXG4gICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgKiAgICAgICAgICAgICBdXG4gICAgICAgICAqICAgICAgICAgfVxuICAgICAgICAgKiAgICAgXVxuICAgICAgICAgKiB9O1xuICAgICAgICAgKlxuICAgICAgICAgKiBsYXlvdXQucmVwbGFjZShuZXdMYXlvdXQpO1xuICAgICAgICAgKiBgYGBcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMucmVwbGFjZSA9IGFzeW5jIChsYXlvdXQpID0+IHtcbiAgICAgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdsYXlvdXQtcmVwbGFjZScpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMucGxhdGZvcm0uZ2V0Q2xpZW50KCk7XG4gICAgICAgICAgICBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ3JlcGxhY2UtbGF5b3V0Jywge1xuICAgICAgICAgICAgICAgIHRhcmdldDogdGhpcy5pZGVudGl0eSxcbiAgICAgICAgICAgICAgICBvcHRzOiB7IGxheW91dCB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJlcGxhY2VzIHRoZSBzcGVjaWZpZWQgdmlldyB3aXRoIGEgdmlldyB3aXRoIHRoZSBwcm92aWRlZCBjb25maWd1cmF0aW9uLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmVtYXJrcyBUaGUgb2xkIHZpZXcgaXMgc3RyaXBwZWQgb2YgaXRzIGxpc3RlbmVycyBhbmQgZWl0aGVyIGNsb3NlZCBvciBhdHRhY2hlZCB0byB0aGUgcHJvdmlkZXIgd2luZG93XG4gICAgICAgICAqIGRlcGVuZGluZyBvbiBgZGV0YWNoT25DbG9zZWAgdmlldyBvcHRpb24uXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB2aWV3VG9SZXBsYWNlIElkZW50aXR5IG9mIHRoZSB2aWV3IHRvIGJlIHJlcGxhY2VkXG4gICAgICAgICAqIEBwYXJhbSBuZXdWaWV3IENyZWF0aW9uIG9wdGlvbnMgb2YgdGhlIG5ldyB2aWV3LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBsZXQgY3VycmVudFdpbmRvdztcbiAgICAgICAgICogaWYgKGZpbi5tZS5pc1dpbmRvdykge1xuICAgICAgICAgKiAgICAgY3VycmVudFdpbmRvdyA9IGZpbi5tZTtcbiAgICAgICAgICogfSBlbHNlIGlmIChmaW4ubWUuaXNWaWV3KSB7XG4gICAgICAgICAqICAgICBjdXJyZW50V2luZG93ID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRXaW5kb3coKTtcbiAgICAgICAgICogfSBlbHNlIHtcbiAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3IG9yIFdpbmRvdycpO1xuICAgICAgICAgKiB9XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IGxheW91dCA9IGZpbi5QbGF0Zm9ybS5MYXlvdXQud3JhcFN5bmMoY3VycmVudFdpbmRvdy5pZGVudGl0eSk7XG4gICAgICAgICAqIGNvbnN0IHZpZXdUb1JlcGxhY2UgPSAoYXdhaXQgY3VycmVudFdpbmRvdy5nZXRDdXJyZW50Vmlld3MoKSlbMF07XG4gICAgICAgICAqIGNvbnN0IG5ld1ZpZXdDb25maWcgPSB7dXJsOiAnaHR0cHM6Ly9leGFtcGxlLmNvbSd9O1xuICAgICAgICAgKiBhd2FpdCBsYXlvdXQucmVwbGFjZVZpZXcodmlld1RvUmVwbGFjZS5pZGVudGl0eSwgbmV3Vmlld0NvbmZpZyk7XG4gICAgICAgICAqIGBgYFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5yZXBsYWNlVmlldyA9IGFzeW5jICh2aWV3VG9SZXBsYWNlLCBuZXdWaWV3KSA9PiB7XG4gICAgICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignbGF5b3V0LXJlcGxhY2UtdmlldycpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMucGxhdGZvcm0uZ2V0Q2xpZW50KCk7XG4gICAgICAgICAgICBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ3JlcGxhY2UtdmlldycsIHtcbiAgICAgICAgICAgICAgICB0YXJnZXQ6IHRoaXMuaWRlbnRpdHksXG4gICAgICAgICAgICAgICAgb3B0czogeyB2aWV3VG9SZXBsYWNlLCBuZXdWaWV3IH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogUmVwbGFjZXMgYSBQbGF0Zm9ybSB3aW5kb3cncyBsYXlvdXQgd2l0aCBhIHByZXNldCBsYXlvdXQgYXJyYW5nZW1lbnQgdXNpbmcgdGhlIGV4aXN0aW5nIFZpZXdzIGF0dGFjaGVkIHRvIHRoZSB3aW5kb3cuXG4gICAgICAgICAqIFRoZSBwcmVzZXQgb3B0aW9ucyBhcmUgYGNvbHVtbnNgLCBgZ3JpZGAsIGByb3dzYCwgYW5kIGB0YWJzYC5cbiAgICAgICAgICogQHBhcmFtIG9wdGlvbnMgTWFuZGF0b3J5IG9iamVjdCB3aXRoIGBwcmVzZXRUeXBlYCBwcm9wZXJ0eSB0aGF0IHNldHMgd2hpY2ggcHJlc2V0IGxheW91dCBhcnJhbmdlbWVudCB0byB1c2UuXG4gICAgICAgICAqIFRoZSBwcmVzZXQgb3B0aW9ucyBhcmUgYGNvbHVtbnNgLCBgZ3JpZGAsIGByb3dzYCwgYW5kIGB0YWJzYC5cbiAgICAgICAgICpcbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogbGV0IHdpbmRvd0lkZW50aXR5O1xuICAgICAgICAgKiBpZiAoZmluLm1lLmlzV2luZG93KSB7XG4gICAgICAgICAqICAgICB3aW5kb3dJZGVudGl0eSA9IGZpbi5tZS5pZGVudGl0eTtcbiAgICAgICAgICogfSBlbHNlIGlmIChmaW4ubWUuaXNWaWV3KSB7XG4gICAgICAgICAqICAgICB3aW5kb3dJZGVudGl0eSA9IChhd2FpdCBmaW4ubWUuZ2V0Q3VycmVudFdpbmRvdygpKS5pZGVudGl0eTtcbiAgICAgICAgICogfSBlbHNlIHtcbiAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3IG9yIFdpbmRvdycpO1xuICAgICAgICAgKiB9XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IGxheW91dCA9IGZpbi5QbGF0Zm9ybS5MYXlvdXQud3JhcFN5bmMod2luZG93SWRlbnRpdHkpO1xuICAgICAgICAgKiBhd2FpdCBsYXlvdXQuYXBwbHlQcmVzZXQoeyBwcmVzZXRUeXBlOiAnZ3JpZCcgfSk7XG4gICAgICAgICAqXG4gICAgICAgICAqIC8vIHdhaXQgNSBzZWNvbmRzIHVudGlsIHlvdSBjaGFuZ2UgdGhlIGxheW91dCBmcm9tIGdyaWQgdG8gdGFic1xuICAgICAgICAgKiBhd2FpdCBuZXcgUHJvbWlzZSAocmVzID0+IHNldFRpbWVvdXQocmVzLCA1MDAwKSk7XG4gICAgICAgICAqIGF3YWl0IGxheW91dC5hcHBseVByZXNldCh7IHByZXNldFR5cGU6ICd0YWJzJyB9KTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmFwcGx5UHJlc2V0ID0gYXN5bmMgKG9wdGlvbnMpID0+IHtcbiAgICAgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdsYXlvdXQtYXBwbHktcHJlc2V0JykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5wbGF0Zm9ybS5nZXRDbGllbnQoKTtcbiAgICAgICAgICAgIGNvbnN0IHsgcHJlc2V0VHlwZSB9ID0gb3B0aW9ucztcbiAgICAgICAgICAgIGlmICghcHJlc2V0VHlwZSB8fCAhKDAsIGNvbW1vbl91dGlsc18xLmlzVmFsaWRQcmVzZXRUeXBlKShwcmVzZXRUeXBlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGFwcGx5IHByZXNldCBsYXlvdXQsIHBsZWFzZSBpbmNsdWRlIGFuIGFwcGxpY2FibGUgcHJlc2V0VHlwZSBwcm9wZXJ0eSBpbiB0aGUgUHJlc2V0TGF5b3V0T3B0aW9ucy4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IGNsaWVudC5kaXNwYXRjaCgnYXBwbHktcHJlc2V0LWxheW91dCcsIHtcbiAgICAgICAgICAgICAgICB0YXJnZXQ6IHRoaXMuaWRlbnRpdHksXG4gICAgICAgICAgICAgICAgb3B0czogeyBwcmVzZXRUeXBlIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBlcnJvck1zZyA9ICgwLCB2YWxpZGF0ZV8xLnZhbGlkYXRlSWRlbnRpdHkpKGlkZW50aXR5KTtcbiAgICAgICAgaWYgKGVycm9yTXNnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNc2cpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaWRlbnRpdHkgPSBpZGVudGl0eTtcbiAgICAgICAgdGhpcy5wbGF0Zm9ybSA9IHRoaXMuZmluLlBsYXRmb3JtLndyYXBTeW5jKHsgdXVpZDogaWRlbnRpdHkudXVpZCB9KTtcbiAgICAgICAgaWYgKGlkZW50aXR5LnV1aWQgPT09IHRoaXMuZmluLm1lLnV1aWQgJiYgaWRlbnRpdHkubmFtZSA9PT0gdGhpcy5maW4ubWUubmFtZSkge1xuICAgICAgICAgICAgdGhpcy5pbml0ID0gdGhpcy5maW4uUGxhdGZvcm0uTGF5b3V0LmluaXQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY29uZmlndXJhdGlvbiBvZiB0aGUgd2luZG93J3MgbGF5b3V0LiAgUmV0dXJucyB0aGUgc2FtZSBpbmZvcm1hdGlvbiB0aGF0IGlzIHJldHVybmVkIGZvciBhbGwgd2luZG93cyBpbiBnZXRTbmFwc2hvdC5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIENhbm5vdCBiZSBjYWxsZWQgZnJvbSBhIFZpZXcuXG4gICAgICpcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBsYXlvdXQgPSBmaW4uUGxhdGZvcm0uTGF5b3V0LmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogLy8gVXNlIHdyYXBwZWQgaW5zdGFuY2UgdG8gZ2V0IHRoZSBsYXlvdXQgY29uZmlndXJhdGlvbiBvZiB0aGUgY3VycmVudCB3aW5kb3cncyBMYXlvdXQ6XG4gICAgICogY29uc3QgbGF5b3V0Q29uZmlnID0gYXdhaXQgbGF5b3V0LmdldENvbmZpZygpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGdldENvbmZpZygpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2xheW91dC1nZXQtY29uZmlnJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5wbGF0Zm9ybS5nZXRDbGllbnQoKTtcbiAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnZ2V0LWZyYW1lLXNuYXBzaG90Jywge1xuICAgICAgICAgICAgdGFyZ2V0OiB0aGlzLmlkZW50aXR5XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIGF0dGFjaGVkIHZpZXdzIGluIGN1cnJlbnQgd2luZG93IGxheW91dC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBsYXlvdXQgPSBmaW4uUGxhdGZvcm0uTGF5b3V0LmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogY29uc3Qgdmlld3MgPSBhd2FpdCBsYXlvdXQuZ2V0Q3VycmVudFZpZXdzKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZ2V0Q3VycmVudFZpZXdzKCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignbGF5b3V0LWdldC12aWV3cycpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMucGxhdGZvcm0uZ2V0Q2xpZW50KCk7XG4gICAgICAgIGNvbnN0IHZpZXdJZGVudGl0aWVzID0gYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdnZXQtbGF5b3V0LXZpZXdzJywge1xuICAgICAgICAgICAgdGFyZ2V0OiB0aGlzLmlkZW50aXR5XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdmlld0lkZW50aXRpZXMubWFwKChpZGVudGl0eSkgPT4gdGhpcy5maW4uVmlldy53cmFwU3luYyhpZGVudGl0eSkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIHRvcCBsZXZlbCBjb250ZW50IGl0ZW0gb2YgdGhlIGxheW91dC5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIENhbm5vdCBiZSBjYWxsZWQgZnJvbSBhIHZpZXcuXG4gICAgICpcbiAgICAgKlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGlmICghZmluLm1lLmlzV2luZG93KSB7XG4gICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3LicpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIC8vIEZyb20gdGhlIGxheW91dCB3aW5kb3dcbiAgICAgKiBjb25zdCBsYXlvdXQgPSBmaW4uUGxhdGZvcm0uTGF5b3V0LmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogLy8gUmV0cmlldmVzIHRoZSBDb2x1bW5PclJvdyBpbnN0YW5jZVxuICAgICAqIGNvbnN0IHJvb3RJdGVtID0gYXdhaXQgbGF5b3V0LmdldFJvb3RJdGVtKCk7XG4gICAgICogY29uc3QgY29udGVudCA9IGF3YWl0IHJvb3RJdGVtLmdldENvbnRlbnQoKTtcbiAgICAgKiBjb25zb2xlLmxvZyhgVGhlIHJvb3QgQ29sdW1uT3JSb3cgaW5zdGFuY2UgaGFzICR7Y29udGVudC5sZW5ndGh9IGl0ZW0ocylgKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBnZXRSb290SXRlbSgpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2xheW91dC1nZXQtcm9vdC1pdGVtJykuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDQodGhpcywgX0xheW91dF9sYXlvdXRDbGllbnQsIFwiZlwiKS5nZXRWYWx1ZSgpO1xuICAgICAgICBjb25zdCByb290ID0gYXdhaXQgY2xpZW50LmdldFJvb3QoJ2xheW91dE5hbWUnIGluIHRoaXMuaWRlbnRpdHkgPyB0aGlzLmlkZW50aXR5IDogdW5kZWZpbmVkKTtcbiAgICAgICAgcmV0dXJuIGxheW91dF9lbnRpdGllc18xLkxheW91dE5vZGUuZ2V0RW50aXR5KHJvb3QsIGNsaWVudCk7XG4gICAgfVxufVxuSW5zdGFuY2UkMS5MYXlvdXQgPSBMYXlvdXQ7XG5fTGF5b3V0X2xheW91dENsaWVudCA9IG5ldyBXZWFrTWFwKCk7XG5cbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDMgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDMgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XG59O1xudmFyIF9MYXlvdXRNb2R1bGVfaW5zdGFuY2VzLCBfTGF5b3V0TW9kdWxlX2xheW91dEluaXRpYWxpemF0aW9uQXR0ZW1wdGVkLCBfTGF5b3V0TW9kdWxlX2xheW91dE1hbmFnZXIsIF9MYXlvdXRNb2R1bGVfZ2V0TGF5b3V0TWFuYWdlclNweSwgX0xheW91dE1vZHVsZV9nZXRTYWZlTGF5b3V0TWFuYWdlcjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShGYWN0b3J5JDIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuRmFjdG9yeSQyLkxheW91dE1vZHVsZSA9IHZvaWQgMDtcbmNvbnN0IGJhc2VfMSQ0ID0gYmFzZTtcbmNvbnN0IEluc3RhbmNlXzEkMiA9IEluc3RhbmNlJDE7XG5jb25zdCBsYXlvdXRfY29uc3RhbnRzXzEgPSBsYXlvdXRfY29uc3RhbnRzO1xuLyoqXG4gKiBTdGF0aWMgbmFtZXNwYWNlIGZvciBPcGVuRmluIEFQSSBtZXRob2RzIHRoYXQgaW50ZXJhY3Qgd2l0aCB0aGUge0BsaW5rIExheW91dH0gY2xhc3MsIGF2YWlsYWJsZSB1bmRlciBgZmluLlBsYXRmb3JtLkxheW91dGAuXG4gKi9cbmNsYXNzIExheW91dE1vZHVsZSBleHRlbmRzIGJhc2VfMSQ0LkJhc2Uge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICBfTGF5b3V0TW9kdWxlX2luc3RhbmNlcy5hZGQodGhpcyk7XG4gICAgICAgIF9MYXlvdXRNb2R1bGVfbGF5b3V0SW5pdGlhbGl6YXRpb25BdHRlbXB0ZWQuc2V0KHRoaXMsIGZhbHNlKTtcbiAgICAgICAgX0xheW91dE1vZHVsZV9sYXlvdXRNYW5hZ2VyLnNldCh0aGlzLCBudWxsKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEluaXRpYWxpemUgdGhlIHdpbmRvdydzIExheW91dC5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJlbWFya3MgTXVzdCBiZSBjYWxsZWQgZnJvbSBhIGN1c3RvbSB3aW5kb3cgdGhhdCBoYXMgYSAnbGF5b3V0JyBvcHRpb24gc2V0IHVwb24gY3JlYXRpb24gb2YgdGhhdCB3aW5kb3cuXG4gICAgICAgICAqIElmIGEgY29udGFpbmVySWQgaXMgbm90IHByb3ZpZGVkLCB0aGlzIG1ldGhvZCBhdHRlbXB0cyB0byBmaW5kIGFuIGVsZW1lbnQgd2l0aCB0aGUgaWQgYGxheW91dC1jb250YWluZXJgLlxuICAgICAgICAgKiBBIExheW91dCB3aWxsIGVtaXQgZXZlbnRzIGxvY2FsbHkgb24gdGhlIERPTSBlbGVtZW50IHJlcHJlc2VudGluZyB0aGUgbGF5b3V0LWNvbnRhaW5lci5cbiAgICAgICAgICogSW4gb3JkZXIgdG8gY2FwdHVyZSB0aGUgcmVsZXZhbnQgZXZlbnRzIGR1cmluZyBMYXlvdXQgaW5pdGlhdGlvbiwgc2V0IHVwIHRoZSBsaXN0ZW5lcnMgb24gdGhlIERPTSBlbGVtZW50IHByaW9yIHRvIGNhbGxpbmcgYGluaXRgLlxuICAgICAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIExheW91dCBpbml0IG9wdGlvbnMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBleHBlcmltZW50YWxcbiAgICAgICAgICpcbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogLy8gSWYgbm8gb3B0aW9ucyBhcmUgaW5jbHVkZWQsIHRoZSBsYXlvdXQgaW4gdGhlIHdpbmRvdyBvcHRpb25zIGlzIGluaXRpYWxpemVkIGluIGFuIGVsZW1lbnQgd2l0aCB0aGUgaWQgYGxheW91dC1jb250YWluZXJgXG4gICAgICAgICAqIGNvbnN0IGxheW91dCA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5MYXlvdXQuaW5pdCgpO1xuICAgICAgICAgKiBgYGBcbiAgICAgICAgICogPGJyPlxuICAgICAgICAgKlxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBjb25zdCBjb250YWluZXJJZCA9ICdteS1jdXN0b20tY29udGFpbmVyLWlkJztcbiAgICAgICAgICpcbiAgICAgICAgICogY29uc3QgbXlMYXlvdXRDb250YWluZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChjb250YWluZXJJZCk7XG4gICAgICAgICAqXG4gICAgICAgICAqIG15TGF5b3V0Q29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ3RhYi1jcmVhdGVkJywgZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgICogICAgIGNvbnN0IHsgdGFiU2VsZWN0b3IgfSA9IGV2ZW50LmRldGFpbDtcbiAgICAgICAgICogICAgIGNvbnN0IHRhYkVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YWJTZWxlY3Rvcik7XG4gICAgICAgICAqICAgICBjb25zdCBleGlzdGluZ0NvbG9yID0gdGFiRWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgICAgICAqICAgICB0YWJFbGVtZW50LnN0eWxlLmJhY2tncm91bmRDb2xvciA9IFwicmVkXCI7XG4gICAgICAgICAqICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICogICAgICAgICB0YWJFbGVtZW50LnN0eWxlLmJhY2tncm91bmRDb2xvciA9IGV4aXN0aW5nQ29sb3I7XG4gICAgICAgICAqICAgICB9LCAyMDAwKTtcbiAgICAgICAgICogfSk7XG4gICAgICAgICAqXG4gICAgICAgICAqIC8vIGluaXRpYWxpemUgdGhlIGxheW91dCBpbnRvIGFuIGV4aXN0aW5nIEhUTUwgZWxlbWVudCB3aXRoIHRoZSBkaXYgYG15LWN1c3RvbS1jb250YWluZXItaWRgXG4gICAgICAgICAqIC8vIHRoZSB3aW5kb3cgbXVzdCBoYXZlIGJlZW4gY3JlYXRlZCB3aXRoIGEgbGF5b3V0IGluIGl0cyB3aW5kb3cgb3B0aW9uc1xuICAgICAgICAgKiBjb25zdCBsYXlvdXQgPSBhd2FpdCBmaW4uUGxhdGZvcm0uTGF5b3V0LmluaXQoeyBjb250YWluZXJJZCB9KTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmluaXQgPSBhc3luYyAob3B0aW9ucyA9IHt9KSA9PiB7XG4gICAgICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignbGF5b3V0LWluaXQnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBpZiAoIXRoaXMud2lyZS5lbnZpcm9ubWVudC5sYXlvdXRBbGxvd2VkSW5Db250ZXh0KHRoaXMuZmluKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTGF5b3V0LmluaXQgY2FuIG9ubHkgYmUgY2FsbGVkIGZyb20gYSBXaW5kb3cgY29udGV4dC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDModGhpcywgX0xheW91dE1vZHVsZV9sYXlvdXRJbml0aWFsaXphdGlvbkF0dGVtcHRlZCwgXCJmXCIpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdMYXlvdXQuaW5pdCB3YXMgYWxyZWFkeSBjYWxsZWQsIHBsZWFzZSB1c2UgTGF5b3V0LmNyZWF0ZSB0byBhZGQgYWRkaXRpb25hbCBsYXlvdXRzLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMud2lyZS5lbnZpcm9ubWVudC50eXBlID09PSAnb3BlbmZpbicpIHtcbiAgICAgICAgICAgICAgICAvLyBwcmVsb2FkIHRoZSBjbGllbnRcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpLmdldENsaWVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQzKHRoaXMsIF9MYXlvdXRNb2R1bGVfbGF5b3V0SW5pdGlhbGl6YXRpb25BdHRlbXB0ZWQsIHRydWUsIFwiZlwiKTtcbiAgICAgICAgICAgIC8vIFRPRE86IHJlbmFtZSB0byBjcmVhdGVMYXlvdXRNYW5hZ2VyXG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDModGhpcywgX0xheW91dE1vZHVsZV9sYXlvdXRNYW5hZ2VyLCBhd2FpdCB0aGlzLndpcmUuZW52aXJvbm1lbnQuaW5pdExheW91dE1hbmFnZXIodGhpcy5maW4sIHRoaXMud2lyZSwgb3B0aW9ucyksIFwiZlwiKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMud2lyZS5lbnZpcm9ubWVudC5hcHBseUxheW91dFNuYXBzaG90KHRoaXMuZmluLCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDModGhpcywgX0xheW91dE1vZHVsZV9sYXlvdXRNYW5hZ2VyLCBcImZcIiksIG9wdGlvbnMpO1xuICAgICAgICAgICAgY29uc3QgbWVJZGVudGl0eSA9IHsgbmFtZTogdGhpcy5maW4ubWUubmFtZSwgdXVpZDogdGhpcy5maW4ubWUudXVpZCB9O1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zLmxheW91dE1hbmFnZXJPdmVycmlkZSkge1xuICAgICAgICAgICAgICAgIC8vIENPUkUtMTA4MSB0byBiZSByZW1vdmVkIHdoZW4gd2UgYWN0dWFsbHkgZGVsZXRlIHRoZSBgbGF5b3V0TWFuYWdlcmAgcHJvcFxuICAgICAgICAgICAgICAgIC8vIGluIHNpbmdsZS1sYXlvdXQgY2FzZSwgd2UgcmV0dXJuIHRoZSB1bmRvY3VtZW50ZWQgbGF5b3V0TWFuYWdlciB0eXBlXG4gICAgICAgICAgICAgICAgY29uc3QgbGF5b3V0SWRlbnRpdHkgPSB7IGxheW91dE5hbWU6IGxheW91dF9jb25zdGFudHNfMS5ERUZBVUxUX0xBWU9VVF9LRVksIC4uLm1lSWRlbnRpdHkgfTtcbiAgICAgICAgICAgICAgICByZXR1cm4gX19jbGFzc1ByaXZhdGVGaWVsZEdldCQzKHRoaXMsIF9MYXlvdXRNb2R1bGVfZ2V0TGF5b3V0TWFuYWdlclNweSwgXCJmXCIpLmNhbGwodGhpcywgbGF5b3V0SWRlbnRpdHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMud3JhcFN5bmMobWVJZGVudGl0eSk7XG4gICAgICAgIH07XG4gICAgICAgIF9MYXlvdXRNb2R1bGVfZ2V0TGF5b3V0TWFuYWdlclNweS5zZXQodGhpcywgKGxheW91dElkZW50aXR5KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBtc2cgPSAnW0xheW91dF0gWW91IGFyZSB1c2luZyBhIGRlcHJlY2F0ZWQgcHJvcGVydHkgYGxheW91dE1hbmFnZXJgIC0gaXQgd2lsbCB0aHJvdyBpZiB5b3UgYWNjZXNzIGl0IHN0YXJ0aW5nIGluIHYzNy4nO1xuICAgICAgICAgICAgY29uc3QgbWFuYWdlclByb3h5ID0gbmV3IFByb3h5KHt9LCB7XG4gICAgICAgICAgICAgICAgZ2V0KHRhcmdldCwga2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgW0xheW91dC1tZ3ItcHJveHldIGFjY2Vzc2luZyAke2tleS50b1N0cmluZygpfWApO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnN0IGxheW91dCA9IE9iamVjdC5hc3NpZ24odGhpcy53cmFwU3luYyhsYXlvdXRJZGVudGl0eSksIHsgbGF5b3V0TWFuYWdlcjogbWFuYWdlclByb3h5IH0pO1xuICAgICAgICAgICAgY29uc3QgbGF5b3V0UHJveHkgPSBuZXcgUHJveHkobGF5b3V0LCB7XG4gICAgICAgICAgICAgICAgZ2V0KHRhcmdldCwga2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgPT09ICdsYXlvdXRNYW5hZ2VyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbTGF5b3V0LXByb3h5XSBhY2Nlc3NpbmcgJHtrZXkudG9TdHJpbmcoKX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0YXJnZXRba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBsYXlvdXRQcm94eTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIHRoZSBsYXlvdXQgbWFuYWdlciBmb3IgdGhlIGN1cnJlbnQgd2luZG93XG4gICAgICAgICAqIEByZXR1cm5zXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmdldEN1cnJlbnRMYXlvdXRNYW5hZ2VyU3luYyA9ICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDModGhpcywgX0xheW91dE1vZHVsZV9pbnN0YW5jZXMsIFwibVwiLCBfTGF5b3V0TW9kdWxlX2dldFNhZmVMYXlvdXRNYW5hZ2VyKS5jYWxsKHRoaXMsIGBmaW4uUGxhdGZvcm0uTGF5b3V0LmdldEN1cnJlbnRMYXlvdXRNYW5hZ2VyU3luYygpYCk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY3JlYXRlID0gYXN5bmMgKG9wdGlvbnMpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuZW52aXJvbm1lbnQuY3JlYXRlTGF5b3V0KF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMyh0aGlzLCBfTGF5b3V0TW9kdWxlX2luc3RhbmNlcywgXCJtXCIsIF9MYXlvdXRNb2R1bGVfZ2V0U2FmZUxheW91dE1hbmFnZXIpLmNhbGwodGhpcywgYGZpbi5QbGF0Zm9ybS5MYXlvdXQuY3JlYXRlKClgKSwgb3B0aW9ucyk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZGVzdHJveSA9IGFzeW5jIChsYXlvdXRJZGVudGl0eSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5lbnZpcm9ubWVudC5kZXN0cm95TGF5b3V0KF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMyh0aGlzLCBfTGF5b3V0TW9kdWxlX2luc3RhbmNlcywgXCJtXCIsIF9MYXlvdXRNb2R1bGVfZ2V0U2FmZUxheW91dE1hbmFnZXIpLmNhbGwodGhpcywgYGZpbi5QbGF0Zm9ybS5MYXlvdXQuZGVzdHJveSgpYCksIGxheW91dElkZW50aXR5KTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhIExheW91dCBvYmplY3QgdGhhdCByZXByZXNlbnRzIGEgV2luZG93J3MgbGF5b3V0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGxldCB3aW5kb3dJZGVudGl0eTtcbiAgICAgKiBpZiAoIWZpbi5tZS5pc1dpbmRvdykge1xuICAgICAqICAgICB3aW5kb3dJZGVudGl0eSA9IGZpbi5tZS5pZGVudGl0eTtcbiAgICAgKiB9IGVsc2UgaWYgKGZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSAoYXdhaXQgZmluLm1lLmdldEN1cnJlbnRXaW5kb3coKSkuaWRlbnRpdHk7XG4gICAgICogfSBlbHNlIHtcbiAgICAgKiAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgcnVubmluZyBpbiBhIHBsYXRmb3JtIFZpZXcgb3IgV2luZG93Jyk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogY29uc3QgbGF5b3V0ID0gYXdhaXQgZmluLlBsYXRmb3JtLkxheW91dC53cmFwKHdpbmRvd0lkZW50aXR5KTtcbiAgICAgKiAvLyBVc2Ugd3JhcHBlZCBpbnN0YW5jZSB0byBjb250cm9sIGxheW91dCwgZS5nLjpcbiAgICAgKiBjb25zdCBsYXlvdXRDb25maWcgPSBhd2FpdCBsYXlvdXQuZ2V0Q29uZmlnKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgd3JhcChpZGVudGl0eSkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignbGF5b3V0LXdyYXAnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbmV3IEluc3RhbmNlXzEkMi5MYXlvdXQoaWRlbnRpdHksIHRoaXMud2lyZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN5bmNocm9ub3VzbHkgcmV0dXJucyBhIExheW91dCBvYmplY3QgdGhhdCByZXByZXNlbnRzIGEgV2luZG93J3MgbGF5b3V0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGxldCB3aW5kb3dJZGVudGl0eTtcbiAgICAgKiBpZiAoIWZpbi5tZS5pc1dpbmRvdykge1xuICAgICAqICAgICB3aW5kb3dJZGVudGl0eSA9IGZpbi5tZS5pZGVudGl0eTtcbiAgICAgKiB9IGVsc2UgaWYgKGZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSAoYXdhaXQgZmluLm1lLmdldEN1cnJlbnRXaW5kb3coKSkuaWRlbnRpdHk7XG4gICAgICogfSBlbHNlIHtcbiAgICAgKiAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgcnVubmluZyBpbiBhIHBsYXRmb3JtIFZpZXcgb3IgV2luZG93Jyk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogY29uc3QgbGF5b3V0ID0gZmluLlBsYXRmb3JtLkxheW91dC53cmFwU3luYyh3aW5kb3dJZGVudGl0eSk7XG4gICAgICogLy8gVXNlIHdyYXBwZWQgaW5zdGFuY2UgdG8gY29udHJvbCBsYXlvdXQsIGUuZy46XG4gICAgICogY29uc3QgbGF5b3V0Q29uZmlnID0gYXdhaXQgbGF5b3V0LmdldENvbmZpZygpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHdyYXBTeW5jKGlkZW50aXR5KSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdsYXlvdXQtd3JhcC1zeW5jJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnN0YW5jZV8xJDIuTGF5b3V0KGlkZW50aXR5LCB0aGlzLndpcmUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBc3luY2hyb25vdXNseSByZXR1cm5zIGEgTGF5b3V0IG9iamVjdCB0aGF0IHJlcHJlc2VudHMgYSBXaW5kb3cncyBsYXlvdXQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgbGF5b3V0ID0gYXdhaXQgZmluLlBsYXRmb3JtLkxheW91dC5nZXRDdXJyZW50KCk7XG4gICAgICogLy8gVXNlIHdyYXBwZWQgaW5zdGFuY2UgdG8gY29udHJvbCBsYXlvdXQsIGUuZy46XG4gICAgICogY29uc3QgbGF5b3V0Q29uZmlnID0gYXdhaXQgbGF5b3V0LmdldENvbmZpZygpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGdldEN1cnJlbnQoKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdsYXlvdXQtZ2V0LWN1cnJlbnQnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIXRoaXMuZmluLm1lLmlzV2luZG93KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBhcmUgbm90IGluIGEgV2luZG93IGNvbnRleHQuICBPbmx5IFdpbmRvd3MgY2FuIGhhdmUgYSBMYXlvdXQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSB0aGlzLmZpbi5tZTtcbiAgICAgICAgcmV0dXJuIHRoaXMud3JhcCh7IHV1aWQsIG5hbWUgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN5bmNocm9ub3VzbHkgcmV0dXJucyBhIExheW91dCBvYmplY3QgdGhhdCByZXByZXNlbnRzIGEgV2luZG93J3MgbGF5b3V0LlxuICAgICAqXG4gICAgICogQHJlbWFya3MgQ2Fubm90IGJlIGNhbGxlZCBmcm9tIGEgdmlldy5cbiAgICAgKlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IGxheW91dCA9IGZpbi5QbGF0Zm9ybS5MYXlvdXQuZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKiAvLyBVc2Ugd3JhcHBlZCBpbnN0YW5jZSB0byBjb250cm9sIGxheW91dCwgZS5nLjpcbiAgICAgKiBjb25zdCBsYXlvdXRDb25maWcgPSBhd2FpdCBsYXlvdXQuZ2V0Q29uZmlnKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0Q3VycmVudFN5bmMoKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdsYXlvdXQtZ2V0LWN1cnJlbnQtc3luYycpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghdGhpcy5maW4ubWUuaXNXaW5kb3cpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IGFyZSBub3QgaW4gYSBXaW5kb3cgY29udGV4dC4gIE9ubHkgV2luZG93cyBjYW4gaGF2ZSBhIExheW91dC4nKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IHRoaXMuZmluLm1lO1xuICAgICAgICByZXR1cm4gdGhpcy53cmFwU3luYyh7IHV1aWQsIG5hbWUgfSk7XG4gICAgfVxufVxuRmFjdG9yeSQyLkxheW91dE1vZHVsZSA9IExheW91dE1vZHVsZTtcbl9MYXlvdXRNb2R1bGVfbGF5b3V0SW5pdGlhbGl6YXRpb25BdHRlbXB0ZWQgPSBuZXcgV2Vha01hcCgpLCBfTGF5b3V0TW9kdWxlX2xheW91dE1hbmFnZXIgPSBuZXcgV2Vha01hcCgpLCBfTGF5b3V0TW9kdWxlX2dldExheW91dE1hbmFnZXJTcHkgPSBuZXcgV2Vha01hcCgpLCBfTGF5b3V0TW9kdWxlX2luc3RhbmNlcyA9IG5ldyBXZWFrU2V0KCksIF9MYXlvdXRNb2R1bGVfZ2V0U2FmZUxheW91dE1hbmFnZXIgPSBmdW5jdGlvbiBfTGF5b3V0TW9kdWxlX2dldFNhZmVMYXlvdXRNYW5hZ2VyKG1ldGhvZCkge1xuICAgIGlmICghX19jbGFzc1ByaXZhdGVGaWVsZEdldCQzKHRoaXMsIF9MYXlvdXRNb2R1bGVfbGF5b3V0TWFuYWdlciwgXCJmXCIpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgWW91IG11c3QgY2FsbCBpbml0IGJlZm9yZSB1c2luZyB0aGUgQVBJICR7bWV0aG9kfWApO1xuICAgIH1cbiAgICByZXR1cm4gX19jbGFzc1ByaXZhdGVGaWVsZEdldCQzKHRoaXMsIF9MYXlvdXRNb2R1bGVfbGF5b3V0TWFuYWdlciwgXCJmXCIpO1xufTtcblxuKGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdC8qKlxuXHQgKiBFbnRyeSBwb2ludCBmb3IgdGhlIE9wZW5GaW4gYExheW91dGAgc3Vic2V0IG9mIHRoZSBgUGxhdGZvcm1gIEFQSSAoYGZpbi5QbGF0Zm9ybS5MYXlvdXRgKS5cblx0ICpcblx0ICogKiB7QGxpbmsgTGF5b3V0TW9kdWxlfSBjb250YWlucyBzdGF0aWMgbWVtYmVycyBvZiB0aGUgYExheW91dGAgQVBJLCBhY2Nlc3NpYmxlIHRocm91Z2ggYGZpbi5QbGF0Zm9ybS5MYXlvdXRgLlxuXHQgKiAqIHtAbGluayBMYXlvdXR9IGRlc2NyaWJlcyBhbiBpbnN0YW5jZSBvZiBhbiBPcGVuRmluIExheW91dCwgZS5nLiBhcyByZXR1cm5lZCBieSBgZmluLlBsYXRmb3JtLkxheW91dC5nZXRDdXJyZW50YC5cblx0ICpcblx0ICogVGhlc2UgYXJlIHNlcGFyYXRlIGNvZGUgZW50aXRpZXMsIGFuZCBhcmUgZG9jdW1lbnRlZCBzZXBhcmF0ZWx5LiBJbiB0aGUgW3ByZXZpb3VzIHZlcnNpb24gb2YgdGhlIEFQSSBkb2N1bWVudGF0aW9uXShodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC8zMi4xMTQuNzYuMTAvaW5kZXguaHRtbCksXG5cdCAqIGJvdGggb2YgdGhlc2Ugd2VyZSBkb2N1bWVudGVkIG9uIHRoZSBzYW1lIHBhZ2UuXG5cdCAqXG5cdCAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuXHQgKlxuXHQgKi9cblx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0ICAgIH1cblx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgb1trMl0gPSBtW2tdO1xuXHR9KSk7XG5cdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0X19leHBvcnRTdGFyKEZhY3RvcnkkMiwgZXhwb3J0cyk7XG5cdF9fZXhwb3J0U3RhcihJbnN0YW5jZSQxLCBleHBvcnRzKTsgXG59IChsYXlvdXQpKTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KEZhY3RvcnkkMywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5GYWN0b3J5JDMuUGxhdGZvcm1Nb2R1bGUgPSB2b2lkIDA7XG5jb25zdCBiYXNlXzEkMyA9IGJhc2U7XG5jb25zdCBJbnN0YW5jZV8xJDEgPSBJbnN0YW5jZSQyO1xuY29uc3QgaW5kZXhfMSQxID0gbGF5b3V0O1xuLyoqXG4gKiBTdGF0aWMgbmFtZXNwYWNlIGZvciBPcGVuRmluIEFQSSBtZXRob2RzIHRoYXQgaW50ZXJhY3Qgd2l0aCB0aGUge0BsaW5rIFBsYXRmb3JtfSBjbGFzcywgYXZhaWxhYmxlIHVuZGVyIGBmaW4uUGxhdGZvcm1gLlxuICovXG5jbGFzcyBQbGF0Zm9ybU1vZHVsZSBleHRlbmRzIGJhc2VfMSQzLkJhc2Uge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHdpcmUsIGNoYW5uZWwpIHtcbiAgICAgICAgc3VwZXIod2lyZSk7XG4gICAgICAgIHRoaXMuX2NoYW5uZWwgPSBjaGFubmVsO1xuICAgICAgICAvKipcbiAgICAgICAgICpcbiAgICAgICAgICogQGRlc2MgTGF5b3V0cyBnaXZlIGFwcCBwcm92aWRlcnMgdGhlIGFiaWxpdHkgdG8gZW1iZWQgbXVsdGlwbGUgdmlld3MgaW4gYSBzaW5nbGUgd2luZG93LiAgVGhlIExheW91dCBuYW1lc3BhY2VcbiAgICAgICAgICogZW5hYmxlcyB0aGUgaW5pdGlhbGl6YXRpb24gYW5kIG1hbmlwdWxhdGlvbiBvZiBhIHdpbmRvdydzIExheW91dC4gIEEgTGF5b3V0IHdpbGxcbiAgICAgICAgICogPGEgaHJlZj1cInR1dG9yaWFsLUxheW91dC5ET01FdmVudHMuaHRtbFwiPmVtaXQgZXZlbnRzIGxvY2FsbHk8L2E+IG9uIHRoZSBET00gZWxlbWVudCByZXByZXNlbnRpbmcgdGhlIGxheW91dC1jb250YWluZXIuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLkxheW91dCA9IG5ldyBpbmRleF8xJDEuTGF5b3V0TW9kdWxlKHRoaXMud2lyZSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemVzIGEgUGxhdGZvcm0uIE11c3QgYmUgY2FsbGVkIGZyb20gdGhlIFByb3ZpZGVyIHdoZW4gdXNpbmcgYSBjdXN0b20gcHJvdmlkZXIuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBwbGF0Zm9ybSBvcHRpb25zIGluY2x1ZGluZyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgY2FuIGJlIHVzZWQgdG8gZXh0ZW5kIG9yIHJlcGxhY2VcbiAgICAgKiBkZWZhdWx0IFByb3ZpZGVyIGJlaGF2aW9yLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgTXVzdCBiZSBjYWxsZWQgZnJvbSB0aGUgUHJvdmlkZXIgd2hlbiB1c2luZyBhIGN1c3RvbSBwcm92aWRlci5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIC8vIEZyb20gUHJvdmlkZXIgY29udGV4dFxuICAgICAqIGF3YWl0IGZpbi5QbGF0Zm9ybS5pbml0KCk7XG4gICAgICogLy8gUGxhdGZvcm0gQVBJIGlzIG5vdyBob29rZWQgdXAgYW5kIHdpbmRvd3MgY29udGFpbmVkIGluIHRoZSBtYW5pZmVzdCBzbmFwc2hvdCBhcmUgb3Blbi5cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIGBQbGF0Zm9ybS5pbml0YCBhY2NlcHRzIGFuIG9wdGlvbnMgb2JqZWN0IHRoYXQgY2FuIGNvbnRhaW4gYSBjYWxsYmFjayBmdW5jdGlvbiB3aGljaCBjYW4gYmUgdXNlZCB0byBleHRlbmQgb3JcbiAgICAgKiByZXBsYWNlIGRlZmF1bHQgUHJvdmlkZXIgYmVoYXZpb3IuIEFzIGFuIGFyZ3VtZW50LCB0aGlzIGZ1bmN0aW9uIHdpbGwgcmVjZWl2ZSB0aGUgYFByb3ZpZGVyYCBjbGFzcywgd2hpY2ggaXNcbiAgICAgKiB1c2VkIHRvIGhhbmRsZSBQbGF0Zm9ybSBhY3Rpb25zLiBUaGUgZnVuY3Rpb24gbXVzdCByZXR1cm4gYW4gb2JqZWN0IHdpdGggbWV0aG9kcyB0byBoYW5kbGUgUGxhdGZvcm0gQVBJIGFjdGlvbnMuXG4gICAgICogVGhlIHJlY29tbWVuZGVkIGFwcHJvYWNoIGlzIHRvIGV4dGVuZCB0aGUgYFByb3ZpZGVyYCBjbGFzcywgb3ZlcnJpZGluZyB0aGUgbWV0aG9kcyB5b3Ugd2lzaCB0byBhbHRlciwgYW5kIHJldHVybiBhblxuICAgICAqIGluc3RhbmNlIG9mIHlvdXIgc3ViY2xhc3M6XG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IG92ZXJyaWRlQ2FsbGJhY2sgPSBhc3luYyAoUGxhdGZvcm1Qcm92aWRlcikgPT4ge1xuICAgICAqICAgICAvLyBBY3Rpb25zIGNhbiBiZSBwZXJmb3JtZWQgYmVmb3JlIGluaXRpYWxpemF0aW9uLlxuICAgICAqICAgICAvLyBlLmcuIHdlIG1pZ2h0IGF1dGhlbnRpY2F0ZSBhIHVzZXIsIHNldCB1cCBhIENoYW5uZWwsIGV0YyBiZWZvcmUgaW5pdGlhbGl6aW5nIHRoZSBQbGF0Zm9ybS5cbiAgICAgKiAgICAgY29uc3QgeyBtYW5pZmVzdFVybCB9ID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnRTeW5jKCkuZ2V0SW5mbygpO1xuICAgICAqXG4gICAgICogICAgIC8vIEV4dGVuZCBvciByZXBsYWNlIGRlZmF1bHQgUGxhdGZvcm1Qcm92aWRlciBiZWhhdmlvciBieSBleHRlbmRpbmcgdGhlIFBsYXRmb3JtUHJvdmlkZXIgY2xhc3MuXG4gICAgICogICAgIGNsYXNzIE15T3ZlcnJpZGUgZXh0ZW5kcyBQbGF0Zm9ybVByb3ZpZGVyIHtcbiAgICAgKiAgICAgICAgIC8vIERlZmF1bHQgYmVoYXZpb3IgY2FuIGJlIGNoYW5nZWQgYnkgaW1wbGVtZW50aW5nIG1ldGhvZHMgd2l0aCB0aGUgc2FtZSBuYW1lcyBhcyB0aG9zZSB1c2VkIGJ5IHRoZSBkZWZhdWx0IFBsYXRmb3JtUHJvdmlkZXIuXG4gICAgICogICAgICAgICBhc3luYyBnZXRTbmFwc2hvdCgpIHtcbiAgICAgKiAgICAgICAgICAgICAvLyBTaW5jZSB3ZSBhcmUgZXh0ZW5kaW5nIHRoZSBjbGFzcywgd2UgY2FuIGNhbGwgYHN1cGVyYCBtZXRob2RzIHRvIGFjY2VzcyBkZWZhdWx0IGJlaGF2aW9yLlxuICAgICAqICAgICAgICAgICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgc3VwZXIuZ2V0U25hcHNob3QoKTtcbiAgICAgKiAgICAgICAgICAgICAvLyBCdXQgd2UgY2FuIG1vZGlmeSByZXR1cm4gdmFsdWVzLlxuICAgICAqICAgICAgICAgICAgIHJldHVybiB7IC4uLnNuYXBzaG90LCBhbnN3ZXI6IDQyLCBtYW5pZmVzdFVybCB9O1xuICAgICAqICAgICAgICAgfVxuICAgICAqICAgICAgICAgYXN5bmMgcmVwbGFjZUxheW91dCh7IG9wdHMsIHRhcmdldCB9KSB7XG4gICAgICogICAgICAgICAgICAgLy8gVG8gZGlzYWJsZSBhbiBBUEkgbWV0aG9kLCBvdmVyd3JpdGUgd2l0aCBhIG5vb3AgZnVuY3Rpb24uXG4gICAgICogICAgICAgICAgICAgcmV0dXJuO1xuICAgICAqICAgICAgICAgfVxuICAgICAqICAgICB9XG4gICAgICogICAgIC8vIFJldHVybiBpbnN0YW5jZSB3aXRoIG1ldGhvZHMgdG8gYmUgY29uc3VtZWQgYnkgUGxhdGZvcm0uXG4gICAgICogICAgIC8vIFRoZSByZXR1cm5lZCBvYmplY3QgbXVzdCBpbXBsZW1lbnQgYWxsIG1ldGhvZHMgb2YgdGhlIFBsYXRmb3JtUHJvdmlkZXIgY2xhc3MuXG4gICAgICogICAgIC8vIEJ5IGV4dGVuZGluZyB0aGUgY2xhc3MsIHdlIGNhbiBzaW1wbHkgaW5oZXJpdCBtZXRob2RzIHdlIGRvIG5vdCB3aXNoIHRvIGFsdGVyLlxuICAgICAqICAgICByZXR1cm4gbmV3IE15T3ZlcnJpZGUoKTtcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogZmluLlBsYXRmb3JtLmluaXQoe292ZXJyaWRlQ2FsbGJhY2t9KTtcbiAgICAgKiBgYGBcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICovXG4gICAgYXN5bmMgaW5pdChvcHRpb25zKSB7XG4gICAgICAgIGlmICghZmluLl9faW50ZXJuYWxfLmlzUGxhdGZvcm0gfHwgZmluLm1lLm5hbWUgIT09IGZpbi5tZS51dWlkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Zpbi5QbGF0Zm9ybS5pbml0IHNob3VsZCBvbmx5IGJlIGNhbGxlZCBmcm9tIGEgY3VzdG9tIHBsYXRmb3JtIHByb3ZpZGVyIHJ1bm5pbmcgaW4gdGhlIG1haW4gd2luZG93IG9mIHRoZSBhcHBsaWNhdGlvbi4nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy53aXJlLmVudmlyb25tZW50LmluaXRQbGF0Zm9ybSh0aGlzLmZpbiwgb3B0aW9ucyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFzeW5jaHJvbm91c2x5IHJldHVybnMgYSBQbGF0Zm9ybSBvYmplY3QgdGhhdCByZXByZXNlbnRzIGFuIGV4aXN0aW5nIHBsYXRmb3JtLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHsgaWRlbnRpdHkgfSA9IGZpbi5tZTtcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS53cmFwKGlkZW50aXR5KTtcbiAgICAgKiAvLyBVc2Ugd3JhcHBlZCBpbnN0YW5jZSB0byBjb250cm9sIGxheW91dCwgZS5nLjpcbiAgICAgKiBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHBsYXRmb3JtLmdldFNuYXBzaG90KCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgd3JhcChpZGVudGl0eSkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0td3JhcCcpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMSQxLlBsYXRmb3JtKHsgdXVpZDogaWRlbnRpdHkudXVpZCB9LCB0aGlzLl9jaGFubmVsKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGEgUGxhdGZvcm0gb2JqZWN0IHRoYXQgcmVwcmVzZW50cyBhbiBleGlzdGluZyBwbGF0Zm9ybS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCB7IGlkZW50aXR5IH0gPSBmaW4ubWU7XG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0ud3JhcFN5bmMoaWRlbnRpdHkpO1xuICAgICAqIC8vIFVzZSB3cmFwcGVkIGluc3RhbmNlIHRvIGNvbnRyb2wgbGF5b3V0LCBlLmcuOlxuICAgICAqIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgcGxhdGZvcm0uZ2V0U25hcHNob3QoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICB3cmFwU3luYyhpZGVudGl0eSkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0td3JhcC1zeW5jJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnN0YW5jZV8xJDEuUGxhdGZvcm0oeyB1dWlkOiBpZGVudGl0eS51dWlkIH0sIHRoaXMuX2NoYW5uZWwpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBc3luY2hyb25vdXNseSByZXR1cm5zIGEgUGxhdGZvcm0gb2JqZWN0IHRoYXQgcmVwcmVzZW50cyB0aGUgY3VycmVudCBwbGF0Zm9ybS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50KCk7XG4gICAgICogLy8gVXNlIHdyYXBwZWQgaW5zdGFuY2UgdG8gY29udHJvbCBsYXlvdXQsIGUuZy46XG4gICAgICogY29uc3Qgc25hcHNob3QgPSBhd2FpdCBwbGF0Zm9ybS5nZXRTbmFwc2hvdCgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGdldEN1cnJlbnQoKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwbGF0Zm9ybS1nZXQtY3VycmVudCcpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzLndyYXAoeyB1dWlkOiB0aGlzLndpcmUubWUudXVpZCB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGEgUGxhdGZvcm0gb2JqZWN0IHRoYXQgcmVwcmVzZW50cyB0aGUgY3VycmVudCBwbGF0Zm9ybS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIC8vIFVzZSB3cmFwcGVkIGluc3RhbmNlIHRvIGNvbnRyb2wgbGF5b3V0LCBlLmcuOlxuICAgICAqIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgcGxhdGZvcm0uZ2V0U25hcHNob3QoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRDdXJyZW50U3luYygpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLWdldC1jdXJyZW50LXN5bmMnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcy53cmFwU3luYyh7IHV1aWQ6IHRoaXMud2lyZS5tZS51dWlkIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuZCBzdGFydHMgYSBQbGF0Zm9ybSBhbmQgcmV0dXJucyBhIHdyYXBwZWQgYW5kIHJ1bm5pbmcgUGxhdGZvcm0gaW5zdGFuY2UuIFRoZSB3cmFwcGVkIFBsYXRmb3JtIG1ldGhvZHMgY2FuXG4gICAgICogYmUgdXNlZCB0byBsYXVuY2ggY29udGVudCBpbnRvIHRoZSBwbGF0Zm9ybS4gIFByb21pc2Ugd2lsbCByZWplY3QgaWYgdGhlIHBsYXRmb3JtIGlzIGFscmVhZHkgcnVubmluZy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiB0cnkge1xuICAgICAqICAgICBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5zdGFydCh7XG4gICAgICogICAgICAgICB1dWlkOiAncGxhdGZvcm0tMScsXG4gICAgICogICAgICAgICBhdXRvU2hvdzogZmFsc2UsXG4gICAgICogICAgICAgICBkZWZhdWx0V2luZG93T3B0aW9uczoge1xuICAgICAqICAgICAgICAgICAgIHN0eWxlc2hlZXRVcmw6ICdjc3Mtc2hlZXQtdXJsJyxcbiAgICAgKiAgICAgICAgICAgICBjb3JuZXJSb3VuZGluZzoge1xuICAgICAqICAgICAgICAgICAgICAgICBoZWlnaHQ6IDEwLFxuICAgICAqICAgICAgICAgICAgICAgICB3aWR0aDogMTBcbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICB9XG4gICAgICogICAgIH0pO1xuICAgICAqICAgICBjb25zb2xlLmxvZygnUGxhdGZvcm0gaXMgcnVubmluZycsIHBsYXRmb3JtKTtcbiAgICAgKiB9IGNhdGNoKGUpIHtcbiAgICAgKiAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgc3RhcnQocGxhdGZvcm1PcHRpb25zKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwbGF0Zm9ybS1zdGFydCcpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hc3luYy1wcm9taXNlLWV4ZWN1dG9yXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgdXVpZCB9ID0gcGxhdGZvcm1PcHRpb25zO1xuICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgdXNpbmcgcHJpdmF0ZSB2YXJpYWJsZS5cbiAgICAgICAgICAgICAgICBjb25zdCBhcHAgPSBhd2FpdCB0aGlzLmZpbi5BcHBsaWNhdGlvbi5fY3JlYXRlKHsgLi4ucGxhdGZvcm1PcHRpb25zLCBpc1BsYXRmb3JtQ29udHJvbGxlcjogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBmaXggdHlwaW5nIChpbnRlcm5hbClcbiAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgICAgICAgICAgYXBwLm9uY2UoJ3BsYXRmb3JtLWFwaS1yZWFkeScsICgpID0+IHJlc29sdmUodGhpcy53cmFwU3luYyh7IHV1aWQgfSkpKTtcbiAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHVzaW5nIHByaXZhdGUgdmFyaWFibGUuXG4gICAgICAgICAgICAgICAgYXBwLl9ydW4oeyB1dWlkIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgcGxhdGZvcm1zJ3MgbWFuaWZlc3QgYW5kIHJldHVybnMgYSB3cmFwcGVkIGFuZCBydW5uaW5nIFBsYXRmb3JtLiAgSWYgdGhlcmUgaXMgYSBzbmFwc2hvdCBpbiB0aGUgbWFuaWZlc3QsXG4gICAgICogaXQgd2lsbCBiZSBsYXVuY2hlZCBpbnRvIHRoZSBwbGF0Zm9ybS5cbiAgICAgKiBAcGFyYW0gbWFuaWZlc3RVcmwgLSBUaGUgVVJMIG9mIHBsYXRmb3JtJ3MgbWFuaWZlc3QuXG4gICAgICogQHBhcmFtIG9wdHMgLSBQYXJhbWV0ZXJzIHRoYXQgdGhlIFJWTSB3aWxsIHVzZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiB0cnkge1xuICAgICAqICAgICBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5zdGFydEZyb21NYW5pZmVzdCgnaHR0cHM6Ly9vcGVuZmluLmdpdGh1Yi5pby9nb2xkZW4tcHJvdG90eXBlL3B1YmxpYy5qc29uJyk7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdQbGF0Zm9ybSBpcyBydW5uaW5nLCB3cmFwcGVkIHBsYXRmb3JtOiAnLCBwbGF0Zm9ybSk7XG4gICAgICogfSBjYXRjaChlKSB7XG4gICAgICogICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICogfVxuICAgICAqIC8vIEZvciBhIGxvY2FsIG1hbmlmZXN0IGZpbGU6XG4gICAgICogdHJ5IHtcbiAgICAgKiAgICAgY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0uc3RhcnRGcm9tTWFuaWZlc3QoJ2ZpbGU6Ly8vQzovc29tZWZvbGRlci9hcHAuanNvbicpO1xuICAgICAqICAgICBjb25zb2xlLmxvZygnUGxhdGZvcm0gaXMgcnVubmluZywgd3JhcHBlZCBwbGF0Zm9ybTogJywgcGxhdGZvcm0pO1xuICAgICAqIH0gY2F0Y2goZSkge1xuICAgICAqICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBzdGFydEZyb21NYW5pZmVzdChtYW5pZmVzdFVybCwgb3B0cykge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tc3RhcnQtZnJvbS1tYW5pZmVzdCcpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hc3luYy1wcm9taXNlLWV4ZWN1dG9yXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgdXNpbmcgcHJpdmF0ZSB2YXJpYWJsZS5cbiAgICAgICAgICAgICAgICBjb25zdCBhcHAgPSBhd2FpdCB0aGlzLmZpbi5BcHBsaWNhdGlvbi5fY3JlYXRlRnJvbU1hbmlmZXN0KG1hbmlmZXN0VXJsKTtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBmaXggdHlwaW5nIChpbnRlcm5hbClcbiAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgICAgICAgICAgYXBwLm9uY2UoJ3BsYXRmb3JtLWFwaS1yZWFkeScsICgpID0+IHJlc29sdmUodGhpcy53cmFwU3luYyh7IHV1aWQ6IGFwcC5pZGVudGl0eS51dWlkIH0pKSk7XG4gICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciB1c2luZyBwcml2YXRlIG1ldGhvZCB3aXRob3V0IHdhcm5pbmcuXG4gICAgICAgICAgICAgICAgYXBwLl9ydW4ob3B0cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufVxuRmFjdG9yeSQzLlBsYXRmb3JtTW9kdWxlID0gUGxhdGZvcm1Nb2R1bGU7XG5cbihmdW5jdGlvbiAoZXhwb3J0cykge1xuXHR2YXIgX19jcmVhdGVCaW5kaW5nID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY3JlYXRlQmluZGluZykgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdCAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XG5cdCAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xuXHQgICAgICBkZXNjID0geyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbVtrXTsgfSB9O1xuXHQgICAgfVxuXHQgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcblx0fSkgOiAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdCAgICBvW2syXSA9IG1ba107XG5cdH0pKTtcblx0dmFyIF9fZXhwb3J0U3RhciA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2V4cG9ydFN0YXIpIHx8IGZ1bmN0aW9uKG0sIGV4cG9ydHMpIHtcblx0ICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZXhwb3J0cywgcCkpIF9fY3JlYXRlQmluZGluZyhleHBvcnRzLCBtLCBwKTtcblx0fTtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHQvKipcblx0ICogRW50cnkgcG9pbnRzIGZvciB0aGUgT3BlbkZpbiBgUGxhdGZvcm1gIEFQSSAoYGZpbi5QbGF0Zm9ybWApXG5cdCAqXG5cdCAqICoge0BsaW5rIFBsYXRmb3JtTW9kdWxlfSBjb250YWlucyBzdGF0aWMgbWVtYmVycyBvZiB0aGUgYFBsYXRmb3JtYCBBUEksIGFjY2Vzc2libGUgdGhyb3VnaCBgZmluLlBsYXRmb3JtYC5cblx0ICogKiB7QGxpbmsgUGxhdGZvcm19IGRlc2NyaWJlcyBhbiBpbnN0YW5jZSBvZiBhbiBPcGVuRmluIFBsYXRmb3JtLCBlLmcuIGFzIHJldHVybmVkIGJ5IGBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudGAuXG5cdCAqXG5cdCAqIFRoZXNlIGFyZSBzZXBhcmF0ZSBjb2RlIGVudGl0aWVzLCBhbmQgYXJlIGRvY3VtZW50ZWQgc2VwYXJhdGVseS4gIEluIHRoZSBbcHJldmlvdXMgdmVyc2lvbiBvZiB0aGUgQVBJIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0LzMyLjExNC43Ni4xMC9pbmRleC5odG1sKSxcblx0ICogYm90aCBvZiB0aGVzZSB3ZXJlIGRvY3VtZW50ZWQgb24gdGhlIHNhbWUgcGFnZS5cblx0ICpcblx0ICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG5cdCAqL1xuXHRfX2V4cG9ydFN0YXIoRmFjdG9yeSQzLCBleHBvcnRzKTtcblx0X19leHBvcnRTdGFyKEluc3RhbmNlJDIsIGV4cG9ydHMpOyBcbn0gKHBsYXRmb3JtKSk7XG5cbnZhciBtZSA9IHt9O1xuXG4oZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRleHBvcnRzLmdldE1lID0gZXhwb3J0cy5nZXRCYXNlTWUgPSBleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlID0gdm9pZCAwO1xuXHRjb25zdCB2aWV3XzEgPSByZXF1aXJlVmlldygpO1xuXHRjb25zdCBmcmFtZV8xID0gZnJhbWU7XG5cdGNvbnN0IHdpbmRvd18xID0gcmVxdWlyZVdpbmRvdygpO1xuXHRjb25zdCBleHRlcm5hbF9hcHBsaWNhdGlvbl8xID0gZXh0ZXJuYWxBcHBsaWNhdGlvbjtcblx0ZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSA9ICdZb3UgYXJlIG5vdCBydW5uaW5nIGluIE9wZW5GaW4uJztcblx0ZnVuY3Rpb24gZ2V0QmFzZU1lKGVudGl0eVR5cGUsIHV1aWQsIG5hbWUpIHtcblx0ICAgIGNvbnN0IGVudGl0eVR5cGVIZWxwZXJzID0ge1xuXHQgICAgICAgIGlzVmlldzogZW50aXR5VHlwZSA9PT0gJ3ZpZXcnLFxuXHQgICAgICAgIGlzV2luZG93OiBlbnRpdHlUeXBlID09PSAnd2luZG93Jyxcblx0ICAgICAgICBpc0ZyYW1lOiBlbnRpdHlUeXBlID09PSAnaWZyYW1lJyxcblx0ICAgICAgICBpc0V4dGVybmFsOiBlbnRpdHlUeXBlID09PSAnZXh0ZXJuYWwgY29ubmVjdGlvbidcblx0ICAgIH07XG5cdCAgICByZXR1cm4geyAuLi5lbnRpdHlUeXBlSGVscGVycywgdXVpZCwgbmFtZSwgZW50aXR5VHlwZSB9O1xuXHR9XG5cdGV4cG9ydHMuZ2V0QmFzZU1lID0gZ2V0QmFzZU1lO1xuXHQvLyBXZSBuZWVkIHRvIGRvIGEgbG90IG9mIGNhc3RpbmcgYXMgdW5rbm93biBoZXJlIGJlY2F1c2UgdGhlIGNvbXBpbGVyIGdldCdzIGNvbmZ1c2VkIGFib3V0IG1hdGNoaW5nIHR5cGVzLiBXaGF0IG1hdHRlcnMgaXMgdGhhdCBpdCB3b3JrcyBvbiB0aGUgb3V0c2lkZVxuXHRmdW5jdGlvbiBnZXRNZSh3aXJlKSB7XG5cdCAgICBjb25zdCB7IHV1aWQsIG5hbWUsIGVudGl0eVR5cGUgfSA9IHdpcmUubWU7XG5cdCAgICBjb25zdCB1bnN1cHBvcnRlZEludGVyb3AgPSB7XG5cdCAgICAgICAgc2V0Q29udGV4dCgpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGV4cG9ydHMuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgYWRkQ29udGV4dEhhbmRsZXIoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGdldENvbnRleHRHcm91cHMoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGpvaW5Db250ZXh0R3JvdXAoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHJlbW92ZUZyb21Db250ZXh0R3JvdXAoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGdldEFsbENsaWVudHNJbkNvbnRleHRHcm91cCgpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGV4cG9ydHMuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgZ2V0SW5mb0ZvckNvbnRleHRHcm91cCgpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGV4cG9ydHMuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuXHQgICAgICAgIH1cblx0ICAgIH07XG5cdCAgICBjb25zdCBmYWxsYmFja0Vycm9yTWVzc2FnZSA9ICdJbnRlcm9wIEFQSSBoYXMgbm90IGJlZW4gaW5zdGFudGlhdGVkLiBFaXRoZXIgY29ubmVjdGlvbiBoYXMgZmFpbGVkIG9yIHlvdSBoYXZlIG5vdCBkZWNsYXJlZCBpbnRlcm9wIGluIHlvdXIgY29uZmlnLic7XG5cdCAgICBjb25zdCBmYWxsYmFja0ludGVyb3AgPSB7XG5cdCAgICAgICAgc2V0Q29udGV4dCgpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGZhbGxiYWNrRXJyb3JNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGFkZENvbnRleHRIYW5kbGVyKCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZmFsbGJhY2tFcnJvck1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgZ2V0Q29udGV4dEdyb3VwcygpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGZhbGxiYWNrRXJyb3JNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGpvaW5Db250ZXh0R3JvdXAoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihmYWxsYmFja0Vycm9yTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICByZW1vdmVGcm9tQ29udGV4dEdyb3VwKCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZmFsbGJhY2tFcnJvck1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgZ2V0QWxsQ2xpZW50c0luQ29udGV4dEdyb3VwKCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZmFsbGJhY2tFcnJvck1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgZ2V0SW5mb0ZvckNvbnRleHRHcm91cCgpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGZhbGxiYWNrRXJyb3JNZXNzYWdlKTtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXHQgICAgY29uc3QgdW5zdXBwb3J0ZWRFdmVudEJhc2UgPSB7XG5cdCAgICAgICAgZXZlbnROYW1lczogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBlbWl0OiAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGxpc3RlbmVyczogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBsaXN0ZW5lckNvdW50OiAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIG9uOiAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGFkZExpc3RlbmVyOiAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIG9uY2U6ICgpID0+IHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGV4cG9ydHMuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgcHJlcGVuZExpc3RlbmVyOiAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHByZXBlbmRPbmNlTGlzdGVuZXI6ICgpID0+IHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGV4cG9ydHMuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgcmVtb3ZlTGlzdGVuZXI6ICgpID0+IHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGV4cG9ydHMuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgcmVtb3ZlQWxsTGlzdGVuZXJzOiAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXHQgICAgc3dpdGNoIChlbnRpdHlUeXBlKSB7XG5cdCAgICAgICAgY2FzZSAndmlldyc6XG5cdCAgICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKG5ldyB2aWV3XzEuVmlldyh3aXJlLCB7IHV1aWQsIG5hbWUgfSksIGdldEJhc2VNZShlbnRpdHlUeXBlLCB1dWlkLCBuYW1lKSwge1xuXHQgICAgICAgICAgICAgICAgaW50ZXJvcDogZmFsbGJhY2tJbnRlcm9wLFxuXHQgICAgICAgICAgICAgICAgaXNPcGVuRmluOiB0cnVlXG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgIGNhc2UgJ3dpbmRvdyc6XG5cdCAgICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKG5ldyB3aW5kb3dfMS5fV2luZG93KHdpcmUsIHsgdXVpZCwgbmFtZSB9KSwgZ2V0QmFzZU1lKGVudGl0eVR5cGUsIHV1aWQsIG5hbWUpLCB7XG5cdCAgICAgICAgICAgICAgICBpbnRlcm9wOiBmYWxsYmFja0ludGVyb3AsXG5cdCAgICAgICAgICAgICAgICBpc09wZW5GaW46IHRydWVcblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgY2FzZSAnaWZyYW1lJzpcblx0ICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24obmV3IGZyYW1lXzEuX0ZyYW1lKHdpcmUsIHsgdXVpZCwgbmFtZSB9KSwgZ2V0QmFzZU1lKGVudGl0eVR5cGUsIHV1aWQsIG5hbWUpLCB7XG5cdCAgICAgICAgICAgICAgICBpbnRlcm9wOiBmYWxsYmFja0ludGVyb3AsXG5cdCAgICAgICAgICAgICAgICBpc09wZW5GaW46IHRydWVcblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgY2FzZSAnZXh0ZXJuYWwgY29ubmVjdGlvbic6XG5cdCAgICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKG5ldyBleHRlcm5hbF9hcHBsaWNhdGlvbl8xLkV4dGVybmFsQXBwbGljYXRpb24od2lyZSwgeyB1dWlkIH0pLCBnZXRCYXNlTWUoZW50aXR5VHlwZSwgdXVpZCwgbmFtZSksIHtcblx0ICAgICAgICAgICAgICAgIGludGVyb3A6IGZhbGxiYWNrSW50ZXJvcCxcblx0ICAgICAgICAgICAgICAgIGlzT3BlbkZpbjogZmFsc2Vcblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgZGVmYXVsdDpcblx0ICAgICAgICAgICAgcmV0dXJuIHtcblx0ICAgICAgICAgICAgICAgIC4uLmdldEJhc2VNZShlbnRpdHlUeXBlLCB1dWlkLCBuYW1lKSxcblx0ICAgICAgICAgICAgICAgIC4uLnVuc3VwcG9ydGVkRXZlbnRCYXNlLFxuXHQgICAgICAgICAgICAgICAgaW50ZXJvcDogdW5zdXBwb3J0ZWRJbnRlcm9wLFxuXHQgICAgICAgICAgICAgICAgaXNPcGVuRmluOiBmYWxzZVxuXHQgICAgICAgICAgICB9O1xuXHQgICAgfVxuXHR9XG5cdGV4cG9ydHMuZ2V0TWUgPSBnZXRNZTsgXG59IChtZSkpO1xuXG52YXIgaW50ZXJvcCA9IHt9O1xuXG52YXIgRmFjdG9yeSQxID0ge307XG5cbnZhciBpbmFjY2Vzc2libGVPYmplY3QgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGluYWNjZXNzaWJsZU9iamVjdCwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5pbmFjY2Vzc2libGVPYmplY3QuY3JlYXRlV2FybmluZ09iamVjdCA9IGluYWNjZXNzaWJsZU9iamVjdC5jcmVhdGVVbnVzYWJsZU9iamVjdCA9IHZvaWQgMDtcbmZ1bmN0aW9uIGNyZWF0ZVVudXNhYmxlT2JqZWN0KG1lc3NhZ2UpIHtcbiAgICBjb25zdCBoYW5kbGUgPSAoKSA9PiB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgICB9O1xuICAgIHJldHVybiBuZXcgUHJveHkoe30sIHtcbiAgICAgICAgYXBwbHk6IGhhbmRsZSxcbiAgICAgICAgY29uc3RydWN0OiBoYW5kbGUsXG4gICAgICAgIGRlZmluZVByb3BlcnR5OiBoYW5kbGUsXG4gICAgICAgIGRlbGV0ZVByb3BlcnR5OiBoYW5kbGUsXG4gICAgICAgIGdldDogaGFuZGxlLFxuICAgICAgICBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I6IGhhbmRsZSxcbiAgICAgICAgZ2V0UHJvdG90eXBlT2Y6IGhhbmRsZSxcbiAgICAgICAgaGFzOiBoYW5kbGUsXG4gICAgICAgIGlzRXh0ZW5zaWJsZTogaGFuZGxlLFxuICAgICAgICBvd25LZXlzOiBoYW5kbGUsXG4gICAgICAgIHByZXZlbnRFeHRlbnNpb25zOiBoYW5kbGUsXG4gICAgICAgIHNldDogaGFuZGxlLFxuICAgICAgICBzZXRQcm90b3R5cGVPZjogaGFuZGxlXG4gICAgfSk7XG59XG5pbmFjY2Vzc2libGVPYmplY3QuY3JlYXRlVW51c2FibGVPYmplY3QgPSBjcmVhdGVVbnVzYWJsZU9iamVjdDtcbmZ1bmN0aW9uIGNyZWF0ZVdhcm5pbmdPYmplY3QobWVzc2FnZSwgb2JqKSB7XG4gICAgcmV0dXJuIG5ldyBQcm94eShvYmosIHtcbiAgICAgICAgZ2V0OiAoLi4uYXJncykgPT4ge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihtZXNzYWdlKTtcbiAgICAgICAgICAgIHJldHVybiBSZWZsZWN0LmdldCguLi5hcmdzKTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0OiAoLi4uYXJncykgPT4ge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihtZXNzYWdlKTtcbiAgICAgICAgICAgIHJldHVybiBSZWZsZWN0LnNldCguLi5hcmdzKTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOiAoLi4uYXJncykgPT4ge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihtZXNzYWdlKTtcbiAgICAgICAgICAgIHJldHVybiBSZWZsZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvciguLi5hcmdzKTtcbiAgICAgICAgfSxcbiAgICAgICAgb3duS2V5czogKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgICBjb25zb2xlLndhcm4obWVzc2FnZSk7XG4gICAgICAgICAgICByZXR1cm4gUmVmbGVjdC5vd25LZXlzKC4uLmFyZ3MpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5pbmFjY2Vzc2libGVPYmplY3QuY3JlYXRlV2FybmluZ09iamVjdCA9IGNyZWF0ZVdhcm5pbmdPYmplY3Q7XG5cbnZhciBJbnRlcm9wQnJva2VyID0ge307XG5cbnZhciBTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyID0ge307XG5cbnZhciBoYXNSZXF1aXJlZFNlc3Npb25Db250ZXh0R3JvdXBCcm9rZXI7XG5cbmZ1bmN0aW9uIHJlcXVpcmVTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlcikgcmV0dXJuIFNlc3Npb25Db250ZXh0R3JvdXBCcm9rZXI7XG5cdGhhc1JlcXVpcmVkU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlciA9IDE7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0Y29uc3QgXzEgPSByZXF1aXJlSW50ZXJvcCgpO1xuXHRsZXQgU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlciQxID0gY2xhc3MgU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlciB7XG5cdCAgICBjb25zdHJ1Y3Rvcihwcm92aWRlciwgaWQpIHtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyID0gcHJvdmlkZXI7XG5cdCAgICAgICAgdGhpcy5pZCA9IGlkO1xuXHQgICAgICAgIHRoaXMubGFzdENvbnRleHQgPSB1bmRlZmluZWQ7XG5cdCAgICAgICAgdGhpcy5jb250ZXh0R3JvdXBNYXAgPSBuZXcgTWFwKCk7XG5cdCAgICAgICAgdGhpcy5jbGllbnRzID0gbmV3IE1hcCgpO1xuXHQgICAgICAgIHRoaXMucmVnaXN0ZXJMaXN0ZW5lcnMoKTtcblx0ICAgIH1cblx0ICAgIHJlZ2lzdGVyTGlzdGVuZXJzKCkge1xuXHQgICAgICAgIHRoaXMucHJvdmlkZXIucmVnaXN0ZXIoYHNlc3Npb25Db250ZXh0R3JvdXA6Z2V0Q29udGV4dC0ke3RoaXMuaWR9YCwgdGhpcy5nZXRDdXJyZW50Q29udGV4dC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLnJlZ2lzdGVyKGBzZXNzaW9uQ29udGV4dEdyb3VwOnNldENvbnRleHQtJHt0aGlzLmlkfWAsIHRoaXMuc2V0Q29udGV4dC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLnJlZ2lzdGVyKGBzZXNzaW9uQ29udGV4dEdyb3VwOmhhbmRsZXJBZGRlZC0ke3RoaXMuaWR9YCwgdGhpcy5oYW5kbGVyQWRkZWQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlci5yZWdpc3Rlcihgc2Vzc2lvbkNvbnRleHRHcm91cDpoYW5kbGVyUmVtb3ZlZC0ke3RoaXMuaWR9YCwgdGhpcy5oYW5kbGVyUmVtb3ZlZC5iaW5kKHRoaXMpKTtcblx0ICAgIH1cblx0ICAgIGdldEN1cnJlbnRDb250ZXh0KHBheWxvYWQpIHtcblx0ICAgICAgICByZXR1cm4gcGF5bG9hZC50eXBlID8gdGhpcy5jb250ZXh0R3JvdXBNYXAuZ2V0KHBheWxvYWQudHlwZSkgOiB0aGlzLmxhc3RDb250ZXh0O1xuXHQgICAgfVxuXHQgICAgc2V0Q29udGV4dChwYXlsb2FkLCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IHsgY29udGV4dCB9ID0gcGF5bG9hZDtcblx0ICAgICAgICBjb25zdCBjb250ZXh0SW50ZWdyaXR5Q2hlY2tSZXN1bHQgPSBfMS5JbnRlcm9wQnJva2VyLmNoZWNrQ29udGV4dEludGVncml0eShjb250ZXh0KTtcblx0ICAgICAgICBpZiAoY29udGV4dEludGVncml0eUNoZWNrUmVzdWx0LmlzVmFsaWQgPT09IGZhbHNlKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHNldCBDb250ZXh0IC0gYmFkIENvbnRleHQuIFJlYXNvbjogJHtjb250ZXh0SW50ZWdyaXR5Q2hlY2tSZXN1bHQucmVhc29ufS4gQ29udGV4dDogJHtKU09OLnN0cmluZ2lmeShjb250ZXh0KX1gKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3QgY2xpZW50U3RhdGUgPSB0aGlzLmdldENsaWVudFN0YXRlKGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICBpZiAoIWNsaWVudFN0YXRlKSB7XG5cdCAgICAgICAgICAgIC8vIFRoaXMgc2hvdWxkbid0IGdldCBoaXQuXG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2xpZW50IHdpdGggSWRlbnRpdHk6ICR7Y2xpZW50SWRlbnRpdHkudXVpZH0gJHtjbGllbnRJZGVudGl0eS5uYW1lfSBub3QgaW4gU2Vzc2lvbiBDbGllbnQgU3RhdGUgTWFwYCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIC8vIHNldCB0aGUgY29udGV4dFxuXHQgICAgICAgIHRoaXMuY29udGV4dEdyb3VwTWFwLnNldChjb250ZXh0LnR5cGUsIGNvbnRleHQpO1xuXHQgICAgICAgIHRoaXMubGFzdENvbnRleHQgPSBjb250ZXh0O1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN1YnNjcmlwdGlvblN0YXRlcyA9IEFycmF5LmZyb20odGhpcy5jbGllbnRzLnZhbHVlcygpKTtcblx0ICAgICAgICBjbGllbnRTdWJzY3JpcHRpb25TdGF0ZXMuZm9yRWFjaCgoY2xpZW50KSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtZXhwcmVzc2lvbnNcblx0ICAgICAgICAgICAgY2xpZW50LmNvbnRleHRIYW5kbGVycy5nZXQoY29udGV4dC50eXBlKT8uZm9yRWFjaCgoaGFuZGxlcklkKSA9PiB7XG5cdCAgICAgICAgICAgICAgICB0aGlzLnByb3ZpZGVyLmRpc3BhdGNoKGNsaWVudC5jbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBjb250ZXh0KTtcblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgIGlmIChjbGllbnQuZ2xvYmFsSGFuZGxlcikge1xuXHQgICAgICAgICAgICAgICAgdGhpcy5wcm92aWRlci5kaXNwYXRjaChjbGllbnQuY2xpZW50SWRlbnRpdHksIGNsaWVudC5nbG9iYWxIYW5kbGVyLCBjb250ZXh0KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgZ2V0Q2xpZW50U3RhdGUoaWQpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy5jbGllbnRzLmdldChpZC5lbmRwb2ludElkKTtcblx0ICAgIH1cblx0ICAgIGFzeW5jIGhhbmRsZXJBZGRlZChwYXlsb2FkLCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IHsgaGFuZGxlcklkLCBjb250ZXh0VHlwZSB9ID0gcGF5bG9hZDtcblx0ICAgICAgICBjb25zdCBjbGllbnRTdWJzY3JpcHRpb25TdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGlmICghY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDbGllbnQgd2l0aCBJZGVudGl0eTogJHtjbGllbnRJZGVudGl0eS51dWlkfSAke2NsaWVudElkZW50aXR5Lm5hbWV9IG5vdCBpbiBDbGllbnQgU3RhdGUgTWFwYCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmIChjb250ZXh0VHlwZSkge1xuXHQgICAgICAgICAgICBjb25zdCBjdXJyZW50SGFuZGxlckxpc3QgPSBjbGllbnRTdWJzY3JpcHRpb25TdGF0ZS5jb250ZXh0SGFuZGxlcnMuZ2V0KGNvbnRleHRUeXBlKSB8fCBbXTtcblx0ICAgICAgICAgICAgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUuY29udGV4dEhhbmRsZXJzLnNldChjb250ZXh0VHlwZSwgWy4uLmN1cnJlbnRIYW5kbGVyTGlzdCwgaGFuZGxlcklkXSk7XG5cdCAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRDb250ZXh0ID0gdGhpcy5jb250ZXh0R3JvdXBNYXAuZ2V0KGNvbnRleHRUeXBlKTtcblx0ICAgICAgICAgICAgaWYgKGN1cnJlbnRDb250ZXh0KSB7XG5cdCAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnByb3ZpZGVyLmRpc3BhdGNoKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGN1cnJlbnRDb250ZXh0KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUuZ2xvYmFsSGFuZGxlciA9IGhhbmRsZXJJZDtcblx0ICAgICAgICAgICAgY29uc3QgZ2xvYmFsRGlzcGF0Y2hQcm9taXNlcyA9IFsuLi50aGlzLmNvbnRleHRHcm91cE1hcC5rZXlzKCldLm1hcChhc3luYyAoY3VycmVudENvbnRleHRUeXBlKSA9PiB7XG5cdCAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50Q29udGV4dCA9IHRoaXMuY29udGV4dEdyb3VwTWFwLmdldChjdXJyZW50Q29udGV4dFR5cGUpO1xuXHQgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRDb250ZXh0KSB7XG5cdCAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wcm92aWRlci5kaXNwYXRjaChjbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBjdXJyZW50Q29udGV4dCk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChnbG9iYWxEaXNwYXRjaFByb21pc2VzKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICBoYW5kbGVyUmVtb3ZlZChwYXlsb2FkLCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IHsgaGFuZGxlcklkIH0gPSBwYXlsb2FkO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuY2xpZW50cy5nZXQoY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCk7XG5cdCAgICAgICAgaWYgKGNsaWVudCkge1xuXHQgICAgICAgICAgICBBcnJheS5mcm9tKGNsaWVudC5jb250ZXh0SGFuZGxlcnMpLmZvckVhY2goKFssIGhhbmRsZXJzXSkgPT4ge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSBoYW5kbGVycy5pbmRleE9mKGhhbmRsZXJJZCk7XG5cdCAgICAgICAgICAgICAgICBpZiAoaW5kZXggPiAtMSkge1xuXHQgICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzLnNwbGljZShpbmRleCwgMSk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICBpZiAoY2xpZW50Lmdsb2JhbEhhbmRsZXIgPT09IGhhbmRsZXJJZCkge1xuXHQgICAgICAgICAgICAgICAgY2xpZW50Lmdsb2JhbEhhbmRsZXIgPSB1bmRlZmluZWQ7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUud2FybihgVHJ5aW5nIHRvIHJlbW92ZSBhIGhhbmRsZXIgZnJvbSBhIGNsaWVudCB0aGF0IGlzbid0IG1hcHBlZC4gaGFuZGxlcklkOiAke2hhbmRsZXJJZH0uIGNsaWVudElkZW50aXR5OiAke2NsaWVudElkZW50aXR5fWApO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIHJlZ2lzdGVyTmV3Q2xpZW50KGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgaWYgKCF0aGlzLmNsaWVudHMuaGFzKGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQpKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGNsaWVudFN1YnNjcmlwdGlvblN0YXRlID0ge1xuXHQgICAgICAgICAgICAgICAgY29udGV4dEhhbmRsZXJzOiBuZXcgTWFwKCksXG5cdCAgICAgICAgICAgICAgICBjbGllbnRJZGVudGl0eSxcblx0ICAgICAgICAgICAgICAgIGdsb2JhbEhhbmRsZXI6IHVuZGVmaW5lZFxuXHQgICAgICAgICAgICB9O1xuXHQgICAgICAgICAgICB0aGlzLmNsaWVudHMuc2V0KGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQsIGNsaWVudFN1YnNjcmlwdGlvblN0YXRlKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICBvbkRpc2Nvbm5lY3Rpb24oY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLmNsaWVudHMuZGVsZXRlKGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQpO1xuXHQgICAgfVxuXHR9O1xuXHRTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyLmRlZmF1bHQgPSBTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyJDE7XG5cdHJldHVybiBTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyO1xufVxuXG52YXIgdXRpbHMkMyA9IHt9O1xuXG4oZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRleHBvcnRzLndyYXBJbnRlbnRIYW5kbGVyID0gZXhwb3J0cy5CUk9LRVJfRVJST1JTID0gZXhwb3J0cy5nZW5lcmF0ZU92ZXJyaWRlV2FybmluZyA9IGV4cG9ydHMuZ2VuZXJhdGVPdmVycmlkZUVycm9yID0gZXhwb3J0cy53cmFwQ29udGV4dEhhbmRsZXIgPSBleHBvcnRzLndyYXBJblRyeUNhdGNoID0gZXhwb3J0cy5nZW5lcmF0ZUlkID0gdm9pZCAwO1xuXHRjb25zdCBnZW5lcmF0ZUlkID0gKCkgPT4gYCR7TWF0aC5yYW5kb20oKX0ke0RhdGUubm93KCl9YDtcblx0ZXhwb3J0cy5nZW5lcmF0ZUlkID0gZ2VuZXJhdGVJZDtcblx0Y29uc3Qgd3JhcEluVHJ5Q2F0Y2ggPSAoZiwgcHJlZml4KSA9PiAoLi4uYXJncykgPT4ge1xuXHQgICAgdHJ5IHtcblx0ICAgICAgICByZXR1cm4gZiguLi5hcmdzKTtcblx0ICAgIH1cblx0ICAgIGNhdGNoIChlKSB7XG5cdCAgICAgICAgdGhyb3cgbmV3IEVycm9yKChwcmVmaXggfHwgJycpICsgZSk7XG5cdCAgICB9XG5cdH07XG5cdGV4cG9ydHMud3JhcEluVHJ5Q2F0Y2ggPSB3cmFwSW5UcnlDYXRjaDtcblx0Y29uc3Qgd3JhcENvbnRleHRIYW5kbGVyID0gKGhhbmRsZXIsIGhhbmRsZXJJZCkgPT4ge1xuXHQgICAgcmV0dXJuIGFzeW5jIChjb250ZXh0KSA9PiB7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgYXdhaXQgaGFuZGxlcihjb250ZXh0KTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIHRocm93biBieSBoYW5kbGVyICR7aGFuZGxlcklkfSBmb3IgY29udGV4dCB0eXBlICR7Y29udGV4dC50eXBlfTogJHtlcnJvcn1gKTtcblx0ICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG5cdCAgICAgICAgfVxuXHQgICAgfTtcblx0fTtcblx0ZXhwb3J0cy53cmFwQ29udGV4dEhhbmRsZXIgPSB3cmFwQ29udGV4dEhhbmRsZXI7XG5cdGNvbnN0IGdlbmVyYXRlT3ZlcnJpZGVFcnJvciA9IChjbGllbnRBcGksIGJyb2tlckFwaSkgPT4ge1xuXHQgICAgcmV0dXJuIGBZb3UgaGF2ZSB0cmllZCB0byB0byB1c2UgJHtjbGllbnRBcGl9IGJ1dCAke2Jyb2tlckFwaX0gaGFzIG5vdCBiZWVuIG92ZXJyaWRkZW4gaW4gdGhlIEludGVyb3AgQnJva2VyLiBQbGVhc2Ugb3ZlcnJpZGUgdGhpcyBmdW5jdGlvbi4gUmVmZXIgdG8gb3VyIGRvY3VtZW50YXRpb24gZm9yIG1vcmUgaW5mby5gO1xuXHR9O1xuXHRleHBvcnRzLmdlbmVyYXRlT3ZlcnJpZGVFcnJvciA9IGdlbmVyYXRlT3ZlcnJpZGVFcnJvcjtcblx0Y29uc3QgZ2VuZXJhdGVPdmVycmlkZVdhcm5pbmcgPSAoZmRjM0NsaWVudEFwaSwgYnJva2VyQXBpLCBpZGVudGl0eSwgaW50ZXJvcENsaWVudEFwaSkgPT4ge1xuXHQgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSBpZGVudGl0eTtcblx0ICAgIGNvbnN0IG1lc3NhZ2UgPSBpbnRlcm9wQ2xpZW50QXBpXG5cdCAgICAgICAgPyBgRW50aXR5IHdpdGggaWRlbnRpdHk6ICR7dXVpZH0vJHtuYW1lfSBoYXMgY2FsbGVkICR7aW50ZXJvcENsaWVudEFwaX0gb3IgJHtmZGMzQ2xpZW50QXBpfSBidXQgJHticm9rZXJBcGl9IGhhcyBub3QgYmVlbiBvdmVycmlkZGVuLmBcblx0ICAgICAgICA6IGBFbnRpdHkgd2l0aCBpZGVudGl0eTogJHt1dWlkfS8ke25hbWV9IGhhcyBjYWxsZWQgJHtmZGMzQ2xpZW50QXBpfSBidXQgJHticm9rZXJBcGl9IGhhcyBub3QgYmVlbiBvdmVycmlkZGVuLmA7XG5cdCAgICByZXR1cm4gbWVzc2FnZTtcblx0fTtcblx0ZXhwb3J0cy5nZW5lcmF0ZU92ZXJyaWRlV2FybmluZyA9IGdlbmVyYXRlT3ZlcnJpZGVXYXJuaW5nO1xuXHRleHBvcnRzLkJST0tFUl9FUlJPUlMgPSB7XG5cdCAgICBmaXJlSW50ZW50OiAoMCwgZXhwb3J0cy5nZW5lcmF0ZU92ZXJyaWRlRXJyb3IpKCdmaXJlSW50ZW50JywgJ2hhbmRsZUZpcmVkSW50ZW50JyksXG5cdCAgICBmaXJlSW50ZW50Rm9yQ29udGV4dDogKDAsIGV4cG9ydHMuZ2VuZXJhdGVPdmVycmlkZUVycm9yKSgnZmlyZUludGVudEZvckNvbnRleHQnLCAnaGFuZGxlRmlyZWRJbnRlbnRGb3JDb250ZXh0JyksXG5cdCAgICBnZXRJbmZvRm9ySW50ZW50OiAoMCwgZXhwb3J0cy5nZW5lcmF0ZU92ZXJyaWRlRXJyb3IpKCdnZXRJbmZvRm9ySW50ZW50JywgJ2hhbmRsZUluZm9Gb3JJbnRlbnQnKSxcblx0ICAgIGdldEluZm9Gb3JJbnRlbnRzQnlDb250ZXh0OiAoMCwgZXhwb3J0cy5nZW5lcmF0ZU92ZXJyaWRlRXJyb3IpKCdnZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dCcsICdoYW5kbGVJbmZvRm9ySW50ZW50c0J5Q29udGV4dCcpLFxuXHQgICAgam9pblNlc3Npb25Db250ZXh0R3JvdXBXaXRoSm9pbkNvbnRleHRHcm91cDogJ1RoZSBDb250ZXh0IEdyb3VwIHlvdSBoYXZlIHRyaWVkIHRvIGpvaW4gaXMgYSBTZXNzaW9uIENvbnRleHQgR3JvdXAuIEN1c3RvbSBDb250ZXh0IEdyb3VwcyBjYW4gb25seSBiZSBkZWZpbmVkIGJ5IHRoZSBJbnRlcm9wIEJyb2tlciB0aHJvdWdoIGNvZGUgb3IgbWFuaWZlc3QgY29uZmlndXJhdGlvbi4gUGxlYXNlIHVzZSBqb2luU2Vzc2lvbkNvbnRleHRHcm91cC4nLFxuXHQgICAgZmRjM09wZW46ICgwLCBleHBvcnRzLmdlbmVyYXRlT3ZlcnJpZGVFcnJvcikoJ2ZkYzMub3BlbicsICdmZGMzSGFuZGxlT3BlbicpLFxuXHQgICAgZmRjM0ZpbmRJbnN0YW5jZXM6ICgwLCBleHBvcnRzLmdlbmVyYXRlT3ZlcnJpZGVFcnJvcikoJ2ZkYzMuZmluZEluc3RhbmNlcycsICdmZGMzSGFuZGxlRmluZEluc3RhbmNlcycpLFxuXHQgICAgZmRjM0dldEFwcE1ldGFkYXRhOiAoMCwgZXhwb3J0cy5nZW5lcmF0ZU92ZXJyaWRlRXJyb3IpKCdmZGMzLmdldEFwcE1ldGFkYXRhJywgJ2ZkYzNIYW5kbGVHZXRBcHBNZXRhZGF0YScpLFxuXHQgICAgZmRjM0dldEluZm86ICgwLCBleHBvcnRzLmdlbmVyYXRlT3ZlcnJpZGVFcnJvcikoJ2ZkYzMuZ2V0SW5mbycsICdmZGMzSGFuZGxlR2V0SW5mbycpXG5cdH07XG5cdGNvbnN0IHdyYXBJbnRlbnRIYW5kbGVyID0gKGhhbmRsZXIsIGhhbmRsZXJJZCkgPT4ge1xuXHQgICAgcmV0dXJuIGFzeW5jIChpbnRlbnQpID0+IHtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICByZXR1cm4gaGFuZGxlcihpbnRlbnQpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgdGhyb3duIGJ5IGhhbmRsZXIgJHtoYW5kbGVySWR9OiAke2Vycm9yfWApO1xuXHQgICAgICAgICAgICB0aHJvdyBlcnJvcjtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXHR9O1xuXHRleHBvcnRzLndyYXBJbnRlbnRIYW5kbGVyID0gd3JhcEludGVudEhhbmRsZXI7IFxufSAodXRpbHMkMykpO1xuXG52YXIgUHJpdmF0ZUNoYW5uZWxQcm92aWRlciA9IHt9O1xuXG52YXIgaGFzUmVxdWlyZWRQcml2YXRlQ2hhbm5lbFByb3ZpZGVyO1xuXG5mdW5jdGlvbiByZXF1aXJlUHJpdmF0ZUNoYW5uZWxQcm92aWRlciAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZFByaXZhdGVDaGFubmVsUHJvdmlkZXIpIHJldHVybiBQcml2YXRlQ2hhbm5lbFByb3ZpZGVyO1xuXHRoYXNSZXF1aXJlZFByaXZhdGVDaGFubmVsUHJvdmlkZXIgPSAxO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoUHJpdmF0ZUNoYW5uZWxQcm92aWRlciwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdFByaXZhdGVDaGFubmVsUHJvdmlkZXIuUHJpdmF0ZUNoYW5uZWxQcm92aWRlciA9IHZvaWQgMDtcblx0Y29uc3QgSW50ZXJvcEJyb2tlcl8xID0gcmVxdWlyZUludGVyb3BCcm9rZXIoKTtcblx0bGV0IFByaXZhdGVDaGFubmVsUHJvdmlkZXIkMSA9IGNsYXNzIFByaXZhdGVDaGFubmVsUHJvdmlkZXIge1xuXHQgICAgY29uc3RydWN0b3IocHJvdmlkZXIsIGlkKSB7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlciA9IHByb3ZpZGVyO1xuXHQgICAgICAgIHRoaXMuaWQgPSBpZDtcblx0ICAgICAgICB0aGlzLmNsaWVudHMgPSBuZXcgTWFwKCk7XG5cdCAgICAgICAgdGhpcy5yZWdpc3Rlckxpc3RlbmVycygpO1xuXHQgICAgICAgIHRoaXMuY29udGV4dEJ5Q29udGV4dFR5cGUgPSBuZXcgTWFwKCk7XG5cdCAgICAgICAgdGhpcy5sYXN0Q29udGV4dCA9IHVuZGVmaW5lZDtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLm9uQ29ubmVjdGlvbigoY2xpZW50SWRlbnRpdHkpID0+IHRoaXMucmVnaXN0ZXJOZXdDbGllbnQoY2xpZW50SWRlbnRpdHkpKTtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLm9uRGlzY29ubmVjdGlvbihhc3luYyAoY2xpZW50SWRlbnRpdHkpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgeyBlbmRwb2ludElkIH0gPSBjbGllbnRJZGVudGl0eTtcblx0ICAgICAgICAgICAgaWYgKHRoaXMuY2xpZW50cy5oYXMoZW5kcG9pbnRJZCkpIHtcblx0ICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuaGFuZGxlQ2xpZW50RGlzY29ubmVjdGluZyhjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgaWYgKChhd2FpdCB0aGlzLnByb3ZpZGVyLmdldEFsbENsaWVudEluZm8oKSkubGVuZ3RoID09PSAwKSB7XG5cdCAgICAgICAgICAgICAgICB0aGlzLnByb3ZpZGVyLmRlc3Ryb3koKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgZ2V0Q2xpZW50U3RhdGUoaWQpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy5jbGllbnRzLmdldChpZC5lbmRwb2ludElkKTtcblx0ICAgIH1cblx0ICAgIHJlZ2lzdGVyTGlzdGVuZXJzKCkge1xuXHQgICAgICAgIHRoaXMucHJvdmlkZXIucmVnaXN0ZXIoJ2Jyb2FkY2FzdCcsIHRoaXMuYnJvYWRjYXN0LmJpbmQodGhpcykpO1xuXHQgICAgICAgIHRoaXMucHJvdmlkZXIucmVnaXN0ZXIoJ2dldEN1cnJlbnRDb250ZXh0JywgdGhpcy5nZXRDdXJyZW50Q29udGV4dC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLnJlZ2lzdGVyKCdjb250ZXh0SGFuZGxlckFkZGVkJywgdGhpcy5jb250ZXh0SGFuZGxlckFkZGVkLmJpbmQodGhpcykpO1xuXHQgICAgICAgIHRoaXMucHJvdmlkZXIucmVnaXN0ZXIoJ2NvbnRleHRIYW5kbGVyUmVtb3ZlZCcsIHRoaXMuY29udGV4dEhhbmRsZXJSZW1vdmVkLmJpbmQodGhpcykpO1xuXHQgICAgICAgIHRoaXMucHJvdmlkZXIucmVnaXN0ZXIoJ25vblN0YW5kYXJkSGFuZGxlclJlbW92ZWQnLCB0aGlzLm5vblN0YW5kYXJkSGFuZGxlclJlbW92ZWQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlci5yZWdpc3Rlcignb25BZGRDb250ZXh0SGFuZGxlckFkZGVkJywgdGhpcy5vbkFkZENvbnRleHRIYW5kbGVyQWRkZWQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlci5yZWdpc3Rlcignb25EaXNjb25uZWN0SGFuZGxlckFkZGVkJywgdGhpcy5vbkRpc2Nvbm5lY3RIYW5kbGVyQWRkZWQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlci5yZWdpc3Rlcignb25VbnN1YnNjcmliZUhhbmRsZXJBZGRlZCcsIHRoaXMub25VbnN1YnNjcmliZUhhbmRsZXJBZGRlZC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLnJlZ2lzdGVyKCdjbGllbnREaXNjb25uZWN0aW5nJywgKHBheWxvYWQsIGNsaWVudElkZW50aXR5KSA9PiB7XG5cdCAgICAgICAgICAgIHRoaXMuaGFuZGxlQ2xpZW50RGlzY29ubmVjdGluZyhjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdCAgICBicm9hZGNhc3QocGF5bG9hZCwgYnJvYWRjYXN0ZXJDbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IHsgY29udGV4dCB9ID0gcGF5bG9hZDtcblx0ICAgICAgICBjb25zdCBicm9hZGNhc3RlckNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShicm9hZGNhc3RlckNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICBpZiAoIWJyb2FkY2FzdGVyQ2xpZW50U3RhdGUpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDbGllbnQgd2l0aCBJZGVudGl0eTogJHticm9hZGNhc3RlckNsaWVudElkZW50aXR5LnV1aWR9ICR7YnJvYWRjYXN0ZXJDbGllbnRJZGVudGl0eS5uYW1lfSwgdHJpZWQgdG8gY2FsbCBicm9hZGNhc3QsIGlzIG5vdCBjb25uZWN0ZWQgdG8gdGhpcyBQcml2YXRlIENoYW5uZWxgKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3QgY29udGV4dEludGVncml0eUNoZWNrUmVzdWx0ID0gSW50ZXJvcEJyb2tlcl8xLkludGVyb3BCcm9rZXIuY2hlY2tDb250ZXh0SW50ZWdyaXR5KGNvbnRleHQpO1xuXHQgICAgICAgIGlmIChjb250ZXh0SW50ZWdyaXR5Q2hlY2tSZXN1bHQuaXNWYWxpZCA9PT0gZmFsc2UpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gYnJvYWRjYXN0IC0gYmFkIENvbnRleHQuIFJlYXNvbjogJHtjb250ZXh0SW50ZWdyaXR5Q2hlY2tSZXN1bHQucmVhc29ufS4gQ29udGV4dDogJHtKU09OLnN0cmluZ2lmeShjb250ZXh0KX1gKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgdGhpcy5jb250ZXh0QnlDb250ZXh0VHlwZS5zZXQoY29udGV4dC50eXBlLCBjb250ZXh0KTtcblx0ICAgICAgICB0aGlzLmxhc3RDb250ZXh0ID0gY29udGV4dDtcblx0ICAgICAgICBBcnJheS5mcm9tKHRoaXMuY2xpZW50cy52YWx1ZXMoKSkuZm9yRWFjaCgoY3VyckNsaWVudFN0YXRlKSA9PiB7XG5cdCAgICAgICAgICAgIGNvbnN0IGhhbmRsZXJJZHNGb3JDb250ZXh0VHlwZSA9IGN1cnJDbGllbnRTdGF0ZS5oYW5kbGVySWRzQnlDb250ZXh0VHlwZXMuZ2V0KGNvbnRleHQudHlwZSk7XG5cdCAgICAgICAgICAgIGlmIChoYW5kbGVySWRzRm9yQ29udGV4dFR5cGUpIHtcblx0ICAgICAgICAgICAgICAgIGhhbmRsZXJJZHNGb3JDb250ZXh0VHlwZS5mb3JFYWNoKChoYW5kbGVySWQpID0+IHtcblx0ICAgICAgICAgICAgICAgICAgICB0aGlzLnByb3ZpZGVyLmRpc3BhdGNoKGN1cnJDbGllbnRTdGF0ZS5jbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBjb250ZXh0KTtcblx0ICAgICAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGlmIChjdXJyQ2xpZW50U3RhdGUuZ2xvYmFsSGFuZGxlcikge1xuXHQgICAgICAgICAgICAgICAgdGhpcy5wcm92aWRlci5kaXNwYXRjaChjdXJyQ2xpZW50U3RhdGUuY2xpZW50SWRlbnRpdHksIGN1cnJDbGllbnRTdGF0ZS5nbG9iYWxIYW5kbGVyLCBjb250ZXh0KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgZ2V0Q3VycmVudENvbnRleHQocGF5bG9hZCwgc2VuZGVyQ2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCB7IGNvbnRleHRUeXBlIH0gPSBwYXlsb2FkO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShzZW5kZXJDbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKCFjbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsaWVudCB3aXRoIElkZW50aXR5OiAke3NlbmRlckNsaWVudElkZW50aXR5LnV1aWR9ICR7c2VuZGVyQ2xpZW50SWRlbnRpdHkubmFtZX0sIHRyaWVkIHRvIGNhbGwgZ2V0Q3VycmVudENvbnRleHQsIGlzIG5vdCBjb25uZWN0ZWQgdG8gdGhpcyBQcml2YXRlIENoYW5uZWxgKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgaWYgKGNvbnRleHRUeXBlICE9PSB1bmRlZmluZWQpIHtcblx0ICAgICAgICAgICAgY29uc3QgY3VycmVudENvbnRleHQgPSB0aGlzLmNvbnRleHRCeUNvbnRleHRUeXBlLmdldChjb250ZXh0VHlwZSk7XG5cdCAgICAgICAgICAgIGlmIChjdXJyZW50Q29udGV4dClcblx0ICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50Q29udGV4dDtcblx0ICAgICAgICAgICAgcmV0dXJuIG51bGw7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiB0aGlzLmxhc3RDb250ZXh0ID8gdGhpcy5sYXN0Q29udGV4dCA6IG51bGw7XG5cdCAgICB9XG5cdCAgICBjb250ZXh0SGFuZGxlckFkZGVkKHBheWxvYWQsIHNlbmRlckNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgY29uc3QgeyBoYW5kbGVySWQsIGNvbnRleHRUeXBlIH0gPSBwYXlsb2FkO1xuXHQgICAgICAgIGNvbnN0IHNlbmRlckNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShzZW5kZXJDbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKCFzZW5kZXJDbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsaWVudCB3aXRoIElkZW50aXR5OiAke3NlbmRlckNsaWVudElkZW50aXR5LnV1aWR9ICR7c2VuZGVyQ2xpZW50SWRlbnRpdHkubmFtZX0sIHRyaWVkIHRvIGNhbGwgYWRkQ29udGV4dExpc3RlbmVyLCBpcyBub3QgY29ubmVjdGVkIHRvIHRoaXMgUHJpdmF0ZSBDaGFubmVsYCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmIChjb250ZXh0VHlwZSkge1xuXHQgICAgICAgICAgICBjb25zdCBjdXJyZW50SGFuZGxlcnNMaXN0ID0gc2VuZGVyQ2xpZW50U3RhdGUuaGFuZGxlcklkc0J5Q29udGV4dFR5cGVzLmdldChjb250ZXh0VHlwZSkgfHwgW107XG5cdCAgICAgICAgICAgIHNlbmRlckNsaWVudFN0YXRlLmhhbmRsZXJJZHNCeUNvbnRleHRUeXBlcy5zZXQoY29udGV4dFR5cGUsIFsuLi5jdXJyZW50SGFuZGxlcnNMaXN0LCBoYW5kbGVySWRdKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIHNlbmRlckNsaWVudFN0YXRlLmdsb2JhbEhhbmRsZXIgPSBoYW5kbGVySWQ7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIEFycmF5LmZyb20odGhpcy5jbGllbnRzLnZhbHVlcygpKS5mb3JFYWNoKChjdXJyQ2xpZW50U3RhdGUpID0+IHtcblx0ICAgICAgICAgICAgaWYgKGN1cnJDbGllbnRTdGF0ZS5jbGllbnRJZGVudGl0eS5lbmRwb2ludElkICE9PSBzZW5kZXJDbGllbnRJZGVudGl0eS5lbmRwb2ludElkICYmXG5cdCAgICAgICAgICAgICAgICBjdXJyQ2xpZW50U3RhdGUub25BZGRDb250ZXh0TGlzdGVuZXJIYW5kbGVySWQpIHtcblx0ICAgICAgICAgICAgICAgIHRoaXMucHJvdmlkZXIuZGlzcGF0Y2goY3VyckNsaWVudFN0YXRlLmNsaWVudElkZW50aXR5LCBjdXJyQ2xpZW50U3RhdGUub25BZGRDb250ZXh0TGlzdGVuZXJIYW5kbGVySWQsIGNvbnRleHRUeXBlKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgYXN5bmMgY29udGV4dEhhbmRsZXJSZW1vdmVkKHBheWxvYWQsIHJlbW92aW5nQ2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICAvLyBNQzogTWFkZSB0aGlzIHJlbW92YWwgYXN5bmMgdG8gZW5zdXJlIHRoYXQgb25VbnN1YnNjcmliZSBoYW5kbGVycyBhcmUgaGl0IGJlZm9yZSBhbnl0aGluZyBlbHNlIGhhcHBlbnMuXG5cdCAgICAgICAgY29uc3QgeyBoYW5kbGVySWQgfSA9IHBheWxvYWQ7XG5cdCAgICAgICAgY29uc3QgcmVtb3ZpbmdDbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUocmVtb3ZpbmdDbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKHJlbW92aW5nQ2xpZW50U3RhdGUpIHtcblx0ICAgICAgICAgICAgbGV0IGNvbnRleHRUeXBlO1xuXHQgICAgICAgICAgICBpZiAocmVtb3ZpbmdDbGllbnRTdGF0ZS5nbG9iYWxIYW5kbGVyID09PSBoYW5kbGVySWQpIHtcblx0ICAgICAgICAgICAgICAgIHJlbW92aW5nQ2xpZW50U3RhdGUuZ2xvYmFsSGFuZGxlciA9IHVuZGVmaW5lZDtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2N1cnJDb250ZXh0VHlwZSwgaGFuZGxlcnNJZHNdIG9mIHJlbW92aW5nQ2xpZW50U3RhdGUuaGFuZGxlcklkc0J5Q29udGV4dFR5cGVzKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSBoYW5kbGVyc0lkcy5pbmRleE9mKGhhbmRsZXJJZCk7XG5cdCAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ID4gLTEpIHtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlcnNJZHMuc3BsaWNlKGluZGV4LCAxKTtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dFR5cGUgPSBjdXJyQ29udGV4dFR5cGU7XG5cdCAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIC8vIGdldHRpbmcgb25seSB2YWxpZCBjbGllbnQgY29ubmVjdGlvbnMgaGVyZSwgaXQgaXMgcG9zc2libGUgd2UgaGF2ZW4ndCByZW1vdmVkIGEgZGlzY29ubmVjdGVkIGNsaWVudCBmcm9tIHRoZSBtYXAgeWV0XG5cdCAgICAgICAgICAgIC8vIHNvIHdlIG5lZWQgdG8gZW5zdXJlIHdlIGRvbid0IGRpc3BhdGNoIHRvIGFueSBkaXNjb25uZWN0ZWQgY2xpZW50XG5cdCAgICAgICAgICAgIC8vIFRPRE86IFRha2UgYSBsb29rIGF0IG91ciBjbGllbnQgZGlzY29ubmVjdGlvbiBsb2dpYyBhbmQgc2VlIGlmIHdlIGNhbiBoYW5kbGUgY2xpZW50IGRpc2Nvbm5lY3Rpb24gY2xlYW5seVxuXHQgICAgICAgICAgICBjb25zdCBjbGllbnRzVG9EaXNwYXRjaFRvID0gYXdhaXQgdGhpcy5nZXRDb25uZWN0ZWRDbGllbnRzKCk7XG5cdCAgICAgICAgICAgIGNvbnN0IGRpc3BhdGNoUHJvbWlzZXMgPSBjbGllbnRzVG9EaXNwYXRjaFRvLm1hcChhc3luYyAob3RoZXJDbGllbnRTdGF0ZSkgPT4ge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgeyBjbGllbnRJZGVudGl0eSwgY2xpZW50SWRlbnRpdHk6IHsgZW5kcG9pbnRJZCB9LCBvblVuc3Vic2NyaWJlSGFuZGxlcklkIH0gPSBvdGhlckNsaWVudFN0YXRlO1xuXHQgICAgICAgICAgICAgICAgaWYgKGVuZHBvaW50SWQgIT09IHJlbW92aW5nQ2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCAmJiBvblVuc3Vic2NyaWJlSGFuZGxlcklkKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wcm92aWRlci5kaXNwYXRjaChjbGllbnRJZGVudGl0eSwgb25VbnN1YnNjcmliZUhhbmRsZXJJZCwgY29udGV4dFR5cGUpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9KTtcblx0ICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKGRpc3BhdGNoUHJvbWlzZXMpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgUHJvYmxlbSB3aGVuIGF0dGVtcHRpbmcgdG8gZGlzcGF0Y2ggdG8gb25VbnN1YnNjcmliZUhhbmRsZXJzLiBFcnJvcjogJHtlcnJvcn0gUmVtb3ZpbmcgQ2xpZW50OiAke2hhbmRsZXJJZH0uIHV1aWQ6ICR7cmVtb3ZpbmdDbGllbnRJZGVudGl0eS51dWlkfS4gbmFtZTogJHtyZW1vdmluZ0NsaWVudElkZW50aXR5Lm5hbWV9LiBlbmRwb2ludElkOiAke3JlbW92aW5nQ2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZH1gKTtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUud2FybihgVHJ5aW5nIHRvIHJlbW92ZSBhIGhhbmRsZXIgZnJvbSBhIGNsaWVudCB0aGF0IGlzbid0IG1hcHBlZC4gaGFuZGxlcklkOiAke2hhbmRsZXJJZH0uIHV1aWQ6ICR7cmVtb3ZpbmdDbGllbnRJZGVudGl0eS51dWlkfS4gbmFtZTogJHtyZW1vdmluZ0NsaWVudElkZW50aXR5Lm5hbWV9LiBlbmRwb2ludElkOiAke3JlbW92aW5nQ2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZH0uYCk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgbm9uU3RhbmRhcmRIYW5kbGVyUmVtb3ZlZChwYXlsb2FkLCBpZCkge1xuXHQgICAgICAgIGNvbnN0IHsgaGFuZGxlcklkIH0gPSBwYXlsb2FkO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShpZCk7XG5cdCAgICAgICAgaWYgKGNsaWVudFN0YXRlKSB7XG5cdCAgICAgICAgICAgIGlmIChjbGllbnRTdGF0ZS5vbkRpc2Nvbm5lY3RIYW5kbGVySWQgPT09IGhhbmRsZXJJZCkge1xuXHQgICAgICAgICAgICAgICAgY2xpZW50U3RhdGUub25EaXNjb25uZWN0SGFuZGxlcklkID0gdW5kZWZpbmVkO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGVsc2UgaWYgKGNsaWVudFN0YXRlLm9uQWRkQ29udGV4dExpc3RlbmVySGFuZGxlcklkID09PSBoYW5kbGVySWQpIHtcblx0ICAgICAgICAgICAgICAgIGNsaWVudFN0YXRlLm9uQWRkQ29udGV4dExpc3RlbmVySGFuZGxlcklkID0gdW5kZWZpbmVkO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGVsc2UgaWYgKGNsaWVudFN0YXRlLm9uVW5zdWJzY3JpYmVIYW5kbGVySWQgPT09IGhhbmRsZXJJZCkge1xuXHQgICAgICAgICAgICAgICAgY2xpZW50U3RhdGUub25VbnN1YnNjcmliZUhhbmRsZXJJZCA9IHVuZGVmaW5lZDtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgY29uc29sZS53YXJuKGBUcnlpbmcgdG8gcmVtb3ZlIGEgaGFuZGxlciBmcm9tIGEgY2xpZW50IHRoYXQgaXNuJ3QgbWFwcGVkLiBoYW5kbGVySWQ6ICR7aGFuZGxlcklkfS4gY2xpZW50SWRlbnRpdHk6ICR7aWR9YCk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgb25BZGRDb250ZXh0SGFuZGxlckFkZGVkKHBheWxvYWQsIHNlbmRlckNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgY29uc3QgY2xpZW50U3RhdGUgPSB0aGlzLmdldENsaWVudFN0YXRlKHNlbmRlckNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICBjb25zdCB7IGhhbmRsZXJJZCB9ID0gcGF5bG9hZDtcblx0ICAgICAgICBpZiAoIWNsaWVudFN0YXRlKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2xpZW50IHdpdGggSWRlbnRpdHk6ICR7c2VuZGVyQ2xpZW50SWRlbnRpdHkudXVpZH0gJHtzZW5kZXJDbGllbnRJZGVudGl0eS5uYW1lfSwgdHJpZWQgdG8gY2FsbCBvbkFkZENvbnRleHRMaXN0ZW5lciwgaXMgbm90IGNvbm5lY3RlZCB0byB0aGlzIFByaXZhdGUgQ2hhbm5lbGApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjbGllbnRTdGF0ZS5vbkFkZENvbnRleHRMaXN0ZW5lckhhbmRsZXJJZCA9IGhhbmRsZXJJZDtcblx0ICAgICAgICAvLyBGREMzIFNwZWMgc2F5cyB0aGF0IHRoZSBhZGRlZCBsaXN0ZW5lciBzaG91bGQgZmlyZSBmb3IgYWxsIHByZXZpb3VzbHktcmVnaXN0ZXJlZCBhZGRDb250ZXh0TGlzdGVuZXJzIGZyb20gdGhlIG90aGVyIGNsaWVudFxuXHQgICAgICAgIEFycmF5LmZyb20odGhpcy5jbGllbnRzLnZhbHVlcygpKS5mb3JFYWNoKChvdGhlckNsaWVudFN0YXRlKSA9PiB7XG5cdCAgICAgICAgICAgIGlmIChvdGhlckNsaWVudFN0YXRlLmNsaWVudElkZW50aXR5LmVuZHBvaW50SWQgIT09IHNlbmRlckNsaWVudElkZW50aXR5LmVuZHBvaW50SWQpIHtcblx0ICAgICAgICAgICAgICAgIEFycmF5LmZyb20ob3RoZXJDbGllbnRTdGF0ZS5oYW5kbGVySWRzQnlDb250ZXh0VHlwZXMua2V5cygpKS5mb3JFYWNoKChzdWJzY3JpYmVkQ29udGV4dFR5cGUpID0+IHtcblx0ICAgICAgICAgICAgICAgICAgICB0aGlzLnByb3ZpZGVyLmRpc3BhdGNoKHNlbmRlckNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIHN1YnNjcmliZWRDb250ZXh0VHlwZSk7XG5cdCAgICAgICAgICAgICAgICB9KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgb25EaXNjb25uZWN0SGFuZGxlckFkZGVkKHBheWxvYWQsIGlkKSB7XG5cdCAgICAgICAgY29uc3QgY2xpZW50U3RhdGUgPSB0aGlzLmdldENsaWVudFN0YXRlKGlkKTtcblx0ICAgICAgICBjb25zdCB7IGhhbmRsZXJJZCB9ID0gcGF5bG9hZDtcblx0ICAgICAgICBpZiAoIWNsaWVudFN0YXRlKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2xpZW50IHdpdGggSWRlbnRpdHk6ICR7aWQudXVpZH0gJHtpZC5uYW1lfSwgdHJpZWQgdG8gY2FsbCBvbkRpc2Nvbm5lY3QsIGlzIG5vdCBjb25uZWN0ZWQgdG8gdGhpcyBQcml2YXRlIENoYW5uZWxgKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2xpZW50U3RhdGUub25EaXNjb25uZWN0SGFuZGxlcklkID0gaGFuZGxlcklkO1xuXHQgICAgfVxuXHQgICAgb25VbnN1YnNjcmliZUhhbmRsZXJBZGRlZChwYXlsb2FkLCBpZCkge1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShpZCk7XG5cdCAgICAgICAgY29uc3QgeyBoYW5kbGVySWQgfSA9IHBheWxvYWQ7XG5cdCAgICAgICAgaWYgKCFjbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsaWVudCB3aXRoIElkZW50aXR5OiAke2lkLnV1aWR9ICR7aWQubmFtZX0sIHRyaWVkIHRvIGNhbGwgb25VbnN1YnNjcmliZSwgaXMgbm90IGNvbm5lY3RlZCB0byB0aGlzIFByaXZhdGUgQ2hhbm5lbGApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjbGllbnRTdGF0ZS5vblVuc3Vic2NyaWJlSGFuZGxlcklkID0gaGFuZGxlcklkO1xuXHQgICAgfVxuXHQgICAgcmVtb3ZlQ2xpZW50KGRpc2Nvbm5lY3RpbmdDbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IGRpc2Nvbm5lY3RpbmdDbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoZGlzY29ubmVjdGluZ0NsaWVudElkZW50aXR5KTtcblx0ICAgICAgICBpZiAoIWRpc2Nvbm5lY3RpbmdDbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsaWVudCB3aXRoIElkZW50aXR5OiAke2Rpc2Nvbm5lY3RpbmdDbGllbnRJZGVudGl0eS51dWlkfSAke2Rpc2Nvbm5lY3RpbmdDbGllbnRJZGVudGl0eS5uYW1lfSwgdHJpZWQgdG8gY2FsbCBkaXNjb25uZWN0LCBpcyBub3QgY29ubmVjdGVkIHRvIHRoaXMgUHJpdmF0ZSBDaGFubmVsYCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGRpc2Nvbm5lY3RpbmdDbGllbnRTdGF0ZS5oYW5kbGVySWRzQnlDb250ZXh0VHlwZXMuY2xlYXIoKTtcblx0ICAgICAgICB0aGlzLmNsaWVudHMuZGVsZXRlKGRpc2Nvbm5lY3RpbmdDbGllbnRJZGVudGl0eS5lbmRwb2ludElkKTtcblx0ICAgIH1cblx0ICAgIGFzeW5jIGZpcmVPbkRpc2Nvbm5lY3RGb3JPdGhlckNsaWVudHMoZGlzY29ubmVjdGluZ0NsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgLy8gVE9ETzogY2FsbCBvbkRpc2Nvbm5lY3QgSGFuZGxlciBvZiB0aGUgb3RoZXIgY2xpZW50IG9ubHkuXG5cdCAgICAgICAgLy8gQ1VSUkVOVExZLCBqdXN0IGNhbGxpbmcgdGhlIG9uRGlzY29ubmVjdCBoYW5kbGVyIGZvciBhbGwgdGhlIG90aGVyIGNsaWVudHMuIE9uY2Ugd2UgbGltaXQgaXQgdG8ganVzdCBvbmUgb3RoZXIgY2xpZW50LCB3ZSBjYW4gZWxpbWluYXRlIGFsbCB0aGUgaXRlcmF0aW9uIGNvZGUuXG5cdCAgICAgICAgY29uc3QgeyBlbmRwb2ludElkIH0gPSBkaXNjb25uZWN0aW5nQ2xpZW50SWRlbnRpdHk7XG5cdCAgICAgICAgLy8gZ2V0dGluZyBvbmx5IHZhbGlkIGNsaWVudCBjb25uZWN0aW9ucyBoZXJlLCBpdCBpcyBwb3NzaWJsZSB3ZSBoYXZlbid0IHJlbW92ZWQgYSBkaXNjb25uZWN0ZWQgY2xpZW50IGZyb20gdGhlIG1hcCB5ZXRcblx0ICAgICAgICAvLyBzbyB3ZSBuZWVkIHRvIGVuc3VyZSB3ZSBkb24ndCBkaXNwYXRjaCB0byBhbnkgZGlzY29ubmVjdGVkIGNsaWVudFxuXHQgICAgICAgIC8vIFRPRE86IFRha2UgYSBsb29rIGF0IG91ciBjbGllbnQgZGlzY29ubmVjdGlvbiBsb2dpYyBhbmQgc2VlIGlmIHdlIGNhbiBoYW5kbGUgY2xpZW50IGRpc2Nvbm5lY3Rpb24gY2xlYW5seVxuXHQgICAgICAgIGNvbnN0IGNsaWVudHNUb0Rpc3BhdGNoVG8gPSBhd2FpdCB0aGlzLmdldENvbm5lY3RlZENsaWVudHMoKTtcblx0ICAgICAgICBjb25zdCBkaXNwYXRjaFByb21pc2VzID0gY2xpZW50c1RvRGlzcGF0Y2hUby5tYXAoYXN5bmMgKG90aGVyQ2xpZW50U3RhdGUpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgeyBjbGllbnRJZGVudGl0eTogeyBlbmRwb2ludElkOiBvdGhlckNsaWVudEVuZHBvaW50SWQgfSwgb25EaXNjb25uZWN0SGFuZGxlcklkIH0gPSBvdGhlckNsaWVudFN0YXRlO1xuXHQgICAgICAgICAgICBpZiAob3RoZXJDbGllbnRFbmRwb2ludElkICE9PSBlbmRwb2ludElkICYmIG9uRGlzY29ubmVjdEhhbmRsZXJJZCkge1xuXHQgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wcm92aWRlci5kaXNwYXRjaChvdGhlckNsaWVudFN0YXRlLmNsaWVudElkZW50aXR5LCBvbkRpc2Nvbm5lY3RIYW5kbGVySWQpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoZGlzcGF0Y2hQcm9taXNlcyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBQcm9ibGVtIHdoZW4gYXR0ZW1wdGluZyB0byBkaXNwYXRjaCB0byBvbkRpc2Nvbm5lY3RIYW5kbGVycy4gRXJyb3I6ICR7ZXJyb3J9IERpc2Nvbm5lY3RpbmcgQ2xpZW50OiB1dWlkOiAke2Rpc2Nvbm5lY3RpbmdDbGllbnRJZGVudGl0eS51dWlkfS4gbmFtZTogJHtkaXNjb25uZWN0aW5nQ2xpZW50SWRlbnRpdHkubmFtZX0uIGVuZHBvaW50SWQ6ICR7ZGlzY29ubmVjdGluZ0NsaWVudElkZW50aXR5LmVuZHBvaW50SWR9YCk7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgYXN5bmMgdW5zdWJzY3JpYmVBbGwoY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCB7IGVuZHBvaW50SWQgfSA9IGNsaWVudElkZW50aXR5O1xuXHQgICAgICAgIGNvbnN0IHN0YXRlID0gdGhpcy5jbGllbnRzLmdldChlbmRwb2ludElkKTtcblx0ICAgICAgICBpZiAoc3RhdGUpIHtcblx0ICAgICAgICAgICAgY29uc3QgY29udGV4dFR5cGVIYW5kbGVySWRzID0gQXJyYXkuZnJvbShzdGF0ZS5oYW5kbGVySWRzQnlDb250ZXh0VHlwZXMudmFsdWVzKCkpLmZsYXQoKTtcblx0ICAgICAgICAgICAgY29uc3QgZ2xvYmFsSGFuZGxlcklkID0gc3RhdGUuZ2xvYmFsSGFuZGxlcjtcblx0ICAgICAgICAgICAgaWYgKGNvbnRleHRUeXBlSGFuZGxlcklkcy5sZW5ndGggPiAwKSB7XG5cdCAgICAgICAgICAgICAgICBjb25zdCB1bnN1YlByb21pc2VzID0gY29udGV4dFR5cGVIYW5kbGVySWRzLm1hcChhc3luYyAoaGFuZGxlcklkKSA9PiB7XG5cdCAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGV4dEhhbmRsZXJSZW1vdmVkKHsgaGFuZGxlcklkIH0sIGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbCh1bnN1YlByb21pc2VzKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IubWVzc2FnZSk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgaWYgKGdsb2JhbEhhbmRsZXJJZCkge1xuXHQgICAgICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmNvbnRleHRIYW5kbGVyUmVtb3ZlZCh7IGhhbmRsZXJJZDogZ2xvYmFsSGFuZGxlcklkIH0sIGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IubWVzc2FnZSk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICBhc3luYyBoYW5kbGVDbGllbnREaXNjb25uZWN0aW5nKGRpc2Nvbm5lY3RpbmdDbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGF3YWl0IHRoaXMudW5zdWJzY3JpYmVBbGwoZGlzY29ubmVjdGluZ0NsaWVudElkZW50aXR5KTtcblx0ICAgICAgICB0aGlzLnJlbW92ZUNsaWVudChkaXNjb25uZWN0aW5nQ2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGF3YWl0IHRoaXMuZmlyZU9uRGlzY29ubmVjdEZvck90aGVyQ2xpZW50cyhkaXNjb25uZWN0aW5nQ2xpZW50SWRlbnRpdHkpO1xuXHQgICAgfVxuXHQgICAgcmVnaXN0ZXJOZXdDbGllbnQoY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBpZiAoIXRoaXMuY2xpZW50cy5oYXMoY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCkpIHtcblx0ICAgICAgICAgICAgY29uc3QgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUgPSB7XG5cdCAgICAgICAgICAgICAgICBjbGllbnRJZGVudGl0eSxcblx0ICAgICAgICAgICAgICAgIGhhbmRsZXJJZHNCeUNvbnRleHRUeXBlczogbmV3IE1hcCgpLFxuXHQgICAgICAgICAgICAgICAgZ2xvYmFsSGFuZGxlcjogdW5kZWZpbmVkLFxuXHQgICAgICAgICAgICAgICAgb25BZGRDb250ZXh0TGlzdGVuZXJIYW5kbGVySWQ6IHVuZGVmaW5lZCxcblx0ICAgICAgICAgICAgICAgIG9uVW5zdWJzY3JpYmVIYW5kbGVySWQ6IHVuZGVmaW5lZCxcblx0ICAgICAgICAgICAgICAgIG9uRGlzY29ubmVjdEhhbmRsZXJJZDogdW5kZWZpbmVkXG5cdCAgICAgICAgICAgIH07XG5cdCAgICAgICAgICAgIHRoaXMuY2xpZW50cy5zZXQoY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCwgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIGFzeW5jIGdldENvbm5lY3RlZENsaWVudHMoKSB7XG5cdCAgICAgICAgY29uc3QgYWxsQ2xpZW50SW5mbyA9IGF3YWl0IHRoaXMucHJvdmlkZXIuZ2V0QWxsQ2xpZW50SW5mbygpO1xuXHQgICAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMuY2xpZW50cy52YWx1ZXMoKSkuZmlsdGVyKChjbGllbnRTdGF0ZSkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IGNsaWVudFN0YXRlLmNsaWVudElkZW50aXR5O1xuXHQgICAgICAgICAgICByZXR1cm4gYWxsQ2xpZW50SW5mby5zb21lKChjbGllbnRJbmZvKSA9PiB7XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gbmFtZSA9PT0gY2xpZW50SW5mby5uYW1lICYmIHV1aWQgPT09IGNsaWVudEluZm8udXVpZDtcblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdCAgICBzdGF0aWMgaW5pdChjaGFubmVsUHJvdmlkZXIsIGlkKSB7XG5cdCAgICAgICAgcmV0dXJuIG5ldyBQcml2YXRlQ2hhbm5lbFByb3ZpZGVyKGNoYW5uZWxQcm92aWRlciwgaWQpO1xuXHQgICAgfVxuXHR9O1xuXHRQcml2YXRlQ2hhbm5lbFByb3ZpZGVyLlByaXZhdGVDaGFubmVsUHJvdmlkZXIgPSBQcml2YXRlQ2hhbm5lbFByb3ZpZGVyJDE7XG5cdHJldHVybiBQcml2YXRlQ2hhbm5lbFByb3ZpZGVyO1xufVxuXG52YXIgaGFzUmVxdWlyZWRJbnRlcm9wQnJva2VyO1xuXG5mdW5jdGlvbiByZXF1aXJlSW50ZXJvcEJyb2tlciAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEludGVyb3BCcm9rZXIpIHJldHVybiBJbnRlcm9wQnJva2VyO1xuXHRoYXNSZXF1aXJlZEludGVyb3BCcm9rZXIgPSAxO1xuXHR2YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xuXHQgICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuXHQgICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuXHQgICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcblx0ICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xuXHR9O1xuXHR2YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG5cdCAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG5cdCAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcblx0ICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG5cdH07XG5cdHZhciBfX2ltcG9ydERlZmF1bHQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19pbXBvcnREZWZhdWx0KSB8fCBmdW5jdGlvbiAobW9kKSB7XG5cdCAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IFwiZGVmYXVsdFwiOiBtb2QgfTtcblx0fTtcblx0dmFyIF9JbnRlcm9wQnJva2VyX2ZkYzNJbmZvLCBfSW50ZXJvcEJyb2tlcl9jb250ZXh0R3JvdXBzLCBfSW50ZXJvcEJyb2tlcl9wcm92aWRlclByb21pc2U7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShJbnRlcm9wQnJva2VyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0SW50ZXJvcEJyb2tlci5JbnRlcm9wQnJva2VyID0gdm9pZCAwO1xuXHRjb25zdCBiYXNlXzEgPSBiYXNlO1xuXHRjb25zdCBTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyXzEgPSBfX2ltcG9ydERlZmF1bHQocmVxdWlyZVNlc3Npb25Db250ZXh0R3JvdXBCcm9rZXIoKSk7XG5cdGNvbnN0IHV0aWxzXzEgPSB1dGlscyQzO1xuXHRjb25zdCBpc0VxdWFsXzEgPSBfX2ltcG9ydERlZmF1bHQocmVxdWlyZSQkMyk7XG5cdGNvbnN0IFByaXZhdGVDaGFubmVsUHJvdmlkZXJfMSA9IHJlcXVpcmVQcml2YXRlQ2hhbm5lbFByb3ZpZGVyKCk7XG5cdGNvbnN0IGxhenlfMSA9IGxhenk7XG5cdGNvbnN0IGRlZmF1bHRDb250ZXh0R3JvdXBzID0gW1xuXHQgICAge1xuXHQgICAgICAgIGlkOiAnZ3JlZW4nLFxuXHQgICAgICAgIGRpc3BsYXlNZXRhZGF0YToge1xuXHQgICAgICAgICAgICBjb2xvcjogJyMwMENDODgnLFxuXHQgICAgICAgICAgICBuYW1lOiAnZ3JlZW4nXG5cdCAgICAgICAgfVxuXHQgICAgfSxcblx0ICAgIHtcblx0ICAgICAgICBpZDogJ3B1cnBsZScsXG5cdCAgICAgICAgZGlzcGxheU1ldGFkYXRhOiB7XG5cdCAgICAgICAgICAgIGNvbG9yOiAnIzhDNjFGRicsXG5cdCAgICAgICAgICAgIG5hbWU6ICdwdXJwbGUnXG5cdCAgICAgICAgfVxuXHQgICAgfSxcblx0ICAgIHtcblx0ICAgICAgICBpZDogJ29yYW5nZScsXG5cdCAgICAgICAgZGlzcGxheU1ldGFkYXRhOiB7XG5cdCAgICAgICAgICAgIGNvbG9yOiAnI0ZGOEM0QycsXG5cdCAgICAgICAgICAgIG5hbWU6ICdvcmFuZ2UnXG5cdCAgICAgICAgfVxuXHQgICAgfSxcblx0ICAgIHtcblx0ICAgICAgICBpZDogJ3JlZCcsXG5cdCAgICAgICAgZGlzcGxheU1ldGFkYXRhOiB7XG5cdCAgICAgICAgICAgIGNvbG9yOiAnI0ZGNUU2MCcsXG5cdCAgICAgICAgICAgIG5hbWU6ICdyZWQnXG5cdCAgICAgICAgfVxuXHQgICAgfSxcblx0ICAgIHtcblx0ICAgICAgICBpZDogJ3BpbmsnLFxuXHQgICAgICAgIGRpc3BsYXlNZXRhZGF0YToge1xuXHQgICAgICAgICAgICBjb2xvcjogJyNGRjhGQjgnLFxuXHQgICAgICAgICAgICBuYW1lOiAncGluaydcblx0ICAgICAgICB9XG5cdCAgICB9LFxuXHQgICAge1xuXHQgICAgICAgIGlkOiAneWVsbG93Jyxcblx0ICAgICAgICBkaXNwbGF5TWV0YWRhdGE6IHtcblx0ICAgICAgICAgICAgY29sb3I6ICcjRTlGRjhGJyxcblx0ICAgICAgICAgICAgbmFtZTogJ3llbGxvdydcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdF07XG5cdC8qKlxuXHQgKiB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5maW4uY28vb2YtZG9jcy9kb2NzL2VuYWJsZS1jb2xvci1saW5raW5nfVxuXHQgKlxuXHQgKiBUaGUgSW50ZXJvcCBCcm9rZXIgaXMgcmVzcG9uc2libGUgZm9yIGtlZXBpbmcgdHJhY2sgb2YgdGhlIEludGVyb3Agc3RhdGUgb2YgdGhlIFBsYXRmb3JtLCBhbmQgZm9yIGRpcmVjdGluZyBtZXNzYWdlcyB0byB0aGUgcHJvcGVyIGxvY2F0aW9ucy5cblx0ICpcblx0ICogQHJlbWFya3MgVGhpcyBjbGFzcyBjb250YWlucyBzb21lIHR5cGVzIHJlbGF0ZWQgdG8gRkRDMyB0aGF0IGFyZSBzcGVjaWZpYyB0byBPcGVuRmluLiB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5maW4uY28vb2YtZG9jcy9kb2NzL2ZkYzMtc3VwcG9ydC1pbi1vcGVuZmluIE9wZW5GaW4ncyBGREMzIHN1cHBvcnR9IGlzIGZvcndhcmQtIGFuZCBiYWNrd2FyZC1jb21wYXRpYmxlLlxuXHQgKiBTdGFuZGFyZCB0eXBlcyBmb3Ige0BsaW5rIGh0dHBzOi8vZmRjMy5maW5vcy5vcmcvIEZEQzN9IGRvIG5vdCBhcHBlYXIgaW4gT3BlbkZpbuKAmXMgQVBJIGRvY3VtZW50YXRpb24sIHRvIGF2b2lkIGR1cGxpY2F0aW9uLlxuXHQgKlxuXHQgKiAtLS1cblx0ICpcblx0ICogVGhlcmUgYXJlIDIgd2F5cyB0byBpbmplY3QgY3VzdG9tIGZ1bmN0aW9uYWxpdHkgaW50byB0aGUgSW50ZXJvcCBCcm9rZXI6XG5cdCAqXG5cdCAqICoqMS4gQ29uZmlndXJhdGlvbioqXG5cdCAqXG5cdCAqIEF0IHRoZSBtb21lbnQsIHlvdSBjYW4gY29uZmlndXJlIHRoZSBkZWZhdWx0IGNvbnRleHQgZ3JvdXBzIGZvciB0aGUgSW50ZXJvcCBCcm9rZXIgd2l0aG91dCBoYXZpbmcgdG8gb3ZlcnJpZGUgaXQuIFRvIGRvIHNvLCBpbmNsdWRlIHRoZSBgaW50ZXJvcEJyb2tlckNvbmZpZ3VyYXRpb25gIGBjb250ZXh0R3JvdXBzYCBvcHRpb24gaW4geW91ciBgcGxhdGZvcm1gIG9wdGlvbnMgaW4geW91ciBtYW5pZmVzdC4gVGhpcyBpcyB0aGUgcHJlZmVycmVkIG1ldGhvZC5cblx0ICogYGBganNcblx0ICoge1xuXHQgKiAgICAgIFwicnVudGltZVwiOiB7XG5cdCAqICAgICAgICAgIFwiYXJndW1lbnRzXCI6IFwiLS12PTEgLS1pbnNwZWN0XCIsXG5cdCAqICAgICAgICAgIFwidmVyc2lvblwiOiBcImFscGhhLXYxOVwiXG5cdCAqICAgICAgfSxcblx0ICogICAgICBcInBsYXRmb3JtXCI6IHtcblx0ICogICAgICAgICAgXCJ1dWlkXCI6IFwicGxhdGZvcm1fY3VzdG9taXphdGlvbl9sb2NhbFwiLFxuXHQgKiAgICAgICAgICBcImFwcGxpY2F0aW9uSWNvblwiOiBcImh0dHBzOi8vb3BlbmZpbi5naXRodWIuaW8vZ29sZGVuLXByb3RvdHlwZS9mYXZpY29uLmljb1wiLFxuXHQgKiAgICAgICAgICBcImF1dG9TaG93XCI6IGZhbHNlLFxuXHQgKiAgICAgICAgICBcInByb3ZpZGVyVXJsXCI6IFwiaHR0cDovL2xvY2FsaG9zdDo1NTU1L3Byb3ZpZGVyLmh0bWxcIixcblx0ICogICAgICAgICAgXCJpbnRlcm9wQnJva2VyQ29uZmlndXJhdGlvblwiOiB7XG5cdCAqICAgICAgICAgICAgICBcImNvbnRleHRHcm91cHNcIjogW1xuXHQgKiAgICAgICAgICAgICAgICAgIHtcblx0ICogICAgICAgICAgICAgICAgICAgICAgXCJpZFwiOiBcImdyZWVuXCIsXG5cdCAqICAgICAgICAgICAgICAgICAgICAgIFwiZGlzcGxheU1ldGFkYXRhXCI6IHtcblx0ICogICAgICAgICAgICAgICAgICAgICAgICAgIFwiY29sb3JcIjogXCIjMDBDQzg4XCIsXG5cdCAqICAgICAgICAgICAgICAgICAgICAgICAgICBcIm5hbWVcIjogXCJncmVlblwiXG5cdCAqICAgICAgICAgICAgICAgICAgICAgIH1cblx0ICogICAgICAgICAgICAgICAgICB9LFxuXHQgKiAgICAgICAgICAgICAgICAgIHtcblx0ICogICAgICAgICAgICAgICAgICAgICAgXCJpZFwiOiBcInB1cnBsZVwiLFxuXHQgKiAgICAgICAgICAgICAgICAgICAgICBcImRpc3BsYXlNZXRhZGF0YVwiOiB7XG5cdCAqICAgICAgICAgICAgICAgICAgICAgICAgICBcImNvbG9yXCI6IFwiIzhDNjFGRlwiLFxuXHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgXCJuYW1lXCI6IFwicHVycGxlXCJcblx0ICogICAgICAgICAgICAgICAgICAgICAgfVxuXHQgKiAgICAgICAgICAgICAgICAgIH0sXG5cdCAqICAgICAgICAgICAgICBdXG5cdCAqICAgICAgICAgIH1cblx0ICogICAgICB9XG5cdCAqIH1cblx0ICogYGBgXG5cdCAqXG5cdCAqIEJ5IGRlZmF1bHQgdGhlIEludGVyb3AgQnJva2VyIGxvZ3MgYWxsIGFjdGlvbnMgdG8gdGhlIGNvbnNvbGUuIFlvdSBjYW4gZGlzYWJsZSB0aGlzIGJ5IHVzaW5nIHRoZSBsb2dnaW5nIG9wdGlvbiBpbiBgaW50ZXJvcEJyb2tlckNvbmZpZ3VyYXRpb25gOlxuXHQgKiBgYGBqc1xuXHQgKiB7XG5cdCAqICAgICAgXCJydW50aW1lXCI6IHtcblx0ICogICAgICAgICAgXCJhcmd1bWVudHNcIjogXCItLXY9MSAtLWluc3BlY3RcIixcblx0ICogICAgICAgICAgXCJ2ZXJzaW9uXCI6IFwiYWxwaGEtdjE5XCJcblx0ICogICAgICB9LFxuXHQgKiAgICAgIFwicGxhdGZvcm1cIjoge1xuXHQgKiAgICAgICAgICBcInV1aWRcIjogXCJwbGF0Zm9ybV9jdXN0b21pemF0aW9uX2xvY2FsXCIsXG5cdCAqICAgICAgICAgIFwiYXBwbGljYXRpb25JY29uXCI6IFwiaHR0cHM6Ly9vcGVuZmluLmdpdGh1Yi5pby9nb2xkZW4tcHJvdG90eXBlL2Zhdmljb24uaWNvXCIsXG5cdCAqICAgICAgICAgIFwiYXV0b1Nob3dcIjogZmFsc2UsXG5cdCAqICAgICAgICAgIFwicHJvdmlkZXJVcmxcIjogXCJodHRwOi8vbG9jYWxob3N0OjU1NTUvcHJvdmlkZXIuaHRtbFwiLFxuXHQgKlx0XHQgICAgXCJpbnRlcm9wQnJva2VyQ29uZmlndXJhdGlvblwiOiB7XG5cdCAqICAgICAgIFx0XHRcImxvZ2dpbmdcIjoge1xuXHQgKiAgIFx0XHRcdFx0XCJiZWZvcmVBY3Rpb25cIjoge1xuXHQgKiAgIFx0XHRcdFx0XHRcImVuYWJsZWRcIjogZmFsc2Vcblx0ICogICBcdFx0XHRcdH0sXG5cdCAqICAgXHRcdFx0XHRcImFmdGVyQWN0aW9uXCI6IHtcblx0ICogICBcdFx0XHRcdFx0XCJlbmFibGVkXCI6IGZhbHNlXG5cdCAqICAgXHRcdFx0XHR9XG5cdCAqICAgXHRcdFx0fVxuXHQgKlx0XHQgICAgfVxuXHQgKiAgICAgIH1cblx0ICogfVxuXHQgKiBgYGBcblx0ICpcblx0ICogLS0tXG5cdCAqICoqMi4gT3ZlcnJpZGluZyoqXG5cdCAqXG5cdCAqIFNpbWlsYXJseSB0byBob3cge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvcGxhdGZvcm0tY3VzdG9taXphdGlvbiNzZWN0aW9uLWN1c3RvbWl6aW5nLXBsYXRmb3JtLWJlaGF2aW9yIFBsYXRmb3JtIE92ZXJyaWRpbmd9IHdvcmtzLCB5b3UgY2FuIG92ZXJyaWRlIGZ1bmN0aW9ucyBpbiB0aGUgSW50ZXJvcCBCcm9rZXIgaW4gYGZpbi5QbGF0Zm9ybS5pbml0YC4gQW4gZXhhbXBsZSBvZiB0aGF0IGlzIHNob3duIGJlbG93LiBPdmVycmlkaW5nIGBpc0Nvbm5lY3Rpb25BdXRob3JpemVkYCBhbmQgYGlzQWN0aW9uQXV0aG9yaXplZGAgd2lsbCBhbGxvdyB5b3UgdG8gY29udHJvbCBhbGxvd2VkIGNvbm5lY3Rpb25zIGFuZCBhbGxvd2VkIGFjdGlvbnMuXG5cdCAqXG5cdCAqIEhvd2V2ZXIsIGlmIHRoZXJlIGlzIGN1c3RvbSBmdW5jdGlvbmFsaXR5IHlvdSB3aXNoIHRvIGluY2x1ZGUgaW4gdGhlIEludGVyb3AgQnJva2VyLCBwbGVhc2UgbGV0IHVzIGtub3cuIFdlIHdvdWxkIGxpa2UgdG8gcHJvdmlkZSBiZXR0ZXIgY29uZmlndXJhdGlvbiBvcHRpb25zIHNvIHRoYXQgeW91IGRvbid0IGhhdmUgdG8gY29udGludWFsbHkgbWFpbnRhaW4geW91ciBvd24gb3ZlcnJpZGUgY29kZS5cblx0ICpcblx0ICogYGBganNcblx0ICogZmluLlBsYXRmb3JtLmluaXQoe1xuXHQgKiAgICAgb3ZlcnJpZGVDYWxsYmFjazogYXN5bmMgKFByb3ZpZGVyKSA9PiB7XG5cdCAqICAgICAgICAgY2xhc3MgT3ZlcnJpZGUgZXh0ZW5kcyBQcm92aWRlciB7XG5cdCAqICAgICAgICAgICAgIGFzeW5jIGdldFNuYXBzaG90KCkge1xuXHQgKiAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ2JlZm9yZSBnZXRTbmFwc2hvdCcpXG5cdCAqICAgICAgICAgICAgICAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHN1cGVyLmdldFNuYXBzaG90KCk7XG5cdCAqICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnYWZ0ZXIgZ2V0U25hcHNob3QnKVxuXHQgKiAgICAgICAgICAgICAgICAgcmV0dXJuIHNuYXBzaG90O1xuXHQgKiAgICAgICAgICAgICB9XG5cdCAqXG5cdCAqICAgICAgICAgICAgIGFzeW5jIGFwcGx5U25hcHNob3QoeyBzbmFwc2hvdCwgb3B0aW9ucyB9KSB7XG5cdCAqICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnYmVmb3JlIGFwcGx5U25hcHNob3QnKVxuXHQgKiAgICAgICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxQcm9taXNlID0gc3VwZXIuYXBwbHlTbmFwc2hvdCh7IHNuYXBzaG90LCBvcHRpb25zIH0pO1xuXHQgKiAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ2FmdGVyIGFwcGx5U25hcHNob3QnKVxuXHQgKlxuXHQgKiAgICAgICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsUHJvbWlzZTtcblx0ICogICAgICAgICAgICAgfVxuXHQgKiAgICAgICAgIH07XG5cdCAqICAgICAgICAgcmV0dXJuIG5ldyBPdmVycmlkZSgpO1xuXHQgKiAgICAgfSxcblx0ICogICAgIGludGVyb3BPdmVycmlkZTogYXN5bmMgKEludGVyb3BCcm9rZXIpID0+IHtcblx0ICogICAgICAgICBjbGFzcyBPdmVycmlkZSBleHRlbmRzIEludGVyb3BCcm9rZXIge1xuXHQgKiAgICAgICAgICAgICBhc3luYyBqb2luQ29udGV4dEdyb3VwKGNoYW5uZWxOYW1lID0gJ2RlZmF1bHQnLCB0YXJnZXQpIHtcblx0ICogICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdiZWZvcmUgc3VwZXIgam9pbkNvbnRleHRHcm91cCcpXG5cdCAqICAgICAgICAgICAgICAgICBzdXBlci5qb2luQ29udGV4dEdyb3VwKGNoYW5uZWxOYW1lLCB0YXJnZXQpO1xuXHQgKiAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ2FmdGVyIHN1cGVyIGpvaW5Db250ZXh0R3JvdXAnKVxuXHQgKiAgICAgICAgICAgICB9XG5cdCAqICAgICAgICAgfVxuXHQgKlxuXHQgKiAgICAgICByZXR1cm4gbmV3IE92ZXJyaWRlKCk7XG5cdCAqICAgfVxuXHQgKiB9KTtcblx0ICogYGBgXG5cdCAqXG5cdCAqIC0tLVxuXHQgKlxuXHQgKi9cblx0bGV0IEludGVyb3BCcm9rZXIkMSA9IGNsYXNzIEludGVyb3BCcm9rZXIgZXh0ZW5kcyBiYXNlXzEuQmFzZSB7XG5cdCAgICAvKipcblx0ICAgICAqIEBpbnRlcm5hbFxuXHQgICAgICovXG5cdCAgICBjb25zdHJ1Y3Rvcih3aXJlLCBjcmVhdGVQcm92aWRlciwgb3B0aW9ucykge1xuXHQgICAgICAgIC8vIFRpcCBmcm9tIFBpZXJyZSBhbmQgTWljaGFlbCBmcm9tIHRoZSBvdmVycmlkZUNoZWNrIHdvcms6IERvbid0IHVzZSBib3VuZCBtZXRob2RzIGZvciBvdmVycmlkZWFibGUgSW50ZXJvcEJyb2tlciBmdW5jdGlvbnMuXG5cdCAgICAgICAgc3VwZXIod2lyZSk7XG5cdCAgICAgICAgX0ludGVyb3BCcm9rZXJfZmRjM0luZm8uc2V0KHRoaXMsIHZvaWQgMCk7XG5cdCAgICAgICAgX0ludGVyb3BCcm9rZXJfY29udGV4dEdyb3Vwcy5zZXQodGhpcywgdm9pZCAwKTtcblx0ICAgICAgICBfSW50ZXJvcEJyb2tlcl9wcm92aWRlclByb21pc2Uuc2V0KHRoaXMsIHZvaWQgMCk7XG5cdCAgICAgICAgdGhpcy5nZXRQcm92aWRlciA9ICgpID0+IHtcblx0ICAgICAgICAgICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BCcm9rZXJfcHJvdmlkZXJQcm9taXNlLCBcImZcIikuZ2V0VmFsdWUoKTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIHRoaXMuaW50ZXJvcENsaWVudHMgPSBuZXcgTWFwKCk7XG5cdCAgICAgICAgdGhpcy5jb250ZXh0R3JvdXBzQnlJZCA9IG5ldyBNYXAoKTtcblx0ICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9JbnRlcm9wQnJva2VyX2NvbnRleHRHcm91cHMsIG9wdGlvbnMuY29udGV4dEdyb3VwcyA/PyBbLi4uZGVmYXVsdENvbnRleHRHcm91cHNdLCBcImZcIik7XG5cdCAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfSW50ZXJvcEJyb2tlcl9mZGMzSW5mbywgb3B0aW9ucy5mZGMzSW5mbywgXCJmXCIpO1xuXHQgICAgICAgIGlmIChvcHRpb25zPy5sb2dnaW5nKSB7XG5cdCAgICAgICAgICAgIHRoaXMubG9nZ2luZyA9IG9wdGlvbnMubG9nZ2luZztcblx0ICAgICAgICB9XG5cdCAgICAgICAgdGhpcy5pbnRlbnRDbGllbnRNYXAgPSBuZXcgTWFwKCk7XG5cdCAgICAgICAgdGhpcy5sYXN0Q29udGV4dE1hcCA9IG5ldyBNYXAoKTtcblx0ICAgICAgICB0aGlzLnNlc3Npb25Db250ZXh0R3JvdXBNYXAgPSBuZXcgTWFwKCk7XG5cdCAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfSW50ZXJvcEJyb2tlcl9wcm92aWRlclByb21pc2UsIG5ldyBsYXp5XzEuTGF6eShjcmVhdGVQcm92aWRlciksIFwiZlwiKTtcblx0ICAgICAgICB0aGlzLnNldENvbnRleHRHcm91cE1hcCgpO1xuXHQgICAgICAgIHRoaXMuc2V0dXBDaGFubmVsUHJvdmlkZXIoKTtcblx0ICAgIH1cblx0ICAgIHN0YXRpYyBjcmVhdGVDbG9zZWRDb25zdHJ1Y3RvciguLi5hcmdzKSB7XG5cdCAgICAgICAgcmV0dXJuIGNsYXNzIE92ZXJyaWRlYWJsZUJyb2tlciBleHRlbmRzIEludGVyb3BCcm9rZXIge1xuXHQgICAgICAgICAgICBjb25zdHJ1Y3RvciguLi51bnVzZWQpIHtcblx0ICAgICAgICAgICAgICAgIGlmICh1bnVzZWQubGVuZ3RoKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgY29uc3QgW19pZ25vcmUxLCBpZ25vcmUyLCBvcHRzXSA9IHVudXNlZDtcblx0ICAgICAgICAgICAgICAgICAgICBpZiAob3B0cyAmJiB0eXBlb2Ygb3B0cyA9PT0gJ29iamVjdCcgJiYgISgwLCBpc0VxdWFsXzEuZGVmYXVsdCkob3B0cywgYXJnc1syXSkpIHtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcblx0ICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3UgaGF2ZSBtb2RpZmllZCB0aGUgcGFyYW1ldGVycyBvZiB0aGUgSW50ZXJvcE92ZXJyaWRlIGNvbnN0cnVjdG9yLiBUaGlzIGJlaGF2aW9yIGlzIGRlcHJlY2F0ZWQgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiBhIGZ1dHVyZSB2ZXJzaW9uLiBZb3UgY2FuIG1vZGlmeSB0aGVzZSBvcHRpb25zIGluIHlvdXIgbWFuaWZlc3QuIFBsZWFzZSBjb25zdWx0IG91ciBJbnRlcm9wIGRvY3MgZm9yIGd1aWRhbmNlIG9uIG1pZ3JhdGluZyB0byB0aGUgbmV3IG92ZXJyaWRlIHNjaGVtZS4nKTtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIoYXJnc1swXSwgYXJnc1sxXSwgb3B0cyk7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcblx0ICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcblx0ICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1lvdSBhcmUgYXR0ZW1wdGluZyB0byBwYXNzIGFyZ3VtZW50cyB0byB0aGUgSW50ZXJvcE92ZXJyaWRlIGNvbnN0cnVjdG9yLiBUaGlzIGlzIG5vdCBuZWNlc3NhcnksIGFuZCB0aGVzZSBwYXNzZWQgYXJndW1lbnRzIHdpbGwgYmUgaWdub3JlZC4gWW91IGFyZSBsaWtlbHkgdXNpbmcgYW4gb2xkZXIgSW50ZXJvcEJyb2tlciBvdmVycmlkZSBzY2hlbWUuIFBsZWFzZSBjb25zdWx0IG91ciBJbnRlcm9wIGRvY3MgZm9yIGd1aWRhbmNlIG9uIG1pZ3JhdGluZyB0byB0aGUgbmV3IG92ZXJyaWRlIHNjaGVtZS4nKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIHN1cGVyKC4uLmFyZ3MpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfTtcblx0ICAgIH1cblx0ICAgIC8qXG5cdCAgICBDbGllbnQgQVBJXG5cdCAgICAqL1xuXHQgICAgLyoqXG5cdCAgICAgKiBTZXRzIGEgY29udGV4dCBmb3IgdGhlIGNvbnRleHQgZ3JvdXAgb2YgdGhlIGluY29taW5nIGN1cnJlbnQgZW50aXR5LlxuXHQgICAgICogQHBhcmFtIHNldENvbnRleHRPcHRpb25zIC0gTmV3IGNvbnRleHQgdG8gc2V0LlxuXHQgICAgICogQHBhcmFtIGNsaWVudElkZW50aXR5IC0gSWRlbnRpdHkgb2YgdGhlIGNsaWVudCBzZW5kZXIuXG5cdCAgICAgKlxuXHQgICAgICovXG5cdCAgICBzZXRDb250ZXh0KHsgY29udGV4dCB9LCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWJyb2tlci1zZXQtY29udGV4dCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKGNsaWVudFN0YXRlICYmIGNsaWVudFN0YXRlLmNvbnRleHRHcm91cElkKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IHsgY29udGV4dEdyb3VwSWQgfSA9IGNsaWVudFN0YXRlO1xuXHQgICAgICAgICAgICB0aGlzLnNldENvbnRleHRGb3JHcm91cCh7IGNvbnRleHQgfSwgY29udGV4dEdyb3VwSWQpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIGlmIChjbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICAvLyBDbGllbnQgaGFzIG5vdCBqb2luZWQgYW55IGNvbnRleHQgZ3JvdXAgYmVoYXZpb3IuXG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IG11c3Qgam9pbiBhIGNvbnRleHQgZ3JvdXAgYmVmb3JlIHlvdSBjYW4gc2V0IGNvbnRleHQuJyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICAvLyBUaGlzIHNob3VsZG4ndCBnZXQgaGl0LlxuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsaWVudCB3aXRoIElkZW50aXR5OiAke2NsaWVudElkZW50aXR5LnV1aWR9ICR7Y2xpZW50SWRlbnRpdHkubmFtZX0gbm90IGluIENsaWVudCBTdGF0ZSBNYXBgKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNldHMgYSBjb250ZXh0IGZvciB0aGUgY29udGV4dCBncm91cC5cblx0ICAgICAqIEBwYXJhbSBzZXRDb250ZXh0T3B0aW9ucyAtIE5ldyBjb250ZXh0IHRvIHNldC5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0R3JvdXBJZCAtIENvbnRleHQgZ3JvdXAgaWQuXG5cdCAgICAgKlxuXHQgICAgICovXG5cdCAgICBzZXRDb250ZXh0Rm9yR3JvdXAoeyBjb250ZXh0IH0sIGNvbnRleHRHcm91cElkKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtYnJva2VyLXNldC1jb250ZXh0LWZvci1ncm91cCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNvbnRleHRHcm91cFN0YXRlID0gdGhpcy5jb250ZXh0R3JvdXBzQnlJZC5nZXQoY29udGV4dEdyb3VwSWQpO1xuXHQgICAgICAgIGlmICghY29udGV4dEdyb3VwU3RhdGUpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gc2V0IGNvbnRleHQgZm9yIGNvbnRleHQgZ3JvdXAgdGhhdCBpc24ndCBpbiB0aGUgY29udGV4dCBncm91cCBtYXBwaW5nOiAke2NvbnRleHRHcm91cElkfS5gKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3QgY29udGV4dEludGVncml0eUNoZWNrUmVzdWx0ID0gSW50ZXJvcEJyb2tlci5jaGVja0NvbnRleHRJbnRlZ3JpdHkoY29udGV4dCk7XG5cdCAgICAgICAgaWYgKGNvbnRleHRJbnRlZ3JpdHlDaGVja1Jlc3VsdC5pc1ZhbGlkID09PSBmYWxzZSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBzZXQgQ29udGV4dCAtIGJhZCBDb250ZXh0LiBSZWFzb246ICR7Y29udGV4dEludGVncml0eUNoZWNrUmVzdWx0LnJlYXNvbn0uIENvbnRleHQ6ICR7SlNPTi5zdHJpbmdpZnkoY29udGV4dCl9YCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNvbnN0IGJyb2FkY2FzdGVkQ29udGV4dFR5cGUgPSBjb250ZXh0LnR5cGU7XG5cdCAgICAgICAgY29udGV4dEdyb3VwU3RhdGUuc2V0KGJyb2FkY2FzdGVkQ29udGV4dFR5cGUsIGNvbnRleHQpO1xuXHQgICAgICAgIHRoaXMubGFzdENvbnRleHRNYXAuc2V0KGNvbnRleHRHcm91cElkLCBicm9hZGNhc3RlZENvbnRleHRUeXBlKTtcblx0ICAgICAgICBjb25zdCBjbGllbnRzSW5TYW1lQ29udGV4dEdyb3VwID0gQXJyYXkuZnJvbSh0aGlzLmludGVyb3BDbGllbnRzLnZhbHVlcygpKS5maWx0ZXIoKGNvbm5lY3RlZENsaWVudCkgPT4gY29ubmVjdGVkQ2xpZW50LmNvbnRleHRHcm91cElkID09PSBjb250ZXh0R3JvdXBJZCk7XG5cdCAgICAgICAgY2xpZW50c0luU2FtZUNvbnRleHRHcm91cC5mb3JFYWNoKChjbGllbnQpID0+IHtcblx0ICAgICAgICAgICAgZm9yIChjb25zdCBbLCBoYW5kbGVySW5mb10gb2YgY2xpZW50LmNvbnRleHRIYW5kbGVycykge1xuXHQgICAgICAgICAgICAgICAgaWYgKEludGVyb3BCcm9rZXIuaXNDb250ZXh0VHlwZUNvbXBhdGlibGUoYnJvYWRjYXN0ZWRDb250ZXh0VHlwZSwgaGFuZGxlckluZm8uY29udGV4dFR5cGUpKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnZva2VDb250ZXh0SGFuZGxlcihjbGllbnQuY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJbmZvLmhhbmRsZXJJZCwgY29udGV4dCk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0IGN1cnJlbnQgY29udGV4dCBmb3IgYSBjbGllbnQgc3Vic2NyaWJlZCB0byBhIENvbnRleHQgR3JvdXAuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgSXQgdGFrZXMgYW4gb3B0aW9uYWwgQ29udGV4dCBUeXBlIGFyZ3VtZW50IGFuZCByZXR1cm5zIHRoZSBsYXN0IGNvbnRleHQgb2YgdGhhdCB0eXBlLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBnZXRDb250ZXh0T3B0aW9ucyAtIE9wdGlvbnMgZm9yIGdldHRpbmcgY29udGV4dFxuXHQgICAgICogQHBhcmFtIGNsaWVudElkZW50aXR5IC0gSWRlbnRpdHkgb2YgdGhlIGNsaWVudCBzZW5kZXIuXG5cdCAgICAgKlxuXHQgICAgICovXG5cdCAgICBnZXRDdXJyZW50Q29udGV4dChnZXRDdXJyZW50Q29udGV4dE9wdGlvbnMsIGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtYnJva2VyLWdldC1jdXJyZW50LWNvbnRleHQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGlmICghY2xpZW50U3RhdGU/LmNvbnRleHRHcm91cElkKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IG11c3QgYmUgYSBtZW1iZXIgb2YgYSBjb250ZXh0IGdyb3VwIHRvIGNhbGwgZ2V0Q3VycmVudENvbnRleHQnKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3QgeyBjb250ZXh0R3JvdXBJZCB9ID0gY2xpZW50U3RhdGU7XG5cdCAgICAgICAgY29uc3QgY29udGV4dEdyb3VwU3RhdGUgPSB0aGlzLmNvbnRleHRHcm91cHNCeUlkLmdldChjb250ZXh0R3JvdXBJZCk7XG5cdCAgICAgICAgY29uc3QgbGFzdENvbnRleHRUeXBlID0gdGhpcy5sYXN0Q29udGV4dE1hcC5nZXQoY29udGV4dEdyb3VwSWQpO1xuXHQgICAgICAgIGNvbnN0IGNvbnRleHRUeXBlID0gZ2V0Q3VycmVudENvbnRleHRPcHRpb25zPy5jb250ZXh0VHlwZSA/PyBsYXN0Q29udGV4dFR5cGU7XG5cdCAgICAgICAgcmV0dXJuIGNvbnRleHRHcm91cFN0YXRlICYmIGNvbnRleHRUeXBlID8gY29udGV4dEdyb3VwU3RhdGUuZ2V0KGNvbnRleHRUeXBlKSA6IHVuZGVmaW5lZDtcblx0ICAgIH1cblx0ICAgIC8qXG5cdCAgICBQbGF0Zm9ybSBXaW5kb3cgQVBJc1xuXHQgICAgKi9cblx0ICAgIC8vIGpvaW5Db250ZXh0R3JvdXAgYW5kIGFkZENsaWVudFRvQ29udGV4dEdyb3VwIGFyZSBzZXBhcmF0ZSBmdW5jdGlvbnMgaGVyZSwgZm9yIGVhc2llciBvdmVycmlkZXMgYW5kIHNlcGFyYXRpb24gb2YgY29uY2VybnMuXG5cdCAgICAvLyBqb2luQ29udGV4dEdyb3VwIGNoZWNrcyBhbGwgY29ubmVjdGlvbnMgZm9yIG1hdGNoaW5nIGlkZW50aXRpZXMsIGluIGNhc2Ugd2UgaGF2ZSBtdWx0aXBsZSBjb25uZWN0aW9uIGZyb20gYW4gZW50aXR5LlxuXHQgICAgLyoqXG5cdCAgICAgKiBKb2luIGFsbCBjb25uZWN0aW9ucyBhdCB0aGUgZ2l2ZW4gaWRlbnRpdHkgKG9yIGp1c3Qgb25lIGlmIGVuZHBvaW50SWQgcHJvdmlkZWQpIHRvIGNvbnRleHQgZ3JvdXAgYGNvbnRleHRHcm91cElkYC5cblx0ICAgICAqIElmIG5vIHRhcmdldCBpcyBzcGVjaWZpZWQsIGl0IGFkZHMgdGhlIHNlbmRlciB0byB0aGUgY29udGV4dCBncm91cC5cblx0ICAgICAqIGpvaW5Db250ZXh0R3JvdXAgaXMgcmVzcG9uc2libGUgZm9yIGNoZWNraW5nIGNvbm5lY3Rpb25zIGF0IHRoZSBpbmNvbWluZyBpZGVudGl0eS4gSXQgY2FsbHMge0BsaW5rIEludGVyb3BCcm9rZXIjYWRkQ2xpZW50VG9Db250ZXh0R3JvdXAgSW50ZXJvcEJyb2tlci5hZGRDbGllbnRUb0NvbnRleHRHcm91cH0gdG8gYWN0dWFsbHkgZ3JvdXAgdGhlIGNsaWVudC5cblx0ICAgICAqIFVzZWQgYnkgUGxhdGZvcm0gV2luZG93cy5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gam9pbkNvbnRleHRHcm91cE9wdGlvbnMgLSBJZCBvZiB0aGUgQ29udGV4dCBHcm91cCBhbmQgaWRlbnRpdHkgb2YgdGhlIGVudGl0eSB0byBqb2luIHRvIHRoZSBncm91cC5cblx0ICAgICAqIEBwYXJhbSBzZW5kZXJJZGVudGl0eSAtIElkZW50aXR5IG9mIHRoZSBjbGllbnQgc2VuZGVyLlxuXHQgICAgICovXG5cdCAgICBhc3luYyBqb2luQ29udGV4dEdyb3VwKHsgY29udGV4dEdyb3VwSWQsIHRhcmdldCB9LCBzZW5kZXJJZGVudGl0eSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWJyb2tlci1qb2luLWNvbnRleHQtZ3JvdXAnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBpZiAodGhpcy5zZXNzaW9uQ29udGV4dEdyb3VwTWFwLmhhcyhjb250ZXh0R3JvdXBJZCkpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5qb2luU2Vzc2lvbkNvbnRleHRHcm91cFdpdGhKb2luQ29udGV4dEdyb3VwKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgaWYgKHRhcmdldCkge1xuXHQgICAgICAgICAgICAvLyBJZiBhbiBlbmRwb2ludElkIGlzIHByb3ZpZGVkLCB1c2UgdGhhdC4gVGhpcyB3aWxsIGxpa2VseSBiZSB1c2VkIGJ5IGV4dGVybmFsIGFkYXB0ZXJzLlxuXHQgICAgICAgICAgICBpZiAoSW50ZXJvcEJyb2tlci5oYXNFbmRwb2ludElkKHRhcmdldCkpIHtcblx0ICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuYWRkQ2xpZW50VG9Db250ZXh0R3JvdXAoeyBjb250ZXh0R3JvdXBJZCB9LCB0YXJnZXQpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIC8vIFNhbml0eSBjaGVjayBoZXJlIGluIGNhc2UgYSBzaW5nbGUgYXBwIGhhcyBtdWx0aXBsZSBjb25uZWN0aW9uc1xuXHQgICAgICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgYWxsQ29ubmVjdGlvbnMgPSB0aGlzLmNoYW5uZWwuY29ubmVjdGlvbnMuZmlsdGVyKCh4KSA9PiB4LnV1aWQgPT09IHRhcmdldC51dWlkICYmIHgubmFtZSA9PT0gdGFyZ2V0Lm5hbWUpO1xuXHQgICAgICAgICAgICAgICAgaWYgKCFhbGxDb25uZWN0aW9ucy5sZW5ndGgpIHtcblx0ICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEdpdmVuIElkZW50aXR5ICR7dGFyZ2V0LnV1aWR9ICR7dGFyZ2V0Lm5hbWV9IGlzIG5vdCBjb25uZWN0ZWQgdG8gdGhlIEludGVyb3AgQnJva2VyLmApO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgaWYgKGFsbENvbm5lY3Rpb25zLmxlbmd0aCA+IDEpIHtcblx0ICAgICAgICAgICAgICAgICAgICAvLyBTaG91bGQgZmlndXJlIG91dCBob3cgd2Ugd2FudCB0byBoYW5kbGUgdGhpcyBzaXR1YXRpb24uIEluIHRoZSBtZWFudGltZSwganVzdCBjaGFuZ2UgY29udGV4dCBncm91cCBmb3IgYWxsIGNvbm5lY3Rpb25zLlxuXHQgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgTW9yZSB0aGFuIG9uZSBjb25uZWN0aW9uIGZvdW5kIGZvciBpZGVudGl0eSAke3RhcmdldC51dWlkfSAke3RhcmdldC5uYW1lfWApO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBbXTtcblx0ICAgICAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbiBvZiBhbGxDb25uZWN0aW9ucykge1xuXHQgICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5hZGRDbGllbnRUb0NvbnRleHRHcm91cCh7IGNvbnRleHRHcm91cElkIH0sIGNvbm5lY3Rpb24pKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIC8vIE5vIHRhcmdldCBwcm92aWRlZCwgYWRkIHRoZSBzZW5kZXIgdG8gdGhlIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgICAgICAgIGF3YWl0IHRoaXMuYWRkQ2xpZW50VG9Db250ZXh0R3JvdXAoeyBjb250ZXh0R3JvdXBJZCB9LCBzZW5kZXJJZGVudGl0eSk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLy8gYWRkQ2xpZW50VG9Db250ZXh0R3JvdXAgZG9lcyB0aGUgYWN0dWFsIGFkZGl0aW9uIG9mIHRoZSBjbGllbnQgdG8gdGhlIENvbnRleHQgR3JvdXBcblx0ICAgIC8qKlxuXHQgICAgICogSGVscGVyIGZ1bmN0aW9uIGZvciB7QGxpbmsgSW50ZXJvcEJyb2tlciNqb2luQ29udGV4dEdyb3VwIEludGVyb3BCcm9rZXIuam9pbkNvbnRleHRHcm91cH0uIERvZXMgdGhlIHdvcmsgb2YgYWN0dWFsbHkgYWRkaW5nIHRoZSBjbGllbnQgdG8gdGhlIENvbnRleHQgR3JvdXAuXG5cdCAgICAgKiBVc2VkIGJ5IFBsYXRmb3JtIFdpbmRvd3MuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGFkZENsaWVudFRvQ29udGV4dEdyb3VwT3B0aW9ucyAtIENvbnRhaW5zIHRoZSBjb250ZXh0R3JvdXBJZFxuXHQgICAgICogQHBhcmFtIGNsaWVudElkZW50aXR5IC0gSWRlbnRpdHkgb2YgdGhlIGNsaWVudCBzZW5kZXIuXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGFkZENsaWVudFRvQ29udGV4dEdyb3VwKHsgY29udGV4dEdyb3VwSWQgfSwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItYWRkLWNsaWVudC10by1jb250ZXh0LWdyb3VwJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUgPSB0aGlzLmdldENsaWVudFN0YXRlKGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICBpZiAoIWNsaWVudFN1YnNjcmlwdGlvblN0YXRlKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2xpZW50IHdpdGggSWRlbnRpdHk6ICR7Y2xpZW50SWRlbnRpdHkudXVpZH0gJHtjbGllbnRJZGVudGl0eS5uYW1lfSBub3QgaW4gQ2xpZW50IFN0YXRlIE1hcGApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBpZiAoIXRoaXMuZ2V0Q29udGV4dEdyb3VwcygpLmZpbmQoKGNvbnRleHRHcm91cEluZm8pID0+IGNvbnRleHRHcm91cEluZm8uaWQgPT09IGNvbnRleHRHcm91cElkKSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEF0dGVtcHRpbmcgdG8gam9pbiBhIGNvbnRleHQgZ3JvdXAgdGhhdCBkb2VzIG5vdCBleGlzdDogJHtjb250ZXh0R3JvdXBJZH0uIFlvdSBtYXkgb25seSBqb2luIGV4aXN0aW5nIGNvbnRleHQgZ3JvdXBzLmApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjb25zdCBvbGRDb250ZXh0R3JvdXBJZCA9IGNsaWVudFN1YnNjcmlwdGlvblN0YXRlLmNvbnRleHRHcm91cElkO1xuXHQgICAgICAgIGlmIChvbGRDb250ZXh0R3JvdXBJZCAhPT0gY29udGV4dEdyb3VwSWQpIHtcblx0ICAgICAgICAgICAgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUuY29udGV4dEdyb3VwSWQgPSBjb250ZXh0R3JvdXBJZDtcblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy5zZXRDdXJyZW50Q29udGV4dEdyb3VwSW5DbGllbnRPcHRpb25zKGNsaWVudElkZW50aXR5LCBjb250ZXh0R3JvdXBJZCk7XG5cdCAgICAgICAgICAgIGNvbnN0IGNvbnRleHRHcm91cE1hcCA9IHRoaXMuY29udGV4dEdyb3Vwc0J5SWQuZ2V0KGNvbnRleHRHcm91cElkKTtcblx0ICAgICAgICAgICAgZm9yIChjb25zdCBbLCBoYW5kbGVySW5mb10gb2YgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUuY29udGV4dEhhbmRsZXJzKSB7XG5cdCAgICAgICAgICAgICAgICBjb25zdCB7IGNvbnRleHRUeXBlLCBoYW5kbGVySWQgfSA9IGhhbmRsZXJJbmZvO1xuXHQgICAgICAgICAgICAgICAgaWYgKGNvbnRleHRUeXBlID09PSB1bmRlZmluZWQpIHtcblx0ICAgICAgICAgICAgICAgICAgICAvLyBTZW5kIHRoaXMgc2luZ2xlIGhhbmRsZXIgYWxsIG9mIHRoZSBjb250ZXh0LCBiZWNhdXNlIGl0IGFjY2VwdHMgYWxsLlxuXHQgICAgICAgICAgICAgICAgICAgIGNvbnRleHRHcm91cE1hcC5mb3JFYWNoKChjb250ZXh0LCBfKSA9PiB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW52b2tlQ29udGV4dEhhbmRsZXIoY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwgY29udGV4dCk7XG5cdCAgICAgICAgICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICBlbHNlIGlmIChjb250ZXh0R3JvdXBNYXAuaGFzKGNvbnRleHRUeXBlKSkge1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRleHRGb3JUeXBlID0gY29udGV4dEdyb3VwTWFwLmdldChjb250ZXh0VHlwZSk7XG5cdCAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnRleHRGb3JUeXBlKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW52b2tlQ29udGV4dEhhbmRsZXIoY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwgY29udGV4dEZvclR5cGUpO1xuXHQgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8vIFJlbW92ZXMgdGhlIHRhcmdldCBmcm9tIGl0cyBjb250ZXh0IGdyb3VwLiBTaW1pbGFyIHN0cnVjdHVyZSB0byBqb2luQ29udGV4dEdyb3VwLlxuXHQgICAgLyoqXG5cdCAgICAgKiBSZW1vdmVzIHRoZSBzcGVjaWZpZWQgdGFyZ2V0IGZyb20gYSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICogSWYgbm8gdGFyZ2V0IGlzIHNwZWNpZmllZCwgaXQgcmVtb3ZlcyB0aGUgc2VuZGVyIGZyb20gdGhlaXIgY29udGV4dCBncm91cC5cblx0ICAgICAqIHJlbW92ZUZyb21Db250ZXh0R3JvdXAgaXMgcmVzcG9uc2libGUgZm9yIGNoZWNraW5nIGNvbm5lY3Rpb25zIGF0IHRoZSBpbmNvbWluZyBpZGVudGl0eS5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBJdCBjYWxscyB7QGxpbmsgSW50ZXJvcEJyb2tlciNyZW1vdmVDbGllbnRGcm9tQ29udGV4dEdyb3VwIEludGVyb3BCcm9rZXIucmVtb3ZlQ2xpZW50RnJvbUNvbnRleHRHcm91cH0gdG8gYWN0dWFsbHkgdW5ncm91cFxuXHQgICAgICogdGhlIGNsaWVudC4gVXNlZCBieSBQbGF0Zm9ybSBXaW5kb3dzLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSByZW1vdmVGcm9tQ29udGV4dEdyb3VwT3B0aW9ucyAtIENvbnRhaW5zIHRoZSB0YXJnZXQgaWRlbnRpdHkgdG8gcmVtb3ZlLlxuXHQgICAgICogQHBhcmFtIHNlbmRlcklkZW50aXR5IC0gSWRlbnRpdHkgb2YgdGhlIGNsaWVudCBzZW5kZXIuXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHJlbW92ZUZyb21Db250ZXh0R3JvdXAoeyB0YXJnZXQgfSwgc2VuZGVySWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItcmVtb3ZlLWZyb20tY29udGV4dC1ncm91cCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGlmICh0YXJnZXQpIHtcblx0ICAgICAgICAgICAgLy8gSWYgYW4gZW5kcG9pbnRJZCBpcyBwcm92aWRlZCwgdXNlIHRoYXQuIFRoaXMgd2lsbCBsaWtlbHkgYmUgdXNlZCBieSBleHRlcm5hbCBhZGFwdGVycy5cblx0ICAgICAgICAgICAgaWYgKEludGVyb3BCcm9rZXIuaGFzRW5kcG9pbnRJZCh0YXJnZXQpKSB7XG5cdCAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJlbW92ZUNsaWVudEZyb21Db250ZXh0R3JvdXAodGFyZ2V0KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICAgICAgLy8gU2FuaXR5IGNoZWNrIGhlcmUgaW4gY2FzZSBhIHNpbmdsZSBhcHAgaGFzIG11bHRpcGxlIGNvbm5lY3Rpb25zXG5cdCAgICAgICAgICAgICAgICBjb25zdCBhbGxDb25uZWN0aW9ucyA9IHRoaXMuY2hhbm5lbC5jb25uZWN0aW9ucy5maWx0ZXIoKHgpID0+IHgudXVpZCA9PT0gdGFyZ2V0LnV1aWQgJiYgeC5uYW1lID09PSB0YXJnZXQubmFtZSk7XG5cdCAgICAgICAgICAgICAgICBpZiAoIWFsbENvbm5lY3Rpb25zLmxlbmd0aCkge1xuXHQgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gY29ubmVjdGlvbiBmb3VuZCBmb3IgZ2l2ZW4gSWRlbnRpdHkgJHt0YXJnZXQudXVpZH0gJHt0YXJnZXQubmFtZX1gKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIGlmIChhbGxDb25uZWN0aW9ucy5sZW5ndGggPiAxKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBNb3JlIHRoYW4gb25lIGNvbm5lY3Rpb24gZm91bmQgZm9yIGlkZW50aXR5ICR7dGFyZ2V0LnV1aWR9ICR7dGFyZ2V0Lm5hbWV9YCk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuXHQgICAgICAgICAgICAgICAgZm9yIChjb25zdCBjb25uZWN0aW9uIG9mIGFsbENvbm5lY3Rpb25zKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLnJlbW92ZUNsaWVudEZyb21Db250ZXh0R3JvdXAoY29ubmVjdGlvbikpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgLy8gTm8gdGFyZ2V0IHByb3ZpZGVkLCByZW1vdmUgdGhlIHNlbmRlciBmcm9tIHRoZSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICAgICAgICBhd2FpdCB0aGlzLnJlbW92ZUNsaWVudEZyb21Db250ZXh0R3JvdXAoc2VuZGVySWRlbnRpdHkpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8vIHJlbW92ZUNsaWVudEZyb21Db250ZXh0R3JvdXAgZG9lcyB0aGUgYWN0dWFsIHJlbW92ZSBvZiB0aGUgY2xpZW50IGZyb20gdGhlIENvbnRleHQgR3JvdXBcblx0ICAgIC8qKlxuXHQgICAgICogSGVscGVyIGZ1bmN0aW9uIGZvciB7QGxpbmsgSW50ZXJvcEJyb2tlciNyZW1vdmVGcm9tQ29udGV4dEdyb3VwIEludGVyb3BCcm9rZXIucmVtb3ZlRnJvbUNvbnRleHRHcm91cH0uIERvZXMgdGhlIHdvcmsgb2YgYWN0dWFsbHkgcmVtb3ZpbmcgdGhlIGNsaWVudCBmcm9tIHRoZSBDb250ZXh0IEdyb3VwLlxuXHQgICAgICogVXNlZCBieSBQbGF0Zm9ybSBXaW5kb3dzLlxuXHQgICAgICpcblx0ICAgICAqIEBwcm9wZXJ0eSB7IENsaWVudElkZW50aXR5IH0gY2xpZW50SWRlbnRpdHkgLSBJZGVudGl0eSBvZiB0aGUgY2xpZW50IHNlbmRlci5cblx0ICAgICAqL1xuXHQgICAgYXN5bmMgcmVtb3ZlQ2xpZW50RnJvbUNvbnRleHRHcm91cChjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWJyb2tlci1yZW1vdmUtY2xpZW50LWZyb20tY29udGV4dC1ncm91cCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKGNsaWVudFN0YXRlKSB7XG5cdCAgICAgICAgICAgIGNsaWVudFN0YXRlLmNvbnRleHRHcm91cElkID0gdW5kZWZpbmVkO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBhd2FpdCB0aGlzLnNldEN1cnJlbnRDb250ZXh0R3JvdXBJbkNsaWVudE9wdGlvbnMoY2xpZW50SWRlbnRpdHksIG51bGwpO1xuXHQgICAgfVxuXHQgICAgLy8gVXNlZCBieSBwbGF0Zm9ybSB3aW5kb3dzIHRvIGtub3cgd2hhdCBjbGllbnQgZ3JvdXBzIHRoZSBwcm92aWRlciBoYXMgZGVjbGFyZWQuIEFsc28gdXNlZCBpbnRlcm5hbGx5IHRvIGFjY2VzcyBjb250ZXh0IGdyb3Vwcy4gT3ZlcnJpZGVhYmxlIHNvIHRoYXQgdGhlIHBsYXRmb3JtIGRldmVsb3BlciBjYW4gbW9kaWZ5IGl0LlxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXR1cm5zIHRoZSBJbnRlcm9wLUJyb2tlci1kZWZpbmVkIGNvbnRleHQgZ3JvdXBzIGF2YWlsYWJsZSBmb3IgYW4gZW50aXR5IHRvIGpvaW4uIEJlY2F1c2UgdGhpcyBmdW5jdGlvbiBpcyB1c2VkIGluIHRoZSByZXN0IG9mIHRoZSBJbnRlcm9wIEJyb2tlciB0byBmZXRjaCB0aGUgQ29udGV4dCBHcm91cHMsIG92ZXJyaWRpbmcgdGhpcyBhbGxvd3MgeW91IHRvIGN1c3RvbWl6ZSB0aGUgQ29udGV4dCBHcm91cHMgZm9yIHRoZSBJbnRlcm9wIEJyb2tlci4gSG93ZXZlciwgd2UgcmVjb21tZW5kIGN1c3RvbWl6aW5nIHRoZSBjb250ZXh0IGdyb3VwcyB0aHJvdWdoIGNvbmZpZ3VyYXRpb24gaW5zdGVhZC5cblx0ICAgICAqIFVzZWQgYnkgUGxhdGZvcm0gV2luZG93cy5cblx0ICAgICAqXG5cdCAgICAgKi9cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBnZXRDb250ZXh0R3JvdXBzKCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWJyb2tlci1nZXQtY29udGV4dC1ncm91cHMnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICAvLyBDcmVhdGUgY29weSBmb3IgaW1tdXRhYmlsaXR5XG5cdCAgICAgICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BCcm9rZXJfY29udGV4dEdyb3VwcywgXCJmXCIpLm1hcCgoY29udGV4dEdyb3VwKSA9PiB7XG5cdCAgICAgICAgICAgIHJldHVybiB7IC4uLmNvbnRleHRHcm91cCB9O1xuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgLy8gVXNlZCB0byBieSBwbGF0Zm9ybSB3aW5kb3dzIHRvIGdldCBkaXNwbGF5IG1ldGFkYXRhIGZvciBhIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAvKipcblx0ICAgICAqIEdldHMgZGlzcGxheSBpbmZvIGZvciBhIGNvbnRleHQgZ3JvdXBcblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBVc2VkIGJ5IFBsYXRmb3JtIFdpbmRvd3MuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGdldEluZm9Gb3JDb250ZXh0R3JvdXBPcHRpb25zIC0gQ29udGFpbnMgY29udGV4dEdyb3VwSWQsIHRoZSBjb250ZXh0IGdyb3VwIHlvdSB3aXNoIHRvIGdldCBkaXNwbGF5IGluZm8gZm9yLlxuXHQgICAgICpcblx0ICAgICAqL1xuXHQgICAgZ2V0SW5mb0ZvckNvbnRleHRHcm91cCh7IGNvbnRleHRHcm91cElkIH0pIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItZ2V0LWluZm8tZm9yLWNvbnRleHQtZ3JvdXAnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gdGhpcy5nZXRDb250ZXh0R3JvdXBzKCkuZmluZCgoY29udGV4dEdyb3VwKSA9PiBjb250ZXh0R3JvdXAuaWQgPT09IGNvbnRleHRHcm91cElkKTtcblx0ICAgIH1cblx0ICAgIC8vIFVzZWQgYnkgcGxhdGZvcm0gd2luZG93cyB0byBnZXQgYWxsIGNsaWVudHMgZm9yIGEgY29udGV4dCBncm91cC5cblx0ICAgIC8qKlxuXHQgICAgICogR2V0cyBhbGwgY2xpZW50cyBmb3IgYSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzICoqVGhpcyBpcyBwcmltYXJpbHkgdXNlZCBmb3IgcGxhdGZvcm0gd2luZG93cy4gVmlld3Mgd2l0aGluIGEgcGxhdGZvcm0gc2hvdWxkIG5vdCBoYXZlIHRvIHVzZSB0aGlzIEFQSS4qKlxuXHQgICAgICogUmV0dXJucyB0aGUgSW50ZXJvcC1Ccm9rZXItZGVmaW5lZCBjb250ZXh0IGdyb3VwcyBhdmFpbGFibGUgZm9yIGFuIGVudGl0eSB0byBqb2luLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBnZXRBbGxDbGllbnRzSW5Db250ZXh0R3JvdXBPcHRpb25zIC0gQ29udGFpbnMgY29udGV4dEdyb3VwSWQsIHRoZSBjb250ZXh0IGdyb3VwIHlvdSB3aXNoIHRvIGdldCBjbGllbnRzIGZvci5cblx0ICAgICAqXG5cdCAgICAgKi9cblx0ICAgIGdldEFsbENsaWVudHNJbkNvbnRleHRHcm91cCh7IGNvbnRleHRHcm91cElkIH0pIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItZ2V0LWFsbC1jbGllbnRzLWluLWNvbnRleHQtZ3JvdXAnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnRzSW5Db250ZXh0R3JvdXAgPSBBcnJheS5mcm9tKHRoaXMuaW50ZXJvcENsaWVudHMudmFsdWVzKCkpXG5cdCAgICAgICAgICAgIC5maWx0ZXIoKGNvbm5lY3RlZENsaWVudCkgPT4gY29ubmVjdGVkQ2xpZW50LmNvbnRleHRHcm91cElkID09PSBjb250ZXh0R3JvdXBJZClcblx0ICAgICAgICAgICAgLm1hcCgoc3Vic2NyaXB0aW9uU3RhdGUpID0+IHtcblx0ICAgICAgICAgICAgcmV0dXJuIHN1YnNjcmlwdGlvblN0YXRlLmNsaWVudElkZW50aXR5O1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiBjbGllbnRzSW5Db250ZXh0R3JvdXA7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlc3BvbnNpYmxlIGZvciBsYXVuY2hpbmcgb2YgYXBwbGljYXRpb25zIHRoYXQgY2FuIGhhbmRsZSBhIGdpdmVuIGludGVudCwgYW5kIGRlbGVnYXRpb24gb2YgaW50ZW50cyB0byB0aG9zZSBhcHBsaWNhdGlvbnMuXG5cdCAgICAgKiBNdXN0IGJlIG92ZXJyaWRkZW4uXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgVG8gbWFrZSB0aGlzIGNhbGwgRkRDMy1Db21wbGlhbnQgaXQgd291bGQgbmVlZCB0byByZXR1cm4gYW4gSW50ZW50UmVzb2x1dGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogaW50ZXJmYWNlIEludGVudFJlc29sdXRpb24ge1xuXHQgICAgICogICBzb3VyY2U6IFRhcmdldEFwcDtcblx0ICAgICAqICAgLy8gZGVwcmVjYXRlZCwgbm90IGFzc2lnbmFibGUgZnJvbSBpbnRlbnQgbGlzdGVuZXJzXG5cdCAgICAgKiAgIGRhdGE/OiBvYmplY3Q7XG5cdCAgICAgKiAgIHZlcnNpb246IHN0cmluZztcblx0ICAgICAqIH1cblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqIE1vcmUgaW5mb3JtYXRpb24gb24gdGhlIEludGVudFJlc29sdXRpb24gdHlwZSBjYW4gYmUgZm91bmQgaW4gdGhlIFtGREMzIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vZmRjMy5maW5vcy5vcmcvZG9jcy9hcGkvcmVmL0ludGVudFJlc29sdXRpb24pLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBpbnRlbnQgVGhlIGNvbWJpbmF0aW9uIG9mIGFuIGFjdGlvbiBhbmQgYSBjb250ZXh0IHRoYXQgaXMgcGFzc2VkIHRvIGFuIGFwcGxpY2F0aW9uIGZvciByZXNvbHV0aW9uLlxuXHQgICAgICogQHBhcmFtICBjbGllbnRJZGVudGl0eSBJZGVudGl0eSBvZiB0aGUgQ2xpZW50IG1ha2luZyB0aGUgcmVxdWVzdC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIC8vIG92ZXJyaWRlIGNhbGwgc28gd2Ugc2V0IGludGVudCB0YXJnZXQgYW5kIGNyZWF0ZSB2aWV3IHRoYXQgd2lsbCBoYW5kbGUgaXRcblx0ICAgICAqIGZpbi5QbGF0Zm9ybS5pbml0KHtcblx0ICAgICAqICAgICBpbnRlcm9wT3ZlcnJpZGU6IGFzeW5jIChJbnRlcm9wQnJva2VyKSA9PiB7XG5cdCAgICAgKiAgICAgICAgIGNsYXNzIE92ZXJyaWRlIGV4dGVuZHMgSW50ZXJvcEJyb2tlciB7XG5cdCAgICAgKiAgICAgICAgICAgICBhc3luYyBoYW5kbGVGaXJlZEludGVudChpbnRlbnQpIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICBzdXBlci5zZXRJbnRlbnRUYXJnZXQoaW50ZW50LCB7IHV1aWQ6ICdwbGF0Zm9ybS11dWlkJywgbmFtZTogJ2ludGVudC12aWV3JyB9KTtcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuXHQgICAgICogICAgICAgICAgICAgICAgIGNvbnN0IHdpbiA9IGZpbi5XaW5kb3cud3JhcFN5bmMoeyBuYW1lOiAnZm9vJywgdXVpZDogJ3BsYXRmb3JtLXV1aWQnIH0pO1xuXHQgICAgICogICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRWaWV3ID0gYXdhaXQgcGxhdGZvcm0uY3JlYXRlVmlldyh7IHVybDogJ2h0dHA6Ly9vcGVuZmluLmNvJywgbmFtZTogJ2ludGVudC12aWV3JyB9LCB3aW4uaWRlbnRpdHkpO1xuXHQgICAgICogICAgICAgICAgICAgfVxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIHJldHVybiBuZXcgT3ZlcnJpZGUoKTtcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuXHQgICAgYXN5bmMgaGFuZGxlRmlyZWRJbnRlbnQoaW50ZW50LCBjbGllbnRJZGVudGl0eSAvLyBUT0RPKENPUkUtODExKTogcmVtb3ZlIGlubGluZSBpbnRlcnNlY3RlZCB0eXBlXG5cdCAgICApIHtcblx0ICAgICAgICBjb25zdCB3YXJuaW5nID0gKDAsIHV0aWxzXzEuZ2VuZXJhdGVPdmVycmlkZVdhcm5pbmcpKCdmZGMzLnJhaXNlSW50ZW50JywgJ0ludGVyb3BCcm9rZXIuaGFuZGxlRmlyZWRJbnRlbnQnLCBjbGllbnRJZGVudGl0eSwgJ2ludGVyb3BDbGllbnQuZmlyZUludGVudCcpO1xuXHQgICAgICAgIGNvbnNvbGUud2Fybih3YXJuaW5nKTtcblx0ICAgICAgICB0aHJvdyBuZXcgRXJyb3IodXRpbHNfMS5CUk9LRVJfRVJST1JTLmZpcmVJbnRlbnQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTaG91bGQgYmUgY2FsbGVkIGluIHtAbGluayBJbnRlcm9wQnJva2VyI2hhbmRsZUZpcmVkSW50ZW50IEludGVyb3BCcm9rZXIuaGFuZGxlRmlyZWRJbnRlbnR9LlxuXHQgICAgICogV2hpbGUgaGFuZGxlRmlyZWRJbnRlbnQgaXMgcmVzcG9uc2libGUgZm9yIGxhdW5jaGluZyBhcHBsaWNhdGlvbnMsIHNldEludGVudFRhcmdldCBpcyB1c2VkIHRvIHRlbGwgdGhlIEludGVyb3BCcm9rZXIgd2hpY2ggYXBwbGljYXRpb24gc2hvdWxkIHJlY2VpdmUgdGhlIGludGVudCB3aGVuIGl0IGlzIHJlYWR5LlxuXHQgICAgICogQHBhcmFtIGludGVudCBUaGUgY29tYmluYXRpb24gb2YgYW4gYWN0aW9uIGFuZCBhIGNvbnRleHQgdGhhdCBpcyBwYXNzZWQgdG8gYW4gYXBwbGljYXRpb24gZm9yIHJlc29sdXRpb24uXG5cdCAgICAgKiBAcGFyYW0gdGFyZ2V0IC0gSWRlbnRpdHkgb2YgdGhlIHRhcmdldCB0aGF0IHdpbGwgaGFuZGxlIHRoZSBpbnRlbnQuXG5cdCAgICAgKlxuXHQgICAgICovXG5cdCAgICBhc3luYyBzZXRJbnRlbnRUYXJnZXQoaW50ZW50LCB0YXJnZXQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItc2V0LWludGVudC10YXJnZXQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIHRoaXMgaXMgb25seSBmb3IgYXBpIGFuYWx5dGljcyBwdXJwb3Nlc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IHRhcmdldEluZm8gPSB0aGlzLmludGVudENsaWVudE1hcC5nZXQodGFyZ2V0Lm5hbWUpO1xuXHQgICAgICAgIGNvbnN0IGhhbmRsZXJJZCA9IGBpbnRlbnQtaGFuZGxlci0ke2ludGVudC5uYW1lfWA7XG5cdCAgICAgICAgaWYgKCF0YXJnZXRJbmZvKSB7XG5cdCAgICAgICAgICAgIHRoaXMuaW50ZW50Q2xpZW50TWFwLnNldCh0YXJnZXQubmFtZSwgbmV3IE1hcCgpKTtcblx0ICAgICAgICAgICAgY29uc3QgbmV3SGFuZGxlckluZm9NYXAgPSB0aGlzLmludGVudENsaWVudE1hcC5nZXQodGFyZ2V0Lm5hbWUpO1xuXHQgICAgICAgICAgICBpZiAobmV3SGFuZGxlckluZm9NYXApIHtcblx0ICAgICAgICAgICAgICAgIG5ld0hhbmRsZXJJbmZvTWFwLnNldChoYW5kbGVySWQsIHsgaXNSZWFkeTogZmFsc2UsIHBlbmRpbmdJbnRlbnRzOiBbaW50ZW50XSB9KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgY29uc3QgaGFuZGxlckluZm8gPSB0YXJnZXRJbmZvLmdldChoYW5kbGVySWQpO1xuXHQgICAgICAgICAgICBpZiAoIWhhbmRsZXJJbmZvKSB7XG5cdCAgICAgICAgICAgICAgICB0YXJnZXRJbmZvLnNldChoYW5kbGVySWQsIHsgaXNSZWFkeTogZmFsc2UsIHBlbmRpbmdJbnRlbnRzOiBbaW50ZW50XSB9KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgICAgIGhhbmRsZXJJbmZvLnBlbmRpbmdJbnRlbnRzLnB1c2goaW50ZW50KTtcblx0ICAgICAgICAgICAgICAgIGlmIChoYW5kbGVySW5mby5jbGllbnRJZGVudGl0eSAmJiBoYW5kbGVySW5mby5pc1JlYWR5KSB7XG5cdCAgICAgICAgICAgICAgICAgICAgY29uc3QgeyBjbGllbnRJZGVudGl0eSwgcGVuZGluZ0ludGVudHMgfSA9IGhhbmRsZXJJbmZvO1xuXHQgICAgICAgICAgICAgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGludGVudFRvU2VuZCA9IHBlbmRpbmdJbnRlbnRzW3BlbmRpbmdJbnRlbnRzLmxlbmd0aCAtIDFdO1xuXHQgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmludm9rZUludGVudEhhbmRsZXIoY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwgaW50ZW50VG9TZW5kKTtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlckluZm8ucGVuZGluZ0ludGVudHMgPSBbXTtcblx0ICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGludm9raW5nIGludGVudCBoYW5kbGVyIGZvciBjbGllbnQgJHtjbGllbnRJZGVudGl0eS51dWlkfS8ke2NsaWVudElkZW50aXR5Lm5hbWV9LyR7Y2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZH1gKTtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlckluZm8uaXNSZWFkeSA9IGZhbHNlO1xuXHQgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVzcG9uc2libGUgZm9yIHJldHVybmluZyBpbmZvcm1hdGlvbiBvbiBhIHBhcnRpY3VsYXIgSW50ZW50LlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFdoZW5ldmVyIEludGVyb3BDbGllbnQuZ2V0SW5mb0ZvckludGVudCBpcyBjYWxsZWQgdGhpcyBmdW5jdGlvbiB3aWxsIGZpcmUuIFRoZSBvcHRpb25zIGFyZ3VtZW50IGdpdmVzIHlvdVxuXHQgICAgICogYWNjZXNzIHRvIHRoZSBpbnRlbnQgbmFtZSBhbmQgYW55IG9wdGlvbmFsIGNvbnRleHQgdGhhdCB3YXMgcGFzc2VkIGFuZCBjbGllbnRJZGVudGl0eSBpcyB0aGUgaWRlbnRpdHkgb2YgdGhlIGNsaWVudFxuXHQgICAgICogdGhhdCBtYWRlIHRoZSBjYWxsLiBJZGVhbGx5IGhlcmUgeW91IHdvdWxkIGZldGNoIHRoZSBpbmZvIGZvciB0aGUgaW50ZW50IGFuZCByZXR1cm4gaXQgd2l0aCB0aGUgc2hhcGUgdGhhdCB0aGVcblx0ICAgICAqIEludGVyb3BDbGllbnQuZ2V0SW5mb0ZvckludGVudCBjYWxsIGlzIGV4cGVjdGluZy5cblx0ICAgICAqXG5cdCAgICAgKiBUbyBtYWtlIHRoaXMgY2FsbCBGREMzLUNvbXBsaWFudCBpdCB3b3VsZCBuZWVkIHRvIHJldHVybiBhbiBBcHAgSW50ZW50OlxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiAvLyB7XG5cdCAgICAgKiAvLyAgICAgaW50ZW50OiB7IG5hbWU6IFwiU3RhcnRDaGF0XCIsIGRpc3BsYXlOYW1lOiBcIkNoYXRcIiB9LFxuXHQgICAgICogLy8gICAgIGFwcHM6IFt7IG5hbWU6IFwiU2t5cGVcIiB9LCB7IG5hbWU6IFwiU3ltcGhvbnlcIiB9LCB7IG5hbWU6IFwiU2xhY2tcIiB9XVxuXHQgICAgICogLy8gfVxuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICogTW9yZSBpbmZvcm1hdGlvbiBvbiB0aGUgQXBwSW50ZW50IHR5cGUgY2FuIGJlIGZvdW5kIGluIHRoZSBbRkRDMyBkb2N1bWVudGF0aW9uXShodHRwczovL2ZkYzMuZmlub3Mub3JnL2RvY3MvYXBpL3JlZi9BcHBJbnRlbnQpLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBvcHRpb25zXG5cdCAgICAgKiBAcGFyYW0gY2xpZW50SWRlbnRpdHkgSWRlbnRpdHkgb2YgdGhlIENsaWVudCBtYWtpbmcgdGhlIHJlcXVlc3QuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBmaW4uUGxhdGZvcm0uaW5pdCh7XG5cdCAgICAgKiAgICAgaW50ZXJvcE92ZXJyaWRlOiBhc3luYyAoSW50ZXJvcEJyb2tlcikgPT4ge1xuXHQgICAgICogICAgICAgICBjbGFzcyBPdmVycmlkZSBleHRlbmRzIEludGVyb3BCcm9rZXIge1xuXHQgICAgICogICAgICAgICAgICAgYXN5bmMgaGFuZGxlSW5mb0ZvckludGVudChvcHRpb25zLCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICogICAgICAgICAgICAgICAgIC8vIFlvdXIgY29kZSBnb2VzIGhlcmUuXG5cdCAgICAgKiAgICAgICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgcmV0dXJuIG5ldyBPdmVycmlkZSgpO1xuXHQgICAgICogICAgIH1cblx0ICAgICAqIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBhc3luYyBoYW5kbGVJbmZvRm9ySW50ZW50KG9wdGlvbnMsIGNsaWVudElkZW50aXR5IC8vIFRPRE8oQ09SRS04MTEpOiByZW1vdmUgaW5saW5lIGludGVyc2VjdGVkIHR5cGVcblx0ICAgICkge1xuXHQgICAgICAgIGNvbnN0IHdhcm5pbmcgPSAoMCwgdXRpbHNfMS5nZW5lcmF0ZU92ZXJyaWRlV2FybmluZykoJ2ZkYzMuZmluZEludGVudCcsICdJbnRlcm9wQnJva2VyLmhhbmRsZUluZm9Gb3JJbnRlbnQnLCBjbGllbnRJZGVudGl0eSwgJ2ludGVyb3BDbGllbnQuZ2V0SW5mb0ZvckludGVudCcpO1xuXHQgICAgICAgIGNvbnNvbGUud2Fybih3YXJuaW5nKTtcblx0ICAgICAgICB0aHJvdyBuZXcgRXJyb3IodXRpbHNfMS5CUk9LRVJfRVJST1JTLmdldEluZm9Gb3JJbnRlbnQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXNwb25zaWJsZSBmb3IgcmV0dXJuaW5nIGluZm9ybWF0aW9uIG9uIHdoaWNoIEludGVudHMgYXJlIG1lYW50IHRvIGhhbmRsZSBhIHNwZWNpZmljIENvbnRleHQuXG5cdCAgICAgKiBNdXN0IGJlIG92ZXJyaWRkZW4uXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgUmVzcG9uc2libGUgZm9yIHJldHVybmluZyBpbmZvcm1hdGlvbiBvbiB3aGljaCBJbnRlbnRzIGFyZSBtZWFudCB0byBoYW5kbGUgYSBzcGVjaWZpYyBDb250ZXh0LiBNdXN0IGJlIG92ZXJyaWRkZW4uXG5cdCAgICAgKlxuXHQgICAgICogV2hlbmV2ZXIgSW50ZXJvcENsaWVudC5nZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dCBpcyBjYWxsZWQgdGhpcyBmdW5jdGlvbiB3aWxsIGZpcmUuIFRoZSBjb250ZXh0IGFyZ3VtZW50IGdpdmVzIHlvdSBhY2Nlc3MgdG8gdGhlIGNvbnRleHQgdGhhdCB0aGUgY2xpZW50IHdhbnRzIGluZm9ybWF0aW9uIG9uIGFuZCBjbGllbnRJZGVudGl0eSBpcyB0aGUgaWRlbnRpdHkgb2YgdGhlIGNsaWVudCB0aGF0IG1hZGUgdGhlIGNhbGwuIElkZWFsbHkgaGVyZSB5b3Ugd291bGQgZmV0Y2ggdGhlIGluZm8gZm9yIGFueSBpbnRlbnQgdGhhdCBjYW4gaGFuZGxlIGFuZCByZXR1cm4gaXQgd2l0aCB0aGUgc2hhcGUgdGhhdCB0aGUgSW50ZXJvcENsaWVudC5nZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dCBjYWxsIGlzIGV4cGVjdGluZy5cblx0ICAgICAqXG5cdCAgICAgKiBUbyBtYWtlIHRoaXMgY2FsbCBGREMzLUNvbXBsaWFudCBpdCB3b3VsZCBuZWVkIHRvIHJldHVybiBhbiBhcnJheSBvZiBBcHBJbnRlbnRzOlxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiAvLyBbe1xuXHQgICAgICogLy8gICAgIGludGVudDogeyBuYW1lOiBcIlN0YXJ0Q2FsbFwiLCBkaXNwbGF5TmFtZTogXCJDYWxsXCIgfSxcblx0ICAgICAqIC8vICAgICBhcHBzOiBbeyBuYW1lOiBcIlNreXBlXCIgfV1cblx0ICAgICAqIC8vIH0sXG5cdCAgICAgKiAvLyB7XG5cdCAgICAgKiAvLyAgICAgaW50ZW50OiB7IG5hbWU6IFwiU3RhcnRDaGF0XCIsIGRpc3BsYXlOYW1lOiBcIkNoYXRcIiB9LFxuXHQgICAgICogLy8gICAgIGFwcHM6IFt7IG5hbWU6IFwiU2t5cGVcIiB9LCB7IG5hbWU6IFwiU3ltcGhvbnlcIiB9LCB7IG5hbWU6IFwiU2xhY2tcIiB9XVxuXHQgICAgICogLy8gfV07XG5cdCAgICAgKiBgYGBcblx0ICAgICAqXG5cdCAgICAgKiBNb3JlIGluZm9ybWF0aW9uIG9uIHRoZSBBcHBJbnRlbnQgdHlwZSBjYW4gYmUgZm91bmQgaW4gdGhlIFtGREMzIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vZmRjMy5maW5vcy5vcmcvZG9jcy9hcGkvcmVmL0FwcEludGVudCkuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGNvbnRleHQgRGF0YSBwYXNzZWQgYmV0d2VlbiBlbnRpdGllcyBhbmQgYXBwbGljYXRpb25zLlxuXHQgICAgICogQHBhcmFtIGNsaWVudElkZW50aXR5IElkZW50aXR5IG9mIHRoZSBDbGllbnQgbWFraW5nIHRoZSByZXF1ZXN0LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLlBsYXRmb3JtLmluaXQoe1xuXHQgICAgICogICAgIGludGVyb3BPdmVycmlkZTogYXN5bmMgKEludGVyb3BCcm9rZXIpID0+IHtcblx0ICAgICAqICAgICAgICAgY2xhc3MgT3ZlcnJpZGUgZXh0ZW5kcyBJbnRlcm9wQnJva2VyIHtcblx0ICAgICAqICAgICAgICAgICAgIGFzeW5jIGhhbmRsZUluZm9Gb3JJbnRlbnRzQnlDb250ZXh0KGNvbnRleHQsIGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgLy8gWW91ciBjb2RlIGdvZXMgaGVyZS5cblx0ICAgICAqICAgICAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgfVxuXHQgICAgICogICAgICAgICByZXR1cm4gbmV3IE92ZXJyaWRlKCk7XG5cdCAgICAgKiAgICAgfVxuXHQgICAgICogfSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcblx0ICAgIGFzeW5jIGhhbmRsZUluZm9Gb3JJbnRlbnRzQnlDb250ZXh0KGNvbnRleHQsIGNsaWVudElkZW50aXR5IC8vIFRPRE8oQ09SRS04MTEpOiByZW1vdmUgaW5saW5lIGludGVyc2VjdGVkIHR5cGVcblx0ICAgICkge1xuXHQgICAgICAgIGNvbnN0IHdhcm5pbmcgPSAoMCwgdXRpbHNfMS5nZW5lcmF0ZU92ZXJyaWRlV2FybmluZykoJ2ZkYzMuZmluZEludGVudHNCeUNvbnRleHQnLCAnSW50ZXJvcEJyb2tlci5oYW5kbGVJbmZvRm9ySW50ZW50c0J5Q29udGV4dCcsIGNsaWVudElkZW50aXR5LCAnaW50ZXJvcENsaWVudC5nZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dCcpO1xuXHQgICAgICAgIGNvbnNvbGUud2Fybih3YXJuaW5nKTtcblx0ICAgICAgICB0aHJvdyBuZXcgRXJyb3IodXRpbHNfMS5CUk9LRVJfRVJST1JTLmdldEluZm9Gb3JJbnRlbnRzQnlDb250ZXh0KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVzcG9uc2libGUgZm9yIHJlc29sdmluZyBhbiBJbnRlbnQgYmFzZWQgb24gYSBzcGVjaWZpYyBDb250ZXh0LlxuXHQgICAgICogTXVzdCBiZSBvdmVycmlkZGVuLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFdoZW5ldmVyIEludGVyb3BDbGllbnQuZmlyZUludGVudEZvckNvbnRleHQgaXMgY2FsbGVkIHRoaXMgZnVuY3Rpb24gd2lsbCBmaXJlLiBUaGUgY29udGV4dEZvckludGVudCBhcmd1bWVudFxuXHQgICAgICogZ2l2ZXMgeW91IGFjY2VzcyB0byB0aGUgY29udGV4dCB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgdG8gYW4gaW50ZW50LiBJdCBhbHNvIGNhbiBvcHRpb25hbGx5IGNvbnRhaW4gYW55IG1ldGFkYXRhIHJlbGV2YW50XG5cdCAgICAgKiB0byByZXNvbHZpbmcgaXQsIGxpa2UgYSBzcGVjaWZpYyBhcHAgdGhlIGNsaWVudCB3YW50cyB0aGUgY29udGV4dCB0byBiZSBoYW5kbGVkIGJ5LiBUaGUgY2xpZW50SWRlbnRpdHkgaXMgdGhlIGlkZW50aXR5XG5cdCAgICAgKiBvZiB0aGUgY2xpZW50IHRoYXQgbWFkZSB0aGUgY2FsbC5cblx0ICAgICAqXG5cdCAgICAgKiBUbyBtYWtlIHRoaXMgY2FsbCBGREMzLUNvbXBsaWFudCBpdCB3b3VsZCBuZWVkIHRvIHJldHVybiBhbiBJbnRlbnRSZXNvbHV0aW9uOlxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiAvLyB7XG5cdCAgICAgKiAvLyAgICAgaW50ZW50OiB7IG5hbWU6IFwiU3RhcnRDaGF0XCIsIGRpc3BsYXlOYW1lOiBcIkNoYXRcIiB9LFxuXHQgICAgICogLy8gICAgIGFwcHM6IFt7IG5hbWU6IFwiU2t5cGVcIiB9LCB7IG5hbWU6IFwiU3ltcGhvbnlcIiB9LCB7IG5hbWU6IFwiU2xhY2tcIiB9XVxuXHQgICAgICogLy8gfVxuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICogTW9yZSBpbmZvcm1hdGlvbiBvbiB0aGUgSW50ZW50UmVzb2x1dGlvbiB0eXBlIGNhbiBiZSBmb3VuZCBpbiB0aGUgW0ZEQzMgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9mZGMzLmZpbm9zLm9yZy9kb2NzL2FwaS9yZWYvTWV0YWRhdGEjaW50ZW50cmVzb2x1dGlvbikuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRGb3JJbnRlbnQgRGF0YSBwYXNzZWQgYmV0d2VlbiBlbnRpdGllcyBhbmQgYXBwbGljYXRpb25zLlxuXHQgICAgICogQHBhcmFtIGNsaWVudElkZW50aXR5IElkZW50aXR5IG9mIHRoZSBDbGllbnQgbWFraW5nIHRoZSByZXF1ZXN0LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLlBsYXRmb3JtLmluaXQoe1xuXHQgICAgICogICAgIGludGVyb3BPdmVycmlkZTogYXN5bmMgKEludGVyb3BCcm9rZXIpID0+IHtcblx0ICAgICAqICAgICAgICAgY2xhc3MgT3ZlcnJpZGUgZXh0ZW5kcyBJbnRlcm9wQnJva2VyIHtcblx0ICAgICAqICAgICAgICAgICAgIGFzeW5jIGhhbmRsZUZpcmVkSW50ZW50Rm9yQ29udGV4dChjb250ZXh0Rm9ySW50ZW50LCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICogICAgICAgICAgICAgICAgIC8vIFlvdXIgY29kZSBnb2VzIGhlcmUuXG5cdCAgICAgKiAgICAgICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgcmV0dXJuIG5ldyBPdmVycmlkZSgpO1xuXHQgICAgICogICAgIH1cblx0ICAgICAqIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBhc3luYyBoYW5kbGVGaXJlZEludGVudEZvckNvbnRleHQoY29udGV4dEZvckludGVudCwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCB3YXJuaW5nID0gKDAsIHV0aWxzXzEuZ2VuZXJhdGVPdmVycmlkZVdhcm5pbmcpKCdmZGMzLnJhaXNlSW50ZW50Rm9yQ29udGV4dCcsICdJbnRlcm9wQnJva2VyLmhhbmRsZUZpcmVkSW50ZW50Rm9yQ29udGV4dCcsIGNsaWVudElkZW50aXR5LCAnaW50ZXJvcENsaWVudC5maXJlSW50ZW50Rm9yQ29udGV4dCcpO1xuXHQgICAgICAgIGNvbnNvbGUud2Fybih3YXJuaW5nKTtcblx0ICAgICAgICB0aHJvdyBuZXcgRXJyb3IodXRpbHNfMS5CUk9LRVJfRVJST1JTLmZpcmVJbnRlbnRGb3JDb250ZXh0KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUHJvdmlkZXMgdGhlIGlkZW50aXR5IG9mIGFueSBJbnRlcm9wIENsaWVudCB0aGF0IGRpc2Nvbm5lY3RzIGZyb20gdGhlIEludGVyb3AgQnJva2VyLiBJdCBpcyBtZWFudCB0byBiZSBvdmVycmlkZW4uXG5cdCAgICAgKiBAcGFyYW0gY2xpZW50SWRlbnRpdHlcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5QbGF0Zm9ybS5pbml0KHtcblx0ICAgICAqICAgICBpbnRlcm9wT3ZlcnJpZGU6IGFzeW5jIChJbnRlcm9wQnJva2VyKSA9PiB7XG5cdCAgICAgKiAgICAgICAgIGNsYXNzIE92ZXJyaWRlIGV4dGVuZHMgSW50ZXJvcEJyb2tlciB7XG5cdCAgICAgKiAgICAgICAgICAgICBhc3luYyBjbGllbnREaXNjb25uZWN0ZWQoY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IGNsaWVudElkZW50aXR5O1xuXHQgICAgICogICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBDbGllbnQgd2l0aCBpZGVudGl0eSAke3V1aWR9LyR7bmFtZX0gaGFzIGJlZW4gZGlzY29ubmVjdGVkYCk7XG5cdCAgICAgKiAgICAgICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgcmV0dXJuIG5ldyBPdmVycmlkZSgpO1xuXHQgICAgICogICAgIH1cblx0ICAgICAqIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBhc3luYyBjbGllbnREaXNjb25uZWN0ZWQoY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICAvLyBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBpbiBjaGFubmVsLm9uRGlzY29ubmVjdGlvbi5cblx0ICAgICAgICAvLyBJdCBpcyBtZWFudCB0byBiZSBvdmVycmlkZGVuIHRvIGluZm9ybSB3aGVuIGFuIEludGVyb3AgQ2xpZW50IGhhcyBiZWVuIGRpc2Nvbm5lY3RlZC5cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVzcG9uc2libGUgZm9yIHJlc29sdmluZyBhbiBmZGMzLm9wZW4gY2FsbC5cblx0ICAgICAqIE11c3QgYmUgb3ZlcnJpZGRlbi5cblx0ICAgICAqIEBwYXJhbSBmZGMzT3Blbk9wdGlvbnMgZmRjMy5vcGVuIG9wdGlvbnNcblx0ICAgICAqIEBwYXJhbSBjbGllbnRJZGVudGl0eSBJZGVudGl0eSBvZiB0aGUgQ2xpZW50IG1ha2luZyB0aGUgcmVxdWVzdC5cblx0ICAgICAqL1xuXHQgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcblx0ICAgIGFzeW5jIGZkYzNIYW5kbGVPcGVuKHsgYXBwLCBjb250ZXh0IH0sIGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgY29uc3Qgd2FybmluZyA9ICgwLCB1dGlsc18xLmdlbmVyYXRlT3ZlcnJpZGVXYXJuaW5nKSgnZmRjMy5vcGVuJywgJ0ludGVyb3BCcm9rZXIuZmRjM0hhbmRsZU9wZW4nLCBjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgY29uc29sZS53YXJuKHdhcm5pbmcpO1xuXHQgICAgICAgIHRocm93IG5ldyBFcnJvcih1dGlsc18xLkJST0tFUl9FUlJPUlMuZmRjM09wZW4pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXNwb25zaWJsZSBmb3IgcmVzb2x2aW5nIHRoZSBmZGMzLmZpbmRJbnN0YW5jZXMgY2FsbC5cblx0ICAgICAqIE11c3QgYmUgb3ZlcnJpZGRlblxuXHQgICAgICogQHBhcmFtIGFwcCBBcHBJZGVudGlmaWVyIHRoYXQgd2FzIHBhc3NlZCB0byBmZGMzLmZpbmRJbnN0YW5jZXNcblx0ICAgICAqIEBwYXJhbSBjbGllbnRJZGVudGl0eSBJZGVudGl0eSBvZiB0aGUgQ2xpZW50IG1ha2luZyB0aGUgcmVxdWVzdC5cblx0ICAgICAqL1xuXHQgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcblx0ICAgIGFzeW5jIGZkYzNIYW5kbGVGaW5kSW5zdGFuY2VzKGFwcCwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCB3YXJuaW5nID0gKDAsIHV0aWxzXzEuZ2VuZXJhdGVPdmVycmlkZVdhcm5pbmcpKCdmZGMzLm9wZW4nLCAnSW50ZXJvcEJyb2tlci5mZGMzSGFuZGxlRmluZEluc3RhbmNlcycsIGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICBjb25zb2xlLndhcm4od2FybmluZyk7XG5cdCAgICAgICAgdGhyb3cgbmV3IEVycm9yKHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5mZGMzRmluZEluc3RhbmNlcyk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlc3BvbnNpYmxlIGZvciByZXNvbHZpbmcgdGhlIGZkYzMuZ2V0QXBwTWV0YWRhdGEgY2FsbC5cblx0ICAgICAqIE11c3QgYmUgb3ZlcnJpZGRlblxuXHQgICAgICogQHBhcmFtIGFwcCBBcHBJZGVudGlmaWVyIHRoYXQgd2FzIHBhc3NlZCB0byBmZGMzLmdldEFwcE1ldGFkYXRhXG5cdCAgICAgKiBAcGFyYW0gY2xpZW50SWRlbnRpdHkgSWRlbnRpdHkgb2YgdGhlIENsaWVudCBtYWtpbmcgdGhlIHJlcXVlc3QuXG5cdCAgICAgKi9cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBhc3luYyBmZGMzSGFuZGxlR2V0QXBwTWV0YWRhdGEoYXBwLCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IHdhcm5pbmcgPSAoMCwgdXRpbHNfMS5nZW5lcmF0ZU92ZXJyaWRlV2FybmluZykoJ2ZkYzMuZ2V0QXBwTWV0YWRhdGEnLCAnSW50ZXJvcEJyb2tlci5mZGMzSGFuZGxlR2V0QXBwTWV0YWRhdGEnLCBjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgY29uc29sZS53YXJuKHdhcm5pbmcpO1xuXHQgICAgICAgIHRocm93IG5ldyBFcnJvcih1dGlsc18xLkJST0tFUl9FUlJPUlMuZmRjM0dldEFwcE1ldGFkYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYnkgdGhlIEludGVyb3AgQnJva2VyIHdoZW5ldmVyIGEgQ29udGV4dCBoYW5kbGVyIHdvdWxkIGZpcmUuXG5cdCAgICAgKiBGb3IgRkRDMyAyLjAgeW91IHdvdWxkIG5lZWQgdG8gb3ZlcnJpZGUgdGhpcyBmdW5jdGlvbiBhbmQgYWRkIHRoZSBjb250ZXh0TWV0YWRhdGEgYXNcblx0ICAgICAqIHBhcnQgb2YgdGhlIENvbnRleHQgb2JqZWN0LiBUaGVuIHdvdWxkIHlvdSBuZWVkIHRvIGNhbGxcblx0ICAgICAqIHN1cGVyLmludm9rZUNvbnRleHRIYW5kbGVyIHBhc3NpbmcgaXQgdGhpcyBuZXcgQ29udGV4dCBvYmplY3QgYWxvbmcgd2l0aCB0aGUgY2xpZW50SWRlbnRpdHkgYW5kIGhhbmRsZXJJZFxuXHQgICAgICogQHBhcmFtIGNsaWVudElkZW50aXR5XG5cdCAgICAgKiBAcGFyYW0gaGFuZGxlcklkXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dFxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLlBsYXRmb3JtLmluaXQoe1xuXHQgICAgICogICAgIGludGVyb3BPdmVycmlkZTogYXN5bmMgKEludGVyb3BCcm9rZXIpID0+IHtcblx0ICAgICAqICAgICAgICAgY2xhc3MgT3ZlcnJpZGUgZXh0ZW5kcyBJbnRlcm9wQnJva2VyIHtcblx0ICAgICAqICAgICAgICAgICAgIGFzeW5jIGludm9rZUNvbnRleHRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGNvbnRleHQpIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICByZXR1cm4gc3VwZXIuaW52b2tlQ29udGV4dEhhbmRsZXIoY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwge1xuXHQgICAgICogICAgICAgICAgICAgICAgICAgICAuLi5jb250ZXh0LFxuXHQgICAgICogICAgICAgICAgICAgICAgICAgICBjb250ZXh0TWV0YWRhdGE6IHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZToge1xuXHQgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcElkOiAnb3BlbmZpbi1hcHAnLFxuXHQgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbmNlSWQ6ICczRDU0RDQ1NkQ5SFQwJ1xuXHQgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICogICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgfSk7XG5cdCAgICAgKiAgICAgICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgcmV0dXJuIG5ldyBPdmVycmlkZSgpO1xuXHQgICAgICogICAgIH1cblx0ICAgICAqIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGludm9rZUNvbnRleHRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGNvbnRleHQpIHtcblx0ICAgICAgICBjb25zdCBwcm92aWRlciA9IGF3YWl0IHRoaXMuZ2V0UHJvdmlkZXIoKTtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICBhd2FpdCBwcm92aWRlci5kaXNwYXRjaChjbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBjb250ZXh0KTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGludm9raW5nIGNvbnRleHQgaGFuZGxlciAke2hhbmRsZXJJZH0gZm9yIGNvbnRleHQgdHlwZSAke2NvbnRleHQudHlwZX0gaW4gY2xpZW50ICR7Y2xpZW50SWRlbnRpdHkudXVpZH0vJHtjbGllbnRJZGVudGl0eS5uYW1lfS8ke2NsaWVudElkZW50aXR5LmVuZHBvaW50SWR9YCwgZXJyb3IpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYnkgdGhlIEludGVyb3AgQnJva2VyIHdoZW5ldmVyIGFuIEludGVudCBoYW5kbGVyIHdvdWxkIGZpcmUuXG5cdCAgICAgKiBGb3IgRkRDMyAyLjAgeW91IHdvdWxkIG5lZWQgdG8gb3ZlcnJpZGUgdGhpcyBmdW5jdGlvbiBhbmQgYWRkIHRoZSBjb250ZXh0TWV0YWRhdGEgYXNcblx0ICAgICAqIHBhcnQgb2YgdGhlIENvbnRleHQgb2JqZWN0IGluc2lkZSB0aGUgSW50ZW50IG9iamVjdC4gVGhlbiB3b3VsZCB5b3UgbmVlZCB0byBjYWxsXG5cdCAgICAgKiBzdXBlci5pbnZva2VJbnRlbnRIYW5kbGVyIHBhc3NpbmcgaXQgdGhpcyBuZXcgSW50ZW50IG9iamVjdCBhbG9uZyB3aXRoIHRoZSBjbGllbnRJZGVudGl0eSBhbmQgaGFuZGxlcklkXG5cdCAgICAgKiBAcGFyYW0gQ2xpZW50SWRlbnRpdHlcblx0ICAgICAqIEBwYXJhbSBoYW5kbGVySWRcblx0ICAgICAqIEBwYXJhbSBjb250ZXh0XG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBmaW4uUGxhdGZvcm0uaW5pdCh7XG5cdCAgICAgKiAgICAgaW50ZXJvcE92ZXJyaWRlOiBhc3luYyAoSW50ZXJvcEJyb2tlcikgPT4ge1xuXHQgICAgICogICAgICAgICBjbGFzcyBPdmVycmlkZSBleHRlbmRzIEludGVyb3BCcm9rZXIge1xuXHQgICAgICogICAgICAgICAgICAgYXN5bmMgaW52b2tlSW50ZW50SGFuZGxlcihjbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBjb250ZXh0KSB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgY29uc3QgeyBjb250ZXh0IH0gPSBpbnRlbnQ7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgcmV0dXJuIHN1cGVyLmludm9rZUludGVudEhhbmRsZXIoY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwge1xuXHQgICAgICogICAgICAgICAgICAgICAgICAgICAuLi5pbnRlbnQsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQ6IHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmNvbnRleHQsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0TWV0YWRhdGE6IHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwSWQ6ICdvcGVuZmluLWFwcCcsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbmNlSWQ6ICczRDU0RDQ1NkQ5SFQwJ1xuXHQgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICogICAgICAgICAgICAgICAgIH0pO1xuXHQgICAgICogICAgICAgICAgICAgfVxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIHJldHVybiBuZXcgT3ZlcnJpZGUoKTtcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBpbnZva2VJbnRlbnRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGludGVudCkge1xuXHQgICAgICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgdGhpcy5nZXRQcm92aWRlcigpO1xuXHQgICAgICAgIGF3YWl0IHByb3ZpZGVyLmRpc3BhdGNoKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGludGVudCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlc3BvbnNpYmxlIGZvciByZXNvbHZpbmcgZmRjMy5nZXRJbmZvIGZvciBGREMzIDIuMFxuXHQgICAgICogV291bGQgbmVlZCB0byByZXR1cm4gdGhlIG9wdGlvbmFsRmVhdHVyZXMgYW5kIGFwcE1ldGFkYXRhIGZvciB0aGUge0BsaW5rIGh0dHBzOi8vZmRjMy5maW5vcy5vcmcvZG9jcy9hcGkvcmVmL01ldGFkYXRhI2ltcGxlbWVudGF0aW9ubWV0YWRhdGEgSW1wbGVtZW50YXRpb25NZXRhZGF0YX0uXG5cdCAgICAgKiBNdXN0IGJlIG92ZXJyaWRkZW4uXG5cdCAgICAgKiBAcGFyYW0gY2xpZW50SWRlbnRpdHlcblx0ICAgICAqXG5cdCAgICAgKi9cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBhc3luYyBmZGMzSGFuZGxlR2V0SW5mbyhwYXlsb2FkLCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IHsgZmRjM1ZlcnNpb24gfSA9IHBheWxvYWQ7XG5cdCAgICAgICAgcmV0dXJuIHtcblx0ICAgICAgICAgICAgZmRjM1ZlcnNpb24sXG5cdCAgICAgICAgICAgIC4uLl9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BCcm9rZXJfZmRjM0luZm8sIFwiZlwiKSxcblx0ICAgICAgICAgICAgb3B0aW9uYWxGZWF0dXJlczoge1xuXHQgICAgICAgICAgICAgICAgT3JpZ2luYXRpbmdBcHBNZXRhZGF0YTogZmFsc2UsXG5cdCAgICAgICAgICAgICAgICBVc2VyQ2hhbm5lbE1lbWJlcnNoaXBBUElzOiB0cnVlXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIGFwcE1ldGFkYXRhOiB7XG5cdCAgICAgICAgICAgICAgICBhcHBJZDogJycsXG5cdCAgICAgICAgICAgICAgICBpbnN0YW5jZUlkOiAnJ1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0dXJucyBhbiBhcnJheSBvZiBpbmZvIGZvciBlYWNoIEludGVyb3AgQ2xpZW50IGNvbm5lY3RlZCB0byB0aGUgSW50ZXJvcCBCcm9rZXIuXG5cdCAgICAgKlxuXHQgICAgICogRkRDMyAyLjA6IFVzZSB0aGUgZW5kcG9pbnRJZCBpbiB0aGUgQ2xpZW50SW5mbyBhcyB0aGUgaW5zdGFuY2VJZCB3aGVuIGdlbmVyYXRpbmdcblx0ICAgICAqIGFuIEFwcElkZW50aWZpZXIuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgRkRDMyAyLjAgTm90ZTogV2hlbiBuZWVkaW5nIGFuIGluc3RhbmNlSWQgdG8gZ2VuZXJhdGUgYW4gQXBwSWRlbnRpZmllciB1c2UgdGhpcyBjYWxsIHRvXG5cdCAgICAgKiBnZXQgdGhlIGVuZHBvaW50SWQgYW5kIHVzZSBpdCBhcyB0aGUgaW5zdGFuY2VJZC4gSW4gdGhlIEV4YW1wbGUgYmVsb3cgd2Ugb3ZlcnJpZGUgaGFuZGxlRmlyZWRJbnRlbnRcblx0ICAgICAqIGFuZCB0aGVuIGNhbGwgc3VwZXIuZ2V0QWxsQ2xpZW50SW5mbyB0byBnZW5lcmF0ZSB0aGUgQXBwSWRlbnRpZmllciBmb3IgdGhlIEludGVudFJlc29sdXRpb24uXG5cdCAgICAgKlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogLy8gRkRDMyAyLjAgRXhhbXBsZTpcblx0ICAgICAqIGZpbi5QbGF0Zm9ybS5pbml0KHtcblx0ICAgICAqICAgICBpbnRlcm9wT3ZlcnJpZGU6IGFzeW5jIChJbnRlcm9wQnJva2VyLCAuLi5hcmdzKSA9PiB7XG5cdCAgICAgKiAgICAgICAgIGNsYXNzIE92ZXJyaWRlIGV4dGVuZHMgSW50ZXJvcEJyb2tlciB7XG5cdCAgICAgKiAgICAgICAgICAgICBhc3luYyBoYW5kbGVGaXJlZEludGVudChpbnRlbnQpIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICBzdXBlci5zZXRJbnRlbnRUYXJnZXQoaW50ZW50LCB7IHV1aWQ6ICdwbGF0Zm9ybS11dWlkJywgbmFtZTogJ2ludGVudC12aWV3JyB9KTtcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuXHQgICAgICogICAgICAgICAgICAgICAgIGNvbnN0IHdpbiA9IGZpbi5XaW5kb3cud3JhcFN5bmMoeyBuYW1lOiAnZm9vJywgdXVpZDogJ3BsYXRmb3JtLXV1aWQnIH0pO1xuXHQgICAgICogICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWRWaWV3ID0gYXdhaXQgcGxhdGZvcm0uY3JlYXRlVmlldyh7IHVybDogJ2h0dHA6Ly9vcGVuZmluLmNvJywgbmFtZTogJ2ludGVudC12aWV3JyB9LCB3aW4uaWRlbnRpdHkpO1xuXHQgICAgICpcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zdCBhbGxDbGllbnRJbmZvID0gYXdhaXQgc3VwZXIuZ2V0QWxsQ2xpZW50SW5mbygpO1xuXHQgICAgICpcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zdCBpbmZvRm9yVGFyZ2V0ID0gYWxsQ2xpZW50SW5mby5maW5kKChjbGllbnRJbmZvKSA9PiB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjbGllbnRJbmZvLnV1aWQgPT09ICdwbGF0Zm9ybS11dWlkJyAmJiBjbGllbnRJbmZvLm5hbWUgPT09ICdpbnRlbnQtdmlldyc7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgfSk7XG5cdCAgICAgKlxuXHQgICAgICogICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgYXBwSWQ6ICdpbnRlbnQtdmlldycsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgIGluc3RhbmNlSWQ6IGluZm9Gb3JUYXJnZXQuZW5kcG9pbnRJZFxuXHQgICAgICogICAgICAgICAgICAgICAgIH1cblx0ICAgICAqXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgcmV0dXJuIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgc291cmNlLFxuXHQgICAgICogICAgICAgICAgICAgICAgICAgICBpbnRlbnQ6IGludGVudC5uYW1lXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgfVxuXHQgICAgICpcblx0ICAgICAqICAgICAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgfVxuXHQgICAgICogICAgICAgICByZXR1cm4gbmV3IE92ZXJyaWRlKC4uLmFyZ3MpO1xuXHQgICAgICogICAgIH1cblx0ICAgICAqIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldEFsbENsaWVudEluZm8oKSB7XG5cdCAgICAgICAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCB0aGlzLmdldFByb3ZpZGVyKCk7XG5cdCAgICAgICAgcmV0dXJuIHByb3ZpZGVyLmdldEFsbENsaWVudEluZm8oKTtcblx0ICAgIH1cblx0ICAgIC8qXG5cdCAgICBTbmFwc2hvdCBBUElzXG5cdCAgICAqL1xuXHQgICAgLy8gVXNlZCB0byBzYXZlIGludGVyb3AgYnJva2VyIHN0YXRlIGluIHNuYXBzaG90c1xuXHQgICAgZGVjb3JhdGVTbmFwc2hvdChzbmFwc2hvdCkge1xuXHQgICAgICAgIHJldHVybiB7IC4uLnNuYXBzaG90LCBpbnRlcm9wU25hcHNob3REZXRhaWxzOiB7IGNvbnRleHRHcm91cFN0YXRlczogdGhpcy5nZXRDb250ZXh0R3JvdXBTdGF0ZXMoKSB9IH07XG5cdCAgICB9XG5cdCAgICAvLyBVc2VkIHRvIHJlc3RvcmUgaW50ZXJvcCBicm9rZXIgc3RhdGUgaW4gc25hcHNob3RzLlxuXHQgICAgYXBwbHlTbmFwc2hvdChzbmFwc2hvdCwgb3B0aW9ucykge1xuXHQgICAgICAgIGNvbnN0IGNvbnRleHRHcm91cFN0YXRlcyA9IHNuYXBzaG90Py5pbnRlcm9wU25hcHNob3REZXRhaWxzPy5jb250ZXh0R3JvdXBTdGF0ZXM7XG5cdCAgICAgICAgaWYgKGNvbnRleHRHcm91cFN0YXRlcykge1xuXHQgICAgICAgICAgICBpZiAoIW9wdGlvbnM/LmNsb3NlRXhpc3RpbmdXaW5kb3dzKSB7XG5cdCAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUV4aXN0aW5nQ2xpZW50cyhjb250ZXh0R3JvdXBTdGF0ZXMpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIHRoaXMucmVoeWRyYXRlQ29udGV4dEdyb3VwU3RhdGVzKGNvbnRleHRHcm91cFN0YXRlcyk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgdXBkYXRlRXhpc3RpbmdDbGllbnRzKGNvbnRleHRHcm91cFN0YXRlcykge1xuXHQgICAgICAgIGNvbnN0IGNsaWVudHMgPSB0aGlzLmludGVyb3BDbGllbnRzO1xuXHQgICAgICAgIGNsaWVudHMuZm9yRWFjaCgoc3ViU3RhdGUpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgeyBjbGllbnRJZGVudGl0eSwgY29udGV4dEdyb3VwSWQsIGNvbnRleHRIYW5kbGVycyB9ID0gc3ViU3RhdGU7XG5cdCAgICAgICAgICAgIGlmIChjb250ZXh0R3JvdXBJZCkge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgZ3JvdXBDb250ZXh0cyA9IGNvbnRleHRHcm91cFN0YXRlc1tjb250ZXh0R3JvdXBJZF07XG5cdCAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IFssIGNvbnRleHRdIG9mIE9iamVjdC5lbnRyaWVzKGdyb3VwQ29udGV4dHMpKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgY29udGV4dEhhbmRsZXJzLmZvckVhY2goKGNvbnRleHRIYW5kbGVyKSA9PiB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgaGFuZGxlcklkLCBjb250ZXh0VHlwZSB9ID0gY29udGV4dEhhbmRsZXI7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGlmIChJbnRlcm9wQnJva2VyLmlzQ29udGV4dFR5cGVDb21wYXRpYmxlKGNvbnRleHQudHlwZSwgY29udGV4dFR5cGUpKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmludm9rZUNvbnRleHRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGNvbnRleHQpO1xuXHQgICAgICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIC8vIFVzZWQgdG8gc3RvcmUgY29udGV4dCBncm91cCBzdGF0ZSBpbiBzbmFwc2hvdHNcblx0ICAgIGdldENvbnRleHRHcm91cFN0YXRlcygpIHtcblx0ICAgICAgICByZXR1cm4gSW50ZXJvcEJyb2tlci50b09iamVjdCh0aGlzLmNvbnRleHRHcm91cHNCeUlkKTtcblx0ICAgIH1cblx0ICAgIC8vIFVzZWQgdG8gcmVoeWRyYXRlIHRoZSBjb250ZXh0IHN0YXRlIGZyb20gYSBzbmFwc2hvdFxuXHQgICAgcmVoeWRyYXRlQ29udGV4dEdyb3VwU3RhdGVzKGluY29taW5nQ29udGV4dEdyb3VwU3RhdGVzKSB7XG5cdCAgICAgICAgY29uc3QgY29udGV4dEdyb3VwU3RhdGVzID0gT2JqZWN0LmVudHJpZXMoaW5jb21pbmdDb250ZXh0R3JvdXBTdGF0ZXMpO1xuXHQgICAgICAgIGZvciAoY29uc3QgW2NvbnRleHRHcm91cElkLCBjb250ZXh0c10gb2YgY29udGV4dEdyb3VwU3RhdGVzKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGNvbnRleHRPYmplY3RzID0gT2JqZWN0LmVudHJpZXMoY29udGV4dHMpO1xuXHQgICAgICAgICAgICBmb3IgKGNvbnN0IFtjb250ZXh0VHlwZSwgY29udGV4dF0gb2YgY29udGV4dE9iamVjdHMpIHtcblx0ICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbnRleHRHcm91cHNCeUlkLmhhcyhjb250ZXh0R3JvdXBJZCkpIHtcblx0ICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50Q29udGV4dEdyb3VwU3RhdGUgPSB0aGlzLmNvbnRleHRHcm91cHNCeUlkLmdldChjb250ZXh0R3JvdXBJZCk7XG5cdCAgICAgICAgICAgICAgICAgICAgY3VycmVudENvbnRleHRHcm91cFN0YXRlLnNldChjb250ZXh0VHlwZSwgY29udGV4dCk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIGxvZ2ljIHdpbGwgY2hhbmdlIHdoZW4gZHluYW1pYyBjb250ZXh0IGdyb3VwIGNyZWF0aW9uIGNvbWVzIGluLlxuXHQgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgQXR0ZW1wdGluZyB0byBzZXQgYSBjb250ZXh0IGdyb3VwIHRoYXQgaXNuJ3QgaW4gdGhlIGNvbnRleHQgZ3JvdXAgbWFwcGluZy4gU2tpcHBpbmcgY29udGV4dCBncm91cCByZWh5ZHJhdGlvbiBmb3I6ICR7Y29udGV4dEdyb3VwSWR9YCk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKlxuXHQgICAgSW50ZXJuYWwgQ29udGV4dCBIYW5kbGVyIEFQSXNcblx0ICAgICovXG5cdCAgICAvLyBVc2VkIHRvIGdpdmUgY29udGV4dCB0byBhIGNsaWVudCB0aGF0IGhhcyByZWdpc3RlcmVkIHRoZWlyIGNvbnRleHQgaGFuZGxlclxuXHQgICAgY29udGV4dEhhbmRsZXJSZWdpc3RlcmVkKHsgY29udGV4dFR5cGUsIGhhbmRsZXJJZCB9LCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IGhhbmRsZXJJbmZvID0geyBjb250ZXh0VHlwZSwgaGFuZGxlcklkIH07XG5cdCAgICAgICAgY29uc3QgY2xpZW50U3RhdGUgPSB0aGlzLmdldENsaWVudFN0YXRlKGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICBjbGllbnRTdGF0ZT8uY29udGV4dEhhbmRsZXJzLnNldChoYW5kbGVySWQsIGhhbmRsZXJJbmZvKTtcblx0ICAgICAgICBpZiAoY2xpZW50U3RhdGUgJiYgY2xpZW50U3RhdGUuY29udGV4dEdyb3VwSWQpIHtcblx0ICAgICAgICAgICAgY29uc3QgeyBjb250ZXh0R3JvdXBJZCB9ID0gY2xpZW50U3RhdGU7XG5cdCAgICAgICAgICAgIGNvbnN0IGNvbnRleHRHcm91cE1hcCA9IHRoaXMuY29udGV4dEdyb3Vwc0J5SWQuZ2V0KGNvbnRleHRHcm91cElkKTtcblx0ICAgICAgICAgICAgaWYgKGNvbnRleHRUeXBlID09PSB1bmRlZmluZWQpIHtcblx0ICAgICAgICAgICAgICAgIC8vIFNlbmQgdGhpcyBzaW5nbGUgaGFuZGxlciBhbGwgb2YgdGhlIGNvbnRleHQsIGJlY2F1c2UgaXQgYWNjZXB0cyBhbGwuXG5cdCAgICAgICAgICAgICAgICBjb250ZXh0R3JvdXBNYXAuZm9yRWFjaCgoY29udGV4dCwgXykgPT4ge1xuXHQgICAgICAgICAgICAgICAgICAgIHRoaXMuaW52b2tlQ29udGV4dEhhbmRsZXIoY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwgY29udGV4dCk7XG5cdCAgICAgICAgICAgICAgICB9KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBlbHNlIGlmIChjb250ZXh0R3JvdXBNYXAuaGFzKGNvbnRleHRUeXBlKSkge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgY29udGV4dEZvclR5cGUgPSBjb250ZXh0R3JvdXBNYXAuZ2V0KGNvbnRleHRUeXBlKTtcblx0ICAgICAgICAgICAgICAgIGlmIChjb250ZXh0Rm9yVHlwZSkge1xuXHQgICAgICAgICAgICAgICAgICAgIHRoaXMuaW52b2tlQ29udGV4dEhhbmRsZXIoY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwgY29udGV4dEZvclR5cGUpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcblx0ICAgIGFzeW5jIGludGVudEhhbmRsZXJSZWdpc3RlcmVkKHBheWxvYWQsIGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgY29uc3QgeyBoYW5kbGVySWQgfSA9IHBheWxvYWQ7XG5cdCAgICAgICAgY29uc3QgY2xpZW50SW50ZW50SW5mbyA9IHRoaXMuaW50ZW50Q2xpZW50TWFwLmdldChjbGllbnRJZGVudGl0eS5uYW1lKTtcblx0ICAgICAgICBjb25zdCBoYW5kbGVySW5mbyA9IGNsaWVudEludGVudEluZm8/LmdldChoYW5kbGVySWQpO1xuXHQgICAgICAgIGlmICghY2xpZW50SW50ZW50SW5mbykge1xuXHQgICAgICAgICAgICB0aGlzLmludGVudENsaWVudE1hcC5zZXQoY2xpZW50SWRlbnRpdHkubmFtZSwgbmV3IE1hcCgpKTtcblx0ICAgICAgICAgICAgY29uc3QgbmV3SGFuZGxlckluZm9NYXAgPSB0aGlzLmludGVudENsaWVudE1hcC5nZXQoY2xpZW50SWRlbnRpdHkubmFtZSk7XG5cdCAgICAgICAgICAgIGlmIChuZXdIYW5kbGVySW5mb01hcCkge1xuXHQgICAgICAgICAgICAgICAgbmV3SGFuZGxlckluZm9NYXAuc2V0KGhhbmRsZXJJZCwgeyBpc1JlYWR5OiB0cnVlLCBwZW5kaW5nSW50ZW50czogW10sIGNsaWVudElkZW50aXR5IH0pO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2UgaWYgKCFoYW5kbGVySW5mbykge1xuXHQgICAgICAgICAgICBjbGllbnRJbnRlbnRJbmZvLnNldChoYW5kbGVySWQsIHsgaXNSZWFkeTogdHJ1ZSwgcGVuZGluZ0ludGVudHM6IFtdLCBjbGllbnRJZGVudGl0eSB9KTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIGNvbnN0IHsgcGVuZGluZ0ludGVudHMgfSA9IGhhbmRsZXJJbmZvO1xuXHQgICAgICAgICAgICBoYW5kbGVySW5mby5jbGllbnRJZGVudGl0eSA9IGNsaWVudElkZW50aXR5O1xuXHQgICAgICAgICAgICBoYW5kbGVySW5mby5pc1JlYWR5ID0gdHJ1ZTtcblx0ICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgIGlmIChwZW5kaW5nSW50ZW50cy5sZW5ndGggPiAwKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgY29uc3QgaW50ZW50VG9TZW5kID0gcGVuZGluZ0ludGVudHNbcGVuZGluZ0ludGVudHMubGVuZ3RoIC0gMV07XG5cdCAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5pbnZva2VJbnRlbnRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGludGVudFRvU2VuZCk7XG5cdCAgICAgICAgICAgICAgICAgICAgaGFuZGxlckluZm8ucGVuZGluZ0ludGVudHMgPSBbXTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIGludm9raW5nIGludGVudCBoYW5kbGVyOiAke2hhbmRsZXJJZH0gZm9yIGNsaWVudCAke2NsaWVudElkZW50aXR5LnV1aWR9LyR7Y2xpZW50SWRlbnRpdHkubmFtZX0vJHtjbGllbnRJZGVudGl0eS5lbmRwb2ludElkfWApO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLy8gVXNlZCB0byByZW1vdmUgYSBjb250ZXh0IGhhbmRsZXIgZm9yIGEgY2xpZW50XG5cdCAgICByZW1vdmVDb250ZXh0SGFuZGxlcih7IGhhbmRsZXJJZCB9LCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKGNsaWVudFN0YXRlKSB7XG5cdCAgICAgICAgICAgIGNsaWVudFN0YXRlLmNvbnRleHRIYW5kbGVycy5kZWxldGUoaGFuZGxlcklkKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICBoYW5kbGVKb2luU2Vzc2lvbkNvbnRleHRHcm91cCh7IHNlc3Npb25Db250ZXh0R3JvdXBJZCB9LCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIGlmICghc2Vzc2lvbkNvbnRleHRHcm91cElkKSB7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBqb2luIHNlc3Npb24gY29udGV4dCBncm91cDogbXVzdCBzcGVjaWZ5IGdyb3VwIGlkLicpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNvbnN0IHNlc3Npb25Db250ZXh0R3JvdXAgPSB0aGlzLnNlc3Npb25Db250ZXh0R3JvdXBNYXAuZ2V0KHNlc3Npb25Db250ZXh0R3JvdXBJZCk7XG5cdCAgICAgICAgICAgIGlmIChzZXNzaW9uQ29udGV4dEdyb3VwKSB7XG5cdCAgICAgICAgICAgICAgICBzZXNzaW9uQ29udGV4dEdyb3VwLnJlZ2lzdGVyTmV3Q2xpZW50KGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IG5ld1Nlc3Npb25Db250ZXh0R3JvdXBCcm9rZXIgPSBuZXcgU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlcl8xLmRlZmF1bHQodGhpcy5jaGFubmVsLCBzZXNzaW9uQ29udGV4dEdyb3VwSWQpO1xuXHQgICAgICAgICAgICAgICAgbmV3U2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlci5yZWdpc3Rlck5ld0NsaWVudChjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb25Db250ZXh0R3JvdXBNYXAuc2V0KHNlc3Npb25Db250ZXh0R3JvdXBJZCwgbmV3U2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlcik7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgcmV0dXJuIHsgaGFzQ29uZmxpY3Q6IHRoaXMuY29udGV4dEdyb3Vwc0J5SWQuaGFzKHNlc3Npb25Db250ZXh0R3JvdXBJZCkgfTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLypcblx0ICAgIEludGVybmFsIFV0aWx0aWVzXG5cdCAgICAqL1xuXHQgICAgLy8gR2V0dGVyIGZvciBpbnRlcm9wIGluZm8gZm9yIGEgY2xpZW50LlxuXHQgICAgZ2V0Q2xpZW50U3RhdGUoaWQpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy5pbnRlcm9wQ2xpZW50cy5nZXQoaWQuZW5kcG9pbnRJZCk7XG5cdCAgICB9XG5cdCAgICAvLyBVdGlsIGZvciBnZXRDb250ZXh0R3JvdXBTdGF0ZXMuIFNlcmlhbGl6ZXMgdGhlIGNvbnRleHRHcm91cFN0YXRlcyBvYmplY3Qgc28gd2UgY2FuIHN0b3JlIGl0LlxuXHQgICAgc3RhdGljIHRvT2JqZWN0KG1hcCkge1xuXHQgICAgICAgIGNvbnN0IG9iamVjdEZyb21NYXAgPSBPYmplY3QuZnJvbUVudHJpZXMobWFwKTtcblx0ICAgICAgICBjb25zdCBuZXdPYmplY3QgPSB7fTtcblx0ICAgICAgICBPYmplY3QuZW50cmllcyhvYmplY3RGcm9tTWFwKS5mb3JFYWNoKChbY29udGV4dEdyb3VwSWQsIGNvbnRleHRNYXBdKSA9PiB7XG5cdCAgICAgICAgICAgIGNvbnN0IG5ld0NvbnRleHRPYmplY3QgPSBPYmplY3QuZnJvbUVudHJpZXMoY29udGV4dE1hcCk7XG5cdCAgICAgICAgICAgIG5ld09iamVjdFtjb250ZXh0R3JvdXBJZF0gPSBuZXdDb250ZXh0T2JqZWN0O1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiBuZXdPYmplY3Q7XG5cdCAgICB9XG5cdCAgICBzdGF0aWMgY2hlY2tDb250ZXh0SW50ZWdyaXR5KGNvbnRleHQpIHtcblx0ICAgICAgICBpZiAoIWNvbnRleHQpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogZmFsc2UsIHJlYXNvbjogJ05vIGNvbnRleHQgc3VwcGxpZWQnIH07XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmICh0eXBlb2YgY29udGV4dCAhPT0gJ29iamVjdCcpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogZmFsc2UsIHJlYXNvbjogJ0NvbnRleHQgbXVzdCBiZSBhbiBPYmplY3QnIH07XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmICghY29udGV4dC50eXBlKSB7XG5cdCAgICAgICAgICAgIHJldHVybiB7IGlzVmFsaWQ6IGZhbHNlLCByZWFzb246ICdDb250ZXh0IG11c3QgaGF2ZSBhIHR5cGUgcHJvcGVydHknIH07XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmIChjb250ZXh0LmlkICYmIHR5cGVvZiBjb250ZXh0LmlkICE9PSAnb2JqZWN0Jykge1xuXHQgICAgICAgICAgICByZXR1cm4ge1xuXHQgICAgICAgICAgICAgICAgaXNWYWxpZDogZmFsc2UsXG5cdCAgICAgICAgICAgICAgICByZWFzb246ICdDb250ZXh0IGlkIG11c3QgYmUgYW4gT2JqZWN0IHBvcHVsYXRlZCB3aXRoIGtleS12YWx1ZSBpZGVudGlmaWVycyAoaWYgc2V0KSdcblx0ICAgICAgICAgICAgfTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgaWYgKGNvbnRleHQuaWQpIHtcblx0ICAgICAgICAgICAgY29uc3QgeyBpZCB9ID0gY29udGV4dDtcblx0ICAgICAgICAgICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGlkKTtcblx0ICAgICAgICAgICAgbGV0IGZvdW5kQmFkSWRlbnRpZmllciA9IGZhbHNlO1xuXHQgICAgICAgICAgICBpZiAoIWtleXMubGVuZ3RoKSB7XG5cdCAgICAgICAgICAgICAgICByZXR1cm4geyBpc1ZhbGlkOiBmYWxzZSwgcmVhc29uOiAnQ29udGV4dCBpZCBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIGtleS12YWx1ZSBpZGVudGlmaWVyJyB9O1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGtleXMuZm9yRWFjaCgoa2V5KSA9PiB7XG5cdCAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGtleSAhPT0gJ3N0cmluZycgfHwgdHlwZW9mIGlkW2tleV0gIT09ICdzdHJpbmcnKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgZm91bmRCYWRJZGVudGlmaWVyID0gdHJ1ZTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgIGlmIChmb3VuZEJhZElkZW50aWZpZXIpIHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiB7IGlzVmFsaWQ6IGZhbHNlLCByZWFzb246ICdDb250ZXh0IGlkIGtleS12YWx1ZSBpZGVudGlmaWVycyBtdXN0IGJlIG9mIHR5cGUgc3RyaW5nJyB9O1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmIChjb250ZXh0Lm5hbWUgJiYgdHlwZW9mIGNvbnRleHQubmFtZSAhPT0gJ3N0cmluZycpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogZmFsc2UsIHJlYXNvbjogJ0NvbnRleHQgbmFtZSBtdXN0IGJlIG9mIHN0cmluZyB0eXBlIChpZiBzZXQpJyB9O1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4geyBpc1ZhbGlkOiB0cnVlIH07XG5cdCAgICB9XG5cdCAgICAvLyBVdGlsIHRvIGNoZWNrIGEgY2xpZW50IGlkZW50aXR5LlxuXHQgICAgc3RhdGljIGhhc0VuZHBvaW50SWQodGFyZ2V0KSB7XG5cdCAgICAgICAgcmV0dXJuIHRhcmdldC5lbmRwb2ludElkICE9PSB1bmRlZmluZWQ7XG5cdCAgICB9XG5cdCAgICAvLyBVdGlsIHRvIGNoZWNrIGlmIHdlIHNob3VsZCBzZW5kIGEgY29udGV4dCB0byBhIGhhbmRsZXIuXG5cdCAgICBzdGF0aWMgaXNDb250ZXh0VHlwZUNvbXBhdGlibGUoY29udGV4dFR5cGUsIHJlZ2lzdGVyZWRDb250ZXh0VHlwZSkge1xuXHQgICAgICAgIHJldHVybiB0eXBlb2YgcmVnaXN0ZXJlZENvbnRleHRUeXBlID09PSAndW5kZWZpbmVkJyB8fCBjb250ZXh0VHlwZSA9PT0gcmVnaXN0ZXJlZENvbnRleHRUeXBlO1xuXHQgICAgfVxuXHQgICAgLy8gU2V0dXAgZnVuY3Rpb24gZm9yIHN0YXRlIG1hcHBpbmdcblx0ICAgIHNldENvbnRleHRHcm91cE1hcCgpIHtcblx0ICAgICAgICAvLyBUaGlzIHdheSwgaWYgYSB1c2VyIG92ZXJyaWRlcyB0aGlzLmdldENvbnRleHRHcm91cHMsIGl0J3MgcmVmbGVjdGVkIGluIHRoZSBjb250ZXh0R3JvdXBNYXBwaW5nLlxuXHQgICAgICAgIGZvciAoY29uc3QgY29udGV4dEdyb3VwSW5mbyBvZiB0aGlzLmdldENvbnRleHRHcm91cHMoKSkge1xuXHQgICAgICAgICAgICB0aGlzLmNvbnRleHRHcm91cHNCeUlkLnNldChjb250ZXh0R3JvdXBJbmZvLmlkLCBuZXcgTWFwKCkpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIGFzeW5jIHNldEN1cnJlbnRDb250ZXh0R3JvdXBJbkNsaWVudE9wdGlvbnMoY2xpZW50SWRlbnRpdHksIGNvbnRleHRHcm91cElkKSB7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgY29uc3QgZW50aXR5SW5mbyA9IGF3YWl0IHRoaXMuZmluLlN5c3RlbS5nZXRFbnRpdHlJbmZvKGNsaWVudElkZW50aXR5LnV1aWQsIGNsaWVudElkZW50aXR5Lm5hbWUpO1xuXHQgICAgICAgICAgICBsZXQgZW50aXR5O1xuXHQgICAgICAgICAgICBpZiAoZW50aXR5SW5mby5lbnRpdHlUeXBlID09PSAndmlldycpIHtcblx0ICAgICAgICAgICAgICAgIGVudGl0eSA9IGF3YWl0IHRoaXMuZmluLlZpZXcud3JhcChjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgZWxzZSBpZiAoZW50aXR5SW5mby5lbnRpdHlUeXBlID09PSAnd2luZG93Jykge1xuXHQgICAgICAgICAgICAgICAgZW50aXR5ID0gYXdhaXQgdGhpcy5maW4uV2luZG93LndyYXAoY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGlmIChlbnRpdHkpIHtcblx0ICAgICAgICAgICAgICAgIGF3YWl0IGVudGl0eS51cGRhdGVPcHRpb25zKHtcblx0ICAgICAgICAgICAgICAgICAgICBpbnRlcm9wOiB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDb250ZXh0R3JvdXA6IGNvbnRleHRHcm91cElkXG5cdCAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIC8vICBNYXkgZmlsZSBpbiBpbnRlcm9wXG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgYXN5bmMgc2V0dXBDaGFubmVsUHJvdmlkZXIoKSB7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgY29uc3QgY2hhbm5lbCA9IGF3YWl0IHRoaXMuZ2V0UHJvdmlkZXIoKTtcblx0ICAgICAgICAgICAgdGhpcy5jaGFubmVsID0gY2hhbm5lbDtcblx0ICAgICAgICAgICAgdGhpcy53aXJlQ2hhbm5lbChjaGFubmVsKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igc2V0dGluZyB1cCBJbnRlcm9wIEJyb2tlciBDaGFubmVsIFByb3ZpZGVyOiAke2Vycm9yfWApO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8vIFNldHVwIENoYW5uZWwgQ29ubmVjdGlvbiBMb2dpY1xuXHQgICAgd2lyZUNoYW5uZWwoY2hhbm5lbCkge1xuXHQgICAgICAgIGNoYW5uZWwub25Db25uZWN0aW9uKGFzeW5jIChjbGllbnRJZGVudGl0eSwgLy8gVE9ETyhDT1JFLTgxMSk6IHJlbW92ZSBpbmxpbmUgaW50ZXJzZWN0ZWQgdHlwZVxuXHQgICAgICAgIHBheWxvYWQpID0+IHtcblx0ICAgICAgICAgICAgaWYgKCEoYXdhaXQgdGhpcy5pc0Nvbm5lY3Rpb25BdXRob3JpemVkKGNsaWVudElkZW50aXR5LCBwYXlsb2FkKSkpIHtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ29ubmVjdGlvbiBub3QgYXV0aG9yaXplZCBmb3IgJHtjbGllbnRJZGVudGl0eS51dWlkfSwgJHtjbGllbnRJZGVudGl0eS5uYW1lfWApO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGlmICghY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCkge1xuXHQgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdWZXJzaW9uIHRvbyBvbGQgdG8gYmUgY29tcGF0aWJsZSB3aXRoIEludGVyb3AuIFBsZWFzZSB1cGdyYWRlIHlvdXIgcnVudGltZSB0byBhIG1vcmUgcmVjZW50IHZlcnNpb24uJyk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgY29uc3QgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUgPSB7XG5cdCAgICAgICAgICAgICAgICBjb250ZXh0R3JvdXBJZDogdW5kZWZpbmVkLFxuXHQgICAgICAgICAgICAgICAgY29udGV4dEhhbmRsZXJzOiBuZXcgTWFwKCksXG5cdCAgICAgICAgICAgICAgICBjbGllbnRJZGVudGl0eVxuXHQgICAgICAgICAgICB9O1xuXHQgICAgICAgICAgICAvLyBPbmx5IGFsbG93IHRoZSBjbGllbnQgdG8gam9pbiBhIGNvbnRleHRHcm91cCB0aGF0IGFjdHVhbGx5IGV4aXN0cy5cblx0ICAgICAgICAgICAgaWYgKHBheWxvYWQ/LmN1cnJlbnRDb250ZXh0R3JvdXAgJiYgdGhpcy5jb250ZXh0R3JvdXBzQnlJZC5oYXMocGF5bG9hZC5jdXJyZW50Q29udGV4dEdyb3VwKSkge1xuXHQgICAgICAgICAgICAgICAgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUuY29udGV4dEdyb3VwSWQgPSBwYXlsb2FkPy5jdXJyZW50Q29udGV4dEdyb3VwO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIHRoaXMuaW50ZXJvcENsaWVudHMuc2V0KGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQsIGNsaWVudFN1YnNjcmlwdGlvblN0YXRlKTtcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjaGFubmVsLm9uRGlzY29ubmVjdGlvbigoY2xpZW50SWRlbnRpdHkpID0+IHtcblx0ICAgICAgICAgICAgdGhpcy5pbnRlcm9wQ2xpZW50cy5kZWxldGUoY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCk7XG5cdCAgICAgICAgICAgIGNvbnN0IHRhcmdldEluZm8gPSB0aGlzLmludGVudENsaWVudE1hcC5nZXQoY2xpZW50SWRlbnRpdHkubmFtZSk7XG5cdCAgICAgICAgICAgIGlmICh0YXJnZXRJbmZvICYmIGNsaWVudElkZW50aXR5LnV1aWQgPT09IHRoaXMuZmluLm1lLnV1aWQpIHtcblx0ICAgICAgICAgICAgICAgIHRhcmdldEluZm8uZm9yRWFjaCgoaGFuZGxlcikgPT4ge1xuXHQgICAgICAgICAgICAgICAgICAgIGhhbmRsZXIuaXNSZWFkeSA9IGZhbHNlO1xuXHQgICAgICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgdGhpcy5zZXNzaW9uQ29udGV4dEdyb3VwTWFwLmZvckVhY2goKHNlc3Npb25Db250ZXh0R3JvdXApID0+IHtcblx0ICAgICAgICAgICAgICAgIHNlc3Npb25Db250ZXh0R3JvdXAub25EaXNjb25uZWN0aW9uKGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgIHRoaXMuY2xpZW50RGlzY29ubmVjdGVkKGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjaGFubmVsLmJlZm9yZUFjdGlvbihhc3luYyAoYWN0aW9uLCBwYXlsb2FkLCBjbGllbnRJZGVudGl0eSkgPT4ge1xuXHQgICAgICAgICAgICBpZiAoIShhd2FpdCB0aGlzLmlzQWN0aW9uQXV0aG9yaXplZChhY3Rpb24sIHBheWxvYWQsIGNsaWVudElkZW50aXR5KSkpIHtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQWN0aW9uICgke2FjdGlvbn0pIG5vdCBhdXRob3JpemVkIGZvciAke2NsaWVudElkZW50aXR5LnV1aWR9LCAke2NsaWVudElkZW50aXR5Lm5hbWV9YCk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgaWYgKHRoaXMubG9nZ2luZz8uYmVmb3JlQWN0aW9uPy5lbmFibGVkKSB7XG5cdCAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhhY3Rpb24sIHBheWxvYWQsIGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNoYW5uZWwuYWZ0ZXJBY3Rpb24oKGFjdGlvbiwgcGF5bG9hZCwgY2xpZW50SWRlbnRpdHkpID0+IHtcblx0ICAgICAgICAgICAgaWYgKHRoaXMubG9nZ2luZz8uYWZ0ZXJBY3Rpb24/LmVuYWJsZWQpIHtcblx0ICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGFjdGlvbiwgcGF5bG9hZCwgY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgLy8gQ2xpZW50IGZ1bmN0aW9uc1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ3NldENvbnRleHQnLCB0aGlzLnNldENvbnRleHQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3RlcignZmlyZUludGVudCcsIHRoaXMuaGFuZGxlRmlyZWRJbnRlbnQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3RlcignZ2V0Q3VycmVudENvbnRleHQnLCB0aGlzLmdldEN1cnJlbnRDb250ZXh0LmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2dldEluZm9Gb3JJbnRlbnQnLCB0aGlzLmhhbmRsZUluZm9Gb3JJbnRlbnQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3RlcignZ2V0SW5mb0ZvckludGVudHNCeUNvbnRleHQnLCB0aGlzLmhhbmRsZUluZm9Gb3JJbnRlbnRzQnlDb250ZXh0LmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2ZpcmVJbnRlbnRGb3JDb250ZXh0JywgdGhpcy5oYW5kbGVGaXJlZEludGVudEZvckNvbnRleHQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgLy8gUGxhdGZvcm0gd2luZG93IGZ1bmN0aW9uc1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2dldENvbnRleHRHcm91cHMnLCB0aGlzLmdldENvbnRleHRHcm91cHMuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3Rlcignam9pbkNvbnRleHRHcm91cCcsIHRoaXMuam9pbkNvbnRleHRHcm91cC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdyZW1vdmVGcm9tQ29udGV4dEdyb3VwJywgdGhpcy5yZW1vdmVGcm9tQ29udGV4dEdyb3VwLmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2dldEFsbENsaWVudHNJbkNvbnRleHRHcm91cCcsIHRoaXMuZ2V0QWxsQ2xpZW50c0luQ29udGV4dEdyb3VwLmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2dldEluZm9Gb3JDb250ZXh0R3JvdXAnLCB0aGlzLmdldEluZm9Gb3JDb250ZXh0R3JvdXAuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgLy8gSW50ZXJuYWwgbWV0aG9kc1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2NvbnRleHRIYW5kbGVyUmVnaXN0ZXJlZCcsIHRoaXMuY29udGV4dEhhbmRsZXJSZWdpc3RlcmVkLmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2ludGVudEhhbmRsZXJSZWdpc3RlcmVkJywgdGhpcy5pbnRlbnRIYW5kbGVyUmVnaXN0ZXJlZC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdyZW1vdmVDb250ZXh0SGFuZGxlcicsIHRoaXMucmVtb3ZlQ29udGV4dEhhbmRsZXIuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3Rlcignc2Vzc2lvbkNvbnRleHRHcm91cDpjcmVhdGVJZk5lZWRlZCcsIHRoaXMuaGFuZGxlSm9pblNlc3Npb25Db250ZXh0R3JvdXAuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgLy8gZmRjMyBvbmx5IG1ldGhvZHNcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdmZGMzT3BlbicsIHRoaXMuZmRjM0hhbmRsZU9wZW4uYmluZCh0aGlzKSk7XG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3RlcignZmRjM3YyRmluZEludGVudHNCeUNvbnRleHQnLCB0aGlzLmhhbmRsZUluZm9Gb3JJbnRlbnRzQnlDb250ZXh0LmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2ZkYzNGaW5kSW5zdGFuY2VzJywgdGhpcy5mZGMzSGFuZGxlRmluZEluc3RhbmNlcy5iaW5kKHRoaXMpKTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdmZGMzR2V0QXBwTWV0YWRhdGEnLCB0aGlzLmZkYzNIYW5kbGVHZXRBcHBNZXRhZGF0YS5iaW5kKHRoaXMpKTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdmZGMzdjJHZXRJbmZvJywgYXN5bmMgKHBheWxvYWQsIGNsaWVudElkZW50aXR5KSA9PiB7XG5cdCAgICAgICAgICAgIHJldHVybiB0aGlzLmZkYzNIYW5kbGVHZXRJbmZvLmJpbmQodGhpcykocGF5bG9hZCwgY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2NyZWF0ZVByaXZhdGVDaGFubmVsUHJvdmlkZXInLCBhc3luYyAocGF5bG9hZCkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCB7IGNoYW5uZWxJZCB9ID0gcGF5bG9hZDtcblx0ICAgICAgICAgICAgY29uc3QgY2hhbm5lbFByb3ZpZGVyID0gYXdhaXQgdGhpcy5maW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZShjaGFubmVsSWQpO1xuXHQgICAgICAgICAgICBQcml2YXRlQ2hhbm5lbFByb3ZpZGVyXzEuUHJpdmF0ZUNoYW5uZWxQcm92aWRlci5pbml0KGNoYW5uZWxQcm92aWRlciwgY2hhbm5lbElkKTtcblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQ2FuIGJlIHVzZWQgdG8gY29tcGxldGVseSBwcmV2ZW50IGEgY29ubmVjdGlvbi4gUmV0dXJuIGZhbHNlIHRvIHByZXZlbnQgY29ubmVjdGlvbnMuIEFsbG93cyBhbGwgY29ubmVjdGlvbnMgYnkgZGVmYXVsdC5cblx0ICAgICAqIEBwYXJhbSBfaWQgdGhlIGlkZW50aXR5IHRyeWluYyB0byBjb25uZWN0XG5cdCAgICAgKiBAcGFyYW0gX2Nvbm5lY3Rpb25QYXlsb2FkIG9wdGlvbmFsIHBheWxvYWQgdG8gdXNlIGluIGN1c3RvbSBpbXBsZW1lbnRhdGlvbnMsIHdpbGwgYmUgdW5kZWZpbmVkIGJ5IGRlZmF1bHRcblx0ICAgICAqL1xuXHQgICAgaXNDb25uZWN0aW9uQXV0aG9yaXplZChfaWQsIF9jb25uZWN0aW9uUGF5bG9hZCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWJyb2tlci1pcy1jb25uZWN0aW9uLWF1dGhvcml6ZWQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRydWUpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBDYWxsZWQgYmVmb3JlIGV2ZXJ5IGFjdGlvbiB0byBjaGVjayBpZiB0aGlzIGVudGl0eSBzaG91bGQgYmUgYWxsb3dlZCB0byB0YWtlIHRoZSBhY3Rpb24uXG5cdCAgICAgKiBSZXR1cm4gZmFsc2UgdG8gcHJldmVudCB0aGUgYWN0aW9uXG5cdCAgICAgKiBAcGFyYW0gX2FjdGlvbiB0aGUgc3RyaW5nIGFjdGlvbiB0byBhdXRob3JpemUgaW4gY2FtZWwgY2FzZVxuXHQgICAgICogQHBhcmFtIF9wYXlsb2FkIHRoZSBkYXRhIGJlaW5nIHNlbnQgZm9yIHRoaXMgYWN0aW9uXG5cdCAgICAgKiBAcGFyYW0gX2lkZW50aXR5IHRoZSBjb25uZWN0aW9uIGF0dGVtcHRpbmcgdG8gZGlzcGF0Y2ggdGhpcyBhY3Rpb25cblx0ICAgICAqL1xuXHQgICAgaXNBY3Rpb25BdXRob3JpemVkKF9hY3Rpb24sIF9wYXlsb2FkLCBfaWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItaXMtYWN0aW9uLWF1dGhvcml6ZWQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRydWUpO1xuXHQgICAgfVxuXHR9O1xuXHRJbnRlcm9wQnJva2VyLkludGVyb3BCcm9rZXIgPSBJbnRlcm9wQnJva2VyJDE7XG5cdF9JbnRlcm9wQnJva2VyX2ZkYzNJbmZvID0gbmV3IFdlYWtNYXAoKSwgX0ludGVyb3BCcm9rZXJfY29udGV4dEdyb3VwcyA9IG5ldyBXZWFrTWFwKCksIF9JbnRlcm9wQnJva2VyX3Byb3ZpZGVyUHJvbWlzZSA9IG5ldyBXZWFrTWFwKCk7XG5cdHJldHVybiBJbnRlcm9wQnJva2VyO1xufVxuXG52YXIgSW50ZXJvcENsaWVudCA9IHt9O1xuXG52YXIgU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudCQxID0ge307XG5cbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XG59O1xudmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMiA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9TZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50X2NsaWVudFByb21pc2U7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudCQxLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGJhc2VfMSQyID0gYmFzZTtcbmNvbnN0IHV0aWxzXzEkMiA9IHV0aWxzJDM7XG5jbGFzcyBTZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50IGV4dGVuZHMgYmFzZV8xJDIuQmFzZSB7XG4gICAgY29uc3RydWN0b3Iod2lyZSwgY2xpZW50LCBpZCkge1xuICAgICAgICBzdXBlcih3aXJlKTtcbiAgICAgICAgX1Nlc3Npb25Db250ZXh0R3JvdXBDbGllbnRfY2xpZW50UHJvbWlzZS5zZXQodGhpcywgdm9pZCAwKTtcbiAgICAgICAgdGhpcy5pZCA9IGlkO1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDIodGhpcywgX1Nlc3Npb25Db250ZXh0R3JvdXBDbGllbnRfY2xpZW50UHJvbWlzZSwgY2xpZW50LCBcImZcIik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNldHMgYSBjb250ZXh0IGZvciB0aGUgc2Vzc2lvbiBjb250ZXh0IGdyb3VwLlxuICAgICAqIEBwYXJhbSBjb250ZXh0IC0gTmV3IGNvbnRleHQgdG8gc2V0LlxuICAgICAqXG4gICAgICogQHR1dG9yaWFsIGludGVyb3Auc2V0Q29udGV4dFxuICAgICAqL1xuICAgIGFzeW5jIHNldENvbnRleHQoY29udGV4dCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1zZXNzaW9uLWNvbnRleHQtZ3JvdXAtc2V0LWNvbnRleHQnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDIodGhpcywgX1Nlc3Npb25Db250ZXh0R3JvdXBDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuICAgICAgICByZXR1cm4gY2xpZW50LmRpc3BhdGNoKGBzZXNzaW9uQ29udGV4dEdyb3VwOnNldENvbnRleHQtJHt0aGlzLmlkfWAsIHtcbiAgICAgICAgICAgIHNlc3Npb25Db250ZXh0R3JvdXBJZDogdGhpcy5pZCxcbiAgICAgICAgICAgIGNvbnRleHRcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGFzeW5jIGdldEN1cnJlbnRDb250ZXh0KHR5cGUpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3Atc2Vzc2lvbi1jb250ZXh0LWdyb3VwLWdldC1jb250ZXh0JykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQyKHRoaXMsIF9TZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50X2NsaWVudFByb21pc2UsIFwiZlwiKTtcbiAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaChgc2Vzc2lvbkNvbnRleHRHcm91cDpnZXRDb250ZXh0LSR7dGhpcy5pZH1gLCB7XG4gICAgICAgICAgICBzZXNzaW9uQ29udGV4dEdyb3VwSWQ6IHRoaXMuaWQsXG4gICAgICAgICAgICB0eXBlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBhc3luYyBhZGRDb250ZXh0SGFuZGxlcihjb250ZXh0SGFuZGxlciwgY29udGV4dFR5cGUpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3Atc2Vzc2lvbi1jb250ZXh0LWdyb3VwLWFkZC1oYW5kbGVyJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGVvZiBjb250ZXh0SGFuZGxlciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm9uLWZ1bmN0aW9uIGFyZ3VtZW50IHBhc3NlZCB0byB0aGUgZmlyc3QgcGFyYW1ldGVyICdoYW5kbGVyJy4gQmUgYXdhcmUgdGhhdCB0aGUgYXJndW1lbnQgb3JkZXIgZG9lcyBub3QgbWF0Y2ggdGhlIEZEQzMgc3RhbmRhcmQuXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMih0aGlzLCBfU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG4gICAgICAgIGxldCBoYW5kbGVySWQ7XG4gICAgICAgIGlmIChjb250ZXh0VHlwZSkge1xuICAgICAgICAgICAgaGFuZGxlcklkID0gYHNlc3Npb25Db250ZXh0SGFuZGxlcjppbnZva2UtJHt0aGlzLmlkfS0ke2NvbnRleHRUeXBlfS0keygwLCB1dGlsc18xJDIuZ2VuZXJhdGVJZCkoKX1gO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaGFuZGxlcklkID0gYHNlc3Npb25Db250ZXh0SGFuZGxlcjppbnZva2UtJHt0aGlzLmlkfWA7XG4gICAgICAgIH1cbiAgICAgICAgY2xpZW50LnJlZ2lzdGVyKGhhbmRsZXJJZCwgKDAsIHV0aWxzXzEkMi53cmFwQ29udGV4dEhhbmRsZXIpKGNvbnRleHRIYW5kbGVyLCBoYW5kbGVySWQpKTtcbiAgICAgICAgYXdhaXQgY2xpZW50LmRpc3BhdGNoKGBzZXNzaW9uQ29udGV4dEdyb3VwOmhhbmRsZXJBZGRlZC0ke3RoaXMuaWR9YCwgeyBoYW5kbGVySWQsIGNvbnRleHRUeXBlIH0pO1xuICAgICAgICByZXR1cm4geyB1bnN1YnNjcmliZTogYXdhaXQgdGhpcy5jcmVhdGVVbnN1YnNjcmliZUNiKGhhbmRsZXJJZCkgfTtcbiAgICB9XG4gICAgYXN5bmMgY3JlYXRlVW5zdWJzY3JpYmVDYihoYW5kbGVySWQpIHtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQyKHRoaXMsIF9TZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50X2NsaWVudFByb21pc2UsIFwiZlwiKTtcbiAgICAgICAgcmV0dXJuIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNsaWVudC5yZW1vdmUoaGFuZGxlcklkKTtcbiAgICAgICAgICAgIGF3YWl0IGNsaWVudC5kaXNwYXRjaChgc2Vzc2lvbkNvbnRleHRHcm91cDpoYW5kbGVyUmVtb3ZlZC0ke3RoaXMuaWR9YCwgeyBoYW5kbGVySWQgfSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldFVzZXJJbnN0YW5jZSgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGlkOiB0aGlzLmlkLFxuICAgICAgICAgICAgc2V0Q29udGV4dDogKDAsIHV0aWxzXzEkMi53cmFwSW5UcnlDYXRjaCkodGhpcy5zZXRDb250ZXh0LmJpbmQodGhpcyksICdGYWlsZWQgdG8gc2V0IGNvbnRleHQ6ICcpLFxuICAgICAgICAgICAgZ2V0Q3VycmVudENvbnRleHQ6ICgwLCB1dGlsc18xJDIud3JhcEluVHJ5Q2F0Y2gpKHRoaXMuZ2V0Q3VycmVudENvbnRleHQuYmluZCh0aGlzKSwgJ0ZhaWxlZCB0byBnZXQgY29udGV4dDogJyksXG4gICAgICAgICAgICBhZGRDb250ZXh0SGFuZGxlcjogKDAsIHV0aWxzXzEkMi53cmFwSW5UcnlDYXRjaCkodGhpcy5hZGRDb250ZXh0SGFuZGxlci5iaW5kKHRoaXMpLCAnRmFpbGVkIHRvIGFkZCBjb250ZXh0IGhhbmRsZXI6ICcpXG4gICAgICAgIH07XG4gICAgfVxufVxuU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudCQxLmRlZmF1bHQgPSBTZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50O1xuX1Nlc3Npb25Db250ZXh0R3JvdXBDbGllbnRfY2xpZW50UHJvbWlzZSA9IG5ldyBXZWFrTWFwKCk7XG5cbnZhciBmZGMzMV8yID0ge307XG5cbnZhciBmZGMzQ29tbW9uID0ge307XG5cbnZhciB1dGlscyQyID0ge307XG5cbnZhciBQcml2YXRlQ2hhbm5lbENsaWVudCQxID0ge307XG5cbnZhciBfX2NyZWF0ZUJpbmRpbmcgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG4gICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XG4gICAgICBkZXNjID0geyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbVtrXTsgfSB9O1xuICAgIH1cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xufSkgOiAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuICAgIG9bazJdID0gbVtrXTtcbn0pKTtcbnZhciBfX3NldE1vZHVsZURlZmF1bHQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19zZXRNb2R1bGVEZWZhdWx0KSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCB2KSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIFwiZGVmYXVsdFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xufSkgOiBmdW5jdGlvbihvLCB2KSB7XG4gICAgb1tcImRlZmF1bHRcIl0gPSB2O1xufSk7XG52YXIgX19pbXBvcnRTdGFyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9faW1wb3J0U3RhcikgfHwgZnVuY3Rpb24gKG1vZCkge1xuICAgIGlmIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpIHJldHVybiBtb2Q7XG4gICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChrICE9PSBcImRlZmF1bHRcIiAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kLCBrKSkgX19jcmVhdGVCaW5kaW5nKHJlc3VsdCwgbW9kLCBrKTtcbiAgICBfX3NldE1vZHVsZURlZmF1bHQocmVzdWx0LCBtb2QpO1xuICAgIHJldHVybiByZXN1bHQ7XG59O1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KFByaXZhdGVDaGFubmVsQ2xpZW50JDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuUHJpdmF0ZUNoYW5uZWxDbGllbnQkMS5Qcml2YXRlQ2hhbm5lbENsaWVudCA9IHZvaWQgMDtcbmNvbnN0IHV0aWxzJDEgPSBfX2ltcG9ydFN0YXIodXRpbHMkMyk7XG5jbGFzcyBQcml2YXRlQ2hhbm5lbENsaWVudCB7XG4gICAgY29uc3RydWN0b3IoY2xpZW50LCBpZCkge1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIHRoaXMuY2xpZW50ID0gY2xpZW50O1xuICAgICAgICB0aGlzLmxpc3RlbmVycyA9IG5ldyBNYXAoKTtcbiAgICB9XG4gICAgYXN5bmMgYnJvYWRjYXN0KGNvbnRleHQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50LmRpc3BhdGNoKCdicm9hZGNhc3QnLCB7IGNvbnRleHQgfSk7XG4gICAgfVxuICAgIGFzeW5jIGdldEN1cnJlbnRDb250ZXh0KGNvbnRleHRUeXBlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNsaWVudC5kaXNwYXRjaCgnZ2V0Q3VycmVudENvbnRleHQnLCB7IGNvbnRleHRUeXBlIH0pO1xuICAgIH1cbiAgICBhc3luYyBhZGRDb250ZXh0TGlzdGVuZXIoY29udGV4dFR5cGUsIGhhbmRsZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBoYW5kbGVyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOb24tZnVuY3Rpb24gYXJndW1lbnQgcGFzc2VkIHRvIHRoZSBzZWNvbmQgcGFyYW1ldGVyICdoYW5kbGVyJy4gQmUgYXdhcmUgdGhhdCB0aGUgYXJndW1lbnQgb3JkZXIgZG9lcyBub3QgbWF0Y2ggdGhlIEZEQzMgc3RhbmRhcmQuXCIpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBoYW5kbGVySWQ7XG4gICAgICAgIGlmIChjb250ZXh0VHlwZSkge1xuICAgICAgICAgICAgaGFuZGxlcklkID0gYGNvbnRleHRIYW5kbGVyOmludm9rZS0ke3RoaXMuaWR9LSR7Y29udGV4dFR5cGV9LSR7dXRpbHMkMS5nZW5lcmF0ZUlkKCl9YDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGhhbmRsZXJJZCA9IGBjb250ZXh0SGFuZGxlcjppbnZva2UtJHt0aGlzLmlkfS0ke3V0aWxzJDEuZ2VuZXJhdGVJZCgpfWA7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jbGllbnQucmVnaXN0ZXIoaGFuZGxlcklkLCB1dGlscyQxLndyYXBDb250ZXh0SGFuZGxlcihoYW5kbGVyLCBoYW5kbGVySWQpKTtcbiAgICAgICAgY29uc3QgbGlzdGVuZXIgPSB7IHVuc3Vic2NyaWJlOiBhd2FpdCB0aGlzLmNyZWF0ZUNvbnRleHRVbnN1YnNjcmliZUNiKGhhbmRsZXJJZCkgfTtcbiAgICAgICAgdGhpcy5saXN0ZW5lcnMuc2V0KGhhbmRsZXJJZCwgbGlzdGVuZXIpO1xuICAgICAgICBhd2FpdCB0aGlzLmNsaWVudC5kaXNwYXRjaChgY29udGV4dEhhbmRsZXJBZGRlZGAsIHsgaGFuZGxlcklkLCBjb250ZXh0VHlwZSB9KTtcbiAgICAgICAgcmV0dXJuIGxpc3RlbmVyO1xuICAgIH1cbiAgICBjcmVhdGVOb25TdGFuZGFyZFVuc3Vic2NyaWJlQ2IoaGFuZGxlcklkKSB7XG4gICAgICAgIHJldHVybiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNsaWVudC5yZW1vdmUoaGFuZGxlcklkKTtcbiAgICAgICAgICAgIHRoaXMubGlzdGVuZXJzLmRlbGV0ZShoYW5kbGVySWQpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jbGllbnQuZGlzcGF0Y2goJ25vblN0YW5kYXJkSGFuZGxlclJlbW92ZWQnLCB7IGhhbmRsZXJJZCB9KTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgY3JlYXRlQ29udGV4dFVuc3Vic2NyaWJlQ2IoaGFuZGxlcklkKSB7XG4gICAgICAgIHJldHVybiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNsaWVudC5yZW1vdmUoaGFuZGxlcklkKTtcbiAgICAgICAgICAgIHRoaXMubGlzdGVuZXJzLmRlbGV0ZShoYW5kbGVySWQpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jbGllbnQuZGlzcGF0Y2goJ2NvbnRleHRIYW5kbGVyUmVtb3ZlZCcsIHsgaGFuZGxlcklkIH0pO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBvbkFkZENvbnRleHRMaXN0ZW5lcihoYW5kbGVyKSB7XG4gICAgICAgIGNvbnN0IGhhbmRsZXJJZCA9IGBvbkNvbnRleHRIYW5kbGVyQWRkZWQ6aW52b2tlLSR7dGhpcy5pZH0tJHt1dGlscyQxLmdlbmVyYXRlSWQoKX1gO1xuICAgICAgICB0aGlzLmNsaWVudC5yZWdpc3RlcihoYW5kbGVySWQsIGhhbmRsZXIpO1xuICAgICAgICBjb25zdCBsaXN0ZW5lciA9IHsgdW5zdWJzY3JpYmU6IHRoaXMuY3JlYXRlTm9uU3RhbmRhcmRVbnN1YnNjcmliZUNiKGhhbmRsZXJJZCkgfTtcbiAgICAgICAgdGhpcy5saXN0ZW5lcnMuc2V0KGhhbmRsZXJJZCwgbGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmNsaWVudC5kaXNwYXRjaChgb25BZGRDb250ZXh0SGFuZGxlckFkZGVkYCwgeyBoYW5kbGVySWQgfSk7XG4gICAgICAgIHJldHVybiBsaXN0ZW5lcjtcbiAgICB9XG4gICAgb25EaXNjb25uZWN0KGhhbmRsZXIpIHtcbiAgICAgICAgY29uc3QgaGFuZGxlcklkID0gYG9uRGlzY29ubmVjdDppbnZva2UtJHt0aGlzLmlkfS0ke3V0aWxzJDEuZ2VuZXJhdGVJZCgpfWA7XG4gICAgICAgIHRoaXMuY2xpZW50LnJlZ2lzdGVyKGhhbmRsZXJJZCwgaGFuZGxlcik7XG4gICAgICAgIGNvbnN0IGxpc3RlbmVyID0geyB1bnN1YnNjcmliZTogdGhpcy5jcmVhdGVOb25TdGFuZGFyZFVuc3Vic2NyaWJlQ2IoaGFuZGxlcklkKSB9O1xuICAgICAgICB0aGlzLmxpc3RlbmVycy5zZXQoaGFuZGxlcklkLCBsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuY2xpZW50LmRpc3BhdGNoKGBvbkRpc2Nvbm5lY3RIYW5kbGVyQWRkZWRgLCB7IGhhbmRsZXJJZCB9KTtcbiAgICAgICAgcmV0dXJuIGxpc3RlbmVyO1xuICAgIH1cbiAgICBvblVuc3Vic2NyaWJlKGhhbmRsZXIpIHtcbiAgICAgICAgY29uc3QgaGFuZGxlcklkID0gYG9uVW5zdWJzY3JpYmU6aW52b2tlLSR7dGhpcy5pZH0tJHt1dGlscyQxLmdlbmVyYXRlSWQoKX1gO1xuICAgICAgICB0aGlzLmNsaWVudC5yZWdpc3RlcihoYW5kbGVySWQsIGhhbmRsZXIpO1xuICAgICAgICBjb25zdCBsaXN0ZW5lciA9IHsgdW5zdWJzY3JpYmU6IHRoaXMuY3JlYXRlTm9uU3RhbmRhcmRVbnN1YnNjcmliZUNiKGhhbmRsZXJJZCkgfTtcbiAgICAgICAgdGhpcy5saXN0ZW5lcnMuc2V0KGhhbmRsZXJJZCwgbGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmNsaWVudC5kaXNwYXRjaChgb25VbnN1YnNjcmliZUhhbmRsZXJBZGRlZGAsIHsgaGFuZGxlcklkIH0pO1xuICAgICAgICByZXR1cm4gbGlzdGVuZXI7XG4gICAgfVxuICAgIGFzeW5jIGNsZWFuVXBBbGxTdWJzKCkge1xuICAgICAgICBjb25zdCBsaXN0ZW5lclVuc3Vic2NyaWJlcnMgPSBBcnJheS5mcm9tKHRoaXMubGlzdGVuZXJzLmtleXMoKSk7XG4gICAgICAgIGxpc3RlbmVyVW5zdWJzY3JpYmVycy5mb3JFYWNoKChoYW5kbGVySWQpID0+IHtcbiAgICAgICAgICAgIHRoaXMuY2xpZW50LnJlbW92ZShoYW5kbGVySWQpO1xuICAgICAgICAgICAgdGhpcy5saXN0ZW5lcnMuZGVsZXRlKGhhbmRsZXJJZCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBhc3luYyBkaXNjb25uZWN0KCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jbGllbnQuZGlzcGF0Y2goJ2NsaWVudERpc2Nvbm5lY3RpbmcnKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2xlYW5VcEFsbFN1YnMoKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2xpZW50LmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvci5tZXNzYWdlKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblByaXZhdGVDaGFubmVsQ2xpZW50JDEuUHJpdmF0ZUNoYW5uZWxDbGllbnQgPSBQcml2YXRlQ2hhbm5lbENsaWVudDtcblxuKGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdHZhciBfX2ltcG9ydERlZmF1bHQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19pbXBvcnREZWZhdWx0KSB8fCBmdW5jdGlvbiAobW9kKSB7XG5cdCAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IFwiZGVmYXVsdFwiOiBtb2QgfTtcblx0fTtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRleHBvcnRzLmdldEludGVudFJlc29sdXRpb24gPSBleHBvcnRzLmlzQ2hhbm5lbCA9IGV4cG9ydHMuaXNDb250ZXh0ID0gZXhwb3J0cy5jb25uZWN0UHJpdmF0ZUNoYW5uZWwgPSBleHBvcnRzLmJ1aWxkQXBwQ2hhbm5lbE9iamVjdCA9IGV4cG9ydHMuYnVpbGRQcml2YXRlQ2hhbm5lbE9iamVjdCA9IGV4cG9ydHMuQ2hhbm5lbEVycm9yID0gZXhwb3J0cy5SZXN1bHRFcnJvciA9IGV4cG9ydHMuVW5zdXBwb3J0ZWRDaGFubmVsQXBpRXJyb3IgPSBleHBvcnRzLmdldFVuc3VwcG9ydGVkQ2hhbm5lbEFwaXMgPSB2b2lkIDA7XG5cdGNvbnN0IHV0aWxzXzEgPSB1dGlscyQzO1xuXHRjb25zdCBQcml2YXRlQ2hhbm5lbENsaWVudF8xID0gUHJpdmF0ZUNoYW5uZWxDbGllbnQkMTtcblx0Y29uc3QgaXNFcXVhbF8xID0gX19pbXBvcnREZWZhdWx0KHJlcXVpcmUkJDMpO1xuXHRjb25zdCBnZXRVbnN1cHBvcnRlZENoYW5uZWxBcGlzID0gKGNoYW5uZWxUeXBlKSA9PiB7XG5cdCAgICByZXR1cm4ge1xuXHQgICAgICAgIGFkZENvbnRleHRMaXN0ZW5lcjogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRDaGFubmVsQXBpRXJyb3IoJ0NoYW5uZWwuYWRkQ29udGV4dExpc3RlbmVyJywgY2hhbm5lbFR5cGUpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgYnJvYWRjYXN0OiAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBVbnN1cHBvcnRlZENoYW5uZWxBcGlFcnJvcignQ2hhbm5lbC5icm9hZGNhc3QnLCBjaGFubmVsVHlwZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBnZXRDdXJyZW50Q29udGV4dDogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRDaGFubmVsQXBpRXJyb3IoJ0NoYW5uZWwuZ2V0Q3VycmVudENvbnRleHQnLCBjaGFubmVsVHlwZSk7XG5cdCAgICAgICAgfVxuXHQgICAgfTtcblx0fTtcblx0ZXhwb3J0cy5nZXRVbnN1cHBvcnRlZENoYW5uZWxBcGlzID0gZ2V0VW5zdXBwb3J0ZWRDaGFubmVsQXBpcztcblx0Y2xhc3MgVW5zdXBwb3J0ZWRDaGFubmVsQXBpRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG5cdCAgICBjb25zdHJ1Y3RvcihhcGlOYW1lLCBjaGFubmVsVHlwZSA9ICdTeXN0ZW0nKSB7XG5cdCAgICAgICAgc3VwZXIoYXBpTmFtZSk7XG5cdCAgICAgICAgdGhpcy5tZXNzYWdlID0gYENhbGxpbmcgJHthcGlOYW1lfSBvbiBhbiBpbnN0YW5jZSBvZiBhICR7Y2hhbm5lbFR5cGV9IENoYW5uZWwgcmV0dXJuZWQgYnkgZmRjMy5nZXQke2NoYW5uZWxUeXBlfUNoYW5uZWxzIGlzIG5vdCBzdXBwb3J0ZWQuIElmIHlvdSB3b3VsZCBsaWtlIHRvIHVzZSBhICR7Y2hhbm5lbFR5cGV9IENoYW5uZWwsIHBsZWFzZSB1c2UgZmRjMy5qb2luQ2hhbm5lbCwgZmRjMy5hZGRDb250ZXh0TGlzdGVuZXIsIGFuZCBmZGMzLmJyb2FkY2FzdCBpbnN0ZWFkLmA7XG5cdCAgICB9XG5cdH1cblx0ZXhwb3J0cy5VbnN1cHBvcnRlZENoYW5uZWxBcGlFcnJvciA9IFVuc3VwcG9ydGVkQ2hhbm5lbEFwaUVycm9yO1xuXHR2YXIgUmVzdWx0RXJyb3I7XG5cdChmdW5jdGlvbiAoUmVzdWx0RXJyb3IpIHtcblx0ICAgIC8qKiBSZXR1cm5lZCBpZiB0aGUgYEludGVudEhhbmRsZXJgIGV4aXRlZCB3aXRob3V0IHJldHVybmluZyBhIFByb21pc2Ugb3IgdGhhdFxuXHQgICAgICogIFByb21pc2Ugd2FzIG5vdCByZXNvbHZlZCB3aXRoIGEgQ29udGV4dCBvciBDaGFubmVsIG9iamVjdC5cblx0ICAgICAqL1xuXHQgICAgUmVzdWx0RXJyb3JbXCJOb1Jlc3VsdFJldHVybmVkXCJdID0gXCJOb1Jlc3VsdFJldHVybmVkXCI7XG5cdCAgICAvKiogUmV0dXJuZWQgaWYgdGhlIGBJbnRlbnRIYW5kbGVyYCBmdW5jdGlvbiBwcm9jZXNzaW5nIHRoZSByYWlzZWQgaW50ZW50XG5cdCAgICAgKiAgdGhyb3dzIGFuIGVycm9yIG9yIHJlamVjdHMgdGhlIFByb21pc2UgaXQgcmV0dXJuZWQuXG5cdCAgICAgKi9cblx0ICAgIFJlc3VsdEVycm9yW1wiSW50ZW50SGFuZGxlclJlamVjdGVkXCJdID0gXCJJbnRlbnRIYW5kbGVyUmVqZWN0ZWRcIjtcblx0fSkoUmVzdWx0RXJyb3IgPSBleHBvcnRzLlJlc3VsdEVycm9yIHx8IChleHBvcnRzLlJlc3VsdEVycm9yID0ge30pKTtcblx0KGZ1bmN0aW9uIChDaGFubmVsRXJyb3IpIHtcblx0ICAgIC8qKiBSZXR1cm5lZCBpZiB0aGUgc3BlY2lmaWVkIGNoYW5uZWwgaXMgbm90IGZvdW5kIHdoZW4gYXR0ZW1wdGluZyB0byBqb2luIGFcblx0ICAgICAqICBjaGFubmVsIHZpYSB0aGUgYGpvaW5Vc2VyQ2hhbm5lbGAgZnVuY3Rpb24gb2YgdGhlIERlc2t0b3BBZ2VudCAoYGZkYzNgKS5cblx0ICAgICAqL1xuXHQgICAgQ2hhbm5lbEVycm9yW1wiTm9DaGFubmVsRm91bmRcIl0gPSBcIk5vQ2hhbm5lbEZvdW5kXCI7XG5cdCAgICAvKiogU0hPVUxEIGJlIHJldHVybmVkIHdoZW4gYSByZXF1ZXN0IHRvIGpvaW4gYSB1c2VyIGNoYW5uZWwgb3IgdG8gYSByZXRyaWV2ZVxuXHQgICAgICogIGEgQ2hhbm5lbCBvYmplY3QgdmlhIHRoZSBgam9pblVzZXJDaGFubmVsYCBvciBgZ2V0T3JDcmVhdGVDaGFubmVsYCBtZXRob2RzXG5cdCAgICAgKiAgb2YgdGhlIERlc2t0b3BBZ2VudCAoYGZkYzNgKSBvYmplY3QgaXMgZGVuaWVkLlxuXHQgICAgICovXG5cdCAgICBDaGFubmVsRXJyb3JbXCJBY2Nlc3NEZW5pZWRcIl0gPSBcIkFjY2Vzc0RlbmllZFwiO1xuXHQgICAgLyoqIFNIT1VMRCBiZSByZXR1cm5lZCB3aGVuIGEgY2hhbm5lbCBjYW5ub3QgYmUgY3JlYXRlZCBvciByZXRyaWV2ZWQgdmlhIHRoZVxuXHQgICAgICogIGBnZXRPckNyZWF0ZUNoYW5uZWxgIG1ldGhvZCBvZiB0aGUgRGVza3RvcEFnZW50IChgZmRjM2ApLlxuXHQgICAgICovXG5cdCAgICBDaGFubmVsRXJyb3JbXCJDcmVhdGlvbkZhaWxlZFwiXSA9IFwiQ3JlYXRpb25GYWlsZWRcIjtcblx0fSkoZXhwb3J0cy5DaGFubmVsRXJyb3IgfHwgKGV4cG9ydHMuQ2hhbm5lbEVycm9yID0ge30pKTtcblx0Y29uc3QgYnVpbGRQcml2YXRlQ2hhbm5lbE9iamVjdCA9IChwcml2YXRlQ2hhbm5lbENsaWVudCkgPT4ge1xuXHQgICAgbGV0IGNsaWVudERpc2Nvbm5lY3RlZCA9IGZhbHNlO1xuXHQgICAgY29uc3QgY2hlY2tJZkNsaWVudERpc2Nvbm5lY3RlZCA9ICgpID0+IHtcblx0ICAgICAgICBpZiAoY2xpZW50RGlzY29ubmVjdGVkKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUHJpdmF0ZSBDaGFubmVsIENsaWVudCBoYXMgYmVlbiBkaXNjb25uZWN0ZWQgZnJvbSB0aGUgUHJpdmF0ZSBDaGFubmVsJyk7XG5cdCAgICAgICAgfVxuXHQgICAgfTtcblx0ICAgIHJldHVybiB7XG5cdCAgICAgICAgaWQ6IHByaXZhdGVDaGFubmVsQ2xpZW50LmlkLFxuXHQgICAgICAgIHR5cGU6ICdwcml2YXRlJyxcblx0ICAgICAgICBicm9hZGNhc3Q6IGFzeW5jIChjb250ZXh0KSA9PiB7XG5cdCAgICAgICAgICAgIGNoZWNrSWZDbGllbnREaXNjb25uZWN0ZWQoKTtcblx0ICAgICAgICAgICAgcmV0dXJuIHByaXZhdGVDaGFubmVsQ2xpZW50LmJyb2FkY2FzdChjb250ZXh0KTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGdldEN1cnJlbnRDb250ZXh0OiBhc3luYyAoY29udGV4dFR5cGUpID0+IHtcblx0ICAgICAgICAgICAgY2hlY2tJZkNsaWVudERpc2Nvbm5lY3RlZCgpO1xuXHQgICAgICAgICAgICByZXR1cm4gcHJpdmF0ZUNoYW5uZWxDbGllbnQuZ2V0Q3VycmVudENvbnRleHQoY29udGV4dFR5cGUpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBUT0RPIFtDT1JFLTE1MjRdXG5cdCAgICAgICAgYWRkQ29udGV4dExpc3RlbmVyOiBhc3luYyAoY29udGV4dFR5cGUsIGhhbmRsZXIpID0+IHtcblx0ICAgICAgICAgICAgY2hlY2tJZkNsaWVudERpc2Nvbm5lY3RlZCgpO1xuXHQgICAgICAgICAgICBsZXQgaGFuZGxlckluVXNlID0gaGFuZGxlcjtcblx0ICAgICAgICAgICAgbGV0IGNvbnRleHRUeXBlSW5Vc2UgPSBjb250ZXh0VHlwZTtcblx0ICAgICAgICAgICAgaWYgKHR5cGVvZiBjb250ZXh0VHlwZSA9PT0gJ2Z1bmN0aW9uJykge1xuXHQgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdhZGRDb250ZXh0TGlzdGVuZXIoaGFuZGxlcikgaGFzIGJlZW4gZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBhZGRDb250ZXh0TGlzdGVuZXIobnVsbCwgaGFuZGxlciknKTtcblx0ICAgICAgICAgICAgICAgIGhhbmRsZXJJblVzZSA9IGNvbnRleHRUeXBlO1xuXHQgICAgICAgICAgICAgICAgY29udGV4dFR5cGVJblVzZSA9IG51bGw7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgY29uc3QgbGlzdGVuZXIgPSBwcml2YXRlQ2hhbm5lbENsaWVudC5hZGRDb250ZXh0TGlzdGVuZXIoY29udGV4dFR5cGVJblVzZSwgaGFuZGxlckluVXNlKTtcblx0ICAgICAgICAgICAgcmV0dXJuIGxpc3RlbmVyO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgb25BZGRDb250ZXh0TGlzdGVuZXI6IChoYW5kbGVyKSA9PiB7XG5cdCAgICAgICAgICAgIGNoZWNrSWZDbGllbnREaXNjb25uZWN0ZWQoKTtcblx0ICAgICAgICAgICAgcmV0dXJuIHByaXZhdGVDaGFubmVsQ2xpZW50Lm9uQWRkQ29udGV4dExpc3RlbmVyKGhhbmRsZXIpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgZGlzY29ubmVjdDogYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICBjaGVja0lmQ2xpZW50RGlzY29ubmVjdGVkKCk7XG5cdCAgICAgICAgICAgIGNsaWVudERpc2Nvbm5lY3RlZCA9IHRydWU7XG5cdCAgICAgICAgICAgIHJldHVybiBwcml2YXRlQ2hhbm5lbENsaWVudC5kaXNjb25uZWN0KCk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBvbkRpc2Nvbm5lY3Q6IChoYW5kbGVyKSA9PiB7XG5cdCAgICAgICAgICAgIGNoZWNrSWZDbGllbnREaXNjb25uZWN0ZWQoKTtcblx0ICAgICAgICAgICAgcmV0dXJuIHByaXZhdGVDaGFubmVsQ2xpZW50Lm9uRGlzY29ubmVjdChoYW5kbGVyKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIG9uVW5zdWJzY3JpYmU6IChoYW5kbGVyKSA9PiB7XG5cdCAgICAgICAgICAgIGNoZWNrSWZDbGllbnREaXNjb25uZWN0ZWQoKTtcblx0ICAgICAgICAgICAgcmV0dXJuIHByaXZhdGVDaGFubmVsQ2xpZW50Lm9uVW5zdWJzY3JpYmUoaGFuZGxlcik7XG5cdCAgICAgICAgfVxuXHQgICAgfTtcblx0fTtcblx0ZXhwb3J0cy5idWlsZFByaXZhdGVDaGFubmVsT2JqZWN0ID0gYnVpbGRQcml2YXRlQ2hhbm5lbE9iamVjdDtcblx0Y29uc3QgYnVpbGRBcHBDaGFubmVsT2JqZWN0ID0gKHNlc3Npb25Db250ZXh0R3JvdXApID0+IHtcblx0ICAgIHJldHVybiB7XG5cdCAgICAgICAgaWQ6IHNlc3Npb25Db250ZXh0R3JvdXAuaWQsXG5cdCAgICAgICAgdHlwZTogJ2FwcCcsXG5cdCAgICAgICAgYnJvYWRjYXN0OiBzZXNzaW9uQ29udGV4dEdyb3VwLnNldENvbnRleHQsXG5cdCAgICAgICAgZ2V0Q3VycmVudENvbnRleHQ6IGFzeW5jIChjb250ZXh0VHlwZSkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgc2Vzc2lvbkNvbnRleHRHcm91cC5nZXRDdXJyZW50Q29udGV4dChjb250ZXh0VHlwZSk7XG5cdCAgICAgICAgICAgIHJldHVybiBjb250ZXh0ID09PSB1bmRlZmluZWQgPyBudWxsIDogY29udGV4dDtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgVE9ETyBbQ09SRS0xNTI0XVxuXHQgICAgICAgIGFkZENvbnRleHRMaXN0ZW5lcjogKGNvbnRleHRUeXBlLCBoYW5kbGVyKSA9PiB7XG5cdCAgICAgICAgICAgIGxldCByZWFsSGFuZGxlcjtcblx0ICAgICAgICAgICAgbGV0IHJlYWxUeXBlO1xuXHQgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnRleHRUeXBlID09PSAnZnVuY3Rpb24nKSB7XG5cdCAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2FkZENvbnRleHRMaXN0ZW5lcihoYW5kbGVyKSBoYXMgYmVlbiBkZXByZWNhdGVkLiBQbGVhc2UgdXNlIGFkZENvbnRleHRMaXN0ZW5lcihudWxsLCBoYW5kbGVyKScpO1xuXHQgICAgICAgICAgICAgICAgcmVhbEhhbmRsZXIgPSBjb250ZXh0VHlwZTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgICAgIHJlYWxIYW5kbGVyID0gaGFuZGxlcjtcblx0ICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGV4dFR5cGUgPT09ICdzdHJpbmcnKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgcmVhbFR5cGUgPSBjb250ZXh0VHlwZTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IChhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgICAgICBsZXQgZmlyc3QgPSB0cnVlO1xuXHQgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudENvbnRleHQgPSBhd2FpdCBzZXNzaW9uQ29udGV4dEdyb3VwLmdldEN1cnJlbnRDb250ZXh0KHJlYWxUeXBlKTtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IHdyYXBwZWRIYW5kbGVyID0gKGNvbnRleHQsIGNvbnRleHRNZXRhZGF0YSkgPT4ge1xuXHQgICAgICAgICAgICAgICAgICAgIGlmIChmaXJzdCkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICBmaXJzdCA9IGZhbHNlO1xuXHQgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKDAsIGlzRXF1YWxfMS5kZWZhdWx0KShjdXJyZW50Q29udGV4dCwgY29udGV4dCkpIHtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29uc2lzdGVudC1yZXR1cm5cblx0ICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVhbEhhbmRsZXIoY29udGV4dCwgY29udGV4dE1ldGFkYXRhKTtcblx0ICAgICAgICAgICAgICAgIH07XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gc2Vzc2lvbkNvbnRleHRHcm91cC5hZGRDb250ZXh0SGFuZGxlcih3cmFwcGVkSGFuZGxlciwgcmVhbFR5cGUpO1xuXHQgICAgICAgICAgICB9KSgpO1xuXHQgICAgICAgICAgICByZXR1cm4ge1xuXHQgICAgICAgICAgICAgICAgLi4ubGlzdGVuZXIsXG5cdCAgICAgICAgICAgICAgICB1bnN1YnNjcmliZTogKCkgPT4gbGlzdGVuZXIudGhlbigobCkgPT4gbC51bnN1YnNjcmliZSgpKVxuXHQgICAgICAgICAgICB9O1xuXHQgICAgICAgIH1cblx0ICAgIH07XG5cdH07XG5cdGV4cG9ydHMuYnVpbGRBcHBDaGFubmVsT2JqZWN0ID0gYnVpbGRBcHBDaGFubmVsT2JqZWN0O1xuXHRjb25zdCBjb25uZWN0UHJpdmF0ZUNoYW5uZWwgPSBhc3luYyAoY2hhbm5lbElkKSA9PiB7XG5cdCAgICB0cnkge1xuXHQgICAgICAgIGNvbnN0IGNoYW5uZWxDbGllbnQgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3QoY2hhbm5lbElkKTtcblx0ICAgICAgICBjb25zdCBwcml2YXRlQ2hhbm5lbENsaWVudCA9IG5ldyBQcml2YXRlQ2hhbm5lbENsaWVudF8xLlByaXZhdGVDaGFubmVsQ2xpZW50KGNoYW5uZWxDbGllbnQsIGNoYW5uZWxJZCk7XG5cdCAgICAgICAgcmV0dXJuICgwLCBleHBvcnRzLmJ1aWxkUHJpdmF0ZUNoYW5uZWxPYmplY3QpKHByaXZhdGVDaGFubmVsQ2xpZW50KTtcblx0ICAgIH1cblx0ICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgIHRocm93IG5ldyBFcnJvcihgUHJpdmF0ZSBDaGFubmVsIHdpdGggaWQ6ICR7Y2hhbm5lbElkfSBkb2Vzbid0IGV4aXN0YCk7XG5cdCAgICB9XG5cdH07XG5cdGV4cG9ydHMuY29ubmVjdFByaXZhdGVDaGFubmVsID0gY29ubmVjdFByaXZhdGVDaGFubmVsO1xuXHRjb25zdCBpc0NvbnRleHQgPSAoY29udGV4dCkgPT4ge1xuXHQgICAgaWYgKGNvbnRleHQgJiYgdHlwZW9mIGNvbnRleHQgPT09ICdvYmplY3QnICYmICd0eXBlJyBpbiBjb250ZXh0KSB7XG5cdCAgICAgICAgY29uc3QgeyB0eXBlIH0gPSBjb250ZXh0O1xuXHQgICAgICAgIHJldHVybiB0eXBlb2YgdHlwZSA9PT0gJ3N0cmluZyc7XG5cdCAgICB9XG5cdCAgICByZXR1cm4gZmFsc2U7XG5cdH07XG5cdGV4cG9ydHMuaXNDb250ZXh0ID0gaXNDb250ZXh0O1xuXHRjb25zdCBpc0NoYW5uZWwgPSAoY2hhbm5lbCkgPT4ge1xuXHQgICAgaWYgKGNoYW5uZWwgJiYgdHlwZW9mIGNoYW5uZWwgPT09ICdvYmplY3QnICYmICd0eXBlJyBpbiBjaGFubmVsICYmICdpZCcgaW4gY2hhbm5lbCkge1xuXHQgICAgICAgIGNvbnN0IHsgdHlwZSwgaWQgfSA9IGNoYW5uZWw7XG5cdCAgICAgICAgcmV0dXJuIHR5cGVvZiB0eXBlID09PSAnc3RyaW5nJyAmJiB0eXBlb2YgaWQgPT09ICdzdHJpbmcnICYmICh0eXBlID09PSAnYXBwJyB8fCB0eXBlID09PSAncHJpdmF0ZScpO1xuXHQgICAgfVxuXHQgICAgcmV0dXJuIGZhbHNlO1xuXHR9O1xuXHRleHBvcnRzLmlzQ2hhbm5lbCA9IGlzQ2hhbm5lbDtcblx0Y29uc3QgZ2V0SW50ZW50UmVzb2x1dGlvbiA9IGFzeW5jIChpbnRlcm9wTW9kdWxlLCBjb250ZXh0LCBhcHAsIGludGVudCkgPT4ge1xuXHQgICAgLy8gR2VuZXJhdGUgYW4gSUQgdG8gbWFrZSBhIHNlc3Npb24gY29udGV4dCBncm91cCB3aXRoLiBXZSB3aWxsIHBhc3MgdGhhdCBJRCB0byB0aGUgQnJva2VyLlxuXHQgICAgLy8gVGhlIGJyb2tlciB3aWxsIHRoZW4gc2V0Q29udGV4dCBvbiB0aGF0IHNlc3Npb24gY29udGV4dCBncm91cCBsYXRlciB3aXRoIG91ciBJbnRlbnQgUmVzdWx0LFxuXHQgICAgY29uc3QgZ3VpZCA9ICgwLCB1dGlsc18xLmdlbmVyYXRlSWQpKCk7IC8vIFRPRE8gbWFrZSB0aGlzIHVuZGVmaW5lZCBpbiB3ZWJcblx0ICAgIC8vIFByb21pc2Ugd2UnbGwgdXNlIGluIGdldFJlc3VsdFxuXHQgICAgY29uc3QgZ2V0UmVzdWx0UHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcblx0ICAgICAgICBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5zdWJzY3JpYmUoeyB1dWlkOiAnKicgfSwgZ3VpZCwgKGludGVudFJlc3VsdCkgPT4ge1xuXHQgICAgICAgICAgICByZXNvbHZlKGludGVudFJlc3VsdCk7XG5cdCAgICAgICAgfSkuY2F0Y2goKCkgPT4gcmVqZWN0KG5ldyBFcnJvcignZ2V0UmVzdWx0IGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhpcyBlbnZpcm9ubWVudCcpKSk7XG5cdCAgICB9KTtcblx0ICAgIC8vIEFkZGluZyB0aGUgaW50ZW50UmVzb2x1dGlvblJlc3VsdElkIHRvIHRoZSBpbnRlbnRPYmouIEJlY2F1c2UgZmlyZUludGVudCBvbmx5IGFjY2VwdHMgYSBzaW5nbGUgYXJnLCB3ZSBoYXZlIHRvIHNsYXAgaXQgaW4gaGVyZS5cblx0ICAgIGNvbnN0IG1ldGFkYXRhID0gYXBwID8geyB0YXJnZXQ6IGFwcCwgaW50ZW50UmVzb2x1dGlvblJlc3VsdElkOiBndWlkIH0gOiB7IGludGVudFJlc29sdXRpb25SZXN1bHRJZDogZ3VpZCB9O1xuXHQgICAgY29uc3QgaW50ZW50T2JqID0gaW50ZW50ID8geyBuYW1lOiBpbnRlbnQsIGNvbnRleHQsIG1ldGFkYXRhIH0gOiB7IC4uLmNvbnRleHQsIG1ldGFkYXRhIH07XG5cdCAgICAvLyBTZXQgdXAgdGhlIGdldFJlc3VsdCBjYWxsLlxuXHQgICAgY29uc3QgZ2V0UmVzdWx0ID0gYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgIGxldCBpbnRlbnRSZXN1bHQgPSBhd2FpdCBnZXRSZXN1bHRQcm9taXNlO1xuXHQgICAgICAgIGlmICghaW50ZW50UmVzdWx0IHx8IHR5cGVvZiBpbnRlbnRSZXN1bHQgIT09ICdvYmplY3QnKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihSZXN1bHRFcnJvci5Ob1Jlc3VsdFJldHVybmVkKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3QgeyBlcnJvciB9ID0gaW50ZW50UmVzdWx0O1xuXHQgICAgICAgIGlmIChlcnJvcikge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoUmVzdWx0RXJyb3IuSW50ZW50SGFuZGxlclJlamVjdGVkKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgaWYgKCgwLCBleHBvcnRzLmlzQ2hhbm5lbCkoaW50ZW50UmVzdWx0KSkge1xuXHQgICAgICAgICAgICBjb25zdCB7IGlkLCB0eXBlIH0gPSBpbnRlbnRSZXN1bHQ7XG5cdCAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuXHQgICAgICAgICAgICAgICAgY2FzZSAncHJpdmF0ZSc6IHtcblx0ICAgICAgICAgICAgICAgICAgICBpbnRlbnRSZXN1bHQgPSBhd2FpdCAoMCwgZXhwb3J0cy5jb25uZWN0UHJpdmF0ZUNoYW5uZWwpKGlkKTtcblx0ICAgICAgICAgICAgICAgICAgICBicmVhaztcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIGNhc2UgJ2FwcCc6IHtcblx0ICAgICAgICAgICAgICAgICAgICBjb25zdCBzZXNzaW9uQ29udGV4dEdyb3VwID0gYXdhaXQgaW50ZXJvcE1vZHVsZS5qb2luU2Vzc2lvbkNvbnRleHRHcm91cChpZCk7XG5cdCAgICAgICAgICAgICAgICAgICAgaW50ZW50UmVzdWx0ID0gKDAsIGV4cG9ydHMuYnVpbGRBcHBDaGFubmVsT2JqZWN0KShzZXNzaW9uQ29udGV4dEdyb3VwKTtcblx0ICAgICAgICAgICAgICAgICAgICBicmVhaztcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIGlmICghKDAsIGV4cG9ydHMuaXNDb250ZXh0KShpbnRlbnRSZXN1bHQpKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihSZXN1bHRFcnJvci5Ob1Jlc3VsdFJldHVybmVkKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIGludGVudFJlc3VsdDtcblx0ICAgIH07XG5cdCAgICAvLyBGaW5hbGx5IGZpcmUgdGhlIGludGVudC5cblx0ICAgIGNvbnN0IGludGVudFJlc29sdXRpb25JbmZvRnJvbUJyb2tlciA9IGludGVudFxuXHQgICAgICAgID8gYXdhaXQgaW50ZXJvcE1vZHVsZS5maXJlSW50ZW50KGludGVudE9iailcblx0ICAgICAgICA6IGF3YWl0IGludGVyb3BNb2R1bGUuZmlyZUludGVudEZvckNvbnRleHQoaW50ZW50T2JqKTtcblx0ICAgIGlmICh0eXBlb2YgaW50ZW50UmVzb2x1dGlvbkluZm9Gcm9tQnJva2VyICE9PSAnb2JqZWN0Jykge1xuXHQgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgIHNvdXJjZToge1xuXHQgICAgICAgICAgICAgICAgYXBwSWQ6ICcnLFxuXHQgICAgICAgICAgICAgICAgaW5zdGFuY2VJZDogJydcblx0ICAgICAgICAgICAgfSxcblx0ICAgICAgICAgICAgaW50ZW50OiAnJyxcblx0ICAgICAgICAgICAgdmVyc2lvbjogJzIuMCcsXG5cdCAgICAgICAgICAgIGdldFJlc3VsdFxuXHQgICAgICAgIH07XG5cdCAgICB9XG5cdCAgICByZXR1cm4geyAuLi5pbnRlbnRSZXNvbHV0aW9uSW5mb0Zyb21Ccm9rZXIsIGdldFJlc3VsdCB9O1xuXHR9O1xuXHRleHBvcnRzLmdldEludGVudFJlc29sdXRpb24gPSBnZXRJbnRlbnRSZXNvbHV0aW9uOyBcbn0gKHV0aWxzJDIpKTtcblxudmFyIGhhc1JlcXVpcmVkRmRjM0NvbW1vbjtcblxuZnVuY3Rpb24gcmVxdWlyZUZkYzNDb21tb24gKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRGZGMzQ29tbW9uKSByZXR1cm4gZmRjM0NvbW1vbjtcblx0aGFzUmVxdWlyZWRGZGMzQ29tbW9uID0gMTtcblx0dmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuXHQgICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuXHQgICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG5cdCAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xuXHR9O1xuXHR2YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xuXHQgICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuXHQgICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuXHQgICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcblx0ICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xuXHR9O1xuXHR2YXIgX19pbXBvcnREZWZhdWx0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9faW1wb3J0RGVmYXVsdCkgfHwgZnVuY3Rpb24gKG1vZCkge1xuXHQgICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBcImRlZmF1bHRcIjogbW9kIH07XG5cdH07XG5cdHZhciBfRkRDM01vZHVsZUJhc2VfcHJvZHVjZXI7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmZGMzQ29tbW9uLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0ZmRjM0NvbW1vbi5GREMzTW9kdWxlQmFzZSA9IHZvaWQgMDtcblx0Y29uc3QgdXRpbHNfMSA9IHV0aWxzJDI7XG5cdGNvbnN0IHV0aWxzXzIgPSB1dGlscyQzO1xuXHRjb25zdCBJbnRlcm9wQ2xpZW50XzEgPSByZXF1aXJlSW50ZXJvcENsaWVudCgpO1xuXHRjb25zdCBpc0VxdWFsXzEgPSBfX2ltcG9ydERlZmF1bHQocmVxdWlyZSQkMyk7XG5cdGNsYXNzIEZEQzNNb2R1bGVCYXNlIHtcblx0ICAgIGdldCBjbGllbnQoKSB7XG5cdCAgICAgICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ZEQzNNb2R1bGVCYXNlX3Byb2R1Y2VyLCBcImZcIikuY2FsbCh0aGlzKTtcblx0ICAgIH1cblx0ICAgIGdldCBmaW4oKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5nZXRGaW4oKTtcblx0ICAgIH1cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11c2VsZXNzLWNvbnN0cnVjdG9yXG5cdCAgICBjb25zdHJ1Y3Rvcihwcm9kdWNlciwgd2lyZSkge1xuXHQgICAgICAgIHRoaXMud2lyZSA9IHdpcmU7XG5cdCAgICAgICAgX0ZEQzNNb2R1bGVCYXNlX3Byb2R1Y2VyLnNldCh0aGlzLCB2b2lkIDApO1xuXHQgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX0ZEQzNNb2R1bGVCYXNlX3Byb2R1Y2VyLCBwcm9kdWNlciwgXCJmXCIpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBCcm9hZGNhc3RzIGEgY29udGV4dCBmb3IgdGhlIGNoYW5uZWwgb2YgdGhlIGN1cnJlbnQgZW50aXR5LlxuXHQgICAgICogQHBhcmFtIGNvbnRleHQgLSBOZXcgY29udGV4dCB0byBzZXQuXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuYnJvYWRjYXN0XG5cdCAgICAgKiBAc3RhdGljXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGJyb2FkY2FzdChjb250ZXh0KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtYnJvYWRjYXN0JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50LnNldENvbnRleHQoY29udGV4dCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIExhdW5jaGVzIGFuIGFwcCB3aXRoIHRhcmdldCBpbmZvcm1hdGlvbiwgd2hpY2ggY2FuIGVpdGhlciBiZSBhIHN0cmluZyBvciBhbiBBcHBNZXRhZGF0YSBvYmplY3QuXG5cdCAgICAgKiBAcGFyYW0gYXBwXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLm9wZW5cblx0ICAgICAqL1xuXHQgICAgYXN5bmMgX29wZW4oYXBwLCBjb250ZXh0KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtb3BlbicpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIHJldHVybiBhd2FpdCBJbnRlcm9wQ2xpZW50XzEuSW50ZXJvcENsaWVudC5mZXJyeUZkYzNDYWxsKHRoaXMuY2xpZW50LCAnZmRjM09wZW4nLCB7IGFwcCwgY29udGV4dCB9KTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGVycm9yVG9UaHJvdyA9IGVycm9yLm1lc3NhZ2UgPT09IHV0aWxzXzIuQlJPS0VSX0VSUk9SUy5mZGMzT3BlbiA/ICdSZXNvbHZlclVuYXZhaWxhYmxlJyA6IGVycm9yLm1lc3NhZ2U7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclRvVGhyb3cpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIGFzeW5jIF9nZXRDaGFubmVscygpIHtcblx0ICAgICAgICBjb25zdCBjaGFubmVscyA9IGF3YWl0IHRoaXMuY2xpZW50LmdldENvbnRleHRHcm91cHMoKTtcblx0ICAgICAgICAvLyBmZGMzIGltcGxlbWVudGF0aW9uIG9mIGdldFN5c3RlbUNoYW5uZWxzIHJldHVybnMgYW4gYXJyYXkgb2YgY2hhbm5lbHMsIGhhdmUgdG8gZGVjb3JhdGUgb3ZlclxuXHQgICAgICAgIC8vIHRoaXMgc28gcGVvcGxlIGtub3cgdGhhdCB0aGVzZSBBUElzIGFyZSBub3Qgc3VwcG9ydGVkXG5cdCAgICAgICAgcmV0dXJuIGNoYW5uZWxzLm1hcCgoY2hhbm5lbCkgPT4ge1xuXHQgICAgICAgICAgICByZXR1cm4geyAuLi5jaGFubmVsLCB0eXBlOiAnc3lzdGVtJywgLi4uKDAsIHV0aWxzXzEuZ2V0VW5zdXBwb3J0ZWRDaGFubmVsQXBpcykoKSB9O1xuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXR1cm5zIGEgQ2hhbm5lbCBvYmplY3QgZm9yIHRoZSBzcGVjaWZpZWQgY2hhbm5lbCwgY3JlYXRpbmcgaXQgYXMgYW4gQXBwIENoYW5uZWwgaWYgaXQgZG9lcyBub3QgZXhpc3QuXG5cdCAgICAgKiBAcGFyYW0gY2hhbm5lbElkXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuZ2V0T3JDcmVhdGVDaGFubmVsXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldE9yQ3JlYXRlQ2hhbm5lbChjaGFubmVsSWQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1nZXQtb3ItY3JlYXRlLWNoYW5uZWwnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBzeXN0ZW1DaGFubmVscyA9IGF3YWl0IHRoaXMuX2dldENoYW5uZWxzKCk7XG5cdCAgICAgICAgY29uc3QgdXNlckNoYW5uZWwgPSBzeXN0ZW1DaGFubmVscy5maW5kKChjaGFubmVsKSA9PiBjaGFubmVsLmlkID09PSBjaGFubmVsSWQpO1xuXHQgICAgICAgIGlmICh1c2VyQ2hhbm5lbCkge1xuXHQgICAgICAgICAgICByZXR1cm4geyAuLi51c2VyQ2hhbm5lbCwgdHlwZTogJ3N5c3RlbScsIC4uLigwLCB1dGlsc18xLmdldFVuc3VwcG9ydGVkQ2hhbm5lbEFwaXMpKCkgfTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkNvbnRleHRHcm91cCA9IGF3YWl0IHRoaXMuY2xpZW50LmpvaW5TZXNzaW9uQ29udGV4dEdyb3VwKGNoYW5uZWxJZCk7XG5cdCAgICAgICAgICAgIHJldHVybiAoMCwgdXRpbHNfMS5idWlsZEFwcENoYW5uZWxPYmplY3QpKHNlc3Npb25Db250ZXh0R3JvdXApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvci5tZXNzYWdlKTtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHV0aWxzXzEuQ2hhbm5lbEVycm9yLkNyZWF0aW9uRmFpbGVkKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgdGhlIEludGVyb3AtQnJva2VyLWRlZmluZWQgY29udGV4dCBncm91cHMgYXZhaWxhYmxlIGZvciBhbiBlbnRpdHkgdG8gam9pbi5cblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5nZXRTeXN0ZW1DaGFubmVsc1xuXHQgICAgICogQHN0YXRpY1xuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRTeXN0ZW1DaGFubmVscygpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1nZXQtc3lzdGVtLWNoYW5uZWxzJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuX2dldENoYW5uZWxzKCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEpvaW4gYWxsIEludGVyb3AgQ2xpZW50cyBhdCB0aGUgZ2l2ZW4gaWRlbnRpdHkgdG8gY29udGV4dCBncm91cCBgY29udGV4dEdyb3VwSWRgLlxuXHQgICAgICogSWYgbm8gdGFyZ2V0IGlzIHNwZWNpZmllZCwgaXQgYWRkcyB0aGUgc2VuZGVyIHRvIHRoZSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICogQmVjYXVzZSBtdWx0aXBsZSBDaGFubmVsIGNvbm5lY3Rpb25zL0ludGVyb3AgQ2xpZW50cyBjYW4gcG90ZW50aWFsbHkgZXhpc3QgYXQgYSBgdXVpZGAvYG5hbWVgIGNvbWJvLCB3ZSBjdXJyZW50bHkgam9pbiBhbGwgQ2hhbm5lbCBjb25uZWN0aW9ucy9JbnRlcm9wIENsaWVudHMgYXQgdGhlIGdpdmVuIGlkZW50aXR5IHRvIHRoZSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICogSWYgYW4gYGVuZHBvaW50SWRgIGlzIHByb3ZpZGVkICh3aGljaCBpcyB1bmxpa2VseSwgdW5sZXNzIHRoZSBjYWxsIGlzIGNvbWluZyBmcm9tIGFuIGV4dGVybmFsIGFkYXB0ZXIpLCB0aGVuIHdlIG9ubHkgam9pbiB0aGF0IHNpbmdsZSBjb25uZWN0aW9uIHRvIHRoZSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICogRm9yIGFsbCBpbnRlbnRzIGFuZCBwdXJwb3NlcywgdGhlcmUgd2lsbCBvbmx5IGJlIDEgY29ubmVjdGlvbiBwcmVzZW50IGluIFBsYXRmb3JtIGFuZCBCcm93c2VyIGltcGxlbWVudGF0aW9ucywgc28gdGhpcyBwb2ludCBpcyBtb3JlLW9yLWxlc3MgbW9vdC5cblx0ICAgICAqIEBwYXJhbSBjaGFubmVsSWQgLSBJZCBvZiB0aGUgY29udGV4dCBncm91cC5cblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5qb2luQ2hhbm5lbFxuXHQgICAgICogQHN0YXRpY1xuXHQgICAgICovXG5cdCAgICBhc3luYyBqb2luQ2hhbm5lbChjaGFubmVsSWQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1qb2luLWNoYW5uZWwnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5jbGllbnQuam9pbkNvbnRleHRHcm91cChjaGFubmVsSWQpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgaWYgKGVycm9yLm1lc3NhZ2UgPT09IHV0aWxzXzIuQlJPS0VSX0VSUk9SUy5qb2luU2Vzc2lvbkNvbnRleHRHcm91cFdpdGhKb2luQ29udGV4dEdyb3VwKSB7XG5cdCAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdUaGUgQ2hhbm5lbCB5b3UgaGF2ZSB0cmllZCB0byBqb2luIGlzIGFuIEFwcCBDaGFubmVsLiBDdXN0b20gQ2hhbm5lbHMgY2FuIG9ubHkgYmUgZGVmaW5lZCBieSB0aGUgSW50ZXJvcCBCcm9rZXIgdGhyb3VnaCBjb2RlIG9yIG1hbmlmZXN0IGNvbmZpZ3VyYXRpb24uIFBsZWFzZSB1c2UgZ2V0T3JDcmVhdGVDaGFubmVsLicpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvci5tZXNzYWdlKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBpZiAoZXJyb3IubWVzc2FnZS5zdGFydHNXaXRoKCdBdHRlbXB0aW5nIHRvIGpvaW4gYSBjb250ZXh0IGdyb3VwIHRoYXQgZG9lcyBub3QgZXhpc3QnKSkge1xuXHQgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHV0aWxzXzEuQ2hhbm5lbEVycm9yLk5vQ2hhbm5lbEZvdW5kKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodXRpbHNfMS5DaGFubmVsRXJyb3IuQWNjZXNzRGVuaWVkKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgdGhlIENoYW5uZWwgdGhhdCB0aGUgZW50aXR5IGlzIHN1YnNjcmliZWQgdG8uIFJldHVybnMgbnVsbCBpZiBub3Qgam9pbmVkIHRvIGEgY2hhbm5lbC5cblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5nZXRDdXJyZW50Q2hhbm5lbFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRDdXJyZW50Q2hhbm5lbCgpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1nZXQtY3VycmVudC1jaGFubmVsJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY3VycmVudENvbnRleHRHcm91cEluZm8gPSBhd2FpdCB0aGlzLmdldEN1cnJlbnRDb250ZXh0R3JvdXBJbmZvKCk7XG5cdCAgICAgICAgaWYgKCFjdXJyZW50Q29udGV4dEdyb3VwSW5mbykge1xuXHQgICAgICAgICAgICByZXR1cm4gbnVsbDtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGRDaGFubmVsT2JqZWN0KGN1cnJlbnRDb250ZXh0R3JvdXBJbmZvKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVtb3ZlcyB0aGUgc3BlY2lmaWVkIHRhcmdldCBmcm9tIGEgY29udGV4dCBncm91cC5cblx0ICAgICAqIElmIG5vIHRhcmdldCBpcyBzcGVjaWZpZWQsIGl0IHJlbW92ZXMgdGhlIHNlbmRlciBmcm9tIHRoZWlyIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMubGVhdmVDdXJyZW50Q2hhbm5lbFxuXHQgICAgICogQHN0YXRpY1xuXHQgICAgICovXG5cdCAgICBhc3luYyBsZWF2ZUN1cnJlbnRDaGFubmVsKCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLWxlYXZlLWN1cnJlbnQtY2hhbm5lbCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiB0aGlzLmNsaWVudC5yZW1vdmVGcm9tQ29udGV4dEdyb3VwKCk7XG5cdCAgICB9XG5cdCAgICAvLyB1dGlsc1xuXHQgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcblx0ICAgIGFzeW5jIGdldEN1cnJlbnRDb250ZXh0R3JvdXBJbmZvKCkge1xuXHQgICAgICAgIGNvbnN0IGNvbnRleHRHcm91cHMgPSBhd2FpdCB0aGlzLmNsaWVudC5nZXRDb250ZXh0R3JvdXBzKCk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50c0luQ3R4R3JvdXBzUHJvbWlzZSA9IGNvbnRleHRHcm91cHMubWFwKGFzeW5jIChjdHhHcm91cCkgPT4ge1xuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy5jbGllbnQuZ2V0QWxsQ2xpZW50c0luQ29udGV4dEdyb3VwKGN0eEdyb3VwLmlkKTtcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnRzSW5DdHhHcm91cHMgPSBhd2FpdCBQcm9taXNlLmFsbChjbGllbnRzSW5DdHhHcm91cHNQcm9taXNlKTtcblx0ICAgICAgICBjb25zdCBjbGllbnRJZHggPSBjbGllbnRzSW5DdHhHcm91cHMuZmluZEluZGV4KChjbGllbnRJZGVudGl0eUFycikgPT4ge1xuXHQgICAgICAgICAgICByZXR1cm4gY2xpZW50SWRlbnRpdHlBcnIuc29tZSgoY2xpZW50SWRlbnRpdHkpID0+IHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IHsgdXVpZCwgbmFtZSB9ID0gY2xpZW50SWRlbnRpdHk7XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy53aXJlLm1lLnV1aWQgPT09IHV1aWQgJiYgdGhpcy53aXJlLm1lLm5hbWUgPT09IG5hbWU7XG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiBjb250ZXh0R3JvdXBzW2NsaWVudElkeF07XG5cdCAgICB9XG5cdCAgICBhc3luYyBidWlsZENoYW5uZWxPYmplY3QoY3VycmVudENvbnRleHRHcm91cEluZm8pIHtcblx0ICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG5cdCAgICAgICAgcmV0dXJuIHtcblx0ICAgICAgICAgICAgLi4uY3VycmVudENvbnRleHRHcm91cEluZm8sXG5cdCAgICAgICAgICAgIHR5cGU6ICdzeXN0ZW0nLFxuXHQgICAgICAgICAgICBhZGRDb250ZXh0TGlzdGVuZXI6ICguLi5bY29udGV4dFR5cGUsIGhhbmRsZXJdKSA9PiB7XG5cdCAgICAgICAgICAgICAgICBsZXQgcmVhbEhhbmRsZXI7XG5cdCAgICAgICAgICAgICAgICBsZXQgcmVhbFR5cGU7XG5cdCAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnRleHRUeXBlID09PSAnZnVuY3Rpb24nKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdhZGRDb250ZXh0TGlzdGVuZXIoaGFuZGxlcikgaGFzIGJlZW4gZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBhZGRDb250ZXh0TGlzdGVuZXIobnVsbCwgaGFuZGxlciknKTtcblx0ICAgICAgICAgICAgICAgICAgICByZWFsSGFuZGxlciA9IGNvbnRleHRUeXBlO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgICAgICAgICAgcmVhbEhhbmRsZXIgPSBoYW5kbGVyO1xuXHQgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGV4dFR5cGUgPT09ICdzdHJpbmcnKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIHJlYWxUeXBlID0gY29udGV4dFR5cGU7XG5cdCAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgY29uc3QgbGlzdGVuZXIgPSAoYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICAgICAgICAgIGxldCBmaXJzdCA9IHRydWU7XG5cdCAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudENvbnRleHQgPSBhd2FpdCB0aGlzLmNsaWVudC5nZXRDdXJyZW50Q29udGV4dChyZWFsVHlwZSk7XG5cdCAgICAgICAgICAgICAgICAgICAgY29uc3Qgd3JhcHBlZEhhbmRsZXIgPSAoY29udGV4dCwgY29udGV4dE1ldGFkYXRhKSA9PiB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaXJzdCkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3QgPSBmYWxzZTtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoMCwgaXNFcXVhbF8xLmRlZmF1bHQpKGN1cnJlbnRDb250ZXh0LCBjb250ZXh0KSkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY29uc2lzdGVudC1yZXR1cm5cblx0ICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlYWxIYW5kbGVyKGNvbnRleHQsIGNvbnRleHRNZXRhZGF0YSk7XG5cdCAgICAgICAgICAgICAgICAgICAgfTtcblx0ICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jbGllbnQuYWRkQ29udGV4dEhhbmRsZXIod3JhcHBlZEhhbmRsZXIsIHJlYWxUeXBlKTtcblx0ICAgICAgICAgICAgICAgIH0pKCk7XG5cdCAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIFRPRE8gW0NPUkUtMTUyNF1cblx0ICAgICAgICAgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgICAgICAgICAgLi4ubGlzdGVuZXIsXG5cdCAgICAgICAgICAgICAgICAgICAgdW5zdWJzY3JpYmU6ICgpID0+IGxpc3RlbmVyLnRoZW4oKGwpID0+IGwudW5zdWJzY3JpYmUoKSlcblx0ICAgICAgICAgICAgICAgIH07XG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIGJyb2FkY2FzdDogdGhpcy5icm9hZGNhc3QuYmluZCh0aGlzKSxcblx0ICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBUeXBlc2NyaXB0IGZhaWxzIHRvIGluZmVyIHRoZSByZXR1cm50eXBlIGlzIGEgUHJvbWlzZVxuXHQgICAgICAgICAgICBnZXRDdXJyZW50Q29udGV4dDogYXN5bmMgKGNvbnRleHRUeXBlKSA9PiB7XG5cdCAgICAgICAgICAgICAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0Q3VycmVudENvbnRleHQoY29udGV4dFR5cGUpO1xuXHQgICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBUeXBlc2NyaXB0IGZhaWxzIHRvIGluZmVyIHRoZSByZXR1cm50eXBlIGlzIGEgUHJvbWlzZVxuXHQgICAgICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQgPT09IHVuZGVmaW5lZCA/IG51bGwgOiBjb250ZXh0O1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfTtcblx0ICAgIH1cblx0fVxuXHRmZGMzQ29tbW9uLkZEQzNNb2R1bGVCYXNlID0gRkRDM01vZHVsZUJhc2U7XG5cdF9GREMzTW9kdWxlQmFzZV9wcm9kdWNlciA9IG5ldyBXZWFrTWFwKCk7XG5cdHJldHVybiBmZGMzQ29tbW9uO1xufVxuXG52YXIgaGFzUmVxdWlyZWRGZGMzMV8yO1xuXG5mdW5jdGlvbiByZXF1aXJlRmRjMzFfMiAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEZkYzMxXzIpIHJldHVybiBmZGMzMV8yO1xuXHRoYXNSZXF1aXJlZEZkYzMxXzIgPSAxO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZmRjMzFfMiwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdGZkYzMxXzIuRmRjM01vZHVsZSA9IHZvaWQgMDtcblx0Y29uc3QgdXRpbHNfMSA9IHV0aWxzJDM7XG5cdGNvbnN0IGZkYzNfY29tbW9uXzEgPSByZXF1aXJlRmRjM0NvbW1vbigpO1xuXHQvKipcblx0ICogQHZlcnNpb24gMS4yXG5cdCAqIFRoZSBGREMzIENsaWVudCBMaWJyYXJ5IHByb3ZpZGVzIGEgc2V0IEFQSXMgdG8gYmUgdXNlZCBmb3IgRkRDMyBjb21wbGlhbmNlLFxuXHQgKiB3aGlsZSB1c2luZyBvdXIgSW50ZXJvcCBBUEkgdW5kZXIgdGhlIGhvb2QuIEluIG9yZGVyIHRvIHVzZSB0aGlzIHNldCBvZiBBUElzXG5cdCAqIHlvdSB3aWxsIG5lZWQgdG8gc2V0IHVwIHlvdXIgb3duIHtAbGluayBJbnRlcm9wQnJva2VyIEludGVyb3BCcm9rZXJ9IG9yIHVzZSBhIFBsYXRmb3JtIGFwcGxpY2F0aW9uLCB3aGljaCBkb2VzIHRoZSBzZXR1cCBmb3IgeW91LiBSZWZlciB0byBvdXIgZG9jdW1lbnRhdGlvbiBvblxuXHQgKiBvdXIge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL29mLWRvY3MvZG9jcy9lbmFibGUtY29sb3ItbGlua2luZyBJbnRlcm9wIEFQSX0uXG5cdCAqXG5cdCAqIFRvIGVuYWJsZSB0aGUgRkRDMyBBUElzIGluIGEge0BsaW5rIFdpbmRvdyBXaW5kb3d9IG9yIHtAbGluayBWaWV3IFZpZXd9LCBhZGQgdGhlIGZkYzNJbnRlcm9wQXBpXG5cdCAqIHByb3BlcnR5IHRvIGl0cyBvcHRpb25zOlxuXHQgKlxuXHQgKiBgYGBqc1xuXHQgKiB7XG5cdCAqICAgICBhdXRvU2hvdzogZmFsc2UsXG5cdCAqICAgICBzYXZlV2luZG93U3RhdGU6IHRydWUsXG5cdCAqICAgICB1cmw6ICdodHRwczovL29wZW5maW4uY28nLFxuXHQgKiAgICAgZmRjM0ludGVyb3BBcGk6ICcxLjInXG5cdCAqIH1cblx0ICogYGBgXG5cdCAqXG5cdCAqIElmIHVzaW5nIGEge0BsaW5rIFBsYXRmb3JtIFBsYXRmb3JtIH0gYXBwbGljYXRpb24sIHlvdSBjYW4gc2V0IHRoaXMgcHJvcGVydHkgaW4gZGVmYXVsdFdpbmRvd09wdGlvbnMgYW5kIGRlZmF1bHRWaWV3T3B0aW9ucy5cblx0ICpcblx0ICogSW4gb3JkZXIgdG8gZW5zdXJlIHRoYXQgdGhlIEZEQzMgQXBpIGlzIHJlYWR5IGJlZm9yZSB1c2UsIHlvdSBjYW4gdXNlIHRoZSAnZmRjM1JlYWR5JyBldmVudCBmaXJlZCBvbiB0aGUgRE9NIFdpbmRvdyBvYmplY3Q6XG5cdCAqXG5cdCAqIGBgYGpzXG5cdCAqIGZ1bmN0aW9uIGZkYzNBY3Rpb24oKSB7XG5cdCAqICAgICAvLyBNYWtlIHNvbWUgZmRjMyBBUEkgY2FsbHMgaGVyZVxuXHQgKiB9XG5cdCAqXG5cdCAqIGlmICh3aW5kb3cuZmRjMykge1xuXHQgKiAgICBmZGMzQWN0aW9uKCk7XG5cdCAqIH0gZWxzZSB7XG5cdCAqICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdmZGMzUmVhZHknLCBmZGMzQWN0aW9uKTtcblx0ICogfVxuXHQgKiBgYGBcblx0ICovXG5cdGNsYXNzIEZkYzNNb2R1bGUgZXh0ZW5kcyBmZGMzX2NvbW1vbl8xLkZEQzNNb2R1bGVCYXNlIHtcblx0ICAgIGFzeW5jIG9wZW4oYXBwLCBjb250ZXh0KSB7XG5cdCAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVyc2NvcmUtZGFuZ2xlXG5cdCAgICAgICAgYXdhaXQgc3VwZXIuX29wZW4oYXBwLCBjb250ZXh0KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQWRkIGEgY29udGV4dCBoYW5kbGVyIGZvciBpbmNvbWluZyBjb250ZXh0LiBJZiBhbiBlbnRpdHkgaXMgcGFydCBvZiBhIGNvbnRleHQgZ3JvdXAsIGFuZCB0aGVuIHNldHMgaXRzIGNvbnRleHQgaGFuZGxlciwgaXQgd2lsbCByZWNlaXZlIGFsbCBvZiBpdHMgZGVjbGFyZWQgY29udGV4dHMuIElmIHlvdSB3aXNoIHRvIGxpc3RlbiBmb3IgYWxsIGluY29taW5nIGNvbnRleHRzLCBwYXNzIGBudWxsYCBmb3IgdGhlIGNvbnRleHRUeXBlIGFyZ3VtZW50LlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRUeXBlIC0gVGhlIHR5cGUgb2YgY29udGV4dCB5b3Ugd2lzaCB0byBoYW5kbGUuXG5cdCAgICAgKiBAcGFyYW0gaGFuZGxlciAtIEhhbmRsZXIgZm9yIGluY29taW5nIGNvbnRleHQuXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuYWRkQ29udGV4dExpc3RlbmVyXG5cdCAgICAgKiBAc3RhdGljXG5cdCAgICAgKi9cblx0ICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgVE9ETyBbQ09SRS0xNTI0XVxuXHQgICAgYWRkQ29udGV4dExpc3RlbmVyKGNvbnRleHRUeXBlLCBoYW5kbGVyKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtYWRkLWNvbnRleHQtbGlzdGVuZXInKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBsZXQgbGlzdGVuZXI7XG5cdCAgICAgICAgaWYgKHR5cGVvZiBjb250ZXh0VHlwZSA9PT0gJ2Z1bmN0aW9uJykge1xuXHQgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2FkZENvbnRleHRMaXN0ZW5lcihoYW5kbGVyKSBoYXMgYmVlbiBkZXByZWNhdGVkLiBQbGVhc2UgdXNlIGFkZENvbnRleHRMaXN0ZW5lcihudWxsLCBoYW5kbGVyKScpO1xuXHQgICAgICAgICAgICBsaXN0ZW5lciA9IHRoaXMuY2xpZW50LmFkZENvbnRleHRIYW5kbGVyKGNvbnRleHRUeXBlKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIGxpc3RlbmVyID0gdGhpcy5jbGllbnQuYWRkQ29udGV4dEhhbmRsZXIoaGFuZGxlciwgY29udGV4dFR5cGUgPT09IG51bGwgPyB1bmRlZmluZWQgOiBjb250ZXh0VHlwZSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgIC4uLmxpc3RlbmVyLFxuXHQgICAgICAgICAgICB1bnN1YnNjcmliZTogKCkgPT4gbGlzdGVuZXIudGhlbigobCkgPT4gbC51bnN1YnNjcmliZSgpKVxuXHQgICAgICAgIH07XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEFkZHMgYSBsaXN0ZW5lciBmb3IgaW5jb21pbmcgSW50ZW50cy5cblx0ICAgICAqIEBwYXJhbSBpbnRlbnQgLSBOYW1lIG9mIHRoZSBJbnRlbnRcblx0ICAgICAqIEBwYXJhbSBoYW5kbGVyIC0gSGFuZGxlciBmb3IgaW5jb21pbmcgSW50ZW50XG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuYWRkSW50ZW50TGlzdGVuZXJcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqL1xuXHQgICAgYWRkSW50ZW50TGlzdGVuZXIoaW50ZW50LCBoYW5kbGVyKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtYWRkLWludGVudC1saXN0ZW5lcicpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNvbnRleHRIYW5kbGVyID0gKHJhaXNlZEludGVudCkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCB7IGNvbnRleHQsIG1ldGFkYXRhOiBpbnRlbnRNZXRhZGF0YSB9ID0gcmFpc2VkSW50ZW50O1xuXHQgICAgICAgICAgICBjb25zdCB7IG1ldGFkYXRhIH0gPSBjb250ZXh0O1xuXHQgICAgICAgICAgICBjb25zdCBpbnRlbnRSZXNvbHV0aW9uUmVzdWx0SWQgPSBpbnRlbnRNZXRhZGF0YT8uaW50ZW50UmVzb2x1dGlvblJlc3VsdElkIHx8IG1ldGFkYXRhPy5pbnRlbnRSZXNvbHV0aW9uUmVzdWx0SWQ7XG5cdCAgICAgICAgICAgIGlmIChpbnRlbnRSZXNvbHV0aW9uUmVzdWx0SWQpIHtcblx0ICAgICAgICAgICAgICAgIHRoaXMuZmluLkludGVyQXBwbGljYXRpb25CdXMucHVibGlzaChpbnRlbnRSZXNvbHV0aW9uUmVzdWx0SWQsIG51bGwpLmNhdGNoKCgpID0+IG51bGwpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGhhbmRsZXIocmFpc2VkSW50ZW50LmNvbnRleHQpO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgY29uc3QgbGlzdGVuZXIgPSB0aGlzLmNsaWVudC5yZWdpc3RlckludGVudEhhbmRsZXIoY29udGV4dEhhbmRsZXIsIGludGVudCwge1xuXHQgICAgICAgICAgICBmZGMzVmVyc2lvbjogJzEuMidcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4ge1xuXHQgICAgICAgICAgICAuLi5saXN0ZW5lcixcblx0ICAgICAgICAgICAgdW5zdWJzY3JpYmU6ICgpID0+IGxpc3RlbmVyLnRoZW4oKGwpID0+IGwudW5zdWJzY3JpYmUoKSlcblx0ICAgICAgICB9O1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSYWlzZXMgYSBzcGVjaWZpYyBpbnRlbnQuXG5cdCAgICAgKiBAcGFyYW0gaW50ZW50IE5hbWUgb2YgdGhlIEludGVudC5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0IENvbnRleHQgYXNzb2NpYXRlZCB3aXRoIHRoZSBJbnRlbnQuXG5cdCAgICAgKiBAcGFyYW0gIGFwcCBBcHAgdGhhdCB3aWxsIHJlc29sdmUgdGhlIEludGVudC4gVGhpcyBpcyBhZGRlZCBhcyBtZXRhZGF0YSB0byB0aGUgSW50ZW50LiBDYW4gYmUgYWNjZXNzZWQgYnkgdGhlIGFwcCBwcm92aWRlciBpbiB7QGxpbmsgSW50ZXJvcEJyb2tlciNoYW5kbGVGaXJlZEludGVudCBJbnRlcm9wQnJva2VyLmhhbmRsZUZpcmVkSW50ZW50fS5cblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5yYWlzZUludGVudFxuXHQgICAgICogQHN0YXRpY1xuXHQgICAgICovXG5cdCAgICBhc3luYyByYWlzZUludGVudChpbnRlbnQsIGNvbnRleHQsIGFwcCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLXJhaXNlLWludGVudCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGludGVudE9iaiA9IGFwcFxuXHQgICAgICAgICAgICA/IHsgbmFtZTogaW50ZW50LCBjb250ZXh0LCBtZXRhZGF0YTogeyB0YXJnZXQ6IGFwcCB9IH1cblx0ICAgICAgICAgICAgOiB7IG5hbWU6IGludGVudCwgY29udGV4dCB9O1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNsaWVudC5maXJlSW50ZW50KGludGVudE9iaik7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zdCBlcnJvclRvVGhyb3cgPSBlcnJvci5tZXNzYWdlID09PSB1dGlsc18xLkJST0tFUl9FUlJPUlMuZmlyZUludGVudCA/ICdSZXNvbHZlclVuYXZhaWxhYmxlJyA6IGVycm9yLm1lc3NhZ2U7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclRvVGhyb3cpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogRmluZCBvdXQgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBhIHBhcnRpY3VsYXIgaW50ZW50IGJ5IHBhc3NpbmcgaXRzIG5hbWUsIGFuZCBvcHRpb25hbGx5IGl0cyBjb250ZXh0LlxuXHQgICAgICogQHBhcmFtIGludGVudCBOYW1lIG9mIHRoZSBJbnRlbnRcblx0ICAgICAqIEBwYXJhbSBjb250ZXh0XG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuZmluZEludGVudFxuXHQgICAgICovXG5cdCAgICBhc3luYyBmaW5kSW50ZW50KGludGVudCwgY29udGV4dCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLWZpbmQtaW50ZW50JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY2xpZW50LmdldEluZm9Gb3JJbnRlbnQoeyBuYW1lOiBpbnRlbnQsIGNvbnRleHQgfSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zdCBlcnJvclRvVGhyb3cgPSBlcnJvci5tZXNzYWdlID09PSB1dGlsc18xLkJST0tFUl9FUlJPUlMuZ2V0SW5mb0ZvckludGVudCA/ICdSZXNvbHZlclVuYXZhaWxhYmxlJyA6IGVycm9yLm1lc3NhZ2U7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclRvVGhyb3cpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogRmluZCBhbGwgdGhlIGF2YWlsYWJsZSBpbnRlbnRzIGZvciBhIHBhcnRpY3VsYXIgY29udGV4dC5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0XG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuZmluZEludGVudHNCeUNvbnRleHRcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZmluZEludGVudHNCeUNvbnRleHQoY29udGV4dCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLWZpbmQtaW50ZW50cy1ieS1jb250ZXh0JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY2xpZW50LmdldEluZm9Gb3JJbnRlbnRzQnlDb250ZXh0KGNvbnRleHQpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc3QgZXJyb3JUb1Rocm93ID0gZXJyb3IubWVzc2FnZSA9PT0gdXRpbHNfMS5CUk9LRVJfRVJST1JTLmdldEluZm9Gb3JJbnRlbnRzQnlDb250ZXh0ID8gJ1Jlc29sdmVyVW5hdmFpbGFibGUnIDogZXJyb3IubWVzc2FnZTtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yVG9UaHJvdyk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBGaW5kcyBhbmQgcmFpc2VzIGFuIGludGVudCBhZ2FpbnN0IGEgdGFyZ2V0IGFwcCBiYXNlZCBwdXJlbHkgb24gY29udGV4dCBkYXRhLlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRcblx0ICAgICAqIEBwYXJhbSBhcHBcblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5yYWlzZUludGVudEZvckNvbnRleHRcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgcmFpc2VJbnRlbnRGb3JDb250ZXh0KGNvbnRleHQsIGFwcCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLXJhaXNlLWludGVudC1mb3ItY29udGV4dCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNsaWVudC5maXJlSW50ZW50Rm9yQ29udGV4dCh7IC4uLmNvbnRleHQsIG1ldGFkYXRhOiB7IHRhcmdldDogYXBwIH0gfSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zdCBlcnJvclRvVGhyb3cgPSBlcnJvci5tZXNzYWdlID09PSB1dGlsc18xLkJST0tFUl9FUlJPUlMuZmlyZUludGVudEZvckNvbnRleHQgPyAnUmVzb2x2ZXJVbmF2YWlsYWJsZScgOiBlcnJvci5tZXNzYWdlO1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JUb1Rocm93KTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgYSBDaGFubmVsIG9iamVjdCBmb3IgdGhlIHNwZWNpZmllZCBjaGFubmVsLCBjcmVhdGluZyBpdCBhcyBhbiBBcHAgQ2hhbm5lbCBpZiBpdCBkb2VzIG5vdCBleGlzdC5cblx0ICAgICAqIEBwYXJhbSBjaGFubmVsSWRcblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5nZXRPckNyZWF0ZUNoYW5uZWxcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0T3JDcmVhdGVDaGFubmVsKGNoYW5uZWxJZCkge1xuXHQgICAgICAgIHJldHVybiBzdXBlci5nZXRPckNyZWF0ZUNoYW5uZWwoY2hhbm5lbElkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0dXJucyBtZXRhZGF0YSByZWxhdGluZyB0byB0aGUgRkRDMyBvYmplY3QgYW5kIGl0cyBwcm92aWRlciwgaW5jbHVkaW5nIHRoZSBzdXBwb3J0ZWQgdmVyc2lvbiBvZiB0aGUgRkRDMyBzcGVjaWZpY2F0aW9uIGFuZCB0aGUgbmFtZSBvZiB0aGUgcHJvdmlkZXIgb2YgdGhlIGltcGxlbWVudGF0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmdldEluZm9cblx0ICAgICAqL1xuXHQgICAgZ2V0SW5mbygpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1nZXQtaW5mbycpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IHZlcnNpb24gPSB0aGlzLndpcmUuZW52aXJvbm1lbnQuZ2V0QWRhcHRlclZlcnNpb25TeW5jKCk7XG5cdCAgICAgICAgcmV0dXJuIHtcblx0ICAgICAgICAgICAgcHJvdmlkZXJWZXJzaW9uOiB2ZXJzaW9uLFxuXHQgICAgICAgICAgICBwcm92aWRlcjogYG9wZW5maW4tJHt0aGlzLndpcmUubWUudXVpZH1gLFxuXHQgICAgICAgICAgICBmZGMzVmVyc2lvbjogJzEuMidcblx0ICAgICAgICB9O1xuXHQgICAgfVxuXHR9XG5cdGZkYzMxXzIuRmRjM01vZHVsZSA9IEZkYzNNb2R1bGU7XG5cdHJldHVybiBmZGMzMV8yO1xufVxuXG52YXIgZmRjMzJfMCA9IHt9O1xuXG52YXIgaGFzUmVxdWlyZWRGZGMzMl8wO1xuXG5mdW5jdGlvbiByZXF1aXJlRmRjMzJfMCAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEZkYzMyXzApIHJldHVybiBmZGMzMl8wO1xuXHRoYXNSZXF1aXJlZEZkYzMyXzAgPSAxO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZmRjMzJfMCwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdGZkYzMyXzAuRmRjM01vZHVsZTIgPSB2b2lkIDA7XG5cdGNvbnN0IGZkYzNfY29tbW9uXzEgPSByZXF1aXJlRmRjM0NvbW1vbigpO1xuXHRjb25zdCB1dGlsc18xID0gdXRpbHMkMztcblx0Y29uc3QgSW50ZXJvcENsaWVudF8xID0gcmVxdWlyZUludGVyb3BDbGllbnQoKTtcblx0Y29uc3QgdXRpbHNfMiA9IHV0aWxzJDI7XG5cdGNvbnN0IFByaXZhdGVDaGFubmVsQ2xpZW50XzEgPSBQcml2YXRlQ2hhbm5lbENsaWVudCQxO1xuXHQvKipcblx0ICogQHZlcnNpb24gMi4wXG5cdCAqIFRoZSBGREMzIENsaWVudCBMaWJyYXJ5IHByb3ZpZGVzIGEgc2V0IEFQSXMgdG8gYmUgdXNlZCBmb3IgRkRDMyBjb21wbGlhbmNlLFxuXHQgKiB3aGlsZSB1c2luZyBvdXIgSW50ZXJvcCBBUEkgdW5kZXIgdGhlIGhvb2QuIEluIG9yZGVyIHRvIHVzZSB0aGlzIHNldCBvZiBBUElzXG5cdCAqIHlvdSB3aWxsIG5lZWQgdG8gc2V0IHVwIHlvdXIgb3duIHtAbGluayBJbnRlcm9wQnJva2VyIEludGVyb3BCcm9rZXJ9IG9yIHVzZSBhIFBsYXRmb3JtIGFwcGxpY2F0aW9uLCB3aGljaCBkb2VzIHRoZSBzZXR1cCBmb3IgeW91LiBSZWZlciB0byBvdXIgZG9jdW1lbnRhdGlvbiBvblxuXHQgKiBvdXIge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL29mLWRvY3MvZG9jcy9lbmFibGUtY29udGV4dC1zaGFyaW5nIEludGVyb3AgQVBJfS5cblx0ICpcblx0ICogVG8gZW5hYmxlIHRoZSBGREMzIEFQSXMgaW4gYSB7QGxpbmsgV2luZG93IFdpbmRvd30gb3Ige0BsaW5rIFZpZXcgVmlld30sIGFkZCB0aGUgZmRjM0ludGVyb3BBcGlcblx0ICogcHJvcGVydHkgdG8gaXRzIG9wdGlvbnM6XG5cdCAqXG5cdCAqIGBgYGpzXG5cdCAqIHtcblx0ICogICAgIGF1dG9TaG93OiBmYWxzZSxcblx0ICogICAgIHNhdmVXaW5kb3dTdGF0ZTogdHJ1ZSxcblx0ICogICAgIHVybDogJ2h0dHBzOi8vb3BlbmZpbi5jbycsXG5cdCAqICAgICBmZGMzSW50ZXJvcEFwaTogJzIuMCdcblx0ICogfVxuXHQgKiBgYGBcblx0ICpcblx0ICogSWYgdXNpbmcgYSB7QGxpbmsgUGxhdGZvcm0gUGxhdGZvcm0gfSBhcHBsaWNhdGlvbiwgeW91IGNhbiBzZXQgdGhpcyBwcm9wZXJ0eSBpbiBkZWZhdWx0V2luZG93T3B0aW9ucyBhbmQgZGVmYXVsdFZpZXdPcHRpb25zLlxuXHQgKlxuXHQgKiBJbiBvcmRlciB0byBlbnN1cmUgdGhhdCB0aGUgRkRDMyBBcGkgaXMgcmVhZHkgYmVmb3JlIHVzZSwgeW91IGNhbiB1c2UgdGhlICdmZGMzUmVhZHknIGV2ZW50IGZpcmVkIG9uIHRoZSBET00gV2luZG93IG9iamVjdDpcblx0ICpcblx0ICogYGBganNcblx0ICogZnVuY3Rpb24gZmRjM0FjdGlvbigpIHtcblx0ICogICAgIC8vIE1ha2Ugc29tZSBmZGMzIEFQSSBjYWxscyBoZXJlXG5cdCAqIH1cblx0ICpcblx0ICogaWYgKHdpbmRvdy5mZGMzKSB7XG5cdCAqICAgIGZkYzNBY3Rpb24oKTtcblx0ICogfSBlbHNlIHtcblx0ICogICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2ZkYzNSZWFkeScsIGZkYzNBY3Rpb24pO1xuXHQgKiB9XG5cdCAqIGBgYFxuXHQgKi9cblx0Y2xhc3MgRmRjM01vZHVsZTIgZXh0ZW5kcyBmZGMzX2NvbW1vbl8xLkZEQzNNb2R1bGVCYXNlIHtcblx0ICAgIC8qKlxuXHQgICAgICogTGF1bmNoZXMgYW4gYXBwLCBzcGVjaWZpZWQgdmlhIGFuIEFwcElkZW50aWZpZXIgb2JqZWN0LlxuXHQgICAgICogQHBhcmFtIGFwcFxuXHQgICAgICogQHBhcmFtIGNvbnRleHRcblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5vcGVuXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIG9wZW4oYXBwLCBjb250ZXh0KSB7XG5cdCAgICAgICAgaWYgKHR5cGVvZiBhcHAgPT09ICdzdHJpbmcnKSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUud2FybignUGFzc2luZyBhIHN0cmluZyBhcyB0aGUgYXBwIHBhcmFtZXRlciBpcyBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIGFuIEFwcElkZW50aWZpZXIgKHsgYXBwSWQ6IHN0cmluZzsgaW5zdGFuY2VJZD86IHN0cmluZyB9KS4nKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVyc2NvcmUtZGFuZ2xlXG5cdCAgICAgICAgcmV0dXJuIHN1cGVyLl9vcGVuKGFwcCwgY29udGV4dCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEZpbmQgYWxsIHRoZSBhdmFpbGFibGUgaW5zdGFuY2VzIGZvciBhIHBhcnRpY3VsYXIgYXBwbGljYXRpb24uXG5cdCAgICAgKiBAcGFyYW0gYXBwXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzN2Mi5maW5kSW5zdGFuY2VzXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGZpbmRJbnN0YW5jZXMoYXBwKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtZmluZC1pbnN0YW5jZXMnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICByZXR1cm4gYXdhaXQgSW50ZXJvcENsaWVudF8xLkludGVyb3BDbGllbnQuZmVycnlGZGMzQ2FsbCh0aGlzLmNsaWVudCwgJ2ZkYzNGaW5kSW5zdGFuY2VzJywgYXBwKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGVycm9yVG9UaHJvdyA9IGVycm9yLm1lc3NhZ2UgPT09IHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5mZGMzRmluZEluc3RhbmNlcyA/ICdSZXNvbHZlclVuYXZhaWxhYmxlJyA6IGVycm9yLm1lc3NhZ2U7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclRvVGhyb3cpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIHRoZSBBcHBNZXRhZGF0YSBmb3IgYW4gQXBwSWRlbnRpZmllciwgd2hpY2ggcHJvdmlkZXMgYWRkaXRpb25hbCBtZXRhZGF0YSAoc3VjaCBhcyBpY29ucywgYSB0aXRsZSBhbmQgZGVzY3JpcHRpb24pIGZyb20gdGhlIEFwcCBEaXJlY3RvcnkgcmVjb3JkIGZvciB0aGUgYXBwbGljYXRpb24sIHRoYXQgbWF5IGJlIHVzZWQgZm9yIGRpc3BsYXkgcHVycG9zZXMuXG5cdCAgICAgKiBAcGFyYW0gYXBwXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzN2Mi5nZXRBcHBNZXRhZGF0YVxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRBcHBNZXRhZGF0YShhcHApIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1nZXQtYXBwLW1ldGFkYXRhJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgcmV0dXJuIGF3YWl0IEludGVyb3BDbGllbnRfMS5JbnRlcm9wQ2xpZW50LmZlcnJ5RmRjM0NhbGwodGhpcy5jbGllbnQsICdmZGMzR2V0QXBwTWV0YWRhdGEnLCBhcHApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc3QgZXJyb3JUb1Rocm93ID0gZXJyb3IubWVzc2FnZSA9PT0gdXRpbHNfMS5CUk9LRVJfRVJST1JTLmZkYzNHZXRBcHBNZXRhZGF0YSA/ICdSZXNvbHZlclVuYXZhaWxhYmxlJyA6IGVycm9yLm1lc3NhZ2U7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclRvVGhyb3cpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQWRkIGEgY29udGV4dCBoYW5kbGVyIGZvciBpbmNvbWluZyBjb250ZXh0LiBJZiBhbiBlbnRpdHkgaXMgcGFydCBvZiBhIGNvbnRleHQgZ3JvdXAsIGFuZCB0aGVuIHNldHMgaXRzIGNvbnRleHQgaGFuZGxlciwgaXQgd2lsbCByZWNlaXZlIGFsbCBvZiBpdHMgZGVjbGFyZWQgY29udGV4dHMuIElmIHlvdSB3aXNoIHRvIGxpc3RlbiBmb3IgYWxsIGluY29taW5nIGNvbnRleHRzLCBwYXNzIGBudWxsYCBmb3IgdGhlIGNvbnRleHRUeXBlIGFyZ3VtZW50LlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRUeXBlXG5cdCAgICAgKiBAcGFyYW0gaGFuZGxlclxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmFkZENvbnRleHRMaXN0ZW5lclxuXHQgICAgICovXG5cdCAgICAvLyBAdHMtZXhwZWN0LWVycm9yIFRPRE8gW0NPUkUtMTUyNF1cblx0ICAgIGFzeW5jIGFkZENvbnRleHRMaXN0ZW5lcihjb250ZXh0VHlwZSwgaGFuZGxlcikge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLWFkZC1jb250ZXh0LWxpc3RlbmVyJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgLy8gVGhlIEZEQzMgQ29udGV4dEhhbmRsZXIgb25seSBleHBlY3RzIHRoZSBjb250ZXh0IGFuZCBvcHRpb25hbCBDb250ZXh0TWV0YWRhdGEsIHNvIHdlIHdyYXAgdGhlIGhhbmRsZXJcblx0ICAgICAgICAvLyBoZXJlIHNvIGl0IG9ubHkgZ2V0cyBwYXNzZWQgdGhlc2UgcGFyYW1ldGVyc1xuXHQgICAgICAgIGNvbnN0IGdldFdyYXBwZWRIYW5kbGVyID0gKGhhbmRsZXJUb1dyYXApID0+IHtcblx0ICAgICAgICAgICAgcmV0dXJuIChjb250ZXh0KSA9PiB7XG5cdCAgICAgICAgICAgICAgICBjb25zdCB7IGNvbnRleHRNZXRhZGF0YSwgLi4ucmVzdCB9ID0gY29udGV4dDtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSBjb250ZXh0TWV0YWRhdGEgPyBbeyAuLi5yZXN0IH0sIGNvbnRleHRNZXRhZGF0YV0gOiBbY29udGV4dCwgbnVsbF07XG5cdCAgICAgICAgICAgICAgICBoYW5kbGVyVG9XcmFwKC4uLmFyZ3MpO1xuXHQgICAgICAgICAgICB9O1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgbGV0IGFjdHVhbEhhbmRsZXIgPSBoYW5kbGVyO1xuXHQgICAgICAgIGxldCB3cmFwcGVkSGFuZGxlciA9IGdldFdyYXBwZWRIYW5kbGVyKGFjdHVhbEhhbmRsZXIpO1xuXHQgICAgICAgIGlmICh0eXBlb2YgY29udGV4dFR5cGUgPT09ICdmdW5jdGlvbicpIHtcblx0ICAgICAgICAgICAgY29uc29sZS53YXJuKCdhZGRDb250ZXh0TGlzdGVuZXIoaGFuZGxlcikgaGFzIGJlZW4gZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBhZGRDb250ZXh0TGlzdGVuZXIobnVsbCwgaGFuZGxlciknKTtcblx0ICAgICAgICAgICAgYWN0dWFsSGFuZGxlciA9IGNvbnRleHRUeXBlO1xuXHQgICAgICAgICAgICB3cmFwcGVkSGFuZGxlciA9IGdldFdyYXBwZWRIYW5kbGVyKGFjdHVhbEhhbmRsZXIpO1xuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy5jbGllbnQuYWRkQ29udGV4dEhhbmRsZXIod3JhcHBlZEhhbmRsZXIpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4gdGhpcy5jbGllbnQuYWRkQ29udGV4dEhhbmRsZXIod3JhcHBlZEhhbmRsZXIsIGNvbnRleHRUeXBlID09PSBudWxsID8gdW5kZWZpbmVkIDogY29udGV4dFR5cGUpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBGaW5kIG91dCBtb3JlIGluZm9ybWF0aW9uIGFib3V0IGEgcGFydGljdWxhciBpbnRlbnQgYnkgcGFzc2luZyBpdHMgbmFtZSwgYW5kIG9wdGlvbmFsbHkgaXRzIGNvbnRleHQgYW5kIHJlc3VsdFR5cGUuXG5cdCAgICAgKiBAcGFyYW0gaW50ZW50IE5hbWUgb2YgdGhlIEludGVudFxuXHQgICAgICogQHBhcmFtIGNvbnRleHQgQ29udGV4dFxuXHQgICAgICogQHBhcmFtIHJlc3VsdFR5cGUgVGhlIHR5cGUgb2YgcmVzdWx0IHJldHVybmVkIGZvciBhbnkgaW50ZW50IHNwZWNpZmllZCBkdXJpbmcgcmVzb2x1dGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5maW5kSW50ZW50XG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGZpbmRJbnRlbnQoaW50ZW50LCBjb250ZXh0LCByZXN1bHRUeXBlKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtZmluZC1pbnRlbnQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5jbGllbnQuZ2V0SW5mb0ZvckludGVudCh7IG5hbWU6IGludGVudCwgY29udGV4dCwgbWV0YWRhdGE6IHsgcmVzdWx0VHlwZSB9IH0pO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc3QgZXJyb3JUb1Rocm93ID0gZXJyb3IubWVzc2FnZSA9PT0gdXRpbHNfMS5CUk9LRVJfRVJST1JTLmdldEluZm9Gb3JJbnRlbnQgPyAnUmVzb2x2ZXJVbmF2YWlsYWJsZScgOiBlcnJvci5tZXNzYWdlO1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JUb1Rocm93KTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEZpbmQgYWxsIHRoZSBhdmFpbGFibGUgaW50ZW50cyBmb3IgYSBwYXJ0aWN1bGFyIGNvbnRleHQuXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dFxuXHQgICAgICogQHBhcmFtIHJlc3VsdFR5cGUgVGhlIHR5cGUgb2YgcmVzdWx0IHJldHVybmVkIGZvciBhbnkgaW50ZW50IHNwZWNpZmllZCBkdXJpbmcgcmVzb2x1dGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjM3YyLmZpbmRJbnRlbnRzQnlDb250ZXh0XG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGZpbmRJbnRlbnRzQnlDb250ZXh0KGNvbnRleHQsIHJlc3VsdFR5cGUpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1maW5kLWludGVudHMtYnktY29udGV4dCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IHBheWxvYWQgPSByZXN1bHRUeXBlID8geyBjb250ZXh0LCBtZXRhZGF0YTogeyByZXN1bHRUeXBlIH0gfSA6IGNvbnRleHQ7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgcmV0dXJuIGF3YWl0IEludGVyb3BDbGllbnRfMS5JbnRlcm9wQ2xpZW50LmZlcnJ5RmRjM0NhbGwodGhpcy5jbGllbnQsICdmZGMzdjJGaW5kSW50ZW50c0J5Q29udGV4dCcsIHBheWxvYWQpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc3QgZXJyb3JUb1Rocm93ID0gZXJyb3IubWVzc2FnZSA9PT0gdXRpbHNfMS5CUk9LRVJfRVJST1JTLmdldEluZm9Gb3JJbnRlbnRzQnlDb250ZXh0ID8gJ1Jlc29sdmVyVW5hdmFpbGFibGUnIDogZXJyb3IubWVzc2FnZTtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yVG9UaHJvdyk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSYWlzZXMgYSBzcGVjaWZpYyBpbnRlbnQgZm9yIHJlc29sdXRpb24gYWdhaW5zdCBhcHBzIHJlZ2lzdGVyZWQgd2l0aCB0aGUgZGVza3RvcCBhZ2VudC5cblx0ICAgICAqIEBwYXJhbSBpbnRlbnQgTmFtZSBvZiB0aGUgSW50ZW50XG5cdCAgICAgKiBAcGFyYW0gY29udGV4dCBDb250ZXh0IGFzc29jaWF0ZWQgd2l0aCB0aGUgSW50ZW50XG5cdCAgICAgKiBAcGFyYW0gYXBwXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzN2Mi5yYWlzZUludGVudFxuXHQgICAgICovXG5cdCAgICBhc3luYyByYWlzZUludGVudChpbnRlbnQsIGNvbnRleHQsIGFwcCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLXJhaXNlLWludGVudCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIGlmICh0eXBlb2YgYXBwID09PSAnc3RyaW5nJykge1xuXHQgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdQYXNzaW5nIGEgc3RyaW5nIGFzIHRoZSBhcHAgcGFyYW1ldGVyIGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSB1c2UgYW4gQXBwSWRlbnRpZmllciAoeyBhcHBJZDogc3RyaW5nOyBpbnN0YW5jZUlkPzogc3RyaW5nIH0pLicpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIHJldHVybiAoMCwgdXRpbHNfMi5nZXRJbnRlbnRSZXNvbHV0aW9uKSh0aGlzLmNsaWVudCwgY29udGV4dCwgYXBwLCBpbnRlbnQpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc3QgZXJyb3JUb1Rocm93ID0gZXJyb3IubWVzc2FnZSA9PT0gdXRpbHNfMS5CUk9LRVJfRVJST1JTLmZpcmVJbnRlbnQgPyAnUmVzb2x2ZXJVbmF2YWlsYWJsZScgOiBlcnJvci5tZXNzYWdlO1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JUb1Rocm93KTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEZpbmRzIGFuZCByYWlzZXMgYW4gaW50ZW50IGFnYWluc3QgYXBwcyByZWdpc3RlcmVkIHdpdGggdGhlIGRlc2t0b3AgYWdlbnQgYmFzZWQgcHVyZWx5IG9uIHRoZSB0eXBlIG9mIHRoZSBjb250ZXh0IGRhdGEuXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dCBDb250ZXh0IGFzc29jaWF0ZWQgd2l0aCB0aGUgSW50ZW50XG5cdCAgICAgKiBAcGFyYW0gYXBwXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzN2Mi5yYWlzZUludGVudEZvckNvbnRleHRcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgcmFpc2VJbnRlbnRGb3JDb250ZXh0KGNvbnRleHQsIGFwcCkge1xuXHQgICAgICAgIC8vIFRPRE86IFdlIGhhdmUgdG8gZG8gdGhlIHNhbWUgdGhpbmcgd2UgZG8gZm9yIHJhaXNlSW50ZW50IGhlcmUgYXMgd2VsbC5cblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1yYWlzZS1pbnRlbnQtZm9yLWNvbnRleHQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICBpZiAodHlwZW9mIGFwcCA9PT0gJ3N0cmluZycpIHtcblx0ICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignUGFzc2luZyBhIHN0cmluZyBhcyB0aGUgYXBwIHBhcmFtZXRlciBpcyBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIGFuIEFwcElkZW50aWZpZXIgKHsgYXBwSWQ6IHN0cmluZzsgaW5zdGFuY2VJZD86IHN0cmluZyB9KS4nKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICByZXR1cm4gKDAsIHV0aWxzXzIuZ2V0SW50ZW50UmVzb2x1dGlvbikodGhpcy5jbGllbnQsIGNvbnRleHQsIGFwcCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zdCBlcnJvclRvVGhyb3cgPSBlcnJvci5tZXNzYWdlID09PSB1dGlsc18xLkJST0tFUl9FUlJPUlMuZmlyZUludGVudCA/ICdSZXNvbHZlclVuYXZhaWxhYmxlJyA6IGVycm9yLm1lc3NhZ2U7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclRvVGhyb3cpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQWRkcyBhIGxpc3RlbmVyIGZvciBpbmNvbWluZyBpbnRlbnRzLlxuXHQgICAgICogQHBhcmFtIGludGVudCAgTmFtZSBvZiB0aGUgSW50ZW50XG5cdCAgICAgKiBAcGFyYW0gaGFuZGxlciBBIGNhbGxiYWNrIHRoYXQgaGFuZGxlcyBhIGNvbnRleHQgZXZlbnQgYW5kIG1heSByZXR1cm4gYSBwcm9taXNlIG9mIGEgQ29udGV4dCBvciBDaGFubmVsIG9iamVjdCB0byBiZSByZXR1cm5lZCB0byB0aGUgYXBwbGljYXRpb24gdGhhdCByYWlzZWQgdGhlIGludGVudC5cblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5hZGRJbnRlbnRMaXN0ZW5lclxuXHQgICAgICovXG5cdCAgICBhc3luYyBhZGRJbnRlbnRMaXN0ZW5lcihpbnRlbnQsIGhhbmRsZXIpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1hZGQtaW50ZW50LWxpc3RlbmVyJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgaWYgKHR5cGVvZiBpbnRlbnQgIT09ICdzdHJpbmcnKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRmlyc3QgYXJndW1lbnQgbXVzdCBiZSBhbiBJbnRlbnQgbmFtZScpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICAvLyBUaGUgRkRDMyBJbnRlbnRlciBoYW5kbGVyIG9ubHkgZXhwZWN0cyB0aGUgY29udGV4dCBhbmQgY29udGV4dE1ldGFkYXRhIHRvIGJlIHBhc3NlZCB0byB0aGUgaGFuZGxlcixcblx0ICAgICAgICAvLyBzbyB3ZSB3cmFwIGl0IGhlcmUgYW5kIG9ubHkgcGFzcyB0aG9zZSBwYXJhbWF0ZXJzLlxuXHQgICAgICAgIGNvbnN0IGNvbnRleHRIYW5kbGVyID0gYXN5bmMgKHJhaXNlZEludGVudCkgPT4ge1xuXHQgICAgICAgICAgICBsZXQgaW50ZW50UmVzdWx0O1xuXHQgICAgICAgICAgICBsZXQgaW50ZW50UmVzdWx0VG9TZW5kO1xuXHQgICAgICAgICAgICBjb25zdCB7IGNvbnRleHQsIG1ldGFkYXRhOiBpbnRlbnRNZXRhZGF0YSB9ID0gcmFpc2VkSW50ZW50O1xuXHQgICAgICAgICAgICBjb25zdCB7IGNvbnRleHRNZXRhZGF0YSwgbWV0YWRhdGEsIC4uLnJlc3QgfSA9IGNvbnRleHQ7XG5cdCAgICAgICAgICAgIGNvbnN0IGludGVudFJlc29sdXRpb25SZXN1bHRJZCA9IGludGVudE1ldGFkYXRhPy5pbnRlbnRSZXNvbHV0aW9uUmVzdWx0SWQgfHwgbWV0YWRhdGE/LmludGVudFJlc29sdXRpb25SZXN1bHRJZDtcblx0ICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IG5ld0NvbnRleHQgPSBtZXRhZGF0YSA/IHsgbWV0YWRhdGEsIC4uLnJlc3QgfSA6IHsgLi4ucmVzdCB9O1xuXHQgICAgICAgICAgICAgICAgaW50ZW50UmVzdWx0ID0gYXdhaXQgaGFuZGxlcihuZXdDb250ZXh0LCBjb250ZXh0TWV0YWRhdGEpO1xuXHQgICAgICAgICAgICAgICAgaW50ZW50UmVzdWx0VG9TZW5kID0gaW50ZW50UmVzdWx0O1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICAgICAgaW50ZW50UmVzdWx0ID0gZXJyb3I7XG5cdCAgICAgICAgICAgICAgICBpbnRlbnRSZXN1bHRUb1NlbmQgPSB7IGVycm9yOiB0cnVlIH07XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgaWYgKGludGVudFJlc29sdXRpb25SZXN1bHRJZCkge1xuXHQgICAgICAgICAgICAgICAgdGhpcy5maW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5wdWJsaXNoKGludGVudFJlc29sdXRpb25SZXN1bHRJZCwgaW50ZW50UmVzdWx0VG9TZW5kKS5jYXRjaCgoKSA9PiBudWxsKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBpZiAoaW50ZW50UmVzdWx0IGluc3RhbmNlb2YgRXJyb3IpIHtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihpbnRlbnRSZXN1bHQubWVzc2FnZSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgcmV0dXJuIGludGVudFJlc3VsdDtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIHJldHVybiB0aGlzLmNsaWVudC5yZWdpc3RlckludGVudEhhbmRsZXIoY29udGV4dEhhbmRsZXIsIGludGVudCwgeyBmZGMzVmVyc2lvbjogJzIuMCcgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgYSBDaGFubmVsIG9iamVjdCBmb3IgdGhlIHNwZWNpZmllZCBjaGFubmVsLCBjcmVhdGluZyBpdCBhcyBhbiBBcHAgQ2hhbm5lbCBpZiBpdCBkb2VzIG5vdCBleGlzdC5cblx0ICAgICAqIEBwYXJhbSBjaGFubmVsSWRcblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5nZXRPckNyZWF0ZUNoYW5uZWxcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0T3JDcmVhdGVDaGFubmVsKGNoYW5uZWxJZCkge1xuXHQgICAgICAgIHJldHVybiBzdXBlci5nZXRPckNyZWF0ZUNoYW5uZWwoY2hhbm5lbElkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0dXJucyBhIENoYW5uZWwgd2l0aCBhbiBhdXRvLWdlbmVyYXRlZCBpZGVudGl0eSB0aGF0IGlzIGludGVuZGVkIGZvciBwcml2YXRlIGNvbW11bmljYXRpb24gYmV0d2VlbiBhcHBsaWNhdGlvbnMuIFByaW1hcmlseSB1c2VkIHRvIGNyZWF0ZSBjaGFubmVscyB0aGF0IHdpbGwgYmUgcmV0dXJuZWQgdG8gb3RoZXIgYXBwbGljYXRpb25zIHZpYSBhbiBJbnRlbnRSZXNvbHV0aW9uIGZvciBhIHJhaXNlZCBpbnRlbnQuXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzN2Mi5jcmVhdGVQcml2YXRlQ2hhbm5lbFxuXHQgICAgICovXG5cdCAgICBhc3luYyBjcmVhdGVQcml2YXRlQ2hhbm5lbCgpIHtcblx0ICAgICAgICBjb25zdCBjaGFubmVsSWQgPSAoMCwgdXRpbHNfMS5nZW5lcmF0ZUlkKSgpO1xuXHQgICAgICAgIGF3YWl0IEludGVyb3BDbGllbnRfMS5JbnRlcm9wQ2xpZW50LmZlcnJ5RmRjM0NhbGwodGhpcy5jbGllbnQsICdjcmVhdGVQcml2YXRlQ2hhbm5lbFByb3ZpZGVyJywgeyBjaGFubmVsSWQgfSk7XG5cdCAgICAgICAgY29uc3QgY2hhbm5lbENsaWVudCA9IGF3YWl0IHRoaXMuZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KGNoYW5uZWxJZCk7XG5cdCAgICAgICAgY29uc3QgbmV3UHJpdmF0ZUNoYW5uZWxDbGllbnQgPSBuZXcgUHJpdmF0ZUNoYW5uZWxDbGllbnRfMS5Qcml2YXRlQ2hhbm5lbENsaWVudChjaGFubmVsQ2xpZW50LCBjaGFubmVsSWQpO1xuXHQgICAgICAgIHJldHVybiAoMCwgdXRpbHNfMi5idWlsZFByaXZhdGVDaGFubmVsT2JqZWN0KShuZXdQcml2YXRlQ2hhbm5lbENsaWVudCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyBhIGxpc3Qgb2YgdGhlIFVzZXIgQ2hhbm5lbHMgYXZhaWxhYmxlIGZvciB0aGUgYXBwIHRvIGpvaW4uXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzN2Mi5nZXRVc2VyQ2hhbm5lbHNcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0VXNlckNoYW5uZWxzKCkge1xuXHQgICAgICAgIGNvbnN0IGNoYW5uZWxzID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0Q29udGV4dEdyb3VwcygpO1xuXHQgICAgICAgIC8vIGZkYzMgaW1wbGVtZW50YXRpb24gb2YgZ2V0VXNlckNoYW5uZWxzIHJldHVybnMgb24gYXJyYXkgb2YgY2hhbm5lbHMsIGhhdmUgdG8gZGVjb3JhdGUgb3ZlclxuXHQgICAgICAgIC8vIHRoaXMgc28gcGVvcGxlIGtub3cgdGhhdCB0aGVzZSBBUElzIGFyZSBub3Qgc3VwcG9ydGVkXG5cdCAgICAgICAgcmV0dXJuIGNoYW5uZWxzLm1hcCgoY2hhbm5lbCkgPT4ge1xuXHQgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIFRPRE8gW0NPUkUtMTUyNF1cblx0ICAgICAgICAgICAgcmV0dXJuIHsgLi4uY2hhbm5lbCwgdHlwZTogJ3VzZXInLCAuLi4oMCwgdXRpbHNfMi5nZXRVbnN1cHBvcnRlZENoYW5uZWxBcGlzKSgnVXNlcicpIH07XG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyBhIGxpc3Qgb2YgdGhlIFVzZXIgQ2hhbm5lbHMgYXZhaWxhYmxlIGZvciB0aGUgYXBwIHRvIGpvaW4uXG5cdCAgICAgKlxuXHQgICAgICogQGRlcHJlY2F0ZWQgUGxlYXNlIHVzZSB7QGxpbmsgZmRjMy5nZXRVc2VyQ2hhbm5lbHMgZmRjMy5nZXRVc2VyQ2hhbm5lbHN9IGluc3RlYWRcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmdldFN5c3RlbUNoYW5uZWxzXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldFN5c3RlbUNoYW5uZWxzKCkge1xuXHQgICAgICAgIGNvbnNvbGUud2FybignVGhpcyBBUEkgaGFzIGJlZW4gZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBmZGMzLmdldFVzZXJDaGFubmVscyBpbnN0ZWFkLicpO1xuXHQgICAgICAgIHJldHVybiBzdXBlci5nZXRTeXN0ZW1DaGFubmVscygpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBKb2luIGFuIGFwcCB0byBhIHNwZWNpZmllZCBVc2VyIGNoYW5uZWwuXG5cdCAgICAgKiBAcGFyYW0gY2hhbm5lbElkIENoYW5uZWwgbmFtZVxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzdjIuam9pblVzZXJDaGFubmVsXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGpvaW5Vc2VyQ2hhbm5lbChjaGFubmVsSWQpIHtcblx0ICAgICAgICByZXR1cm4gc3VwZXIuam9pbkNoYW5uZWwoY2hhbm5lbElkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogSm9pbiBhbiBhcHAgdG8gYSBzcGVjaWZpZWQgVXNlciBjaGFubmVsLlxuXHQgICAgICogQHBhcmFtIGNoYW5uZWxJZCBDaGFubmVsIG5hbWVcblx0ICAgICAqIEBkZXByZWNhdGVkIFBsZWFzZSB1c2Uge0BsaW5rIGZkYzMuam9pblVzZXJDaGFubmVsIGZkYzMuam9pblVzZXJDaGFubmVsfSBpbnN0ZWFkXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuam9pbkNoYW5uZWxcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgam9pbkNoYW5uZWwoY2hhbm5lbElkKSB7XG5cdCAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIEFQSSBoYXMgYmVlbiBkZXByZWNhdGVkLiBQbGVhc2UgdXNlIGZkYzMuam9pblVzZXJDaGFubmVsIGluc3RlYWQuJyk7XG5cdCAgICAgICAgcmV0dXJuIHN1cGVyLmpvaW5DaGFubmVsKGNoYW5uZWxJZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgdGhlIENoYW5uZWwgb2JqZWN0IGZvciB0aGUgY3VycmVudCBVc2VyIGNoYW5uZWwgbWVtYmVyc2hpcFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmdldEN1cnJlbnRDaGFubmVsXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldEN1cnJlbnRDaGFubmVsKCkge1xuXHQgICAgICAgIGNvbnN0IGN1cnJlbnRDaGFubmVsID0gYXdhaXQgc3VwZXIuZ2V0Q3VycmVudENoYW5uZWwoKTtcblx0ICAgICAgICBpZiAoIWN1cnJlbnRDaGFubmVsKSB7XG5cdCAgICAgICAgICAgIHJldHVybiBudWxsO1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4ge1xuXHQgICAgICAgICAgICAuLi5jdXJyZW50Q2hhbm5lbCxcblx0ICAgICAgICAgICAgdHlwZTogJ3VzZXInLFxuXHQgICAgICAgICAgICBicm9hZGNhc3Q6IHRoaXMuYnJvYWRjYXN0LmJpbmQodGhpcylcblx0ICAgICAgICB9O1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXRyaWV2ZXMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIEZEQzMgaW1wbGVtZW50YXRpb24sIGluY2x1ZGluZyB0aGUgc3VwcG9ydGVkIHZlcnNpb24gb2YgdGhlIEZEQzMgc3BlY2lmaWNhdGlvbiwgdGhlIG5hbWUgb2YgdGhlIHByb3ZpZGVyIG9mIHRoZSBpbXBsZW1lbnRhdGlvbiwgaXRzIG93biB2ZXJzaW9uIG51bWJlciwgZGV0YWlscyBvZiB3aGV0aGVyIG9wdGlvbmFsIEFQSSBmZWF0dXJlcyBhcmUgaW1wbGVtZW50ZWQgYW5kIHRoZSBtZXRhZGF0YSBvZiB0aGUgY2FsbGluZyBhcHBsaWNhdGlvbiBhY2NvcmRpbmcgdG8gdGhlIGRlc2t0b3AgYWdlbnQuXG5cdCAgICAgKiBmZGMzSGFuZGxlR2V0SW5mbyBtdXN0IGJlIG92ZXJyaWRkZW4gaW4gdGhlIEludGVyb3BCcm9rZXIgc28gdGhhdCB0aGUgSW1wbGVtZW50YXRpb25NZXRhZGF0YSB3aWxsIGhhdmUgdGhlIGFwcE1ldGFkYXRhIGluZm8uXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzN2Mi5nZXRJbmZvXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldEluZm8oKSB7XG5cdCAgICAgICAgcmV0dXJuIEludGVyb3BDbGllbnRfMS5JbnRlcm9wQ2xpZW50LmZlcnJ5RmRjM0NhbGwodGhpcy5jbGllbnQsICdmZGMzdjJHZXRJbmZvJywgeyBmZGMzVmVyc2lvbjogJzIuMCcgfSk7XG5cdCAgICB9XG5cdH1cblx0ZmRjMzJfMC5GZGMzTW9kdWxlMiA9IEZkYzNNb2R1bGUyO1xuXHRyZXR1cm4gZmRjMzJfMDtcbn1cblxudmFyIGhhc1JlcXVpcmVkSW50ZXJvcENsaWVudDtcblxuZnVuY3Rpb24gcmVxdWlyZUludGVyb3BDbGllbnQgKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRJbnRlcm9wQ2xpZW50KSByZXR1cm4gSW50ZXJvcENsaWVudDtcblx0aGFzUmVxdWlyZWRJbnRlcm9wQ2xpZW50ID0gMTtcblx0dmFyIF9fY2xhc3NQcml2YXRlRmllbGRTZXQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcblx0ICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcblx0ICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcblx0ICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG5cdCAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcblx0fTtcblx0dmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuXHQgICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuXHQgICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG5cdCAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xuXHR9O1xuXHR2YXIgX19pbXBvcnREZWZhdWx0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9faW1wb3J0RGVmYXVsdCkgfHwgZnVuY3Rpb24gKG1vZCkge1xuXHQgICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBcImRlZmF1bHRcIjogbW9kIH07XG5cdH07XG5cdHZhciBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBfSW50ZXJvcENsaWVudF9zZXNzaW9uQ29udGV4dEdyb3Vwcztcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KEludGVyb3BDbGllbnQsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRJbnRlcm9wQ2xpZW50LkludGVyb3BDbGllbnQgPSB2b2lkIDA7XG5cdGNvbnN0IGJhc2VfMSA9IGJhc2U7XG5cdGNvbnN0IFNlc3Npb25Db250ZXh0R3JvdXBDbGllbnRfMSA9IF9faW1wb3J0RGVmYXVsdChTZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50JDEpO1xuXHRjb25zdCBmZGMzXzFfMl8xID0gcmVxdWlyZUZkYzMxXzIoKTtcblx0Y29uc3QgZmRjM18yXzBfMSA9IHJlcXVpcmVGZGMzMl8wKCk7XG5cdGNvbnN0IHV0aWxzXzEgPSB1dGlscyQzO1xuXHQvKipcblx0ICogVGhlIEludGVyb3AgQ2xpZW50IEFQSSBpcyBicm9rZW4gdXAgaW50byB0d28gZ3JvdXBzOlxuXHQgKlxuXHQgKiAqKkNvbnRlbnQgRmFjaW5nIEFQSXMqKiAtIEZvciBBcHBsaWNhdGlvbiBEZXZlbG9wZXJzIHB1dHRpbmcgVmlld3MgaW50byBhIFBsYXRmb3JtIFdpbmRvdywgd2hvIGNhcmUgYWJvdXQgQ29udGV4dC4gVGhlc2UgYXJlIEFQSXMgdGhhdCBzZW5kIG91dCBhbmQgcmVjZWl2ZSB0aGUgQ29udGV4dCBkYXRhIHRoYXQgZmxvd3MgYmV0d2VlbiBhcHBsaWNhdGlvbnMuIFRoaW5rIG9mIHRoaXMgYXMgdGhlIFdhdGVyIGluIHRoZSBJbnRlcm9wIFBpcGVzLlxuXHQgKlxuXHQgKiAqKkNvbnRleHQgR3JvdXBpbmcgQVBJcyoqIC0gRm9yIFBsYXRmb3JtIERldmVsb3BlcnMsIHRvIGFkZCBhbmQgcmVtb3ZlIFZpZXdzIHRvIGFuZCBmcm9tIENvbnRleHQgR3JvdXBzLiBUaGVzZSBBUElzIGFyZSB1dGlsaXplZCB1bmRlci10aGUtaG9vZCBpbiBQbGF0Zm9ybXMsIHNvIHRoZXkgZG9uJ3QgbmVlZCB0byBiZSB1c2VkIHRvIHBhcnRpY2lwYXRlIGluIEludGVyb3AuIFRoZXNlIGFyZSB0aGUgQVBJcyB0aGF0IGRlY2lkZSB3aGljaCBlbnRpdGllcyB0aGUgY29udGV4dCBkYXRhIGZsb3dzIGJldHdlZW4uIFRoaW5rIG9mIHRoZXNlIGFzIHRoZSB2YWx2ZXMgb3IgcGlwZXMgdGhhdCBjb250cm9sIHRoZSBmbG93IG9mIENvbnRleHQgRGF0YSBmb3IgSW50ZXJvcC5cblx0ICpcblx0ICogLS0tXG5cdCAqXG5cdCAqIEFsbCBBUElzIGFyZSBhdmFpbGFibGUgYXQgdGhlIGBmaW4ubWUuaW50ZXJvcGAgbmFtZXNwYWNlLlxuXHQgKlxuXHQgKiAtLS1cblx0ICpcblx0ICogKipZb3Ugb25seSBuZWVkIDIgdGhpbmdzIHRvIHBhcnRpY2lwYXRlIGluIEludGVyb3AgQ29udGV4dCBHcm91cGluZzoqKlxuXHQgKiAqIEEgQ29udGV4dCBIYW5kbGVyIGZvciBpbmNvbWluZyBjb250ZXh0OiB7QGxpbmsgSW50ZXJvcENsaWVudCNhZGRDb250ZXh0SGFuZGxlciBhZGRDb250ZXh0SGFuZGxlcihoYW5kbGVyLCBjb250ZXh0VHlwZT8pfVxuXHQgKiAqIENhbGwgc2V0Q29udGV4dCBvbiB5b3VyIGNvbnRleHQgZ3JvdXAgd2hlbiB5b3Ugd2FudCB0byBzaGFyZSBjb250ZXh0IHdpdGggb3RoZXIgZ3JvdXAgbWVtYmVyczoge0BsaW5rIEludGVyb3BDbGllbnQjc2V0Q29udGV4dCBzZXRDb250ZXh0KGNvbnRleHQpfVxuXHQgKlxuXHQgKiAtLS1cblx0ICpcblx0ICogIyMjIyMgQ29uc3RydWN0b3Jcblx0ICogUmV0dXJuZWQgYnkge0BsaW5rIEludGVyb3AuY29ubmVjdFN5bmMgSW50ZXJvcC5jb25uZWN0U3luY30uXG5cdCAqXG5cdCAqIC0tLVxuXHQgKlxuXHQgKiAjIyMjIyBJbnRlcm9wIG1ldGhvZHMgaW50ZW5kZWQgZm9yIFZpZXdzXG5cdCAqXG5cdCAqXG5cdCAqICoqQ29udGV4dCBHcm91cHMgQVBJKipcblx0ICogICoge0BsaW5rIEludGVyb3BDbGllbnQjYWRkQ29udGV4dEhhbmRsZXIgYWRkQ29udGV4dEhhbmRsZXIoaGFuZGxlciwgY29udGV4dFR5cGU/KX1cblx0ICogICoge0BsaW5rIEludGVyb3BDbGllbnQjc2V0Q29udGV4dCBzZXRDb250ZXh0KGNvbnRleHQpfVxuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNnZXRDdXJyZW50Q29udGV4dCBnZXRDdXJyZW50Q29udGV4dChjb250ZXh0VHlwZT8pfVxuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNqb2luU2Vzc2lvbkNvbnRleHRHcm91cCBqb2luU2Vzc2lvbkNvbnRleHRHcm91cChzZXNzaW9uQ29udGV4dEdyb3VwSWQpfVxuXHQgKlxuXHQgKlxuXHQgKiAqKkludGVudHMgQVBJKipcblx0ICogICoge0BsaW5rIEludGVyb3BDbGllbnQjZmlyZUludGVudCBmaXJlSW50ZW50KGludGVudCl9XG5cdCAqICAqIHtAbGluayBJbnRlcm9wQ2xpZW50I3JlZ2lzdGVySW50ZW50SGFuZGxlciByZWdpc3RlckludGVudEhhbmRsZXIoaW50ZW50SGFuZGxlciwgaW50ZW50TmFtZSl9XG5cdCAqICAqIHtAbGluayBJbnRlcm9wQ2xpZW50I2dldEluZm9Gb3JJbnRlbnQgZ2V0SW5mb0ZvckludGVudChpbmZvRm9ySW50ZW50T3B0aW9ucyl9XG5cdCAqICAqIHtAbGluayBJbnRlcm9wQ2xpZW50I2dldEluZm9Gb3JJbnRlbnRzQnlDb250ZXh0IGdldEluZm9Gb3JJbnRlbnRzQnlDb250ZXh0KGNvbnRleHQpfVxuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNmaXJlSW50ZW50Rm9yQ29udGV4dCBmaXJlSW50ZW50Rm9yQ29udGV4dChjb250ZXh0Rm9ySW50ZW50KX1cblx0ICpcblx0ICogIyMjIyMgSW50ZXJvcCBtZXRob2RzIGludGVuZGVkIGZvciBXaW5kb3dzXG5cdCAqICAqIHtAbGluayBJbnRlcm9wQ2xpZW50I2dldENvbnRleHRHcm91cHMgZ2V0Q29udGV4dEdyb3VwcygpfVxuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNqb2luQ29udGV4dEdyb3VwIGpvaW5Db250ZXh0R3JvdXAoY29udGV4dEdyb3VwSWQsIHRhcmdldD8pfVxuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNyZW1vdmVGcm9tQ29udGV4dEdyb3VwIHJlbW92ZUZyb21Db250ZXh0R3JvdXAodGFyZ2V0Pyl9XG5cdCAqICAqIHtAbGluayBJbnRlcm9wQ2xpZW50I2dldEluZm9Gb3JDb250ZXh0R3JvdXAgZ2V0SW5mb0ZvckNvbnRleHRHcm91cChjb250ZXh0R3JvdXBJZCl9XG5cdCAqICAqIHtAbGluayBJbnRlcm9wQ2xpZW50I2dldEFsbENsaWVudHNJbkNvbnRleHRHcm91cCBnZXRBbGxDbGllbnRzSW5Db250ZXh0R3JvdXAoY29udGV4dEdyb3VwSWQpfVxuXHQgKlxuXHQgKi9cblx0bGV0IEludGVyb3BDbGllbnQkMSA9IGNsYXNzIEludGVyb3BDbGllbnQgZXh0ZW5kcyBiYXNlXzEuQmFzZSB7XG5cdCAgICAvKipcblx0ICAgICAqIEBpbnRlcm5hbFxuXHQgICAgICovXG5cdCAgICBjb25zdHJ1Y3Rvcih3aXJlLCBjbGllbnRQcm9taXNlKSB7XG5cdCAgICAgICAgc3VwZXIod2lyZSk7XG5cdCAgICAgICAgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZS5zZXQodGhpcywgdm9pZCAwKTtcblx0ICAgICAgICBfSW50ZXJvcENsaWVudF9zZXNzaW9uQ29udGV4dEdyb3Vwcy5zZXQodGhpcywgdm9pZCAwKTtcblx0ICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9JbnRlcm9wQ2xpZW50X3Nlc3Npb25Db250ZXh0R3JvdXBzLCBuZXcgTWFwKCksIFwiZlwiKTtcblx0ICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9JbnRlcm9wQ2xpZW50X2NsaWVudFByb21pc2UsIGNsaWVudFByb21pc2UsIFwiZlwiKTtcblx0ICAgIH1cblx0ICAgIC8qXG5cdCAgICBDbGllbnQgQVBJc1xuXHQgICAgKi9cblx0ICAgIC8qKlxuXHQgICAgICogU2V0cyBhIGNvbnRleHQgZm9yIHRoZSBjb250ZXh0IGdyb3VwIG9mIHRoZSBjdXJyZW50IGVudGl0eS5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBUaGUgZW50aXR5IG11c3QgYmUgcGFydCBvZiBhIGNvbnRleHQgZ3JvdXAgaW4gb3JkZXIgc2V0IGEgY29udGV4dC5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dCAtIE5ldyBjb250ZXh0IHRvIHNldC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIHNldEluc3RydW1lbnRDb250ZXh0ID0gYXN5bmMgKHRpY2tlcikgPT4ge1xuXHQgICAgICogICAgIGZpbi5tZS5pbnRlcm9wLnNldENvbnRleHQoe3R5cGU6ICdpbnN0cnVtZW50JywgaWQ6IHt0aWNrZXJ9fSlcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiAvLyBUaGUgdXNlciBjbGlja3MgYW4gaW5zdHJ1bWVudCBvZiBpbnRlcmVzdC4gV2Ugd2FudCB0byBzZXQgdGhhdCBJbnN0cnVtZW50IGNvbnRleHQgc28gdGhhdCB0aGUgcmVzdCBvZiBvdXIgd29ya2Zsb3cgdXBkYXRlcyB3aXRoIGluZm9ybWF0aW9uIGZvciB0aGF0IGluc3RydW1lbnRcblx0ICAgICAqIGluc3RydW1lbnRFbGVtZW50Lm9uKCdjbGljaycsIChldnQpID0+IHtcblx0ICAgICAqICAgICBzZXRJbnN0cnVtZW50Q29udGV4dChldnQudGlja2VyKVxuXHQgICAgICogfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBzZXRDb250ZXh0KGNvbnRleHQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtc2V0LWNvbnRleHQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQ2xpZW50X2NsaWVudFByb21pc2UsIFwiZlwiKTtcblx0ICAgICAgICByZXR1cm4gY2xpZW50LmRpc3BhdGNoKCdzZXRDb250ZXh0JywgeyBjb250ZXh0IH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBBZGQgYSBjb250ZXh0IGhhbmRsZXIgZm9yIGluY29taW5nIGNvbnRleHQuIElmIGFuIGVudGl0eSBpcyBwYXJ0IG9mIGEgY29udGV4dCBncm91cCwgYW5kIHRoZW4gc2V0cyBpdHMgY29udGV4dCBoYW5kbGVyLFxuXHQgICAgICogaXQgd2lsbCByZWNlaXZlIGFsbCBvZiBpdHMgZGVjbGFyZWQgY29udGV4dHMuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGhhbmRsZXIgLSBIYW5kbGVyIGZvciBpbmNvbWluZyBjb250ZXh0LlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRUeXBlIC0gVGhlIHR5cGUgb2YgY29udGV4dCB5b3Ugd2lzaCB0byBoYW5kbGUuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBmdW5jdGlvbiBoYW5kbGVJbmNvbWluZ0NvbnRleHQoY29udGV4dEluZm8pIHtcblx0ICAgICAqICAgICBjb25zdCB7IHR5cGUsIGlkIH0gPSBjb250ZXh0SW5mbztcblx0ICAgICAqICAgICBzd2l0Y2ggKHR5cGUpIHtcblx0ICAgICAqICAgICAgICAgY2FzZSAnaW5zdHJ1bWVudCc6XG5cdCAgICAgKiAgICAgICAgICAgICBoYW5kbGVJbnN0cnVtZW50Q29udGV4dChjb250ZXh0SW5mbyk7XG5cdCAgICAgKiAgICAgICAgICAgICBicmVhaztcblx0ICAgICAqICAgICAgICAgY2FzZSAnY291bnRyeSc6XG5cdCAgICAgKiAgICAgICAgICAgICBoYW5kbGVDb3VudHJ5Q29udGV4dChjb250ZXh0SW5mbyk7XG5cdCAgICAgKiAgICAgICAgICAgICBicmVhaztcblx0ICAgICAqXG5cdCAgICAgKiAgICAgICAgIGRlZmF1bHQ6XG5cdCAgICAgKiAgICAgICAgICAgICBicmVhaztcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICpcblx0ICAgICAqIGZ1bmN0aW9uIGhhbmRsZUluc3RydW1lbnRDb250ZXh0KGNvbnRleHRJbmZvKSB7XG5cdCAgICAgKiAgICAgY29uc3QgeyB0eXBlLCBpZCB9ID0gY29udGV4dEluZm87XG5cdCAgICAgKiAgICAgY29uc29sZS5sb2coJ2NvbnRleHRJbmZvIGZvciBpbnN0cnVtZW50JywgY29udGV4dEluZm8pXG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZnVuY3Rpb24gaGFuZGxlQ291bnRyeUNvbnRleHQoY29udGV4dEluZm8pIHtcblx0ICAgICAqICAgICBjb25zdCB7IHR5cGUsIGlkIH0gPSBjb250ZXh0SW5mbztcblx0ICAgICAqICAgICBjb25zb2xlLmxvZygnY29udGV4dEluZm8gZm9yIGNvdW50cnknLCBjb250ZXh0SW5mbylcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBmaW4ubWUuaW50ZXJvcC5hZGRDb250ZXh0SGFuZGxlcihoYW5kbGVJbmNvbWluZ0NvbnRleHQpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICpcblx0ICAgICAqIFBhc3NpbmcgaW4gYSBjb250ZXh0IHR5cGUgYXMgdGhlIHNlY29uZCBwYXJhbWV0ZXIgd2lsbCBjYXVzZSB0aGUgaGFuZGxlciB0byBvbmx5IGJlIGludm9rZWQgd2l0aCB0aGF0IGNvbnRleHQgdHlwZS5cblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZnVuY3Rpb24gaGFuZGxlSW5zdHJ1bWVudENvbnRleHQoY29udGV4dEluZm8pIHtcblx0ICAgICAqICAgICBjb25zdCB7IHR5cGUsIGlkIH0gPSBjb250ZXh0SW5mbztcblx0ICAgICAqICAgICBjb25zb2xlLmxvZygnY29udGV4dEluZm8gZm9yIGluc3RydW1lbnQnLCBjb250ZXh0SW5mbylcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBmdW5jdGlvbiBoYW5kbGVDb3VudHJ5Q29udGV4dChjb250ZXh0SW5mbykge1xuXHQgICAgICogICAgIGNvbnN0IHsgdHlwZSwgaWQgfSA9IGNvbnRleHRJbmZvO1xuXHQgICAgICogICAgIGNvbnNvbGUubG9nKCdjb250ZXh0SW5mbyBmb3IgY291bnRyeScsIGNvbnRleHRJbmZvKVxuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqXG5cdCAgICAgKiBmaW4ubWUuaW50ZXJvcC5hZGRDb250ZXh0SGFuZGxlcihoYW5kbGVJbnN0cnVtZW50Q29udGV4dCwgJ2luc3RydW1lbnQnKVxuXHQgICAgICogZmluLm1lLmludGVyb3AuYWRkQ29udGV4dEhhbmRsZXIoaGFuZGxlQ291bnRyeUNvbnRleHQsICdjb3VudHJ5Jylcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBhZGRDb250ZXh0SGFuZGxlcihoYW5kbGVyLCBjb250ZXh0VHlwZSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWNsaWVudC1hZGQtY29udGV4dC1oYW5kbGVyJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgaWYgKHR5cGVvZiBoYW5kbGVyICE9PSAnZnVuY3Rpb24nKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vbi1mdW5jdGlvbiBhcmd1bWVudCBwYXNzZWQgdG8gdGhlIGZpcnN0IHBhcmFtZXRlciAnaGFuZGxlcicuIEJlIGF3YXJlIHRoYXQgdGhlIGFyZ3VtZW50IG9yZGVyIGRvZXMgbm90IG1hdGNoIHRoZSBGREMzIHN0YW5kYXJkLlwiKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgbGV0IGhhbmRsZXJJZDtcblx0ICAgICAgICBpZiAoY29udGV4dFR5cGUpIHtcblx0ICAgICAgICAgICAgaGFuZGxlcklkID0gYGludm9rZUNvbnRleHRIYW5kbGVyLSR7Y29udGV4dFR5cGV9LSR7KDAsIHV0aWxzXzEuZ2VuZXJhdGVJZCkoKX1gO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgaGFuZGxlcklkID0gJ2ludm9rZUNvbnRleHRIYW5kbGVyJztcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3Qgd3JhcHBlZEhhbmRsZXIgPSAoMCwgdXRpbHNfMS53cmFwQ29udGV4dEhhbmRsZXIpKGhhbmRsZXIsIGhhbmRsZXJJZCk7XG5cdCAgICAgICAgY2xpZW50LnJlZ2lzdGVyKGhhbmRsZXJJZCwgd3JhcHBlZEhhbmRsZXIpO1xuXHQgICAgICAgIGF3YWl0IGNsaWVudC5kaXNwYXRjaCgnY29udGV4dEhhbmRsZXJSZWdpc3RlcmVkJywgeyBoYW5kbGVySWQsIGNvbnRleHRUeXBlIH0pO1xuXHQgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgIHVuc3Vic2NyaWJlOiBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgICAgICBjbGllbnQucmVtb3ZlKGhhbmRsZXJJZCk7XG5cdCAgICAgICAgICAgICAgICBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ3JlbW92ZUNvbnRleHRIYW5kbGVyJywgeyBoYW5kbGVySWQgfSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9O1xuXHQgICAgfVxuXHQgICAgLypcblx0ICAgIFBsYXRmb3JtIFdpbmRvdyBBUElzXG5cdCAgICAqL1xuXHQgICAgLyoqXG5cdCAgICAgKiBSZXR1cm5zIHRoZSBJbnRlcm9wLUJyb2tlci1kZWZpbmVkIGNvbnRleHQgZ3JvdXBzIGF2YWlsYWJsZSBmb3IgYW4gZW50aXR5IHRvIGpvaW4uXG5cdCAgICAgKiBVc2VkIGJ5IFBsYXRmb3JtIFdpbmRvd3MuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBmaW4ubWUuaW50ZXJvcC5nZXRDb250ZXh0R3JvdXBzKClcblx0ICAgICAqICAgICAgICAgLnRoZW4oY29udGV4dEdyb3VwcyA9PiB7XG5cdCAgICAgKiAgICAgICAgICAgICBjb250ZXh0R3JvdXBzLmZvckVhY2goY29udGV4dEdyb3VwID0+IHtcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhjb250ZXh0R3JvdXAuZGlzcGxheU1ldGFkYXRhLm5hbWUpXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coY29udGV4dEdyb3VwLmRpc3BsYXlNZXRhZGF0YS5jb2xvcilcblx0ICAgICAqICAgICAgICAgICAgIH0pXG5cdCAgICAgKiAgICAgICAgIH0pXG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0Q29udGV4dEdyb3VwcygpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtZ2V0LWNvbnRleHQtZ3JvdXBzJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnZ2V0Q29udGV4dEdyb3VwcycpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBKb2luIGFsbCBJbnRlcm9wIENsaWVudHMgYXQgdGhlIGdpdmVuIGlkZW50aXR5IHRvIGNvbnRleHQgZ3JvdXAgYGNvbnRleHRHcm91cElkYC5cblx0ICAgICAqIElmIG5vIHRhcmdldCBpcyBzcGVjaWZpZWQsIGl0IGFkZHMgdGhlIHNlbmRlciB0byB0aGUgY29udGV4dCBncm91cC5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBCZWNhdXNlIG11bHRpcGxlIENoYW5uZWwgY29ubmVjdGlvbnMvSW50ZXJvcCBDbGllbnRzIGNhbiBwb3RlbnRpYWxseSBleGlzdCBhdCBhIGB1dWlkYC9gbmFtZWAgY29tYm8sIHdlIGN1cnJlbnRseSBqb2luIGFsbCBDaGFubmVsIGNvbm5lY3Rpb25zL0ludGVyb3AgQ2xpZW50cyBhdCB0aGUgZ2l2ZW4gaWRlbnRpdHkgdG8gdGhlIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKiBJZiBhbiBgZW5kcG9pbnRJZGAgaXMgcHJvdmlkZWQgKHdoaWNoIGlzIHVubGlrZWx5LCB1bmxlc3MgdGhlIGNhbGwgaXMgY29taW5nIGZyb20gYW4gZXh0ZXJuYWwgYWRhcHRlciksIHRoZW4gd2Ugb25seSBqb2luIHRoYXQgc2luZ2xlIGNvbm5lY3Rpb24gdG8gdGhlIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKiBGb3IgYWxsIGludGVudHMgYW5kIHB1cnBvc2VzLCB0aGVyZSB3aWxsIG9ubHkgYmUgMSBjb25uZWN0aW9uIHByZXNlbnQgaW4gUGxhdGZvcm0gYW5kIEJyb3dzZXIgaW1wbG1lbnRhdGlvbnMsIHNvIHRoaXMgcG9pbnQgaXMgbW9yZS1vci1sZXNzIG1vb3QuXG5cdCAgICAgKiBVc2VkIGJ5IFBsYXRmb3JtIFdpbmRvd3MuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRHcm91cElkIC0gSWQgb2YgdGhlIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKiBAcGFyYW0gdGFyZ2V0IC0gSWRlbnRpdHkgb2YgdGhlIGVudGl0eSB5b3Ugd2lzaCB0byBqb2luIHRvIGEgY29udGV4dCBncm91cC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGpvaW5WaWV3VG9Db250ZXh0R3JvdXAgPSBhc3luYyAoY29udGV4dEdyb3VwSWQsIHZpZXcpID0+IHtcblx0ICAgICAqICAgICBhd2FpdCBmaW4ubWUuaW50ZXJvcC5qb2luQ29udGV4dEdyb3VwKGNvbnRleHRHcm91cElkLCB2aWV3KTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRMYXN0Rm9jdXNlZFZpZXcoKVxuXHQgICAgICogICAgIC50aGVuKGxhc3RGb2N1c2VkVmlld0lkZW50aXR5ID0+IHtcblx0ICAgICAqICAgICAgICAgam9pblZpZXdUb0NvbnRleHRHcm91cCgncmVkJywgbGFzdEZvY3VzZWRWaWV3SWRlbnRpdHkpXG5cdCAgICAgKiAgICAgfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBqb2luQ29udGV4dEdyb3VwKGNvbnRleHRHcm91cElkLCB0YXJnZXQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtam9pbi1jb250ZXh0LWdyb3VwJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgaWYgKCFjb250ZXh0R3JvdXBJZCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNvbnRleHRHcm91cElkIHNwZWNpZmllZCBmb3Igam9pbkNvbnRleHRHcm91cC4nKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnam9pbkNvbnRleHRHcm91cCcsIHsgY29udGV4dEdyb3VwSWQsIHRhcmdldCB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVtb3ZlcyB0aGUgc3BlY2lmaWVkIHRhcmdldCBmcm9tIGEgY29udGV4dCBncm91cC5cblx0ICAgICAqIElmIG5vIHRhcmdldCBpcyBzcGVjaWZpZWQsIGl0IHJlbW92ZXMgdGhlIHNlbmRlciBmcm9tIHRoZWlyIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKiBVc2VkIGJ5IFBsYXRmb3JtIFdpbmRvd3MuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIHRhcmdldCAtIElkZW50aXR5IG9mIHRoZSBlbnRpdHkgeW91IHdpc2ggdG8gam9pbiB0byBhIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiByZW1vdmVWaWV3RnJvbUNvbnRleHRHcm91cCA9IGFzeW5jICh2aWV3KSA9PiB7XG5cdCAgICAgKiAgICAgYXdhaXQgZmluLm1lLmludGVyb3AucmVtb3ZlRnJvbUNvbnRleHRHcm91cCh2aWV3KTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRMYXN0Rm9jdXNlZFZpZXcoKVxuXHQgICAgICogICAgIC50aGVuKGxhc3RGb2N1c2VkVmlld0lkZW50aXR5ID0+IHtcblx0ICAgICAqICAgICAgICAgcmVtb3ZlVmlld0Zyb21Db250ZXh0R3JvdXAobGFzdEZvY3VzZWRWaWV3SWRlbnRpdHkpXG5cdCAgICAgKiAgICAgfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyByZW1vdmVGcm9tQ29udGV4dEdyb3VwKHRhcmdldCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWNsaWVudC1yZW1vdmUtZnJvbS1jb250ZXh0LWdyb3VwJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgncmVtb3ZlRnJvbUNvbnRleHRHcm91cCcsIHsgdGFyZ2V0IH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBHZXRzIGFsbCBjbGllbnRzIGZvciBhIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgKipUaGlzIGlzIHByaW1hcmlseSB1c2VkIGZvciBwbGF0Zm9ybSB3aW5kb3dzLiBWaWV3cyB3aXRoaW4gYSBwbGF0Zm9ybSBzaG91bGQgbm90IGhhdmUgdG8gdXNlIHRoaXMgQVBJLioqXG5cdCAgICAgKlxuXHQgICAgICogUmV0dXJucyB0aGUgSW50ZXJvcC1Ccm9rZXItZGVmaW5lZCBjb250ZXh0IGdyb3VwcyBhdmFpbGFibGUgZm9yIGFuIGVudGl0eSB0byBqb2luLlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRHcm91cElkIC0gVGhlIGlkIG9mIGNvbnRleHQgZ3JvdXAgeW91IHdpc2ggdG8gZ2V0IGNsaWVudHMgZm9yLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLm1lLmludGVyb3AuZ2V0QWxsQ2xpZW50c0luQ29udGV4dEdyb3VwKCdyZWQnKVxuXHQgICAgICogICAgIC50aGVuKGNsaWVudHNJbkNvbnRleHRHcm91cCA9PiB7XG5cdCAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKGNsaWVudHNJbkNvbnRleHRHcm91cClcblx0ICAgICAqICAgICB9KVxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldEFsbENsaWVudHNJbkNvbnRleHRHcm91cChjb250ZXh0R3JvdXBJZCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWNsaWVudC1nZXQtYWxsLWNsaWVudHMtaW4tY29udGV4dC1ncm91cCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIGlmICghY29udGV4dEdyb3VwSWQpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjb250ZXh0R3JvdXBJZCBzcGVjaWZpZWQgZm9yIGdldEFsbENsaWVudHNJbkNvbnRleHRHcm91cC4nKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnZ2V0QWxsQ2xpZW50c0luQ29udGV4dEdyb3VwJywgeyBjb250ZXh0R3JvdXBJZCB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0cyBkaXNwbGF5IGluZm8gZm9yIGEgY29udGV4dCBncm91cFxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFVzZWQgYnkgUGxhdGZvcm0gV2luZG93cy5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0R3JvdXBJZCAtIFRoZSBpZCBvZiBjb250ZXh0IGdyb3VwIHlvdSB3aXNoIHRvIGdldCBkaXNwbGF5IGluZm8gZm9yLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLm1lLmludGVyb3AuZ2V0SW5mb0ZvckNvbnRleHRHcm91cCgncmVkJylcblx0ICAgICAqICAgICAudGhlbihjb250ZXh0R3JvdXBJbmZvID0+IHtcblx0ICAgICAqICAgICAgICAgY29uc29sZS5sb2coY29udGV4dEdyb3VwSW5mby5kaXNwbGF5TWV0YWRhdGEubmFtZSlcblx0ICAgICAqICAgICAgICAgY29uc29sZS5sb2coY29udGV4dEdyb3VwSW5mby5kaXNwbGF5TWV0YWRhdGEuY29sb3IpXG5cdCAgICAgKiAgICAgfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRJbmZvRm9yQ29udGV4dEdyb3VwKGNvbnRleHRHcm91cElkKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtY2xpZW50LWdldC1pbmZvLWZvci1jb250ZXh0LWdyb3VwJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgaWYgKCFjb250ZXh0R3JvdXBJZCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNvbnRleHRHcm91cElkIHNwZWNpZmllZCBmb3IgZ2V0SW5mb0ZvckNvbnRleHRHcm91cC4nKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnZ2V0SW5mb0ZvckNvbnRleHRHcm91cCcsIHsgY29udGV4dEdyb3VwSWQgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNlbmRzIGFuIGludGVudCB0byB0aGUgSW50ZXJvcCBCcm9rZXIgdG8gcmVzb2x2ZS5cblx0ICAgICAqIEBwYXJhbSBpbnRlbnQgLSBUaGUgY29tYmluYXRpb24gb2YgYW4gYWN0aW9uIGFuZCBhIGNvbnRleHQgdGhhdCBpcyBwYXNzZWQgdG8gYW4gYXBwbGljYXRpb24gZm9yIHJlc29sdXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiAvLyBWaWV3IHdhbnRzIHRvIGZpcmUgYW4gSW50ZW50IGFmdGVyIGEgdXNlciBjbGlja3Mgb24gYSB0aWNrZXJcblx0ICAgICAqIHRpY2tlckVsZW1lbnQub24oJ2NsaWNrJywgKGVsZW1lbnQpID0+IHtcblx0ICAgICAqICAgICBjb25zdCB0aWNrZXIgPSBlbGVtZW50LmlubmVyVGV4dDtcblx0ICAgICAqICAgICBjb25zdCBpbnRlbnQgPSB7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdWaWV3Q2hhcnQnLFxuXHQgICAgICogICAgICAgICBjb250ZXh0OiB7dHlwZTogJ2ZkYzMuaW5zdHJ1bWVudCcsIGlkOiB7IHRpY2tlciB9fVxuXHQgICAgICogICAgIH1cblx0ICAgICAqXG5cdCAgICAgKiAgICAgZmluLm1lLmludGVyb3AuZmlyZUludGVudChpbnRlbnQpO1xuXHQgICAgICogfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBmaXJlSW50ZW50KGludGVudCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWNsaWVudC1maXJlLWludGVudCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgdGhpcyBpcyBvbmx5IGZvciBhcGkgYW5hbHl0aWNzIHB1cnBvc2VzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnZmlyZUludGVudCcsIGludGVudCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEFkZHMgYW4gaW50ZW50IGhhbmRsZXIgZm9yIGluY29taW5nIGludGVudHMuIFRoZSBsYXN0IGludGVudCBzZW50IG9mIHRoZSBuYW1lIHN1YnNjcmliZWQgdG8gd2lsbCBiZSByZWNlaXZlZC5cblx0ICAgICAqIEBwYXJhbSBoYW5kbGVyIC0gUmVnaXN0ZXJlZCBmdW5jdGlvbiBtZWFudCB0byBoYW5kbGUgYSBzcGVjaWZpYyBpbnRlbnQgdHlwZS5cblx0ICAgICAqIEBwYXJhbSBpbnRlbnROYW1lIC0gVGhlIG5hbWUgb2YgYW4gaW50ZW50LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3QgaW50ZW50SGFuZGxlciA9IChpbnRlbnQpID0+IHtcblx0ICAgICAqICAgICBjb25zdCB7IGNvbnRleHQgfSA9IGludGVudDtcblx0ICAgICAqICAgICBteVZpZXdDaGFydEhhbmRsZXIoY29udGV4dCk7XG5cdCAgICAgKiB9O1xuXHQgICAgICpcblx0ICAgICAqIGNvbnN0IHN1YnNjcmlwdGlvbiA9IGF3YWl0IGZpbi5tZS5pbnRlcm9wLnJlZ2lzdGVySW50ZW50SGFuZGxlcihpbnRlbnRIYW5kbGVyLCAnVmlld0NoYXJ0Jyk7XG5cdCAgICAgKlxuXHQgICAgICogZnVuY3Rpb24gbXlBcHBDbG9zZVNlcXVlbmNlKCkge1xuXHQgICAgICogICAgIC8vIHRvIHVuc3Vic2NyaWJlIHRoZSBoYW5kbGVyLCBzaW1wbHkgY2FsbDpcblx0ICAgICAqICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcblx0ICAgICAqIH1cblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyByZWdpc3RlckludGVudEhhbmRsZXIoaGFuZGxlciwgaW50ZW50TmFtZSwgb3B0aW9ucykge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWNsaWVudC1yZWdpc3Rlci1pbnRlbnQtaGFuZGxlcicpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgdGhpcyBpcyBvbmx5IGZvciBhcGkgYW5hbHl0aWNzIHB1cnBvc2VzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgY29uc3QgaGFuZGxlcklkID0gYGludGVudC1oYW5kbGVyLSR7aW50ZW50TmFtZX1gO1xuXHQgICAgICAgIGNvbnN0IHdyYXBwZWRIYW5kbGVyID0gKDAsIHV0aWxzXzEud3JhcEludGVudEhhbmRsZXIpKGhhbmRsZXIsIGhhbmRsZXJJZCk7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgYXdhaXQgY2xpZW50LnJlZ2lzdGVyKGhhbmRsZXJJZCwgd3JhcHBlZEhhbmRsZXIpO1xuXHQgICAgICAgICAgICBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ2ludGVudEhhbmRsZXJSZWdpc3RlcmVkJywgeyBoYW5kbGVySWQsIC4uLm9wdGlvbnMgfSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byByZWdpc3RlciBpbnRlbnQgaGFuZGxlcicpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4ge1xuXHQgICAgICAgICAgICB1bnN1YnNjcmliZTogYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICAgICAgY2xpZW50LnJlbW92ZShoYW5kbGVySWQpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0cyB0aGUgbGFzdCBjb250ZXh0IG9mIHRoZSBDb250ZXh0IEdyb3VwIGN1cnJlbnRseSBzdWJzY3JpYmVkIHRvLiBJdCB0YWtlcyBhbiBvcHRpb25hbCBDb250ZXh0IFR5cGUgYW5kIHJldHVybnMgdGhlXG5cdCAgICAgKiBsYXN0IGNvbnRleHQgb2YgdGhhdCB0eXBlLlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRUeXBlXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhd2FpdCBmaW4ubWUuaW50ZXJvcC5qb2luQ29udGV4dEdyb3VwKCd5ZWxsb3cnKTtcblx0ICAgICAqIGF3YWl0IGZpbi5tZS5pbnRlcm9wLnNldENvbnRleHQoeyB0eXBlOiAnaW5zdHJ1bWVudCcsIGlkOiB7IHRpY2tlcjogJ0ZPTycgfX0pO1xuXHQgICAgICogY29uc3QgY3VycmVudENvbnRleHQgPSBhd2FpdCBmaW4ubWUuaW50ZXJvcC5nZXRDdXJyZW50Q29udGV4dCgpO1xuXHQgICAgICpcblx0ICAgICAqIC8vIHdpdGggYSBzcGVjaWZpYyBjb250ZXh0XG5cdCAgICAgKiBhd2FpdCBmaW4ubWUuaW50ZXJvcC5qb2luQ29udGV4dEdyb3VwKCd5ZWxsb3cnKTtcblx0ICAgICAqIGF3YWl0IGZpbi5tZS5pbnRlcm9wLnNldENvbnRleHQoeyB0eXBlOiAnY291bnRyeScsIGlkOiB7IElTT0FMUEhBMzogJ1VTJyB9fSk7XG5cdCAgICAgKiBhd2FpdCBmaW4ubWUuaW50ZXJvcC5zZXRDb250ZXh0KHsgdHlwZTogJ2luc3RydW1lbnQnLCBpZDogeyB0aWNrZXI6ICdGT08nIH19KTtcblx0ICAgICAqIGNvbnN0IGN1cnJlbnRDb250ZXh0ID0gYXdhaXQgZmluLm1lLmludGVyb3AuZ2V0Q3VycmVudENvbnRleHQoJ2NvdW50cnknKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRDdXJyZW50Q29udGV4dChjb250ZXh0VHlwZSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWNsaWVudC1nZXQtY3VycmVudC1jb250ZXh0JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnZ2V0Q3VycmVudENvbnRleHQnLCB7IGNvbnRleHRUeXBlIH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBHZXQgaW5mb3JtYXRpb24gZm9yIGEgcGFydGljdWxhciBJbnRlbnQgZnJvbSB0aGUgSW50ZXJvcCBCcm9rZXIuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgVG8gcmVzb2x2ZSB0aGlzIGluZm8sIHRoZSBmdW5jdGlvbiBoYW5kbGVJbmZvRm9ySW50ZW50IGlzIG1lYW50IHRvIGJlIG92ZXJyaWRkZW4gaW4gdGhlIEludGVyb3AgQnJva2VyLlxuXHQgICAgICogVGhlIGZvcm1hdCBmb3IgdGhlIHJlc3BvbnNlIHdpbGwgYmUgZGV0ZXJtaW5lZCBieSB0aGUgQXBwIFByb3ZpZGVyIG92ZXJyaWRpbmcgdGhlIGZ1bmN0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBvcHRpb25zXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCBpbnRlbnRJbmZvID0gYXdhaXQgZmluLm1lLmludGVyb3AuZ2V0SW5mb0ZvckludGVudCgnVmlld0NoYXJ0Jyk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0SW5mb0ZvckludGVudChvcHRpb25zKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtY2xpZW50LWdldC1pbmZvLWZvci1pbnRlbnQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQ2xpZW50X2NsaWVudFByb21pc2UsIFwiZlwiKTtcblx0ICAgICAgICByZXR1cm4gY2xpZW50LmRpc3BhdGNoKCdnZXRJbmZvRm9ySW50ZW50Jywgb3B0aW9ucyk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEdldCBpbmZvcm1hdGlvbiBmcm9tIHRoZSBJbnRlcm9wIEJyb2tlciBvbiBhbGwgSW50ZW50cyB0aGF0IGFyZSBtZWFudCB0byBoYW5kbGUgYSBwYXJ0aWN1bGFyIGNvbnRleHQuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgVG8gcmVzb2x2ZSB0aGlzIGluZm8sIHRoZSBmdW5jdGlvbiBoYW5kbGVJbmZvRm9ySW50ZW50c0J5Q29udGV4dCBpcyBtZWFudCB0byBiZSBvdmVycmlkZGVuIGluIHRoZSBJbnRlcm9wIEJyb2tlci5cblx0ICAgICAqIFRoZSBmb3JtYXQgZm9yIHRoZSByZXNwb25zZSB3aWxsIGJlIGRldGVybWluZWQgYnkgdGhlIEFwcCBQcm92aWRlciBvdmVycmlkaW5nIHRoZSBmdW5jdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dFxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogdGlja2VyRWxlbWVudC5vbignY2xpY2snLCAoZWxlbWVudCkgPT4ge1xuXHQgICAgICogICAgIGNvbnN0IHRpY2tlciA9IGVsZW1lbnQuaW5uZXJUZXh0O1xuXHQgICAgICpcblx0ICAgICAqICAgICBjb25zdCBjb250ZXh0ID0ge1xuXHQgICAgICogICAgICAgICB0eXBlOiAnZmRjMy5pbnN0cnVtZW50Jyxcblx0ICAgICAqICAgICAgICAgaWQ6IHtcblx0ICAgICAqICAgICAgICAgICAgIHRpY2tlclxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgfVxuXHQgICAgICpcblx0ICAgICAqICAgICBjb25zdCBpbnRlbnRzSW5mbyA9IGF3YWl0IGZpbi5tZS5pbnRlcm9wLmdldEluZm9Gb3JJbnRlbnRCeUNvbnRleHQoY29udGV4dCk7XG5cdCAgICAgKiB9KVxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldEluZm9Gb3JJbnRlbnRzQnlDb250ZXh0KGNvbnRleHQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtZ2V0LWluZm8tZm9yLWludGVudHMtYnktY29udGV4dCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2dldEluZm9Gb3JJbnRlbnRzQnlDb250ZXh0JywgY29udGV4dCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNlbmRzIGEgQ29udGV4dCB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgdG8gYW4gSW50ZW50IGJ5IHRoZSBJbnRlcm9wIEJyb2tlci5cblx0ICAgICAqIFRoaXMgY29udGV4dCBhY2NlcHRzIGEgbWV0YWRhdGEgcHJvcGVydHkuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgVG8gcmVzb2x2ZSB0aGlzIGluZm8sIHRoZSBmdW5jdGlvbiBoYW5kbGVGaXJlZEludGVudEJ5Q29udGV4dCBpcyBtZWFudCB0byBiZSBvdmVycmlkZGVuIGluIHRoZSBJbnRlcm9wIEJyb2tlci5cblx0ICAgICAqIFRoZSBmb3JtYXQgZm9yIHRoZSByZXNwb25zZSB3aWxsIGJlIGRldGVybWluZWQgYnkgdGhlIEFwcCBQcm92aWRlciBvdmVycmlkaW5nIHRoZSBmdW5jdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dFxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogdGlja2VyRWxlbWVudC5vbignY2xpY2snLCAoZWxlbWVudCkgPT4ge1xuXHQgICAgICogICAgIGNvbnN0IHRpY2tlciA9IGVsZW1lbnQuaW5uZXJUZXh0O1xuXHQgICAgICpcblx0ICAgICAqICAgICBjb25zdCBjb250ZXh0ID0ge1xuXHQgICAgICogICAgICAgICB0eXBlOiAnZmRjMy5pbnN0cnVtZW50Jyxcblx0ICAgICAqICAgICAgICAgaWQ6IHtcblx0ICAgICAqICAgICAgICAgICAgIHRpY2tlclxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgfVxuXHQgICAgICpcblx0ICAgICAqICAgICBjb25zdCBpbnRlbnRSZXNvbHV0aW9uID0gYXdhaXQgZmluLm1lLmludGVyb3AuZmlyZUludGVudEZvckNvbnRleHQoY29udGV4dCk7XG5cdCAgICAgKiB9KVxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGZpcmVJbnRlbnRGb3JDb250ZXh0KGNvbnRleHQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtZmlyZS1pbnRlbnQtZm9yLWNvbnRleHQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQ2xpZW50X2NsaWVudFByb21pc2UsIFwiZlwiKTtcblx0ICAgICAgICByZXR1cm4gY2xpZW50LmRpc3BhdGNoKCdmaXJlSW50ZW50Rm9yQ29udGV4dCcsIGNvbnRleHQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBKb2luIHRoZSBjdXJyZW50IGVudGl0eSB0byBzZXNzaW9uIGNvbnRleHQgZ3JvdXAgYHNlc3Npb25Db250ZXh0R3JvdXBJZGAgYW5kIHJldHVybiBhIHNlc3Npb25Db250ZXh0R3JvdXAgaW5zdGFuY2UuXG5cdCAgICAgKiBJZiB0aGUgc2Vzc2lvbkNvbnRleHRHcm91cCBkb2Vzbid0IGV4aXN0LCBvbmUgd2lsbCBnZXQgY3JlYXRlZC5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBTZXNzaW9uIENvbnRleHQgR3JvdXBzIGRvIG5vdCBwZXJzaXN0IGJldHdlZW4gcnVucyBhbmQgYXJlbid0IHByZXNlbnQgb24gc25hcHNob3RzLlxuXHQgICAgICogQHBhcmFtIHNlc3Npb25Db250ZXh0R3JvdXBJZCAtIElkIG9mIHRoZSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBTYXkgd2Ugd2FudCB0byBoYXZlIGEgU2Vzc2lvbiBDb250ZXh0IEdyb3VwIHRoYXQgaG9sZHMgVUkgdGhlbWUgaW5mb3JtYXRpb24gZm9yIGFsbCBhcHBzIHRvIGNvbnN1bWU6XG5cdCAgICAgKlxuXHQgICAgICogTXkgY29sb3ItcGlja2VyIFZpZXc6XG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogICAgIGNvbnN0IHRoZW1lU2Vzc2lvbkNvbnRleHRHcm91cCA9IGF3YWl0IGZpbi5tZS5pbnRlcm9wLmpvaW5TZXNzaW9uQ29udGV4dEdyb3VwKCd0aGVtZScpO1xuXHQgICAgICpcblx0ICAgICAqICAgICBjb25zdCBteUNvbG9yUGlja2VyRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjb2xvci1wYWxldHRlLXBpY2tlcicpO1xuXHQgICAgICogICAgIG15Q29sb3JQaWNrZXJFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIGV2ZW50ID0+IHtcblx0ICAgICAqICAgICAgICAgdGhlbWVTZXNzaW9uQ29udGV4dEdyb3VwLnNldENvbnRleHQoeyB0eXBlOiAnY29sb3ItcGFsZXR0ZScsIHNlbGVjdGlvbjogZXZlbnQudmFsdWUgfSk7XG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqXG5cdCAgICAgKiBJbiBvdGhlciB2aWV3czpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiAgICAgY29uc3QgdGhlbWVTZXNzaW9uQ29udGV4dEdyb3VwID0gYXdhaXQgZmluLm1lLmludGVyb3Auam9pblNlc3Npb25Db250ZXh0R3JvdXAoJ3RoZW1lJyk7XG5cdCAgICAgKlxuXHQgICAgICogICAgIGNvbnN0IGNoYW5nZUNvbG9yUGFsZXR0ZSA9ICh7IHNlbGVjdGlvbiB9KSA9PiB7XG5cdCAgICAgKiAgICAgICAgIC8vIGNoYW5nZSB0aGUgY29sb3IgcGFsZXR0ZSB0byB0aGUgc2VsZWN0aW9uXG5cdCAgICAgKiAgICAgfTtcblx0ICAgICAqXG5cdCAgICAgKiAgICAgLy8gSWYgdGhlIGNvbnRleHQgaXMgYWxyZWFkeSBzZXQgYnkgdGhlIHRpbWUgdGhlIGhhbmRsZXIgd2FzIHNldCwgdGhlIGhhbmRsZXIgd2lsbCBnZXQgaW52b2tlZCBpbW1lZGlhdGVseSB3aXRoIHRoZSBjdXJyZW50IGNvbnRleHQuXG5cdCAgICAgKiAgICAgdGhlbWVTZXNzaW9uQ29udGV4dEdyb3VwLmFkZENvbnRleHRIYW5kbGVyKGNoYW5nZUNvbG9yUGFsZXR0ZSwgJ2NvbG9yLXBhbGV0dGUnKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBqb2luU2Vzc2lvbkNvbnRleHRHcm91cChzZXNzaW9uQ29udGV4dEdyb3VwSWQpIHtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICBjb25zdCBjdXJyZW50U2Vzc2lvbkNvbnRleHRHcm91cCA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfc2Vzc2lvbkNvbnRleHRHcm91cHMsIFwiZlwiKS5nZXQoc2Vzc2lvbkNvbnRleHRHcm91cElkKTtcblx0ICAgICAgICAgICAgaWYgKGN1cnJlbnRTZXNzaW9uQ29udGV4dEdyb3VwKSB7XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudFNlc3Npb25Db250ZXh0R3JvdXAuZ2V0VXNlckluc3RhbmNlKCk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgICAgIGNvbnN0IHsgaGFzQ29uZmxpY3QgfSA9IGF3YWl0IGNsaWVudC5kaXNwYXRjaCgnc2Vzc2lvbkNvbnRleHRHcm91cDpjcmVhdGVJZk5lZWRlZCcsIHtcblx0ICAgICAgICAgICAgICAgIHNlc3Npb25Db250ZXh0R3JvdXBJZFxuXHQgICAgICAgICAgICB9KTtcblx0ICAgICAgICAgICAgaWYgKGhhc0NvbmZsaWN0KSB7XG5cdCAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYEEgKG5vbi1zZXNzaW9uKSBjb250ZXh0IGdyb3VwIHdpdGggdGhlIG5hbWUgXCIke3Nlc3Npb25Db250ZXh0R3JvdXBJZH1cIiBhbHJlYWR5IGV4aXN0cy4gSWYgeW91IGFyZSB0cnlpbmcgdG8gam9pbiBhIENvbnRleHQgR3JvdXAsIGNhbGwgam9pbkNvbnRleHRHcm91cCBpbnN0ZWFkLmApO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNvbnN0IG5ld1Nlc3Npb25Db250ZXh0R3JvdXAgPSBuZXcgU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudF8xLmRlZmF1bHQodGhpcy53aXJlLCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQ2xpZW50X2NsaWVudFByb21pc2UsIFwiZlwiKSwgc2Vzc2lvbkNvbnRleHRHcm91cElkKTtcblx0ICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9zZXNzaW9uQ29udGV4dEdyb3VwcywgXCJmXCIpLnNldChzZXNzaW9uQ29udGV4dEdyb3VwSWQsIG5ld1Nlc3Npb25Db250ZXh0R3JvdXApO1xuXHQgICAgICAgICAgICByZXR1cm4gbmV3U2Vzc2lvbkNvbnRleHRHcm91cC5nZXRVc2VySW5zdGFuY2UoKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIHRocm93biB0cnlpbmcgdG8gY3JlYXRlIFNlc3Npb24gQ29udGV4dCBHcm91cCB3aXRoIGlkIFwiJHtzZXNzaW9uQ29udGV4dEdyb3VwSWR9XCI6ICR7ZXJyb3J9YCk7XG5cdCAgICAgICAgICAgIHRocm93IGVycm9yO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVnaXN0ZXIgYSBsaXN0ZW5lciB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoZSBJbnRlcm9wIENsaWVudCBoYXMgYmVlbiBkaXNjb25uZWN0ZWQgZnJvbSB0aGUgSW50ZXJvcCBCcm9rZXIuXG5cdCAgICAgKiBPbmx5IG9uZSBsaXN0ZW5lciBwZXIgSW50ZXJvcCBDbGllbnQgY2FuIGJlIHNldC5cblx0ICAgICAqIEBwYXJhbSBsaXN0ZW5lclxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3QgbGlzdGVuZXIgPSAoZXZlbnQpID0+IHtcblx0ICAgICAqICAgICBjb25zdCB7IHR5cGUsIHRvcGljLCBicm9rZXJOYW1lfSA9IGV2ZW50O1xuXHQgICAgICogICAgIGNvbnNvbGUubG9nKGBEaXNjb25uZWN0ZWQgZnJvbSBJbnRlcm9wIEJyb2tlciAke2Jyb2tlck5hbWV9IGApO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGF3YWl0IGZpbi5tZS5pbnRlcm9wLm9uRGlzY29ubmVjdGlvbihsaXN0ZW5lcik7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgb25EaXNjb25uZWN0aW9uKGxpc3RlbmVyKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtY2xpZW50LWFkZC1vbmRpc2Nvbm5lY3Rpb24tbGlzdGVuZXInKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQ2xpZW50X2NsaWVudFByb21pc2UsIFwiZlwiKTtcblx0ICAgICAgICByZXR1cm4gY2xpZW50Lm9uRGlzY29ubmVjdGlvbigoZXZlbnQpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgeyB1dWlkIH0gPSBldmVudDtcblx0ICAgICAgICAgICAgbGlzdGVuZXIoeyB0eXBlOiAnaW50ZXJvcC1icm9rZXInLCB0b3BpYzogJ2Rpc2Nvbm5lY3RlZCcsIGJyb2tlck5hbWU6IHV1aWQgfSk7XG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdCAgICBnZXRGREMzU3luYyh2ZXJzaW9uKSB7XG5cdCAgICAgICAgc3dpdGNoICh2ZXJzaW9uKSB7XG5cdCAgICAgICAgICAgIGNhc2UgJzEuMic6XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gbmV3IGZkYzNfMV8yXzEuRmRjM01vZHVsZSgoKSA9PiB0aGlzLCB0aGlzLndpcmUpO1xuXHQgICAgICAgICAgICBjYXNlICcyLjAnOlxuXHQgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBmZGMzXzJfMF8xLkZkYzNNb2R1bGUyKCgpID0+IHRoaXMsIHRoaXMud2lyZSk7XG5cdCAgICAgICAgICAgIGRlZmF1bHQ6XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgRkRDMyB2ZXJzaW9uIHByb3ZpZGVkOiAke3ZlcnNpb259LiBNdXN0IGJlICcxLjInIG9yICcyLjAnYCk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgYXN5bmMgZ2V0RkRDMyh2ZXJzaW9uKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RkRDM1N5bmModmVyc2lvbik7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEBpbnRlcm5hbFxuXHQgICAgICpcblx0ICAgICAqIFVzZWQgdG8gZmVycnkgZmRjMy1vbmx5IGNhbGxzIGZyb20gdGhlIGZkYzMgc2hpbSB0byB0aGUgSW50ZXJvcCBCcm9rZXJcblx0ICAgICAqL1xuXHQgICAgc3RhdGljIGFzeW5jIGZlcnJ5RmRjM0NhbGwoaW50ZXJvcENsaWVudCwgYWN0aW9uLCBwYXlsb2FkKSB7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldChpbnRlcm9wQ2xpZW50LCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaChhY3Rpb24sIHBheWxvYWQgfHwgbnVsbCk7XG5cdCAgICB9XG5cdH07XG5cdEludGVyb3BDbGllbnQuSW50ZXJvcENsaWVudCA9IEludGVyb3BDbGllbnQkMTtcblx0X0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSA9IG5ldyBXZWFrTWFwKCksIF9JbnRlcm9wQ2xpZW50X3Nlc3Npb25Db250ZXh0R3JvdXBzID0gbmV3IFdlYWtNYXAoKTtcblx0cmV0dXJuIEludGVyb3BDbGllbnQ7XG59XG5cbnZhciBvdmVycmlkZUNoZWNrID0ge307XG5cbnZhciBoYXNSZXF1aXJlZE92ZXJyaWRlQ2hlY2s7XG5cbmZ1bmN0aW9uIHJlcXVpcmVPdmVycmlkZUNoZWNrICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkT3ZlcnJpZGVDaGVjaykgcmV0dXJuIG92ZXJyaWRlQ2hlY2s7XG5cdGhhc1JlcXVpcmVkT3ZlcnJpZGVDaGVjayA9IDE7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvdmVycmlkZUNoZWNrLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0b3ZlcnJpZGVDaGVjay5vdmVycmlkZUNoZWNrID0gb3ZlcnJpZGVDaGVjay5jaGVja0ZEQzMyT3ZlcnJpZGVzID0gb3ZlcnJpZGVDaGVjay5nZXREZWZhdWx0Vmlld0ZkYzNWZXJzaW9uRnJvbUFwcEluZm8gPSB2b2lkIDA7XG5cdGNvbnN0IEludGVyb3BCcm9rZXJfMSA9IHJlcXVpcmVJbnRlcm9wQnJva2VyKCk7XG5cdGZ1bmN0aW9uIGdldERlZmF1bHRWaWV3RmRjM1ZlcnNpb25Gcm9tQXBwSW5mbyh7IG1hbmlmZXN0LCBpbml0aWFsT3B0aW9ucyB9KSB7XG5cdCAgICBjb25zdCBzZXRWZXJzaW9uID0gbWFuaWZlc3Q/LnBsYXRmb3JtPy5kZWZhdWx0Vmlld09wdGlvbnM/LmZkYzNJbnRlcm9wQXBpID8/IGluaXRpYWxPcHRpb25zLmRlZmF1bHRWaWV3T3B0aW9ucz8uZmRjM0ludGVyb3BBcGk7XG5cdCAgICByZXR1cm4gWycxLjInLCAnMi4wJ10uaW5jbHVkZXMoc2V0VmVyc2lvbiA/PyAnJykgPyBzZXRWZXJzaW9uIDogdW5kZWZpbmVkO1xuXHR9XG5cdG92ZXJyaWRlQ2hlY2suZ2V0RGVmYXVsdFZpZXdGZGMzVmVyc2lvbkZyb21BcHBJbmZvID0gZ2V0RGVmYXVsdFZpZXdGZGMzVmVyc2lvbkZyb21BcHBJbmZvO1xuXHRmdW5jdGlvbiBjaGVja0ZEQzMyT3ZlcnJpZGVzKG92ZXJyaWRkZW5Ccm9rZXIpIHtcblx0ICAgIC8vIFRoZXNlIGFyZSB0aGUgQVBJcyB0aGF0IG11c3QgYmUgb3ZlcnJpZGRlbiBmb3IgRkRDMyAyLjAgY29tcGxpYW5jZVxuXHQgICAgY29uc3QgbXVzdE92ZXJyaWRlQVBJcyA9IFtcblx0ICAgICAgICAnZmRjM0hhbmRsZUZpbmRJbnN0YW5jZXMnLFxuXHQgICAgICAgICdoYW5kbGVJbmZvRm9ySW50ZW50Jyxcblx0ICAgICAgICAnaGFuZGxlSW5mb0ZvckludGVudHNCeUNvbnRleHQnLFxuXHQgICAgICAgICdmZGMzSGFuZGxlR2V0QXBwTWV0YWRhdGEnLFxuXHQgICAgICAgICdmZGMzSGFuZGxlR2V0SW5mbycsXG5cdCAgICAgICAgJ2ZkYzNIYW5kbGVPcGVuJyxcblx0ICAgICAgICAnaGFuZGxlRmlyZWRJbnRlbnQnLFxuXHQgICAgICAgICdoYW5kbGVGaXJlZEludGVudEZvckNvbnRleHQnXG5cdCAgICBdO1xuXHQgICAgcmV0dXJuIG11c3RPdmVycmlkZUFQSXMuZmlsdGVyKChhcGkpID0+IHtcblx0ICAgICAgICByZXR1cm4gb3ZlcnJpZGRlbkJyb2tlclthcGldID09PSBJbnRlcm9wQnJva2VyXzEuSW50ZXJvcEJyb2tlci5wcm90b3R5cGVbYXBpXTtcblx0ICAgIH0pO1xuXHR9XG5cdG92ZXJyaWRlQ2hlY2suY2hlY2tGREMzMk92ZXJyaWRlcyA9IGNoZWNrRkRDMzJPdmVycmlkZXM7XG5cdGZ1bmN0aW9uIG92ZXJyaWRlQ2hlY2skMShvdmVycmlkZGVuQnJva2VyLCBmZGMzSW50ZXJvcEFwaSkge1xuXHQgICAgaWYgKGZkYzNJbnRlcm9wQXBpICYmIGZkYzNJbnRlcm9wQXBpID09PSAnMi4wJykge1xuXHQgICAgICAgIGNvbnN0IG5vdE92ZXJyaWRkZW4gPSBjaGVja0ZEQzMyT3ZlcnJpZGVzKG92ZXJyaWRkZW5Ccm9rZXIpO1xuXHQgICAgICAgIGlmIChub3RPdmVycmlkZGVuLmxlbmd0aCA+IDApIHtcblx0ICAgICAgICAgICAgY29uc29sZS53YXJuKGBXQVJOSU5HOiBGREMzIDIuMCBoYXMgYmVlbiBzZXQgYXMgYSBkZWZhdWx0IG9wdGlvbiBmb3IgVmlld3MgaW4gdGhpcyBQbGF0Zm9ybSwgYnV0IHRoZSByZXF1aXJlZCBJbnRlcm9wQnJva2VyIEFQSXMgZm9yIEZEQzMgMi4wIGNvbXBsaWFuY2UgaGF2ZSBub3QgYWxsIGJlZW4gb3ZlcnJpZGRlbi5cXG5UaGUgZm9sbG93aW5nIEFQSXMgbmVlZCB0byBiZSBvdmVycmlkZGVuOlxcbiR7bm90T3ZlcnJpZGRlbi5qb2luKCdcXG4nKX1gKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdH1cblx0b3ZlcnJpZGVDaGVjay5vdmVycmlkZUNoZWNrID0gb3ZlcnJpZGVDaGVjayQxO1xuXHRyZXR1cm4gb3ZlcnJpZGVDaGVjaztcbn1cblxudmFyIGhhc1JlcXVpcmVkRmFjdG9yeTtcblxuZnVuY3Rpb24gcmVxdWlyZUZhY3RvcnkgKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRGYWN0b3J5KSByZXR1cm4gRmFjdG9yeSQxO1xuXHRoYXNSZXF1aXJlZEZhY3RvcnkgPSAxO1xuXHR2YXIgX19pbXBvcnREZWZhdWx0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9faW1wb3J0RGVmYXVsdCkgfHwgZnVuY3Rpb24gKG1vZCkge1xuXHQgICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBcImRlZmF1bHRcIjogbW9kIH07XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShGYWN0b3J5JDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRGYWN0b3J5JDEuSW50ZXJvcE1vZHVsZSA9IHZvaWQgMDtcblx0Y29uc3QgY2xvbmVEZWVwXzEgPSBfX2ltcG9ydERlZmF1bHQocmVxdWlyZSQkMCQxKTtcblx0Y29uc3QgaW5hY2Nlc3NpYmxlT2JqZWN0XzEgPSBpbmFjY2Vzc2libGVPYmplY3Q7XG5cdGNvbnN0IGJhc2VfMSA9IGJhc2U7XG5cdGNvbnN0IEludGVyb3BCcm9rZXJfMSA9IHJlcXVpcmVJbnRlcm9wQnJva2VyKCk7XG5cdGNvbnN0IEludGVyb3BDbGllbnRfMSA9IHJlcXVpcmVJbnRlcm9wQ2xpZW50KCk7XG5cdGNvbnN0IG92ZXJyaWRlQ2hlY2tfMSA9IHJlcXVpcmVPdmVycmlkZUNoZWNrKCk7XG5cdGNvbnN0IGNvbW1vbl91dGlsc18xID0gY29tbW9uVXRpbHM7XG5cdGNvbnN0IGRlZmF1bHRPdmVycmlkZSA9IChDbGFzcykgPT4gbmV3IENsYXNzKCk7XG5cdGNvbnN0IEJyb2tlclBhcmFtQWNjZXNzRXJyb3IgPSAnWW91IGhhdmUgYXR0ZW1wdGVkIHRvIHVzZSBvciBtb2RpZnkgSW50ZXJvcEJyb2tlciBwYXJhbWV0ZXJzLCB3aGljaCBpcyBub3QgYWxsb3dlZC4gWW91IGFyZSBsaWtlbHkgdXNpbmcgYW4gb2xkZXIgSW50ZXJvcEJyb2tlciBvdmVycmlkZSBzY2hlbWUuIFBsZWFzZSBjb25zdWx0IG91ciBJbnRlcm9wIGRvY3MgZm9yIGd1aWRhbmNlIG9uIG1pZ3JhdGluZyB0byB0aGUgbmV3IG92ZXJyaWRlIHNjaGVtZS4nO1xuXHQvKipcblx0ICogTWFuYWdlcyBjcmVhdGlvbiBvZiBJbnRlcm9wIEJyb2tlcnMgYW5kIEludGVyb3AgQ2xpZW50cy4gVGhlc2UgQVBJcyBhcmUgY2FsbGVkIHVuZGVyLXRoZS1ob29kIGluIFBsYXRmb3Jtcy5cblx0ICpcblx0ICovXG5cdGNsYXNzIEludGVyb3BNb2R1bGUgZXh0ZW5kcyBiYXNlXzEuQmFzZSB7XG5cdCAgICAvKipcblx0ICAgICAqIEluaXRpYWxpemVzIGFuIEludGVyb3AgQnJva2VyLiBUaGlzIGlzIGNhbGxlZCB1bmRlci10aGUtaG9vZCBmb3IgUGxhdGZvcm1zLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIEZvciBQbGF0Zm9ybXMsIHRoaXMgaXMgc2V0IHVwIGF1dG9tYXRpY2FsbHkuIFdlIGFkdmlzZSB0byBvbmx5IGNyZWF0ZSB5b3VyIG93biBJbnRlcm9wIEJyb2tlclxuXHQgICAgICogd2hlbiBub3QgdXNpbmcgYSBQbGF0Zm9ybSBhcHAuIFlvdSBjYW4gb3ZlcnJpZGUgZnVuY3Rpb25zIGluIHRoZSBJbnRlcm9wIEJyb2tlci4gTW9yZSBpbmZvIHtAbGluayBJbnRlcm9wQnJva2VyIGhlcmV9LlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBuYW1lIC0gTmFtZSBvZiB0aGUgSW50ZXJvcCBCcm9rZXIuXG5cdCAgICAgKiBAcGFyYW0gb3ZlcnJpZGUgLSBBIGNhbGxiYWNrIGZ1bmN0aW9uIG9yIGFycmF5IG9mIGNhbGxiYWNrIGZ1bmN0aW9ucyB0aGF0IGNhbiBiZSB1c2VkIHRvIGV4dGVuZCBvciByZXBsYWNlIGRlZmF1bHQgSW50ZXJvcCBCcm9rZXIgYmVoYXZpb3IuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYCBqc1xuXHQgICAgICogY29uc3QgaW50ZXJvcEJyb2tlciA9IGF3YWl0IGZpbi5JbnRlcm9wLmluaXQoJ29wZW5maW4nKTtcblx0ICAgICAqIGNvbnN0IGNvbnRleHRHcm91cHMgPSBhd2FpdCBpbnRlcm9wQnJva2VyLmdldENvbnRleHRHcm91cHMoKTtcblx0ICAgICAqIGNvbnNvbGUubG9nKGNvbnRleHRHcm91cHMpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGluaXQobmFtZSwgb3ZlcnJpZGUgPSBkZWZhdWx0T3ZlcnJpZGUpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1pbml0JykuY2F0Y2goKCkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICAvLyBBbGxvd3MgZm9yIG1hbmlmZXN0LWxldmVsIGNvbmZpZ3VyYXRpb24sIHdpdGhvdXQgaGF2aW5nIHRvIG92ZXJyaWRlLiAoZS5nLiBzcGVjaWZ5aW5nIGN1c3RvbSBjb250ZXh0IGdyb3Vwcylcblx0ICAgICAgICBjb25zdCBvcHRpb25zID0gYXdhaXQgdGhpcy53aXJlLmVudmlyb25tZW50LmdldEludGVyb3BJbmZvKHRoaXMud2lyZS5nZXRGaW4oKSk7XG5cdCAgICAgICAgY29uc3Qgb2JqZWN0VGhhdFRocm93cyA9ICgwLCBpbmFjY2Vzc2libGVPYmplY3RfMS5jcmVhdGVVbnVzYWJsZU9iamVjdCkoQnJva2VyUGFyYW1BY2Nlc3NFcnJvcik7XG5cdCAgICAgICAgY29uc3Qgd2FybmluZ09wdHNDbG9uZSA9ICgwLCBpbmFjY2Vzc2libGVPYmplY3RfMS5jcmVhdGVXYXJuaW5nT2JqZWN0KShCcm9rZXJQYXJhbUFjY2Vzc0Vycm9yLCAoMCwgY2xvbmVEZWVwXzEuZGVmYXVsdCkob3B0aW9ucykpO1xuXHQgICAgICAgIGNvbnN0IGdldFByb3ZpZGVyID0gKCkgPT4ge1xuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy5maW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZShgaW50ZXJvcC1icm9rZXItJHtuYW1lfWApO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgY29uc3QgdGhyb3dpbmdHZXRQcm92aWRlciA9IGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKEJyb2tlclBhcmFtQWNjZXNzRXJyb3IpO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgY29uc3QgT3ZlcnJpZGVhYmxlQnJva2VyID0gSW50ZXJvcEJyb2tlcl8xLkludGVyb3BCcm9rZXIuY3JlYXRlQ2xvc2VkQ29uc3RydWN0b3IodGhpcy53aXJlLCBnZXRQcm92aWRlciwgb3B0aW9ucyk7XG5cdCAgICAgICAgbGV0IGJyb2tlcjtcblx0ICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShvdmVycmlkZSkpIHtcblx0ICAgICAgICAgICAgY29uc3QgQnJva2VyQ29uc3RydWN0b3IgPSAoMCwgY29tbW9uX3V0aWxzXzEub3ZlcnJpZGVGcm9tQ29tcG9zYWJsZXMpKC4uLm92ZXJyaWRlKShPdmVycmlkZWFibGVCcm9rZXIpO1xuXHQgICAgICAgICAgICAvLyBXZSBuZWVkIHRvIHVzZSB0aGVzZSBvYmplY3RzIGJlY2F1c2UgcmVtb3ZpbmcgdGhlbSBlbnRpcmVseSB3b3VsZCBiZSBhIGJyZWFraW5nIGNoYW5nZSBhbmQgd2Ugd2FudCBhbiBpbmZvcm1hdGl2ZSBlcnJvclxuXHQgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG5cdCAgICAgICAgICAgIGJyb2tlciA9IG5ldyBCcm9rZXJDb25zdHJ1Y3RvcihvYmplY3RUaGF0VGhyb3dzLCB0aHJvd2luZ0dldFByb3ZpZGVyLCB3YXJuaW5nT3B0c0Nsb25lKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIC8vIFdlIG5lZWQgdG8gdXNlIHRoZXNlIG9iamVjdHMgYmVjYXVzZSByZW1vdmluZyB0aGVtIGVudGlyZWx5IHdvdWxkIGJlIGEgYnJlYWtpbmcgY2hhbmdlIGFuZCB3ZSB3YW50IGFuIGluZm9ybWF0aXZlIGVycm9yXG5cdCAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3Jcblx0ICAgICAgICAgICAgYnJva2VyID0gYXdhaXQgb3ZlcnJpZGUoT3ZlcnJpZGVhYmxlQnJva2VyLCBvYmplY3RUaGF0VGhyb3dzLCB0aHJvd2luZ0dldFByb3ZpZGVyLCB3YXJuaW5nT3B0c0Nsb25lKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgKDAsIG92ZXJyaWRlQ2hlY2tfMS5vdmVycmlkZUNoZWNrKShicm9rZXIsIG9wdGlvbnMuZmRjM1ZlcnNpb24pO1xuXHQgICAgICAgIHJldHVybiBicm9rZXI7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIENvbm5lY3RzIGEgY2xpZW50IHRvIGFuIEludGVyb3AgYnJva2VyLiBUaGlzIGlzIGNhbGxlZCB1bmRlci10aGUtaG9vZCBmb3IgVmlld3MgaW4gYSBQbGF0Zm9ybS5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrc1xuXHQgICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgSW50ZXJvcCBCcm9rZXIgdG8gY29ubmVjdCB0by4gRm9yIFBsYXRmb3JtcywgdGhpcyB3aWxsIGRlZmF1bHQgdG8gdGhlIHV1aWQgb2YgdGhlIFBsYXRmb3JtLlxuXHQgICAgICogQHBhcmFtIGludGVyb3BDb25maWcgLSBJbmZvcm1hdGlvbiByZWxldmFudCB0byB0aGUgSW50ZXJvcCBCcm9rZXIuIFR5cGljYWxseSBhIGRlY2xhcmF0aW9uIG9mXG5cdCAgICAgKiB3aGF0IGNvbnRleHQocykgdGhlIGVudGl0eSB3YW50cyB0byBzdWJzY3JpYmUgdG8sIGFuZCB0aGUgY3VycmVudCBDb250ZXh0IEdyb3VwIG9mIHRoZSBlbnRpdHkuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCBpbnRlcm9wQ29uZmlnID0ge1xuXHQgICAgICogICAgIGN1cnJlbnRDb250ZXh0R3JvdXA6ICdncmVlbidcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBjb25zdCBpbnRlcm9wQnJva2VyID0gYXdhaXQgZmluLkludGVyb3AuaW5pdCgnb3BlbmZpbicpO1xuXHQgICAgICogY29uc3QgY2xpZW50ID0gYXdhaXQgZmluLkludGVyb3AuY29ubmVjdFN5bmMoJ29wZW5maW4nLCBpbnRlcm9wQ29uZmlnKTtcblx0ICAgICAqIGNvbnN0IGNvbnRleHRHcm91cEluZm8gPSBhd2FpdCBjbGllbnQuZ2V0SW5mb0ZvckNvbnRleHRHcm91cCgpO1xuXHQgICAgICogY29uc29sZS5sb2coY29udGV4dEdyb3VwSW5mbyk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgY29ubmVjdFN5bmMobmFtZSwgaW50ZXJvcENvbmZpZykge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWNvbm5lY3Qtc3luYycpLmNhdGNoKCgpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIG5ldyBJbnRlcm9wQ2xpZW50XzEuSW50ZXJvcENsaWVudCh0aGlzLndpcmUsIHRoaXMud2lyZS5lbnZpcm9ubWVudC53aGVuUmVhZHkoKS50aGVuKCgpID0+IHtcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KGBpbnRlcm9wLWJyb2tlci0ke25hbWV9YCwge1xuXHQgICAgICAgICAgICAgICAgcGF5bG9hZDogaW50ZXJvcENvbmZpZ1xuXHQgICAgICAgICAgICB9KTtcblx0ICAgICAgICB9KSk7XG5cdCAgICB9XG5cdH1cblx0RmFjdG9yeSQxLkludGVyb3BNb2R1bGUgPSBJbnRlcm9wTW9kdWxlO1xuXHRyZXR1cm4gRmFjdG9yeSQxO1xufVxuXG52YXIgaGFzUmVxdWlyZWRJbnRlcm9wO1xuXG5mdW5jdGlvbiByZXF1aXJlSW50ZXJvcCAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEludGVyb3ApIHJldHVybiBpbnRlcm9wO1xuXHRoYXNSZXF1aXJlZEludGVyb3AgPSAxO1xuXHQoZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0XHQvKipcblx0XHQgKiBFbnRyeSBwb2ludCBmb3IgdGhlIE9wZW5GaW4gYEludGVyb3BgIEFQSSAoYGZpbi5JbnRlcm9wYCkuXG5cdFx0ICpcblx0XHQgKiAqIHtAbGluayBJbnRlcm9wTW9kdWxlfSBjb250YWlucyBzdGF0aWMgbWVtYmVycyBvZiB0aGUgYEludGVyb3BgIEFQSSAoYXZhaWxhYmxlIHVuZGVyIGBmaW4uSW50ZXJvcGApXG5cdFx0ICogKiB7QGxpbmsgSW50ZXJvcENsaWVudH0gYW5kIHtAbGluayBJbnRlcm9wQnJva2VyfSBkb2N1bWVudCBpbnN0YW5jZXMgb2YgdGhlaXIgcmVzcGVjdGl2ZSBjbGFzc2VzLlxuXHRcdCAqXG5cdFx0ICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG5cdFx0ICovXG5cdFx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdFx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdFx0ICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcblx0XHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0XHQgICAgICBkZXNjID0geyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbVtrXTsgfSB9O1xuXHRcdCAgICB9XG5cdFx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdFx0fSkgOiAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0XHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0XHQgICAgb1trMl0gPSBtW2tdO1xuXHRcdH0pKTtcblx0XHR2YXIgX19leHBvcnRTdGFyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fZXhwb3J0U3RhcikgfHwgZnVuY3Rpb24obSwgZXhwb3J0cykge1xuXHRcdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdFx0fTtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdFx0X19leHBvcnRTdGFyKHJlcXVpcmVGYWN0b3J5KCksIGV4cG9ydHMpO1xuXHRcdF9fZXhwb3J0U3RhcihyZXF1aXJlSW50ZXJvcENsaWVudCgpLCBleHBvcnRzKTtcblx0XHRfX2V4cG9ydFN0YXIocmVxdWlyZUludGVyb3BCcm9rZXIoKSwgZXhwb3J0cyk7IFxuXHR9IChpbnRlcm9wKSk7XG5cdHJldHVybiBpbnRlcm9wO1xufVxuXG52YXIgc25hcHNob3RTb3VyY2UgPSB7fTtcblxudmFyIEZhY3RvcnkgPSB7fTtcblxudmFyIEluc3RhbmNlID0ge307XG5cbnZhciB1dGlscyA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkodXRpbHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudXRpbHMuZ2V0U25hcHNob3RTb3VyY2VDaGFubmVsTmFtZSA9IHZvaWQgMDtcbmNvbnN0IGNoYW5uZWxQcmVmaXggPSAnc25hcHNob3Qtc291cmNlLXByb3ZpZGVyLSc7XG5jb25zdCBnZXRTbmFwc2hvdFNvdXJjZUNoYW5uZWxOYW1lID0gKGlkKSA9PiBgJHtjaGFubmVsUHJlZml4fSR7aWQudXVpZH1gO1xudXRpbHMuZ2V0U25hcHNob3RTb3VyY2VDaGFubmVsTmFtZSA9IGdldFNuYXBzaG90U291cmNlQ2hhbm5lbE5hbWU7XG5cbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDEgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XG59O1xudmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMSA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9TbmFwc2hvdFNvdXJjZV9pZGVudGl0eSwgX1NuYXBzaG90U291cmNlX2dldENvbm5lY3Rpb24sIF9TbmFwc2hvdFNvdXJjZV9nZXRDbGllbnQsIF9TbmFwc2hvdFNvdXJjZV9zdGFydENvbm5lY3Rpb24sIF9TbmFwc2hvdFNvdXJjZV9zZXRVcENvbm5lY3Rpb25MaXN0ZW5lcjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShJbnN0YW5jZSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5JbnN0YW5jZS5TbmFwc2hvdFNvdXJjZSA9IHZvaWQgMDtcbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb24gKi9cbmNvbnN0IGJhc2VfMSQxID0gYmFzZTtcbmNvbnN0IHV0aWxzXzEkMSA9IHV0aWxzO1xuY29uc3QgY29ubmVjdGlvbk1hcCA9IG5ldyBNYXAoKTtcbi8qKlxuICogRW5hYmxlcyBjb25maWd1cmluZyBhIFNuYXBzaG90U291cmNlIHdpdGggY3VzdG9tIGdldFNuYXBzaG90IGFuZCBhcHBseVNuYXBzaG90IG1ldGhvZHMuXG4gKlxuICogQHR5cGVQYXJhbSBTbmFwc2hvdCBJbXBsZW1lbnRhdGlvbi1kZWZpbmVkIHNoYXBlIG9mIGFuIGFwcGxpY2F0aW9uIHNuYXBzaG90LiAgQWxsb3dzXG4gKiBjdXN0b20gc25hcHNob3QgaW1wbGVtZW50YXRpb25zIGZvciBsZWdhY3kgYXBwbGljYXRpb25zIHRvIGRlZmluZSB0aGVpciBvd24gc25hcHNob3QgZm9ybWF0LlxuICovXG5jbGFzcyBTbmFwc2hvdFNvdXJjZSBleHRlbmRzIGJhc2VfMSQxLkJhc2Uge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHdpcmUsIGlkKSB7XG4gICAgICAgIHN1cGVyKHdpcmUpO1xuICAgICAgICBfU25hcHNob3RTb3VyY2VfaWRlbnRpdHkuc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIF9TbmFwc2hvdFNvdXJjZV9nZXRDb25uZWN0aW9uLnNldCh0aGlzLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWNvbm5lY3Rpb25NYXAuaGFzKHRoaXMuaWRlbnRpdHkudXVpZCkpIHtcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uTWFwLnNldCh0aGlzLmlkZW50aXR5LnV1aWQsIHsgZXZlbnRGaXJlZDogbnVsbCwgY2xpZW50UHJvbWlzZTogbnVsbCB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjb25uZWN0aW9uTWFwLmdldCh0aGlzLmlkZW50aXR5LnV1aWQpO1xuICAgICAgICB9KTtcbiAgICAgICAgX1NuYXBzaG90U291cmNlX2dldENsaWVudC5zZXQodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2dldENvbm5lY3Rpb24sIFwiZlwiKS5jYWxsKHRoaXMpLmNsaWVudFByb21pc2UpIHtcbiAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2dldENvbm5lY3Rpb24sIFwiZlwiKS5jYWxsKHRoaXMpLmNsaWVudFByb21pc2UgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX3N0YXJ0Q29ubmVjdGlvbiwgXCJmXCIpLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gX19jbGFzc1ByaXZhdGVGaWVsZEdldCQxKHRoaXMsIF9TbmFwc2hvdFNvdXJjZV9nZXRDb25uZWN0aW9uLCBcImZcIikuY2FsbCh0aGlzKS5jbGllbnRQcm9taXNlO1xuICAgICAgICB9KTtcbiAgICAgICAgX1NuYXBzaG90U291cmNlX3N0YXJ0Q29ubmVjdGlvbi5zZXQodGhpcywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY2hhbm5lbE5hbWUgPSAoMCwgdXRpbHNfMSQxLmdldFNuYXBzaG90U291cmNlQ2hhbm5lbE5hbWUpKHRoaXMuaWRlbnRpdHkpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAoIV9fY2xhc3NQcml2YXRlRmllbGRHZXQkMSh0aGlzLCBfU25hcHNob3RTb3VyY2VfZ2V0Q29ubmVjdGlvbiwgXCJmXCIpLmNhbGwodGhpcykuZXZlbnRGaXJlZCkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX3NldFVwQ29ubmVjdGlvbkxpc3RlbmVyLCBcImZcIikuY2FsbCh0aGlzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5maW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3QoY2hhbm5lbE5hbWUsIHsgd2FpdDogZmFsc2UgfSk7XG4gICAgICAgICAgICAgICAgY2xpZW50Lm9uRGlzY29ubmVjdGlvbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMSh0aGlzLCBfU25hcHNob3RTb3VyY2VfZ2V0Q29ubmVjdGlvbiwgXCJmXCIpLmNhbGwodGhpcykuY2xpZW50UHJvbWlzZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMSh0aGlzLCBfU25hcHNob3RTb3VyY2VfZ2V0Q29ubmVjdGlvbiwgXCJmXCIpLmNhbGwodGhpcykuZXZlbnRGaXJlZCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNsaWVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQxKHRoaXMsIF9TbmFwc2hvdFNvdXJjZV9nZXRDb25uZWN0aW9uLCBcImZcIikuY2FsbCh0aGlzKS5jbGllbnRQcm9taXNlID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJUaGUgdGFyZ2V0ZWQgU25hcHNob3RTb3VyY2UgaXMgbm90IGN1cnJlbnRseSBpbml0aWFsaXplZC4gQXdhaXQgdGhpcyBvYmplY3QncyByZWFkeSgpIG1ldGhvZC5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBfU25hcHNob3RTb3VyY2Vfc2V0VXBDb25uZWN0aW9uTGlzdGVuZXIuc2V0KHRoaXMsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5uZWxOYW1lID0gKDAsIHV0aWxzXzEkMS5nZXRTbmFwc2hvdFNvdXJjZUNoYW5uZWxOYW1lKSh0aGlzLmlkZW50aXR5KTtcbiAgICAgICAgICAgIGxldCByZXNvbHZlO1xuICAgICAgICAgICAgbGV0IHJlamVjdDtcbiAgICAgICAgICAgIGNvbnN0IGV2ZW50RmlyZWQgPSBuZXcgUHJvbWlzZSgoeSwgbikgPT4ge1xuICAgICAgICAgICAgICAgIHJlc29sdmUgPSB5O1xuICAgICAgICAgICAgICAgIHJlamVjdCA9IG47XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMSh0aGlzLCBfU25hcHNob3RTb3VyY2VfZ2V0Q29ubmVjdGlvbiwgXCJmXCIpLmNhbGwodGhpcykuZXZlbnRGaXJlZCA9IGV2ZW50RmlyZWQ7XG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IGFzeW5jIChlKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGUuY2hhbm5lbE5hbWUgPT09IGNoYW5uZWxOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwucmVtb3ZlTGlzdGVuZXIoJ2Nvbm5lY3RlZCcsIGxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwub24oJ2Nvbm5lY3RlZCcsIGxpc3RlbmVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkMSh0aGlzLCBfU25hcHNob3RTb3VyY2VfaWRlbnRpdHksIGlkLCBcImZcIik7XG4gICAgfVxuICAgIGdldCBpZGVudGl0eSgpIHtcbiAgICAgICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMSh0aGlzLCBfU25hcHNob3RTb3VyY2VfaWRlbnRpdHksIFwiZlwiKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogTWV0aG9kIHRvIGRldGVybWluZSBpZiB0aGUgU25hcHNob3RTb3VyY2UgaGFzIGJlZW4gaW5pdGlhbGl6ZWQuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBVc2Ugd2hlbiB0aGUgcGFyZW50IGFwcGxpY2F0aW9uIGlzIHN0YXJ0aW5nIHVwIHRvIGVuc3VyZSB0aGUgU25hcHNob3RTb3VyY2UgaXMgYWJsZSB0byBhY2NlcHQgYW5kXG4gICAgICogYXBwbHkgYSBzbmFwc2hvdCB1c2luZyB0aGUge0BsaW5rIFNuYXBzaG90U291cmNlI2FwcGx5U25hcHNob3QgYXBwbHlTbmFwc2hvdH0gbWV0aG9kLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGxldCBzbmFwc2hvdFNvdXJjZSA9IGZpbi5TbmFwc2hvdFNvdXJjZS53cmFwU3luYyhmaW4ubWUpO1xuICAgICAqXG4gICAgICogY29uc3Qgc25hcHNob3RQcm92aWRlciA9IHtcbiAgICAgKiAgICAgYXN5bmMgZ2V0U25hcHNob3QoKSB7IHJldHVybiAnZm9vJyB9LFxuICAgICAqICAgICBhc3luYyBhcHBseVNuYXBzaG90KHNuYXBzaG90KSB7XG4gICAgICogICAgICAgY29uc29sZS5sb2coc25hcHNob3QpO1xuICAgICAqICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICogICAgIH1cbiAgICAgKiB9XG4gICAgICogYXdhaXQgZmluLlNuYXBzaG90U291cmNlLmluaXQoc25hcHNob3RQcm92aWRlcik7XG4gICAgICpcbiAgICAgKiB0cnkge1xuICAgICAqICAgYXdhaXQgc25hcHNob3RTb3VyY2UucmVhZHkoKTtcbiAgICAgKiAgIGF3YWl0IHNuYXBzaG90U291cmNlLmFwcGx5U25hcHNob3QoJ2ZvbycpO1xuICAgICAqIH0gY2F0Y2ggKGVycikge1xuICAgICAqICAgY29uc29sZS5sb2coZXJyKVxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyByZWFkeSgpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NuYXBzaG90LXNvdXJjZS1yZWFkeScpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1hc3luYy1wcm9taXNlLWV4ZWN1dG9yXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBJZiBnZXRDbGllbnQgd2FzIGFscmVhZHkgY2FsbGVkIGJlZm9yZSB0aGlzLCBkbyB3ZSBoYXZlIGEgdGltaW5nIGlzc3VlIHdoZXJlIHRoZSBjaGFubmVsIG1pZ2h0IGhhdmUgYmVlbiBjcmVhdGVkIGJ1dCB3ZSBtaXNzZWQgdGhlIGV2ZW50IGJ1dCB0aGlzIHN0aWxsIGZhaWxzP1xuICAgICAgICAgICAgYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQxKHRoaXMsIF9TbmFwc2hvdFNvdXJjZV9nZXRDbGllbnQsIFwiZlwiKS5jYWxsKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvLyBpdCB3YXMgbm90IHJ1bm5pbmcuXG4gICAgICAgICAgICBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2dldENvbm5lY3Rpb24sIFwiZlwiKS5jYWxsKHRoaXMpLmV2ZW50RmlyZWQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2FsbCB0aGUgU25hcHNob3RTb3VyY2UncyBnZXRTbmFwc2hvdCBtZXRob2QgZGVmaW5lZCBieSB7QGxpbmsgU25hcHNob3RTb3VyY2UuU25hcHNob3RTb3VyY2VNb2R1bGUjaW5pdCBpbml0fS5cbiAgICAgKlxuICAgICAqL1xuICAgIGFzeW5jIGdldFNuYXBzaG90KCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignc25hcHNob3Qtc291cmNlLWdldC1zbmFwc2hvdCcpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMSh0aGlzLCBfU25hcHNob3RTb3VyY2VfZ2V0Q2xpZW50LCBcImZcIikuY2FsbCh0aGlzKTtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSAoYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdnZXQtc25hcHNob3QnKSk7XG4gICAgICAgIHJldHVybiAoYXdhaXQgcmVzcG9uc2UpLnNuYXBzaG90O1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDYWxsIHRoZSBTbmFwc2hvdFNvdXJjZSdzIGFwcGx5U25hcHNob3QgbWV0aG9kIGRlZmluZWQgYnkge0BsaW5rIFNuYXBzaG90U291cmNlLlNuYXBzaG90U291cmNlTW9kdWxlI2luaXQgaW5pdH0uXG4gICAgICpcbiAgICAgKi9cbiAgICBhc3luYyBhcHBseVNuYXBzaG90KHNuYXBzaG90KSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzbmFwc2hvdC1zb3VyY2UtYXBwbHktc25hcHNob3QnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2dldENsaWVudCwgXCJmXCIpLmNhbGwodGhpcyk7XG4gICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2FwcGx5LXNuYXBzaG90JywgeyBzbmFwc2hvdCB9KTtcbiAgICB9XG59XG5JbnN0YW5jZS5TbmFwc2hvdFNvdXJjZSA9IFNuYXBzaG90U291cmNlO1xuX1NuYXBzaG90U291cmNlX2lkZW50aXR5ID0gbmV3IFdlYWtNYXAoKSwgX1NuYXBzaG90U291cmNlX2dldENvbm5lY3Rpb24gPSBuZXcgV2Vha01hcCgpLCBfU25hcHNob3RTb3VyY2VfZ2V0Q2xpZW50ID0gbmV3IFdlYWtNYXAoKSwgX1NuYXBzaG90U291cmNlX3N0YXJ0Q29ubmVjdGlvbiA9IG5ldyBXZWFrTWFwKCksIF9TbmFwc2hvdFNvdXJjZV9zZXRVcENvbm5lY3Rpb25MaXN0ZW5lciA9IG5ldyBXZWFrTWFwKCk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShGYWN0b3J5LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbkZhY3RvcnkuU25hcHNob3RTb3VyY2VNb2R1bGUgPSB2b2lkIDA7XG5jb25zdCBiYXNlXzEgPSBiYXNlO1xuY29uc3QgSW5zdGFuY2VfMSA9IEluc3RhbmNlO1xuY29uc3QgdXRpbHNfMSA9IHV0aWxzO1xuLyoqXG4gKiBTdGF0aWMgbmFtZXNwYWNlIGZvciBPcGVuRmluIEFQSSBtZXRob2RzIHRoYXQgaW50ZXJhY3Qgd2l0aCB0aGUge0BsaW5rIFNuYXBzaG90U291cmNlfSBjbGFzcywgYXZhaWxhYmxlIHVuZGVyIGBmaW4uU25hcHNob3RTb3VyY2VgLlxuICovXG5jbGFzcyBTbmFwc2hvdFNvdXJjZU1vZHVsZSBleHRlbmRzIGJhc2VfMS5CYXNlIHtcbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyBhIFNuYXBzaG90U291cmNlIHdpdGggdGhlIGdldFNuYXBzaG90IGFuZCBhcHBseVNuYXBzaG90IG1ldGhvZHMgZGVmaW5lZC5cbiAgICAgKlxuICAgICAqIEB0eXBlUGFyYW0gU25hcHNob3QgSW1wbGVtZW50YXRpb24tZGVmaW5lZCBzaGFwZSBvZiBhbiBhcHBsaWNhdGlvbiBzbmFwc2hvdC4gIEFsbG93c1xuICAgICAqIGN1c3RvbSBzbmFwc2hvdCBpbXBsZW1lbnRhdGlvbnMgZm9yIGxlZ2FjeSBhcHBsaWNhdGlvbnMgdG8gZGVmaW5lIHRoZWlyIG93biBzbmFwc2hvdCBmb3JtYXQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3Qgc25hcHNob3RQcm92aWRlciA9IHtcbiAgICAgKiAgICAgYXN5bmMgZ2V0U25hcHNob3QoKSB7XG4gICAgICogICAgICAgY29uc3QgYm91bmRzID0gYXdhaXQgZmluLm1lLmdldEJvdW5kcygpO1xuICAgICAqICAgICAgIHJldHVybiBib3VuZHM7XG4gICAgICogICAgICB9LFxuICAgICAqICAgICBhc3luYyBhcHBseVNuYXBzaG90KHNuYXBzaG90KSB7XG4gICAgICogICAgICAgYXdhaXQgZmluLm1lLnNldEJvdW5kcyhzbmFwc2hvdCk7XG4gICAgICogICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgKiAgICAgfVxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGF3YWl0IGZpbi5TbmFwc2hvdFNvdXJjZS5pbml0KHNuYXBzaG90UHJvdmlkZXIpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICovXG4gICAgYXN5bmMgaW5pdChwcm92aWRlcikge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignc25hcHNob3Qtc291cmNlLWluaXQnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAodHlwZW9mIHByb3ZpZGVyICE9PSAnb2JqZWN0JyB8fFxuICAgICAgICAgICAgdHlwZW9mIHByb3ZpZGVyLmdldFNuYXBzaG90ICE9PSAnZnVuY3Rpb24nIHx8XG4gICAgICAgICAgICB0eXBlb2YgcHJvdmlkZXIuYXBwbHlTbmFwc2hvdCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd5b3UgbXVzdCBwYXNzIGluIGEgdmFsaWQgU25hcHNob3RQcm92aWRlcicpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoYW5uZWwgPSBhd2FpdCB0aGlzLmZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY3JlYXRlKCgwLCB1dGlsc18xLmdldFNuYXBzaG90U291cmNlQ2hhbm5lbE5hbWUpKHRoaXMuZmluLm1lKSk7XG4gICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2dldC1zbmFwc2hvdCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgcHJvdmlkZXIuZ2V0U25hcHNob3QoKTtcbiAgICAgICAgICAgIHJldHVybiB7IHNuYXBzaG90IH07XG4gICAgICAgIH0pO1xuICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdhcHBseS1zbmFwc2hvdCcsICh7IHNuYXBzaG90IH0pID0+IHByb3ZpZGVyLmFwcGx5U25hcHNob3Qoc25hcHNob3QpKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGEgU25hcHNob3RTb3VyY2Ugb2JqZWN0IHRoYXQgcmVwcmVzZW50cyB0aGUgY3VycmVudCBTbmFwc2hvdFNvdXJjZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBzbmFwc2hvdFNvdXJjZSA9IGZpbi5TbmFwc2hvdFNvdXJjZS53cmFwU3luYyhmaW4ubWUpO1xuICAgICAqIC8vIFVzZSB3cmFwcGVkIGluc3RhbmNlJ3MgZ2V0U25hcHNob3QgbWV0aG9kLCBlLmcuOlxuICAgICAqIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgc25hcHNob3RTb3VyY2UuZ2V0U25hcHNob3QoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICB3cmFwU3luYyhpZGVudGl0eSkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignc25hcHNob3Qtc291cmNlLXdyYXAtc3luYycpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMS5TbmFwc2hvdFNvdXJjZSh0aGlzLndpcmUsIGlkZW50aXR5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhIFNuYXBzaG90U291cmNlIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIGN1cnJlbnQgU25hcHNob3RTb3VyY2UuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3Qgc25hcHNob3RTb3VyY2UgPSBhd2FpdCBmaW4uU25hcHNob3RTb3VyY2Uud3JhcChmaW4ubWUpO1xuICAgICAqIC8vIFVzZSB3cmFwcGVkIGluc3RhbmNlJ3MgZ2V0U25hcHNob3QgbWV0aG9kLCBlLmcuOlxuICAgICAqIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgc25hcHNob3RTb3VyY2UuZ2V0U25hcHNob3QoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyB3cmFwKGlkZW50aXR5KSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzbmFwc2hvdC1zb3VyY2Utd3JhcCcpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzLndyYXBTeW5jKGlkZW50aXR5KTtcbiAgICB9XG59XG5GYWN0b3J5LlNuYXBzaG90U291cmNlTW9kdWxlID0gU25hcHNob3RTb3VyY2VNb2R1bGU7XG5cbihmdW5jdGlvbiAoZXhwb3J0cykge1xuXHQvKipcblx0ICogRW50cnkgcG9pbnRzIGZvciB0aGUgT3BlbkZpbiBgU25hcHNob3RTb3VyY2VgIEFQSSAoYGZpbi5TbmFwc2hvdFNvdXJjZWApLlxuXHQgKlxuXHQgKiAqIHtAbGluayBTbmFwc2hvdFNvdXJjZU1vZHVsZX0gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBTbmFwc2hvdFNvdXJjZWAgQVBJLCBhY2Nlc3NpYmxlIHRocm91Z2ggYGZpbi5TbmFwc2hvdFNvdXJjZWAuXG5cdCAqICoge0BsaW5rIFNuYXBzaG90U291cmNlfSBkZXNjcmliZXMgYW4gaW5zdGFuY2Ugb2YgYW4gT3BlbkZpbiBTbmFwc2hvdFNvdXJjZSwgZS5nLiBhcyByZXR1cm5lZCBieSBgZmluLlNuYXBzaG90U291cmNlLndyYXBgLlxuXHQgKlxuXHQgKiBUaGVzZSBhcmUgc2VwYXJhdGUgY29kZSBlbnRpdGllcywgYW5kIGFyZSBkb2N1bWVudGVkIHNlcGFyYXRlbHkuICBJbiB0aGUgW3ByZXZpb3VzIHZlcnNpb24gb2YgdGhlIEFQSSBkb2N1bWVudGF0aW9uXShodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC8zMi4xMTQuNzYuMTAvaW5kZXguaHRtbCksXG5cdCAqIGJvdGggb2YgdGhlc2Ugd2VyZSBkb2N1bWVudGVkIG9uIHRoZSBzYW1lIHBhZ2UuXG5cdCAqXG5cdCAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuXHQgKi9cblx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0ICAgIH1cblx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgb1trMl0gPSBtW2tdO1xuXHR9KSk7XG5cdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0X19leHBvcnRTdGFyKEZhY3RvcnksIGV4cG9ydHMpO1xuXHRfX2V4cG9ydFN0YXIoSW5zdGFuY2UsIGV4cG9ydHMpOyBcbn0gKHNuYXBzaG90U291cmNlKSk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShmaW4kMiwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgRmluXzEgPSBmaW4kMi5GaW4gPSB2b2lkIDA7XG5jb25zdCBldmVudHNfMSQzID0gcmVxdWlyZSQkMDtcbi8vIEltcG9ydCBmcm9tIHRoZSBmaWxlIHJhdGhlciB0aGFuIHRoZSBkaXJlY3RvcnkgaW4gY2FzZSBzb21lb25lIGNvbnN1bWluZyB0eXBlcyBpcyB1c2luZyBtb2R1bGUgcmVzb2x1dGlvbiBvdGhlciB0aGFuIFwibm9kZVwiXG5jb25zdCBpbmRleF8xID0gc3lzdGVtO1xuY29uc3QgaW5kZXhfMiA9IHJlcXVpcmVXaW5kb3coKTtcbmNvbnN0IGluZGV4XzMgPSByZXF1aXJlQXBwbGljYXRpb24oKTtcbmNvbnN0IGluZGV4XzQgPSBpbnRlcmFwcGJ1cztcbmNvbnN0IGluZGV4XzUgPSBjbGlwYm9hcmQ7XG5jb25zdCBpbmRleF82ID0gZXh0ZXJuYWxBcHBsaWNhdGlvbjtcbmNvbnN0IGluZGV4XzcgPSBmcmFtZTtcbmNvbnN0IGluZGV4XzggPSBnbG9iYWxIb3RrZXk7XG5jb25zdCBpbmRleF85ID0gcmVxdWlyZVZpZXcoKTtcbmNvbnN0IGluZGV4XzEwID0gcGxhdGZvcm07XG5jb25zdCBtZV8xJDIgPSBtZTtcbmNvbnN0IGludGVyb3BfMSA9IHJlcXVpcmVJbnRlcm9wKCk7XG5jb25zdCBzbmFwc2hvdF9zb3VyY2VfMSA9IHNuYXBzaG90U291cmNlO1xuLyoqXG4gKiBAaW50ZXJuYWxcbiAqL1xuY2xhc3MgRmluIGV4dGVuZHMgZXZlbnRzXzEkMy5FdmVudEVtaXR0ZXIge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHdpcmUpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy53aXJlID0gd2lyZTtcbiAgICAgICAgdGhpcy5TeXN0ZW0gPSBuZXcgaW5kZXhfMS5TeXN0ZW0od2lyZSk7XG4gICAgICAgIHRoaXMuV2luZG93ID0gbmV3IGluZGV4XzIuX1dpbmRvd01vZHVsZSh3aXJlKTtcbiAgICAgICAgdGhpcy5BcHBsaWNhdGlvbiA9IG5ldyBpbmRleF8zLkFwcGxpY2F0aW9uTW9kdWxlKHdpcmUpO1xuICAgICAgICB0aGlzLkludGVyQXBwbGljYXRpb25CdXMgPSBuZXcgaW5kZXhfNC5JbnRlckFwcGxpY2F0aW9uQnVzKHdpcmUpO1xuICAgICAgICB0aGlzLkNsaXBib2FyZCA9IG5ldyBpbmRleF81LkNsaXBib2FyZCh3aXJlKTtcbiAgICAgICAgdGhpcy5FeHRlcm5hbEFwcGxpY2F0aW9uID0gbmV3IGluZGV4XzYuRXh0ZXJuYWxBcHBsaWNhdGlvbk1vZHVsZSh3aXJlKTtcbiAgICAgICAgdGhpcy5GcmFtZSA9IG5ldyBpbmRleF83Ll9GcmFtZU1vZHVsZSh3aXJlKTtcbiAgICAgICAgdGhpcy5HbG9iYWxIb3RrZXkgPSBuZXcgaW5kZXhfOC5HbG9iYWxIb3RrZXkod2lyZSk7XG4gICAgICAgIHRoaXMuUGxhdGZvcm0gPSBuZXcgaW5kZXhfMTAuUGxhdGZvcm1Nb2R1bGUod2lyZSwgdGhpcy5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwpO1xuICAgICAgICB0aGlzLlZpZXcgPSBuZXcgaW5kZXhfOS5WaWV3TW9kdWxlKHdpcmUpO1xuICAgICAgICB0aGlzLkludGVyb3AgPSBuZXcgaW50ZXJvcF8xLkludGVyb3BNb2R1bGUod2lyZSk7XG4gICAgICAgIHRoaXMuU25hcHNob3RTb3VyY2UgPSBuZXcgc25hcHNob3Rfc291cmNlXzEuU25hcHNob3RTb3VyY2VNb2R1bGUod2lyZSk7XG4gICAgICAgIHdpcmUucmVnaXN0ZXJGaW4odGhpcyk7XG4gICAgICAgIHRoaXMubWUgPSAoMCwgbWVfMSQyLmdldE1lKSh3aXJlKTtcbiAgICAgICAgLy8gSGFuZGxlIGRpc2Nvbm5lY3QgZXZlbnRzXG4gICAgICAgIHdpcmUub24oJ2Rpc2Nvbm5lY3RlZCcsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZW1pdCgnZGlzY29ubmVjdGVkJyk7XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbkZpbl8xID0gZmluJDIuRmluID0gRmluO1xuXG52YXIgdHJhbnNwb3J0ID0ge307XG5cbnZhciB3aXJlID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aXJlLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbndpcmUuaXNJbnRlcm5hbENvbm5lY3RDb25maWcgPSB3aXJlLmlzUG9ydERpc2NvdmVyeUNvbmZpZyA9IHdpcmUuaXNOZXdDb25uZWN0Q29uZmlnID0gd2lyZS5pc0NvbmZpZ1dpdGhSZWNlaXZlciA9IHdpcmUuaXNSZW1vdGVDb25maWcgPSB3aXJlLmlzRXhpc3RpbmdDb25uZWN0Q29uZmlnID0gd2lyZS5pc0V4dGVybmFsQ29uZmlnID0gdm9pZCAwO1xuZnVuY3Rpb24gaXNFeHRlcm5hbENvbmZpZyhjb25maWcpIHtcbiAgICBpZiAodHlwZW9mIGNvbmZpZy5tYW5pZmVzdFVybCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbndpcmUuaXNFeHRlcm5hbENvbmZpZyA9IGlzRXh0ZXJuYWxDb25maWc7XG5mdW5jdGlvbiBpc0V4aXN0aW5nQ29ubmVjdENvbmZpZyhjb25maWcpIHtcbiAgICByZXR1cm4gaGFzVXVpZChjb25maWcpICYmIHR5cGVvZiBjb25maWcuYWRkcmVzcyA9PT0gJ3N0cmluZyc7XG59XG53aXJlLmlzRXhpc3RpbmdDb25uZWN0Q29uZmlnID0gaXNFeGlzdGluZ0Nvbm5lY3RDb25maWc7XG5mdW5jdGlvbiBpc1JlbW90ZUNvbmZpZyhjb25maWcpIHtcbiAgICByZXR1cm4gaXNFeGlzdGluZ0Nvbm5lY3RDb25maWcoY29uZmlnKSAmJiB0eXBlb2YgY29uZmlnLnRva2VuID09PSAnc3RyaW5nJztcbn1cbndpcmUuaXNSZW1vdGVDb25maWcgPSBpc1JlbW90ZUNvbmZpZztcbmZ1bmN0aW9uIGlzQ29uZmlnV2l0aFJlY2VpdmVyKGNvbmZpZykge1xuICAgIHJldHVybiB0eXBlb2YgY29uZmlnLnJlY2VpdmVyID09PSAnb2JqZWN0JyAmJiBpc1JlbW90ZUNvbmZpZyh7IC4uLmNvbmZpZywgYWRkcmVzczogJycgfSk7XG59XG53aXJlLmlzQ29uZmlnV2l0aFJlY2VpdmVyID0gaXNDb25maWdXaXRoUmVjZWl2ZXI7XG5mdW5jdGlvbiBoYXNVdWlkKGNvbmZpZykge1xuICAgIHJldHVybiB0eXBlb2YgY29uZmlnLnV1aWQgPT09ICdzdHJpbmcnO1xufVxuZnVuY3Rpb24gaGFzUnVudGltZVZlcnNpb24oY29uZmlnKSB7XG4gICAgcmV0dXJuIGNvbmZpZy5ydW50aW1lICYmIHR5cGVvZiBjb25maWcucnVudGltZS52ZXJzaW9uID09PSAnc3RyaW5nJztcbn1cbmZ1bmN0aW9uIGlzTmV3Q29ubmVjdENvbmZpZyhjb25maWcpIHtcbiAgICByZXR1cm4gaGFzVXVpZChjb25maWcpICYmIGhhc1J1bnRpbWVWZXJzaW9uKGNvbmZpZyk7XG59XG53aXJlLmlzTmV3Q29ubmVjdENvbmZpZyA9IGlzTmV3Q29ubmVjdENvbmZpZztcbmZ1bmN0aW9uIGlzUG9ydERpc2NvdmVyeUNvbmZpZyhjb25maWcpIHtcbiAgICByZXR1cm4gKGlzRXh0ZXJuYWxDb25maWcoY29uZmlnKSAmJiBoYXNSdW50aW1lVmVyc2lvbihjb25maWcpKSB8fCBpc05ld0Nvbm5lY3RDb25maWcoY29uZmlnKTtcbn1cbndpcmUuaXNQb3J0RGlzY292ZXJ5Q29uZmlnID0gaXNQb3J0RGlzY292ZXJ5Q29uZmlnO1xuZnVuY3Rpb24gaXNJbnRlcm5hbENvbm5lY3RDb25maWcoY29uZmlnKSB7XG4gICAgcmV0dXJuIGlzRXhpc3RpbmdDb25uZWN0Q29uZmlnKGNvbmZpZykgfHwgaXNOZXdDb25uZWN0Q29uZmlnKGNvbmZpZyk7XG59XG53aXJlLmlzSW50ZXJuYWxDb25uZWN0Q29uZmlnID0gaXNJbnRlcm5hbENvbm5lY3RDb25maWc7XG5cbnZhciBldmVudEFnZ3JlZ2F0b3IgPSB7fTtcblxudmFyIGVtaXR0ZXJNYXAgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGVtaXR0ZXJNYXAsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZW1pdHRlck1hcC5FbWl0dGVyTWFwID0gdm9pZCAwO1xuY29uc3QgZXZlbnRzXzEkMiA9IHJlcXVpcmUkJDA7XG5jbGFzcyBFbWl0dGVyTWFwIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5zdG9yYWdlID0gbmV3IE1hcCgpO1xuICAgIH1cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuICAgIGhhc2hLZXlzKGtleXMpIHtcbiAgICAgICAgY29uc3QgaGFzaGVkID0ga2V5cy5tYXAobm9ybWFsaXplU3RyaW5nKTtcbiAgICAgICAgcmV0dXJuIGhhc2hlZC5qb2luKCcvJyk7XG4gICAgfVxuICAgIGdldE9yQ3JlYXRlKGtleXMpIHtcbiAgICAgICAgY29uc3QgaGFzaCA9IHRoaXMuaGFzaEtleXMoa2V5cyk7XG4gICAgICAgIGlmICghdGhpcy5zdG9yYWdlLmhhcyhoYXNoKSkge1xuICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnNldChoYXNoLCBuZXcgZXZlbnRzXzEkMi5FdmVudEVtaXR0ZXIoKSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gV2Ugc2V0IGl0IGFib3ZlXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuZ2V0KGhhc2gpO1xuICAgIH1cbiAgICBoYXMoa2V5cykge1xuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmhhcyh0aGlzLmhhc2hLZXlzKGtleXMpKTtcbiAgICB9XG4gICAgZGVsZXRlKGtleXMpIHtcbiAgICAgICAgY29uc3QgaGFzaCA9IHRoaXMuaGFzaEtleXMoa2V5cyk7XG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuZGVsZXRlKGhhc2gpO1xuICAgIH1cbn1cbmVtaXR0ZXJNYXAuRW1pdHRlck1hcCA9IEVtaXR0ZXJNYXA7XG5mdW5jdGlvbiBub3JtYWxpemVTdHJpbmcocykge1xuICAgIGNvbnN0IGIgPSBCdWZmZXIuZnJvbShzKTtcbiAgICByZXR1cm4gYi50b1N0cmluZygnYmFzZTY0Jyk7XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShldmVudEFnZ3JlZ2F0b3IsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29uc3QgZW1pdHRlck1hcF8xID0gZW1pdHRlck1hcDtcbmZ1bmN0aW9uIGlzRXZlbnRNZXNzYWdlKG1lc3NhZ2UpIHtcbiAgICByZXR1cm4gbWVzc2FnZS5hY3Rpb24gPT09ICdwcm9jZXNzLWRlc2t0b3AtZXZlbnQnO1xufVxuZnVuY3Rpb24gbWFwS2V5RnJvbUV2ZW50KGV2ZW50KSB7XG4gICAgY29uc3QgeyB0b3BpYyB9ID0gZXZlbnQ7XG4gICAgaWYgKHRvcGljID09PSAnZnJhbWUnIHx8IHRvcGljID09PSAnd2luZG93JyB8fCB0b3BpYyA9PT0gJ3ZpZXcnKSB7XG4gICAgICAgIGNvbnN0IHsgdXVpZCwgbmFtZSB9ID0gZXZlbnQ7XG4gICAgICAgIHJldHVybiBbdG9waWMsIHV1aWQsIG5hbWVdO1xuICAgIH1cbiAgICBpZiAodG9waWMgPT09ICdhcHBsaWNhdGlvbicpIHtcbiAgICAgICAgY29uc3QgeyB1dWlkIH0gPSBldmVudDtcbiAgICAgICAgcmV0dXJuIFt0b3BpYywgdXVpZF07XG4gICAgfVxuICAgIHJldHVybiBbdG9waWNdO1xufVxuY2xhc3MgRXZlbnRBZ2dyZWdhdG9yIGV4dGVuZHMgZW1pdHRlck1hcF8xLkVtaXR0ZXJNYXAge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlciguLi5hcmd1bWVudHMpO1xuICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQgPSAobWVzc2FnZSkgPT4ge1xuICAgICAgICAgICAgaWYgKGlzRXZlbnRNZXNzYWdlKG1lc3NhZ2UpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBtZXNzYWdlO1xuICAgICAgICAgICAgICAgIGNvbnN0IGFjY2Vzc29yID0gbWFwS2V5RnJvbUV2ZW50KHBheWxvYWQpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmhhcyhhY2Nlc3NvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRPckNyZWF0ZShhY2Nlc3NvcikuZW1pdChwYXlsb2FkLnR5cGUsIHBheWxvYWQpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG4gICAgfVxufVxuZXZlbnRBZ2dyZWdhdG9yLmRlZmF1bHQgPSBFdmVudEFnZ3JlZ2F0b3I7XG5cbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcbn07XG52YXIgX19pbXBvcnREZWZhdWx0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9faW1wb3J0RGVmYXVsdCkgfHwgZnVuY3Rpb24gKG1vZCkge1xuICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgXCJkZWZhdWx0XCI6IG1vZCB9O1xufTtcbnZhciBfVHJhbnNwb3J0X3dpcmUsIF9UcmFuc3BvcnRfZmluO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KHRyYW5zcG9ydCwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgVHJhbnNwb3J0XzEgPSB0cmFuc3BvcnQuVHJhbnNwb3J0ID0gdm9pZCAwO1xuY29uc3QgZXZlbnRzXzEkMSA9IHJlcXVpcmUkJDA7XG5jb25zdCB3aXJlXzEgPSB3aXJlO1xuY29uc3QgdHJhbnNwb3J0X2Vycm9yc18xID0gdHJhbnNwb3J0RXJyb3JzO1xuY29uc3QgZXZlbnRBZ2dyZWdhdG9yXzEgPSBfX2ltcG9ydERlZmF1bHQoZXZlbnRBZ2dyZWdhdG9yKTtcbmNvbnN0IG1lXzEkMSA9IG1lO1xuY29uc3QgZXJyb3JzXzEgPSBlcnJvcnM7XG5jbGFzcyBUcmFuc3BvcnQgZXh0ZW5kcyBldmVudHNfMSQxLkV2ZW50RW1pdHRlciB7XG4gICAgY29uc3RydWN0b3IoV2lyZVR5cGUsIGVudmlyb25tZW50LCBjb25maWcpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy53aXJlTGlzdGVuZXJzID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLnRvcGljUmVmTWFwID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLmV2ZW50QWdncmVnYXRvciA9IG5ldyBldmVudEFnZ3JlZ2F0b3JfMS5kZWZhdWx0KCk7XG4gICAgICAgIHRoaXMubWVzc2FnZUhhbmRsZXJzID0gW3RoaXMuZXZlbnRBZ2dyZWdhdG9yLmRpc3BhdGNoRXZlbnRdO1xuICAgICAgICBfVHJhbnNwb3J0X3dpcmUuc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIC8vIFR5cGluZyBhcyB1bmtub3duIHRvIGF2b2lkIGNpcmN1bGFyIGRlcGVuZGVuY3ksIHNob3VsZCBub3QgYmUgdXNlZCBkaXJlY3RseS5cbiAgICAgICAgX1RyYW5zcG9ydF9maW4uc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIHRoaXMuY29ubmVjdFN5bmMgPSAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB3aXJlID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfVHJhbnNwb3J0X3dpcmUsIFwiZlwiKTtcbiAgICAgICAgICAgIHdpcmUuY29ubmVjdFN5bmMoKTtcbiAgICAgICAgfTtcbiAgICAgICAgLy8gVGhpcyBmdW5jdGlvbiBpcyBvbmx5IHVzZWQgaW4gb3VyIHRlc3RzLlxuICAgICAgICB0aGlzLmdldFBvcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB3aXJlID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfVHJhbnNwb3J0X3dpcmUsIFwiZlwiKTtcbiAgICAgICAgICAgIHJldHVybiB3aXJlLmdldFBvcnQoKTtcbiAgICAgICAgfTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfVHJhbnNwb3J0X3dpcmUsIG5ldyBXaXJlVHlwZSh0aGlzLm9ubWVzc2FnZS5iaW5kKHRoaXMpKSwgXCJmXCIpO1xuICAgICAgICB0aGlzLmVudmlyb25tZW50ID0gZW52aXJvbm1lbnQ7XG4gICAgICAgIHRoaXMuc2VuZFJhdyA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1RyYW5zcG9ydF93aXJlLCBcImZcIikuc2VuZC5iaW5kKF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1RyYW5zcG9ydF93aXJlLCBcImZcIikpO1xuICAgICAgICB0aGlzLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIodGhpcy5oYW5kbGVNZXNzYWdlLmJpbmQodGhpcykpO1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9UcmFuc3BvcnRfd2lyZSwgXCJmXCIpLm9uKCdkaXNjb25uZWN0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IFssIHsgaGFuZGxlTmFjayB9XSBvZiB0aGlzLndpcmVMaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgICAgICBoYW5kbGVOYWNrKHsgcmVhc29uOiAnUmVtb3RlIGNvbm5lY3Rpb24gaGFzIGNsb3NlZCcgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndpcmVMaXN0ZW5lcnMuY2xlYXIoKTtcbiAgICAgICAgICAgIHRoaXMuZW1pdCgnZGlzY29ubmVjdGVkJyk7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IGNvbmZpZztcbiAgICAgICAgY29uc3QgZW50aXR5VHlwZSA9IHRoaXMuZW52aXJvbm1lbnQuZ2V0Q3VycmVudEVudGl0eVR5cGUoKTtcbiAgICAgICAgdGhpcy5tZSA9ICgwLCBtZV8xJDEuZ2V0QmFzZU1lKShlbnRpdHlUeXBlLCB1dWlkLCBuYW1lKTtcbiAgICB9XG4gICAgZ2V0RmluKCkge1xuICAgICAgICBpZiAoIV9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1RyYW5zcG9ydF9maW4sIFwiZlwiKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBGaW4gb2JqZWN0IHJlZ2lzdGVyZWQgZm9yIHRoaXMgdHJhbnNwb3J0Jyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1RyYW5zcG9ydF9maW4sIFwiZlwiKTtcbiAgICB9XG4gICAgcmVnaXN0ZXJGaW4oX2Zpbikge1xuICAgICAgICBpZiAoX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfVHJhbnNwb3J0X2ZpbiwgXCJmXCIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZpbiBvYmplY3QgaGFzIGFscmVhZHkgYmVlbiByZWdpc3RlcmVkIGZvciB0aGlzIHRyYW5zcG9ydCcpO1xuICAgICAgICB9XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX1RyYW5zcG9ydF9maW4sIF9maW4sIFwiZlwiKTtcbiAgICB9XG4gICAgc2h1dGRvd24oKSB7XG4gICAgICAgIGNvbnN0IHdpcmUgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9UcmFuc3BvcnRfd2lyZSwgXCJmXCIpO1xuICAgICAgICByZXR1cm4gd2lyZS5zaHV0ZG93bigpO1xuICAgIH1cbiAgICBhc3luYyBjb25uZWN0KGNvbmZpZykge1xuICAgICAgICBpZiAoKDAsIHdpcmVfMS5pc0NvbmZpZ1dpdGhSZWNlaXZlcikoY29uZmlnKSkge1xuICAgICAgICAgICAgYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfVHJhbnNwb3J0X3dpcmUsIFwiZlwiKS5jb25uZWN0KGNvbmZpZy5yZWNlaXZlcik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hdXRob3JpemUoY29uZmlnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKDAsIHdpcmVfMS5pc1JlbW90ZUNvbmZpZykoY29uZmlnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdFJlbW90ZShjb25maWcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgoMCwgd2lyZV8xLmlzRXhpc3RpbmdDb25uZWN0Q29uZmlnKShjb25maWcpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25uZWN0QnlQb3J0KGNvbmZpZyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCgwLCB3aXJlXzEuaXNOZXdDb25uZWN0Q29uZmlnKShjb25maWcpKSB7XG4gICAgICAgICAgICBjb25zdCBwb3J0ID0gYXdhaXQgdGhpcy5lbnZpcm9ubWVudC5yZXRyaWV2ZVBvcnQoY29uZmlnKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbm5lY3RCeVBvcnQoeyAuLi5jb25maWcsIGFkZHJlc3M6IGB3czovL2xvY2FsaG9zdDoke3BvcnR9YCB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBhc3luYyBjb25uZWN0UmVtb3RlKGNvbmZpZykge1xuICAgICAgICBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9UcmFuc3BvcnRfd2lyZSwgXCJmXCIpLmNvbm5lY3QobmV3ICh0aGlzLmVudmlyb25tZW50LmdldFdzQ29uc3RydWN0b3IoKSkoY29uZmlnLmFkZHJlc3MpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aG9yaXplKGNvbmZpZyk7XG4gICAgfVxuICAgIGFzeW5jIGNvbm5lY3RCeVBvcnQoY29uZmlnKSB7XG4gICAgICAgIGNvbnN0IHsgYWRkcmVzcywgdXVpZCB9ID0gY29uZmlnO1xuICAgICAgICBjb25zdCByZXFBdXRoUGF5bG9hZCA9IHsgLi4uY29uZmlnLCB0eXBlOiAnZmlsZS10b2tlbicgfTtcbiAgICAgICAgY29uc3Qgd2lyZSA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1RyYW5zcG9ydF93aXJlLCBcImZcIik7XG4gICAgICAgIGF3YWl0IHdpcmUuY29ubmVjdChuZXcgKHRoaXMuZW52aXJvbm1lbnQuZ2V0V3NDb25zdHJ1Y3RvcigpKShjb25maWcuYWRkcmVzcykpO1xuICAgICAgICBjb25zdCByZXF1ZXN0RXh0QXV0aFJldCA9IGF3YWl0IHRoaXMuc2VuZEFjdGlvbigncmVxdWVzdC1leHRlcm5hbC1hdXRob3JpemF0aW9uJywge1xuICAgICAgICAgICAgdXVpZCxcbiAgICAgICAgICAgIHR5cGU6ICdmaWxlLXRva2VuJ1xuICAgICAgICB9LCB0cnVlKTtcbiAgICAgICAgaWYgKHJlcXVlc3RFeHRBdXRoUmV0LmFjdGlvbiAhPT0gJ2V4dGVybmFsLWF1dGhvcml6YXRpb24tcmVzcG9uc2UnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgdHJhbnNwb3J0X2Vycm9yc18xLlVuZXhwZWN0ZWRBY3Rpb25FcnJvcihyZXF1ZXN0RXh0QXV0aFJldC5hY3Rpb24pO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMuZW52aXJvbm1lbnQud3JpdGVUb2tlbihyZXF1ZXN0RXh0QXV0aFJldC5wYXlsb2FkLmZpbGUsIHJlcXVlc3RFeHRBdXRoUmV0LnBheWxvYWQudG9rZW4pO1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRob3JpemUocmVxQXV0aFBheWxvYWQpO1xuICAgIH1cbiAgICBhc3luYyBhdXRob3JpemUocmVxQXV0aFBheWxvYWQpIHtcbiAgICAgICAgY29uc3QgcmVxdWVzdEF1dGhSZXQgPSBhd2FpdCB0aGlzLnNlbmRBY3Rpb24oJ3JlcXVlc3QtYXV0aG9yaXphdGlvbicsIHJlcUF1dGhQYXlsb2FkLCB0cnVlKTtcbiAgICAgICAgaWYgKHJlcXVlc3RBdXRoUmV0LmFjdGlvbiAhPT0gJ2F1dGhvcml6YXRpb24tcmVzcG9uc2UnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgdHJhbnNwb3J0X2Vycm9yc18xLlVuZXhwZWN0ZWRBY3Rpb25FcnJvcihyZXF1ZXN0QXV0aFJldC5hY3Rpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHJlcXVlc3RBdXRoUmV0LnBheWxvYWQuc3VjY2VzcyAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IHRyYW5zcG9ydF9lcnJvcnNfMS5SdW50aW1lRXJyb3IocmVxdWVzdEF1dGhSZXQucGF5bG9hZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgc2VuZEFjdGlvbihhY3Rpb24sIHBheWxvYWQgPSB7fSwgdW5jb3JyZWxhdGVkID0gZmFsc2VcbiAgICAvLyBzcGVjaWFsUmVzcG9uc2UgdHlwZSBpcyBvbmx5IHVzZWQgZm9yICdyZXF1ZXN0QXV0aG9yaXphdGlvbidcbiAgICApIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICAgICAgICBsZXQgY2FuY2VsID0gKCkgPT4geyB9O1xuICAgICAgICAvLyBXZSB3YW50IHRoZSBjYWxsc2l0ZSBmcm9tIHRoZSBjYWxsZXIgb2YgdGhpcyBmdW5jdGlvbiwgbm90IGZyb20gaGVyZS5cbiAgICAgICAgY29uc3QgY2FsbFNpdGVzID0gdHJhbnNwb3J0X2Vycm9yc18xLlJ1bnRpbWVFcnJvci5nZXRDYWxsU2l0ZSgxKTtcbiAgICAgICAgY29uc3QgbWVzc2FnZUlkID0gdGhpcy5lbnZpcm9ubWVudC5nZXROZXh0TWVzc2FnZUlkKCk7XG4gICAgICAgIGNvbnN0IHByb20gPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjYW5jZWwgPSByZWplY3Q7XG4gICAgICAgICAgICBjb25zdCBtc2cgPSB7XG4gICAgICAgICAgICAgICAgYWN0aW9uLFxuICAgICAgICAgICAgICAgIHBheWxvYWQsXG4gICAgICAgICAgICAgICAgbWVzc2FnZUlkXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgd2lyZSA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1RyYW5zcG9ydF93aXJlLCBcImZcIik7XG4gICAgICAgICAgICB0aGlzLmFkZFdpcmVMaXN0ZW5lcihtZXNzYWdlSWQsIHJlc29sdmUsIChwYXlsb2FkKSA9PiB0aGlzLm5hY2tIYW5kbGVyKHBheWxvYWQsIHJlamVjdCwgY2FsbFNpdGVzKSwgdW5jb3JyZWxhdGVkKTtcbiAgICAgICAgICAgIHJldHVybiB3aXJlLnNlbmQobXNnKS5jYXRjaChyZWplY3QpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24ocHJvbSwgeyBjYW5jZWwsIG1lc3NhZ2VJZCB9KTtcbiAgICB9XG4gICAgbmFja0hhbmRsZXIocGF5bG9hZE9yTWVzc2FnZSwgcmVqZWN0LCBjYWxsU2l0ZXMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBwYXlsb2FkT3JNZXNzYWdlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gTk9URTogdGhpcyBpcyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgdG8gc3VwcG9ydCBwbGFpbiBzdHJpbmcgcmVqZWN0aW9uc1xuICAgICAgICAgICAgcmVqZWN0KHBheWxvYWRPck1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVqZWN0KG5ldyB0cmFuc3BvcnRfZXJyb3JzXzEuUnVudGltZUVycm9yKHBheWxvYWRPck1lc3NhZ2UsIGNhbGxTaXRlcykpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZlcnJ5QWN0aW9uKG9yaWdEYXRhKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBpZCA9IHRoaXMuZW52aXJvbm1lbnQuZ2V0TmV4dE1lc3NhZ2VJZCgpO1xuICAgICAgICAgICAgb3JpZ0RhdGEubWVzc2FnZUlkID0gaWQ7XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlciA9IChkYXRhKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShkYXRhLnBheWxvYWQpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHdpcmUgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9UcmFuc3BvcnRfd2lyZSwgXCJmXCIpO1xuICAgICAgICAgICAgcmV0dXJuIHdpcmVcbiAgICAgICAgICAgICAgICAuc2VuZChvcmlnRGF0YSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLmFkZFdpcmVMaXN0ZW5lcihpZCwgcmVzb2x2ZXIsIChwYXlsb2FkKSA9PiB0aGlzLm5hY2tIYW5kbGVyKHBheWxvYWQsIHJlamVjdCksIGZhbHNlKSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gocmVqZWN0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoaGFuZGxlcikge1xuICAgICAgICB0aGlzLm1lc3NhZ2VIYW5kbGVycy5wdXNoKGhhbmRsZXIpO1xuICAgIH1cbiAgICBhZGRXaXJlTGlzdGVuZXIoaWQsIHJlc29sdmUsIGhhbmRsZU5hY2ssIHVuY29ycmVsYXRlZCkge1xuICAgICAgICBpZiAodW5jb3JyZWxhdGVkKSB7XG4gICAgICAgICAgICB0aGlzLnVuY29ycmVsYXRlZExpc3RlbmVyID0gcmVzb2x2ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLndpcmVMaXN0ZW5lcnMuaGFzKGlkKSkge1xuICAgICAgICAgICAgaGFuZGxlTmFjayh7XG4gICAgICAgICAgICAgICAgcmVhc29uOiAnRHVwbGljYXRlIGhhbmRsZXIgaWQnLFxuICAgICAgICAgICAgICAgIGVycm9yOiAoMCwgZXJyb3JzXzEuZXJyb3JUb1BPSk8pKG5ldyB0cmFuc3BvcnRfZXJyb3JzXzEuRHVwbGljYXRlQ29ycmVsYXRpb25FcnJvcihTdHJpbmcoaWQpKSlcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy53aXJlTGlzdGVuZXJzLnNldChpZCwgeyByZXNvbHZlLCBoYW5kbGVOYWNrIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRpbWVvdXQgYW5kIHJlamVjdCgpP1xuICAgIH1cbiAgICAvLyBUaGlzIG1ldGhvZCBleGVjdXRlcyBtZXNzYWdlIGhhbmRsZXJzIHVudGlsIHRoZSBfb25lXyB0aGF0IGhhbmRsZXMgdGhlIG1lc3NhZ2UgKHJldHVybnMgdHJ1dGh5KSBoYXMgcnVuXG4gICAgb25tZXNzYWdlKGRhdGEpIHtcbiAgICAgICAgZm9yIChjb25zdCBoIG9mIHRoaXMubWVzc2FnZUhhbmRsZXJzKSB7XG4gICAgICAgICAgICBoLmNhbGwobnVsbCwgZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaGFuZGxlTWVzc2FnZShkYXRhKSB7XG4gICAgICAgIGNvbnN0IGlkID0gZGF0YS5jb3JyZWxhdGlvbklkIHx8IE5hTjtcbiAgICAgICAgaWYgKCEoJ2NvcnJlbGF0aW9uSWQnIGluIGRhdGEpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy51bmNvcnJlbGF0ZWRMaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHRoaXMudW5jb3JyZWxhdGVkTGlzdGVuZXIuY2FsbChudWxsLCBkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMudW5jb3JyZWxhdGVkTGlzdGVuZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gZW1wdHkgYmxvY2tcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoIXRoaXMud2lyZUxpc3RlbmVycy5oYXMoaWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBXZSBqdXN0IGNoZWNrZWQgZm9yIGV4aXN0ZW5jZSBhYm92ZVxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgICAgIGNvbnN0IHsgcmVzb2x2ZSwgaGFuZGxlTmFjayB9ID0gdGhpcy53aXJlTGlzdGVuZXJzLmdldChpZCk7XG4gICAgICAgICAgICBpZiAoZGF0YS5hY3Rpb24gIT09ICdhY2snKSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlTmFjayh7IHJlYXNvbjogJ0RpZCBub3QgcmVjZWl2ZSBhY2sgYWN0aW9uJywgZXJyb3I6ICgwLCBlcnJvcnNfMS5lcnJvclRvUE9KTykobmV3IHRyYW5zcG9ydF9lcnJvcnNfMS5Ob0Fja0Vycm9yKGRhdGEuYWN0aW9uKSkgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICghKCdwYXlsb2FkJyBpbiBkYXRhKSkge1xuICAgICAgICAgICAgICAgIC8vIEknbSBub3Qgc3VyZSB3aGVuIHRoaXMgY29kZSB3b3VsZCBhY3R1YWxseSBydW4sIGJ1dCBwYXNzaW5nIGluIHNvbWV0aGluZyB0aGF0IGRvZWVzbid0IGhhdmUgYSByZWFzb24gdG8gdGhlIHJ1bnRpbWVlcnJvciBjb25zdHJ1Y3RvciB3aWxsIG5vdCBlbmQgd2VsbC5cbiAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhLnJlYXNvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlTmFjayhkYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignUmVjZWl2ZWQgaW52YWxpZCByZXNwb25zZSBmcm9tIGNvcmUnLCBkYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlTmFjayh7IHJlYXNvbjogJ2ludmFsaWQgcmVzcG9uc2Ugc2hhcGUnIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKCFkYXRhLnBheWxvYWQuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgIGhhbmRsZU5hY2soZGF0YS5wYXlsb2FkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc29sdmUuY2FsbChudWxsLCBkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMud2lyZUxpc3RlbmVycy5kZWxldGUoaWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn1cblRyYW5zcG9ydF8xID0gdHJhbnNwb3J0LlRyYW5zcG9ydCA9IFRyYW5zcG9ydDtcbl9UcmFuc3BvcnRfd2lyZSA9IG5ldyBXZWFrTWFwKCksIF9UcmFuc3BvcnRfZmluID0gbmV3IFdlYWtNYXAoKTtcblxudmFyIG1vY2tFbnZpcm9ubWVudCA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkobW9ja0Vudmlyb25tZW50LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnZhciBNb2NrRW52aXJvbm1lbnRfMSA9IG1vY2tFbnZpcm9ubWVudC5Nb2NrRW52aXJvbm1lbnQgPSB2b2lkIDA7XG5jb25zdCBtZV8xID0gbWU7XG5jbGFzcyBNb2NrRW52aXJvbm1lbnQge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnR5cGUgPSAnb3RoZXInO1xuICAgICAgICB0aGlzLmNoaWxkVmlld3MgPSB0cnVlO1xuICAgIH1cbiAgICBnZXRBZGFwdGVyVmVyc2lvblN5bmMoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgYXN5bmMgZ2V0SW50ZXJvcEluZm8oKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgZ2V0RGVmYXVsdENoYW5uZWxPcHRpb25zKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGdldFJ0Y1BlZXIoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgbGF5b3V0QWxsb3dlZEluQ29udGV4dChfZmluKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgaW5pdExheW91dE1hbmFnZXIoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgYXBwbHlMYXlvdXRTbmFwc2hvdCgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICBhc3luYyBjcmVhdGVMYXlvdXQoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgYXN5bmMgZGVzdHJveUxheW91dCgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICBhc3luYyByZXNvbHZlTGF5b3V0KCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGluaXRQbGF0Zm9ybSgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICBvYnNlcnZlQm91bmRzKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIHdyaXRlVG9rZW4ocGF0aCwgdG9rZW4pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICByZXRyaWV2ZVBvcnQoY29uZmlnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgZ2V0TmV4dE1lc3NhZ2VJZCgpIHtcbiAgICAgICAgcmV0dXJuIGBtb2NrLW1lc3NhZ2UtaWQtJHtNYXRoLnJhbmRvbSgpfWA7XG4gICAgfVxuICAgIGdldFJhbmRvbUlkKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGNyZWF0ZUNoaWxkQ29udGVudChvcHRpb25zKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgZ2V0V2ViV2luZG93KGlkZW50aXR5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgZ2V0Q3VycmVudEVudGl0eUlkZW50aXR5KCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGdldEN1cnJlbnRFbnRpdHlUeXBlKCkge1xuICAgICAgICByZXR1cm4gJ3Vua25vd24nO1xuICAgIH1cbiAgICByYWlzZUV2ZW50KGV2ZW50TmFtZSwgZXZlbnRBcmdzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgZ2V0VXJsKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIHdoZW5SZWFkeSgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICBnZXRXc0NvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQuJyk7XG4gICAgfVxufVxuTW9ja0Vudmlyb25tZW50XzEgPSBtb2NrRW52aXJvbm1lbnQuTW9ja0Vudmlyb25tZW50ID0gTW9ja0Vudmlyb25tZW50O1xuXG52YXIgbW9ja1dpcmUgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vY2tXaXJlLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnZhciBNb2NrV2lyZV8xID0gbW9ja1dpcmUuTW9ja1dpcmUgPSB2b2lkIDA7XG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi9cbmNvbnN0IGV2ZW50c18xID0gcmVxdWlyZSQkMDtcbmNsYXNzIE1vY2tXaXJlIGV4dGVuZHMgZXZlbnRzXzEuRXZlbnRFbWl0dGVyIHtcbiAgICBjb25uZWN0KCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBhcmUgbm90IHJ1bm5pbmcgaW4gT3BlbkZpbi4nKTtcbiAgICB9XG4gICAgY29ubmVjdFN5bmMoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IGFyZSBub3QgcnVubmluZyBpbiBPcGVuRmluLicpO1xuICAgIH1cbiAgICBzZW5kKGRhdGEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgYXJlIG5vdCBydW5uaW5nIGluIE9wZW5GaW4uJyk7XG4gICAgfVxuICAgIHNodXRkb3duKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBhcmUgbm90IHJ1bm5pbmcgaW4gT3BlbkZpbi4nKTtcbiAgICB9XG4gICAgZ2V0UG9ydCgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGlzIHRyYW5zcG9ydCBoYXMgbm8gcG9ydCcpO1xuICAgIH1cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlbGVzcy1jb25zdHJ1Y3RvclxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcigpO1xuICAgIH1cbn1cbk1vY2tXaXJlXzEgPSBtb2NrV2lyZS5Nb2NrV2lyZSA9IE1vY2tXaXJlO1xuXG5jb25zdCBmaW4kMSA9ICgodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgd2luZG93Py5maW4pIHx8XG4gICAgKCgpID0+IHtcbiAgICAgICAgY29uc3QgZW52aXJvbm1lbnQgPSBuZXcgTW9ja0Vudmlyb25tZW50XzEoKTtcbiAgICAgICAgY29uc3QgdHJhbnNwb3J0ID0gbmV3IFRyYW5zcG9ydF8xKE1vY2tXaXJlXzEsIGVudmlyb25tZW50LCB7XG4gICAgICAgICAgICB1dWlkOiAnJyxcbiAgICAgICAgICAgIG5hbWU6ICcnXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbmV3IEZpbl8xKHRyYW5zcG9ydCk7XG4gICAgfSkoKSk7XG5cbmV4cG9ydHMuT3BlbkZpbiA9IE9wZW5GaW4kMTtcbmV4cG9ydHMuZGVmYXVsdCA9IE9wZW5GaW4kMTtcbmV4cG9ydHMuZmluID0gZmluJDE7XG4iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgUiA9IHR5cGVvZiBSZWZsZWN0ID09PSAnb2JqZWN0JyA/IFJlZmxlY3QgOiBudWxsXG52YXIgUmVmbGVjdEFwcGx5ID0gUiAmJiB0eXBlb2YgUi5hcHBseSA9PT0gJ2Z1bmN0aW9uJ1xuICA/IFIuYXBwbHlcbiAgOiBmdW5jdGlvbiBSZWZsZWN0QXBwbHkodGFyZ2V0LCByZWNlaXZlciwgYXJncykge1xuICAgIHJldHVybiBGdW5jdGlvbi5wcm90b3R5cGUuYXBwbHkuY2FsbCh0YXJnZXQsIHJlY2VpdmVyLCBhcmdzKTtcbiAgfVxuXG52YXIgUmVmbGVjdE93bktleXNcbmlmIChSICYmIHR5cGVvZiBSLm93bktleXMgPT09ICdmdW5jdGlvbicpIHtcbiAgUmVmbGVjdE93bktleXMgPSBSLm93bktleXNcbn0gZWxzZSBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scykge1xuICBSZWZsZWN0T3duS2V5cyA9IGZ1bmN0aW9uIFJlZmxlY3RPd25LZXlzKHRhcmdldCkge1xuICAgIHJldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0YXJnZXQpXG4gICAgICAuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHModGFyZ2V0KSk7XG4gIH07XG59IGVsc2Uge1xuICBSZWZsZWN0T3duS2V5cyA9IGZ1bmN0aW9uIFJlZmxlY3RPd25LZXlzKHRhcmdldCkge1xuICAgIHJldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0YXJnZXQpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBQcm9jZXNzRW1pdFdhcm5pbmcod2FybmluZykge1xuICBpZiAoY29uc29sZSAmJiBjb25zb2xlLndhcm4pIGNvbnNvbGUud2Fybih3YXJuaW5nKTtcbn1cblxudmFyIE51bWJlcklzTmFOID0gTnVtYmVyLmlzTmFOIHx8IGZ1bmN0aW9uIE51bWJlcklzTmFOKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSAhPT0gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIEV2ZW50RW1pdHRlcigpIHtcbiAgRXZlbnRFbWl0dGVyLmluaXQuY2FsbCh0aGlzKTtcbn1cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xubW9kdWxlLmV4cG9ydHMub25jZSA9IG9uY2U7XG5cbi8vIEJhY2t3YXJkcy1jb21wYXQgd2l0aCBub2RlIDAuMTAueFxuRXZlbnRFbWl0dGVyLkV2ZW50RW1pdHRlciA9IEV2ZW50RW1pdHRlcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fZXZlbnRzID0gdW5kZWZpbmVkO1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fZXZlbnRzQ291bnQgPSAwO1xuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5fbWF4TGlzdGVuZXJzID0gdW5kZWZpbmVkO1xuXG4vLyBCeSBkZWZhdWx0IEV2ZW50RW1pdHRlcnMgd2lsbCBwcmludCBhIHdhcm5pbmcgaWYgbW9yZSB0aGFuIDEwIGxpc3RlbmVycyBhcmVcbi8vIGFkZGVkIHRvIGl0LiBUaGlzIGlzIGEgdXNlZnVsIGRlZmF1bHQgd2hpY2ggaGVscHMgZmluZGluZyBtZW1vcnkgbGVha3MuXG52YXIgZGVmYXVsdE1heExpc3RlbmVycyA9IDEwO1xuXG5mdW5jdGlvbiBjaGVja0xpc3RlbmVyKGxpc3RlbmVyKSB7XG4gIGlmICh0eXBlb2YgbGlzdGVuZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgXCJsaXN0ZW5lclwiIGFyZ3VtZW50IG11c3QgYmUgb2YgdHlwZSBGdW5jdGlvbi4gUmVjZWl2ZWQgdHlwZSAnICsgdHlwZW9mIGxpc3RlbmVyKTtcbiAgfVxufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoRXZlbnRFbWl0dGVyLCAnZGVmYXVsdE1heExpc3RlbmVycycsIHtcbiAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZGVmYXVsdE1heExpc3RlbmVycztcbiAgfSxcbiAgc2V0OiBmdW5jdGlvbihhcmcpIHtcbiAgICBpZiAodHlwZW9mIGFyZyAhPT0gJ251bWJlcicgfHwgYXJnIDwgMCB8fCBOdW1iZXJJc05hTihhcmcpKSB7XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVGhlIHZhbHVlIG9mIFwiZGVmYXVsdE1heExpc3RlbmVyc1wiIGlzIG91dCBvZiByYW5nZS4gSXQgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBudW1iZXIuIFJlY2VpdmVkICcgKyBhcmcgKyAnLicpO1xuICAgIH1cbiAgICBkZWZhdWx0TWF4TGlzdGVuZXJzID0gYXJnO1xuICB9XG59KTtcblxuRXZlbnRFbWl0dGVyLmluaXQgPSBmdW5jdGlvbigpIHtcblxuICBpZiAodGhpcy5fZXZlbnRzID09PSB1bmRlZmluZWQgfHxcbiAgICAgIHRoaXMuX2V2ZW50cyA9PT0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMpLl9ldmVudHMpIHtcbiAgICB0aGlzLl9ldmVudHMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgfVxuXG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59O1xuXG4vLyBPYnZpb3VzbHkgbm90IGFsbCBFbWl0dGVycyBzaG91bGQgYmUgbGltaXRlZCB0byAxMC4gVGhpcyBmdW5jdGlvbiBhbGxvd3Ncbi8vIHRoYXQgdG8gYmUgaW5jcmVhc2VkLiBTZXQgdG8gemVybyBmb3IgdW5saW1pdGVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5zZXRNYXhMaXN0ZW5lcnMgPSBmdW5jdGlvbiBzZXRNYXhMaXN0ZW5lcnMobikge1xuICBpZiAodHlwZW9mIG4gIT09ICdudW1iZXInIHx8IG4gPCAwIHx8IE51bWJlcklzTmFOKG4pKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RoZSB2YWx1ZSBvZiBcIm5cIiBpcyBvdXQgb2YgcmFuZ2UuIEl0IG11c3QgYmUgYSBub24tbmVnYXRpdmUgbnVtYmVyLiBSZWNlaXZlZCAnICsgbiArICcuJyk7XG4gIH1cbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gbjtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5mdW5jdGlvbiBfZ2V0TWF4TGlzdGVuZXJzKHRoYXQpIHtcbiAgaWYgKHRoYXQuX21heExpc3RlbmVycyA9PT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiBFdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycztcbiAgcmV0dXJuIHRoYXQuX21heExpc3RlbmVycztcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5nZXRNYXhMaXN0ZW5lcnMgPSBmdW5jdGlvbiBnZXRNYXhMaXN0ZW5lcnMoKSB7XG4gIHJldHVybiBfZ2V0TWF4TGlzdGVuZXJzKHRoaXMpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24gZW1pdCh0eXBlKSB7XG4gIHZhciBhcmdzID0gW107XG4gIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSBhcmdzLnB1c2goYXJndW1lbnRzW2ldKTtcbiAgdmFyIGRvRXJyb3IgPSAodHlwZSA9PT0gJ2Vycm9yJyk7XG5cbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgaWYgKGV2ZW50cyAhPT0gdW5kZWZpbmVkKVxuICAgIGRvRXJyb3IgPSAoZG9FcnJvciAmJiBldmVudHMuZXJyb3IgPT09IHVuZGVmaW5lZCk7XG4gIGVsc2UgaWYgKCFkb0Vycm9yKVxuICAgIHJldHVybiBmYWxzZTtcblxuICAvLyBJZiB0aGVyZSBpcyBubyAnZXJyb3InIGV2ZW50IGxpc3RlbmVyIHRoZW4gdGhyb3cuXG4gIGlmIChkb0Vycm9yKSB7XG4gICAgdmFyIGVyO1xuICAgIGlmIChhcmdzLmxlbmd0aCA+IDApXG4gICAgICBlciA9IGFyZ3NbMF07XG4gICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIC8vIE5vdGU6IFRoZSBjb21tZW50cyBvbiB0aGUgYHRocm93YCBsaW5lcyBhcmUgaW50ZW50aW9uYWwsIHRoZXkgc2hvd1xuICAgICAgLy8gdXAgaW4gTm9kZSdzIG91dHB1dCBpZiB0aGlzIHJlc3VsdHMgaW4gYW4gdW5oYW5kbGVkIGV4Y2VwdGlvbi5cbiAgICAgIHRocm93IGVyOyAvLyBVbmhhbmRsZWQgJ2Vycm9yJyBldmVudFxuICAgIH1cbiAgICAvLyBBdCBsZWFzdCBnaXZlIHNvbWUga2luZCBvZiBjb250ZXh0IHRvIHRoZSB1c2VyXG4gICAgdmFyIGVyciA9IG5ldyBFcnJvcignVW5oYW5kbGVkIGVycm9yLicgKyAoZXIgPyAnICgnICsgZXIubWVzc2FnZSArICcpJyA6ICcnKSk7XG4gICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICB0aHJvdyBlcnI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gIH1cblxuICB2YXIgaGFuZGxlciA9IGV2ZW50c1t0eXBlXTtcblxuICBpZiAoaGFuZGxlciA9PT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiBmYWxzZTtcblxuICBpZiAodHlwZW9mIGhhbmRsZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICBSZWZsZWN0QXBwbHkoaGFuZGxlciwgdGhpcywgYXJncyk7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGxlbiA9IGhhbmRsZXIubGVuZ3RoO1xuICAgIHZhciBsaXN0ZW5lcnMgPSBhcnJheUNsb25lKGhhbmRsZXIsIGxlbik7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSlcbiAgICAgIFJlZmxlY3RBcHBseShsaXN0ZW5lcnNbaV0sIHRoaXMsIGFyZ3MpO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5mdW5jdGlvbiBfYWRkTGlzdGVuZXIodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lciwgcHJlcGVuZCkge1xuICB2YXIgbTtcbiAgdmFyIGV2ZW50cztcbiAgdmFyIGV4aXN0aW5nO1xuXG4gIGNoZWNrTGlzdGVuZXIobGlzdGVuZXIpO1xuXG4gIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuICBpZiAoZXZlbnRzID09PSB1bmRlZmluZWQpIHtcbiAgICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgdGFyZ2V0Ll9ldmVudHNDb3VudCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gICAgaWYgKGV2ZW50cy5uZXdMaXN0ZW5lciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0YXJnZXQuZW1pdCgnbmV3TGlzdGVuZXInLCB0eXBlLFxuICAgICAgICAgICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgPyBsaXN0ZW5lci5saXN0ZW5lciA6IGxpc3RlbmVyKTtcblxuICAgICAgLy8gUmUtYXNzaWduIGBldmVudHNgIGJlY2F1c2UgYSBuZXdMaXN0ZW5lciBoYW5kbGVyIGNvdWxkIGhhdmUgY2F1c2VkIHRoZVxuICAgICAgLy8gdGhpcy5fZXZlbnRzIHRvIGJlIGFzc2lnbmVkIHRvIGEgbmV3IG9iamVjdFxuICAgICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHM7XG4gICAgfVxuICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdO1xuICB9XG5cbiAgaWYgKGV4aXN0aW5nID09PSB1bmRlZmluZWQpIHtcbiAgICAvLyBPcHRpbWl6ZSB0aGUgY2FzZSBvZiBvbmUgbGlzdGVuZXIuIERvbid0IG5lZWQgdGhlIGV4dHJhIGFycmF5IG9iamVjdC5cbiAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9IGxpc3RlbmVyO1xuICAgICsrdGFyZ2V0Ll9ldmVudHNDb3VudDtcbiAgfSBlbHNlIHtcbiAgICBpZiAodHlwZW9mIGV4aXN0aW5nID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAvLyBBZGRpbmcgdGhlIHNlY29uZCBlbGVtZW50LCBuZWVkIHRvIGNoYW5nZSB0byBhcnJheS5cbiAgICAgIGV4aXN0aW5nID0gZXZlbnRzW3R5cGVdID1cbiAgICAgICAgcHJlcGVuZCA/IFtsaXN0ZW5lciwgZXhpc3RpbmddIDogW2V4aXN0aW5nLCBsaXN0ZW5lcl07XG4gICAgICAvLyBJZiB3ZSd2ZSBhbHJlYWR5IGdvdCBhbiBhcnJheSwganVzdCBhcHBlbmQuXG4gICAgfSBlbHNlIGlmIChwcmVwZW5kKSB7XG4gICAgICBleGlzdGluZy51bnNoaWZ0KGxpc3RlbmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZXhpc3RpbmcucHVzaChsaXN0ZW5lcik7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgICBtID0gX2dldE1heExpc3RlbmVycyh0YXJnZXQpO1xuICAgIGlmIChtID4gMCAmJiBleGlzdGluZy5sZW5ndGggPiBtICYmICFleGlzdGluZy53YXJuZWQpIHtcbiAgICAgIGV4aXN0aW5nLndhcm5lZCA9IHRydWU7XG4gICAgICAvLyBObyBlcnJvciBjb2RlIGZvciB0aGlzIHNpbmNlIGl0IGlzIGEgV2FybmluZ1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXJlc3RyaWN0ZWQtc3ludGF4XG4gICAgICB2YXIgdyA9IG5ldyBFcnJvcignUG9zc2libGUgRXZlbnRFbWl0dGVyIG1lbW9yeSBsZWFrIGRldGVjdGVkLiAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmcubGVuZ3RoICsgJyAnICsgU3RyaW5nKHR5cGUpICsgJyBsaXN0ZW5lcnMgJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdhZGRlZC4gVXNlIGVtaXR0ZXIuc2V0TWF4TGlzdGVuZXJzKCkgdG8gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdpbmNyZWFzZSBsaW1pdCcpO1xuICAgICAgdy5uYW1lID0gJ01heExpc3RlbmVyc0V4Y2VlZGVkV2FybmluZyc7XG4gICAgICB3LmVtaXR0ZXIgPSB0YXJnZXQ7XG4gICAgICB3LnR5cGUgPSB0eXBlO1xuICAgICAgdy5jb3VudCA9IGV4aXN0aW5nLmxlbmd0aDtcbiAgICAgIFByb2Nlc3NFbWl0V2FybmluZyh3KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGFyZ2V0O1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gYWRkTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgcmV0dXJuIF9hZGRMaXN0ZW5lcih0aGlzLCB0eXBlLCBsaXN0ZW5lciwgZmFsc2UpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZExpc3RlbmVyID1cbiAgICBmdW5jdGlvbiBwcmVwZW5kTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIHRydWUpO1xuICAgIH07XG5cbmZ1bmN0aW9uIG9uY2VXcmFwcGVyKCkge1xuICBpZiAoIXRoaXMuZmlyZWQpIHtcbiAgICB0aGlzLnRhcmdldC5yZW1vdmVMaXN0ZW5lcih0aGlzLnR5cGUsIHRoaXMud3JhcEZuKTtcbiAgICB0aGlzLmZpcmVkID0gdHJ1ZTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMClcbiAgICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmNhbGwodGhpcy50YXJnZXQpO1xuICAgIHJldHVybiB0aGlzLmxpc3RlbmVyLmFwcGx5KHRoaXMudGFyZ2V0LCBhcmd1bWVudHMpO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9vbmNlV3JhcCh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBzdGF0ZSA9IHsgZmlyZWQ6IGZhbHNlLCB3cmFwRm46IHVuZGVmaW5lZCwgdGFyZ2V0OiB0YXJnZXQsIHR5cGU6IHR5cGUsIGxpc3RlbmVyOiBsaXN0ZW5lciB9O1xuICB2YXIgd3JhcHBlZCA9IG9uY2VXcmFwcGVyLmJpbmQoc3RhdGUpO1xuICB3cmFwcGVkLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHN0YXRlLndyYXBGbiA9IHdyYXBwZWQ7XG4gIHJldHVybiB3cmFwcGVkO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbiBvbmNlKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGNoZWNrTGlzdGVuZXIobGlzdGVuZXIpO1xuICB0aGlzLm9uKHR5cGUsIF9vbmNlV3JhcCh0aGlzLCB0eXBlLCBsaXN0ZW5lcikpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucHJlcGVuZE9uY2VMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZE9uY2VMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgY2hlY2tMaXN0ZW5lcihsaXN0ZW5lcik7XG4gICAgICB0aGlzLnByZXBlbmRMaXN0ZW5lcih0eXBlLCBfb25jZVdyYXAodGhpcywgdHlwZSwgbGlzdGVuZXIpKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbi8vIEVtaXRzIGEgJ3JlbW92ZUxpc3RlbmVyJyBldmVudCBpZiBhbmQgb25seSBpZiB0aGUgbGlzdGVuZXIgd2FzIHJlbW92ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID1cbiAgICBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcikge1xuICAgICAgdmFyIGxpc3QsIGV2ZW50cywgcG9zaXRpb24sIGksIG9yaWdpbmFsTGlzdGVuZXI7XG5cbiAgICAgIGNoZWNrTGlzdGVuZXIobGlzdGVuZXIpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoZXZlbnRzID09PSB1bmRlZmluZWQpXG4gICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICBsaXN0ID0gZXZlbnRzW3R5cGVdO1xuICAgICAgaWYgKGxpc3QgPT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fCBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICBpZiAoLS10aGlzLl9ldmVudHNDb3VudCA9PT0gMClcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdC5saXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGxpc3QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcG9zaXRpb24gPSAtMTtcblxuICAgICAgICBmb3IgKGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgaWYgKGxpc3RbaV0gPT09IGxpc3RlbmVyIHx8IGxpc3RbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICBvcmlnaW5hbExpc3RlbmVyID0gbGlzdFtpXS5saXN0ZW5lcjtcbiAgICAgICAgICAgIHBvc2l0aW9uID0gaTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwb3NpdGlvbiA8IDApXG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgICAgaWYgKHBvc2l0aW9uID09PSAwKVxuICAgICAgICAgIGxpc3Quc2hpZnQoKTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgc3BsaWNlT25lKGxpc3QsIHBvc2l0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsaXN0Lmxlbmd0aCA9PT0gMSlcbiAgICAgICAgICBldmVudHNbdHlwZV0gPSBsaXN0WzBdO1xuXG4gICAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgb3JpZ2luYWxMaXN0ZW5lciB8fCBsaXN0ZW5lcik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub2ZmID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPVxuICAgIGZ1bmN0aW9uIHJlbW92ZUFsbExpc3RlbmVycyh0eXBlKSB7XG4gICAgICB2YXIgbGlzdGVuZXJzLCBldmVudHMsIGk7XG5cbiAgICAgIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcbiAgICAgIGlmIChldmVudHMgPT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICAgIC8vIG5vdCBsaXN0ZW5pbmcgZm9yIHJlbW92ZUxpc3RlbmVyLCBubyBuZWVkIHRvIGVtaXRcbiAgICAgIGlmIChldmVudHMucmVtb3ZlTGlzdGVuZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuX2V2ZW50cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50c1t0eXBlXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgaWYgKC0tdGhpcy5fZXZlbnRzQ291bnQgPT09IDApXG4gICAgICAgICAgICB0aGlzLl9ldmVudHMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGRlbGV0ZSBldmVudHNbdHlwZV07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhldmVudHMpO1xuICAgICAgICB2YXIga2V5O1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICAgICAgaWYgKGtleSA9PT0gJ3JlbW92ZUxpc3RlbmVyJykgY29udGludWU7XG4gICAgICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycygncmVtb3ZlTGlzdGVuZXInKTtcbiAgICAgICAgdGhpcy5fZXZlbnRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAgICAgdGhpcy5fZXZlbnRzQ291bnQgPSAwO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgbGlzdGVuZXJzID0gZXZlbnRzW3R5cGVdO1xuXG4gICAgICBpZiAodHlwZW9mIGxpc3RlbmVycyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVycyk7XG4gICAgICB9IGVsc2UgaWYgKGxpc3RlbmVycyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIExJRk8gb3JkZXJcbiAgICAgICAgZm9yIChpID0gbGlzdGVuZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbmZ1bmN0aW9uIF9saXN0ZW5lcnModGFyZ2V0LCB0eXBlLCB1bndyYXApIHtcbiAgdmFyIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuXG4gIGlmIChldmVudHMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gW107XG5cbiAgdmFyIGV2bGlzdGVuZXIgPSBldmVudHNbdHlwZV07XG4gIGlmIChldmxpc3RlbmVyID09PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIFtdO1xuXG4gIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJylcbiAgICByZXR1cm4gdW53cmFwID8gW2V2bGlzdGVuZXIubGlzdGVuZXIgfHwgZXZsaXN0ZW5lcl0gOiBbZXZsaXN0ZW5lcl07XG5cbiAgcmV0dXJuIHVud3JhcCA/XG4gICAgdW53cmFwTGlzdGVuZXJzKGV2bGlzdGVuZXIpIDogYXJyYXlDbG9uZShldmxpc3RlbmVyLCBldmxpc3RlbmVyLmxlbmd0aCk7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJzID0gZnVuY3Rpb24gbGlzdGVuZXJzKHR5cGUpIHtcbiAgcmV0dXJuIF9saXN0ZW5lcnModGhpcywgdHlwZSwgdHJ1ZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJhd0xpc3RlbmVycyA9IGZ1bmN0aW9uIHJhd0xpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5saXN0ZW5lckNvdW50ID0gZnVuY3Rpb24oZW1pdHRlciwgdHlwZSkge1xuICBpZiAodHlwZW9mIGVtaXR0ZXIubGlzdGVuZXJDb3VudCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBlbWl0dGVyLmxpc3RlbmVyQ291bnQodHlwZSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGxpc3RlbmVyQ291bnQuY2FsbChlbWl0dGVyLCB0eXBlKTtcbiAgfVxufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lckNvdW50ID0gbGlzdGVuZXJDb3VudDtcbmZ1bmN0aW9uIGxpc3RlbmVyQ291bnQodHlwZSkge1xuICB2YXIgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuXG4gIGlmIChldmVudHMgIT09IHVuZGVmaW5lZCkge1xuICAgIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuXG4gICAgaWYgKHR5cGVvZiBldmxpc3RlbmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9IGVsc2UgaWYgKGV2bGlzdGVuZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAwO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmV2ZW50TmFtZXMgPSBmdW5jdGlvbiBldmVudE5hbWVzKCkge1xuICByZXR1cm4gdGhpcy5fZXZlbnRzQ291bnQgPiAwID8gUmVmbGVjdE93bktleXModGhpcy5fZXZlbnRzKSA6IFtdO1xufTtcblxuZnVuY3Rpb24gYXJyYXlDbG9uZShhcnIsIG4pIHtcbiAgdmFyIGNvcHkgPSBuZXcgQXJyYXkobik7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKVxuICAgIGNvcHlbaV0gPSBhcnJbaV07XG4gIHJldHVybiBjb3B5O1xufVxuXG5mdW5jdGlvbiBzcGxpY2VPbmUobGlzdCwgaW5kZXgpIHtcbiAgZm9yICg7IGluZGV4ICsgMSA8IGxpc3QubGVuZ3RoOyBpbmRleCsrKVxuICAgIGxpc3RbaW5kZXhdID0gbGlzdFtpbmRleCArIDFdO1xuICBsaXN0LnBvcCgpO1xufVxuXG5mdW5jdGlvbiB1bndyYXBMaXN0ZW5lcnMoYXJyKSB7XG4gIHZhciByZXQgPSBuZXcgQXJyYXkoYXJyLmxlbmd0aCk7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcmV0Lmxlbmd0aDsgKytpKSB7XG4gICAgcmV0W2ldID0gYXJyW2ldLmxpc3RlbmVyIHx8IGFycltpXTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBvbmNlKGVtaXR0ZXIsIG5hbWUpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBmdW5jdGlvbiBlcnJvckxpc3RlbmVyKGVycikge1xuICAgICAgZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihuYW1lLCByZXNvbHZlcik7XG4gICAgICByZWplY3QoZXJyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNvbHZlcigpIHtcbiAgICAgIGlmICh0eXBlb2YgZW1pdHRlci5yZW1vdmVMaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBlbWl0dGVyLnJlbW92ZUxpc3RlbmVyKCdlcnJvcicsIGVycm9yTGlzdGVuZXIpO1xuICAgICAgfVxuICAgICAgcmVzb2x2ZShbXS5zbGljZS5jYWxsKGFyZ3VtZW50cykpO1xuICAgIH07XG5cbiAgICBldmVudFRhcmdldEFnbm9zdGljQWRkTGlzdGVuZXIoZW1pdHRlciwgbmFtZSwgcmVzb2x2ZXIsIHsgb25jZTogdHJ1ZSB9KTtcbiAgICBpZiAobmFtZSAhPT0gJ2Vycm9yJykge1xuICAgICAgYWRkRXJyb3JIYW5kbGVySWZFdmVudEVtaXR0ZXIoZW1pdHRlciwgZXJyb3JMaXN0ZW5lciwgeyBvbmNlOiB0cnVlIH0pO1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGFkZEVycm9ySGFuZGxlcklmRXZlbnRFbWl0dGVyKGVtaXR0ZXIsIGhhbmRsZXIsIGZsYWdzKSB7XG4gIGlmICh0eXBlb2YgZW1pdHRlci5vbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGV2ZW50VGFyZ2V0QWdub3N0aWNBZGRMaXN0ZW5lcihlbWl0dGVyLCAnZXJyb3InLCBoYW5kbGVyLCBmbGFncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZXZlbnRUYXJnZXRBZ25vc3RpY0FkZExpc3RlbmVyKGVtaXR0ZXIsIG5hbWUsIGxpc3RlbmVyLCBmbGFncykge1xuICBpZiAodHlwZW9mIGVtaXR0ZXIub24gPT09ICdmdW5jdGlvbicpIHtcbiAgICBpZiAoZmxhZ3Mub25jZSkge1xuICAgICAgZW1pdHRlci5vbmNlKG5hbWUsIGxpc3RlbmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZW1pdHRlci5vbihuYW1lLCBsaXN0ZW5lcik7XG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGVvZiBlbWl0dGVyLmFkZEV2ZW50TGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAvLyBFdmVudFRhcmdldCBkb2VzIG5vdCBoYXZlIGBlcnJvcmAgZXZlbnQgc2VtYW50aWNzIGxpa2UgTm9kZVxuICAgIC8vIEV2ZW50RW1pdHRlcnMsIHdlIGRvIG5vdCBsaXN0ZW4gZm9yIGBlcnJvcmAgZXZlbnRzIGhlcmUuXG4gICAgZW1pdHRlci5hZGRFdmVudExpc3RlbmVyKG5hbWUsIGZ1bmN0aW9uIHdyYXBMaXN0ZW5lcihhcmcpIHtcbiAgICAgIC8vIElFIGRvZXMgbm90IGhhdmUgYnVpbHRpbiBgeyBvbmNlOiB0cnVlIH1gIHN1cHBvcnQgc28gd2VcbiAgICAgIC8vIGhhdmUgdG8gZG8gaXQgbWFudWFsbHkuXG4gICAgICBpZiAoZmxhZ3Mub25jZSkge1xuICAgICAgICBlbWl0dGVyLnJlbW92ZUV2ZW50TGlzdGVuZXIobmFtZSwgd3JhcExpc3RlbmVyKTtcbiAgICAgIH1cbiAgICAgIGxpc3RlbmVyKGFyZyk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIFwiZW1pdHRlclwiIGFyZ3VtZW50IG11c3QgYmUgb2YgdHlwZSBFdmVudEVtaXR0ZXIuIFJlY2VpdmVkIHR5cGUgJyArIHR5cGVvZiBlbWl0dGVyKTtcbiAgfVxufVxuIiwidmFyIGdldE5hdGl2ZSA9IHJlcXVpcmUoJy4vX2dldE5hdGl2ZScpLFxuICAgIHJvb3QgPSByZXF1aXJlKCcuL19yb290Jyk7XG5cbi8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHRoYXQgYXJlIHZlcmlmaWVkIHRvIGJlIG5hdGl2ZS4gKi9cbnZhciBEYXRhVmlldyA9IGdldE5hdGl2ZShyb290LCAnRGF0YVZpZXcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBEYXRhVmlldztcbiIsInZhciBoYXNoQ2xlYXIgPSByZXF1aXJlKCcuL19oYXNoQ2xlYXInKSxcbiAgICBoYXNoRGVsZXRlID0gcmVxdWlyZSgnLi9faGFzaERlbGV0ZScpLFxuICAgIGhhc2hHZXQgPSByZXF1aXJlKCcuL19oYXNoR2V0JyksXG4gICAgaGFzaEhhcyA9IHJlcXVpcmUoJy4vX2hhc2hIYXMnKSxcbiAgICBoYXNoU2V0ID0gcmVxdWlyZSgnLi9faGFzaFNldCcpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBoYXNoIG9iamVjdC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0FycmF5fSBbZW50cmllc10gVGhlIGtleS12YWx1ZSBwYWlycyB0byBjYWNoZS5cbiAqL1xuZnVuY3Rpb24gSGFzaChlbnRyaWVzKSB7XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgbGVuZ3RoID0gZW50cmllcyA9PSBudWxsID8gMCA6IGVudHJpZXMubGVuZ3RoO1xuXG4gIHRoaXMuY2xlYXIoKTtcbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICB2YXIgZW50cnkgPSBlbnRyaWVzW2luZGV4XTtcbiAgICB0aGlzLnNldChlbnRyeVswXSwgZW50cnlbMV0pO1xuICB9XG59XG5cbi8vIEFkZCBtZXRob2RzIHRvIGBIYXNoYC5cbkhhc2gucHJvdG90eXBlLmNsZWFyID0gaGFzaENsZWFyO1xuSGFzaC5wcm90b3R5cGVbJ2RlbGV0ZSddID0gaGFzaERlbGV0ZTtcbkhhc2gucHJvdG90eXBlLmdldCA9IGhhc2hHZXQ7XG5IYXNoLnByb3RvdHlwZS5oYXMgPSBoYXNoSGFzO1xuSGFzaC5wcm90b3R5cGUuc2V0ID0gaGFzaFNldDtcblxubW9kdWxlLmV4cG9ydHMgPSBIYXNoO1xuIiwidmFyIGxpc3RDYWNoZUNsZWFyID0gcmVxdWlyZSgnLi9fbGlzdENhY2hlQ2xlYXInKSxcbiAgICBsaXN0Q2FjaGVEZWxldGUgPSByZXF1aXJlKCcuL19saXN0Q2FjaGVEZWxldGUnKSxcbiAgICBsaXN0Q2FjaGVHZXQgPSByZXF1aXJlKCcuL19saXN0Q2FjaGVHZXQnKSxcbiAgICBsaXN0Q2FjaGVIYXMgPSByZXF1aXJlKCcuL19saXN0Q2FjaGVIYXMnKSxcbiAgICBsaXN0Q2FjaGVTZXQgPSByZXF1aXJlKCcuL19saXN0Q2FjaGVTZXQnKTtcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGxpc3QgY2FjaGUgb2JqZWN0LlxuICpcbiAqIEBwcml2YXRlXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7QXJyYXl9IFtlbnRyaWVzXSBUaGUga2V5LXZhbHVlIHBhaXJzIHRvIGNhY2hlLlxuICovXG5mdW5jdGlvbiBMaXN0Q2FjaGUoZW50cmllcykge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IGVudHJpZXMgPT0gbnVsbCA/IDAgOiBlbnRyaWVzLmxlbmd0aDtcblxuICB0aGlzLmNsZWFyKCk7XG4gIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgdmFyIGVudHJ5ID0gZW50cmllc1tpbmRleF07XG4gICAgdGhpcy5zZXQoZW50cnlbMF0sIGVudHJ5WzFdKTtcbiAgfVxufVxuXG4vLyBBZGQgbWV0aG9kcyB0byBgTGlzdENhY2hlYC5cbkxpc3RDYWNoZS5wcm90b3R5cGUuY2xlYXIgPSBsaXN0Q2FjaGVDbGVhcjtcbkxpc3RDYWNoZS5wcm90b3R5cGVbJ2RlbGV0ZSddID0gbGlzdENhY2hlRGVsZXRlO1xuTGlzdENhY2hlLnByb3RvdHlwZS5nZXQgPSBsaXN0Q2FjaGVHZXQ7XG5MaXN0Q2FjaGUucHJvdG90eXBlLmhhcyA9IGxpc3RDYWNoZUhhcztcbkxpc3RDYWNoZS5wcm90b3R5cGUuc2V0ID0gbGlzdENhY2hlU2V0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IExpc3RDYWNoZTtcbiIsInZhciBnZXROYXRpdmUgPSByZXF1aXJlKCcuL19nZXROYXRpdmUnKSxcbiAgICByb290ID0gcmVxdWlyZSgnLi9fcm9vdCcpO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyB0aGF0IGFyZSB2ZXJpZmllZCB0byBiZSBuYXRpdmUuICovXG52YXIgTWFwID0gZ2V0TmF0aXZlKHJvb3QsICdNYXAnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBNYXA7XG4iLCJ2YXIgbWFwQ2FjaGVDbGVhciA9IHJlcXVpcmUoJy4vX21hcENhY2hlQ2xlYXInKSxcbiAgICBtYXBDYWNoZURlbGV0ZSA9IHJlcXVpcmUoJy4vX21hcENhY2hlRGVsZXRlJyksXG4gICAgbWFwQ2FjaGVHZXQgPSByZXF1aXJlKCcuL19tYXBDYWNoZUdldCcpLFxuICAgIG1hcENhY2hlSGFzID0gcmVxdWlyZSgnLi9fbWFwQ2FjaGVIYXMnKSxcbiAgICBtYXBDYWNoZVNldCA9IHJlcXVpcmUoJy4vX21hcENhY2hlU2V0Jyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG1hcCBjYWNoZSBvYmplY3QgdG8gc3RvcmUga2V5LXZhbHVlIHBhaXJzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7QXJyYXl9IFtlbnRyaWVzXSBUaGUga2V5LXZhbHVlIHBhaXJzIHRvIGNhY2hlLlxuICovXG5mdW5jdGlvbiBNYXBDYWNoZShlbnRyaWVzKSB7XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgbGVuZ3RoID0gZW50cmllcyA9PSBudWxsID8gMCA6IGVudHJpZXMubGVuZ3RoO1xuXG4gIHRoaXMuY2xlYXIoKTtcbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICB2YXIgZW50cnkgPSBlbnRyaWVzW2luZGV4XTtcbiAgICB0aGlzLnNldChlbnRyeVswXSwgZW50cnlbMV0pO1xuICB9XG59XG5cbi8vIEFkZCBtZXRob2RzIHRvIGBNYXBDYWNoZWAuXG5NYXBDYWNoZS5wcm90b3R5cGUuY2xlYXIgPSBtYXBDYWNoZUNsZWFyO1xuTWFwQ2FjaGUucHJvdG90eXBlWydkZWxldGUnXSA9IG1hcENhY2hlRGVsZXRlO1xuTWFwQ2FjaGUucHJvdG90eXBlLmdldCA9IG1hcENhY2hlR2V0O1xuTWFwQ2FjaGUucHJvdG90eXBlLmhhcyA9IG1hcENhY2hlSGFzO1xuTWFwQ2FjaGUucHJvdG90eXBlLnNldCA9IG1hcENhY2hlU2V0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IE1hcENhY2hlO1xuIiwidmFyIGdldE5hdGl2ZSA9IHJlcXVpcmUoJy4vX2dldE5hdGl2ZScpLFxuICAgIHJvb3QgPSByZXF1aXJlKCcuL19yb290Jyk7XG5cbi8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHRoYXQgYXJlIHZlcmlmaWVkIHRvIGJlIG5hdGl2ZS4gKi9cbnZhciBQcm9taXNlID0gZ2V0TmF0aXZlKHJvb3QsICdQcm9taXNlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gUHJvbWlzZTtcbiIsInZhciBnZXROYXRpdmUgPSByZXF1aXJlKCcuL19nZXROYXRpdmUnKSxcbiAgICByb290ID0gcmVxdWlyZSgnLi9fcm9vdCcpO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyB0aGF0IGFyZSB2ZXJpZmllZCB0byBiZSBuYXRpdmUuICovXG52YXIgU2V0ID0gZ2V0TmF0aXZlKHJvb3QsICdTZXQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBTZXQ7XG4iLCJ2YXIgTWFwQ2FjaGUgPSByZXF1aXJlKCcuL19NYXBDYWNoZScpLFxuICAgIHNldENhY2hlQWRkID0gcmVxdWlyZSgnLi9fc2V0Q2FjaGVBZGQnKSxcbiAgICBzZXRDYWNoZUhhcyA9IHJlcXVpcmUoJy4vX3NldENhY2hlSGFzJyk7XG5cbi8qKlxuICpcbiAqIENyZWF0ZXMgYW4gYXJyYXkgY2FjaGUgb2JqZWN0IHRvIHN0b3JlIHVuaXF1ZSB2YWx1ZXMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtBcnJheX0gW3ZhbHVlc10gVGhlIHZhbHVlcyB0byBjYWNoZS5cbiAqL1xuZnVuY3Rpb24gU2V0Q2FjaGUodmFsdWVzKSB7XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgbGVuZ3RoID0gdmFsdWVzID09IG51bGwgPyAwIDogdmFsdWVzLmxlbmd0aDtcblxuICB0aGlzLl9fZGF0YV9fID0gbmV3IE1hcENhY2hlO1xuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIHRoaXMuYWRkKHZhbHVlc1tpbmRleF0pO1xuICB9XG59XG5cbi8vIEFkZCBtZXRob2RzIHRvIGBTZXRDYWNoZWAuXG5TZXRDYWNoZS5wcm90b3R5cGUuYWRkID0gU2V0Q2FjaGUucHJvdG90eXBlLnB1c2ggPSBzZXRDYWNoZUFkZDtcblNldENhY2hlLnByb3RvdHlwZS5oYXMgPSBzZXRDYWNoZUhhcztcblxubW9kdWxlLmV4cG9ydHMgPSBTZXRDYWNoZTtcbiIsInZhciBMaXN0Q2FjaGUgPSByZXF1aXJlKCcuL19MaXN0Q2FjaGUnKSxcbiAgICBzdGFja0NsZWFyID0gcmVxdWlyZSgnLi9fc3RhY2tDbGVhcicpLFxuICAgIHN0YWNrRGVsZXRlID0gcmVxdWlyZSgnLi9fc3RhY2tEZWxldGUnKSxcbiAgICBzdGFja0dldCA9IHJlcXVpcmUoJy4vX3N0YWNrR2V0JyksXG4gICAgc3RhY2tIYXMgPSByZXF1aXJlKCcuL19zdGFja0hhcycpLFxuICAgIHN0YWNrU2V0ID0gcmVxdWlyZSgnLi9fc3RhY2tTZXQnKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgc3RhY2sgY2FjaGUgb2JqZWN0IHRvIHN0b3JlIGtleS12YWx1ZSBwYWlycy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0FycmF5fSBbZW50cmllc10gVGhlIGtleS12YWx1ZSBwYWlycyB0byBjYWNoZS5cbiAqL1xuZnVuY3Rpb24gU3RhY2soZW50cmllcykge1xuICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX18gPSBuZXcgTGlzdENhY2hlKGVudHJpZXMpO1xuICB0aGlzLnNpemUgPSBkYXRhLnNpemU7XG59XG5cbi8vIEFkZCBtZXRob2RzIHRvIGBTdGFja2AuXG5TdGFjay5wcm90b3R5cGUuY2xlYXIgPSBzdGFja0NsZWFyO1xuU3RhY2sucHJvdG90eXBlWydkZWxldGUnXSA9IHN0YWNrRGVsZXRlO1xuU3RhY2sucHJvdG90eXBlLmdldCA9IHN0YWNrR2V0O1xuU3RhY2sucHJvdG90eXBlLmhhcyA9IHN0YWNrSGFzO1xuU3RhY2sucHJvdG90eXBlLnNldCA9IHN0YWNrU2V0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN0YWNrO1xuIiwidmFyIHJvb3QgPSByZXF1aXJlKCcuL19yb290Jyk7XG5cbi8qKiBCdWlsdC1pbiB2YWx1ZSByZWZlcmVuY2VzLiAqL1xudmFyIFN5bWJvbCA9IHJvb3QuU3ltYm9sO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFN5bWJvbDtcbiIsInZhciByb290ID0gcmVxdWlyZSgnLi9fcm9vdCcpO1xuXG4vKiogQnVpbHQtaW4gdmFsdWUgcmVmZXJlbmNlcy4gKi9cbnZhciBVaW50OEFycmF5ID0gcm9vdC5VaW50OEFycmF5O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFVpbnQ4QXJyYXk7XG4iLCJ2YXIgZ2V0TmF0aXZlID0gcmVxdWlyZSgnLi9fZ2V0TmF0aXZlJyksXG4gICAgcm9vdCA9IHJlcXVpcmUoJy4vX3Jvb3QnKTtcblxuLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgdGhhdCBhcmUgdmVyaWZpZWQgdG8gYmUgbmF0aXZlLiAqL1xudmFyIFdlYWtNYXAgPSBnZXROYXRpdmUocm9vdCwgJ1dlYWtNYXAnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBXZWFrTWFwO1xuIiwiLyoqXG4gKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uZm9yRWFjaGAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gKi9cbmZ1bmN0aW9uIGFycmF5RWFjaChhcnJheSwgaXRlcmF0ZWUpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIGlmIChpdGVyYXRlZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkgPT09IGZhbHNlKSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGFycmF5O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGFycmF5RWFjaDtcbiIsIi8qKlxuICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmZpbHRlcmAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yXG4gKiBpdGVyYXRlZSBzaG9ydGhhbmRzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGZpbHRlcmVkIGFycmF5LlxuICovXG5mdW5jdGlvbiBhcnJheUZpbHRlcihhcnJheSwgcHJlZGljYXRlKSB7XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGgsXG4gICAgICByZXNJbmRleCA9IDAsXG4gICAgICByZXN1bHQgPSBbXTtcblxuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIHZhciB2YWx1ZSA9IGFycmF5W2luZGV4XTtcbiAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICByZXN1bHRbcmVzSW5kZXgrK10gPSB2YWx1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBhcnJheUZpbHRlcjtcbiIsInZhciBiYXNlVGltZXMgPSByZXF1aXJlKCcuL19iYXNlVGltZXMnKSxcbiAgICBpc0FyZ3VtZW50cyA9IHJlcXVpcmUoJy4vaXNBcmd1bWVudHMnKSxcbiAgICBpc0FycmF5ID0gcmVxdWlyZSgnLi9pc0FycmF5JyksXG4gICAgaXNCdWZmZXIgPSByZXF1aXJlKCcuL2lzQnVmZmVyJyksXG4gICAgaXNJbmRleCA9IHJlcXVpcmUoJy4vX2lzSW5kZXgnKSxcbiAgICBpc1R5cGVkQXJyYXkgPSByZXF1aXJlKCcuL2lzVHlwZWRBcnJheScpO1xuXG4vKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgb2YgdGhlIGFycmF5LWxpa2UgYHZhbHVlYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcXVlcnkuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGluaGVyaXRlZCBTcGVjaWZ5IHJldHVybmluZyBpbmhlcml0ZWQgcHJvcGVydHkgbmFtZXMuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICovXG5mdW5jdGlvbiBhcnJheUxpa2VLZXlzKHZhbHVlLCBpbmhlcml0ZWQpIHtcbiAgdmFyIGlzQXJyID0gaXNBcnJheSh2YWx1ZSksXG4gICAgICBpc0FyZyA9ICFpc0FyciAmJiBpc0FyZ3VtZW50cyh2YWx1ZSksXG4gICAgICBpc0J1ZmYgPSAhaXNBcnIgJiYgIWlzQXJnICYmIGlzQnVmZmVyKHZhbHVlKSxcbiAgICAgIGlzVHlwZSA9ICFpc0FyciAmJiAhaXNBcmcgJiYgIWlzQnVmZiAmJiBpc1R5cGVkQXJyYXkodmFsdWUpLFxuICAgICAgc2tpcEluZGV4ZXMgPSBpc0FyciB8fCBpc0FyZyB8fCBpc0J1ZmYgfHwgaXNUeXBlLFxuICAgICAgcmVzdWx0ID0gc2tpcEluZGV4ZXMgPyBiYXNlVGltZXModmFsdWUubGVuZ3RoLCBTdHJpbmcpIDogW10sXG4gICAgICBsZW5ndGggPSByZXN1bHQubGVuZ3RoO1xuXG4gIGZvciAodmFyIGtleSBpbiB2YWx1ZSkge1xuICAgIGlmICgoaW5oZXJpdGVkIHx8IGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIGtleSkpICYmXG4gICAgICAgICEoc2tpcEluZGV4ZXMgJiYgKFxuICAgICAgICAgICAvLyBTYWZhcmkgOSBoYXMgZW51bWVyYWJsZSBgYXJndW1lbnRzLmxlbmd0aGAgaW4gc3RyaWN0IG1vZGUuXG4gICAgICAgICAgIGtleSA9PSAnbGVuZ3RoJyB8fFxuICAgICAgICAgICAvLyBOb2RlLmpzIDAuMTAgaGFzIGVudW1lcmFibGUgbm9uLWluZGV4IHByb3BlcnRpZXMgb24gYnVmZmVycy5cbiAgICAgICAgICAgKGlzQnVmZiAmJiAoa2V5ID09ICdvZmZzZXQnIHx8IGtleSA9PSAncGFyZW50JykpIHx8XG4gICAgICAgICAgIC8vIFBoYW50b21KUyAyIGhhcyBlbnVtZXJhYmxlIG5vbi1pbmRleCBwcm9wZXJ0aWVzIG9uIHR5cGVkIGFycmF5cy5cbiAgICAgICAgICAgKGlzVHlwZSAmJiAoa2V5ID09ICdidWZmZXInIHx8IGtleSA9PSAnYnl0ZUxlbmd0aCcgfHwga2V5ID09ICdieXRlT2Zmc2V0JykpIHx8XG4gICAgICAgICAgIC8vIFNraXAgaW5kZXggcHJvcGVydGllcy5cbiAgICAgICAgICAgaXNJbmRleChrZXksIGxlbmd0aClcbiAgICAgICAgKSkpIHtcbiAgICAgIHJlc3VsdC5wdXNoKGtleSk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYXJyYXlMaWtlS2V5cztcbiIsIi8qKlxuICogQXBwZW5kcyB0aGUgZWxlbWVudHMgb2YgYHZhbHVlc2AgdG8gYGFycmF5YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIG1vZGlmeS5cbiAqIEBwYXJhbSB7QXJyYXl9IHZhbHVlcyBUaGUgdmFsdWVzIHRvIGFwcGVuZC5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICovXG5mdW5jdGlvbiBhcnJheVB1c2goYXJyYXksIHZhbHVlcykge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICBvZmZzZXQgPSBhcnJheS5sZW5ndGg7XG5cbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICBhcnJheVtvZmZzZXQgKyBpbmRleF0gPSB2YWx1ZXNbaW5kZXhdO1xuICB9XG4gIHJldHVybiBhcnJheTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBhcnJheVB1c2g7XG4iLCIvKipcbiAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5zb21lYCBmb3IgYXJyYXlzIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWVcbiAqIHNob3J0aGFuZHMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IFthcnJheV0gVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFueSBlbGVtZW50IHBhc3NlcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICogIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gYXJyYXlTb21lKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICBsZW5ndGggPSBhcnJheSA9PSBudWxsID8gMCA6IGFycmF5Lmxlbmd0aDtcblxuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIGlmIChwcmVkaWNhdGUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGFycmF5U29tZTtcbiIsInZhciBiYXNlQXNzaWduVmFsdWUgPSByZXF1aXJlKCcuL19iYXNlQXNzaWduVmFsdWUnKSxcbiAgICBlcSA9IHJlcXVpcmUoJy4vZXEnKTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBBc3NpZ25zIGB2YWx1ZWAgdG8gYGtleWAgb2YgYG9iamVjdGAgaWYgdGhlIGV4aXN0aW5nIHZhbHVlIGlzIG5vdCBlcXVpdmFsZW50XG4gKiB1c2luZyBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICogZm9yIGVxdWFsaXR5IGNvbXBhcmlzb25zLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gbW9kaWZ5LlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBwcm9wZXJ0eSB0byBhc3NpZ24uXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBhc3NpZ24uXG4gKi9cbmZ1bmN0aW9uIGFzc2lnblZhbHVlKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICB2YXIgb2JqVmFsdWUgPSBvYmplY3Rba2V5XTtcbiAgaWYgKCEoaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkgJiYgZXEob2JqVmFsdWUsIHZhbHVlKSkgfHxcbiAgICAgICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmICEoa2V5IGluIG9iamVjdCkpKSB7XG4gICAgYmFzZUFzc2lnblZhbHVlKG9iamVjdCwga2V5LCB2YWx1ZSk7XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBhc3NpZ25WYWx1ZTtcbiIsInZhciBlcSA9IHJlcXVpcmUoJy4vZXEnKTtcblxuLyoqXG4gKiBHZXRzIHRoZSBpbmRleCBhdCB3aGljaCB0aGUgYGtleWAgaXMgZm91bmQgaW4gYGFycmF5YCBvZiBrZXktdmFsdWUgcGFpcnMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpbnNwZWN0LlxuICogQHBhcmFtIHsqfSBrZXkgVGhlIGtleSB0byBzZWFyY2ggZm9yLlxuICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAqL1xuZnVuY3Rpb24gYXNzb2NJbmRleE9mKGFycmF5LCBrZXkpIHtcbiAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcbiAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgaWYgKGVxKGFycmF5W2xlbmd0aF1bMF0sIGtleSkpIHtcbiAgICAgIHJldHVybiBsZW5ndGg7XG4gICAgfVxuICB9XG4gIHJldHVybiAtMTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBhc3NvY0luZGV4T2Y7XG4iLCJ2YXIgY29weU9iamVjdCA9IHJlcXVpcmUoJy4vX2NvcHlPYmplY3QnKSxcbiAgICBrZXlzID0gcmVxdWlyZSgnLi9rZXlzJyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uYXNzaWduYCB3aXRob3V0IHN1cHBvcnQgZm9yIG11bHRpcGxlIHNvdXJjZXNcbiAqIG9yIGBjdXN0b21pemVyYCBmdW5jdGlvbnMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIHNvdXJjZSBvYmplY3QuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICovXG5mdW5jdGlvbiBiYXNlQXNzaWduKG9iamVjdCwgc291cmNlKSB7XG4gIHJldHVybiBvYmplY3QgJiYgY29weU9iamVjdChzb3VyY2UsIGtleXMoc291cmNlKSwgb2JqZWN0KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlQXNzaWduO1xuIiwidmFyIGNvcHlPYmplY3QgPSByZXF1aXJlKCcuL19jb3B5T2JqZWN0JyksXG4gICAga2V5c0luID0gcmVxdWlyZSgnLi9rZXlzSW4nKTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5hc3NpZ25JbmAgd2l0aG91dCBzdXBwb3J0IGZvciBtdWx0aXBsZSBzb3VyY2VzXG4gKiBvciBgY3VzdG9taXplcmAgZnVuY3Rpb25zLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBzb3VyY2Ugb2JqZWN0LlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAqL1xuZnVuY3Rpb24gYmFzZUFzc2lnbkluKG9iamVjdCwgc291cmNlKSB7XG4gIHJldHVybiBvYmplY3QgJiYgY29weU9iamVjdChzb3VyY2UsIGtleXNJbihzb3VyY2UpLCBvYmplY3QpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VBc3NpZ25JbjtcbiIsInZhciBkZWZpbmVQcm9wZXJ0eSA9IHJlcXVpcmUoJy4vX2RlZmluZVByb3BlcnR5Jyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGFzc2lnblZhbHVlYCBhbmQgYGFzc2lnbk1lcmdlVmFsdWVgIHdpdGhvdXRcbiAqIHZhbHVlIGNoZWNrcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gYXNzaWduLlxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gYXNzaWduLlxuICovXG5mdW5jdGlvbiBiYXNlQXNzaWduVmFsdWUob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkgPT0gJ19fcHJvdG9fXycgJiYgZGVmaW5lUHJvcGVydHkpIHtcbiAgICBkZWZpbmVQcm9wZXJ0eShvYmplY3QsIGtleSwge1xuICAgICAgJ2NvbmZpZ3VyYWJsZSc6IHRydWUsXG4gICAgICAnZW51bWVyYWJsZSc6IHRydWUsXG4gICAgICAndmFsdWUnOiB2YWx1ZSxcbiAgICAgICd3cml0YWJsZSc6IHRydWVcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBvYmplY3Rba2V5XSA9IHZhbHVlO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUFzc2lnblZhbHVlO1xuIiwidmFyIFN0YWNrID0gcmVxdWlyZSgnLi9fU3RhY2snKSxcbiAgICBhcnJheUVhY2ggPSByZXF1aXJlKCcuL19hcnJheUVhY2gnKSxcbiAgICBhc3NpZ25WYWx1ZSA9IHJlcXVpcmUoJy4vX2Fzc2lnblZhbHVlJyksXG4gICAgYmFzZUFzc2lnbiA9IHJlcXVpcmUoJy4vX2Jhc2VBc3NpZ24nKSxcbiAgICBiYXNlQXNzaWduSW4gPSByZXF1aXJlKCcuL19iYXNlQXNzaWduSW4nKSxcbiAgICBjbG9uZUJ1ZmZlciA9IHJlcXVpcmUoJy4vX2Nsb25lQnVmZmVyJyksXG4gICAgY29weUFycmF5ID0gcmVxdWlyZSgnLi9fY29weUFycmF5JyksXG4gICAgY29weVN5bWJvbHMgPSByZXF1aXJlKCcuL19jb3B5U3ltYm9scycpLFxuICAgIGNvcHlTeW1ib2xzSW4gPSByZXF1aXJlKCcuL19jb3B5U3ltYm9sc0luJyksXG4gICAgZ2V0QWxsS2V5cyA9IHJlcXVpcmUoJy4vX2dldEFsbEtleXMnKSxcbiAgICBnZXRBbGxLZXlzSW4gPSByZXF1aXJlKCcuL19nZXRBbGxLZXlzSW4nKSxcbiAgICBnZXRUYWcgPSByZXF1aXJlKCcuL19nZXRUYWcnKSxcbiAgICBpbml0Q2xvbmVBcnJheSA9IHJlcXVpcmUoJy4vX2luaXRDbG9uZUFycmF5JyksXG4gICAgaW5pdENsb25lQnlUYWcgPSByZXF1aXJlKCcuL19pbml0Q2xvbmVCeVRhZycpLFxuICAgIGluaXRDbG9uZU9iamVjdCA9IHJlcXVpcmUoJy4vX2luaXRDbG9uZU9iamVjdCcpLFxuICAgIGlzQXJyYXkgPSByZXF1aXJlKCcuL2lzQXJyYXknKSxcbiAgICBpc0J1ZmZlciA9IHJlcXVpcmUoJy4vaXNCdWZmZXInKSxcbiAgICBpc01hcCA9IHJlcXVpcmUoJy4vaXNNYXAnKSxcbiAgICBpc09iamVjdCA9IHJlcXVpcmUoJy4vaXNPYmplY3QnKSxcbiAgICBpc1NldCA9IHJlcXVpcmUoJy4vaXNTZXQnKSxcbiAgICBrZXlzID0gcmVxdWlyZSgnLi9rZXlzJyksXG4gICAga2V5c0luID0gcmVxdWlyZSgnLi9rZXlzSW4nKTtcblxuLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3IgY2xvbmluZy4gKi9cbnZhciBDTE9ORV9ERUVQX0ZMQUcgPSAxLFxuICAgIENMT05FX0ZMQVRfRkxBRyA9IDIsXG4gICAgQ0xPTkVfU1lNQk9MU19GTEFHID0gNDtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIGFyZ3NUYWcgPSAnW29iamVjdCBBcmd1bWVudHNdJyxcbiAgICBhcnJheVRhZyA9ICdbb2JqZWN0IEFycmF5XScsXG4gICAgYm9vbFRhZyA9ICdbb2JqZWN0IEJvb2xlYW5dJyxcbiAgICBkYXRlVGFnID0gJ1tvYmplY3QgRGF0ZV0nLFxuICAgIGVycm9yVGFnID0gJ1tvYmplY3QgRXJyb3JdJyxcbiAgICBmdW5jVGFnID0gJ1tvYmplY3QgRnVuY3Rpb25dJyxcbiAgICBnZW5UYWcgPSAnW29iamVjdCBHZW5lcmF0b3JGdW5jdGlvbl0nLFxuICAgIG1hcFRhZyA9ICdbb2JqZWN0IE1hcF0nLFxuICAgIG51bWJlclRhZyA9ICdbb2JqZWN0IE51bWJlcl0nLFxuICAgIG9iamVjdFRhZyA9ICdbb2JqZWN0IE9iamVjdF0nLFxuICAgIHJlZ2V4cFRhZyA9ICdbb2JqZWN0IFJlZ0V4cF0nLFxuICAgIHNldFRhZyA9ICdbb2JqZWN0IFNldF0nLFxuICAgIHN0cmluZ1RhZyA9ICdbb2JqZWN0IFN0cmluZ10nLFxuICAgIHN5bWJvbFRhZyA9ICdbb2JqZWN0IFN5bWJvbF0nLFxuICAgIHdlYWtNYXBUYWcgPSAnW29iamVjdCBXZWFrTWFwXSc7XG5cbnZhciBhcnJheUJ1ZmZlclRhZyA9ICdbb2JqZWN0IEFycmF5QnVmZmVyXScsXG4gICAgZGF0YVZpZXdUYWcgPSAnW29iamVjdCBEYXRhVmlld10nLFxuICAgIGZsb2F0MzJUYWcgPSAnW29iamVjdCBGbG9hdDMyQXJyYXldJyxcbiAgICBmbG9hdDY0VGFnID0gJ1tvYmplY3QgRmxvYXQ2NEFycmF5XScsXG4gICAgaW50OFRhZyA9ICdbb2JqZWN0IEludDhBcnJheV0nLFxuICAgIGludDE2VGFnID0gJ1tvYmplY3QgSW50MTZBcnJheV0nLFxuICAgIGludDMyVGFnID0gJ1tvYmplY3QgSW50MzJBcnJheV0nLFxuICAgIHVpbnQ4VGFnID0gJ1tvYmplY3QgVWludDhBcnJheV0nLFxuICAgIHVpbnQ4Q2xhbXBlZFRhZyA9ICdbb2JqZWN0IFVpbnQ4Q2xhbXBlZEFycmF5XScsXG4gICAgdWludDE2VGFnID0gJ1tvYmplY3QgVWludDE2QXJyYXldJyxcbiAgICB1aW50MzJUYWcgPSAnW29iamVjdCBVaW50MzJBcnJheV0nO1xuXG4vKiogVXNlZCB0byBpZGVudGlmeSBgdG9TdHJpbmdUYWdgIHZhbHVlcyBzdXBwb3J0ZWQgYnkgYF8uY2xvbmVgLiAqL1xudmFyIGNsb25lYWJsZVRhZ3MgPSB7fTtcbmNsb25lYWJsZVRhZ3NbYXJnc1RhZ10gPSBjbG9uZWFibGVUYWdzW2FycmF5VGFnXSA9XG5jbG9uZWFibGVUYWdzW2FycmF5QnVmZmVyVGFnXSA9IGNsb25lYWJsZVRhZ3NbZGF0YVZpZXdUYWddID1cbmNsb25lYWJsZVRhZ3NbYm9vbFRhZ10gPSBjbG9uZWFibGVUYWdzW2RhdGVUYWddID1cbmNsb25lYWJsZVRhZ3NbZmxvYXQzMlRhZ10gPSBjbG9uZWFibGVUYWdzW2Zsb2F0NjRUYWddID1cbmNsb25lYWJsZVRhZ3NbaW50OFRhZ10gPSBjbG9uZWFibGVUYWdzW2ludDE2VGFnXSA9XG5jbG9uZWFibGVUYWdzW2ludDMyVGFnXSA9IGNsb25lYWJsZVRhZ3NbbWFwVGFnXSA9XG5jbG9uZWFibGVUYWdzW251bWJlclRhZ10gPSBjbG9uZWFibGVUYWdzW29iamVjdFRhZ10gPVxuY2xvbmVhYmxlVGFnc1tyZWdleHBUYWddID0gY2xvbmVhYmxlVGFnc1tzZXRUYWddID1cbmNsb25lYWJsZVRhZ3Nbc3RyaW5nVGFnXSA9IGNsb25lYWJsZVRhZ3Nbc3ltYm9sVGFnXSA9XG5jbG9uZWFibGVUYWdzW3VpbnQ4VGFnXSA9IGNsb25lYWJsZVRhZ3NbdWludDhDbGFtcGVkVGFnXSA9XG5jbG9uZWFibGVUYWdzW3VpbnQxNlRhZ10gPSBjbG9uZWFibGVUYWdzW3VpbnQzMlRhZ10gPSB0cnVlO1xuY2xvbmVhYmxlVGFnc1tlcnJvclRhZ10gPSBjbG9uZWFibGVUYWdzW2Z1bmNUYWddID1cbmNsb25lYWJsZVRhZ3Nbd2Vha01hcFRhZ10gPSBmYWxzZTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jbG9uZWAgYW5kIGBfLmNsb25lRGVlcGAgd2hpY2ggdHJhY2tzXG4gKiB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2xvbmUuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuXG4gKiAgMSAtIERlZXAgY2xvbmVcbiAqICAyIC0gRmxhdHRlbiBpbmhlcml0ZWQgcHJvcGVydGllc1xuICogIDQgLSBDbG9uZSBzeW1ib2xzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjbG9uaW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IFtrZXldIFRoZSBrZXkgb2YgYHZhbHVlYC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBUaGUgcGFyZW50IG9iamVjdCBvZiBgdmFsdWVgLlxuICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBvYmplY3RzIGFuZCB0aGVpciBjbG9uZSBjb3VudGVycGFydHMuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgY2xvbmVkIHZhbHVlLlxuICovXG5mdW5jdGlvbiBiYXNlQ2xvbmUodmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGtleSwgb2JqZWN0LCBzdGFjaykge1xuICB2YXIgcmVzdWx0LFxuICAgICAgaXNEZWVwID0gYml0bWFzayAmIENMT05FX0RFRVBfRkxBRyxcbiAgICAgIGlzRmxhdCA9IGJpdG1hc2sgJiBDTE9ORV9GTEFUX0ZMQUcsXG4gICAgICBpc0Z1bGwgPSBiaXRtYXNrICYgQ0xPTkVfU1lNQk9MU19GTEFHO1xuXG4gIGlmIChjdXN0b21pemVyKSB7XG4gICAgcmVzdWx0ID0gb2JqZWN0ID8gY3VzdG9taXplcih2YWx1ZSwga2V5LCBvYmplY3QsIHN0YWNrKSA6IGN1c3RvbWl6ZXIodmFsdWUpO1xuICB9XG4gIGlmIChyZXN1bHQgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgaWYgKCFpc09iamVjdCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbiAgdmFyIGlzQXJyID0gaXNBcnJheSh2YWx1ZSk7XG4gIGlmIChpc0Fycikge1xuICAgIHJlc3VsdCA9IGluaXRDbG9uZUFycmF5KHZhbHVlKTtcbiAgICBpZiAoIWlzRGVlcCkge1xuICAgICAgcmV0dXJuIGNvcHlBcnJheSh2YWx1ZSwgcmVzdWx0KTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFyIHRhZyA9IGdldFRhZyh2YWx1ZSksXG4gICAgICAgIGlzRnVuYyA9IHRhZyA9PSBmdW5jVGFnIHx8IHRhZyA9PSBnZW5UYWc7XG5cbiAgICBpZiAoaXNCdWZmZXIodmFsdWUpKSB7XG4gICAgICByZXR1cm4gY2xvbmVCdWZmZXIodmFsdWUsIGlzRGVlcCk7XG4gICAgfVxuICAgIGlmICh0YWcgPT0gb2JqZWN0VGFnIHx8IHRhZyA9PSBhcmdzVGFnIHx8IChpc0Z1bmMgJiYgIW9iamVjdCkpIHtcbiAgICAgIHJlc3VsdCA9IChpc0ZsYXQgfHwgaXNGdW5jKSA/IHt9IDogaW5pdENsb25lT2JqZWN0KHZhbHVlKTtcbiAgICAgIGlmICghaXNEZWVwKSB7XG4gICAgICAgIHJldHVybiBpc0ZsYXRcbiAgICAgICAgICA/IGNvcHlTeW1ib2xzSW4odmFsdWUsIGJhc2VBc3NpZ25JbihyZXN1bHQsIHZhbHVlKSlcbiAgICAgICAgICA6IGNvcHlTeW1ib2xzKHZhbHVlLCBiYXNlQXNzaWduKHJlc3VsdCwgdmFsdWUpKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCFjbG9uZWFibGVUYWdzW3RhZ10pIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdCA/IHZhbHVlIDoge307XG4gICAgICB9XG4gICAgICByZXN1bHQgPSBpbml0Q2xvbmVCeVRhZyh2YWx1ZSwgdGFnLCBpc0RlZXApO1xuICAgIH1cbiAgfVxuICAvLyBDaGVjayBmb3IgY2lyY3VsYXIgcmVmZXJlbmNlcyBhbmQgcmV0dXJuIGl0cyBjb3JyZXNwb25kaW5nIGNsb25lLlxuICBzdGFjayB8fCAoc3RhY2sgPSBuZXcgU3RhY2spO1xuICB2YXIgc3RhY2tlZCA9IHN0YWNrLmdldCh2YWx1ZSk7XG4gIGlmIChzdGFja2VkKSB7XG4gICAgcmV0dXJuIHN0YWNrZWQ7XG4gIH1cbiAgc3RhY2suc2V0KHZhbHVlLCByZXN1bHQpO1xuXG4gIGlmIChpc1NldCh2YWx1ZSkpIHtcbiAgICB2YWx1ZS5mb3JFYWNoKGZ1bmN0aW9uKHN1YlZhbHVlKSB7XG4gICAgICByZXN1bHQuYWRkKGJhc2VDbG9uZShzdWJWYWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwgc3ViVmFsdWUsIHZhbHVlLCBzdGFjaykpO1xuICAgIH0pO1xuICB9IGVsc2UgaWYgKGlzTWFwKHZhbHVlKSkge1xuICAgIHZhbHVlLmZvckVhY2goZnVuY3Rpb24oc3ViVmFsdWUsIGtleSkge1xuICAgICAgcmVzdWx0LnNldChrZXksIGJhc2VDbG9uZShzdWJWYWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwga2V5LCB2YWx1ZSwgc3RhY2spKTtcbiAgICB9KTtcbiAgfVxuXG4gIHZhciBrZXlzRnVuYyA9IGlzRnVsbFxuICAgID8gKGlzRmxhdCA/IGdldEFsbEtleXNJbiA6IGdldEFsbEtleXMpXG4gICAgOiAoaXNGbGF0ID8ga2V5c0luIDoga2V5cyk7XG5cbiAgdmFyIHByb3BzID0gaXNBcnIgPyB1bmRlZmluZWQgOiBrZXlzRnVuYyh2YWx1ZSk7XG4gIGFycmF5RWFjaChwcm9wcyB8fCB2YWx1ZSwgZnVuY3Rpb24oc3ViVmFsdWUsIGtleSkge1xuICAgIGlmIChwcm9wcykge1xuICAgICAga2V5ID0gc3ViVmFsdWU7XG4gICAgICBzdWJWYWx1ZSA9IHZhbHVlW2tleV07XG4gICAgfVxuICAgIC8vIFJlY3Vyc2l2ZWx5IHBvcHVsYXRlIGNsb25lIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgYXNzaWduVmFsdWUocmVzdWx0LCBrZXksIGJhc2VDbG9uZShzdWJWYWx1ZSwgYml0bWFzaywgY3VzdG9taXplciwga2V5LCB2YWx1ZSwgc3RhY2spKTtcbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUNsb25lO1xuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9pc09iamVjdCcpO1xuXG4vKiogQnVpbHQtaW4gdmFsdWUgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RDcmVhdGUgPSBPYmplY3QuY3JlYXRlO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNyZWF0ZWAgd2l0aG91dCBzdXBwb3J0IGZvciBhc3NpZ25pbmdcbiAqIHByb3BlcnRpZXMgdG8gdGhlIGNyZWF0ZWQgb2JqZWN0LlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gcHJvdG8gVGhlIG9iamVjdCB0byBpbmhlcml0IGZyb20uXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICovXG52YXIgYmFzZUNyZWF0ZSA9IChmdW5jdGlvbigpIHtcbiAgZnVuY3Rpb24gb2JqZWN0KCkge31cbiAgcmV0dXJuIGZ1bmN0aW9uKHByb3RvKSB7XG4gICAgaWYgKCFpc09iamVjdChwcm90bykpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gICAgaWYgKG9iamVjdENyZWF0ZSkge1xuICAgICAgcmV0dXJuIG9iamVjdENyZWF0ZShwcm90byk7XG4gICAgfVxuICAgIG9iamVjdC5wcm90b3R5cGUgPSBwcm90bztcbiAgICB2YXIgcmVzdWx0ID0gbmV3IG9iamVjdDtcbiAgICBvYmplY3QucHJvdG90eXBlID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59KCkpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VDcmVhdGU7XG4iLCJ2YXIgYXJyYXlQdXNoID0gcmVxdWlyZSgnLi9fYXJyYXlQdXNoJyksXG4gICAgaXNBcnJheSA9IHJlcXVpcmUoJy4vaXNBcnJheScpO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBnZXRBbGxLZXlzYCBhbmQgYGdldEFsbEtleXNJbmAgd2hpY2ggdXNlc1xuICogYGtleXNGdW5jYCBhbmQgYHN5bWJvbHNGdW5jYCB0byBnZXQgdGhlIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgYW5kXG4gKiBzeW1ib2xzIG9mIGBvYmplY3RgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBrZXlzRnVuYyBUaGUgZnVuY3Rpb24gdG8gZ2V0IHRoZSBrZXlzIG9mIGBvYmplY3RgLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gc3ltYm9sc0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGdldCB0aGUgc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgYW5kIHN5bWJvbHMuXG4gKi9cbmZ1bmN0aW9uIGJhc2VHZXRBbGxLZXlzKG9iamVjdCwga2V5c0Z1bmMsIHN5bWJvbHNGdW5jKSB7XG4gIHZhciByZXN1bHQgPSBrZXlzRnVuYyhvYmplY3QpO1xuICByZXR1cm4gaXNBcnJheShvYmplY3QpID8gcmVzdWx0IDogYXJyYXlQdXNoKHJlc3VsdCwgc3ltYm9sc0Z1bmMob2JqZWN0KSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUdldEFsbEtleXM7XG4iLCJ2YXIgU3ltYm9sID0gcmVxdWlyZSgnLi9fU3ltYm9sJyksXG4gICAgZ2V0UmF3VGFnID0gcmVxdWlyZSgnLi9fZ2V0UmF3VGFnJyksXG4gICAgb2JqZWN0VG9TdHJpbmcgPSByZXF1aXJlKCcuL19vYmplY3RUb1N0cmluZycpO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgbnVsbFRhZyA9ICdbb2JqZWN0IE51bGxdJyxcbiAgICB1bmRlZmluZWRUYWcgPSAnW29iamVjdCBVbmRlZmluZWRdJztcblxuLyoqIEJ1aWx0LWluIHZhbHVlIHJlZmVyZW5jZXMuICovXG52YXIgc3ltVG9TdHJpbmdUYWcgPSBTeW1ib2wgPyBTeW1ib2wudG9TdHJpbmdUYWcgOiB1bmRlZmluZWQ7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGdldFRhZ2Agd2l0aG91dCBmYWxsYmFja3MgZm9yIGJ1Z2d5IGVudmlyb25tZW50cy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcXVlcnkuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBgdG9TdHJpbmdUYWdgLlxuICovXG5mdW5jdGlvbiBiYXNlR2V0VGFnKHZhbHVlKSB7XG4gIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgPyB1bmRlZmluZWRUYWcgOiBudWxsVGFnO1xuICB9XG4gIHJldHVybiAoc3ltVG9TdHJpbmdUYWcgJiYgc3ltVG9TdHJpbmdUYWcgaW4gT2JqZWN0KHZhbHVlKSlcbiAgICA/IGdldFJhd1RhZyh2YWx1ZSlcbiAgICA6IG9iamVjdFRvU3RyaW5nKHZhbHVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlR2V0VGFnO1xuIiwidmFyIGJhc2VHZXRUYWcgPSByZXF1aXJlKCcuL19iYXNlR2V0VGFnJyksXG4gICAgaXNPYmplY3RMaWtlID0gcmVxdWlyZSgnLi9pc09iamVjdExpa2UnKTtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIGFyZ3NUYWcgPSAnW29iamVjdCBBcmd1bWVudHNdJztcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc0FyZ3VtZW50c2AuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gYGFyZ3VtZW50c2Agb2JqZWN0LFxuICovXG5mdW5jdGlvbiBiYXNlSXNBcmd1bWVudHModmFsdWUpIHtcbiAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgYmFzZUdldFRhZyh2YWx1ZSkgPT0gYXJnc1RhZztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlSXNBcmd1bWVudHM7XG4iLCJ2YXIgYmFzZUlzRXF1YWxEZWVwID0gcmVxdWlyZSgnLi9fYmFzZUlzRXF1YWxEZWVwJyksXG4gICAgaXNPYmplY3RMaWtlID0gcmVxdWlyZSgnLi9pc09iamVjdExpa2UnKTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc0VxdWFsYCB3aGljaCBzdXBwb3J0cyBwYXJ0aWFsIGNvbXBhcmlzb25zXG4gKiBhbmQgdHJhY2tzIHRyYXZlcnNlZCBvYmplY3RzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy5cbiAqICAxIC0gVW5vcmRlcmVkIGNvbXBhcmlzb25cbiAqICAyIC0gUGFydGlhbCBjb21wYXJpc29uXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbc3RhY2tdIFRyYWNrcyB0cmF2ZXJzZWQgYHZhbHVlYCBhbmQgYG90aGVyYCBvYmplY3RzLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gYmFzZUlzRXF1YWwodmFsdWUsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdGFjaykge1xuICBpZiAodmFsdWUgPT09IG90aGVyKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKHZhbHVlID09IG51bGwgfHwgb3RoZXIgPT0gbnVsbCB8fCAoIWlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgIWlzT2JqZWN0TGlrZShvdGhlcikpKSB7XG4gICAgcmV0dXJuIHZhbHVlICE9PSB2YWx1ZSAmJiBvdGhlciAhPT0gb3RoZXI7XG4gIH1cbiAgcmV0dXJuIGJhc2VJc0VxdWFsRGVlcCh2YWx1ZSwgb3RoZXIsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGJhc2VJc0VxdWFsLCBzdGFjayk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUlzRXF1YWw7XG4iLCJ2YXIgU3RhY2sgPSByZXF1aXJlKCcuL19TdGFjaycpLFxuICAgIGVxdWFsQXJyYXlzID0gcmVxdWlyZSgnLi9fZXF1YWxBcnJheXMnKSxcbiAgICBlcXVhbEJ5VGFnID0gcmVxdWlyZSgnLi9fZXF1YWxCeVRhZycpLFxuICAgIGVxdWFsT2JqZWN0cyA9IHJlcXVpcmUoJy4vX2VxdWFsT2JqZWN0cycpLFxuICAgIGdldFRhZyA9IHJlcXVpcmUoJy4vX2dldFRhZycpLFxuICAgIGlzQXJyYXkgPSByZXF1aXJlKCcuL2lzQXJyYXknKSxcbiAgICBpc0J1ZmZlciA9IHJlcXVpcmUoJy4vaXNCdWZmZXInKSxcbiAgICBpc1R5cGVkQXJyYXkgPSByZXF1aXJlKCcuL2lzVHlwZWRBcnJheScpO1xuXG4vKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciB2YWx1ZSBjb21wYXJpc29ucy4gKi9cbnZhciBDT01QQVJFX1BBUlRJQUxfRkxBRyA9IDE7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBhcmdzVGFnID0gJ1tvYmplY3QgQXJndW1lbnRzXScsXG4gICAgYXJyYXlUYWcgPSAnW29iamVjdCBBcnJheV0nLFxuICAgIG9iamVjdFRhZyA9ICdbb2JqZWN0IE9iamVjdF0nO1xuXG4vKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4vKipcbiAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxgIGZvciBhcnJheXMgYW5kIG9iamVjdHMgd2hpY2ggcGVyZm9ybXNcbiAqIGRlZXAgY29tcGFyaXNvbnMgYW5kIHRyYWNrcyB0cmF2ZXJzZWQgb2JqZWN0cyBlbmFibGluZyBvYmplY3RzIHdpdGggY2lyY3VsYXJcbiAqIHJlZmVyZW5jZXMgdG8gYmUgY29tcGFyZWQuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICogQHBhcmFtIHtPYmplY3R9IG90aGVyIFRoZSBvdGhlciBvYmplY3QgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGJhc2VJc0VxdWFsYCBmb3IgbW9yZSBkZXRhaWxzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gY3VzdG9taXplciBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICogQHBhcmFtIHtPYmplY3R9IFtzdGFja10gVHJhY2tzIHRyYXZlcnNlZCBgb2JqZWN0YCBhbmQgYG90aGVyYCBvYmplY3RzLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBvYmplY3RzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGJhc2VJc0VxdWFsRGVlcChvYmplY3QsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKSB7XG4gIHZhciBvYmpJc0FyciA9IGlzQXJyYXkob2JqZWN0KSxcbiAgICAgIG90aElzQXJyID0gaXNBcnJheShvdGhlciksXG4gICAgICBvYmpUYWcgPSBvYmpJc0FyciA/IGFycmF5VGFnIDogZ2V0VGFnKG9iamVjdCksXG4gICAgICBvdGhUYWcgPSBvdGhJc0FyciA/IGFycmF5VGFnIDogZ2V0VGFnKG90aGVyKTtcblxuICBvYmpUYWcgPSBvYmpUYWcgPT0gYXJnc1RhZyA/IG9iamVjdFRhZyA6IG9ialRhZztcbiAgb3RoVGFnID0gb3RoVGFnID09IGFyZ3NUYWcgPyBvYmplY3RUYWcgOiBvdGhUYWc7XG5cbiAgdmFyIG9iaklzT2JqID0gb2JqVGFnID09IG9iamVjdFRhZyxcbiAgICAgIG90aElzT2JqID0gb3RoVGFnID09IG9iamVjdFRhZyxcbiAgICAgIGlzU2FtZVRhZyA9IG9ialRhZyA9PSBvdGhUYWc7XG5cbiAgaWYgKGlzU2FtZVRhZyAmJiBpc0J1ZmZlcihvYmplY3QpKSB7XG4gICAgaWYgKCFpc0J1ZmZlcihvdGhlcikpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgb2JqSXNBcnIgPSB0cnVlO1xuICAgIG9iaklzT2JqID0gZmFsc2U7XG4gIH1cbiAgaWYgKGlzU2FtZVRhZyAmJiAhb2JqSXNPYmopIHtcbiAgICBzdGFjayB8fCAoc3RhY2sgPSBuZXcgU3RhY2spO1xuICAgIHJldHVybiAob2JqSXNBcnIgfHwgaXNUeXBlZEFycmF5KG9iamVjdCkpXG4gICAgICA/IGVxdWFsQXJyYXlzKG9iamVjdCwgb3RoZXIsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spXG4gICAgICA6IGVxdWFsQnlUYWcob2JqZWN0LCBvdGhlciwgb2JqVGFnLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKTtcbiAgfVxuICBpZiAoIShiaXRtYXNrICYgQ09NUEFSRV9QQVJUSUFMX0ZMQUcpKSB7XG4gICAgdmFyIG9iaklzV3JhcHBlZCA9IG9iaklzT2JqICYmIGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCAnX193cmFwcGVkX18nKSxcbiAgICAgICAgb3RoSXNXcmFwcGVkID0gb3RoSXNPYmogJiYgaGFzT3duUHJvcGVydHkuY2FsbChvdGhlciwgJ19fd3JhcHBlZF9fJyk7XG5cbiAgICBpZiAob2JqSXNXcmFwcGVkIHx8IG90aElzV3JhcHBlZCkge1xuICAgICAgdmFyIG9ialVud3JhcHBlZCA9IG9iaklzV3JhcHBlZCA/IG9iamVjdC52YWx1ZSgpIDogb2JqZWN0LFxuICAgICAgICAgIG90aFVud3JhcHBlZCA9IG90aElzV3JhcHBlZCA/IG90aGVyLnZhbHVlKCkgOiBvdGhlcjtcblxuICAgICAgc3RhY2sgfHwgKHN0YWNrID0gbmV3IFN0YWNrKTtcbiAgICAgIHJldHVybiBlcXVhbEZ1bmMob2JqVW53cmFwcGVkLCBvdGhVbndyYXBwZWQsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIHN0YWNrKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFpc1NhbWVUYWcpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgc3RhY2sgfHwgKHN0YWNrID0gbmV3IFN0YWNrKTtcbiAgcmV0dXJuIGVxdWFsT2JqZWN0cyhvYmplY3QsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlSXNFcXVhbERlZXA7XG4iLCJ2YXIgZ2V0VGFnID0gcmVxdWlyZSgnLi9fZ2V0VGFnJyksXG4gICAgaXNPYmplY3RMaWtlID0gcmVxdWlyZSgnLi9pc09iamVjdExpa2UnKTtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIG1hcFRhZyA9ICdbb2JqZWN0IE1hcF0nO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzTWFwYCB3aXRob3V0IE5vZGUuanMgb3B0aW1pemF0aW9ucy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIG1hcCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBiYXNlSXNNYXAodmFsdWUpIHtcbiAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgZ2V0VGFnKHZhbHVlKSA9PSBtYXBUYWc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUlzTWFwO1xuIiwidmFyIGlzRnVuY3Rpb24gPSByZXF1aXJlKCcuL2lzRnVuY3Rpb24nKSxcbiAgICBpc01hc2tlZCA9IHJlcXVpcmUoJy4vX2lzTWFza2VkJyksXG4gICAgaXNPYmplY3QgPSByZXF1aXJlKCcuL2lzT2JqZWN0JyksXG4gICAgdG9Tb3VyY2UgPSByZXF1aXJlKCcuL190b1NvdXJjZScpO1xuXG4vKipcbiAqIFVzZWQgdG8gbWF0Y2ggYFJlZ0V4cGBcbiAqIFtzeW50YXggY2hhcmFjdGVyc10oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtcGF0dGVybnMpLlxuICovXG52YXIgcmVSZWdFeHBDaGFyID0gL1tcXFxcXiQuKis/KClbXFxde318XS9nO1xuXG4vKiogVXNlZCB0byBkZXRlY3QgaG9zdCBjb25zdHJ1Y3RvcnMgKFNhZmFyaSkuICovXG52YXIgcmVJc0hvc3RDdG9yID0gL15cXFtvYmplY3QgLis/Q29uc3RydWN0b3JcXF0kLztcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIGZ1bmNQcm90byA9IEZ1bmN0aW9uLnByb3RvdHlwZSxcbiAgICBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIHJlc29sdmUgdGhlIGRlY29tcGlsZWQgc291cmNlIG9mIGZ1bmN0aW9ucy4gKi9cbnZhciBmdW5jVG9TdHJpbmcgPSBmdW5jUHJvdG8udG9TdHJpbmc7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBpZiBhIG1ldGhvZCBpcyBuYXRpdmUuICovXG52YXIgcmVJc05hdGl2ZSA9IFJlZ0V4cCgnXicgK1xuICBmdW5jVG9TdHJpbmcuY2FsbChoYXNPd25Qcm9wZXJ0eSkucmVwbGFjZShyZVJlZ0V4cENoYXIsICdcXFxcJCYnKVxuICAucmVwbGFjZSgvaGFzT3duUHJvcGVydHl8KGZ1bmN0aW9uKS4qPyg/PVxcXFxcXCgpfCBmb3IgLis/KD89XFxcXFxcXSkvZywgJyQxLio/JykgKyAnJCdcbik7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNOYXRpdmVgIHdpdGhvdXQgYmFkIHNoaW0gY2hlY2tzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgbmF0aXZlIGZ1bmN0aW9uLFxuICogIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gYmFzZUlzTmF0aXZlKHZhbHVlKSB7XG4gIGlmICghaXNPYmplY3QodmFsdWUpIHx8IGlzTWFza2VkKHZhbHVlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICB2YXIgcGF0dGVybiA9IGlzRnVuY3Rpb24odmFsdWUpID8gcmVJc05hdGl2ZSA6IHJlSXNIb3N0Q3RvcjtcbiAgcmV0dXJuIHBhdHRlcm4udGVzdCh0b1NvdXJjZSh2YWx1ZSkpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VJc05hdGl2ZTtcbiIsInZhciBnZXRUYWcgPSByZXF1aXJlKCcuL19nZXRUYWcnKSxcbiAgICBpc09iamVjdExpa2UgPSByZXF1aXJlKCcuL2lzT2JqZWN0TGlrZScpO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgc2V0VGFnID0gJ1tvYmplY3QgU2V0XSc7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNTZXRgIHdpdGhvdXQgTm9kZS5qcyBvcHRpbWl6YXRpb25zLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgc2V0LCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGJhc2VJc1NldCh2YWx1ZSkge1xuICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJiBnZXRUYWcodmFsdWUpID09IHNldFRhZztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlSXNTZXQ7XG4iLCJ2YXIgYmFzZUdldFRhZyA9IHJlcXVpcmUoJy4vX2Jhc2VHZXRUYWcnKSxcbiAgICBpc0xlbmd0aCA9IHJlcXVpcmUoJy4vaXNMZW5ndGgnKSxcbiAgICBpc09iamVjdExpa2UgPSByZXF1aXJlKCcuL2lzT2JqZWN0TGlrZScpO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgYXJnc1RhZyA9ICdbb2JqZWN0IEFyZ3VtZW50c10nLFxuICAgIGFycmF5VGFnID0gJ1tvYmplY3QgQXJyYXldJyxcbiAgICBib29sVGFnID0gJ1tvYmplY3QgQm9vbGVhbl0nLFxuICAgIGRhdGVUYWcgPSAnW29iamVjdCBEYXRlXScsXG4gICAgZXJyb3JUYWcgPSAnW29iamVjdCBFcnJvcl0nLFxuICAgIGZ1bmNUYWcgPSAnW29iamVjdCBGdW5jdGlvbl0nLFxuICAgIG1hcFRhZyA9ICdbb2JqZWN0IE1hcF0nLFxuICAgIG51bWJlclRhZyA9ICdbb2JqZWN0IE51bWJlcl0nLFxuICAgIG9iamVjdFRhZyA9ICdbb2JqZWN0IE9iamVjdF0nLFxuICAgIHJlZ2V4cFRhZyA9ICdbb2JqZWN0IFJlZ0V4cF0nLFxuICAgIHNldFRhZyA9ICdbb2JqZWN0IFNldF0nLFxuICAgIHN0cmluZ1RhZyA9ICdbb2JqZWN0IFN0cmluZ10nLFxuICAgIHdlYWtNYXBUYWcgPSAnW29iamVjdCBXZWFrTWFwXSc7XG5cbnZhciBhcnJheUJ1ZmZlclRhZyA9ICdbb2JqZWN0IEFycmF5QnVmZmVyXScsXG4gICAgZGF0YVZpZXdUYWcgPSAnW29iamVjdCBEYXRhVmlld10nLFxuICAgIGZsb2F0MzJUYWcgPSAnW29iamVjdCBGbG9hdDMyQXJyYXldJyxcbiAgICBmbG9hdDY0VGFnID0gJ1tvYmplY3QgRmxvYXQ2NEFycmF5XScsXG4gICAgaW50OFRhZyA9ICdbb2JqZWN0IEludDhBcnJheV0nLFxuICAgIGludDE2VGFnID0gJ1tvYmplY3QgSW50MTZBcnJheV0nLFxuICAgIGludDMyVGFnID0gJ1tvYmplY3QgSW50MzJBcnJheV0nLFxuICAgIHVpbnQ4VGFnID0gJ1tvYmplY3QgVWludDhBcnJheV0nLFxuICAgIHVpbnQ4Q2xhbXBlZFRhZyA9ICdbb2JqZWN0IFVpbnQ4Q2xhbXBlZEFycmF5XScsXG4gICAgdWludDE2VGFnID0gJ1tvYmplY3QgVWludDE2QXJyYXldJyxcbiAgICB1aW50MzJUYWcgPSAnW29iamVjdCBVaW50MzJBcnJheV0nO1xuXG4vKiogVXNlZCB0byBpZGVudGlmeSBgdG9TdHJpbmdUYWdgIHZhbHVlcyBvZiB0eXBlZCBhcnJheXMuICovXG52YXIgdHlwZWRBcnJheVRhZ3MgPSB7fTtcbnR5cGVkQXJyYXlUYWdzW2Zsb2F0MzJUYWddID0gdHlwZWRBcnJheVRhZ3NbZmxvYXQ2NFRhZ10gPVxudHlwZWRBcnJheVRhZ3NbaW50OFRhZ10gPSB0eXBlZEFycmF5VGFnc1tpbnQxNlRhZ10gPVxudHlwZWRBcnJheVRhZ3NbaW50MzJUYWddID0gdHlwZWRBcnJheVRhZ3NbdWludDhUYWddID1cbnR5cGVkQXJyYXlUYWdzW3VpbnQ4Q2xhbXBlZFRhZ10gPSB0eXBlZEFycmF5VGFnc1t1aW50MTZUYWddID1cbnR5cGVkQXJyYXlUYWdzW3VpbnQzMlRhZ10gPSB0cnVlO1xudHlwZWRBcnJheVRhZ3NbYXJnc1RhZ10gPSB0eXBlZEFycmF5VGFnc1thcnJheVRhZ10gPVxudHlwZWRBcnJheVRhZ3NbYXJyYXlCdWZmZXJUYWddID0gdHlwZWRBcnJheVRhZ3NbYm9vbFRhZ10gPVxudHlwZWRBcnJheVRhZ3NbZGF0YVZpZXdUYWddID0gdHlwZWRBcnJheVRhZ3NbZGF0ZVRhZ10gPVxudHlwZWRBcnJheVRhZ3NbZXJyb3JUYWddID0gdHlwZWRBcnJheVRhZ3NbZnVuY1RhZ10gPVxudHlwZWRBcnJheVRhZ3NbbWFwVGFnXSA9IHR5cGVkQXJyYXlUYWdzW251bWJlclRhZ10gPVxudHlwZWRBcnJheVRhZ3Nbb2JqZWN0VGFnXSA9IHR5cGVkQXJyYXlUYWdzW3JlZ2V4cFRhZ10gPVxudHlwZWRBcnJheVRhZ3Nbc2V0VGFnXSA9IHR5cGVkQXJyYXlUYWdzW3N0cmluZ1RhZ10gPVxudHlwZWRBcnJheVRhZ3Nbd2Vha01hcFRhZ10gPSBmYWxzZTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc1R5cGVkQXJyYXlgIHdpdGhvdXQgTm9kZS5qcyBvcHRpbWl6YXRpb25zLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgdHlwZWQgYXJyYXksIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gYmFzZUlzVHlwZWRBcnJheSh2YWx1ZSkge1xuICByZXR1cm4gaXNPYmplY3RMaWtlKHZhbHVlKSAmJlxuICAgIGlzTGVuZ3RoKHZhbHVlLmxlbmd0aCkgJiYgISF0eXBlZEFycmF5VGFnc1tiYXNlR2V0VGFnKHZhbHVlKV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUlzVHlwZWRBcnJheTtcbiIsInZhciBpc1Byb3RvdHlwZSA9IHJlcXVpcmUoJy4vX2lzUHJvdG90eXBlJyksXG4gICAgbmF0aXZlS2V5cyA9IHJlcXVpcmUoJy4vX25hdGl2ZUtleXMnKTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5rZXlzYCB3aGljaCBkb2Vzbid0IHRyZWF0IHNwYXJzZSBhcnJheXMgYXMgZGVuc2UuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gKi9cbmZ1bmN0aW9uIGJhc2VLZXlzKG9iamVjdCkge1xuICBpZiAoIWlzUHJvdG90eXBlKG9iamVjdCkpIHtcbiAgICByZXR1cm4gbmF0aXZlS2V5cyhvYmplY3QpO1xuICB9XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgZm9yICh2YXIga2V5IGluIE9iamVjdChvYmplY3QpKSB7XG4gICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpICYmIGtleSAhPSAnY29uc3RydWN0b3InKSB7XG4gICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VLZXlzO1xuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9pc09iamVjdCcpLFxuICAgIGlzUHJvdG90eXBlID0gcmVxdWlyZSgnLi9faXNQcm90b3R5cGUnKSxcbiAgICBuYXRpdmVLZXlzSW4gPSByZXF1aXJlKCcuL19uYXRpdmVLZXlzSW4nKTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5rZXlzSW5gIHdoaWNoIGRvZXNuJ3QgdHJlYXQgc3BhcnNlIGFycmF5cyBhcyBkZW5zZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAqL1xuZnVuY3Rpb24gYmFzZUtleXNJbihvYmplY3QpIHtcbiAgaWYgKCFpc09iamVjdChvYmplY3QpKSB7XG4gICAgcmV0dXJuIG5hdGl2ZUtleXNJbihvYmplY3QpO1xuICB9XG4gIHZhciBpc1Byb3RvID0gaXNQcm90b3R5cGUob2JqZWN0KSxcbiAgICAgIHJlc3VsdCA9IFtdO1xuXG4gIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICBpZiAoIShrZXkgPT0gJ2NvbnN0cnVjdG9yJyAmJiAoaXNQcm90byB8fCAhaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkpKSkge1xuICAgICAgcmVzdWx0LnB1c2goa2V5KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlS2V5c0luO1xuIiwiLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy50aW1lc2Agd2l0aG91dCBzdXBwb3J0IGZvciBpdGVyYXRlZSBzaG9ydGhhbmRzXG4gKiBvciBtYXggYXJyYXkgbGVuZ3RoIGNoZWNrcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IG4gVGhlIG51bWJlciBvZiB0aW1lcyB0byBpbnZva2UgYGl0ZXJhdGVlYC5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHJlc3VsdHMuXG4gKi9cbmZ1bmN0aW9uIGJhc2VUaW1lcyhuLCBpdGVyYXRlZSkge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIHJlc3VsdCA9IEFycmF5KG4pO1xuXG4gIHdoaWxlICgrK2luZGV4IDwgbikge1xuICAgIHJlc3VsdFtpbmRleF0gPSBpdGVyYXRlZShpbmRleCk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlVGltZXM7XG4iLCIvKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnVuYXJ5YCB3aXRob3V0IHN1cHBvcnQgZm9yIHN0b3JpbmcgbWV0YWRhdGEuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNhcCBhcmd1bWVudHMgZm9yLlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgY2FwcGVkIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBiYXNlVW5hcnkoZnVuYykge1xuICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gZnVuYyh2YWx1ZSk7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZVVuYXJ5O1xuIiwiLyoqXG4gKiBDaGVja3MgaWYgYSBgY2FjaGVgIHZhbHVlIGZvciBga2V5YCBleGlzdHMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBjYWNoZSBUaGUgY2FjaGUgdG8gcXVlcnkuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFuIGVudHJ5IGZvciBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gY2FjaGVIYXMoY2FjaGUsIGtleSkge1xuICByZXR1cm4gY2FjaGUuaGFzKGtleSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2FjaGVIYXM7XG4iLCJ2YXIgVWludDhBcnJheSA9IHJlcXVpcmUoJy4vX1VpbnQ4QXJyYXknKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgY2xvbmUgb2YgYGFycmF5QnVmZmVyYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheUJ1ZmZlcn0gYXJyYXlCdWZmZXIgVGhlIGFycmF5IGJ1ZmZlciB0byBjbG9uZS5cbiAqIEByZXR1cm5zIHtBcnJheUJ1ZmZlcn0gUmV0dXJucyB0aGUgY2xvbmVkIGFycmF5IGJ1ZmZlci5cbiAqL1xuZnVuY3Rpb24gY2xvbmVBcnJheUJ1ZmZlcihhcnJheUJ1ZmZlcikge1xuICB2YXIgcmVzdWx0ID0gbmV3IGFycmF5QnVmZmVyLmNvbnN0cnVjdG9yKGFycmF5QnVmZmVyLmJ5dGVMZW5ndGgpO1xuICBuZXcgVWludDhBcnJheShyZXN1bHQpLnNldChuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcikpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNsb25lQXJyYXlCdWZmZXI7XG4iLCJ2YXIgcm9vdCA9IHJlcXVpcmUoJy4vX3Jvb3QnKTtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBleHBvcnRzYC4gKi9cbnZhciBmcmVlRXhwb3J0cyA9IHR5cGVvZiBleHBvcnRzID09ICdvYmplY3QnICYmIGV4cG9ydHMgJiYgIWV4cG9ydHMubm9kZVR5cGUgJiYgZXhwb3J0cztcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBtb2R1bGVgLiAqL1xudmFyIGZyZWVNb2R1bGUgPSBmcmVlRXhwb3J0cyAmJiB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblxuLyoqIERldGVjdCB0aGUgcG9wdWxhciBDb21tb25KUyBleHRlbnNpb24gYG1vZHVsZS5leHBvcnRzYC4gKi9cbnZhciBtb2R1bGVFeHBvcnRzID0gZnJlZU1vZHVsZSAmJiBmcmVlTW9kdWxlLmV4cG9ydHMgPT09IGZyZWVFeHBvcnRzO1xuXG4vKiogQnVpbHQtaW4gdmFsdWUgcmVmZXJlbmNlcy4gKi9cbnZhciBCdWZmZXIgPSBtb2R1bGVFeHBvcnRzID8gcm9vdC5CdWZmZXIgOiB1bmRlZmluZWQsXG4gICAgYWxsb2NVbnNhZmUgPSBCdWZmZXIgPyBCdWZmZXIuYWxsb2NVbnNhZmUgOiB1bmRlZmluZWQ7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNsb25lIG9mICBgYnVmZmVyYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtCdWZmZXJ9IGJ1ZmZlciBUaGUgYnVmZmVyIHRvIGNsb25lLlxuICogQHBhcmFtIHtib29sZWFufSBbaXNEZWVwXSBTcGVjaWZ5IGEgZGVlcCBjbG9uZS5cbiAqIEByZXR1cm5zIHtCdWZmZXJ9IFJldHVybnMgdGhlIGNsb25lZCBidWZmZXIuXG4gKi9cbmZ1bmN0aW9uIGNsb25lQnVmZmVyKGJ1ZmZlciwgaXNEZWVwKSB7XG4gIGlmIChpc0RlZXApIHtcbiAgICByZXR1cm4gYnVmZmVyLnNsaWNlKCk7XG4gIH1cbiAgdmFyIGxlbmd0aCA9IGJ1ZmZlci5sZW5ndGgsXG4gICAgICByZXN1bHQgPSBhbGxvY1Vuc2FmZSA/IGFsbG9jVW5zYWZlKGxlbmd0aCkgOiBuZXcgYnVmZmVyLmNvbnN0cnVjdG9yKGxlbmd0aCk7XG5cbiAgYnVmZmVyLmNvcHkocmVzdWx0KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjbG9uZUJ1ZmZlcjtcbiIsInZhciBjbG9uZUFycmF5QnVmZmVyID0gcmVxdWlyZSgnLi9fY2xvbmVBcnJheUJ1ZmZlcicpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBjbG9uZSBvZiBgZGF0YVZpZXdgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YVZpZXcgVGhlIGRhdGEgdmlldyB0byBjbG9uZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgZGF0YSB2aWV3LlxuICovXG5mdW5jdGlvbiBjbG9uZURhdGFWaWV3KGRhdGFWaWV3LCBpc0RlZXApIHtcbiAgdmFyIGJ1ZmZlciA9IGlzRGVlcCA/IGNsb25lQXJyYXlCdWZmZXIoZGF0YVZpZXcuYnVmZmVyKSA6IGRhdGFWaWV3LmJ1ZmZlcjtcbiAgcmV0dXJuIG5ldyBkYXRhVmlldy5jb25zdHJ1Y3RvcihidWZmZXIsIGRhdGFWaWV3LmJ5dGVPZmZzZXQsIGRhdGFWaWV3LmJ5dGVMZW5ndGgpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNsb25lRGF0YVZpZXc7XG4iLCIvKiogVXNlZCB0byBtYXRjaCBgUmVnRXhwYCBmbGFncyBmcm9tIHRoZWlyIGNvZXJjZWQgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUZsYWdzID0gL1xcdyokLztcblxuLyoqXG4gKiBDcmVhdGVzIGEgY2xvbmUgb2YgYHJlZ2V4cGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSByZWdleHAgVGhlIHJlZ2V4cCB0byBjbG9uZS5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCByZWdleHAuXG4gKi9cbmZ1bmN0aW9uIGNsb25lUmVnRXhwKHJlZ2V4cCkge1xuICB2YXIgcmVzdWx0ID0gbmV3IHJlZ2V4cC5jb25zdHJ1Y3RvcihyZWdleHAuc291cmNlLCByZUZsYWdzLmV4ZWMocmVnZXhwKSk7XG4gIHJlc3VsdC5sYXN0SW5kZXggPSByZWdleHAubGFzdEluZGV4O1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNsb25lUmVnRXhwO1xuIiwidmFyIFN5bWJvbCA9IHJlcXVpcmUoJy4vX1N5bWJvbCcpO1xuXG4vKiogVXNlZCB0byBjb252ZXJ0IHN5bWJvbHMgdG8gcHJpbWl0aXZlcyBhbmQgc3RyaW5ncy4gKi9cbnZhciBzeW1ib2xQcm90byA9IFN5bWJvbCA/IFN5bWJvbC5wcm90b3R5cGUgOiB1bmRlZmluZWQsXG4gICAgc3ltYm9sVmFsdWVPZiA9IHN5bWJvbFByb3RvID8gc3ltYm9sUHJvdG8udmFsdWVPZiA6IHVuZGVmaW5lZDtcblxuLyoqXG4gKiBDcmVhdGVzIGEgY2xvbmUgb2YgdGhlIGBzeW1ib2xgIG9iamVjdC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IHN5bWJvbCBUaGUgc3ltYm9sIG9iamVjdCB0byBjbG9uZS5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCBzeW1ib2wgb2JqZWN0LlxuICovXG5mdW5jdGlvbiBjbG9uZVN5bWJvbChzeW1ib2wpIHtcbiAgcmV0dXJuIHN5bWJvbFZhbHVlT2YgPyBPYmplY3Qoc3ltYm9sVmFsdWVPZi5jYWxsKHN5bWJvbCkpIDoge307XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2xvbmVTeW1ib2w7XG4iLCJ2YXIgY2xvbmVBcnJheUJ1ZmZlciA9IHJlcXVpcmUoJy4vX2Nsb25lQXJyYXlCdWZmZXInKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgY2xvbmUgb2YgYHR5cGVkQXJyYXlgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gdHlwZWRBcnJheSBUaGUgdHlwZWQgYXJyYXkgdG8gY2xvbmUuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIHR5cGVkIGFycmF5LlxuICovXG5mdW5jdGlvbiBjbG9uZVR5cGVkQXJyYXkodHlwZWRBcnJheSwgaXNEZWVwKSB7XG4gIHZhciBidWZmZXIgPSBpc0RlZXAgPyBjbG9uZUFycmF5QnVmZmVyKHR5cGVkQXJyYXkuYnVmZmVyKSA6IHR5cGVkQXJyYXkuYnVmZmVyO1xuICByZXR1cm4gbmV3IHR5cGVkQXJyYXkuY29uc3RydWN0b3IoYnVmZmVyLCB0eXBlZEFycmF5LmJ5dGVPZmZzZXQsIHR5cGVkQXJyYXkubGVuZ3RoKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjbG9uZVR5cGVkQXJyYXk7XG4iLCIvKipcbiAqIENvcGllcyB0aGUgdmFsdWVzIG9mIGBzb3VyY2VgIHRvIGBhcnJheWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IHNvdXJjZSBUaGUgYXJyYXkgdG8gY29weSB2YWx1ZXMgZnJvbS5cbiAqIEBwYXJhbSB7QXJyYXl9IFthcnJheT1bXV0gVGhlIGFycmF5IHRvIGNvcHkgdmFsdWVzIHRvLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gKi9cbmZ1bmN0aW9uIGNvcHlBcnJheShzb3VyY2UsIGFycmF5KSB7XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgbGVuZ3RoID0gc291cmNlLmxlbmd0aDtcblxuICBhcnJheSB8fCAoYXJyYXkgPSBBcnJheShsZW5ndGgpKTtcbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICBhcnJheVtpbmRleF0gPSBzb3VyY2VbaW5kZXhdO1xuICB9XG4gIHJldHVybiBhcnJheTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb3B5QXJyYXk7XG4iLCJ2YXIgYXNzaWduVmFsdWUgPSByZXF1aXJlKCcuL19hc3NpZ25WYWx1ZScpLFxuICAgIGJhc2VBc3NpZ25WYWx1ZSA9IHJlcXVpcmUoJy4vX2Jhc2VBc3NpZ25WYWx1ZScpO1xuXG4vKipcbiAqIENvcGllcyBwcm9wZXJ0aWVzIG9mIGBzb3VyY2VgIHRvIGBvYmplY3RgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3QgdG8gY29weSBwcm9wZXJ0aWVzIGZyb20uXG4gKiBAcGFyYW0ge0FycmF5fSBwcm9wcyBUaGUgcHJvcGVydHkgaWRlbnRpZmllcnMgdG8gY29weS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0PXt9XSBUaGUgb2JqZWN0IHRvIGNvcHkgcHJvcGVydGllcyB0by5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvcGllZCB2YWx1ZXMuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICovXG5mdW5jdGlvbiBjb3B5T2JqZWN0KHNvdXJjZSwgcHJvcHMsIG9iamVjdCwgY3VzdG9taXplcikge1xuICB2YXIgaXNOZXcgPSAhb2JqZWN0O1xuICBvYmplY3QgfHwgKG9iamVjdCA9IHt9KTtcblxuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IHByb3BzLmxlbmd0aDtcblxuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF07XG5cbiAgICB2YXIgbmV3VmFsdWUgPSBjdXN0b21pemVyXG4gICAgICA/IGN1c3RvbWl6ZXIob2JqZWN0W2tleV0sIHNvdXJjZVtrZXldLCBrZXksIG9iamVjdCwgc291cmNlKVxuICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAobmV3VmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgbmV3VmFsdWUgPSBzb3VyY2Vba2V5XTtcbiAgICB9XG4gICAgaWYgKGlzTmV3KSB7XG4gICAgICBiYXNlQXNzaWduVmFsdWUob2JqZWN0LCBrZXksIG5ld1ZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXNzaWduVmFsdWUob2JqZWN0LCBrZXksIG5ld1ZhbHVlKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG9iamVjdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb3B5T2JqZWN0O1xuIiwidmFyIGNvcHlPYmplY3QgPSByZXF1aXJlKCcuL19jb3B5T2JqZWN0JyksXG4gICAgZ2V0U3ltYm9scyA9IHJlcXVpcmUoJy4vX2dldFN5bWJvbHMnKTtcblxuLyoqXG4gKiBDb3BpZXMgb3duIHN5bWJvbHMgb2YgYHNvdXJjZWAgdG8gYG9iamVjdGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCB0byBjb3B5IHN5bWJvbHMgZnJvbS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0PXt9XSBUaGUgb2JqZWN0IHRvIGNvcHkgc3ltYm9scyB0by5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gKi9cbmZ1bmN0aW9uIGNvcHlTeW1ib2xzKHNvdXJjZSwgb2JqZWN0KSB7XG4gIHJldHVybiBjb3B5T2JqZWN0KHNvdXJjZSwgZ2V0U3ltYm9scyhzb3VyY2UpLCBvYmplY3QpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNvcHlTeW1ib2xzO1xuIiwidmFyIGNvcHlPYmplY3QgPSByZXF1aXJlKCcuL19jb3B5T2JqZWN0JyksXG4gICAgZ2V0U3ltYm9sc0luID0gcmVxdWlyZSgnLi9fZ2V0U3ltYm9sc0luJyk7XG5cbi8qKlxuICogQ29waWVzIG93biBhbmQgaW5oZXJpdGVkIHN5bWJvbHMgb2YgYHNvdXJjZWAgdG8gYG9iamVjdGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCB0byBjb3B5IHN5bWJvbHMgZnJvbS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0PXt9XSBUaGUgb2JqZWN0IHRvIGNvcHkgc3ltYm9scyB0by5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gKi9cbmZ1bmN0aW9uIGNvcHlTeW1ib2xzSW4oc291cmNlLCBvYmplY3QpIHtcbiAgcmV0dXJuIGNvcHlPYmplY3Qoc291cmNlLCBnZXRTeW1ib2xzSW4oc291cmNlKSwgb2JqZWN0KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb3B5U3ltYm9sc0luO1xuIiwidmFyIHJvb3QgPSByZXF1aXJlKCcuL19yb290Jyk7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBvdmVycmVhY2hpbmcgY29yZS1qcyBzaGltcy4gKi9cbnZhciBjb3JlSnNEYXRhID0gcm9vdFsnX19jb3JlLWpzX3NoYXJlZF9fJ107XG5cbm1vZHVsZS5leHBvcnRzID0gY29yZUpzRGF0YTtcbiIsInZhciBnZXROYXRpdmUgPSByZXF1aXJlKCcuL19nZXROYXRpdmUnKTtcblxudmFyIGRlZmluZVByb3BlcnR5ID0gKGZ1bmN0aW9uKCkge1xuICB0cnkge1xuICAgIHZhciBmdW5jID0gZ2V0TmF0aXZlKE9iamVjdCwgJ2RlZmluZVByb3BlcnR5Jyk7XG4gICAgZnVuYyh7fSwgJycsIHt9KTtcbiAgICByZXR1cm4gZnVuYztcbiAgfSBjYXRjaCAoZSkge31cbn0oKSk7XG5cbm1vZHVsZS5leHBvcnRzID0gZGVmaW5lUHJvcGVydHk7XG4iLCJ2YXIgU2V0Q2FjaGUgPSByZXF1aXJlKCcuL19TZXRDYWNoZScpLFxuICAgIGFycmF5U29tZSA9IHJlcXVpcmUoJy4vX2FycmF5U29tZScpLFxuICAgIGNhY2hlSGFzID0gcmVxdWlyZSgnLi9fY2FjaGVIYXMnKTtcblxuLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3IgdmFsdWUgY29tcGFyaXNvbnMuICovXG52YXIgQ09NUEFSRV9QQVJUSUFMX0ZMQUcgPSAxLFxuICAgIENPTVBBUkVfVU5PUkRFUkVEX0ZMQUcgPSAyO1xuXG4vKipcbiAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxEZWVwYCBmb3IgYXJyYXlzIHdpdGggc3VwcG9ydCBmb3JcbiAqIHBhcnRpYWwgZGVlcCBjb21wYXJpc29ucy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge0FycmF5fSBvdGhlciBUaGUgb3RoZXIgYXJyYXkgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGJhc2VJc0VxdWFsYCBmb3IgbW9yZSBkZXRhaWxzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gY3VzdG9taXplciBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICogQHBhcmFtIHtPYmplY3R9IHN0YWNrIFRyYWNrcyB0cmF2ZXJzZWQgYGFycmF5YCBhbmQgYG90aGVyYCBvYmplY3RzLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBhcnJheXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gZXF1YWxBcnJheXMoYXJyYXksIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKSB7XG4gIHZhciBpc1BhcnRpYWwgPSBiaXRtYXNrICYgQ09NUEFSRV9QQVJUSUFMX0ZMQUcsXG4gICAgICBhcnJMZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICBvdGhMZW5ndGggPSBvdGhlci5sZW5ndGg7XG5cbiAgaWYgKGFyckxlbmd0aCAhPSBvdGhMZW5ndGggJiYgIShpc1BhcnRpYWwgJiYgb3RoTGVuZ3RoID4gYXJyTGVuZ3RoKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBDaGVjayB0aGF0IGN5Y2xpYyB2YWx1ZXMgYXJlIGVxdWFsLlxuICB2YXIgYXJyU3RhY2tlZCA9IHN0YWNrLmdldChhcnJheSk7XG4gIHZhciBvdGhTdGFja2VkID0gc3RhY2suZ2V0KG90aGVyKTtcbiAgaWYgKGFyclN0YWNrZWQgJiYgb3RoU3RhY2tlZCkge1xuICAgIHJldHVybiBhcnJTdGFja2VkID09IG90aGVyICYmIG90aFN0YWNrZWQgPT0gYXJyYXk7XG4gIH1cbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICByZXN1bHQgPSB0cnVlLFxuICAgICAgc2VlbiA9IChiaXRtYXNrICYgQ09NUEFSRV9VTk9SREVSRURfRkxBRykgPyBuZXcgU2V0Q2FjaGUgOiB1bmRlZmluZWQ7XG5cbiAgc3RhY2suc2V0KGFycmF5LCBvdGhlcik7XG4gIHN0YWNrLnNldChvdGhlciwgYXJyYXkpO1xuXG4gIC8vIElnbm9yZSBub24taW5kZXggcHJvcGVydGllcy5cbiAgd2hpbGUgKCsraW5kZXggPCBhcnJMZW5ndGgpIHtcbiAgICB2YXIgYXJyVmFsdWUgPSBhcnJheVtpbmRleF0sXG4gICAgICAgIG90aFZhbHVlID0gb3RoZXJbaW5kZXhdO1xuXG4gICAgaWYgKGN1c3RvbWl6ZXIpIHtcbiAgICAgIHZhciBjb21wYXJlZCA9IGlzUGFydGlhbFxuICAgICAgICA/IGN1c3RvbWl6ZXIob3RoVmFsdWUsIGFyclZhbHVlLCBpbmRleCwgb3RoZXIsIGFycmF5LCBzdGFjaylcbiAgICAgICAgOiBjdXN0b21pemVyKGFyclZhbHVlLCBvdGhWYWx1ZSwgaW5kZXgsIGFycmF5LCBvdGhlciwgc3RhY2spO1xuICAgIH1cbiAgICBpZiAoY29tcGFyZWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGNvbXBhcmVkKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgLy8gUmVjdXJzaXZlbHkgY29tcGFyZSBhcnJheXMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICBpZiAoc2Vlbikge1xuICAgICAgaWYgKCFhcnJheVNvbWUob3RoZXIsIGZ1bmN0aW9uKG90aFZhbHVlLCBvdGhJbmRleCkge1xuICAgICAgICAgICAgaWYgKCFjYWNoZUhhcyhzZWVuLCBvdGhJbmRleCkgJiZcbiAgICAgICAgICAgICAgICAoYXJyVmFsdWUgPT09IG90aFZhbHVlIHx8IGVxdWFsRnVuYyhhcnJWYWx1ZSwgb3RoVmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIHN0YWNrKSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIHNlZW4ucHVzaChvdGhJbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSkpIHtcbiAgICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoIShcbiAgICAgICAgICBhcnJWYWx1ZSA9PT0gb3RoVmFsdWUgfHxcbiAgICAgICAgICAgIGVxdWFsRnVuYyhhcnJWYWx1ZSwgb3RoVmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIHN0YWNrKVxuICAgICAgICApKSB7XG4gICAgICByZXN1bHQgPSBmYWxzZTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICBzdGFja1snZGVsZXRlJ10oYXJyYXkpO1xuICBzdGFja1snZGVsZXRlJ10ob3RoZXIpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGVxdWFsQXJyYXlzO1xuIiwidmFyIFN5bWJvbCA9IHJlcXVpcmUoJy4vX1N5bWJvbCcpLFxuICAgIFVpbnQ4QXJyYXkgPSByZXF1aXJlKCcuL19VaW50OEFycmF5JyksXG4gICAgZXEgPSByZXF1aXJlKCcuL2VxJyksXG4gICAgZXF1YWxBcnJheXMgPSByZXF1aXJlKCcuL19lcXVhbEFycmF5cycpLFxuICAgIG1hcFRvQXJyYXkgPSByZXF1aXJlKCcuL19tYXBUb0FycmF5JyksXG4gICAgc2V0VG9BcnJheSA9IHJlcXVpcmUoJy4vX3NldFRvQXJyYXknKTtcblxuLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3IgdmFsdWUgY29tcGFyaXNvbnMuICovXG52YXIgQ09NUEFSRV9QQVJUSUFMX0ZMQUcgPSAxLFxuICAgIENPTVBBUkVfVU5PUkRFUkVEX0ZMQUcgPSAyO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgYm9vbFRhZyA9ICdbb2JqZWN0IEJvb2xlYW5dJyxcbiAgICBkYXRlVGFnID0gJ1tvYmplY3QgRGF0ZV0nLFxuICAgIGVycm9yVGFnID0gJ1tvYmplY3QgRXJyb3JdJyxcbiAgICBtYXBUYWcgPSAnW29iamVjdCBNYXBdJyxcbiAgICBudW1iZXJUYWcgPSAnW29iamVjdCBOdW1iZXJdJyxcbiAgICByZWdleHBUYWcgPSAnW29iamVjdCBSZWdFeHBdJyxcbiAgICBzZXRUYWcgPSAnW29iamVjdCBTZXRdJyxcbiAgICBzdHJpbmdUYWcgPSAnW29iamVjdCBTdHJpbmddJyxcbiAgICBzeW1ib2xUYWcgPSAnW29iamVjdCBTeW1ib2xdJztcblxudmFyIGFycmF5QnVmZmVyVGFnID0gJ1tvYmplY3QgQXJyYXlCdWZmZXJdJyxcbiAgICBkYXRhVmlld1RhZyA9ICdbb2JqZWN0IERhdGFWaWV3XSc7XG5cbi8qKiBVc2VkIHRvIGNvbnZlcnQgc3ltYm9scyB0byBwcmltaXRpdmVzIGFuZCBzdHJpbmdzLiAqL1xudmFyIHN5bWJvbFByb3RvID0gU3ltYm9sID8gU3ltYm9sLnByb3RvdHlwZSA6IHVuZGVmaW5lZCxcbiAgICBzeW1ib2xWYWx1ZU9mID0gc3ltYm9sUHJvdG8gPyBzeW1ib2xQcm90by52YWx1ZU9mIDogdW5kZWZpbmVkO1xuXG4vKipcbiAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxEZWVwYCBmb3IgY29tcGFyaW5nIG9iamVjdHMgb2ZcbiAqIHRoZSBzYW1lIGB0b1N0cmluZ1RhZ2AuXG4gKlxuICogKipOb3RlOioqIFRoaXMgZnVuY3Rpb24gb25seSBzdXBwb3J0cyBjb21wYXJpbmcgdmFsdWVzIHdpdGggdGFncyBvZlxuICogYEJvb2xlYW5gLCBgRGF0ZWAsIGBFcnJvcmAsIGBOdW1iZXJgLCBgUmVnRXhwYCwgb3IgYFN0cmluZ2AuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICogQHBhcmFtIHtPYmplY3R9IG90aGVyIFRoZSBvdGhlciBvYmplY3QgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgVGhlIGB0b1N0cmluZ1RhZ2Agb2YgdGhlIG9iamVjdHMgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLiBTZWUgYGJhc2VJc0VxdWFsYCBmb3IgbW9yZSBkZXRhaWxzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gY3VzdG9taXplciBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNvbXBhcmlzb25zLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICogQHBhcmFtIHtPYmplY3R9IHN0YWNrIFRyYWNrcyB0cmF2ZXJzZWQgYG9iamVjdGAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBlcXVhbEJ5VGFnKG9iamVjdCwgb3RoZXIsIHRhZywgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjaykge1xuICBzd2l0Y2ggKHRhZykge1xuICAgIGNhc2UgZGF0YVZpZXdUYWc6XG4gICAgICBpZiAoKG9iamVjdC5ieXRlTGVuZ3RoICE9IG90aGVyLmJ5dGVMZW5ndGgpIHx8XG4gICAgICAgICAgKG9iamVjdC5ieXRlT2Zmc2V0ICE9IG90aGVyLmJ5dGVPZmZzZXQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIG9iamVjdCA9IG9iamVjdC5idWZmZXI7XG4gICAgICBvdGhlciA9IG90aGVyLmJ1ZmZlcjtcblxuICAgIGNhc2UgYXJyYXlCdWZmZXJUYWc6XG4gICAgICBpZiAoKG9iamVjdC5ieXRlTGVuZ3RoICE9IG90aGVyLmJ5dGVMZW5ndGgpIHx8XG4gICAgICAgICAgIWVxdWFsRnVuYyhuZXcgVWludDhBcnJheShvYmplY3QpLCBuZXcgVWludDhBcnJheShvdGhlcikpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuXG4gICAgY2FzZSBib29sVGFnOlxuICAgIGNhc2UgZGF0ZVRhZzpcbiAgICBjYXNlIG51bWJlclRhZzpcbiAgICAgIC8vIENvZXJjZSBib29sZWFucyB0byBgMWAgb3IgYDBgIGFuZCBkYXRlcyB0byBtaWxsaXNlY29uZHMuXG4gICAgICAvLyBJbnZhbGlkIGRhdGVzIGFyZSBjb2VyY2VkIHRvIGBOYU5gLlxuICAgICAgcmV0dXJuIGVxKCtvYmplY3QsICtvdGhlcik7XG5cbiAgICBjYXNlIGVycm9yVGFnOlxuICAgICAgcmV0dXJuIG9iamVjdC5uYW1lID09IG90aGVyLm5hbWUgJiYgb2JqZWN0Lm1lc3NhZ2UgPT0gb3RoZXIubWVzc2FnZTtcblxuICAgIGNhc2UgcmVnZXhwVGFnOlxuICAgIGNhc2Ugc3RyaW5nVGFnOlxuICAgICAgLy8gQ29lcmNlIHJlZ2V4ZXMgdG8gc3RyaW5ncyBhbmQgdHJlYXQgc3RyaW5ncywgcHJpbWl0aXZlcyBhbmQgb2JqZWN0cyxcbiAgICAgIC8vIGFzIGVxdWFsLiBTZWUgaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXJlZ2V4cC5wcm90b3R5cGUudG9zdHJpbmdcbiAgICAgIC8vIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICByZXR1cm4gb2JqZWN0ID09IChvdGhlciArICcnKTtcblxuICAgIGNhc2UgbWFwVGFnOlxuICAgICAgdmFyIGNvbnZlcnQgPSBtYXBUb0FycmF5O1xuXG4gICAgY2FzZSBzZXRUYWc6XG4gICAgICB2YXIgaXNQYXJ0aWFsID0gYml0bWFzayAmIENPTVBBUkVfUEFSVElBTF9GTEFHO1xuICAgICAgY29udmVydCB8fCAoY29udmVydCA9IHNldFRvQXJyYXkpO1xuXG4gICAgICBpZiAob2JqZWN0LnNpemUgIT0gb3RoZXIuc2l6ZSAmJiAhaXNQYXJ0aWFsKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIC8vIEFzc3VtZSBjeWNsaWMgdmFsdWVzIGFyZSBlcXVhbC5cbiAgICAgIHZhciBzdGFja2VkID0gc3RhY2suZ2V0KG9iamVjdCk7XG4gICAgICBpZiAoc3RhY2tlZCkge1xuICAgICAgICByZXR1cm4gc3RhY2tlZCA9PSBvdGhlcjtcbiAgICAgIH1cbiAgICAgIGJpdG1hc2sgfD0gQ09NUEFSRV9VTk9SREVSRURfRkxBRztcblxuICAgICAgLy8gUmVjdXJzaXZlbHkgY29tcGFyZSBvYmplY3RzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgICBzdGFjay5zZXQob2JqZWN0LCBvdGhlcik7XG4gICAgICB2YXIgcmVzdWx0ID0gZXF1YWxBcnJheXMoY29udmVydChvYmplY3QpLCBjb252ZXJ0KG90aGVyKSwgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjayk7XG4gICAgICBzdGFja1snZGVsZXRlJ10ob2JqZWN0KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG5cbiAgICBjYXNlIHN5bWJvbFRhZzpcbiAgICAgIGlmIChzeW1ib2xWYWx1ZU9mKSB7XG4gICAgICAgIHJldHVybiBzeW1ib2xWYWx1ZU9mLmNhbGwob2JqZWN0KSA9PSBzeW1ib2xWYWx1ZU9mLmNhbGwob3RoZXIpO1xuICAgICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBlcXVhbEJ5VGFnO1xuIiwidmFyIGdldEFsbEtleXMgPSByZXF1aXJlKCcuL19nZXRBbGxLZXlzJyk7XG5cbi8qKiBVc2VkIHRvIGNvbXBvc2UgYml0bWFza3MgZm9yIHZhbHVlIGNvbXBhcmlzb25zLiAqL1xudmFyIENPTVBBUkVfUEFSVElBTF9GTEFHID0gMTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsRGVlcGAgZm9yIG9iamVjdHMgd2l0aCBzdXBwb3J0IGZvclxuICogcGFydGlhbCBkZWVwIGNvbXBhcmlzb25zLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBiYXNlSXNFcXVhbGAgZm9yIG1vcmUgZGV0YWlscy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGN1c3RvbWl6ZXIgVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGFjayBUcmFja3MgdHJhdmVyc2VkIGBvYmplY3RgIGFuZCBgb3RoZXJgIG9iamVjdHMuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gZXF1YWxPYmplY3RzKG9iamVjdCwgb3RoZXIsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spIHtcbiAgdmFyIGlzUGFydGlhbCA9IGJpdG1hc2sgJiBDT01QQVJFX1BBUlRJQUxfRkxBRyxcbiAgICAgIG9ialByb3BzID0gZ2V0QWxsS2V5cyhvYmplY3QpLFxuICAgICAgb2JqTGVuZ3RoID0gb2JqUHJvcHMubGVuZ3RoLFxuICAgICAgb3RoUHJvcHMgPSBnZXRBbGxLZXlzKG90aGVyKSxcbiAgICAgIG90aExlbmd0aCA9IG90aFByb3BzLmxlbmd0aDtcblxuICBpZiAob2JqTGVuZ3RoICE9IG90aExlbmd0aCAmJiAhaXNQYXJ0aWFsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHZhciBpbmRleCA9IG9iakxlbmd0aDtcbiAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICB2YXIga2V5ID0gb2JqUHJvcHNbaW5kZXhdO1xuICAgIGlmICghKGlzUGFydGlhbCA/IGtleSBpbiBvdGhlciA6IGhhc093blByb3BlcnR5LmNhbGwob3RoZXIsIGtleSkpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIC8vIENoZWNrIHRoYXQgY3ljbGljIHZhbHVlcyBhcmUgZXF1YWwuXG4gIHZhciBvYmpTdGFja2VkID0gc3RhY2suZ2V0KG9iamVjdCk7XG4gIHZhciBvdGhTdGFja2VkID0gc3RhY2suZ2V0KG90aGVyKTtcbiAgaWYgKG9ialN0YWNrZWQgJiYgb3RoU3RhY2tlZCkge1xuICAgIHJldHVybiBvYmpTdGFja2VkID09IG90aGVyICYmIG90aFN0YWNrZWQgPT0gb2JqZWN0O1xuICB9XG4gIHZhciByZXN1bHQgPSB0cnVlO1xuICBzdGFjay5zZXQob2JqZWN0LCBvdGhlcik7XG4gIHN0YWNrLnNldChvdGhlciwgb2JqZWN0KTtcblxuICB2YXIgc2tpcEN0b3IgPSBpc1BhcnRpYWw7XG4gIHdoaWxlICgrK2luZGV4IDwgb2JqTGVuZ3RoKSB7XG4gICAga2V5ID0gb2JqUHJvcHNbaW5kZXhdO1xuICAgIHZhciBvYmpWYWx1ZSA9IG9iamVjdFtrZXldLFxuICAgICAgICBvdGhWYWx1ZSA9IG90aGVyW2tleV07XG5cbiAgICBpZiAoY3VzdG9taXplcikge1xuICAgICAgdmFyIGNvbXBhcmVkID0gaXNQYXJ0aWFsXG4gICAgICAgID8gY3VzdG9taXplcihvdGhWYWx1ZSwgb2JqVmFsdWUsIGtleSwgb3RoZXIsIG9iamVjdCwgc3RhY2spXG4gICAgICAgIDogY3VzdG9taXplcihvYmpWYWx1ZSwgb3RoVmFsdWUsIGtleSwgb2JqZWN0LCBvdGhlciwgc3RhY2spO1xuICAgIH1cbiAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIG9iamVjdHMgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgICBpZiAoIShjb21wYXJlZCA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgPyAob2JqVmFsdWUgPT09IG90aFZhbHVlIHx8IGVxdWFsRnVuYyhvYmpWYWx1ZSwgb3RoVmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIHN0YWNrKSlcbiAgICAgICAgICA6IGNvbXBhcmVkXG4gICAgICAgICkpIHtcbiAgICAgIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHNraXBDdG9yIHx8IChza2lwQ3RvciA9IGtleSA9PSAnY29uc3RydWN0b3InKTtcbiAgfVxuICBpZiAocmVzdWx0ICYmICFza2lwQ3Rvcikge1xuICAgIHZhciBvYmpDdG9yID0gb2JqZWN0LmNvbnN0cnVjdG9yLFxuICAgICAgICBvdGhDdG9yID0gb3RoZXIuY29uc3RydWN0b3I7XG5cbiAgICAvLyBOb24gYE9iamVjdGAgb2JqZWN0IGluc3RhbmNlcyB3aXRoIGRpZmZlcmVudCBjb25zdHJ1Y3RvcnMgYXJlIG5vdCBlcXVhbC5cbiAgICBpZiAob2JqQ3RvciAhPSBvdGhDdG9yICYmXG4gICAgICAgICgnY29uc3RydWN0b3InIGluIG9iamVjdCAmJiAnY29uc3RydWN0b3InIGluIG90aGVyKSAmJlxuICAgICAgICAhKHR5cGVvZiBvYmpDdG9yID09ICdmdW5jdGlvbicgJiYgb2JqQ3RvciBpbnN0YW5jZW9mIG9iakN0b3IgJiZcbiAgICAgICAgICB0eXBlb2Ygb3RoQ3RvciA9PSAnZnVuY3Rpb24nICYmIG90aEN0b3IgaW5zdGFuY2VvZiBvdGhDdG9yKSkge1xuICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgfVxuICB9XG4gIHN0YWNrWydkZWxldGUnXShvYmplY3QpO1xuICBzdGFja1snZGVsZXRlJ10ob3RoZXIpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGVxdWFsT2JqZWN0cztcbiIsIi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZ2xvYmFsYCBmcm9tIE5vZGUuanMuICovXG52YXIgZnJlZUdsb2JhbCA9IHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsICYmIGdsb2JhbC5PYmplY3QgPT09IE9iamVjdCAmJiBnbG9iYWw7XG5cbm1vZHVsZS5leHBvcnRzID0gZnJlZUdsb2JhbDtcbiIsInZhciBiYXNlR2V0QWxsS2V5cyA9IHJlcXVpcmUoJy4vX2Jhc2VHZXRBbGxLZXlzJyksXG4gICAgZ2V0U3ltYm9scyA9IHJlcXVpcmUoJy4vX2dldFN5bWJvbHMnKSxcbiAgICBrZXlzID0gcmVxdWlyZSgnLi9rZXlzJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBhcnJheSBvZiBvd24gZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBhbmQgc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyBhbmQgc3ltYm9scy5cbiAqL1xuZnVuY3Rpb24gZ2V0QWxsS2V5cyhvYmplY3QpIHtcbiAgcmV0dXJuIGJhc2VHZXRBbGxLZXlzKG9iamVjdCwga2V5cywgZ2V0U3ltYm9scyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0QWxsS2V5cztcbiIsInZhciBiYXNlR2V0QWxsS2V5cyA9IHJlcXVpcmUoJy4vX2Jhc2VHZXRBbGxLZXlzJyksXG4gICAgZ2V0U3ltYm9sc0luID0gcmVxdWlyZSgnLi9fZ2V0U3ltYm9sc0luJyksXG4gICAga2V5c0luID0gcmVxdWlyZSgnLi9rZXlzSW4nKTtcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGFycmF5IG9mIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgYW5kXG4gKiBzeW1ib2xzIG9mIGBvYmplY3RgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIGFuZCBzeW1ib2xzLlxuICovXG5mdW5jdGlvbiBnZXRBbGxLZXlzSW4ob2JqZWN0KSB7XG4gIHJldHVybiBiYXNlR2V0QWxsS2V5cyhvYmplY3QsIGtleXNJbiwgZ2V0U3ltYm9sc0luKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBnZXRBbGxLZXlzSW47XG4iLCJ2YXIgaXNLZXlhYmxlID0gcmVxdWlyZSgnLi9faXNLZXlhYmxlJyk7XG5cbi8qKlxuICogR2V0cyB0aGUgZGF0YSBmb3IgYG1hcGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBtYXAgVGhlIG1hcCB0byBxdWVyeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIHJlZmVyZW5jZSBrZXkuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgbWFwIGRhdGEuXG4gKi9cbmZ1bmN0aW9uIGdldE1hcERhdGEobWFwLCBrZXkpIHtcbiAgdmFyIGRhdGEgPSBtYXAuX19kYXRhX187XG4gIHJldHVybiBpc0tleWFibGUoa2V5KVxuICAgID8gZGF0YVt0eXBlb2Yga2V5ID09ICdzdHJpbmcnID8gJ3N0cmluZycgOiAnaGFzaCddXG4gICAgOiBkYXRhLm1hcDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBnZXRNYXBEYXRhO1xuIiwidmFyIGJhc2VJc05hdGl2ZSA9IHJlcXVpcmUoJy4vX2Jhc2VJc05hdGl2ZScpLFxuICAgIGdldFZhbHVlID0gcmVxdWlyZSgnLi9fZ2V0VmFsdWUnKTtcblxuLyoqXG4gKiBHZXRzIHRoZSBuYXRpdmUgZnVuY3Rpb24gYXQgYGtleWAgb2YgYG9iamVjdGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgbWV0aG9kIHRvIGdldC5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBmdW5jdGlvbiBpZiBpdCdzIG5hdGl2ZSwgZWxzZSBgdW5kZWZpbmVkYC5cbiAqL1xuZnVuY3Rpb24gZ2V0TmF0aXZlKG9iamVjdCwga2V5KSB7XG4gIHZhciB2YWx1ZSA9IGdldFZhbHVlKG9iamVjdCwga2V5KTtcbiAgcmV0dXJuIGJhc2VJc05hdGl2ZSh2YWx1ZSkgPyB2YWx1ZSA6IHVuZGVmaW5lZDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBnZXROYXRpdmU7XG4iLCJ2YXIgb3ZlckFyZyA9IHJlcXVpcmUoJy4vX292ZXJBcmcnKTtcblxuLyoqIEJ1aWx0LWluIHZhbHVlIHJlZmVyZW5jZXMuICovXG52YXIgZ2V0UHJvdG90eXBlID0gb3ZlckFyZyhPYmplY3QuZ2V0UHJvdG90eXBlT2YsIE9iamVjdCk7XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0UHJvdG90eXBlO1xuIiwidmFyIFN5bWJvbCA9IHJlcXVpcmUoJy4vX1N5bWJvbCcpO1xuXG4vKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4vKipcbiAqIFVzZWQgdG8gcmVzb2x2ZSB0aGVcbiAqIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICogb2YgdmFsdWVzLlxuICovXG52YXIgbmF0aXZlT2JqZWN0VG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuLyoqIEJ1aWx0LWluIHZhbHVlIHJlZmVyZW5jZXMuICovXG52YXIgc3ltVG9TdHJpbmdUYWcgPSBTeW1ib2wgPyBTeW1ib2wudG9TdHJpbmdUYWcgOiB1bmRlZmluZWQ7XG5cbi8qKlxuICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlR2V0VGFnYCB3aGljaCBpZ25vcmVzIGBTeW1ib2wudG9TdHJpbmdUYWdgIHZhbHVlcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcXVlcnkuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSByYXcgYHRvU3RyaW5nVGFnYC5cbiAqL1xuZnVuY3Rpb24gZ2V0UmF3VGFnKHZhbHVlKSB7XG4gIHZhciBpc093biA9IGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIHN5bVRvU3RyaW5nVGFnKSxcbiAgICAgIHRhZyA9IHZhbHVlW3N5bVRvU3RyaW5nVGFnXTtcblxuICB0cnkge1xuICAgIHZhbHVlW3N5bVRvU3RyaW5nVGFnXSA9IHVuZGVmaW5lZDtcbiAgICB2YXIgdW5tYXNrZWQgPSB0cnVlO1xuICB9IGNhdGNoIChlKSB7fVxuXG4gIHZhciByZXN1bHQgPSBuYXRpdmVPYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKTtcbiAgaWYgKHVubWFza2VkKSB7XG4gICAgaWYgKGlzT3duKSB7XG4gICAgICB2YWx1ZVtzeW1Ub1N0cmluZ1RhZ10gPSB0YWc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlbGV0ZSB2YWx1ZVtzeW1Ub1N0cmluZ1RhZ107XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0UmF3VGFnO1xuIiwidmFyIGFycmF5RmlsdGVyID0gcmVxdWlyZSgnLi9fYXJyYXlGaWx0ZXInKSxcbiAgICBzdHViQXJyYXkgPSByZXF1aXJlKCcuL3N0dWJBcnJheScpO1xuXG4vKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKiogQnVpbHQtaW4gdmFsdWUgcmVmZXJlbmNlcy4gKi9cbnZhciBwcm9wZXJ0eUlzRW51bWVyYWJsZSA9IG9iamVjdFByb3RvLnByb3BlcnR5SXNFbnVtZXJhYmxlO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlR2V0U3ltYm9scyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHM7XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBzeW1ib2xzLlxuICovXG52YXIgZ2V0U3ltYm9scyA9ICFuYXRpdmVHZXRTeW1ib2xzID8gc3R1YkFycmF5IDogZnVuY3Rpb24ob2JqZWN0KSB7XG4gIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICBvYmplY3QgPSBPYmplY3Qob2JqZWN0KTtcbiAgcmV0dXJuIGFycmF5RmlsdGVyKG5hdGl2ZUdldFN5bWJvbHMob2JqZWN0KSwgZnVuY3Rpb24oc3ltYm9sKSB7XG4gICAgcmV0dXJuIHByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwob2JqZWN0LCBzeW1ib2wpO1xuICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0U3ltYm9scztcbiIsInZhciBhcnJheVB1c2ggPSByZXF1aXJlKCcuL19hcnJheVB1c2gnKSxcbiAgICBnZXRQcm90b3R5cGUgPSByZXF1aXJlKCcuL19nZXRQcm90b3R5cGUnKSxcbiAgICBnZXRTeW1ib2xzID0gcmVxdWlyZSgnLi9fZ2V0U3ltYm9scycpLFxuICAgIHN0dWJBcnJheSA9IHJlcXVpcmUoJy4vc3R1YkFycmF5Jyk7XG5cbi8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVHZXRTeW1ib2xzID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scztcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGFycmF5IG9mIHRoZSBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHN5bWJvbHMgb2YgYG9iamVjdGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2Ygc3ltYm9scy5cbiAqL1xudmFyIGdldFN5bWJvbHNJbiA9ICFuYXRpdmVHZXRTeW1ib2xzID8gc3R1YkFycmF5IDogZnVuY3Rpb24ob2JqZWN0KSB7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgd2hpbGUgKG9iamVjdCkge1xuICAgIGFycmF5UHVzaChyZXN1bHQsIGdldFN5bWJvbHMob2JqZWN0KSk7XG4gICAgb2JqZWN0ID0gZ2V0UHJvdG90eXBlKG9iamVjdCk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0U3ltYm9sc0luO1xuIiwidmFyIERhdGFWaWV3ID0gcmVxdWlyZSgnLi9fRGF0YVZpZXcnKSxcbiAgICBNYXAgPSByZXF1aXJlKCcuL19NYXAnKSxcbiAgICBQcm9taXNlID0gcmVxdWlyZSgnLi9fUHJvbWlzZScpLFxuICAgIFNldCA9IHJlcXVpcmUoJy4vX1NldCcpLFxuICAgIFdlYWtNYXAgPSByZXF1aXJlKCcuL19XZWFrTWFwJyksXG4gICAgYmFzZUdldFRhZyA9IHJlcXVpcmUoJy4vX2Jhc2VHZXRUYWcnKSxcbiAgICB0b1NvdXJjZSA9IHJlcXVpcmUoJy4vX3RvU291cmNlJyk7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBtYXBUYWcgPSAnW29iamVjdCBNYXBdJyxcbiAgICBvYmplY3RUYWcgPSAnW29iamVjdCBPYmplY3RdJyxcbiAgICBwcm9taXNlVGFnID0gJ1tvYmplY3QgUHJvbWlzZV0nLFxuICAgIHNldFRhZyA9ICdbb2JqZWN0IFNldF0nLFxuICAgIHdlYWtNYXBUYWcgPSAnW29iamVjdCBXZWFrTWFwXSc7XG5cbnZhciBkYXRhVmlld1RhZyA9ICdbb2JqZWN0IERhdGFWaWV3XSc7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBtYXBzLCBzZXRzLCBhbmQgd2Vha21hcHMuICovXG52YXIgZGF0YVZpZXdDdG9yU3RyaW5nID0gdG9Tb3VyY2UoRGF0YVZpZXcpLFxuICAgIG1hcEN0b3JTdHJpbmcgPSB0b1NvdXJjZShNYXApLFxuICAgIHByb21pc2VDdG9yU3RyaW5nID0gdG9Tb3VyY2UoUHJvbWlzZSksXG4gICAgc2V0Q3RvclN0cmluZyA9IHRvU291cmNlKFNldCksXG4gICAgd2Vha01hcEN0b3JTdHJpbmcgPSB0b1NvdXJjZShXZWFrTWFwKTtcblxuLyoqXG4gKiBHZXRzIHRoZSBgdG9TdHJpbmdUYWdgIG9mIGB2YWx1ZWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHF1ZXJ5LlxuICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgYHRvU3RyaW5nVGFnYC5cbiAqL1xudmFyIGdldFRhZyA9IGJhc2VHZXRUYWc7XG5cbi8vIEZhbGxiYWNrIGZvciBkYXRhIHZpZXdzLCBtYXBzLCBzZXRzLCBhbmQgd2VhayBtYXBzIGluIElFIDExIGFuZCBwcm9taXNlcyBpbiBOb2RlLmpzIDwgNi5cbmlmICgoRGF0YVZpZXcgJiYgZ2V0VGFnKG5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIoMSkpKSAhPSBkYXRhVmlld1RhZykgfHxcbiAgICAoTWFwICYmIGdldFRhZyhuZXcgTWFwKSAhPSBtYXBUYWcpIHx8XG4gICAgKFByb21pc2UgJiYgZ2V0VGFnKFByb21pc2UucmVzb2x2ZSgpKSAhPSBwcm9taXNlVGFnKSB8fFxuICAgIChTZXQgJiYgZ2V0VGFnKG5ldyBTZXQpICE9IHNldFRhZykgfHxcbiAgICAoV2Vha01hcCAmJiBnZXRUYWcobmV3IFdlYWtNYXApICE9IHdlYWtNYXBUYWcpKSB7XG4gIGdldFRhZyA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgdmFyIHJlc3VsdCA9IGJhc2VHZXRUYWcodmFsdWUpLFxuICAgICAgICBDdG9yID0gcmVzdWx0ID09IG9iamVjdFRhZyA/IHZhbHVlLmNvbnN0cnVjdG9yIDogdW5kZWZpbmVkLFxuICAgICAgICBjdG9yU3RyaW5nID0gQ3RvciA/IHRvU291cmNlKEN0b3IpIDogJyc7XG5cbiAgICBpZiAoY3RvclN0cmluZykge1xuICAgICAgc3dpdGNoIChjdG9yU3RyaW5nKSB7XG4gICAgICAgIGNhc2UgZGF0YVZpZXdDdG9yU3RyaW5nOiByZXR1cm4gZGF0YVZpZXdUYWc7XG4gICAgICAgIGNhc2UgbWFwQ3RvclN0cmluZzogcmV0dXJuIG1hcFRhZztcbiAgICAgICAgY2FzZSBwcm9taXNlQ3RvclN0cmluZzogcmV0dXJuIHByb21pc2VUYWc7XG4gICAgICAgIGNhc2Ugc2V0Q3RvclN0cmluZzogcmV0dXJuIHNldFRhZztcbiAgICAgICAgY2FzZSB3ZWFrTWFwQ3RvclN0cmluZzogcmV0dXJuIHdlYWtNYXBUYWc7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0VGFnO1xuIiwiLyoqXG4gKiBHZXRzIHRoZSB2YWx1ZSBhdCBga2V5YCBvZiBgb2JqZWN0YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3RdIFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBwcm9wZXJ0eSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gZ2V0VmFsdWUob2JqZWN0LCBrZXkpIHtcbiAgcmV0dXJuIG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0W2tleV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0VmFsdWU7XG4iLCJ2YXIgbmF0aXZlQ3JlYXRlID0gcmVxdWlyZSgnLi9fbmF0aXZlQ3JlYXRlJyk7XG5cbi8qKlxuICogUmVtb3ZlcyBhbGwga2V5LXZhbHVlIGVudHJpZXMgZnJvbSB0aGUgaGFzaC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgY2xlYXJcbiAqIEBtZW1iZXJPZiBIYXNoXG4gKi9cbmZ1bmN0aW9uIGhhc2hDbGVhcigpIHtcbiAgdGhpcy5fX2RhdGFfXyA9IG5hdGl2ZUNyZWF0ZSA/IG5hdGl2ZUNyZWF0ZShudWxsKSA6IHt9O1xuICB0aGlzLnNpemUgPSAwO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGhhc2hDbGVhcjtcbiIsIi8qKlxuICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIGhhc2guXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGRlbGV0ZVxuICogQG1lbWJlck9mIEhhc2hcbiAqIEBwYXJhbSB7T2JqZWN0fSBoYXNoIFRoZSBoYXNoIHRvIG1vZGlmeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gcmVtb3ZlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBoYXNoRGVsZXRlKGtleSkge1xuICB2YXIgcmVzdWx0ID0gdGhpcy5oYXMoa2V5KSAmJiBkZWxldGUgdGhpcy5fX2RhdGFfX1trZXldO1xuICB0aGlzLnNpemUgLT0gcmVzdWx0ID8gMSA6IDA7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaGFzaERlbGV0ZTtcbiIsInZhciBuYXRpdmVDcmVhdGUgPSByZXF1aXJlKCcuL19uYXRpdmVDcmVhdGUnKTtcblxuLyoqIFVzZWQgdG8gc3RhbmQtaW4gZm9yIGB1bmRlZmluZWRgIGhhc2ggdmFsdWVzLiAqL1xudmFyIEhBU0hfVU5ERUZJTkVEID0gJ19fbG9kYXNoX2hhc2hfdW5kZWZpbmVkX18nO1xuXG4vKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4vKipcbiAqIEdldHMgdGhlIGhhc2ggdmFsdWUgZm9yIGBrZXlgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBnZXRcbiAqIEBtZW1iZXJPZiBIYXNoXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBlbnRyeSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gaGFzaEdldChrZXkpIHtcbiAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICBpZiAobmF0aXZlQ3JlYXRlKSB7XG4gICAgdmFyIHJlc3VsdCA9IGRhdGFba2V5XTtcbiAgICByZXR1cm4gcmVzdWx0ID09PSBIQVNIX1VOREVGSU5FRCA/IHVuZGVmaW5lZCA6IHJlc3VsdDtcbiAgfVxuICByZXR1cm4gaGFzT3duUHJvcGVydHkuY2FsbChkYXRhLCBrZXkpID8gZGF0YVtrZXldIDogdW5kZWZpbmVkO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGhhc2hHZXQ7XG4iLCJ2YXIgbmF0aXZlQ3JlYXRlID0gcmVxdWlyZSgnLi9fbmF0aXZlQ3JlYXRlJyk7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgaGFzaCB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBoYXNcbiAqIEBtZW1iZXJPZiBIYXNoXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFuIGVudHJ5IGZvciBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gaGFzaEhhcyhrZXkpIHtcbiAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICByZXR1cm4gbmF0aXZlQ3JlYXRlID8gKGRhdGFba2V5XSAhPT0gdW5kZWZpbmVkKSA6IGhhc093blByb3BlcnR5LmNhbGwoZGF0YSwga2V5KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBoYXNoSGFzO1xuIiwidmFyIG5hdGl2ZUNyZWF0ZSA9IHJlcXVpcmUoJy4vX25hdGl2ZUNyZWF0ZScpO1xuXG4vKiogVXNlZCB0byBzdGFuZC1pbiBmb3IgYHVuZGVmaW5lZGAgaGFzaCB2YWx1ZXMuICovXG52YXIgSEFTSF9VTkRFRklORUQgPSAnX19sb2Rhc2hfaGFzaF91bmRlZmluZWRfXyc7XG5cbi8qKlxuICogU2V0cyB0aGUgaGFzaCBga2V5YCB0byBgdmFsdWVgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBzZXRcbiAqIEBtZW1iZXJPZiBIYXNoXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHNldC5cbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldC5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGhhc2ggaW5zdGFuY2UuXG4gKi9cbmZ1bmN0aW9uIGhhc2hTZXQoa2V5LCB2YWx1ZSkge1xuICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX187XG4gIHRoaXMuc2l6ZSArPSB0aGlzLmhhcyhrZXkpID8gMCA6IDE7XG4gIGRhdGFba2V5XSA9IChuYXRpdmVDcmVhdGUgJiYgdmFsdWUgPT09IHVuZGVmaW5lZCkgPyBIQVNIX1VOREVGSU5FRCA6IHZhbHVlO1xuICByZXR1cm4gdGhpcztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBoYXNoU2V0O1xuIiwiLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBJbml0aWFsaXplcyBhbiBhcnJheSBjbG9uZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGNsb25lLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAqL1xuZnVuY3Rpb24gaW5pdENsb25lQXJyYXkoYXJyYXkpIHtcbiAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgIHJlc3VsdCA9IG5ldyBhcnJheS5jb25zdHJ1Y3RvcihsZW5ndGgpO1xuXG4gIC8vIEFkZCBwcm9wZXJ0aWVzIGFzc2lnbmVkIGJ5IGBSZWdFeHAjZXhlY2AuXG4gIGlmIChsZW5ndGggJiYgdHlwZW9mIGFycmF5WzBdID09ICdzdHJpbmcnICYmIGhhc093blByb3BlcnR5LmNhbGwoYXJyYXksICdpbmRleCcpKSB7XG4gICAgcmVzdWx0LmluZGV4ID0gYXJyYXkuaW5kZXg7XG4gICAgcmVzdWx0LmlucHV0ID0gYXJyYXkuaW5wdXQ7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpbml0Q2xvbmVBcnJheTtcbiIsInZhciBjbG9uZUFycmF5QnVmZmVyID0gcmVxdWlyZSgnLi9fY2xvbmVBcnJheUJ1ZmZlcicpLFxuICAgIGNsb25lRGF0YVZpZXcgPSByZXF1aXJlKCcuL19jbG9uZURhdGFWaWV3JyksXG4gICAgY2xvbmVSZWdFeHAgPSByZXF1aXJlKCcuL19jbG9uZVJlZ0V4cCcpLFxuICAgIGNsb25lU3ltYm9sID0gcmVxdWlyZSgnLi9fY2xvbmVTeW1ib2wnKSxcbiAgICBjbG9uZVR5cGVkQXJyYXkgPSByZXF1aXJlKCcuL19jbG9uZVR5cGVkQXJyYXknKTtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIGJvb2xUYWcgPSAnW29iamVjdCBCb29sZWFuXScsXG4gICAgZGF0ZVRhZyA9ICdbb2JqZWN0IERhdGVdJyxcbiAgICBtYXBUYWcgPSAnW29iamVjdCBNYXBdJyxcbiAgICBudW1iZXJUYWcgPSAnW29iamVjdCBOdW1iZXJdJyxcbiAgICByZWdleHBUYWcgPSAnW29iamVjdCBSZWdFeHBdJyxcbiAgICBzZXRUYWcgPSAnW29iamVjdCBTZXRdJyxcbiAgICBzdHJpbmdUYWcgPSAnW29iamVjdCBTdHJpbmddJyxcbiAgICBzeW1ib2xUYWcgPSAnW29iamVjdCBTeW1ib2xdJztcblxudmFyIGFycmF5QnVmZmVyVGFnID0gJ1tvYmplY3QgQXJyYXlCdWZmZXJdJyxcbiAgICBkYXRhVmlld1RhZyA9ICdbb2JqZWN0IERhdGFWaWV3XScsXG4gICAgZmxvYXQzMlRhZyA9ICdbb2JqZWN0IEZsb2F0MzJBcnJheV0nLFxuICAgIGZsb2F0NjRUYWcgPSAnW29iamVjdCBGbG9hdDY0QXJyYXldJyxcbiAgICBpbnQ4VGFnID0gJ1tvYmplY3QgSW50OEFycmF5XScsXG4gICAgaW50MTZUYWcgPSAnW29iamVjdCBJbnQxNkFycmF5XScsXG4gICAgaW50MzJUYWcgPSAnW29iamVjdCBJbnQzMkFycmF5XScsXG4gICAgdWludDhUYWcgPSAnW29iamVjdCBVaW50OEFycmF5XScsXG4gICAgdWludDhDbGFtcGVkVGFnID0gJ1tvYmplY3QgVWludDhDbGFtcGVkQXJyYXldJyxcbiAgICB1aW50MTZUYWcgPSAnW29iamVjdCBVaW50MTZBcnJheV0nLFxuICAgIHVpbnQzMlRhZyA9ICdbb2JqZWN0IFVpbnQzMkFycmF5XSc7XG5cbi8qKlxuICogSW5pdGlhbGl6ZXMgYW4gb2JqZWN0IGNsb25lIGJhc2VkIG9uIGl0cyBgdG9TdHJpbmdUYWdgLlxuICpcbiAqICoqTm90ZToqKiBUaGlzIGZ1bmN0aW9uIG9ubHkgc3VwcG9ydHMgY2xvbmluZyB2YWx1ZXMgd2l0aCB0YWdzIG9mXG4gKiBgQm9vbGVhbmAsIGBEYXRlYCwgYEVycm9yYCwgYE1hcGAsIGBOdW1iZXJgLCBgUmVnRXhwYCwgYFNldGAsIG9yIGBTdHJpbmdgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY2xvbmUuXG4gKiBAcGFyYW0ge3N0cmluZ30gdGFnIFRoZSBgdG9TdHJpbmdUYWdgIG9mIHRoZSBvYmplY3QgdG8gY2xvbmUuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgaW5pdGlhbGl6ZWQgY2xvbmUuXG4gKi9cbmZ1bmN0aW9uIGluaXRDbG9uZUJ5VGFnKG9iamVjdCwgdGFnLCBpc0RlZXApIHtcbiAgdmFyIEN0b3IgPSBvYmplY3QuY29uc3RydWN0b3I7XG4gIHN3aXRjaCAodGFnKSB7XG4gICAgY2FzZSBhcnJheUJ1ZmZlclRhZzpcbiAgICAgIHJldHVybiBjbG9uZUFycmF5QnVmZmVyKG9iamVjdCk7XG5cbiAgICBjYXNlIGJvb2xUYWc6XG4gICAgY2FzZSBkYXRlVGFnOlxuICAgICAgcmV0dXJuIG5ldyBDdG9yKCtvYmplY3QpO1xuXG4gICAgY2FzZSBkYXRhVmlld1RhZzpcbiAgICAgIHJldHVybiBjbG9uZURhdGFWaWV3KG9iamVjdCwgaXNEZWVwKTtcblxuICAgIGNhc2UgZmxvYXQzMlRhZzogY2FzZSBmbG9hdDY0VGFnOlxuICAgIGNhc2UgaW50OFRhZzogY2FzZSBpbnQxNlRhZzogY2FzZSBpbnQzMlRhZzpcbiAgICBjYXNlIHVpbnQ4VGFnOiBjYXNlIHVpbnQ4Q2xhbXBlZFRhZzogY2FzZSB1aW50MTZUYWc6IGNhc2UgdWludDMyVGFnOlxuICAgICAgcmV0dXJuIGNsb25lVHlwZWRBcnJheShvYmplY3QsIGlzRGVlcCk7XG5cbiAgICBjYXNlIG1hcFRhZzpcbiAgICAgIHJldHVybiBuZXcgQ3RvcjtcblxuICAgIGNhc2UgbnVtYmVyVGFnOlxuICAgIGNhc2Ugc3RyaW5nVGFnOlxuICAgICAgcmV0dXJuIG5ldyBDdG9yKG9iamVjdCk7XG5cbiAgICBjYXNlIHJlZ2V4cFRhZzpcbiAgICAgIHJldHVybiBjbG9uZVJlZ0V4cChvYmplY3QpO1xuXG4gICAgY2FzZSBzZXRUYWc6XG4gICAgICByZXR1cm4gbmV3IEN0b3I7XG5cbiAgICBjYXNlIHN5bWJvbFRhZzpcbiAgICAgIHJldHVybiBjbG9uZVN5bWJvbChvYmplY3QpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaW5pdENsb25lQnlUYWc7XG4iLCJ2YXIgYmFzZUNyZWF0ZSA9IHJlcXVpcmUoJy4vX2Jhc2VDcmVhdGUnKSxcbiAgICBnZXRQcm90b3R5cGUgPSByZXF1aXJlKCcuL19nZXRQcm90b3R5cGUnKSxcbiAgICBpc1Byb3RvdHlwZSA9IHJlcXVpcmUoJy4vX2lzUHJvdG90eXBlJyk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZXMgYW4gb2JqZWN0IGNsb25lLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY2xvbmUuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAqL1xuZnVuY3Rpb24gaW5pdENsb25lT2JqZWN0KG9iamVjdCkge1xuICByZXR1cm4gKHR5cGVvZiBvYmplY3QuY29uc3RydWN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNQcm90b3R5cGUob2JqZWN0KSlcbiAgICA/IGJhc2VDcmVhdGUoZ2V0UHJvdG90eXBlKG9iamVjdCkpXG4gICAgOiB7fTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpbml0Q2xvbmVPYmplY3Q7XG4iLCIvKiogVXNlZCBhcyByZWZlcmVuY2VzIGZvciB2YXJpb3VzIGBOdW1iZXJgIGNvbnN0YW50cy4gKi9cbnZhciBNQVhfU0FGRV9JTlRFR0VSID0gOTAwNzE5OTI1NDc0MDk5MTtcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IHVuc2lnbmVkIGludGVnZXIgdmFsdWVzLiAqL1xudmFyIHJlSXNVaW50ID0gL14oPzowfFsxLTldXFxkKikkLztcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHZhbGlkIGFycmF5LWxpa2UgaW5kZXguXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9TUFYX1NBRkVfSU5URUdFUl0gVGhlIHVwcGVyIGJvdW5kcyBvZiBhIHZhbGlkIGluZGV4LlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBpbmRleCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBpc0luZGV4KHZhbHVlLCBsZW5ndGgpIHtcbiAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gIGxlbmd0aCA9IGxlbmd0aCA9PSBudWxsID8gTUFYX1NBRkVfSU5URUdFUiA6IGxlbmd0aDtcblxuICByZXR1cm4gISFsZW5ndGggJiZcbiAgICAodHlwZSA9PSAnbnVtYmVyJyB8fFxuICAgICAgKHR5cGUgIT0gJ3N5bWJvbCcgJiYgcmVJc1VpbnQudGVzdCh2YWx1ZSkpKSAmJlxuICAgICAgICAodmFsdWUgPiAtMSAmJiB2YWx1ZSAlIDEgPT0gMCAmJiB2YWx1ZSA8IGxlbmd0aCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNJbmRleDtcbiIsIi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUgZm9yIHVzZSBhcyB1bmlxdWUgb2JqZWN0IGtleS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBzdWl0YWJsZSwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBpc0tleWFibGUodmFsdWUpIHtcbiAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gIHJldHVybiAodHlwZSA9PSAnc3RyaW5nJyB8fCB0eXBlID09ICdudW1iZXInIHx8IHR5cGUgPT0gJ3N5bWJvbCcgfHwgdHlwZSA9PSAnYm9vbGVhbicpXG4gICAgPyAodmFsdWUgIT09ICdfX3Byb3RvX18nKVxuICAgIDogKHZhbHVlID09PSBudWxsKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc0tleWFibGU7XG4iLCJ2YXIgY29yZUpzRGF0YSA9IHJlcXVpcmUoJy4vX2NvcmVKc0RhdGEnKTtcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IG1ldGhvZHMgbWFzcXVlcmFkaW5nIGFzIG5hdGl2ZS4gKi9cbnZhciBtYXNrU3JjS2V5ID0gKGZ1bmN0aW9uKCkge1xuICB2YXIgdWlkID0gL1teLl0rJC8uZXhlYyhjb3JlSnNEYXRhICYmIGNvcmVKc0RhdGEua2V5cyAmJiBjb3JlSnNEYXRhLmtleXMuSUVfUFJPVE8gfHwgJycpO1xuICByZXR1cm4gdWlkID8gKCdTeW1ib2woc3JjKV8xLicgKyB1aWQpIDogJyc7XG59KCkpO1xuXG4vKipcbiAqIENoZWNrcyBpZiBgZnVuY2AgaGFzIGl0cyBzb3VyY2UgbWFza2VkLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgZnVuY2AgaXMgbWFza2VkLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGlzTWFza2VkKGZ1bmMpIHtcbiAgcmV0dXJuICEhbWFza1NyY0tleSAmJiAobWFza1NyY0tleSBpbiBmdW5jKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc01hc2tlZDtcbiIsIi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgbGlrZWx5IGEgcHJvdG90eXBlIG9iamVjdC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHByb3RvdHlwZSwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBpc1Byb3RvdHlwZSh2YWx1ZSkge1xuICB2YXIgQ3RvciA9IHZhbHVlICYmIHZhbHVlLmNvbnN0cnVjdG9yLFxuICAgICAgcHJvdG8gPSAodHlwZW9mIEN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiBDdG9yLnByb3RvdHlwZSkgfHwgb2JqZWN0UHJvdG87XG5cbiAgcmV0dXJuIHZhbHVlID09PSBwcm90bztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc1Byb3RvdHlwZTtcbiIsIi8qKlxuICogUmVtb3ZlcyBhbGwga2V5LXZhbHVlIGVudHJpZXMgZnJvbSB0aGUgbGlzdCBjYWNoZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgY2xlYXJcbiAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAqL1xuZnVuY3Rpb24gbGlzdENhY2hlQ2xlYXIoKSB7XG4gIHRoaXMuX19kYXRhX18gPSBbXTtcbiAgdGhpcy5zaXplID0gMDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBsaXN0Q2FjaGVDbGVhcjtcbiIsInZhciBhc3NvY0luZGV4T2YgPSByZXF1aXJlKCcuL19hc3NvY0luZGV4T2YnKTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIGFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGU7XG5cbi8qKiBCdWlsdC1pbiB2YWx1ZSByZWZlcmVuY2VzLiAqL1xudmFyIHNwbGljZSA9IGFycmF5UHJvdG8uc3BsaWNlO1xuXG4vKipcbiAqIFJlbW92ZXMgYGtleWAgYW5kIGl0cyB2YWx1ZSBmcm9tIHRoZSBsaXN0IGNhY2hlLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBkZWxldGVcbiAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gcmVtb3ZlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBsaXN0Q2FjaGVEZWxldGUoa2V5KSB7XG4gIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyxcbiAgICAgIGluZGV4ID0gYXNzb2NJbmRleE9mKGRhdGEsIGtleSk7XG5cbiAgaWYgKGluZGV4IDwgMCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICB2YXIgbGFzdEluZGV4ID0gZGF0YS5sZW5ndGggLSAxO1xuICBpZiAoaW5kZXggPT0gbGFzdEluZGV4KSB7XG4gICAgZGF0YS5wb3AoKTtcbiAgfSBlbHNlIHtcbiAgICBzcGxpY2UuY2FsbChkYXRhLCBpbmRleCwgMSk7XG4gIH1cbiAgLS10aGlzLnNpemU7XG4gIHJldHVybiB0cnVlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGxpc3RDYWNoZURlbGV0ZTtcbiIsInZhciBhc3NvY0luZGV4T2YgPSByZXF1aXJlKCcuL19hc3NvY0luZGV4T2YnKTtcblxuLyoqXG4gKiBHZXRzIHRoZSBsaXN0IGNhY2hlIHZhbHVlIGZvciBga2V5YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgZ2V0XG4gKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBlbnRyeSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gbGlzdENhY2hlR2V0KGtleSkge1xuICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX18sXG4gICAgICBpbmRleCA9IGFzc29jSW5kZXhPZihkYXRhLCBrZXkpO1xuXG4gIHJldHVybiBpbmRleCA8IDAgPyB1bmRlZmluZWQgOiBkYXRhW2luZGV4XVsxXTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBsaXN0Q2FjaGVHZXQ7XG4iLCJ2YXIgYXNzb2NJbmRleE9mID0gcmVxdWlyZSgnLi9fYXNzb2NJbmRleE9mJyk7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgbGlzdCBjYWNoZSB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBoYXNcbiAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgZW50cnkgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW4gZW50cnkgZm9yIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBsaXN0Q2FjaGVIYXMoa2V5KSB7XG4gIHJldHVybiBhc3NvY0luZGV4T2YodGhpcy5fX2RhdGFfXywga2V5KSA+IC0xO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGxpc3RDYWNoZUhhcztcbiIsInZhciBhc3NvY0luZGV4T2YgPSByZXF1aXJlKCcuL19hc3NvY0luZGV4T2YnKTtcblxuLyoqXG4gKiBTZXRzIHRoZSBsaXN0IGNhY2hlIGBrZXlgIHRvIGB2YWx1ZWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIHNldFxuICogQG1lbWJlck9mIExpc3RDYWNoZVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBsaXN0IGNhY2hlIGluc3RhbmNlLlxuICovXG5mdW5jdGlvbiBsaXN0Q2FjaGVTZXQoa2V5LCB2YWx1ZSkge1xuICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX18sXG4gICAgICBpbmRleCA9IGFzc29jSW5kZXhPZihkYXRhLCBrZXkpO1xuXG4gIGlmIChpbmRleCA8IDApIHtcbiAgICArK3RoaXMuc2l6ZTtcbiAgICBkYXRhLnB1c2goW2tleSwgdmFsdWVdKTtcbiAgfSBlbHNlIHtcbiAgICBkYXRhW2luZGV4XVsxXSA9IHZhbHVlO1xuICB9XG4gIHJldHVybiB0aGlzO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGxpc3RDYWNoZVNldDtcbiIsInZhciBIYXNoID0gcmVxdWlyZSgnLi9fSGFzaCcpLFxuICAgIExpc3RDYWNoZSA9IHJlcXVpcmUoJy4vX0xpc3RDYWNoZScpLFxuICAgIE1hcCA9IHJlcXVpcmUoJy4vX01hcCcpO1xuXG4vKipcbiAqIFJlbW92ZXMgYWxsIGtleS12YWx1ZSBlbnRyaWVzIGZyb20gdGhlIG1hcC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgY2xlYXJcbiAqIEBtZW1iZXJPZiBNYXBDYWNoZVxuICovXG5mdW5jdGlvbiBtYXBDYWNoZUNsZWFyKCkge1xuICB0aGlzLnNpemUgPSAwO1xuICB0aGlzLl9fZGF0YV9fID0ge1xuICAgICdoYXNoJzogbmV3IEhhc2gsXG4gICAgJ21hcCc6IG5ldyAoTWFwIHx8IExpc3RDYWNoZSksXG4gICAgJ3N0cmluZyc6IG5ldyBIYXNoXG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbWFwQ2FjaGVDbGVhcjtcbiIsInZhciBnZXRNYXBEYXRhID0gcmVxdWlyZSgnLi9fZ2V0TWFwRGF0YScpO1xuXG4vKipcbiAqIFJlbW92ZXMgYGtleWAgYW5kIGl0cyB2YWx1ZSBmcm9tIHRoZSBtYXAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGRlbGV0ZVxuICogQG1lbWJlck9mIE1hcENhY2hlXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZW50cnkgd2FzIHJlbW92ZWQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gbWFwQ2FjaGVEZWxldGUoa2V5KSB7XG4gIHZhciByZXN1bHQgPSBnZXRNYXBEYXRhKHRoaXMsIGtleSlbJ2RlbGV0ZSddKGtleSk7XG4gIHRoaXMuc2l6ZSAtPSByZXN1bHQgPyAxIDogMDtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBtYXBDYWNoZURlbGV0ZTtcbiIsInZhciBnZXRNYXBEYXRhID0gcmVxdWlyZSgnLi9fZ2V0TWFwRGF0YScpO1xuXG4vKipcbiAqIEdldHMgdGhlIG1hcCB2YWx1ZSBmb3IgYGtleWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGdldFxuICogQG1lbWJlck9mIE1hcENhY2hlXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBlbnRyeSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gbWFwQ2FjaGVHZXQoa2V5KSB7XG4gIHJldHVybiBnZXRNYXBEYXRhKHRoaXMsIGtleSkuZ2V0KGtleSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbWFwQ2FjaGVHZXQ7XG4iLCJ2YXIgZ2V0TWFwRGF0YSA9IHJlcXVpcmUoJy4vX2dldE1hcERhdGEnKTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYSBtYXAgdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgaGFzXG4gKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgZW50cnkgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW4gZW50cnkgZm9yIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBtYXBDYWNoZUhhcyhrZXkpIHtcbiAgcmV0dXJuIGdldE1hcERhdGEodGhpcywga2V5KS5oYXMoa2V5KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBtYXBDYWNoZUhhcztcbiIsInZhciBnZXRNYXBEYXRhID0gcmVxdWlyZSgnLi9fZ2V0TWFwRGF0YScpO1xuXG4vKipcbiAqIFNldHMgdGhlIG1hcCBga2V5YCB0byBgdmFsdWVgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBzZXRcbiAqIEBtZW1iZXJPZiBNYXBDYWNoZVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBtYXAgY2FjaGUgaW5zdGFuY2UuXG4gKi9cbmZ1bmN0aW9uIG1hcENhY2hlU2V0KGtleSwgdmFsdWUpIHtcbiAgdmFyIGRhdGEgPSBnZXRNYXBEYXRhKHRoaXMsIGtleSksXG4gICAgICBzaXplID0gZGF0YS5zaXplO1xuXG4gIGRhdGEuc2V0KGtleSwgdmFsdWUpO1xuICB0aGlzLnNpemUgKz0gZGF0YS5zaXplID09IHNpemUgPyAwIDogMTtcbiAgcmV0dXJuIHRoaXM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbWFwQ2FjaGVTZXQ7XG4iLCIvKipcbiAqIENvbnZlcnRzIGBtYXBgIHRvIGl0cyBrZXktdmFsdWUgcGFpcnMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBtYXAgVGhlIG1hcCB0byBjb252ZXJ0LlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBrZXktdmFsdWUgcGFpcnMuXG4gKi9cbmZ1bmN0aW9uIG1hcFRvQXJyYXkobWFwKSB7XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgcmVzdWx0ID0gQXJyYXkobWFwLnNpemUpO1xuXG4gIG1hcC5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHtcbiAgICByZXN1bHRbKytpbmRleF0gPSBba2V5LCB2YWx1ZV07XG4gIH0pO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG1hcFRvQXJyYXk7XG4iLCJ2YXIgZ2V0TmF0aXZlID0gcmVxdWlyZSgnLi9fZ2V0TmF0aXZlJyk7XG5cbi8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHRoYXQgYXJlIHZlcmlmaWVkIHRvIGJlIG5hdGl2ZS4gKi9cbnZhciBuYXRpdmVDcmVhdGUgPSBnZXROYXRpdmUoT2JqZWN0LCAnY3JlYXRlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gbmF0aXZlQ3JlYXRlO1xuIiwidmFyIG92ZXJBcmcgPSByZXF1aXJlKCcuL19vdmVyQXJnJyk7XG5cbi8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVLZXlzID0gb3ZlckFyZyhPYmplY3Qua2V5cywgT2JqZWN0KTtcblxubW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVLZXlzO1xuIiwiLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGxpa2VcbiAqIFtgT2JqZWN0LmtleXNgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3Qua2V5cylcbiAqIGV4Y2VwdCB0aGF0IGl0IGluY2x1ZGVzIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnRpZXMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gKi9cbmZ1bmN0aW9uIG5hdGl2ZUtleXNJbihvYmplY3QpIHtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICBpZiAob2JqZWN0ICE9IG51bGwpIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gT2JqZWN0KG9iamVjdCkpIHtcbiAgICAgIHJlc3VsdC5wdXNoKGtleSk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbmF0aXZlS2V5c0luO1xuIiwidmFyIGZyZWVHbG9iYWwgPSByZXF1aXJlKCcuL19mcmVlR2xvYmFsJyk7XG5cbi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG52YXIgZnJlZUV4cG9ydHMgPSB0eXBlb2YgZXhwb3J0cyA9PSAnb2JqZWN0JyAmJiBleHBvcnRzICYmICFleHBvcnRzLm5vZGVUeXBlICYmIGV4cG9ydHM7XG5cbi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbnZhciBmcmVlTW9kdWxlID0gZnJlZUV4cG9ydHMgJiYgdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbi8qKiBEZXRlY3QgdGhlIHBvcHVsYXIgQ29tbW9uSlMgZXh0ZW5zaW9uIGBtb2R1bGUuZXhwb3J0c2AuICovXG52YXIgbW9kdWxlRXhwb3J0cyA9IGZyZWVNb2R1bGUgJiYgZnJlZU1vZHVsZS5leHBvcnRzID09PSBmcmVlRXhwb3J0cztcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBwcm9jZXNzYCBmcm9tIE5vZGUuanMuICovXG52YXIgZnJlZVByb2Nlc3MgPSBtb2R1bGVFeHBvcnRzICYmIGZyZWVHbG9iYWwucHJvY2VzcztcblxuLyoqIFVzZWQgdG8gYWNjZXNzIGZhc3RlciBOb2RlLmpzIGhlbHBlcnMuICovXG52YXIgbm9kZVV0aWwgPSAoZnVuY3Rpb24oKSB7XG4gIHRyeSB7XG4gICAgLy8gVXNlIGB1dGlsLnR5cGVzYCBmb3IgTm9kZS5qcyAxMCsuXG4gICAgdmFyIHR5cGVzID0gZnJlZU1vZHVsZSAmJiBmcmVlTW9kdWxlLnJlcXVpcmUgJiYgZnJlZU1vZHVsZS5yZXF1aXJlKCd1dGlsJykudHlwZXM7XG5cbiAgICBpZiAodHlwZXMpIHtcbiAgICAgIHJldHVybiB0eXBlcztcbiAgICB9XG5cbiAgICAvLyBMZWdhY3kgYHByb2Nlc3MuYmluZGluZygndXRpbCcpYCBmb3IgTm9kZS5qcyA8IDEwLlxuICAgIHJldHVybiBmcmVlUHJvY2VzcyAmJiBmcmVlUHJvY2Vzcy5iaW5kaW5nICYmIGZyZWVQcm9jZXNzLmJpbmRpbmcoJ3V0aWwnKTtcbiAgfSBjYXRjaCAoZSkge31cbn0oKSk7XG5cbm1vZHVsZS5leHBvcnRzID0gbm9kZVV0aWw7XG4iLCIvKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKipcbiAqIFVzZWQgdG8gcmVzb2x2ZSB0aGVcbiAqIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICogb2YgdmFsdWVzLlxuICovXG52YXIgbmF0aXZlT2JqZWN0VG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuLyoqXG4gKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgc3RyaW5nIHVzaW5nIGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29udmVydC5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGNvbnZlcnRlZCBzdHJpbmcuXG4gKi9cbmZ1bmN0aW9uIG9iamVjdFRvU3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiBuYXRpdmVPYmplY3RUb1N0cmluZy5jYWxsKHZhbHVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBvYmplY3RUb1N0cmluZztcbiIsIi8qKlxuICogQ3JlYXRlcyBhIHVuYXJ5IGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCBpdHMgYXJndW1lbnQgdHJhbnNmb3JtZWQuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHdyYXAuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSB0cmFuc2Zvcm0gVGhlIGFyZ3VtZW50IHRyYW5zZm9ybS5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBvdmVyQXJnKGZ1bmMsIHRyYW5zZm9ybSkge1xuICByZXR1cm4gZnVuY3Rpb24oYXJnKSB7XG4gICAgcmV0dXJuIGZ1bmModHJhbnNmb3JtKGFyZykpO1xuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG92ZXJBcmc7XG4iLCJ2YXIgZnJlZUdsb2JhbCA9IHJlcXVpcmUoJy4vX2ZyZWVHbG9iYWwnKTtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBzZWxmYC4gKi9cbnZhciBmcmVlU2VsZiA9IHR5cGVvZiBzZWxmID09ICdvYmplY3QnICYmIHNlbGYgJiYgc2VsZi5PYmplY3QgPT09IE9iamVjdCAmJiBzZWxmO1xuXG4vKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbnZhciByb290ID0gZnJlZUdsb2JhbCB8fCBmcmVlU2VsZiB8fCBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJvb3Q7XG4iLCIvKiogVXNlZCB0byBzdGFuZC1pbiBmb3IgYHVuZGVmaW5lZGAgaGFzaCB2YWx1ZXMuICovXG52YXIgSEFTSF9VTkRFRklORUQgPSAnX19sb2Rhc2hfaGFzaF91bmRlZmluZWRfXyc7XG5cbi8qKlxuICogQWRkcyBgdmFsdWVgIHRvIHRoZSBhcnJheSBjYWNoZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgYWRkXG4gKiBAbWVtYmVyT2YgU2V0Q2FjaGVcbiAqIEBhbGlhcyBwdXNoXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjYWNoZS5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNhY2hlIGluc3RhbmNlLlxuICovXG5mdW5jdGlvbiBzZXRDYWNoZUFkZCh2YWx1ZSkge1xuICB0aGlzLl9fZGF0YV9fLnNldCh2YWx1ZSwgSEFTSF9VTkRFRklORUQpO1xuICByZXR1cm4gdGhpcztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzZXRDYWNoZUFkZDtcbiIsIi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgaW4gdGhlIGFycmF5IGNhY2hlLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBoYXNcbiAqIEBtZW1iZXJPZiBTZXRDYWNoZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2VhcmNoIGZvci5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgZm91bmQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gc2V0Q2FjaGVIYXModmFsdWUpIHtcbiAgcmV0dXJuIHRoaXMuX19kYXRhX18uaGFzKHZhbHVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzZXRDYWNoZUhhcztcbiIsIi8qKlxuICogQ29udmVydHMgYHNldGAgdG8gYW4gYXJyYXkgb2YgaXRzIHZhbHVlcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IHNldCBUaGUgc2V0IHRvIGNvbnZlcnQuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHZhbHVlcy5cbiAqL1xuZnVuY3Rpb24gc2V0VG9BcnJheShzZXQpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICByZXN1bHQgPSBBcnJheShzZXQuc2l6ZSk7XG5cbiAgc2V0LmZvckVhY2goZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXN1bHRbKytpbmRleF0gPSB2YWx1ZTtcbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc2V0VG9BcnJheTtcbiIsInZhciBMaXN0Q2FjaGUgPSByZXF1aXJlKCcuL19MaXN0Q2FjaGUnKTtcblxuLyoqXG4gKiBSZW1vdmVzIGFsbCBrZXktdmFsdWUgZW50cmllcyBmcm9tIHRoZSBzdGFjay5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgY2xlYXJcbiAqIEBtZW1iZXJPZiBTdGFja1xuICovXG5mdW5jdGlvbiBzdGFja0NsZWFyKCkge1xuICB0aGlzLl9fZGF0YV9fID0gbmV3IExpc3RDYWNoZTtcbiAgdGhpcy5zaXplID0gMDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzdGFja0NsZWFyO1xuIiwiLyoqXG4gKiBSZW1vdmVzIGBrZXlgIGFuZCBpdHMgdmFsdWUgZnJvbSB0aGUgc3RhY2suXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGRlbGV0ZVxuICogQG1lbWJlck9mIFN0YWNrXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZW50cnkgd2FzIHJlbW92ZWQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gc3RhY2tEZWxldGUoa2V5KSB7XG4gIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyxcbiAgICAgIHJlc3VsdCA9IGRhdGFbJ2RlbGV0ZSddKGtleSk7XG5cbiAgdGhpcy5zaXplID0gZGF0YS5zaXplO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHN0YWNrRGVsZXRlO1xuIiwiLyoqXG4gKiBHZXRzIHRoZSBzdGFjayB2YWx1ZSBmb3IgYGtleWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGdldFxuICogQG1lbWJlck9mIFN0YWNrXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBlbnRyeSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gc3RhY2tHZXQoa2V5KSB7XG4gIHJldHVybiB0aGlzLl9fZGF0YV9fLmdldChrZXkpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHN0YWNrR2V0O1xuIiwiLyoqXG4gKiBDaGVja3MgaWYgYSBzdGFjayB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBoYXNcbiAqIEBtZW1iZXJPZiBTdGFja1xuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIHN0YWNrSGFzKGtleSkge1xuICByZXR1cm4gdGhpcy5fX2RhdGFfXy5oYXMoa2V5KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzdGFja0hhcztcbiIsInZhciBMaXN0Q2FjaGUgPSByZXF1aXJlKCcuL19MaXN0Q2FjaGUnKSxcbiAgICBNYXAgPSByZXF1aXJlKCcuL19NYXAnKSxcbiAgICBNYXBDYWNoZSA9IHJlcXVpcmUoJy4vX01hcENhY2hlJyk7XG5cbi8qKiBVc2VkIGFzIHRoZSBzaXplIHRvIGVuYWJsZSBsYXJnZSBhcnJheSBvcHRpbWl6YXRpb25zLiAqL1xudmFyIExBUkdFX0FSUkFZX1NJWkUgPSAyMDA7XG5cbi8qKlxuICogU2V0cyB0aGUgc3RhY2sgYGtleWAgdG8gYHZhbHVlYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgc2V0XG4gKiBAbWVtYmVyT2YgU3RhY2tcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gc2V0LlxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgc3RhY2sgY2FjaGUgaW5zdGFuY2UuXG4gKi9cbmZ1bmN0aW9uIHN0YWNrU2V0KGtleSwgdmFsdWUpIHtcbiAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICBpZiAoZGF0YSBpbnN0YW5jZW9mIExpc3RDYWNoZSkge1xuICAgIHZhciBwYWlycyA9IGRhdGEuX19kYXRhX187XG4gICAgaWYgKCFNYXAgfHwgKHBhaXJzLmxlbmd0aCA8IExBUkdFX0FSUkFZX1NJWkUgLSAxKSkge1xuICAgICAgcGFpcnMucHVzaChba2V5LCB2YWx1ZV0pO1xuICAgICAgdGhpcy5zaXplID0gKytkYXRhLnNpemU7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgZGF0YSA9IHRoaXMuX19kYXRhX18gPSBuZXcgTWFwQ2FjaGUocGFpcnMpO1xuICB9XG4gIGRhdGEuc2V0KGtleSwgdmFsdWUpO1xuICB0aGlzLnNpemUgPSBkYXRhLnNpemU7XG4gIHJldHVybiB0aGlzO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHN0YWNrU2V0O1xuIiwiLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIGZ1bmNQcm90byA9IEZ1bmN0aW9uLnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gcmVzb2x2ZSB0aGUgZGVjb21waWxlZCBzb3VyY2Ugb2YgZnVuY3Rpb25zLiAqL1xudmFyIGZ1bmNUb1N0cmluZyA9IGZ1bmNQcm90by50b1N0cmluZztcblxuLyoqXG4gKiBDb252ZXJ0cyBgZnVuY2AgdG8gaXRzIHNvdXJjZSBjb2RlLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjb252ZXJ0LlxuICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc291cmNlIGNvZGUuXG4gKi9cbmZ1bmN0aW9uIHRvU291cmNlKGZ1bmMpIHtcbiAgaWYgKGZ1bmMgIT0gbnVsbCkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZnVuY1RvU3RyaW5nLmNhbGwoZnVuYyk7XG4gICAgfSBjYXRjaCAoZSkge31cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIChmdW5jICsgJycpO1xuICAgIH0gY2F0Y2ggKGUpIHt9XG4gIH1cbiAgcmV0dXJuICcnO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHRvU291cmNlO1xuIiwidmFyIGJhc2VDbG9uZSA9IHJlcXVpcmUoJy4vX2Jhc2VDbG9uZScpO1xuXG4vKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciBjbG9uaW5nLiAqL1xudmFyIENMT05FX0RFRVBfRkxBRyA9IDEsXG4gICAgQ0xPTkVfU1lNQk9MU19GTEFHID0gNDtcblxuLyoqXG4gKiBUaGlzIG1ldGhvZCBpcyBsaWtlIGBfLmNsb25lYCBleGNlcHQgdGhhdCBpdCByZWN1cnNpdmVseSBjbG9uZXMgYHZhbHVlYC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDEuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcmVjdXJzaXZlbHkgY2xvbmUuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZGVlcCBjbG9uZWQgdmFsdWUuXG4gKiBAc2VlIF8uY2xvbmVcbiAqIEBleGFtcGxlXG4gKlxuICogdmFyIG9iamVjdHMgPSBbeyAnYSc6IDEgfSwgeyAnYic6IDIgfV07XG4gKlxuICogdmFyIGRlZXAgPSBfLmNsb25lRGVlcChvYmplY3RzKTtcbiAqIGNvbnNvbGUubG9nKGRlZXBbMF0gPT09IG9iamVjdHNbMF0pO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gY2xvbmVEZWVwKHZhbHVlKSB7XG4gIHJldHVybiBiYXNlQ2xvbmUodmFsdWUsIENMT05FX0RFRVBfRkxBRyB8IENMT05FX1NZTUJPTFNfRkxBRyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2xvbmVEZWVwO1xuIiwiLyoqXG4gKiBQZXJmb3JtcyBhXG4gKiBbYFNhbWVWYWx1ZVplcm9gXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1zYW1ldmFsdWV6ZXJvKVxuICogY29tcGFyaXNvbiBiZXR3ZWVuIHR3byB2YWx1ZXMgdG8gZGV0ZXJtaW5lIGlmIHRoZXkgYXJlIGVxdWl2YWxlbnQuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxIH07XG4gKiB2YXIgb3RoZXIgPSB7ICdhJzogMSB9O1xuICpcbiAqIF8uZXEob2JqZWN0LCBvYmplY3QpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uZXEob2JqZWN0LCBvdGhlcik7XG4gKiAvLyA9PiBmYWxzZVxuICpcbiAqIF8uZXEoJ2EnLCAnYScpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uZXEoJ2EnLCBPYmplY3QoJ2EnKSk7XG4gKiAvLyA9PiBmYWxzZVxuICpcbiAqIF8uZXEoTmFOLCBOYU4pO1xuICogLy8gPT4gdHJ1ZVxuICovXG5mdW5jdGlvbiBlcSh2YWx1ZSwgb3RoZXIpIHtcbiAgcmV0dXJuIHZhbHVlID09PSBvdGhlciB8fCAodmFsdWUgIT09IHZhbHVlICYmIG90aGVyICE9PSBvdGhlcik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZXE7XG4iLCJ2YXIgYmFzZUlzQXJndW1lbnRzID0gcmVxdWlyZSgnLi9fYmFzZUlzQXJndW1lbnRzJyksXG4gICAgaXNPYmplY3RMaWtlID0gcmVxdWlyZSgnLi9pc09iamVjdExpa2UnKTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqIEJ1aWx0LWluIHZhbHVlIHJlZmVyZW5jZXMuICovXG52YXIgcHJvcGVydHlJc0VudW1lcmFibGUgPSBvYmplY3RQcm90by5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBsaWtlbHkgYW4gYGFyZ3VtZW50c2Agb2JqZWN0LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGBhcmd1bWVudHNgIG9iamVjdCxcbiAqICBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNBcmd1bWVudHMoZnVuY3Rpb24oKSB7IHJldHVybiBhcmd1bWVudHM7IH0oKSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc0FyZ3VtZW50cyhbMSwgMiwgM10pO1xuICogLy8gPT4gZmFsc2VcbiAqL1xudmFyIGlzQXJndW1lbnRzID0gYmFzZUlzQXJndW1lbnRzKGZ1bmN0aW9uKCkgeyByZXR1cm4gYXJndW1lbnRzOyB9KCkpID8gYmFzZUlzQXJndW1lbnRzIDogZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgaGFzT3duUHJvcGVydHkuY2FsbCh2YWx1ZSwgJ2NhbGxlZScpICYmXG4gICAgIXByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwodmFsdWUsICdjYWxsZWUnKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gaXNBcmd1bWVudHM7XG4iLCIvKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYW4gYEFycmF5YCBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gYXJyYXksIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc0FycmF5KFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc0FycmF5KGRvY3VtZW50LmJvZHkuY2hpbGRyZW4pO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzQXJyYXkoJ2FiYycpO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzQXJyYXkoXy5ub29wKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbnZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSBpc0FycmF5O1xuIiwidmFyIGlzRnVuY3Rpb24gPSByZXF1aXJlKCcuL2lzRnVuY3Rpb24nKSxcbiAgICBpc0xlbmd0aCA9IHJlcXVpcmUoJy4vaXNMZW5ndGgnKTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhcnJheS1saWtlLiBBIHZhbHVlIGlzIGNvbnNpZGVyZWQgYXJyYXktbGlrZSBpZiBpdCdzXG4gKiBub3QgYSBmdW5jdGlvbiBhbmQgaGFzIGEgYHZhbHVlLmxlbmd0aGAgdGhhdCdzIGFuIGludGVnZXIgZ3JlYXRlciB0aGFuIG9yXG4gKiBlcXVhbCB0byBgMGAgYW5kIGxlc3MgdGhhbiBvciBlcXVhbCB0byBgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVJgLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFycmF5LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc0FycmF5TGlrZShbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNBcnJheUxpa2UoZG9jdW1lbnQuYm9keS5jaGlsZHJlbik7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc0FycmF5TGlrZSgnYWJjJyk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc0FycmF5TGlrZShfLm5vb3ApO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNBcnJheUxpa2UodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgaXNMZW5ndGgodmFsdWUubGVuZ3RoKSAmJiAhaXNGdW5jdGlvbih2YWx1ZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNBcnJheUxpa2U7XG4iLCJ2YXIgcm9vdCA9IHJlcXVpcmUoJy4vX3Jvb3QnKSxcbiAgICBzdHViRmFsc2UgPSByZXF1aXJlKCcuL3N0dWJGYWxzZScpO1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGV4cG9ydHNgLiAqL1xudmFyIGZyZWVFeHBvcnRzID0gdHlwZW9mIGV4cG9ydHMgPT0gJ29iamVjdCcgJiYgZXhwb3J0cyAmJiAhZXhwb3J0cy5ub2RlVHlwZSAmJiBleHBvcnRzO1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYG1vZHVsZWAuICovXG52YXIgZnJlZU1vZHVsZSA9IGZyZWVFeHBvcnRzICYmIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlICYmICFtb2R1bGUubm9kZVR5cGUgJiYgbW9kdWxlO1xuXG4vKiogRGV0ZWN0IHRoZSBwb3B1bGFyIENvbW1vbkpTIGV4dGVuc2lvbiBgbW9kdWxlLmV4cG9ydHNgLiAqL1xudmFyIG1vZHVsZUV4cG9ydHMgPSBmcmVlTW9kdWxlICYmIGZyZWVNb2R1bGUuZXhwb3J0cyA9PT0gZnJlZUV4cG9ydHM7XG5cbi8qKiBCdWlsdC1pbiB2YWx1ZSByZWZlcmVuY2VzLiAqL1xudmFyIEJ1ZmZlciA9IG1vZHVsZUV4cG9ydHMgPyByb290LkJ1ZmZlciA6IHVuZGVmaW5lZDtcblxuLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xudmFyIG5hdGl2ZUlzQnVmZmVyID0gQnVmZmVyID8gQnVmZmVyLmlzQnVmZmVyIDogdW5kZWZpbmVkO1xuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgYnVmZmVyLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4zLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgYnVmZmVyLCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNCdWZmZXIobmV3IEJ1ZmZlcigyKSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc0J1ZmZlcihuZXcgVWludDhBcnJheSgyKSk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG52YXIgaXNCdWZmZXIgPSBuYXRpdmVJc0J1ZmZlciB8fCBzdHViRmFsc2U7XG5cbm1vZHVsZS5leHBvcnRzID0gaXNCdWZmZXI7XG4iLCJ2YXIgYmFzZUlzRXF1YWwgPSByZXF1aXJlKCcuL19iYXNlSXNFcXVhbCcpO1xuXG4vKipcbiAqIFBlcmZvcm1zIGEgZGVlcCBjb21wYXJpc29uIGJldHdlZW4gdHdvIHZhbHVlcyB0byBkZXRlcm1pbmUgaWYgdGhleSBhcmVcbiAqIGVxdWl2YWxlbnQuXG4gKlxuICogKipOb3RlOioqIFRoaXMgbWV0aG9kIHN1cHBvcnRzIGNvbXBhcmluZyBhcnJheXMsIGFycmF5IGJ1ZmZlcnMsIGJvb2xlYW5zLFxuICogZGF0ZSBvYmplY3RzLCBlcnJvciBvYmplY3RzLCBtYXBzLCBudW1iZXJzLCBgT2JqZWN0YCBvYmplY3RzLCByZWdleGVzLFxuICogc2V0cywgc3RyaW5ncywgc3ltYm9scywgYW5kIHR5cGVkIGFycmF5cy4gYE9iamVjdGAgb2JqZWN0cyBhcmUgY29tcGFyZWRcbiAqIGJ5IHRoZWlyIG93biwgbm90IGluaGVyaXRlZCwgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLiBGdW5jdGlvbnMgYW5kIERPTVxuICogbm9kZXMgYXJlIGNvbXBhcmVkIGJ5IHN0cmljdCBlcXVhbGl0eSwgaS5lLiBgPT09YC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHZhbHVlcyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiB2YXIgb2JqZWN0ID0geyAnYSc6IDEgfTtcbiAqIHZhciBvdGhlciA9IHsgJ2EnOiAxIH07XG4gKlxuICogXy5pc0VxdWFsKG9iamVjdCwgb3RoZXIpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIG9iamVjdCA9PT0gb3RoZXI7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0VxdWFsKHZhbHVlLCBvdGhlcikge1xuICByZXR1cm4gYmFzZUlzRXF1YWwodmFsdWUsIG90aGVyKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc0VxdWFsO1xuIiwidmFyIGJhc2VHZXRUYWcgPSByZXF1aXJlKCcuL19iYXNlR2V0VGFnJyksXG4gICAgaXNPYmplY3QgPSByZXF1aXJlKCcuL2lzT2JqZWN0Jyk7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBhc3luY1RhZyA9ICdbb2JqZWN0IEFzeW5jRnVuY3Rpb25dJyxcbiAgICBmdW5jVGFnID0gJ1tvYmplY3QgRnVuY3Rpb25dJyxcbiAgICBnZW5UYWcgPSAnW29iamVjdCBHZW5lcmF0b3JGdW5jdGlvbl0nLFxuICAgIHByb3h5VGFnID0gJ1tvYmplY3QgUHJveHldJztcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYEZ1bmN0aW9uYCBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBmdW5jdGlvbiwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzRnVuY3Rpb24oXyk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc0Z1bmN0aW9uKC9hYmMvKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzRnVuY3Rpb24odmFsdWUpIHtcbiAgaWYgKCFpc09iamVjdCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgLy8gVGhlIHVzZSBvZiBgT2JqZWN0I3RvU3RyaW5nYCBhdm9pZHMgaXNzdWVzIHdpdGggdGhlIGB0eXBlb2ZgIG9wZXJhdG9yXG4gIC8vIGluIFNhZmFyaSA5IHdoaWNoIHJldHVybnMgJ29iamVjdCcgZm9yIHR5cGVkIGFycmF5cyBhbmQgb3RoZXIgY29uc3RydWN0b3JzLlxuICB2YXIgdGFnID0gYmFzZUdldFRhZyh2YWx1ZSk7XG4gIHJldHVybiB0YWcgPT0gZnVuY1RhZyB8fCB0YWcgPT0gZ2VuVGFnIHx8IHRhZyA9PSBhc3luY1RhZyB8fCB0YWcgPT0gcHJveHlUYWc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNGdW5jdGlvbjtcbiIsIi8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIHZhcmlvdXMgYE51bWJlcmAgY29uc3RhbnRzLiAqL1xudmFyIE1BWF9TQUZFX0lOVEVHRVIgPSA5MDA3MTk5MjU0NzQwOTkxO1xuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgdmFsaWQgYXJyYXktbGlrZSBsZW5ndGguXG4gKlxuICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGlzIGxvb3NlbHkgYmFzZWQgb25cbiAqIFtgVG9MZW5ndGhgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy10b2xlbmd0aCkuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBsZW5ndGgsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc0xlbmd0aCgzKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzTGVuZ3RoKE51bWJlci5NSU5fVkFMVUUpO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzTGVuZ3RoKEluZmluaXR5KTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc0xlbmd0aCgnMycpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNMZW5ndGgodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJyAmJlxuICAgIHZhbHVlID4gLTEgJiYgdmFsdWUgJSAxID09IDAgJiYgdmFsdWUgPD0gTUFYX1NBRkVfSU5URUdFUjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc0xlbmd0aDtcbiIsInZhciBiYXNlSXNNYXAgPSByZXF1aXJlKCcuL19iYXNlSXNNYXAnKSxcbiAgICBiYXNlVW5hcnkgPSByZXF1aXJlKCcuL19iYXNlVW5hcnknKSxcbiAgICBub2RlVXRpbCA9IHJlcXVpcmUoJy4vX25vZGVVdGlsJyk7XG5cbi8qIE5vZGUuanMgaGVscGVyIHJlZmVyZW5jZXMuICovXG52YXIgbm9kZUlzTWFwID0gbm9kZVV0aWwgJiYgbm9kZVV0aWwuaXNNYXA7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBNYXBgIG9iamVjdC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMy4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIG1hcCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzTWFwKG5ldyBNYXApO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNNYXAobmV3IFdlYWtNYXApO1xuICogLy8gPT4gZmFsc2VcbiAqL1xudmFyIGlzTWFwID0gbm9kZUlzTWFwID8gYmFzZVVuYXJ5KG5vZGVJc01hcCkgOiBiYXNlSXNNYXA7XG5cbm1vZHVsZS5leHBvcnRzID0gaXNNYXA7XG4iLCIvKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHRoZVxuICogW2xhbmd1YWdlIHR5cGVdKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1lY21hc2NyaXB0LWxhbmd1YWdlLXR5cGVzKVxuICogb2YgYE9iamVjdGAuIChlLmcuIGFycmF5cywgZnVuY3Rpb25zLCBvYmplY3RzLCByZWdleGVzLCBgbmV3IE51bWJlcigwKWAsIGFuZCBgbmV3IFN0cmluZygnJylgKVxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0KHt9KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChfLm5vb3ApO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgKHR5cGUgPT0gJ29iamVjdCcgfHwgdHlwZSA9PSAnZnVuY3Rpb24nKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc09iamVjdDtcbiIsIi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UuIEEgdmFsdWUgaXMgb2JqZWN0LWxpa2UgaWYgaXQncyBub3QgYG51bGxgXG4gKiBhbmQgaGFzIGEgYHR5cGVvZmAgcmVzdWx0IG9mIFwib2JqZWN0XCIuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgb2JqZWN0LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdExpa2Uoe30pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdExpa2UoXy5ub29wKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc09iamVjdExpa2UobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdExpa2UodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgdHlwZW9mIHZhbHVlID09ICdvYmplY3QnO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzT2JqZWN0TGlrZTtcbiIsInZhciBiYXNlSXNTZXQgPSByZXF1aXJlKCcuL19iYXNlSXNTZXQnKSxcbiAgICBiYXNlVW5hcnkgPSByZXF1aXJlKCcuL19iYXNlVW5hcnknKSxcbiAgICBub2RlVXRpbCA9IHJlcXVpcmUoJy4vX25vZGVVdGlsJyk7XG5cbi8qIE5vZGUuanMgaGVscGVyIHJlZmVyZW5jZXMuICovXG52YXIgbm9kZUlzU2V0ID0gbm9kZVV0aWwgJiYgbm9kZVV0aWwuaXNTZXQ7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBTZXRgIG9iamVjdC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMy4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHNldCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzU2V0KG5ldyBTZXQpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNTZXQobmV3IFdlYWtTZXQpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xudmFyIGlzU2V0ID0gbm9kZUlzU2V0ID8gYmFzZVVuYXJ5KG5vZGVJc1NldCkgOiBiYXNlSXNTZXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gaXNTZXQ7XG4iLCJ2YXIgYmFzZUlzVHlwZWRBcnJheSA9IHJlcXVpcmUoJy4vX2Jhc2VJc1R5cGVkQXJyYXknKSxcbiAgICBiYXNlVW5hcnkgPSByZXF1aXJlKCcuL19iYXNlVW5hcnknKSxcbiAgICBub2RlVXRpbCA9IHJlcXVpcmUoJy4vX25vZGVVdGlsJyk7XG5cbi8qIE5vZGUuanMgaGVscGVyIHJlZmVyZW5jZXMuICovXG52YXIgbm9kZUlzVHlwZWRBcnJheSA9IG5vZGVVdGlsICYmIG5vZGVVdGlsLmlzVHlwZWRBcnJheTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgdHlwZWQgYXJyYXkuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAzLjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB0eXBlZCBhcnJheSwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzVHlwZWRBcnJheShuZXcgVWludDhBcnJheSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc1R5cGVkQXJyYXkoW10pO1xuICogLy8gPT4gZmFsc2VcbiAqL1xudmFyIGlzVHlwZWRBcnJheSA9IG5vZGVJc1R5cGVkQXJyYXkgPyBiYXNlVW5hcnkobm9kZUlzVHlwZWRBcnJheSkgOiBiYXNlSXNUeXBlZEFycmF5O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGlzVHlwZWRBcnJheTtcbiIsInZhciBhcnJheUxpa2VLZXlzID0gcmVxdWlyZSgnLi9fYXJyYXlMaWtlS2V5cycpLFxuICAgIGJhc2VLZXlzID0gcmVxdWlyZSgnLi9fYmFzZUtleXMnKSxcbiAgICBpc0FycmF5TGlrZSA9IHJlcXVpcmUoJy4vaXNBcnJheUxpa2UnKTtcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGFycmF5IG9mIHRoZSBvd24gZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBvZiBgb2JqZWN0YC5cbiAqXG4gKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy4gU2VlIHRoZVxuICogW0VTIHNwZWNdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLW9iamVjdC5rZXlzKVxuICogZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBAc3RhdGljXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgT2JqZWN0XG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICogQGV4YW1wbGVcbiAqXG4gKiBmdW5jdGlvbiBGb28oKSB7XG4gKiAgIHRoaXMuYSA9IDE7XG4gKiAgIHRoaXMuYiA9IDI7XG4gKiB9XG4gKlxuICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAqXG4gKiBfLmtleXMobmV3IEZvbyk7XG4gKiAvLyA9PiBbJ2EnLCAnYiddIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gKlxuICogXy5rZXlzKCdoaScpO1xuICogLy8gPT4gWycwJywgJzEnXVxuICovXG5mdW5jdGlvbiBrZXlzKG9iamVjdCkge1xuICByZXR1cm4gaXNBcnJheUxpa2Uob2JqZWN0KSA/IGFycmF5TGlrZUtleXMob2JqZWN0KSA6IGJhc2VLZXlzKG9iamVjdCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ga2V5cztcbiIsInZhciBhcnJheUxpa2VLZXlzID0gcmVxdWlyZSgnLi9fYXJyYXlMaWtlS2V5cycpLFxuICAgIGJhc2VLZXlzSW4gPSByZXF1aXJlKCcuL19iYXNlS2V5c0luJyksXG4gICAgaXNBcnJheUxpa2UgPSByZXF1aXJlKCcuL2lzQXJyYXlMaWtlJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSBuYW1lcyBvZiBgb2JqZWN0YC5cbiAqXG4gKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDMuMC4wXG4gKiBAY2F0ZWdvcnkgT2JqZWN0XG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICogQGV4YW1wbGVcbiAqXG4gKiBmdW5jdGlvbiBGb28oKSB7XG4gKiAgIHRoaXMuYSA9IDE7XG4gKiAgIHRoaXMuYiA9IDI7XG4gKiB9XG4gKlxuICogRm9vLnByb3RvdHlwZS5jID0gMztcbiAqXG4gKiBfLmtleXNJbihuZXcgRm9vKTtcbiAqIC8vID0+IFsnYScsICdiJywgJ2MnXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICovXG5mdW5jdGlvbiBrZXlzSW4ob2JqZWN0KSB7XG4gIHJldHVybiBpc0FycmF5TGlrZShvYmplY3QpID8gYXJyYXlMaWtlS2V5cyhvYmplY3QsIHRydWUpIDogYmFzZUtleXNJbihvYmplY3QpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGtleXNJbjtcbiIsIi8qKlxuICogVGhpcyBtZXRob2QgcmV0dXJucyBhIG5ldyBlbXB0eSBhcnJheS5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMTMuMFxuICogQGNhdGVnb3J5IFV0aWxcbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGVtcHR5IGFycmF5LlxuICogQGV4YW1wbGVcbiAqXG4gKiB2YXIgYXJyYXlzID0gXy50aW1lcygyLCBfLnN0dWJBcnJheSk7XG4gKlxuICogY29uc29sZS5sb2coYXJyYXlzKTtcbiAqIC8vID0+IFtbXSwgW11dXG4gKlxuICogY29uc29sZS5sb2coYXJyYXlzWzBdID09PSBhcnJheXNbMV0pO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gc3R1YkFycmF5KCkge1xuICByZXR1cm4gW107XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc3R1YkFycmF5O1xuIiwiLyoqXG4gKiBUaGlzIG1ldGhvZCByZXR1cm5zIGBmYWxzZWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjEzLjBcbiAqIEBjYXRlZ29yeSBVdGlsXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLnRpbWVzKDIsIF8uc3R1YkZhbHNlKTtcbiAqIC8vID0+IFtmYWxzZSwgZmFsc2VdXG4gKi9cbmZ1bmN0aW9uIHN0dWJGYWxzZSgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHN0dWJGYWxzZTtcbiIsIi8vIFRoZSBtb2R1bGUgY2FjaGVcbnZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcblxuLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbmZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG5cdHZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdO1xuXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XG5cdH1cblx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcblx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XG5cdFx0aWQ6IG1vZHVsZUlkLFxuXHRcdGxvYWRlZDogZmFsc2UsXG5cdFx0ZXhwb3J0czoge31cblx0fTtcblxuXHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cblx0X193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0obW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cblx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuXHRtb2R1bGUubG9hZGVkID0gdHJ1ZTtcblxuXHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuXHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG59XG5cbiIsIl9fd2VicGFja19yZXF1aXJlX18uZyA9IChmdW5jdGlvbigpIHtcblx0aWYgKHR5cGVvZiBnbG9iYWxUaGlzID09PSAnb2JqZWN0JykgcmV0dXJuIGdsb2JhbFRoaXM7XG5cdHRyeSB7XG5cdFx0cmV0dXJuIHRoaXMgfHwgbmV3IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcpIHJldHVybiB3aW5kb3c7XG5cdH1cbn0pKCk7IiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiX193ZWJwYWNrX3JlcXVpcmVfXy5ubWQgPSAobW9kdWxlKSA9PiB7XG5cdG1vZHVsZS5wYXRocyA9IFtdO1xuXHRpZiAoIW1vZHVsZS5jaGlsZHJlbikgbW9kdWxlLmNoaWxkcmVuID0gW107XG5cdHJldHVybiBtb2R1bGU7XG59OyIsImltcG9ydCB0eXBlIE9wZW5GaW4gZnJvbSBcIkBvcGVuZmluL2NvcmVcIjtcbmltcG9ydCB7IGZpbiB9IGZyb20gXCJAb3BlbmZpbi9jb3JlXCI7XG5cbmxldCBmaWxlTmFtZTogc3RyaW5nO1xubGV0IGRlYnVnTG9nU3RyOiBzdHJpbmc7XG5sZXQgZGVidWdMb2dGaWxlOiBGaWxlO1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBhc3luYyAoKSA9PiB7XG5cdHRyeSB7XG5cdFx0YXdhaXQgaW5pdERvbSgpO1xuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuXHR9XG59KTtcblxuLyoqXG4gKiBQb3B1bGF0ZXMgRE9NIHdpdGggdGhlIFVJIGVsZW1lbnRzIGFuZCBhZGRzIGxpc3RlbmVycyBvYnRhaW5pbmcgc2VsZWN0ZWQvc3VibWl0dGVkIG9wdGlvbnMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluaXREb20oKTogUHJvbWlzZTx2b2lkPiB7XG5cdGNvbnN0IGxvZ0xpc3RFbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MU2VsZWN0RWxlbWVudD4oXCIjbG9nLWxpc3RcIik7XG5cdGlmIChsb2dMaXN0RWxlbWVudCkge1xuXHRcdGF3YWl0IGNyZWF0ZUxvZ0Ryb3BEb3duKGxvZ0xpc3RFbGVtZW50KTtcblx0XHRsb2dMaXN0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFwiY2hhbmdlXCIsIGFzeW5jIChzZWxlY3Rpb25DaGFuZ2VFdmVudCkgPT4ge1xuXHRcdFx0ZmlsZU5hbWUgPSAoc2VsZWN0aW9uQ2hhbmdlRXZlbnQudGFyZ2V0IGFzIEhUTUxPcHRpb25FbGVtZW50KS52YWx1ZTtcblx0XHR9KTtcblx0fVxuXG5cdGNvbnN0IHVwbG9hZCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEZvcm1FbGVtZW50PihcIiN1cGxvYWQtZm9ybVwiKTtcblx0aWYgKHVwbG9hZCkge1xuXHRcdHVwbG9hZC5hZGRFdmVudExpc3RlbmVyKFwic3VibWl0XCIsIHVwbG9hZEhhbmRsZXIpO1xuXHR9XG5cdGNvbnN0IHNlbmRBcHBMb2dCdG4gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxCdXR0b25FbGVtZW50PihcIiNzZW5kLWFwcC1sb2dcIik7XG5cdGlmIChzZW5kQXBwTG9nQnRuKSB7XG5cdFx0c2VuZEFwcExvZ0J0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgc2VuZEFwcGxpY2F0aW9uTG9ncyk7XG5cdH1cbn1cblxuLyoqXG4gKiBIYW5kbGUgdXBsb2Fkcy5cbiAqIDEuIENyZWF0ZXMgYSBGb3JtRGF0YSBvYmplY3QuXG4gKiAyLiBDcmVhdGVzIGEgRmlsZSBvYmplY3QgZnJvbSB0aGUgc3RyaW5nIG9mIHRoZSBSdW50aW1lIGRlYnVnIGxvZyBmaWxlIGNvbnRlbnRzLlxuICogMy4gUG9wdWxhdGVzIHRoZSBGb3JtRGF0YSBvYmplY3Qgd2l0aCBuZWNlc3NhcnkgcGFyYW1ldGVycyB0byBiZSByZWFkIGJ5IHRoZSBzZXJ2ZXIuXG4gKiA0LiBVcGxvYWRzIHRoZSBjcmVhdGVkIHJ1bnRpbWUgZGVidWcgbG9nIGZpbGUgdG8gYSBzZXJ2ZXIgZW5kcG9pbnQuXG4gKiBAcGFyYW0gc3VibWl0RXZlbnQgVGhlIGV2ZW50IHRvIGhhbmRsZS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdXBsb2FkSGFuZGxlcihzdWJtaXRFdmVudDogRXZlbnQpOiBQcm9taXNlPHZvaWQ+IHtcblx0c3VibWl0RXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0aWYgKCFmaWxlTmFtZSkge1xuXHRcdGZpbGVOYW1lID0gXCJkZWJ1Zy5sb2dcIjtcblx0fVxuXHRjb25zdCBmb3JtRGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuXHRkZWJ1Z0xvZ1N0ciA9IGF3YWl0IGdldExvZ0Zyb21OYW1lKGZpbGVOYW1lKTtcblx0ZGVidWdMb2dGaWxlID0gbmV3IEZpbGUoW2RlYnVnTG9nU3RyXSwgZmlsZU5hbWUsIHsgdHlwZTogXCJ0ZXh0L3BsYWluXCIgfSk7XG5cdGZvcm1EYXRhLmFwcGVuZChcImZpbGVcIiwgZGVidWdMb2dGaWxlKTtcblx0Zm9ybURhdGEuYXBwZW5kKFwiZmlsZW5hbWVcIiwgZmlsZU5hbWUpO1xuXHRmb3JtRGF0YS5hcHBlbmQoXCJ1dWlkXCIsIGZpbi5tZS51dWlkKTtcblx0Y29uc3QgdXBsb2FkU3RhdGUgPSBhd2FpdCBmZXRjaChcImh0dHA6Ly9sb2NhbGhvc3Q6NTA1MC91cGxvYWRzXCIsIHtcblx0XHRtZXRob2Q6IFwiUE9TVFwiLFxuXHRcdGJvZHk6IGZvcm1EYXRhXG5cdH0pO1xuXG5cdGNvbnN0IHVwbG9hZFN0YXRlSnNvbiA9IGF3YWl0IHVwbG9hZFN0YXRlLmpzb24oKTtcblx0Y29uc3QgdXBsb2FkU3RhdGVKc29uU3RyaW5nID0gSlNPTi5zdHJpbmdpZnkodXBsb2FkU3RhdGVKc29uLCBudWxsLCA1KTtcblx0Y29uc3QgbG9ncyA9IGAke25ldyBEYXRlKCkudG9Mb2NhbGVUaW1lU3RyaW5nKCl9OiAke3VwbG9hZFN0YXRlSnNvblN0cmluZ31cXG5gO1xuXHRjb25zdCBsb2dQcmV2aWV3ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNwcmV2aWV3XCIpO1xuXHRpZiAobG9nUHJldmlldykge1xuXHRcdGxvZ1ByZXZpZXcudGV4dENvbnRlbnQgKz0gbG9ncztcblx0fVxufVxuXG4vKipcbiAqIFNlbmRzIGEgbWVzc2FnZSB0byB0aGUgT3BlbkZpbiBSVk0gdG8gc2VuZCB0aGUgYXBwbGljYXRpb24gbG9ncy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2VuZEFwcGxpY2F0aW9uTG9ncygpOiBQcm9taXNlPHZvaWQ+IHtcblx0dHJ5IHtcblx0XHRjb25zdCBhcHBMb2dSZXNwb25zZSA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50U3luYygpLnNlbmRBcHBsaWNhdGlvbkxvZygpO1xuXHRcdGNvbnNvbGUubG9nKGBMb2cgSUQ6ICR7YXBwTG9nUmVzcG9uc2UubG9nSWR9YCk7XG5cdH0gY2F0Y2gge1xuXHRcdC8vIHN3YWxsb3cgdW5uZWNlc3NhcnkgZXJyb3JzLlxuXHR9XG59XG5cbi8qKlxuICogUmV0cmlldmVzIHRoZSBydW50aW1lIGRlYnVnIGxvZyBmcm9tIGEgZmlsZW5hbWUuXG4gKiBAcGFyYW0gbmFtZSBmaWxlIG5hbWUgb2YgdGhlIHJ1bnRpbWUgZGVidWcgbG9nIHRvIHJldHJpZXZlLlxuICogQHJldHVybnMgdGhlIGxvZyBjb250ZW50LlxuICovXG5hc3luYyBmdW5jdGlvbiBnZXRMb2dGcm9tTmFtZShuYW1lOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuXHRjb25zdCBsb2cgPSBhd2FpdCBmaW4uU3lzdGVtLmdldExvZyh7IG5hbWUgfSk7XG5cdHJldHVybiBsb2c7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBIVE1MT3B0aW9uRWxlbWVudCBmb3IgZWFjaCBvZiB0aGUgUnVudGltZSBkZWJ1ZyBsb2dzLlxuICogQHBhcmFtIHBhcmVudEVsZW1lbnQgSFRNTCBFbGVtZW50IHRvIGFwcGVuZCB0aGUgbG9nIGZpbGVuYW1lIEhUTUxPcHRpb25FbGVtZW50IHRvLlxuICovXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVMb2dEcm9wRG93bihwYXJlbnRFbGVtZW50OiBIVE1MU2VsZWN0RWxlbWVudCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBsb2dMaXN0OiBPcGVuRmluLkxvZ0luZm9bXSA9IGF3YWl0IGZpbi5TeXN0ZW0uZ2V0TG9nTGlzdCgpO1xuXG5cdGZvciAoY29uc3QgbG9nIG9mIGxvZ0xpc3QpIHtcblx0XHRjb25zdCBsb2dFbGVtZW50OiBIVE1MT3B0aW9uRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG5cdFx0bG9nRWxlbWVudC5pZCA9IGxvZy5kYXRlO1xuXHRcdGxvZ0VsZW1lbnQudGV4dENvbnRlbnQgPSBsb2cubmFtZTtcblx0XHRsb2dFbGVtZW50LnZhbHVlID0gbG9nLm5hbWU7XG5cdFx0cGFyZW50RWxlbWVudC5hcHBlbmQobG9nRWxlbWVudCk7XG5cdH1cbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-logging-apis/manifest.fin.json b/dev/john/update-logging-example/use-logging-apis/manifest.fin.json new file mode 100644 index 00000000..b4c82b3c --- /dev/null +++ b/dev/john/update-logging-example/use-logging-apis/manifest.fin.json @@ -0,0 +1,25 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "licenseKey": "64605fac-add3-48a0-8710-64b38e96a2dd", + "startup_app": { + "name": "use-application-logging", + "uuid": "use-application-logging", + "description": "An example of using application logging", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-logging-apis/html/app.html", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-logging-apis/favicon.ico", + "autoShow": true, + "defaultWidth": 1200, + "defaultHeight": 800, + "defaultCentered": true, + "minWidth": 800, + "minHeight": 400, + "enableAppLogging": true, + "logManagement": { + "enabled": true, + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-logging-apis" + } + } +} diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/assets/openfin_ZDKIEer6PC.gif b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/assets/openfin_ZDKIEer6PC.gif new file mode 100644 index 00000000..8581a2a2 Binary files /dev/null and b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/assets/openfin_ZDKIEer6PC.gif differ diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/common/images/icon-blue.png b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/common/style/app.css b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/favicon.ico b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/favicon.ico differ diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/dialog.html b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/dialog.html new file mode 100644 index 00000000..7fcf01b3 --- /dev/null +++ b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/dialog.html @@ -0,0 +1,23 @@ + + + + + + + View(s) preventing closing + + + + + + +
+
+
+
+ + +
+
+ + diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/provider.html b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/provider.html new file mode 100644 index 00000000..f2bf9c81 --- /dev/null +++ b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/provider.html @@ -0,0 +1,17 @@ + + + + + + Provider + + + + + + +
+

+
+ + diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/view.html b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/view.html new file mode 100644 index 00000000..199b686f --- /dev/null +++ b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/view.html @@ -0,0 +1,25 @@ + + + + + + + View + + + + + +
+

View

+

+ Type in the field below and try close the View or Window. A dialog will pop up indicating that this + view may have unsaved changes. +

+
+

Test Input

+ +
+
+ + diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/js/dialog.bundle.js b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/js/dialog.bundle.js new file mode 100644 index 00000000..9a5e321b --- /dev/null +++ b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/js/dialog.bundle.js @@ -0,0 +1,22620 @@ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "../../../node_modules/@openfin/core/out/mock.js": +/*!*******************************************************!*\ + !*** ../../../node_modules/@openfin/core/out/mock.js ***! + \*******************************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var require$$0 = __webpack_require__(/*! events */ "../../../node_modules/events/events.js"); +var require$$0$1 = __webpack_require__(/*! lodash/cloneDeep */ "../../../node_modules/lodash/cloneDeep.js"); +var require$$3 = __webpack_require__(/*! lodash/isEqual */ "../../../node_modules/lodash/isEqual.js"); + +function _mergeNamespaces(n, m) { + m.forEach(function (e) { + e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) { + if (k !== 'default' && !(k in n)) { + var d = Object.getOwnPropertyDescriptor(e, k); + Object.defineProperty(n, k, d.get ? d : { + enumerable: true, + get: function () { return e[k]; } + }); + } + }); + }); + return Object.freeze(n); +} + +var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g : typeof self !== 'undefined' ? self : {}; + +function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; +} + +var OpenFin$2 = {}; + +var events = {}; + +var application$1 = {}; + +/** + * Namespace for events that can be emitted by an {@link OpenFin.Application}. Includes events + * re-propagated from the {@link OpenFin.Window} (and, transitively, {@link OpenFin.View}) level, prefixed with `window-` (and also, if applicable, `view-`). + * For example, a view's "attached" event will fire as 'window-view-attached' at the application level. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * This namespace contains only payload shapes for events that are unique to `Application`. Events that propagate to `Application` from + * child {@link OpenFin.Window windows} and {@link OpenFin.View views} are defined in the {@link OpenFin.WindowEvents} and + * {@link OpenFin.ViewEvents} namespaces. For a list of valid string keys for *all* application events, see {@link Application.on Application.on}. + * + * {@link ApplicationSourcedEvent Application-sourced events} (i.e. those that have not propagated from {@link OpenFin.ViewEvents Views} + * or {@link OpenFin.WindowEvents Windows} re-propagate to {@link OpenFin.SystemEvents System} with their type string prefixed with `application-`. + * {@link ApplicationWindowEvent Application events that are tied to Windows but do not propagate from them} + * are propagated to `System` without any type string prefixing. + * + * "Requested" events (e.g. {@link RunRequestedEvent}) do not propagate. + * + * @packageDocumentation + */ +Object.defineProperty(application$1, "__esModule", { value: true }); + +var base$1 = {}; + +/** + * Namespace for shared event payloads and utility types common to all event emitters. + * + * @packageDocumentation + */ +Object.defineProperty(base$1, "__esModule", { value: true }); + +var externalApplication$1 = {}; + +/** + * Namespace for events that can be transmitted by an {@link OpenFin.ExternalApplication}. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * For a list of valid string keys for external application events, see {@link ExternalApplication.on ExternalApplication.on}. + * + * @packageDocumentation + */ +Object.defineProperty(externalApplication$1, "__esModule", { value: true }); + +var frame$1 = {}; + +Object.defineProperty(frame$1, "__esModule", { value: true }); + +var globalHotkey$1 = {}; + +/** + * + * Namespace for events that can be transmitted by {@link GlobalHotkey.GlobalHotkey}. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * For a list of valid string keys for global hotkey events, see {@link GlobalHotkey.GlobalHotkey.on GlobalHotkey.on}. + * + * @packageDocumentation + */ +Object.defineProperty(globalHotkey$1, "__esModule", { value: true }); + +var platform$1 = {}; + +/** + * + * Namespace for events that can emitted by a {@link OpenFin.Platform}. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * The Platform `EventEmitter` is a superset of the {@link OpenFin.Application} `EventEmitter`, + * meaning it can listen to all {@link OpenFin.ApplicationEvents Application events} in addition to the + * Platform-specific events listed here. For a list of valid string keys for *all* platform events, see + * {@link Platform.on Platform.on}. + * + * @packageDocumentation + */ +Object.defineProperty(platform$1, "__esModule", { value: true }); + +var system$1 = {}; + +/** + * Namespace for runtime-wide OpenFin events emitted by {@link System.System}. Includes events + * re-propagated from {@link OpenFin.Application}, {@link OpenFin.Window}, and {@link OpenFin.View} (prefixed with `application-`, `window-`, and `view-`). All + * event propagations are visible at the System level. Propagated events from WebContents (windows, views, frames) to the Application level will *not* + * transitively re-propagate to the System level, because they are already visible at the system level and contain the identity + * of the application. For example, an application's "closed" event will fire as 'application-closed' at the system level. A view's 'shown' event + * will be visible as 'view-shown' at the system level, but *not* as `application-window-view-shown`. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * This namespace contains only payload shapes for events that are unique to `System`. Events that propagate to `System` from + * child {@link OpenFin.Application applications}, {@link OpenFin.Window windows}, and {@link OpenFin.View views} are defined in the + * {@link OpenFin.ApplicationEvents}, {@link OpenFin.WindowEvents}, and {@link OpenFin.ViewEvents} namespaces. For a list of valid string keys for *all* + * system events, see {@link System.on System.on}. + * + * @packageDocumentation + */ +Object.defineProperty(system$1, "__esModule", { value: true }); + +var view$1 = {}; + +/** + * Namespace for events that can be emitted by a {@link OpenFin.View}. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * This namespace contains only payload shapes for events that are unique to `View`. Events that are shared between all `WebContents` + * (i.e. {@link OpenFin.Window}, {@link OpenFin.View}) are defined in {@link OpenFin.WebContentsEvents}. For a list + * of valid string keys for *all* View events, see {@link View.on View.on}. + * + * View events propagate to their parent {@link OpenFin.WindowEvents Window}, {@link OpenFin.ApplicationEvents Application}, + * and {@link OpenFin.SystemEvents System} with an added `viewIdentity` property and their event types prefixed with `'view-'`. + * + * @packageDocumentation + */ +Object.defineProperty(view$1, "__esModule", { value: true }); + +var webcontents = {}; + +/** + * Namespace for events shared by all OpenFin WebContents elements (i.e. {@link OpenFin.Window}, + * {@link OpenFin.View}). + * + * WebContents events will re-emit on parent entities - e.g., a propagating event in a view will also be emitted on the view's + * parent window, and propagating events in a window will also be emitted on the window's parent {@link OpenFin.Application}. + * + * @packageDocumentation + */ +Object.defineProperty(webcontents, "__esModule", { value: true }); + +var window$2 = {}; + +/** + * Namespace for events that can be emitted by a {@link OpenFin.Window}. + * + * Event payloads are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * Events gain metadata as they propagate, which is *not* present on the explicit payload interfaces. To refer to the full type + * of an event as it would be raised on this emitter, use {@link Payload}. + * + * This namespace contains only payload shapes for events that are unique to `Window`. Events that are shared between all `WebContents` + * (i.e. {@link OpenFin.Window}, {@link OpenFin.View}) are defined in {@link OpenFin.WebContentsEvents}. Events that + * propagate from `View` are defined in {@link OpenFin.ViewEvents}. For a list of valid string keys for *all* Window events, see + * {@link Window.on Window.on} + * + * {@link OpenFin.WindowEvents.WindowSourcedEvent Window-sourced events} (i.e. those that are not propagated from a + * {@link OpenFin.ViewEvents View}) propagate to their parent {@link OpenFin.ApplicationEvents Application} and + * {@link OpenFin.SystemEvents System} with their event types prefixed with `'window-'`). + * + * "Requested" events (e.g. {@link AuthRequestedEvent}) do not propagate to `System. The {@link OpenFin.WindowEvents.WindowCloseRequestedEvent} + * does not propagate at all. + * + * @packageDocumentation + */ +Object.defineProperty(window$2, "__esModule", { value: true }); + +/** + * Namespace for OpenFin event types. Each entity that emits OpenFin events has its own sub-namespace. Event payloads + * themselves are documented as interfaces, while algebraic helper types and derived types are documented as type aliases. + * + * #### Event emitters + * + * The following entities emit OpenFin events, and have corresponding sub-namespaces: + * + * * {@link OpenFin.Application}: {@link OpenFin.ApplicationEvents} + * * {@link OpenFin.ExternalApplication}: {@link OpenFin.ExternalApplicationEvents} + * * {@link OpenFin.Frame}: {@link OpenFin.FrameEvents} + * * {@link OpenFin.GlobalHotkey}: {@link OpenFin.GlobalHotkeyEvents} + * * {@link OpenFin.Platform}: {@link OpenFin.PlatformEvents} + * * {@link OpenFin.System}: {@link OpenFin.SystemEvents} + * * {@link OpenFin.View}: {@link OpenFin.ViewEvents} + * * {@link OpenFin.Window}: {@link OpenFin.WindowEvents} + * + * These `EventEmitter` entities share a common set of methods for interacting with the OpenFin event bus, which can be + * seen on the individual documentation pages for each entity type. + * + * Registering event handlers is an asynchronous operation. It is important to ensure that the returned Promises are awaited to reduce the + * risk of race conditions. + * + * When the `EventEmitter` receives an event from the browser process and emits on the renderer, all of the functions attached to that + * specific event are called synchronously. Any values returned by the called listeners are ignored and will be discarded. If the window document + * is destroyed by page navigation or reload, its registered event listeners will be removed. + * + * We recommend using Arrow Functions for event listeners to ensure the this scope is consistent with the original function context. + * + * Events re-propagate from smaller/more-local scopes to larger/more-global scopes. For example, an event emitted on a specific + * view will propagate to the window in which the view is embedded, and then to the application in which the window is running, and + * finally to the OpenFin runtime itself at the "system" level. For details on propagation semantics, see the namespace for + * the propagating (or propagated-to) entity. + * + * If you need the payload type for a specific type of event (especially propagated events), use the emitting topic's `Payload` generic + * (e.g. {@link WindowEvents.Payload}) with the event's `type` string. For example, the payload of + * a {@link ViewEvents.CreatedEvent} after it has propagated to its parent {@link WindowEvents Window} can be found with + * `WindowEvents.Payload<'view-created'>`. + * + * @packageDocumentation + */ +var __createBinding$1 = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault$1 = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar$1 = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding$1(result, mod, k); + __setModuleDefault$1(result, mod); + return result; +}; +Object.defineProperty(events, "__esModule", { value: true }); +events.WindowEvents = events.WebContentsEvents = events.ViewEvents = events.SystemEvents = events.PlatformEvents = events.GlobalHotkeyEvents = events.FrameEvents = events.ExternalApplicationEvents = events.BaseEvents = events.ApplicationEvents = void 0; +const ApplicationEvents = __importStar$1(application$1); +events.ApplicationEvents = ApplicationEvents; +const BaseEvents = __importStar$1(base$1); +events.BaseEvents = BaseEvents; +const ExternalApplicationEvents = __importStar$1(externalApplication$1); +events.ExternalApplicationEvents = ExternalApplicationEvents; +const FrameEvents = __importStar$1(frame$1); +events.FrameEvents = FrameEvents; +const GlobalHotkeyEvents = __importStar$1(globalHotkey$1); +events.GlobalHotkeyEvents = GlobalHotkeyEvents; +const PlatformEvents = __importStar$1(platform$1); +events.PlatformEvents = PlatformEvents; +const SystemEvents = __importStar$1(system$1); +events.SystemEvents = SystemEvents; +const ViewEvents = __importStar$1(view$1); +events.ViewEvents = ViewEvents; +const WebContentsEvents = __importStar$1(webcontents); +events.WebContentsEvents = WebContentsEvents; +const WindowEvents = __importStar$1(window$2); +events.WindowEvents = WindowEvents; + +(function (exports) { + /** + * Top-level namespace for types referenced by the OpenFin API. Contains: + * + * * The type of the global `fin` entry point ({@link FinApi}) + * * Classes that act as static namespaces returned from the `fin` global (e.g. {@link ApplicationModule}, accessible via `fin.Application`) + * * Instance classes that are returned from API calls (e.g. {@link Application}, accessible via `fin.Application.getCurrentSync()`) + * * Parameter shapes for API methods (e.g. {@link ApplicationOptions}, used in `fin.Application.start()`) + * * Event namespaces and payload union types (e.g. {@link ApplicationEvents} and {@link ApplicationEvent}) + * + * @packageDocumentation + */ + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + // Deprecated shim to preserve v30 namespace names + __exportStar(events, exports); +} (OpenFin$2)); + +var OpenFin = /*@__PURE__*/getDefaultExportFromCjs(OpenFin$2); + +var OpenFin$1 = /*#__PURE__*/_mergeNamespaces({ + __proto__: null, + default: OpenFin +}, [OpenFin$2]); + +var fin$2 = {}; + +var system = {}; + +var base = {}; + +var promises = {}; + +Object.defineProperty(promises, "__esModule", { value: true }); +promises.promiseMapSerial = promises.serial = promises.promiseMap = promises.promisify = void 0; +function promisify(func) { + return (...args) => new Promise((resolve, reject) => { + func(...args, (err, val) => (err ? reject(err) : resolve(val))); + }); +} +promises.promisify = promisify; +async function promiseMap(arr, asyncF) { + return Promise.all(arr.map(asyncF)); +} +promises.promiseMap = promiseMap; +async function serial(arr) { + const ret = []; + for (const func of arr) { + // eslint-disable-next-line no-await-in-loop + const next = await func(); + ret.push(next); + } + return ret; +} +promises.serial = serial; +async function promiseMapSerial(arr, func) { + return serial(arr.map((value, index, array) => () => func(value, index, array))); +} +promises.promiseMapSerial = promiseMapSerial; + +var __classPrivateFieldSet$c = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$e = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _EmitterBase_emitterAccessor; +Object.defineProperty(base, "__esModule", { value: true }); +base.Reply = base.EmitterBase = base.Base = void 0; +const promises_1 = promises; +class Base { + /** + * @internal + */ + constructor(wire) { + /** + * @internal + * @deprecated + */ + this.isNodeEnvironment = () => { + return this.wire.environment.type === 'node'; + }; + /** + * @internal + * @deprecated + */ + this.isOpenFinEnvironment = () => { + return this.wire.environment.type === 'openfin'; + }; + /** + * @internal + * @deprecated + */ + this.isBrowserEnvironment = () => { + return this.wire.environment.type === 'other'; + }; + this.wire = wire; + } + get fin() { + return this.wire.getFin(); + } + /** + * Provides access to the OpenFin representation of the current code context (usually a document + * such as a {@link OpenFin.View} or {@link OpenFin.Window}), as well as to the current `Interop` context. + * + * Useful for debugging in the devtools console, where this will intelligently type itself based + * on the context in which the devtools panel was opened. + */ + get me() { + return this.wire.me; + } +} +base.Base = Base; +/** + * An entity that emits OpenFin events. + * + * @remarks Event-binding methods are asynchronous as they must cross process boundaries + * and setup the listener in the browser process. When the `EventEmitter` receives an event from the browser process + * and emits on the renderer, all of the functions attached to that specific event are called synchronously. Any values + * returned by the called listeners are ignored and will be discarded. If the execution context of the window is destroyed + * by page navigation or reload, any events that have been setup in that context will be destroyed. + * + * It is important to keep in mind that when an ordinary listener function is called, the standard `this` keyword is intentionally + * set to reference the `EventEmitter` instance to which the listener is attached. It is possible to use ES6 Arrow Functions as + * listeners, however, when doing so, the `this` keyword will no longer reference the `EventEmitter` instance. + * + * Events re-propagate from smaller/more-local scopes to larger/more-global scopes. For example, an event emitted on a specific + * view will propagate to the window in which the view is embedded, and then to the application in which the window is running, and + * finally to the OpenFin runtime itself at the "system" level. Re-propagated events are prefixed with the name of the scope in which + * they originated - for example, a "shown" event emitted on a view will be re-propagated at the window level as "view-shown", and + * then to the application as "window-view-shown", and finally at the system level as "application-window-view-shown". + * + * All event propagations are visible at the System level, regardless of source, so transitive re-propagations (e.g. from view to window + * to application) are visible in their entirety at the system level. So, we can listen to the above event as "shown", "view-shown", + * "window-view-shown", or "application-window-view-shown." + */ +class EmitterBase extends Base { + constructor(wire, topic, ...additionalAccessors) { + super(wire); + this.topic = topic; + _EmitterBase_emitterAccessor.set(this, void 0); + this.eventNames = () => (this.hasEmitter() ? this.getOrCreateEmitter().eventNames() : []); + /** + * @internal + */ + this.emit = (eventType, payload, ...args) => { + return this.hasEmitter() ? this.getOrCreateEmitter().emit(eventType, payload, ...args) : false; + }; + this.hasEmitter = () => this.wire.eventAggregator.has(__classPrivateFieldGet$e(this, _EmitterBase_emitterAccessor, "f")); + this.getOrCreateEmitter = () => this.wire.eventAggregator.getOrCreate(__classPrivateFieldGet$e(this, _EmitterBase_emitterAccessor, "f")); + this.listeners = (type) => this.hasEmitter() ? this.getOrCreateEmitter().listeners(type) : []; + this.listenerCount = (type) => this.hasEmitter() ? this.getOrCreateEmitter().listenerCount(type) : 0; + this.registerEventListener = async (eventType, options = {}, applySubscription, undoSubscription) => { + const runtimeEvent = { + ...this.identity, + timestamp: options.timestamp || Date.now(), + topic: this.topic, + type: eventType + }; + const emitter = this.getOrCreateEmitter(); + // We apply the subscription and then undo if the async call fails to avoid + // indeterminacy in subscription application order, which can break things elsewhere + applySubscription(emitter); + try { + await this.wire.sendAction('subscribe-to-desktop-event', runtimeEvent); + } + catch (e) { + undoSubscription(emitter); + this.deleteEmitterIfNothingRegistered(emitter); + throw e; + } + }; + this.deregisterEventListener = async (eventType, options = {}) => { + if (this.hasEmitter()) { + const runtimeEvent = { + ...this.identity, + timestamp: options.timestamp || Date.now(), + topic: this.topic, + type: eventType + }; + await this.wire.sendAction('unsubscribe-to-desktop-event', runtimeEvent).catch(() => null); + const emitter = this.getOrCreateEmitter(); + return emitter; + } + // This will only be reached if unsubscribe from event that does not exist but do not want to error here + return Promise.resolve(); + }; + __classPrivateFieldSet$c(this, _EmitterBase_emitterAccessor, [topic, ...additionalAccessors], "f"); + this.listeners = (event) => this.hasEmitter() ? this.getOrCreateEmitter().listeners(event) : []; + } + /** + * Adds a listener to the end of the listeners array for the specified event. + * + * @remarks Event payloads are documented in the {@link OpenFin.Events} namespace. + */ + async on(eventType, listener, options) { + await this.registerEventListener(eventType, options, (emitter) => { + emitter.on(eventType, listener); + }, (emitter) => { + emitter.removeListener(eventType, listener); + }); + return this; + } + /** + * Adds a listener to the end of the listeners array for the specified event. + */ + async addListener(eventType, listener, options) { + return this.on(eventType, listener, options); + } + /** + * Adds a one time listener for the event. The listener is invoked only the first time the event is fired, after which it is removed. + * + * @remarks Event payloads are documented in the {@link OpenFin.Events} namespace. + */ + async once(eventType, listener, options) { + const deregister = () => this.deregisterEventListener(eventType); + await this.registerEventListener(eventType, options, (emitter) => { + emitter.once(eventType, deregister); + emitter.once(eventType, listener); + }, (emitter) => { + emitter.removeListener(eventType, deregister); + emitter.removeListener(eventType, listener); + }); + return this; + } + /** + * Adds a listener to the beginning of the listeners array for the specified event. + * + * @remarks Event payloads are documented in the {@link OpenFin.Events} namespace. + */ + async prependListener(eventType, listener, options) { + await this.registerEventListener(eventType, options, (emitter) => { + emitter.prependListener(eventType, listener); + }, (emitter) => { + emitter.removeListener(eventType, listener); + }); + return this; + } + /** + * Adds a one time listener for the event. The listener is invoked only the first time the event is fired, + * after which it is removed. The listener is added to the beginning of the listeners array. + * + * @remarks Event payloads are documented in the {@link OpenFin.Events} namespace. + */ + async prependOnceListener(eventType, listener, options) { + const deregister = () => this.deregisterEventListener(eventType); + await this.registerEventListener(eventType, options, (emitter) => { + emitter.prependOnceListener(eventType, listener); + emitter.once(eventType, deregister); + }, (emitter) => { + emitter.removeListener(eventType, listener); + emitter.removeListener(eventType, deregister); + }); + return this; + } + /** + * Remove a listener from the listener array for the specified event. + * + * @remarks Caution: Calling this method changes the array indices in the listener array behind the listener. + */ + async removeListener(eventType, listener, options) { + const emitter = await this.deregisterEventListener(eventType, options); + if (emitter) { + emitter.removeListener(eventType, listener); + this.deleteEmitterIfNothingRegistered(emitter); + } + return this; + } + async deregisterAllListeners(eventType) { + const runtimeEvent = { ...this.identity, type: eventType, topic: this.topic }; + if (this.hasEmitter()) { + const emitter = this.getOrCreateEmitter(); + const refCount = emitter.listenerCount(runtimeEvent.type); + const unsubscribePromises = []; + for (let i = 0; i < refCount; i++) { + unsubscribePromises.push(this.wire.sendAction('unsubscribe-to-desktop-event', runtimeEvent).catch(() => null)); + } + await Promise.all(unsubscribePromises); + return emitter; + } + return undefined; + } + /** + * Removes all listeners, or those of the specified event. + * + */ + async removeAllListeners(eventType) { + const removeByEvent = async (event) => { + const emitter = await this.deregisterAllListeners(event); + if (emitter) { + emitter.removeAllListeners(event); + this.deleteEmitterIfNothingRegistered(emitter); + } + }; + if (eventType) { + await removeByEvent(eventType); + } + else if (this.hasEmitter()) { + const events = this.getOrCreateEmitter().eventNames(); + await (0, promises_1.promiseMap)(events, removeByEvent); + } + return this; + } + deleteEmitterIfNothingRegistered(emitter) { + if (emitter.eventNames().length === 0) { + this.wire.eventAggregator.delete(__classPrivateFieldGet$e(this, _EmitterBase_emitterAccessor, "f")); + } + } +} +base.EmitterBase = EmitterBase; +_EmitterBase_emitterAccessor = new WeakMap(); +class Reply { +} +base.Reply = Reply; + +var transportErrors = {}; + +Object.defineProperty(transportErrors, "__esModule", { value: true }); +transportErrors.RuntimeError = transportErrors.NotSupportedError = transportErrors.NotImplementedError = transportErrors.NoAckError = transportErrors.DuplicateCorrelationError = transportErrors.UnexpectedActionError = transportErrors.DisconnectedError = void 0; +class DisconnectedError extends Error { + constructor(readyState) { + super(`Expected websocket state OPEN but found ${readyState}`); + this.readyState = readyState; + } +} +transportErrors.DisconnectedError = DisconnectedError; +class UnexpectedActionError extends Error { +} +transportErrors.UnexpectedActionError = UnexpectedActionError; +class DuplicateCorrelationError extends Error { +} +transportErrors.DuplicateCorrelationError = DuplicateCorrelationError; +class NoAckError extends Error { +} +transportErrors.NoAckError = NoAckError; +class NotImplementedError extends Error { +} +transportErrors.NotImplementedError = NotImplementedError; +class NotSupportedError extends Error { +} +transportErrors.NotSupportedError = NotSupportedError; +class InternalError extends Error { + constructor(err) { + const { message, name, stack, ...rest } = err; + super(message); + this.name = name || 'Error'; + this.stack = stack ?? this.toString(); + Object.keys(rest).forEach(key => { + this[key] = rest[key]; + }); + } +} +// For documentation of the error methods being used see here: https://v8.dev/docs/stack-trace-api +class RuntimeError extends Error { + static getCallSite(callsToRemove = 0) { + const length = Error.stackTraceLimit; + const realCallsToRemove = callsToRemove + 1; // remove this call; + Error.stackTraceLimit = length + realCallsToRemove; + // eslint-disable-next-line no-underscore-dangle + const _prepareStackTrace = Error.prepareStackTrace; + // This will be called when we access the `stack` property + Error.prepareStackTrace = (_, stack) => stack; + // stack is optional in non chromium contexts + const stack = new Error().stack?.slice(realCallsToRemove) ?? []; + Error.prepareStackTrace = _prepareStackTrace; + Error.stackTraceLimit = length; + return stack; + } + static prepareStackTrace(err, callSites) { + if (typeof Error.prepareStackTrace === 'function') { + return Error.prepareStackTrace(err, callSites); + } + let string = ""; + string += err.name || "Error"; + string += `: ${err.message || ""}`; + for (const callSite of callSites) { + string += `\n at ${callSite.toString()}`; + } + return string; + } + ; + constructor(payload, callSites) { + const { reason, error } = payload; + super(reason); + this.name = 'RuntimeError'; + if (error?.stack) { + this.cause = new InternalError(error); + } + if (callSites) { + this.stack = RuntimeError.prepareStackTrace(this, callSites); + } + } +} +transportErrors.RuntimeError = RuntimeError; + +var window$1 = {}; + +var Factory$8 = {}; + +var validate = {}; + +Object.defineProperty(validate, "__esModule", { value: true }); +validate.validateIdentity = void 0; +function validateIdentity(identity) { + let errorMsg; + if (typeof identity !== 'object' || typeof identity.uuid !== 'string') { + errorMsg = 'Not a valid identity object'; + } + return errorMsg; +} +validate.validateIdentity = validateIdentity; + +var Instance$7 = {}; + +var application = {}; + +var Factory$7 = {}; + +var Instance$6 = {}; + +var view = {}; + +var Factory$6 = {}; + +var warnings = {}; + +Object.defineProperty(warnings, "__esModule", { value: true }); +warnings.handleDeprecatedWarnings = void 0; +const handleDeprecatedWarnings = (options) => { + if (options.contentNavigation?.whitelist || + options.contentNavigation?.blacklist || + options.contentRedirect?.whitelist || + options.contentRedirect?.blacklist) { + console.warn(`The properties 'whitelist' and 'blacklist' have been marked as deprecated and will be removed in a future version. Please use 'allowlist' and 'denylist'.`); + } +}; +warnings.handleDeprecatedWarnings = handleDeprecatedWarnings; + +var hasRequiredFactory$3; + +function requireFactory$3 () { + if (hasRequiredFactory$3) return Factory$6; + hasRequiredFactory$3 = 1; + Object.defineProperty(Factory$6, "__esModule", { value: true }); + Factory$6.ViewModule = void 0; + const base_1 = base; + const validate_1 = validate; + const index_1 = requireView(); + const warnings_1 = warnings; + /** + * Static namespace for OpenFin API methods that interact with the {@link View} class, available under `fin.View`. + */ + class ViewModule extends base_1.Base { + /** + * Creates a new View. + * @param options - View creation options + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameCreate', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * createView() + * .then((createdView) => { + * view = createdView; + * console.log('View created.', view); + * view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * }) + * .catch(err => console.log(err)); + * ``` + * Note that created views needs to navigate somewhere for them to actually render a website. + * @experimental + */ + async create(options) { + const { uuid } = this.wire.me; + if (!options.name || typeof options.name !== 'string') { + throw new Error('Please provide a name property as a string in order to create a View.'); + } + (0, warnings_1.handleDeprecatedWarnings)(options); + if (this.wire.environment.childViews) { + await this.wire.environment.createChildContent({ + entityType: 'view', + options: { ...options, uuid } + }); + } + else { + await this.wire.sendAction('create-view', { ...options, uuid }); + } + return this.wrapSync({ uuid, name: options.name }); + } + /** + * Asynchronously returns an API handle for the given View identity. + * + * @remarks Wrapping a View identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a View throughout its entire lifecycle. + * + * @example + * ```js + * fin.View.wrap({ uuid: 'testViewUuid', name: 'testViewName' })) + * .then(view => console.log('wrapped view', view)) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + async wrap(identity) { + this.wire.sendAction('view-wrap').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new index_1.View(this.wire, identity); + } + /** + * Synchronously returns an API handle for the given View identity. + * + * @remarks Wrapping a View identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a View throughout its entire lifecycle. + * + * @example + * ```js + * const view = fin.View.wrapSync({ uuid: 'testView', name: 'testViewName' }); + * await view.hide(); + * ``` + * @experimental + */ + wrapSync(identity) { + this.wire.sendAction('view-wrap-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new index_1.View(this.wire, identity); + } + /** + * Asynchronously returns a View object that represents the current view + * + * @example + * ```js + * fin.View.getCurrent() + * .then(view => console.log('current view', view)) + * .catch(err => console.log(err)); + * + * ``` + * @experimental + */ + getCurrent() { + this.wire.sendAction('view-get-current').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (!this.wire.me.isView) { + throw new Error('You are not in a View context'); + } + const { uuid, name } = this.wire.me; + return this.wrap({ uuid, name }); + } + /** + * Synchronously returns a View object that represents the current view + * + * @example + * ```js + * const view = fin.View.getCurrentSync(); + * console.log(view); + * + * ``` + * @experimental + */ + getCurrentSync() { + this.wire.sendAction('view-get-current-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (!this.wire.me.isView) { + throw new Error('You are not in a View context'); + } + const { uuid, name } = this.wire.me; + return this.wrapSync({ uuid, name }); + } + } + Factory$6.ViewModule = ViewModule; + return Factory$6; +} + +var Instance$5 = {}; + +var lazy = {}; + +Object.defineProperty(lazy, "__esModule", { value: true }); +lazy.AsyncRetryableLazy = lazy.Lazy = void 0; +/** + * Handy class for managing asynchronous dependencies of classes. + * + * Will call the producer function once and only once when getValue is called, + * returning the resultant value for every subsequent call. + */ +class Lazy { + // eslint-disable-next-line + constructor(producerFn) { + this.producerFn = producerFn; + } + /** + * Lazily get the value returned by the producer. + * @returns The value returned from the producer function + */ + getValue() { + if (!this.value) { + this.value = this.producerFn(); + } + return this.value; + } +} +lazy.Lazy = Lazy; +/** + * Handy class for managing asynchronous dependencies of classes. + * + * Will call asynchronous producer only after `getValue` is called. If the + * deferred code errors, we can try it again by re-calling `getValue` after + * the promise rejects. + */ +class AsyncRetryableLazy { + // eslint-disable-next-line + constructor(producerFn) { + this.producerFn = producerFn; + } + /** + * Lazily get the value returned by the async producer. + * + * @returns The value returned from the producer function + */ + async getValue() { + if (!this.promise) { + this.promise = this.producerFn().catch((e) => { + delete this.promise; + throw e; + }); + } + return this.promise; + } +} +lazy.AsyncRetryableLazy = AsyncRetryableLazy; + +var layoutEntities = {}; + +var apiExposer$1 = {}; + +var apiConsumer = {}; + +Object.defineProperty(apiConsumer, "__esModule", { value: true }); +apiConsumer.ApiConsumer = void 0; +/** + * Consumer for apis exposed with {@see ApiExposer}. + * + * A strategy that matches the strategy used to expose a target API must be provided. + */ +class ApiConsumer { + // eslint-disable-next-line + constructor(strategy) { + this.strategy = strategy; + /** + * Consumes an api exposed using a given transport strategy, and generates a client + * for easy, type safe consumption of that client. + * @param options Strategy specific consumption options. + * @returns An api client matching the given type. + */ + this.consume = async (options) => { + const exposedProperties = await this.strategy.getExposedFunctions(options); + return exposedProperties.reduce((client, prop) => ({ + ...client, + [prop.key]: this.strategy.createFunction(prop, options) + }), {}); + }; + } +} +apiConsumer.ApiConsumer = ApiConsumer; + +var apiExposer = {}; + +var decorators = {}; + +Object.defineProperty(decorators, "__esModule", { value: true }); +decorators.expose = decorators.getExposedProperties = void 0; +const exposedProperties = Symbol('exposedProperties'); +const getExposedProperties = (target) => { + return target[exposedProperties] || target.prototype[exposedProperties] || []; +}; +decorators.getExposedProperties = getExposedProperties; +/** + * Indicates that a class member function can be exposed using {@link ApiExposer}. + * @param options Options specific to the strategy used in {@link ApiExposer} + */ +// Returns any as decorator typing is weird. +const expose = (options) => (target, key, descriptor) => { + target[exposedProperties] = target[exposedProperties] || []; + target[exposedProperties].push({ key, descriptor, options }); +}; +decorators.expose = expose; + +Object.defineProperty(apiExposer, "__esModule", { value: true }); +apiExposer.ApiExposer = void 0; +const decorators_1 = decorators; +/** + * Exposes api services on the transport of choice. + */ +class ApiExposer { + /** + * @param strategy The expose strategy to use to expose instances. + */ + // eslint-disable-next-line + constructor(strategy) { + this.strategy = strategy; + /** + * Exposes an instance of a given api on + * @param instance Instance of a class which has been decorated to indicate which functions can be exposed. + * @param instanceOptions Transport strategy specific options to use when exposing. + */ + this.exposeInstance = async (instance, instanceOptions) => { + const exposableProps = (0, decorators_1.getExposedProperties)(instance); + const exposedProps = await Promise.all(exposableProps.map(async ({ key, options }) => { + const customConsumptionOptions = await this.strategy.exposeFunction(instance[key].bind(instance), { + key, + options, + meta: instanceOptions + }); + return { + key, + options: customConsumptionOptions + }; + })); + await this.strategy.exposeMeta(instanceOptions, exposedProps); + }; + } + ; +} +apiExposer.ApiExposer = ApiExposer; + +var strategies = {}; + +var openfinChannels = {}; + +var channelsConsumer = {}; + +Object.defineProperty(channelsConsumer, "__esModule", { value: true }); +channelsConsumer.ChannelsConsumer = void 0; +class ChannelsConsumer { + // eslint-disable-next-line + constructor(channel) { + this.channel = channel; + this.getExposedFunctions = async (options) => { + const { id } = options; + const { props } = await this.channel.dispatch(`api-meta:${id}`); + return props; + }; + this.createFunction = (prop) => (...args) => { + const { action } = prop.options; + return this.channel.dispatch(action, { args }); + }; + } + ; +} +channelsConsumer.ChannelsConsumer = ChannelsConsumer; + +var channelsExposer = {}; + +Object.defineProperty(channelsExposer, "__esModule", { value: true }); +channelsExposer.ChannelsExposer = void 0; +class ChannelsExposer { + // eslint-disable-next-line + constructor(channelProviderOrClient) { + this.channelProviderOrClient = channelProviderOrClient; + this.exposeFunction = async (target, config) => { + const { key, options, meta } = config; + const { id } = meta; + const action = `${id}.${options?.action || key}`; + await this.channelProviderOrClient.register(action, async ({ args }) => { + return target(...args); + }); + return { action }; + }; + this.exposeMeta = async ({ id }, props) => { + const action = `api-meta:${id}`; + await this.channelProviderOrClient.register(action, () => ({ props })); + }; + } +} +channelsExposer.ChannelsExposer = ChannelsExposer; + +(function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(channelsConsumer, exports); + __exportStar(channelsExposer, exports); +} (openfinChannels)); + +(function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(openfinChannels, exports); +} (strategies)); + +(function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(apiConsumer, exports); + __exportStar(apiExposer, exports); + __exportStar(strategies, exports); + __exportStar(decorators, exports); +} (apiExposer$1)); + +var channelApiRelay = {}; + +Object.defineProperty(channelApiRelay, "__esModule", { value: true }); +channelApiRelay.createRelayedDispatch = channelApiRelay.relayChannelClientApi = void 0; +const EXPECTED_ERRORS = [ + 'no longer connected', + 'RTCDataChannel closed unexpectedly', + 'The client you are trying to dispatch from is disconnected from the target provider', +]; +// Checks possible error messages that we want to trap, client error message can originate +// from ChannelProvider::dispatch OR ClassicStrategy::closeEndpoint OR RTCEndPoint::dataChannel::onclose +const isDisconnectedError = (errorMsg) => { + return EXPECTED_ERRORS.some(e => errorMsg.includes(e)); +}; +/** + * @internal + * Create a channel relay for a given channel exposition, allowing a single provider to route + * actions to the designated clients. + * + * Designed to be used in conjunction with @expose + * + * @param channelProvider The channel provider to relay the actions on. + * @param config Determines which actions to relay. Please ensure action prefix matches the exposed api. + */ +const relayChannelClientApi = async (channelProvider, relayId) => { + channelProvider.register(`relay:${relayId}`, ({ action, target, payload }) => { + return channelProvider.dispatch(target, action, payload); + }); + await Promise.resolve(); +}; +channelApiRelay.relayChannelClientApi = relayChannelClientApi; +const createRelayedDispatch = (client, target, relayId, relayErrorMsg) => async (action, payload) => { + try { + return await client.dispatch(`relay:${relayId}`, { + action, + payload, + target + }); + } + catch (e) { + if (isDisconnectedError(e.message) && relayErrorMsg) { + throw new Error(relayErrorMsg); + } + throw e; + } +}; +channelApiRelay.createRelayedDispatch = createRelayedDispatch; + +var __classPrivateFieldSet$b = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$d = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _LayoutNode_client, _TabStack_client, _ColumnOrRow_client; +Object.defineProperty(layoutEntities, "__esModule", { value: true }); +layoutEntities.ColumnOrRow = layoutEntities.TabStack = layoutEntities.LayoutNode = void 0; +const api_exposer_1 = apiExposer$1; +const channel_api_relay_1 = channelApiRelay; +/* + This file includes LayoutNode, ColumnOrRow and TabStack classes, which are all closely + intertwined, and share members via parent abstract class LayoutNode. To prevent circular + refs, we define and export all the classes here. +*/ +/** + * @ignore + * @internal + * Supplies an ApiClient for {@link LayoutEntitiesController} and helper methods + * for the entities {@link TabStack} AND {@link ColumnOrRow} to use. + */ +class LayoutNode { + /** + * @internal + * @ignore + */ + constructor(client, entityId) { + /** + * @ignore + * @internal + * ApiClient for {@link LayoutEntitiesController} + */ + _LayoutNode_client.set(this, void 0); + /** + * Checks if the TabStack or ColumnOrRow is the root content item + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * const isRoot = await stack.isRoot(); + * // The TabStack is root: false + * console.log(`The TabStack is root: ${isRoot}`); + * + * // Retrieves the parent ColumnOrRow + * const parent = await stack.getParent(); + * const parentIsRoot = await parent.isRoot(); + * // The parent ColumnOrRow is root: true + * console.log(`The parent ColumnOrRow is root: ${parentIsRoot}`); + * ``` + */ + this.isRoot = () => __classPrivateFieldGet$d(this, _LayoutNode_client, "f").isRoot(this.entityId); + /** + * Checks if the TabStack or ColumnOrRow exists + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Retrieves the parent ColumnOrRow + * const columnOrRow = await stack.getParent(); + * let exists = await stack.exists(); + * // or + * let exists = await columnOrRow.exists(); + * // The entity exists: true + * console.log(`The entity exists: ${exists}`); + * ``` + */ + this.exists = () => __classPrivateFieldGet$d(this, _LayoutNode_client, "f").exists(this.entityId); + /** + * Retrieves the parent of the TabStack or ColumnOrRow + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Retrieves the parent ColumnOrRow + * const columnOrRow = await stack.getParent(); + * + * // undefined if entity is the root item + * let parent = await columnOrRow.getParent(); + * // or + * let parent = await stack.getParent(); + * ``` + */ + this.getParent = async () => { + const parent = await __classPrivateFieldGet$d(this, _LayoutNode_client, "f").getParent(this.entityId); + if (!parent) { + return undefined; + } + return LayoutNode.getEntity(parent, __classPrivateFieldGet$d(this, _LayoutNode_client, "f")); + }; + /** + * Creates a new TabStack adjacent to the given TabStack or ColumnOrRow. Inputs can be new views to create, or existing views. + * + * Known Issue: If the number of views to add overflows the tab-container, the added views will be set as active + * during each render, and then placed at the front of the tab-stack, while the underlying order of tabs will remain unchanged. + * This means the views you pass to createAdjacentStack() may not render in the order given by the array. + * Until fixed, this problem can be avoided only if your window is wide enough to fit creating all the views in the tabstack. + * + * @param views The views that will populate the new TabStack. + * @param options Additional options that control new TabStack creation. + * @returns The newly-created TabStack. + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * const columnOrRow = await stack.getParent(); + * + * // Create view references by supplying a 'name' and 'url' + * const views = [ + * // if 'name' is undefined, one will be generated + * // if 'url' is undefined, it will default the view URL to 'about:blank' + * { name: 'google-view', url: 'http://google.com/'}, + * { name: 'of-developers-view', url: 'http://developers.openfin.co/'}, + * ]; + * + * // Create a view beforehand to be included in the new tab stack + * const outsideView = await fin.View.create({ + * name: 'outside-bloomberg-view', + * url: 'https://bloomberg.com/', + * target: fin.me.identity, + * }); + * + * // Views to add can be identities, or the reference views mentioned above + * const viewsToAdd = [outsideView.identity, ...views]; + * + * // Possible position inputs: 'right' | 'left' | 'top' | 'bottom' + * let stackFrom = await columnOrRow.createAdjacentStack(viewsToAdd, { position: 'right' }); + * // Or + * let newStack = await stack.createAdjacentStack(viewsToAdd, { position: 'right' }); + * console.log(`A new TabStack created to the right has ${newStack.length} views in it`); + * + * ``` + * @experimental + */ + this.createAdjacentStack = async (views, options) => { + const entityId = await __classPrivateFieldGet$d(this, _LayoutNode_client, "f").createAdjacentStack(this.entityId, views, options); + return LayoutNode.getEntity({ entityId, type: 'stack' }, __classPrivateFieldGet$d(this, _LayoutNode_client, "f")); + }; + /** + * Retrieves the adjacent TabStacks of the given TabStack or ColumnOrRow. + * + * @param edge Edge whose adjacent TabStacks will be returned. + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * const columnOrRow = await stack.getParent(); + * // Possible position inputs: 'right' | 'left' | 'top' | 'bottom' + * let rightStacks = await columnOrRow.getAdjacentStacks('right'); + * let leftStacks = await columnOrRow.getAdjacentStacks('left'); + * // or + * let rightStacks = await stack.getAdjacentStacks('right'); + * let leftStacks = await stack.getAdjacentStacks('left'); + * + * console.log(`The entity has ${rightStacks.length} stacks to the right, and ${leftStacks.length} stacks to the left`); + * + * ``` + * @experimental + */ + this.getAdjacentStacks = async (edge) => { + const adjacentStacks = await __classPrivateFieldGet$d(this, _LayoutNode_client, "f").getAdjacentStacks({ + targetId: this.entityId, + edge + }); + return adjacentStacks.map((stack) => LayoutNode.getEntity({ + type: 'stack', + entityId: stack.entityId + }, __classPrivateFieldGet$d(this, _LayoutNode_client, "f"))); + }; + __classPrivateFieldSet$b(this, _LayoutNode_client, client, "f"); + this.entityId = entityId; + } +} +layoutEntities.LayoutNode = LayoutNode; +_LayoutNode_client = new WeakMap(); +/** + * @ignore + * @internal + * Encapsulates Api consumption of {@link LayoutEntitiesClient} with a relayed dispatch + * @param client + * @param controllerId + * @param identity + * @returns a new instance of {@link LayoutEntitiesClient} with bound to the controllerId + */ +LayoutNode.newLayoutEntitiesClient = async (client, controllerId, identity) => { + const dispatch = (0, channel_api_relay_1.createRelayedDispatch)(client, identity, 'layout-relay', 'You are trying to interact with a layout component on a window that does not exist or has been destroyed.'); + const consumer = new api_exposer_1.ApiConsumer(new api_exposer_1.ChannelsConsumer({ dispatch })); + return consumer.consume({ id: controllerId }); +}; +LayoutNode.getEntity = (definition, client) => { + const { entityId, type } = definition; + switch (type) { + case 'column': + case 'row': + return new ColumnOrRow(client, entityId, type); + case 'stack': + return new TabStack(client, entityId); + default: + throw new Error(`Unrecognised Layout Entity encountered ('${JSON.stringify(definition)})`); + } +}; +/** + * A TabStack is used to manage the state of a stack of tabs within an OpenFin Layout. + */ +class TabStack extends LayoutNode { + /** @internal */ + constructor(client, entityId) { + super(client, entityId); + /** + * @internal + * ApiClient for {@link LayoutEntitiesController} + */ + _TabStack_client.set(this, void 0); + /** + * Type of the content item. Always stack, but useful for distinguishing between a {@link TabStack} and {@link ColumnOrRow}. + */ + this.type = 'stack'; + /** + * Retrieves a list of all views belonging to this {@link TabStack}. + * + * Known Issue: If adding a view overflows the tab-container width, the added view will be set as active + * and rendered at the front of the tab-stack, while the underlying order of tabs will remain unchanged. + * If that happens and then getViews() is called, it will return the identities in a different order than + * than the currently rendered tab order. + * + * + * @throws If the {@link TabStack} has been destroyed. + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Alternatively, you can wrap any view and get the stack from there + * // const viewFromSomewhere = fin.View.wrapSync(someView.identity); + * // const stack = await viewFromSomewhere.getCurrentStack(); + * const views = await stack.getViews(); + * console.log(`Stack contains ${views.length} view(s)`); + * ``` + * @experimental + */ + this.getViews = () => __classPrivateFieldGet$d(this, _TabStack_client, "f").getStackViews(this.entityId); + /** + * Adds or creates a view in this {@link TabStack}. + * + * @remarks Known Issue: If adding a view overflows the tab-container, the added view will be set as active + * and rendered at the front of the tab-stack, while the underlying order of tabs will remain unchanged. + * + * @param view The identity of an existing view to add, or options to create a view. + * @param options Optional view options: index number used to insert the view into the stack at that index. Defaults to 0 (front of the stack) + * @returns Resolves with the {@link OpenFin.Identity identity} of the added view. + * @throws If the view does not exist or fails to create. + * @throws If the {@link TabStack} has been destroyed. + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Alternatively, you can wrap any view and get the stack from there + * // const viewFromSomewhere = fin.View.wrapSync(someView.identity); + * // const stack = await viewFromSomewhere.getCurrentStack(); + * const googleViewIdentity = await stack.addView({ name: 'google-view', url: 'http://google.com/' }); + * console.log('Identity of the google view just added', { googleViewIdentity }); + * // pass in { index: number } to set the index in the stack. Here 1 means, end of the stack (defaults to 0) + * const appleViewIdentity = await stack.addView({ name: 'apple-view', url: 'http://apple.com/' }, { index: 1 }); + * console.log('Identity of the apple view just added', { appleViewIdentity }); + * ``` + * @experimental + */ + this.addView = async (view, options = { index: 0 }) => __classPrivateFieldGet$d(this, _TabStack_client, "f").addViewToStack(this.entityId, view, options); + /** + * Removes a view from this {@link TabStack}. + * + * @remarks Throws an exception if the view identity does not exist or was already destroyed. + * + * @param view - Identity of the view to remove. + * @throws If the view does not exist or does not belong to the stack. + * @throws If the {@link TabStack} has been destroyed. + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * const googleViewIdentity = await stack.addView({ name: 'google-view', url: 'http://google.com/' }); + * + * await stack.removeView(googleViewIdentity); + * + * try { + * await stack.removeView(googleViewIdentity); + * } catch (error) { + * // Tried to remove a view ('google-view') which does not belong to the stack. + * console.log(error); + * } + * ``` + */ + this.removeView = async (view) => { + await __classPrivateFieldGet$d(this, _TabStack_client, "f").removeViewFromStack(this.entityId, view); + }; + /** + * Sets the active view of the {@link TabStack} without focusing it. + * @param view - Identity of the view to activate. + * @returns Promise which resolves with void once the view has been activated. + * @throws If the {@link TabStack} has been destroyed. + * @throws If the view does not exist. + * @example + * Change the active tab of a known View's TabStack: + * ```js + * const targetView = fin.View.wrapSync({ uuid: 'uuid', name: 'view-name' }); + * const stack = await targetView.getCurrentStack(); + * await stack.setActiveView(targetView.identity); + * ``` + * + * Set the current View as active within its TabStack: + * ```js + * const stack = await fin.me.getCurrentStack(); + * await stack.setActiveView(fin.me.identity); + * ``` + * @experimental + */ + this.setActiveView = async (view) => { + await __classPrivateFieldGet$d(this, _TabStack_client, "f").setStackActiveView(this.entityId, view); + }; + __classPrivateFieldSet$b(this, _TabStack_client, client, "f"); + } +} +layoutEntities.TabStack = TabStack; +_TabStack_client = new WeakMap(); +/** + * A ColumnOrRow is used to manage the state of Column and Rows within an OpenFin Layout. + */ +class ColumnOrRow extends LayoutNode { + /** + * @internal + */ + constructor(client, entityId, type) { + super(client, entityId); + /** + * @ignore + * @internal + * ApiClient for {@link LayoutEntitiesController} + */ + _ColumnOrRow_client.set(this, void 0); + /** + * Retrieves the content array of the ColumnOrRow + * + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Retrieves the parent ColumnOrRow + * const columnOrRow = await stack.getParent(); + * + * // returns [TabStack] + * const contentArray = await columnOrRow.getContent(); + * console.log(`The ColumnOrRow has ${contentArray.length} item(s)`); + * ``` + */ + this.getContent = async () => { + const contentItemEntities = await __classPrivateFieldGet$d(this, _ColumnOrRow_client, "f").getContent(this.entityId); + return contentItemEntities.map((entity) => LayoutNode.getEntity(entity, __classPrivateFieldGet$d(this, _ColumnOrRow_client, "f"))); + }; + __classPrivateFieldSet$b(this, _ColumnOrRow_client, client, "f"); + this.type = type; + } +} +layoutEntities.ColumnOrRow = ColumnOrRow; +_ColumnOrRow_client = new WeakMap(); + +var layout_constants = {}; + +Object.defineProperty(layout_constants, "__esModule", { value: true }); +layout_constants.DEFAULT_LAYOUT_KEY = layout_constants.LAYOUT_CONTROLLER_ID = void 0; +layout_constants.LAYOUT_CONTROLLER_ID = 'layout-entities'; +// TODO: eventually export this somehow +layout_constants.DEFAULT_LAYOUT_KEY = '__default__'; + +var main = {}; + +Object.defineProperty(main, "__esModule", { value: true }); +main.WebContents = void 0; +const base_1$j = base; +class WebContents extends base_1$j.EmitterBase { + /** + * @param identity The identity of the {@link OpenFin.WebContentsEvents WebContents}. + * @param entityType The type of the {@link OpenFin.WebContentsEvents WebContents}. + */ + constructor(wire, identity, entityType) { + super(wire, entityType, identity.uuid, identity.name); + this.identity = identity; + this.entityType = entityType; + } + /** + * Gets a base64 encoded image of all or part of the WebContents. + * @param options Options for the capturePage call. + * + * @example + * + * View: + * ```js + * const view = fin.View.getCurrentSync(); + * + * // PNG image of a full visible View + * console.log(await view.capturePage()); + * + * // Low-quality JPEG image of a defined visible area of the view + * const options = { + * area: { + * height: 100, + * width: 100, + * x: 10, + * y: 10, + * }, + * format: 'jpg', + * quality: 20 + * } + * console.log(await view.capturePage(options)); + * ``` + * + * Window: + * ```js + * const wnd = await fin.Window.getCurrent(); + * + * // PNG image of a full visible window + * console.log(await wnd.capturePage()); + * + * // Low-quality JPEG image of a defined visible area of the window + * const options = { + * area: { + * height: 100, + * width: 100, + * x: 10, + * y: 10, + * }, + * format: 'jpg', + * quality: 20 + * } + * console.log(await wnd.capturePage(options)); + * ``` + * + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + capturePage(options) { + return this.wire.sendAction('capture-page', { options, ...this.identity }).then(({ payload }) => payload.data); + } + /** + * Executes Javascript on the WebContents, restricted to contents you own or contents owned by + * applications you have created. + * @param code JavaScript code to be executed on the view. + * + * @example + * View: + * ```js + * async function executeJavaScript(code) { + * const view = await fin.View.wrap({uuid: 'uuid', name: 'view name'}); + * return await view.executeJavaScript(code); + * } + * + * executeJavaScript(`console.log('Hello, Openfin')`).then(() => console.log('Javascript excuted')).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function executeJavaScript(code) { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.executeJavaScript.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.executeJavaScript(code); + * } + * + * executeJavaScript(`console.log('Hello, Openfin')`).then(() => console.log('Javascript excuted')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + executeJavaScript(code) { + return this.wire + .sendAction('execute-javascript-in-window', { ...this.identity, code }) + .then(({ payload }) => payload.data); + } + /** + * Returns the zoom level of the WebContents. + * + * @example + * View: + * ```js + * async function getZoomLevel() { + * const view = await fin.View.getCurrent(); + * return await view.getZoomLevel(); + * } + * + * getZoomLevel().then(zoomLevel => console.log(zoomLevel)).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getZoomLevel.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function getZoomLevel() { + * const win = await createWin(); + * return await win.getZoomLevel(); + * } + * + * getZoomLevel().then(zoomLevel => console.log(zoomLevel)).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + getZoomLevel() { + return this.wire.sendAction('get-zoom-level', this.identity).then(({ payload }) => payload.data); + } + /** + * Sets the zoom level of the WebContents. + * @param level The zoom level + * + * @example + * View: + * ```js + * async function setZoomLevel(number) { + * const view = await fin.View.getCurrent(); + * return await view.setZoomLevel(number); + * } + * + * setZoomLevel(4).then(() => console.log('Setting a zoom level')).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.setZoomLevel.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function setZoomLevel(number) { + * const win = await createWin(); + * return await win.setZoomLevel(number); + * } + * + * setZoomLevel(4).then(() => console.log('Setting a zoom level')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + setZoomLevel(level) { + return this.wire.sendAction('set-zoom-level', { ...this.identity, level }).then(() => undefined); + } + /** + * Navigates the WebContents to a specified URL. + * + * Note: The url must contain the protocol prefix such as http:// or https://. + * @param url - The URL to navigate the WebContents to. + * + * @example + * View: + * ```js + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewName', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * createView() + * .then(view => view.navigate('https://example.com')) + * .then(() => console.log('navigation complete')) + * .catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function navigate() { + * const win = await fin.Window.getCurrent(); + * return await win.navigate('https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.navigate.html'); + * } + * navigate().then(() => console.log('Navigate to tutorial')).catch(err => console.log(err)); + * ``` + * @experimental + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + navigate(url) { + return this.wire.sendAction('navigate-window', { ...this.identity, url }).then(() => undefined); + } + /** + * Navigates the WebContents back one page. + * + * @example + * View: + * ```js + * async function navigateBack() { + * const view = await fin.View.wrap({ name: 'testapp-view', uuid: 'testapp' }); + * await view.navigate('https://www.google.com'); + * return await view.navigateBack(); + * } + * navigateBack().then(() => console.log('Navigated back')).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function navigateBack() { + * const win = await fin.Window.wrap({ name: 'testapp', uuid: 'testapp' }); + * await win.navigate('https://www.google.com'); + * return await win.navigateBack(); + * } + * navigateBack().then(() => console.log('Navigated back')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + navigateBack() { + return this.wire.sendAction('navigate-window-back', { ...this.identity }).then(() => undefined); + } + /** + * Navigates the WebContents forward one page. + * + * @example + * View: + * ```js + * async function navigateForward() { + * const view = await fin.View.getCurrent(); + * await view.navigate('https://www.google.com'); + * await view.navigateBack(); + * return await view.navigateForward(); + * } + * navigateForward().then(() => console.log('Navigated forward')).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function navigateForward() { + * const win = await fin.Window.getCurrent(); + * await win.navigate('https://www.google.com'); + * await win.navigateBack(); + * return await win.navigateForward(); + * } + * navigateForward().then(() => console.log('Navigated forward')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async navigateForward() { + await this.wire.sendAction('navigate-window-forward', { ...this.identity }); + } + /** + * Stops any current navigation the WebContents is performing. + * + * @example + * View: + * ```js + * async function stopNavigation() { + * const view = await fin.View.wrap({ name: 'testapp-view', uuid: 'testapp' }); + * await view.navigate('https://www.google.com'); + * return await view.stopNavigation(); + * } + * stopNavigation().then(() => console.log('you shall not navigate')).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function stopNavigation() { + * const win = await fin.Window.wrap({ name: 'testapp', uuid: 'testapp' }); + * await win.navigate('https://www.google.com'); + * return await win.stopNavigation(); + * } + * stopNavigation().then(() => console.log('you shall not navigate')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + stopNavigation() { + return this.wire.sendAction('stop-window-navigation', { ...this.identity }).then(() => undefined); + } + /** + * Reloads the WebContents + * + * @example + * View: + * ```js + * async function reload() { + * const view = await fin.View.getCurrent(); + * return await view.reload(); + * } + * + * reload().then(() => { + * console.log('Reloaded view') + * }).catch(err => console.log(err)); + * ``` + * + * Window: + * ```js + * async function reloadWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.reload.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.reload(); + * } + * + * reloadWindow().then(() => { + * console.log('Reloaded window') + * }).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + reload(ignoreCache = false) { + return this.wire + .sendAction('reload-window', { + ignoreCache, + ...this.identity + }) + .then(() => undefined); + } + /** + * Prints the WebContents. + * @param options Printer Options + * + * Note: When `silent` is set to `true`, the API will pick the system's default printer if deviceName + * is empty and the default settings for printing. + * + * Use the CSS style `page-break-before: always;` to force print to a new page. + * + * @example + * ```js + * const view = fin.View.getCurrentSync(); + * + * view.print({ silent: false, deviceName: 'system-printer-name' }).then(() => { + * console.log('print call has been sent to the system'); + * }); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + print(options = {}) { + return this.wire.sendAction('print', { ...this.identity, options }).then(() => undefined); + } + /** + * Find and highlight text on a page. + * @param searchTerm Term to find in page + * @param options Search options + * + * Note: By default, each subsequent call will highlight the next text that matches the search term. + * + * Returns a promise with the results for the request. By subscribing to the + * found-in-page event, you can get the results of this call as well. + * + * @example + * View: + * ```js + * const view = fin.View.getCurrentSync(); + * + * //By subscribing to the 'found in page' event we can get the results of each findInPage call made. + * view.addListener('found-in-page', (event) => { + * console.log(event); + * }); + * + * // The promise also returns the results for the request + * view.findInPage('a').then((result) => { + * console.log(result) + * }); + * ``` + * + * Window: + * ```js + * const win = fin.Window.getCurrentSync(); + * + * //By subscribing to the 'found in page' event we can get the results of each findInPage call made. + * win.addListener('found-in-page', (event) => { + * console.log(event); + * }); + * + * // The promise also returns the results for the request + * win.findInPage('a').then((result) => { + * console.log(result) + * }); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + findInPage(searchTerm, options) { + return this.wire + .sendAction('find-in-page', { ...this.identity, searchTerm, options }) + .then(({ payload }) => payload.data); + } + /** + * Stop a {@link View#findInPage findInPage} call by specifying any of these actions: + * + * * clearSelection - Clear the selection. + * * keepSelection - Translate the selection into a normal selection. + * * activateSelection - Focus and click the selection node. + * + * @example + * View: + * ```js + * const view = fin.View.getCurrentSync(); + * + * view.addListener('found-in-page', (event) => { + * setTimeout(() => { + * view.stopFindInPage('clearSelection'); + * }, 5000); + * }); + * + * view.findInPage('a').then(results => { + * console.log(results); + * }); + * ``` + * + * Window: + * ```js + * const win = fin.Window.getCurrentSync(); + * + * win.addListener('found-in-page', (event) => { + * setTimeout(() => { + * win.stopFindInPage('clearSelection'); + * }, 5000); + * }); + * + * win.findInPage('a').then(results => { + * console.log(results); + * }); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + stopFindInPage(action) { + return this.wire.sendAction('stop-find-in-page', { ...this.identity, action }).then(() => undefined); + } + /** + * Returns an array with all system printers + * @deprecated use System.getPrinters instead + * + * @example + * View: + * ```js + * const view = fin.View.getCurrentSync(); + * + * view.getPrinters() + * .then((printers) => { + * printers.forEach((printer) => { + * if (printer.isDefault) { + * console.log(printer); + * } + * }); + * }) + * .catch((err) => { + * console.log(err); + * }); + * ``` + * + * Window: + * ```js + * const win = fin.Window.getCurrentSync(); + * + * win.getPrinters() + * .then((printers) => { + * printers.forEach((printer) => { + * if (printer.isDefault) { + * console.log(printer); + * } + * }); + * }) + * .catch((err) => { + * console.log(err); + * }); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + getPrinters() { + return this.wire.sendAction('get-printers', { ...this.identity }).then(({ payload }) => payload.data); + } + /** + * Gives focus to the WebContents. + * + * @example + * ```js + * async function focusWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.focus.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.focus(); + * } + * + * focusWindow().then(() => console.log('Window focused')).catch(err => console.log(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async focus({ emitSynthFocused } = { emitSynthFocused: true }) { + await this.wire.sendAction('focus-window', { emitSynthFocused, ...this.identity }); + } + /** + * Shows the Chromium Developer Tools + * + * @example + * View: + * ```js + * async function showDeveloperTools() { + * const view = await fin.View.getCurrent(); + * return view.showDeveloperTools(); + * } + * + * showDevelopertools() + * .then(() => console.log('Showing dev tools')) + * .catch(err => console.error(err)); + * ``` + * + * Window: + * ```js + * async function showDeveloperTools() { + * const win = await fin.Window.getCurrent(); + * return win.showDeveloperTools(); + * } + * + * showDevelopertools() + * .then(() => console.log('Showing dev tools')) + * .catch(err => console.error(err)); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async showDeveloperTools() { + // Note this hits the system action map in core state for legacy reasons. + await this.wire.sendAction('show-developer-tools', this.identity); + } + /** + * Retrieves the process information associated with a WebContents. + * + * Note: This includes any iframes associated with the WebContents + * + * @example + * View: + * ```js + * const view = await fin.View.getCurrent(); + * const processInfo = await view.getProcessInfo(); + * ``` + * + * Window: + * ```js + * const win = await fin.Window.getCurrent(); + * const processInfo = await win.getProcessInfo(); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async getProcessInfo() { + const { payload: { data } } = await this.wire.sendAction('get-process-info', this.identity); + return data; + } + /** + * Retrieves information on all Shared Workers. + * + * @example + * View: + * ```js + * const view = await fin.View.create({ + * name: 'viewName', + * target: fin.me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * + * await view.navigate('https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/'); + * + * const sharedWorkers = await view.getSharedWorkers(); + * ``` + * + * Window: + * ```js + * const winOption = { + * name:'child', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/', + * frame: true, + * autoShow: true + * }; + * const win = await fin.Window.create(winOption); + * const sharedWorkers = await win.getSharedWorkers(); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async getSharedWorkers() { + return this.wire.sendAction('get-shared-workers', this.identity).then(({ payload }) => payload.data); + } + /** + * Opens the developer tools for the shared worker context. + * + * @example + * View: + * ```js + * const view = await fin.View.create({ + * name: 'viewName', + * target: fin.me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * + * await view.navigate('https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/'); + * + * await view.inspectSharedWorker(); + * ``` + * + * Example: + * ```js + * const winOption = { + * name:'child', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/', + * frame: true, + * autoShow: true + * }; + * const win = await fin.Window.create(winOption); + * await win.inspectSharedWorker(); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async inspectSharedWorker() { + await this.wire.sendAction('inspect-shared-worker', { ...this.identity }); + } + /** + * Inspects the shared worker based on its ID. + * @param workerId - The id of the shared worker. + * + * @example + * View: + * ```js + * const view = await fin.View.create({ + * name: 'viewName', + * target: fin.me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * + * await view.navigate('https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/'); + * + * const sharedWorkers = await view.getSharedWorkers(); + * await view.inspectSharedWorkerById(sharedWorkers[0].id); + * ``` + * + * Window: + * ```js + * const winOption = { + * name:'child', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'https://mdn.github.io/dom-examples/web-workers/simple-shared-worker/', + * frame: true, + * autoShow: true + * }; + * const win = await fin.Window.create(winOption); + * const sharedWorkers = await win.getSharedWorkers(); + * await win.inspectSharedWorkerById(sharedWorkers[0].id); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async inspectSharedWorkerById(workerId) { + await this.wire.sendAction('inspect-shared-worker-by-id', { ...this.identity, workerId }); + } + /** + * Opens the developer tools for the service worker context. + * + * @example + * View: + * ```js + * const view = await fin.View.create({ + * name: 'viewName', + * target: fin.me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * + * await view.navigate('http://googlechrome.github.io/samples/service-worker/basic/index.html'); + * + * await view.inspectServiceWorker(); + * ``` + * + * Window: + * ```js + * const winOption = { + * name:'child', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'http://googlechrome.github.io/samples/service-worker/basic/index.html', + * frame: true, + * autoShow: true + * }; + * const win = await fin.Window.create(winOption); + * await win.inspectServiceWorker(); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async inspectServiceWorker() { + await this.wire.sendAction('inspect-service-worker', { ...this.identity }); + } + /** + * Shows a popup window. + * + * Note: If this WebContents is a view and its attached window has a popup open, this will close it. + * + * Shows a popup window. Including a `name` in `options` will attempt to show an existing window as a popup, if + * that window doesn't exist or no `name` is included a window will be created. If the caller view or the caller + * view's parent window currently has a popup window open, calling `showPopupWindow` again will dismiss the currently + * open popup window before showing the new popup window. Also, if the caller view is destroyed or detached, the popup + * will be dismissed. + * + * Note: in the case where the window being shown as a popup needs to be created, it is a child of the caller view's parent window. + * + * @example + * + * Create and show a single-use popup window that returns a single result to the caller. `initialOptions` allows + * us to pass window options to the popup window that will be created. `resultDispatchBehavior: 'close'` ensures + * that once the popup window calls `dispatchPopupResult` it is closed. `blurBehavior: 'close'` will yield a dismissed + * result should the popup window lose focus. + * + * ```js + * const result = await fin.me.showPopupWindow({ + * initialOptions: { + * frame: false + * }, + * url: '', + * resultDispatchBehavior: 'close', + * blurBehavior: 'close', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0 + * }); + * ``` + * + * Same as above but using an existing window as a popup by referencing its `name`: + * + * Note: if a window with the `name` provided doesn't exist, it will be created. + * + * ```js + * const result = await fin.me.showPopupWindow({ + * initialOptions: { + * frame: true + * }, + * name: 'my-popup', // shows the 'my-popup' window if it exists, otherwise creates it + * url: '', // navigates to this url if it doesn't match the location.href of the 'my-popup' window + * resultDispatchBehavior: 'close', + * blurBehavior: 'close', + * focus: true, + * hideOnClose: true, // persist window on 'dismissed' result, alternatively change onResultDispatch and blurBehavior to 'hide' + * height: 300, + * width: 300, + * x: 0, + * y: 0 + * }); + * ``` + * + * Create and show a popup window that is able to return multiple results to the caller via an `onPopupResult` callback. Each + * time the popup window calls `dispatchPopupResult`, the callback will be executed on the result. Once the popup window is + * closed or hidden, the `showPopupWindow` promise will resolve with a `dismissed` result that will include the most recently + * dispatched result as `lastDispatchResult`: + * + * ```js + * const popupResultCallback = (payload) => { + * if (payload.result === 'clicked') { + * if (payload.data.topic === 'color-changed') { + * // do something like + * // setColor(payload.data.value); + * } + * } + * }; + * + * await fin.me.showPopupWindow({ + * initialOptions: { + * frame: false + * }, + * url: '', + * resultDispatchBehavior: 'none', + * blurBehavior: 'close', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0, + * onPopupResult: popupResultCallback + * }); + * ``` + * + * Same as above but using an existing window as a popup: + * + * ```js + * const popupResultCallback = (payload) => { + * if (payload.result === 'clicked') { + * if (payload.data.topic === 'color-changed') { + * // do something like + * // setColor(payload.data.value); + * } + * } + * }; + * + * await fin.me.showPopupWindow({ + * initialOptions: { + * frame: false + * }, + * name: 'my-popup', // shows the 'my-popup' window if it exists, otherwise creates it + * url: '', // navigates to this url if it doesn't match the location.href of the 'my-popup' window + * resultDispatchBehavior: 'none', + * blurBehavior: 'hide', + * focus: true, + * hideOnClose: true, // we can just use this or we can change blurBehavior to 'hide' + * height: 300, + * width: 300, + * x: 0, + * y: 0, + * onPopupResult: popupResultCallback + * }); + * ``` + * + * Create or show a popup window that disables user movement (positioning and resizing) in the caller + * view's parent window by using `blurBehavior: 'modal'`: + * + * ```js + * const result = await fin.me.showPopupWindow({ + * initialOptions: { + * frame: false + * }, + * url: '', + * resultDispatchBehavior: 'close', + * blurBehavior: 'modal', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0 + * }); + * ``` + * + * Create a popup window as a modal: + * + * Note: The only way to ensure true modal behavior is to create the window being shown as a popup with a + * `modalParentIdentity` that uses the caller view's parent window identity. + * + * ```js + * const result = await fin.me.showPopupWindow({ + * initialOptions: { + * frame: false, + * modalParentIdentity: fin.me.identity + * }, + * url: '', + * resultDispatchBehavior: 'close', + * blurBehavior: 'modal', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0 + * }); + * ``` + * + * Pass data to a popup window that is available when the popup is shown. + * + * Note: this is just one example for a use of `additionalOptions`, it can be used to update any updatable + * window options when creating or showing an existing window as a popup. + * + * ```js + * const result = await fin.me.showPopupWindow({ + * additionalOptions: { + * customData: { + * foo: 'bar' + * } + * }, + * url: '', + * resultDispatchBehavior: 'close', + * blurBehavior: 'close', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0 + * }); + * + * // Access from the popup window context like so: + * const { customData } = await fin.me.getOptions(); + * const { foo } = customData; + * ``` + * + * Execute a callback on the popup's OpenFin window when the popup is shown: + * + * ```js + * const popupWindowCallback = async (win) => { + * await win.flash(); + * }; + * + * const result = await fin.me.showPopupWindow({ + * url: '', + * resultDispatchBehavior: 'close', + * blurBehavior: 'close', + * focus: true, + * height: 300, + * width: 300, + * x: 0, + * y: 0, + * onPopupReady: popupWindowCallback; + * }); + * ``` + * @remarks + * `WebContents` refers to shared functionality between {@link OpenFin.Window} and {@link OpenFin.View}. + * We do not expose an explicit superclass for this functionality, but it does have its own + * {@link OpenFin.WebContentsEvents event namespace}. + */ + async showPopupWindow(options) { + this.wire.sendAction(`${this.entityType}-show-popup-window`, this.identity).catch(() => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (options?.onPopupReady) { + const readyListener = async ({ popupName }) => { + try { + const popupWindow = this.fin.Window.wrapSync({ uuid: this.fin.me.uuid, name: popupName }); + await options.onPopupReady(popupWindow); + } + catch (error) { + throw new Error(`Something went wrong during onPopupReady execution: ${error}`); + } + }; + // TODO: fix typing (internal) + // @ts-expect-error + await this.once('popup-ready', readyListener); + } + const { payload: tryCreatePayload } = await this.wire.sendAction('try-create-popup-window', { + options: { + ...options, + // Internal use only. + // @ts-expect-error + hasResultCallback: !!options?.onPopupResult, + hasReadyCallback: !!options?.onPopupReady + }, + ...this.identity + }); + const { data: { willOpen, options: popupOptions } } = tryCreatePayload; + if (willOpen) { + // Solve the issue where Interop in a popup window with non cross-origin url is not working(core-1076). + await this.fin.Window.create(popupOptions.initialOptions); + } + const normalizePopupResult = (payload) => { + const { name, uuid, result, data } = payload; + const popupResult = { + identity: { + name, + uuid + }, + result + }; + if (data) { + popupResult.data = data; + } + return popupResult; + }; + if (options?.onPopupResult) { + const dispatchResultListener = async (payload) => { + await options.onPopupResult(normalizePopupResult(payload)); + }; + const teardownListener = async () => { + // TODO: fix typing (internal) + // @ts-expect-error + await this.removeListener('popup-result', dispatchResultListener); + }; + // TODO: fix typing (internal) + // @ts-expect-error + await this.on('popup-result', dispatchResultListener); + // TODO: fix typing (internal) + // hilariously this does not need a ts-expect-error - this is gap in type soundness + // should investigate - probably due to `teardownListener` taking a void argument + // which might play nicely with the `never` type? huh... + await this.once('popup-teardown', teardownListener); + } + const { payload } = await this.wire.sendAction('show-popup-window', { + options: popupOptions, + ...this.identity + }); + return payload.data; + } +} +main.WebContents = WebContents; + +var hasRequiredInstance$2; + +function requireInstance$2 () { + if (hasRequiredInstance$2) return Instance$5; + hasRequiredInstance$2 = 1; + var __classPrivateFieldGet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + var _View_providerChannelClient; + Object.defineProperty(Instance$5, "__esModule", { value: true }); + Instance$5.View = void 0; + const transport_errors_1 = transportErrors; + const lazy_1 = lazy; + const layout_entities_1 = layoutEntities; + const layout_constants_1 = layout_constants; + const main_1 = main; + const window_1 = requireWindow(); + /** + * A View can be used to embed additional web content into a Window. + * It is like a child window, except it is positioned relative to its owning window. + * It has the ability to listen for {@link OpenFin.ViewEvents View-specific events}. + * + * By default, a View will try to share the same renderer process as other Views owned by its parent Application. + * To change that behavior, see the processAffinity {@link OpenFin.ViewOptions view option}. + * + * A View's lifecycle is tied to its owning window and can be re-attached to a different window at any point during its lifecycle. + */ + class View extends main_1.WebContents { + /** + * @internal + */ + constructor(wire, identity) { + super(wire, identity, 'view'); + this.identity = identity; + _View_providerChannelClient.set(this, new lazy_1.Lazy(() => { + const platform = this.fin.Platform.wrapSync(this.identity); + return platform.getClient(); + })); + /** + * Attaches the current view to the given window identity. + * Identity must be the identity of a window in the same application. + * This detaches the view from its current window, and sets the view to be destroyed when its new window closes. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameAttach', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function attachView() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * const winOption = { + * name:'winOptionName', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.create.html', + * frame: true, + * autoShow: true + * }; + * const newWindow = await fin.Window.create(winOption); + * view.attach(newWindow.identity); + * } + * + * attachView() + * .then(() => console.log('View attached to new window.')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.attach = async (target) => { + await this.wire.sendAction('attach-view', { target, ...this.identity }); + }; + /** + * Destroys the current view + * + * @example + * ```js + * const view = fin.View.wrapSync({ uuid: 'viewUuid', name: 'viewName' }); + * view.destroy(); + * ``` + * @experimental + */ + this.destroy = async () => { + await this.wire.sendAction('destroy-view', { ...this.identity }); + }; + /** + * Shows the current view if it is currently hidden. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameShow', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function hideAndShowView() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url option.'); + * + * await view.hide(); + * console.log("View hidden."); + * + * view.show(); + * console.log("View shown."); + * } + * + * hideAndShowView() + * .then(() => console.log('View hidden and shown.')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.show = async () => { + await this.wire.sendAction('show-view', { ...this.identity }); + }; + /** + * Sets the bounds (top, left, width, height) of the view relative to its window and shows it if it is hidden. + * This method ensures the view is both positioned and showing. It will reposition a visible view and both show and reposition a hidden view. + * + * @remarks View position is relative to the bounds of the window. + * ({top: 0, left: 0} represents the top left corner of the window) + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameSetBounds', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function showViewAt() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * await view.showAt({ + * top: 100, + * left: 100, + * width: 300, + * height: 300 + * }, { + * bringToFront : true + * }); + * } + * + * showViewAt() + * .then(() => console.log('View set to new bounds and shown.')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.showAt = async (bounds, options = {}) => { + await this.wire.sendAction('show-view-at', { bounds, ...this.identity, options }); + }; + /** + * Brings the specified view to the front of its current window. This ensures the view will be visible on top of any other views + * which have overlapping bounds with it. + * + * Please note, this is not a permanent action - when a new view is created or attached to the window, it will display on top of all other views + * in the window that share bounds with it. + */ + this.bringToFront = async () => { + await this.wire.sendAction('bring-view-to-front', { ...this.identity }); + }; + /** + * Hides the current view if it is currently visible. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameHide', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function hideView() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * await view.hide(); + * } + * + * hideView() + * .then(() => console.log('View hidden.')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.hide = async () => { + await this.wire.sendAction('hide-view', { ...this.identity }); + }; + /** + * Sets the bounds (top, left, width, height) of the view relative to its window. + * + * @remarks View position is relative to the bounds of the window. + * ({top: 0, left: 0} represents the top left corner of the window) + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameSetBounds', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function setViewBounds() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * await view.setBounds({ + * top: 100, + * left: 100, + * width: 300, + * height: 300 + * }); + * } + * + * setViewBounds() + * .then(() => console.log('View set to new bounds.')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.setBounds = async (bounds) => { + await this.wire.sendAction('set-view-bounds', { bounds, ...this.identity }); + }; + /** + * Gets the bounds (top, left, width, height) of the view relative to its window. + * + * @remarks View position is relative to the bounds of the window. + * ({top: 0, left: 0} represents the top left corner of the window) + * + * @example + * ```js + * const view = await fin.View.create({ + * name: 'viewNameSetBounds', + * target: fin.me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * + * await view.navigate('https://google.com'); + * + * await view.setBounds({ + * top: 100, + * left: 100, + * width: 300, + * height: 300 + * }); + * + * console.log(await view.getBounds()); + * ``` + * @experimental + */ + this.getBounds = async () => { + const ack = await this.wire.sendAction('get-view-bounds', { ...this.identity }); + return ack.payload.data; + }; + /** + * Gets the View's info. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameGetInfo', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function getViewInfo() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * return view.getInfo(); + * } + * + * getViewInfo() + * .then((info) => console.log('View info fetched.', info)) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.getInfo = async () => { + const ack = await this.wire.sendAction('get-view-info', { ...this.identity }); + return ack.payload.data; + }; + /** + * Retrieves the layout for the window the view is attached to. + * + * @example + * ```js + * //get the current View + * const view = await fin.View.getCurrent(); + * + * //get a reference to the Layout for the Window the view is part of + * const layout = await view.getParentLayout(); + * ``` + * @experimental + */ + this.getParentLayout = async () => { + this.wire.sendAction('view-get-parent-layout', { ...this.identity }).catch(() => { + // don't expose + }); + const layoutWindow = await this.getCurrentWindow(); + let layoutWindowIdentity = layoutWindow.identity; + // TODO: CORE-1857 - when we tearout active layout or drag a view out of a window, the above identity includes the whole window info. + if (layoutWindowIdentity.identity) { + layoutWindowIdentity = layoutWindowIdentity.identity; + } + try { + const providerChannelClient = await __classPrivateFieldGet(this, _View_providerChannelClient, "f").getValue(); + const client = await layout_entities_1.LayoutNode.newLayoutEntitiesClient(providerChannelClient, layout_constants_1.LAYOUT_CONTROLLER_ID, layoutWindowIdentity); + const layoutIdentity = await client.getLayoutIdentityForViewOrThrow(this.identity); + return this.fin.Platform.Layout.wrap(layoutIdentity); + } + catch (e) { + const allowedErrors = [ + 'No action registered at target for', + 'getLayoutIdentityForViewOrThrow is not a function' + ]; + if (!allowedErrors.some((m) => e.message.includes(m))) { + throw e; + } + // fallback logic for missing endpoint + return this.fin.Platform.Layout.wrap(layoutWindowIdentity); + } + }; + /** + * Gets the View's options. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * name: 'viewNameGetOptions', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function getViewOptions() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url.'); + * + * const me = await fin.Window.getCurrent(); + * view = fin.View.wrapSync({ uuid: me.identity.uuid, name: 'viewNameGetOptions' }); + * return view.getOptions(); + * } + * + * getViewOptions() + * .then((info) => console.log('View options fetched.', info)) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.getOptions = async () => { + return this.wire.sendAction('get-view-options', { ...this.identity }).then(({ payload }) => payload.data); + }; + /** + * Updates the view's options. + * + * @example + * ```js + * let view; + * async function createView() { + * const me = await fin.Window.getCurrent(); + * return fin.View.create({ + * url: 'https://google.com', + * name: 'viewNameUpdateOptions', + * target: me.identity, + * bounds: {top: 10, left: 10, width: 200, height: 200} + * }); + * } + * + * async function updateViewOptions() { + * view = await createView(); + * console.log('View created.'); + * + * await view.navigate('https://google.com'); + * console.log('View navigated to given url option.'); + * + * const newOptions = { autoResize: { + * width: true, + * horizontal: true + * }}; + * return view.updateOptions(newOptions); + * } + * + * updateViewOptions() + * .then(payload => console.log('View options updated: ', payload)) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + this.updateOptions = async (options) => { + return this.wire.sendAction('update-view-options', { options, ...this.identity }).then(() => undefined); + }; + /** + * Retrieves the window the view is currently attached to. + * + * @example + * ```js + * const view = fin.View.wrapSync({ uuid: 'viewUuid', name: 'viewName' }); + * view.getCurrentWindow() + * .then(win => console.log('current window', win)) + * .catch(err => console.log(err));) + * ``` + * @experimental + */ + this.getCurrentWindow = async () => { + const { payload: { data } } = await this.wire.sendAction('get-view-window', { ...this.identity }); + return new window_1._Window(this.wire, data); + }; + /** + * Retrieves the current {@link OpenFin.TabStack} of the view if it belongs to one. + * @returns this view belongs to. + * @throws if this view does not belong to a TabStack or if the window has been destroyed. + * @example + * ```js + * if (!fin.me.isView) { + * throw new Error('Not running in a platform View.'); + * } + * + * const stack = await fin.me.getCurrentStack(); + * // Alternatively, you can wrap any view and get the stack from there + * // const viewFromSomewhere = fin.View.wrapSync(someView.identity); + * // const stack = await viewFromSomewhere.getCurrentStack(); + * const views = await stack.getViews(); + * console.log(`Stack contains ${views.length} view(s)`); + * ``` + */ + this.getCurrentStack = async () => { + this.wire.sendAction('view-get-current-stack').catch(() => { + // don't expose + }); + try { + const layoutWindow = await this.getCurrentWindow(); + const providerChannelClient = await __classPrivateFieldGet(this, _View_providerChannelClient, "f").getValue(); + const client = await layout_entities_1.LayoutNode.newLayoutEntitiesClient(providerChannelClient, layout_constants_1.LAYOUT_CONTROLLER_ID, layoutWindow.identity); + const stackDefinition = (await client.getStackByView(this.identity)); + return layout_entities_1.LayoutNode.getEntity(stackDefinition, client); + } + catch (error) { + throw new transport_errors_1.RuntimeError({ reason: 'This view does not belong to a stack.', error }); + } + }; + /** + * Triggers the before-unload handler for the View, if one is set. + * + * @remarks Returns `true` if the handler is trying to prevent the View from unloading, and `false` if it isn't. + * Only enabled when setting enableBeforeUnload: true in your View options. If this option is not enabled it will + * always return false. + * + * This method is used internally by the Platform Provider to determine the status of each before unload handler in Views when closing the Window. + * + * @example + * + * ```js + * // from inside a View context + * const unloadPrevented = await fin.me.triggerBeforeUnload(); + * ``` + * + * @experimental + */ + this.triggerBeforeUnload = async () => { + const message = await this.wire.sendAction('trigger-before-unload', { ...this.identity }); + return message.payload.data; + }; + /** + * **NOTE**: Internal use only. + * Attaches this view to an HTML element in the current context. The view will resize responsively when the element bounds change. + * + * **Known issue**: View.bindToElement does not track position changes, if the element has fixed px width and height values it is possible for the view to not update responsively. + * + * **Known issue**: When View.bindToElement is used on a element that takes up the entire page in a platform window, the bound view will not respond responsively when the window is resized to be smaller. + * + * @param element - HTML element to attach the view to. + * @returns - Cleanup function that will disconnect the element resize observer. + * @internal + * @experimental + * @remarks View will resize accordingly when the element is resized. If the element is repositioned in the DOM the view will not be repositioned, to handle this case call `bindToElement` again once the element changes position. + * + * @example + * ```html + *
+ * + * ``` + */ + this.bindToElement = async (element) => { + if (!element) { + throw new Error('Element not found.'); + } + const onChange = async (bounds) => this.setBounds(bounds); + return this.wire.environment.observeBounds(element, onChange); + }; + } + /** + * Focuses the view + * + * @example + * ```js + * const view = fin.View.wrapSync({ uuid: 'viewUuid', name: 'viewName' }); + * await view.focus(); + * // do things with the focused view + * ``` + * @experimental + */ + async focus({ emitSynthFocused } = { emitSynthFocused: true }) { + const win = await this.getCurrentWindow(); + await win.focusedWebViewWasChanged(); + await super.focus({ emitSynthFocused }); + } + } + Instance$5.View = View; + _View_providerChannelClient = new WeakMap(); + return Instance$5; +} + +var hasRequiredView; + +function requireView () { + if (hasRequiredView) return view; + hasRequiredView = 1; + (function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + /** + * Entry points for the OpenFin `View` API (`fin.View`). + * + * * {@link ViewModule} contains static members of the `View` API, accessible through `fin.View`. + * * {@link View} describes an instance of an OpenFin View, e.g. as returned by `fin.View.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + */ + __exportStar(requireFactory$3(), exports); + __exportStar(requireInstance$2(), exports); + } (view)); + return view; +} + +var hasRequiredInstance$1; + +function requireInstance$1 () { + if (hasRequiredInstance$1) return Instance$6; + hasRequiredInstance$1 = 1; + Object.defineProperty(Instance$6, "__esModule", { value: true }); + Instance$6.Application = void 0; + /* eslint-disable import/prefer-default-export */ + const base_1 = base; + const window_1 = requireWindow(); + const view_1 = requireView(); + /** + * An object representing an application. Allows the developer to create, + * execute, show/close an application as well as listen to {@link OpenFin.ApplicationEvents application events}. + */ + class Application extends base_1.EmitterBase { + /** + * @internal + */ + constructor(wire, identity) { + super(wire, 'application', identity.uuid); + this.identity = identity; + this.window = new window_1._Window(this.wire, { + uuid: this.identity.uuid, + name: this.identity.uuid + }); + } + windowListFromIdentityList(identityList) { + const windowList = []; + identityList.forEach((identity) => { + windowList.push(new window_1._Window(this.wire, { + uuid: identity.uuid, + name: identity.name + })); + }); + return windowList; + } + /** + * Determines if the application is currently running. + * + * @example + * + * ```js + * async function isAppRunning() { + * const app = await fin.Application.getCurrent(); + * return await app.isRunning(); + * } + * isAppRunning().then(running => console.log(`Current app is running: ${running}`)).catch(err => console.log(err)); + * ``` + */ + isRunning() { + return this.wire.sendAction('is-application-running', this.identity).then(({ payload }) => payload.data); + } + /** + * Closes the application and any child windows created by the application. + * Cleans the application from state so it is no longer found in getAllApplications. + * @param force Close will be prevented from closing when force is false and + * ‘close-requested’ has been subscribed to for application’s main window. + * + * @example + * + * ```js + * async function closeApp() { + * const allApps1 = await fin.System.getAllApplications(); //[{uuid: 'app1', isRunning: true}, {uuid: 'app2', isRunning: true}] + * const app = await fin.Application.wrap({uuid: 'app2'}); + * await app.quit(); + * const allApps2 = await fin.System.getAllApplications(); //[{uuid: 'app1', isRunning: true}] + * + * } + * closeApp().then(() => console.log('Application quit')).catch(err => console.log(err)); + * ``` + */ + async quit(force = false) { + try { + await this._close(force); + await this.wire.sendAction('destroy-application', { force, ...this.identity }); + } + catch (error) { + const acceptableErrors = ['Remote connection has closed', 'Could not locate the requested application']; + if (!acceptableErrors.some((msg) => error.message.includes(msg))) { + throw error; + } + } + } + async _close(force = false) { + try { + await this.wire.sendAction('close-application', { force, ...this.identity }); + } + catch (error) { + if (!error.message.includes('Remote connection has closed')) { + throw error; + } + } + } + /** + * @deprecated use Application.quit instead + * Closes the application and any child windows created by the application. + * @param force - Close will be prevented from closing when force is false and ‘close-requested’ has been subscribed to for application’s main window. + * @param callback - called if the method succeeds. + * @param errorCallback - called if the method fails. The reason for failure is passed as an argument. + * + * @example + * + * ```js + * async function closeApp() { + * const app = await fin.Application.getCurrent(); + * return await app.close(); + * } + * closeApp().then(() => console.log('Application closed')).catch(err => console.log(err)); + * ``` + */ + close(force = false) { + console.warn('Deprecation Warning: Application.close is deprecated Please use Application.quit'); + this.wire.sendAction('application-close', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this._close(force); + } + /** + * Retrieves an array of wrapped fin.Windows for each of the application’s child windows. + * + * @example + * + * ```js + * async function getChildWindows() { + * const app = await fin.Application.getCurrent(); + * return await app.getChildWindows(); + * } + * + * getChildWindows().then(children => console.log(children)).catch(err => console.log(err)); + * ``` + */ + getChildWindows() { + return this.wire.sendAction('get-child-windows', this.identity).then(({ payload }) => { + const identityList = []; + payload.data.forEach((winName) => { + identityList.push({ uuid: this.identity.uuid, name: winName }); + }); + return this.windowListFromIdentityList(identityList); + }); + } + /** + * Retrieves the JSON manifest that was used to create the application. Invokes the error callback + * if the application was not created from a manifest. + * + * @example + * + * ```js + * async function getManifest() { + * const app = await fin.Application.getCurrent(); + * return await app.getManifest(); + * } + * + * getManifest().then(manifest => console.log(manifest)).catch(err => console.log(err)); + * ``` + */ + getManifest() { + return this.wire.sendAction('get-application-manifest', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves UUID of the application that launches this application. Invokes the error callback + * if the application was created from a manifest. + * + * @example + * + * ```js + * async function getParentUuid() { + * const app = await fin.Application.start({ + * uuid: 'app-1', + * name: 'myApp', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Application.getParentUuid.html', + * autoShow: true + * }); + * return await app.getParentUuid(); + * } + * + * getParentUuid().then(parentUuid => console.log(parentUuid)).catch(err => console.log(err)); + * ``` + */ + getParentUuid() { + return this.wire.sendAction('get-parent-application', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves current application's shortcut configuration. + * + * @example + * + * ```js + * async function getShortcuts() { + * const app = await fin.Application.wrap({ uuid: 'testapp' }); + * return await app.getShortcuts(); + * } + * getShortcuts().then(config => console.log(config)).catch(err => console.log(err)); + * ``` + */ + getShortcuts() { + return this.wire.sendAction('get-shortcuts', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves current application's views. + * @experimental + * + * @example + * + * ```js + * async function getViews() { + * const app = await fin.Application.getCurrent(); + * return await app.getViews(); + * } + * getViews().then(views => console.log(views)).catch(err => console.log(err)); + * ``` + */ + async getViews() { + const { payload } = await this.wire.sendAction('application-get-views', this.identity); + return payload.data.map((id) => new view_1.View(this.wire, id)); + } + /** + * Returns the current zoom level of the application. + * + * @example + * + * ```js + * async function getZoomLevel() { + * const app = await fin.Application.getCurrent(); + * return await app.getZoomLevel(); + * } + * + * getZoomLevel().then(zoomLevel => console.log(zoomLevel)).catch(err => console.log(err)); + * ``` + */ + getZoomLevel() { + return this.wire.sendAction('get-application-zoom-level', this.identity).then(({ payload }) => payload.data); + } + /** + * Returns an instance of the main Window of the application + * + * @example + * + * ```js + * async function getWindow() { + * const app = await fin.Application.start({ + * uuid: 'app-1', + * name: 'myApp', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Application.getWindow.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * getWindow().then(win => { + * win.showAt(0, 400); + * win.flash(); + * }).catch(err => console.log(err)); + * ``` + */ + getWindow() { + this.wire.sendAction('application-get-window', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return Promise.resolve(this.window); + } + /** + * Manually registers a user with the licensing service. The only data sent by this call is userName and appName. + * @param userName - username to be passed to the RVM. + * @param appName - app name to be passed to the RVM. + * + * @example + * + * ```js + * async function registerUser() { + * const app = await fin.Application.getCurrent(); + * return await app.registerUser('user', 'myApp'); + * } + * + * registerUser().then(() => console.log('Successfully registered the user')).catch(err => console.log(err)); + * ``` + */ + registerUser(userName, appName) { + return this.wire.sendAction('register-user', { userName, appName, ...this.identity }).then(() => undefined); + } + /** + * Removes the application’s icon from the tray. + * + * @example + * + * ```js + * async function removeTrayIcon() { + * const app = await fin.Application.getCurrent(); + * return await app.removeTrayIcon(); + * } + * + * removeTrayIcon().then(() => console.log('Removed the tray icon.')).catch(err => console.log(err)); + * ``` + */ + removeTrayIcon() { + return this.wire.sendAction('remove-tray-icon', this.identity).then(() => undefined); + } + /** + * Restarts the application. + * + * @example + * + * ```js + * async function restartApp() { + * const app = await fin.Application.getCurrent(); + * return await app.restart(); + * } + * restartApp().then(() => console.log('Application restarted')).catch(err => console.log(err)); + * ``` + */ + restart() { + return this.wire.sendAction('restart-application', this.identity).then(() => undefined); + } + /** + * DEPRECATED method to run the application. + * Needed when starting application via {@link Application.create}, but NOT needed when starting via {@link Application.start}. + * + * @example + * + * ```js + * async function run() { + * const app = await fin.Application.create({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Application.run.html', + * autoShow: true + * }); + * await app.run(); + * } + * run().then(() => console.log('Application is running')).catch(err => console.log(err)); + * ``` + * + * @ignore + */ + run() { + console.warn('Deprecation Warning: Application.run is deprecated Please use fin.Application.start'); + this.wire.sendAction('application-run', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this._run(); + } + _run(opts = {}) { + return this.wire + .sendAction('run-application', { + manifestUrl: this._manifestUrl, + opts, + ...this.identity + }) + .then(() => undefined); + } + /** + * Instructs the RVM to schedule one restart of the application. + * + * @example + * + * ```js + * async function scheduleRestart() { + * const app = await fin.Application.getCurrent(); + * return await app.scheduleRestart(); + * } + * + * scheduleRestart().then(() => console.log('Application is scheduled to restart')).catch(err => console.log(err)); + * ``` + */ + scheduleRestart() { + return this.wire.sendAction('relaunch-on-close', this.identity).then(() => undefined); + } + /** + * Sends a message to the RVM to upload the application's logs. On success, + * an object containing logId is returned. + * + * @example + * + * ```js + * async function sendLog() { + * const app = await fin.Application.getCurrent(); + * return await app.sendApplicationLog(); + * } + * + * sendLog().then(info => console.log(info.logId)).catch(err => console.log(err)); + * ``` + */ + async sendApplicationLog() { + const { payload } = await this.wire.sendAction('send-application-log', this.identity); + return payload.data; + } + /** + * Sets or removes a custom JumpList for the application. Only applicable in Windows OS. + * If categories is null the previously set custom JumpList (if any) will be replaced by the standard JumpList for the app (managed by Windows). + * + * Note: If the "name" property is omitted it defaults to "tasks". + * @param jumpListCategories An array of JumpList Categories to populate. If null, remove any existing JumpList configuration and set to Windows default. + * + * + * @remarks If categories is null the previously set custom JumpList (if any) will be replaced by the standard JumpList for the app (managed by Windows). + * + * The bottommost item in the jumplist will always be an item pointing to the current app. Its name is taken from the manifest's + * **` shortcut.name `** and uses **` shortcut.company `** as a fallback. Clicking that item will launch the app from its current manifest. + * + * Note: If the "name" property is omitted it defaults to "tasks". + * + * Note: Window OS caches jumplists icons, therefore an icon change might only be visible after the cache is removed or the + * uuid or shortcut.name is changed. + * + * @example + * + * ```js + * const app = fin.Application.getCurrentSync(); + * const appName = 'My App'; + * const jumpListConfig = [ // array of JumpList categories + * { + * // has no name and no type so `type` is assumed to be "tasks" + * items: [ // array of JumpList items + * { + * type: 'task', + * title: `Launch ${appName}`, + * description: `Runs ${appName} with the default configuration`, + * deepLink: 'fins://path.to/app/manifest.json', + * iconPath: 'https://path.to/app/icon.ico', + * iconIndex: 0 + * }, + * { type: 'separator' }, + * { + * type: 'task', + * title: `Restore ${appName}`, + * description: 'Restore to last configuration', + * deepLink: 'fins://path.to/app/manifest.json?$$use-last-configuration=true', + * iconPath: 'https://path.to/app/icon.ico', + * iconIndex: 0 + * }, + * ] + * }, + * { + * name: 'Tools', + * items: [ // array of JumpList items + * { + * type: 'task', + * title: 'Tool A', + * description: 'Runs Tool A', + * deepLink: 'fins://path.to/tool-a/manifest.json', + * iconPath: 'https://path.to/tool-a/icon.ico', + * iconIndex: 0 + * }, + * { + * type: 'task', + * title: 'Tool B', + * description: 'Runs Tool B', + * deepLink: 'fins://path.to/tool-b/manifest.json', + * iconPath: 'https://path.to/tool-b/icon.ico', + * iconIndex: 0 + * }] + * } + * ]; + * + * app.setJumpList(jumpListConfig).then(() => console.log('JumpList applied')).catch(e => console.log(`JumpList failed to apply: ${e.toString()}`)); + * ``` + * + * To handle deeplink args: + * ```js + * function handleUseLastConfiguration() { + * // this handler is called when the app is being launched + * app.on('run-requested', event => { + * if(event.userAppConfigArgs['use-last-configuration']) { + * // your logic here + * } + * }); + * // this handler is called when the app was already running when the launch was requested + * fin.desktop.main(function(args) { + * if(args && args['use-last-configuration']) { + * // your logic here + * } + * }); + * } + * ``` + */ + async setJumpList(jumpListCategories) { + await this.wire.sendAction('set-jump-list', { config: jumpListCategories, ...this.identity }); + } + /** + * Adds a customizable icon in the system tray. To listen for a click on the icon use the `tray-icon-clicked` event. + * @param icon Image URL or base64 encoded string to be used as the icon + * + * @example + * + * ```js + * const imageUrl = "http://cdn.openfin.co/assets/testing/icons/circled-digit-one.png"; + * const base64EncodedImage = "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX\ + * ///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII"; + * const dataURL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DH\ + * xgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; + * + * async function setTrayIcon(icon) { + * const app = await fin.Application.getCurrent(); + * return await app.setTrayIcon(icon); + * } + * + * // use image url to set tray icon + * setTrayIcon(imageUrl).then(() => console.log('Setting tray icon')).catch(err => console.log(err)); + * + * // use base64 encoded string to set tray icon + * setTrayIcon(base64EncodedImage).then(() => console.log('Setting tray icon')).catch(err => console.log(err)); + * + * // use a dataURL to set tray icon + * setTrayIcon(dataURL).then(() => console.log('Setting tray icon')).catch(err => console.log(err)); + * ``` + */ + setTrayIcon(icon) { + return this.wire + .sendAction('set-tray-icon', { + enabledIcon: icon, + ...this.identity + }) + .then(() => undefined); + } + /** + * Sets new application's shortcut configuration. Windows only. + * @param config New application's shortcut configuration. + * + * @remarks Application has to be launched with a manifest and has to have shortcut configuration (icon url, name, etc.) in its manifest + * to be able to change shortcut states. + * + * @example + * + * ```js + * async function setShortcuts(config) { + * const app = await fin.Application.getCurrent(); + * return app.setShortcuts(config); + * } + * + * setShortcuts({ + * desktop: true, + * startMenu: false, + * systemStartup: true + * }).then(() => console.log('Shortcuts are set.')).catch(err => console.log(err)); + * ``` + */ + setShortcuts(config) { + return this.wire.sendAction('set-shortcuts', { data: config, ...this.identity }).then(() => undefined); + } + /** + * Sets the query string in all shortcuts for this app. Requires RVM 5.5+. + * @param queryString The new query string for this app's shortcuts. + * + * @example + * + * ```js + * const newQueryArgs = 'arg=true&arg2=false'; + * const app = await fin.Application.getCurrent(); + * try { + * await app.setShortcutQueryParams(newQueryArgs); + * } catch(err) { + * console.error(err) + * } + * ``` + */ + async setShortcutQueryParams(queryString) { + await this.wire.sendAction('set-shortcut-query-args', { data: queryString, ...this.identity }); + } + /** + * Sets the zoom level of the application. The original size is 0 and each increment above or below represents zooming 20% + * larger or smaller to default limits of 300% and 50% of original size, respectively. + * @param level The zoom level + * + * @example + * + * ```js + * async function setZoomLevel(number) { + * const app = await fin.Application.getCurrent(); + * return await app.setZoomLevel(number); + * } + * + * setZoomLevel(5).then(() => console.log('Setting a zoom level')).catch(err => console.log(err)); + * ``` + */ + setZoomLevel(level) { + return this.wire.sendAction('set-application-zoom-level', { level, ...this.identity }).then(() => undefined); + } + /** + * Sets a username to correlate with App Log Management. + * @param username Username to correlate with App's Log. + * + * @example + * + * ```js + * async function setAppLogUser() { + * const app = await fin.Application.getCurrent(); + * return await app.setAppLogUsername('username'); + * } + * + * setAppLogUser().then(() => console.log('Success')).catch(err => console.log(err)); + * + * ``` + */ + async setAppLogUsername(username) { + await this.wire.sendAction('set-app-log-username', { data: username, ...this.identity }); + } + /** + * Retrieves information about the system tray. If the system tray is not set, it will throw an error message. + * @remarks The only information currently returned is the position and dimensions. + * + * @example + * + * ```js + * async function getTrayIconInfo() { + * const app = await fin.Application.wrap({ uuid: 'testapp' }); + * return await app.getTrayIconInfo(); + * } + * getTrayIconInfo().then(info => console.log(info)).catch(err => console.log(err)); + * ``` + */ + getTrayIconInfo() { + return this.wire.sendAction('get-tray-icon-info', this.identity).then(({ payload }) => payload.data); + } + /** + * Checks if the application has an associated tray icon. + * + * @example + * + * ```js + * const app = await fin.Application.wrap({ uuid: 'testapp' }); + * const hasTrayIcon = await app.hasTrayIcon(); + * console.log(hasTrayIcon); + * ``` + */ + hasTrayIcon() { + return this.wire.sendAction('has-tray-icon', this.identity).then(({ payload }) => payload.data); + } + /** + * Closes the application by terminating its process. + * + * @example + * + * ```js + * async function terminateApp() { + * const app = await fin.Application.getCurrent(); + * return await app.terminate(); + * } + * terminateApp().then(() => console.log('Application terminated')).catch(err => console.log(err)); + * ``` + */ + terminate() { + return this.wire.sendAction('terminate-application', this.identity).then(() => undefined); + } + /** + * Waits for a hanging application. This method can be called in response to an application + * "not-responding" to allow the application to continue and to generate another "not-responding" + * message after a certain period of time. + * + * @ignore + */ + wait() { + return this.wire.sendAction('wait-for-hung-application', this.identity).then(() => undefined); + } + /** + * Retrieves information about the application. + * + * @remarks If the application was not launched from a manifest, the call will return the closest parent application `manifest` + * and `manifestUrl`. `initialOptions` shows the parameters used when launched programmatically, or the `startup_app` options + * if launched from manifest. The `parentUuid` will be the uuid of the immediate parent (if applicable). + * + * @example + * + * ```js + * async function getInfo() { + * const app = await fin.Application.getCurrent(); + * return await app.getInfo(); + * } + * + * getInfo().then(info => console.log(info)).catch(err => console.log(err)); + * ``` + */ + getInfo() { + return this.wire.sendAction('get-info', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves all process information for entities (windows and views) associated with an application. + * + * @example + * ```js + * const app = await fin.Application.getCurrent(); + * const processInfo = await app.getProcessInfo(); + * ``` + * @experimental + */ + async getProcessInfo() { + const { payload: { data } } = await this.wire.sendAction('application-get-process-info', this.identity); + return data; + } + /** + * Sets file auto download location. It's only allowed in the same application. + * + * Note: This method is restricted by default and must be enabled via + * API security settings. + * @param downloadLocation file auto download location + * + * @throws if setting file auto download location on different applications. + * @example + * + * ```js + * const downloadLocation = 'C:\\dev\\temp'; + * const app = await fin.Application.getCurrent(); + * try { + * await app.setFileDownloadLocation(downloadLocation); + * console.log('File download location is set'); + * } catch(err) { + * console.error(err) + * } + * ``` + */ + async setFileDownloadLocation(downloadLocation) { + const { name } = this.wire.me; + const entityIdentity = { uuid: this.identity.uuid, name }; + await this.wire.sendAction('set-file-download-location', { ...entityIdentity, downloadLocation }); + } + /** + * Gets file auto download location. It's only allowed in the same application. If file auto download location is not set, it will return the default location. + * + * Note: This method is restricted by default and must be enabled via + * API security settings. + * + * @throws if getting file auto download location on different applications. + * @example + * + * ```js + * const app = await fin.Application.getCurrent(); + * const fileDownloadDir = await app.getFileDownloadLocation(); + * ``` + */ + async getFileDownloadLocation() { + const { payload: { data } } = await this.wire.sendAction('get-file-download-location', this.identity); + return data; + } + /** + * Shows a menu on the tray icon. Use with tray-icon-clicked event. + * @param options + * @typeParam Data User-defined shape for data returned upon menu item click. Should be a + * [union](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) + * of all possible data shapes for the entire menu, and the click handler should process + * these with a "reducer" pattern. + * @throws if the application has no tray icon set + * @throws if the system tray is currently hidden + * @example + * + * ```js + * const iconUrl = 'http://cdn.openfin.co/assets/testing/icons/circled-digit-one.png'; + * const app = fin.Application.getCurrentSync(); + * + * await app.setTrayIcon(iconUrl); + * + * const template = [ + * { + * label: 'Menu Item 1', + * data: 'hello from item 1' + * }, + * { type: 'separator' }, + * { + * label: 'Menu Item 2', + * type: 'checkbox', + * checked: true, + * data: 'The user clicked the checkbox' + * }, + * { + * label: 'see more', + * enabled: false, + * submenu: [ + * { label: 'submenu 1', data: 'hello from submenu' } + * ] + * } + * ]; + * + * app.addListener('tray-icon-clicked', (event) => { + * // right-click + * if (event.button === 2) { + * app.showTrayIconPopupMenu({ template }).then(r => { + * if (r.result === 'closed') { + * console.log('nothing happened'); + * } else { + * console.log(r.data); + * } + * }); + * } + * }); + * ``` + */ + async showTrayIconPopupMenu(options) { + const { name } = this.wire.me; + const entityIdentity = { uuid: this.identity.uuid, name }; + const { payload } = await this.wire.sendAction('show-tray-icon-popup-menu', { ...entityIdentity, options }); + return payload.data; + } + /** + * Closes the tray icon menu. + * + * @throws if the application has no tray icon set + * @example + * + * ```js + * const app = fin.Application.getCurrentSync(); + * + * await app.closeTrayIconPopupMenu(); + * ``` + */ + async closeTrayIconPopupMenu() { + const { name } = this.wire.me; + const entityIdentity = { uuid: this.identity.uuid, name }; + await this.wire.sendAction('close-tray-icon-popup-menu', { ...entityIdentity }); + } + } + Instance$6.Application = Application; + return Instance$6; +} + +var hasRequiredFactory$2; + +function requireFactory$2 () { + if (hasRequiredFactory$2) return Factory$7; + hasRequiredFactory$2 = 1; + Object.defineProperty(Factory$7, "__esModule", { value: true }); + Factory$7.ApplicationModule = void 0; + const base_1 = base; + const validate_1 = validate; + const Instance_1 = requireInstance$1(); + /** + * Static namespace for OpenFin API methods that interact with the {@link Application} class, available under `fin.Application`. + */ + class ApplicationModule extends base_1.Base { + /** + * Asynchronously returns an API handle for the given Application identity. + * + * @remarks Wrapping an Application identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for an Application throughout its entire lifecycle. + * + * @example + * + * ```js + * fin.Application.wrap({ uuid: 'testapp' }) + * .then(app => app.isRunning()) + * .then(running => console.log('Application is running: ' + running)) + * .catch(err => console.log(err)); + * ``` + * + */ + async wrap(identity) { + this.wire.sendAction('wrap-application').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1.Application(this.wire, identity); + } + /** + * Synchronously returns an API handle for the given Application identity. + * + * @remarks Wrapping an Application identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for an Aplication throughout its entire lifecycle. + * + * @example + * + * ```js + * const app = fin.Application.wrapSync({ uuid: 'testapp' }); + * await app.close(); + * ``` + * + */ + wrapSync(identity) { + this.wire.sendAction('wrap-application-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1.Application(this.wire, identity); + } + async _create(appOptions) { + // set defaults: + if (appOptions.waitForPageLoad === undefined) { + appOptions.waitForPageLoad = false; + } + if (appOptions.autoShow === undefined && appOptions.isPlatformController === undefined) { + appOptions.autoShow = true; + } + await this.wire.sendAction('create-application', appOptions); + return this.wrap({ uuid: appOptions.uuid }); + } + /** + * DEPRECATED method to create a new Application. Use {@link Application.ApplicationModule.start Application.start} instead. + * + * @example + * + * ```js + * async function createApp() { + * const app = await fin.Application.create({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Application.create.html', + * autoShow: true + * }); + * await app.run(); + * } + * + * createApp().then(() => console.log('Application is created')).catch(err => console.log(err)); + * ``` + * + * @ignore + */ + create(appOptions) { + console.warn('Deprecation Warning: fin.Application.create is deprecated. Please use fin.Application.start'); + this.wire.sendAction('application-create').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this._create(appOptions); + } + /** + * Creates and starts a new Application. + * + * @example + * + * ```js + * async function start() { + * return fin.Application.start({ + * name: 'app-1', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Application.start.html', + * autoShow: true + * }); + * } + * start().then(() => console.log('Application is running')).catch(err => console.log(err)); + * ``` + * + */ + async start(appOptions) { + this.wire.sendAction('start-application').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const app = await this._create(appOptions); + await this.wire.sendAction('run-application', { uuid: appOptions.uuid }); + return app; + } + /** + * Asynchronously starts a batch of applications given an array of application identifiers and manifestUrls. + * Returns once the RVM is finished attempting to launch the applications. + * @param opts - Parameters that the RVM will use. + * + * @example + * + * ```js + * + * const applicationInfoArray = [ + * { + * "uuid": 'App-1', + * "manifestUrl": 'http://localhost:5555/app1.json', + * }, + * { + * "uuid": 'App-2', + * "manifestUrl": 'http://localhost:5555/app2.json', + * }, + * { + * "uuid": 'App-3', + * "manifestUrl": 'http://localhost:5555/app3.json', + * } + * ] + * + * fin.Application.startManyManifests(applicationInfoArray) + * .then(() => { + * console.log('RVM has finished launching the application list.'); + * }) + * .catch((err) => { + * console.log(err); + * }) + * ``` + * + * @experimental + */ + async startManyManifests(applications, opts) { + return this.wire.sendAction('run-applications', { applications, opts }).then(() => undefined); + } + /** + * Asynchronously returns an Application object that represents the current application + * + * @example + * + * ```js + * async function isCurrentAppRunning () { + * const app = await fin.Application.getCurrent(); + * return app.isRunning(); + * } + * + * isCurrentAppRunning().then(running => { + * console.log(`Current app is running: ${running}`); + * }).catch(err => { + * console.error(err); + * }); + * + * ``` + */ + getCurrent() { + this.wire.sendAction('get-current-application').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.wrap({ uuid: this.wire.me.uuid }); + } + /** + * Synchronously returns an Application object that represents the current application + * + * @example + * + * ```js + * async function isCurrentAppRunning () { + * const app = fin.Application.getCurrentSync(); + * return app.isRunning(); + * } + * + * isCurrentAppRunning().then(running => { + * console.log(`Current app is running: ${running}`); + * }).catch(err => { + * console.error(err); + * }); + * + * ``` + */ + getCurrentSync() { + this.wire.sendAction('get-current-application-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.wrapSync({ uuid: this.wire.me.uuid }); + } + /** + * Retrieves application's manifest and returns a running instance of the application. + * @param manifestUrl - The URL of app's manifest. + * @param opts - Parameters that the RVM will use. + * + * @example + * + * ```js + * fin.Application.startFromManifest('http://localhost:5555/app.json').then(app => console.log('App is running')).catch(err => console.log(err)); + * + * // For a local manifest file: + * fin.Application.startFromManifest('file:///C:/somefolder/app.json').then(app => console.log('App is running')).catch(err => console.log(err)); + * ``` + */ + async startFromManifest(manifestUrl, opts) { + this.wire.sendAction('application-start-from-manifest').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const app = await this._createFromManifest(manifestUrl); + // @ts-expect-error using private method without warning. + await app._run(opts); // eslint-disable-line no-underscore-dangle + return app; + } + /** + * @deprecated Use {@link Application.ApplicationModule.startFromManifest Application.startFromManifest} instead. + * Retrieves application's manifest and returns a wrapped application. + * @param manifestUrl - The URL of app's manifest. + * @param callback - called if the method succeeds. + * @param errorCallback - called if the method fails. The reason for failure is passed as an argument. + * + * @example + * + * ```js + * fin.Application.createFromManifest('http://localhost:5555/app.json').then(app => console.log(app)).catch(err => console.log(err)); + * ``` + * @ignore + */ + createFromManifest(manifestUrl) { + console.warn('Deprecation Warning: fin.Application.createFromManifest is deprecated. Please use fin.Application.startFromManifest'); + this.wire.sendAction('application-create-from-manifest').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this._createFromManifest(manifestUrl); + } + _createFromManifest(manifestUrl) { + return this.wire + .sendAction('get-application-manifest', { manifestUrl }) + .then(({ payload }) => { + const uuid = payload.data.platform ? payload.data.platform.uuid : payload.data.startup_app.uuid; + return this.wrap({ uuid }); + }) + .then((app) => { + app._manifestUrl = manifestUrl; // eslint-disable-line no-underscore-dangle + return app; + }); + } + } + Factory$7.ApplicationModule = ApplicationModule; + return Factory$7; +} + +var hasRequiredApplication; + +function requireApplication () { + if (hasRequiredApplication) return application; + hasRequiredApplication = 1; + (function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + /** + * Entry points for the OpenFin `Application` API (`fin.Application`). + * + * * {@link ApplicationModule} contains static members of the `Application` API, accessible through `fin.Application`. + * * {@link Application} describes an instance of an OpenFin Application, e.g. as returned by `fin.Application.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + */ + __exportStar(requireFactory$2(), exports); + __exportStar(requireInstance$1(), exports); + } (application)); + return application; +} + +var promisifySubscription$1 = {}; + +Object.defineProperty(promisifySubscription$1, "__esModule", { value: true }); +promisifySubscription$1.promisifySubscription = void 0; +const promisifySubscription = async (emitter, eventName, predicate = () => true, timeout) => { + let resolve; + let reject; + let timer; + const valuePromise = new Promise((y, n) => { + resolve = y; + reject = n; + }); + const listener = (e) => { + if (predicate(e)) { + clearTimeout(timer); + resolve(e); + } + }; + await emitter.on(eventName, listener); + if (timeout) { + timer = setTimeout(() => reject(new Error('event timed out')), timeout); + } + valuePromise.finally(() => { + emitter.removeListener(eventName, listener).catch(() => null); + }); + return { + getValue: () => valuePromise + }; +}; +promisifySubscription$1.promisifySubscription = promisifySubscription; + +var hasRequiredInstance; + +function requireInstance () { + if (hasRequiredInstance) return Instance$7; + hasRequiredInstance = 1; + Object.defineProperty(Instance$7, "__esModule", { value: true }); + Instance$7._Window = void 0; + /* eslint-disable import/prefer-default-export */ + /* eslint-disable @typescript-eslint/no-unused-vars */ + /* eslint-disable no-console */ + /* eslint-disable @typescript-eslint/no-non-null-assertion */ + const application_1 = requireApplication(); + const main_1 = main; + const view_1 = requireView(); + const warnings_1 = warnings; + const promisifySubscription_1 = promisifySubscription$1; + /** + * A basic window that wraps a native HTML window. Provides more fine-grained + * control over the window state such as the ability to minimize, maximize, restore, etc. + * By default a window does not show upon instantiation; instead the window's show() method + * must be invoked manually. The new window appears in the same process as the parent window. + * It has the ability to listen for {@link OpenFin.WindowEvents window specific events}. + */ + // The window.Window name is taken + class _Window extends main_1.WebContents { + /** + * @internal + */ + constructor(wire, identity) { + super(wire, identity, 'window'); + } + async createWindow(options) { + this.wire.sendAction('window-create-window', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const CONSTRUCTOR_CB_TOPIC = 'fire-constructor-callback'; + const responseSubscription = await (0, promisifySubscription_1.promisifySubscription)(this, CONSTRUCTOR_CB_TOPIC); + // set defaults: + if (options.waitForPageLoad === undefined) { + options.waitForPageLoad = false; + } + if (options.autoShow === undefined) { + options.autoShow = true; + } + (0, warnings_1.handleDeprecatedWarnings)(options); + const windowCreation = this.wire.environment.createChildContent({ entityType: 'window', options }); + const [response] = await Promise.all([responseSubscription.getValue(), windowCreation]); + let cbPayload; + const { success } = response; + const responseData = response.data; + const { message } = responseData; + if (success) { + cbPayload = { + httpResponseCode: responseData.httpResponseCode, + apiInjected: responseData.apiInjected + }; + } + else { + cbPayload = { + message: responseData.message, + networkErrorCode: responseData.networkErrorCode, + stack: responseData.stack + }; + } + const pageResolve = { + message, + cbPayload, + success + }; + try { + // this is to enforce a 5.0 contract that the child's main function + // will not fire before the parent's success callback on creation. + // if the child window is not accessible (CORS) this contract does + // not hold. + const webWindow = this.getWebWindow(); + webWindow.fin.__internal_.openerSuccessCBCalled(); + } + catch (e) { + // common for main windows, we do not want to expose this error. here just to have a debug target. + // console.error(e); + } + if (pageResolve.success) { + return this; + } + return Promise.reject(pageResolve); + } + /** + * Retrieves an array of frame info objects representing the main frame and any + * iframes that are currently on the page. + * + * @example + * ```js + * async function getAllFrames() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getAllFrames.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getAllFrames(); + * } + * + * getAllFrames().then(framesInfo => console.log(framesInfo)).catch(err => console.log(err)); + * ``` + */ + getAllFrames() { + return this.wire.sendAction('get-all-frames', this.identity).then(({ payload }) => payload.data); + } + /** + * Gets the current bounds (top, bottom, right, left, width, height) of the window. + * + * @example + * ```js + * async function getBounds() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getBounds.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getBounds(); + * } + * + * getBounds().then(bounds => console.log(bounds)).catch(err => console.log(err)); + * ``` + */ + getBounds() { + return this.wire + .sendAction('get-window-bounds', this.identity) + .then(({ payload }) => payload.data); + } + /** + * Centers the window on its current screen. + * + * @remarks Does not have an effect on minimized or maximized windows. + * + * @example + * ```js + * async function centerWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.center.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.center(); + * } + * + * centerWindow().then(() => console.log('Window centered')).catch(err => console.log(err)); + * ``` + * + */ + center() { + return this.wire.sendAction('center-window', this.identity).then(() => undefined); + } + /** + * Removes focus from the window. + * + * @example + * ```js + * async function blurWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.blur.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.blur(); + * } + * + * blurWindow().then(() => console.log('Blured Window')).catch(err => console.log(err)); + * ``` + */ + blur() { + return this.wire.sendAction('blur-window', this.identity).then(() => undefined); + } + /** + * Brings the window to the front of the window stack. + * + * @example + * ```js + * async function BringWindowToFront() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.bringToFront.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.bringToFront(); + * } + * + * BringWindowToFront().then(() => console.log('Window is in the front')).catch(err => console.log(err)); + * ``` + */ + bringToFront() { + return this.wire.sendAction('bring-window-to-front', this.identity).then(() => undefined); + } + /** + * Performs the specified window transitions. + * @param transitions - Describes the animations to perform. See the tutorial. + * @param options - Options for the animation. See the tutorial. + * + * @example + * ``` + * async function animateWindow() { + * const transitions = { + * opacity: { + * opacity: 0.7, + * duration: 500 + * }, + * position: { + * top: 100, + * left: 100, + * duration: 500, + * relative: true + * } + * }; + * const options = { + * interrupt: true, + * tween: 'ease-in' + * }; + * + * const win = await fin.Window.getCurrent(); + * return win.animate(transitions, options); + * } + * + * animateWindow() + * .then(() => console.log('Animation done')) + * .catch(err => console.error(err)); + * ``` + */ + animate(transitions, options) { + return this.wire + .sendAction('animate-window', { + transitions, + options, + ...this.identity + }) + .then(() => undefined); + } + /** + * Hides the window. + * + * @example + * ```js + * async function hideWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.hide.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.hide(); + * } + * + * hideWindow().then(() => console.log('Window is hidden')).catch(err => console.log(err)); + * ``` + */ + hide() { + return this.wire.sendAction('hide-window', this.identity).then(() => undefined); + } + /** + * closes the window application + * @param force Close will be prevented from closing when force is false and + * ‘close-requested’ has been subscribed to for application’s main window. + * + * @example + * ```js + * async function closeWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.close.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.close(); + * } + * + * closeWindow().then(() => console.log('Window closed')).catch(err => console.log(err)); + * ``` + */ + close(force = false) { + return this.wire.sendAction('close-window', { force, ...this.identity }).then(() => { + Object.setPrototypeOf(this, null); + return undefined; + }); + } + focusedWebViewWasChanged() { + return this.wire.sendAction('focused-webview-changed', this.identity).then(() => undefined); + } + /** + * Returns the native OS level Id. + * + * @remarks In Windows, it will return the Windows [handle](https://docs.microsoft.com/en-us/windows/desktop/WinProg/windows-data-types#HWND). + * + * @example + * ```js + * async function getWindowNativeId() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getNativeId.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getNativeId(); + * } + * + * getWindowNativeId().then(nativeId => console.log(nativeId)).catch(err => console.log(err)); + * ``` + */ + getNativeId() { + return this.wire.sendAction('get-window-native-id', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves window's attached views. + * @experimental + * + * @example + * ```js + * const win = fin.Window.getCurrentSync(); + * + * win.getCurrentViews() + * .then(views => console.log(views)) + * .catch(console.error); + * ``` + */ + async getCurrentViews() { + const { payload } = await this.wire.sendAction('window-get-views', this.identity); + return payload.data.map((id) => new view_1.View(this.wire, id)); + } + /** + * @deprecated Use {@link Window._Window.disableUserMovement} instead. + */ + disableFrame() { + console.warn('Function is deprecated; use disableUserMovement instead.'); + return this.wire.sendAction('disable-window-frame', this.identity).then(() => undefined); + } + /** + * Prevents a user from changing a window's size/position when using the window's frame. + * + * @example + * ```js + * async function disableUserMovement() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.disableFrame.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.disableUserMovement(); + * } + * + * disableUserMovement().then(() => console.log('Window is disabled')).catch(err => console.log(err)); + * ``` + */ + disableUserMovement() { + return this.wire.sendAction('disable-window-frame', this.identity).then(() => undefined); + } + /** + * @deprecated Use {@link Window._Window.enableUserMovement} instead. + */ + enableFrame() { + console.warn('Function is deprecated; use enableUserMovement instead.'); + return this.wire.sendAction('enable-window-frame', this.identity).then(() => undefined); + } + /** + * Re-enables user changes to a window's size/position when using the window's frame. + * + * @example + * ```js + * async function enableUserMovement() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-3', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.enableFrame.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.enableUserMovement(); + * } + * + * enableUserMovement().then(() => console.log('Window is enabled')).catch(err => console.log(err)); + * ``` + */ + enableUserMovement() { + return this.wire.sendAction('enable-window-frame', this.identity).then(() => undefined); + } + /** + * Flashes the window’s frame and taskbar icon until stopFlashing is called or until a focus event is fired. + * + * @remarks On macOS flash only works on inactive windows. + * @example + * ```js + * async function windowFlash() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.flash.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.flash(); + * } + * + * windowFlash().then(() => console.log('Window flashing')).catch(err => console.log(err)); + * ``` + */ + flash() { + return this.wire.sendAction('flash-window', this.identity).then(() => undefined); + } + /** + * Stops the taskbar icon from flashing. + * + * @example + * ```js + * async function stopWindowFlashing() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.stopFlashing.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.stopFlashing(); + * } + * + * stopWindowFlashing().then(() => console.log('Application window flashing')).catch(err => console.log(err)); + * ``` + */ + stopFlashing() { + return this.wire.sendAction('stop-flash-window', this.identity).then(() => undefined); + } + /** + * Gets an information object for the window. + * + * @example + * ```js + * async function getInfo() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getInfo.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getInfo(); + * } + * + * getInfo().then(info => console.log(info)).catch(err => console.log(err)); + * ``` + */ + getInfo() { + return this.wire.sendAction('get-window-info', this.identity).then(({ payload }) => payload.data); + } + /** + * Retrieves the window's Layout + * + * @example + * ```js + * //get the current window + * const window = await fin.Window.getCurrent(); + * + * //get the layout for the window + * const layout = await window.getLayout(); + * ``` + * @experimental + */ + async getLayout(layoutIdentity) { + this.wire.sendAction('window-get-layout', this.identity).catch((e) => { + // don't expose + }); + const opts = await this.getOptions(); + if (!opts.layout && !opts.layoutSnapshot) { + throw new Error('Window does not have a Layout'); + } + return this.fin.Platform.Layout.wrap(layoutIdentity ?? this.identity); + } + /** + * Gets the current settings of the window. + * + * @example + * ```js + * async function getWindowOptions() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getOptions.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getOptions(); + * } + * + * getWindowOptions().then(opts => console.log(opts)).catch(err => console.log(err)); + * ``` + */ + getOptions() { + return this.wire.sendAction('get-window-options', this.identity).then(({ payload }) => payload.data); + } + /** + * Gets the parent application. + * + * @example + * ```js + * async function getParentApplication() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getParentApplication.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getParentApplication(); + * } + * + * getParentApplication().then(parentApplication => console.log(parentApplication)).catch(err => console.log(err)); + * ``` + */ + getParentApplication() { + this.wire.sendAction('window-get-parent-application', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return Promise.resolve(new application_1.Application(this.wire, this.identity)); + } + /** + * Gets the parent window. + * + * @example + * ```js + * async function getParentWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getParentWindow.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getParentWindow(); + * } + * + * getParentWindow().then(parentWindow => console.log(parentWindow)).catch(err => console.log(err)); + * ``` + */ + getParentWindow() { + this.wire.sendAction('window-get-parent-window', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return Promise.resolve(new application_1.Application(this.wire, this.identity)).then((app) => app.getWindow()); + } + /** + * ***DEPRECATED - please use Window.capturePage.*** + * Gets a base64 encoded PNG image of the window or just part a of it. + * @param area The area of the window to be captured. + * Omitting it will capture the whole visible window. + * + * @tutorial Window.capturePage + */ + async getSnapshot(area) { + const req = { area, ...this.identity }; + console.warn('Window.getSnapshot has been deprecated, please use Window.capturePage'); + const res = await this.wire.sendAction('get-window-snapshot', req); + return res.payload.data; + } + /** + * Gets the current state ("minimized", "maximized", or "normal") of the window. + * + * @example + * ```js + * async function getWindowState() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.getState.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.getState(); + * } + * + * getWindowState().then(winState => console.log(winState)).catch(err => console.log(err)); + * ``` + */ + getState() { + return this.wire.sendAction('get-window-state', this.identity).then(({ payload }) => payload.data); + } + /** + * Previously called getNativeWindow. + * Returns the [Window Object](https://developer.mozilla.org/en-US/docs/Web/API/Window) + * that represents the web context of the target window. This is the same object that + * you would get from calling [window.open()](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) in a standard web context. + * The target window needs to be in the same application as the requesting window + * as well as comply with [same-origin](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy) policy requirements. + * + * @example + * Injecting content into an empty window: + * + * ```js + * (async ()=> { + * try { + * const winName = `child-window-${Date.now()}`; + * const win = await fin.Window.create({ + * name: winName, + * url: 'about:blank' + * }); + * win.getWebWindow().document.write('

Hello World

'); + * } catch (err) { + * console.error(err); + * } + * })(); + * ``` + * + * Cloning DOM elements from the parent window (in this example we clone an `h3` element from the parent window): + * ```js + * (async ()=> { + * try { + * const currentWindow = await fin.Window.getCurrent(); + * const parentWindow = await currentWindow.getParentWindow(); + * const clonedH3 = parentWindow.getWebWindow().document.querySelector('h3').cloneNode(true); + * document.body.append(clonedH3); + * + * } catch (err) { + * console.error(err); + * } + * })(); + * ``` + * + * Rendering on a child window via a library (in this example we are using the [lit-html](https://lit-html.polymer-project.org/) + * template library to render content on a blank child window. You are not going to be able to copy paste this example without + * configuring the project correctly but this would demonstrate some templating options available): + * ```js + * (async ()=> { + * try { + * const win = await fin.Window.create({ + * name: `child-window-${Date.now()}`, + * url: 'about:blank' + * }); + * const template = html` + *
+ * Click here: + * + *
`; + * render(template, win.getWebWindow().document.body); + * + * } catch (err) { + * console.error(err); + * } + * })(); + * ``` + */ + getWebWindow() { + this.wire.sendAction('window-get-web-window', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.wire.environment.getWebWindow(this.identity); + } + /** + * Determines if the window is a main window. + * + * @example + * ```js + * const wnd = fin.Window.getCurrentSync(); + * const isMainWnd = wnd.isMainWindow(); + * console.log('Is this a main window? ' + isMainWnd); + * ``` + */ + isMainWindow() { + this.wire.sendAction('window-is-main-window', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.me.uuid === this.me.name; + } + /** + * Determines if the window is currently showing. + * + * @example + * ```js + * async function isWindowShowing() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.isShowing.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.isShowing(); + * } + * + * isWindowShowing().then(bool => console.log(bool)).catch(err => console.log(err)); + * ``` + */ + isShowing() { + return this.wire.sendAction('is-window-showing', this.identity).then(({ payload }) => payload.data); + } + /** + * Maximizes the window + * + * @example + * ```js + * async function maxWindow() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.maximize.html', + * autoShow: true + * }); + * const win = await app.getWindow(); + * return await win.maximize(); + * } + * + * maxWindow().then(() => console.log('Maximized window')).catch(err => console.log(err)); + * ``` + */ + maximize() { + return this.wire.sendAction('maximize-window', this.identity).then(() => undefined); + } + /** + * Minimizes the window. + * + * @example + * ```js + * async function minWindow() { + * const win = await fin.Window.getCurrent(); + * return await win.minimize(); + * } + * + * minWindow().then(() => console.log('Minimized window')).catch(err => console.log(err)); + * ``` + */ + minimize() { + return this.wire.sendAction('minimize-window', this.identity).then(() => undefined); + } + /** + * Moves the window by a specified amount. + * @param deltaLeft The change in the left position of the window + * @param deltaTop The change in the top position of the window + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.moveBy.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function moveBy(left, top) { + * const win = await createWin(); + * return await win.moveBy(left, top); + * } + * + * moveBy(580, 300).then(() => console.log('Moved')).catch(err => console.log(err)); + * ``` + */ + moveBy(deltaLeft, deltaTop, positioningOptions) { + return this.wire + .sendAction('move-window-by', { + deltaLeft, + deltaTop, + positioningOptions, + ...this.identity + }) + .then(() => undefined); + } + /** + * Moves the window to a specified location. + * @param left The left position of the window + * @param top The top position of the window + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.moveTo.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function moveTo(left, top) { + * const win = await createWin(); + * return await win.moveTo(left, top) + * } + * + * moveTo(580, 300).then(() => console.log('Moved')).catch(err => console.log(err)) + * ``` + */ + moveTo(left, top, positioningOptions) { + return this.wire + .sendAction('move-window', { + left, + top, + positioningOptions, + ...this.identity + }) + .then(() => undefined); + } + /** + * Resizes the window by a specified amount. + * @param deltaWidth The change in the width of the window + * @param deltaHeight The change in the height of the window + * @param anchor Specifies a corner to remain fixed during the resize. + * Can take the values: "top-left", "top-right", "bottom-left", or "bottom-right". + * If undefined, the default is "top-left" + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.resizeBy.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function resizeBy(left, top, anchor) { + * const win = await createWin(); + * return await win.resizeBy(left, top, anchor) + * } + * + * resizeBy(580, 300, 'top-right').then(() => console.log('Resized')).catch(err => console.log(err)); + * ``` + */ + resizeBy(deltaWidth, deltaHeight, anchor, positioningOptions) { + return this.wire + .sendAction('resize-window-by', { + deltaWidth: Math.floor(deltaWidth), + deltaHeight: Math.floor(deltaHeight), + anchor, + positioningOptions, + ...this.identity + }) + .then(() => undefined); + } + /** + * Resizes the window to the specified dimensions. + * @param width The change in the width of the window + * @param height The change in the height of the window + * @param anchor Specifies a corner to remain fixed during the resize. + * Can take the values: "top-left", "top-right", "bottom-left", or "bottom-right". + * If undefined, the default is "top-left" + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.resizeTo.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function resizeTo(left, top, anchor) { + * const win = await createWin(); + * return await win.resizeTo(left, top, anchor); + * } + * + * resizeTo(580, 300, 'top-left').then(() => console.log('Resized')).catch(err => console.log(err)); + * ``` + */ + resizeTo(width, height, anchor, positioningOptions) { + return this.wire + .sendAction('resize-window', { + width: Math.floor(width), + height: Math.floor(height), + anchor, + positioningOptions, + ...this.identity + }) + .then(() => undefined); + } + /** + * Restores the window to its normal state (i.e., unminimized, unmaximized). + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.restore.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function restore() { + * const win = await createWin(); + * return await win.restore(); + * } + * + * restore().then(() => console.log('Restored')).catch(err => console.log(err)); + * ``` + */ + restore() { + return this.wire.sendAction('restore-window', this.identity).then(() => undefined); + } + /** + * Will bring the window to the front of the entire stack and give it focus. + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.setAsForeground.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function setAsForeground() { + * const win = await createWin(); + * return await win.setAsForeground() + * } + * + * setAsForeground().then(() => console.log('In the foreground')).catch(err => console.log(err)); + * ``` + */ + setAsForeground() { + return this.wire.sendAction('set-foreground-window', this.identity).then(() => undefined); + } + /** + * Sets the window's size and position. + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.setBounds.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function setBounds(bounds) { + * const win = await createWin(); + * return await win.setBounds(bounds); + * } + * + * setBounds({ + * height: 100, + * width: 200, + * top: 400, + * left: 400 + * }).then(() => console.log('Bounds set to window')).catch(err => console.log(err)); + * ``` + */ + setBounds(bounds, positioningOptions) { + return this.wire + .sendAction('set-window-bounds', { ...bounds, ...this.identity, positioningOptions }) + .then(() => undefined); + } + /** + * Shows the window if it is hidden. + * @param force Show will be prevented from showing when force is false and + * ‘show-requested’ has been subscribed to for application’s main window. + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.show.html', + * autoShow: false + * }); + * return await app.getWindow(); + * } + * + * async function show() { + * const win = await createWin(); + * return await win.show() + * } + * + * show().then(() => console.log('Showing')).catch(err => console.log(err)); + * ``` + */ + show(force = false) { + return this.wire.sendAction('show-window', { force, ...this.identity }).then(() => undefined); + } + /** + * Shows the window if it is hidden at the specified location. + * + * @param left The left position of the window in pixels + * @param top The top position of the window in pixels + * @param force Show will be prevented from closing when force is false and + * ‘show-requested’ has been subscribed to for application’s main window + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.showAt.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * + * async function showAt(left, top) { + * const win = await createWin(); + * return await win.showAt(left, top) + * } + * + * showAt(580, 300).then(() => console.log('Showing at')).catch(err => console.log(err)); + * ``` + */ + showAt(left, top, force = false) { + return this.wire + .sendAction('show-at-window', { + force, + left: Math.floor(left), + top: Math.floor(top), + ...this.identity + }) + .then(() => undefined); + } + /** + * Shows the Chromium Developer Tools + * + * @tutorial Window.showDeveloperTools + */ + /** + * Updates the window using the passed options. + * + * @remarks Values that are objects are deep-merged, overwriting only the values that are provided. + * @param options Changes a window's options that were defined upon creation. See tutorial + * + * @example + * ```js + * async function updateOptions() { + * const win = await fin.Window.getCurrent(); + * return win.updateOptions({maxWidth: 100}); + * } + * updateOptions().then(() => console.log('options is updated')).catch(err => console.error(err)); + * ``` + */ + updateOptions(options) { + return this.wire.sendAction('update-window-options', { options, ...this.identity }).then(() => undefined); + } + /** + * Provides credentials to authentication requests + * @param userName userName to provide to the authentication challenge + * @param password password to provide to the authentication challenge + * + * @example + * ```js + * fin.Application.wrap({uuid: 'OpenfinPOC'}).then(app => { + * app.on('window-auth-requested', evt => { + * let win = fin.Window.wrap({ uuid: evt.uuid, name: evt.name}); + * win.authenticate('userName', 'P@assw0rd').then(()=> console.log('authenticated')).catch(err => console.log(err)); + * }); + * }); + * ``` + */ + authenticate(userName, password) { + return this.wire + .sendAction('window-authenticate', { userName, password, ...this.identity }) + .then(() => undefined); + } + /** + * Shows a menu on the window. + * + * @remarks Returns a promise that resolves when the user has either selected an item or closed the menu. (This may take longer than other apis). + * Resolves to an object with `{result: 'clicked', data }` where data is the data field on the menu item clicked, or `{result 'closed'}` when the user doesn't select anything. + * Calling this method will close previously opened menus. + * @experimental + * @param options + * @typeParam Data User-defined shape for data returned upon menu item click. Should be a + * [union](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) + * of all possible data shapes for the entire menu, and the click handler should process + * these with a "reducer" pattern. + * @example + * This could be used to show a drop down menu over views in a platform window: + * ```js + * const template = [ + * { + * label: 'Menu Item 1', + * data: 'hello from item 1' + * }, + * { type: 'separator' }, + * { + * label: 'Menu Item 2', + * type: 'checkbox', + * checked: true, + * data: 'The user clicked the checkbox' + * }, + * { + * label: 'see more', + * enabled: false, + * submenu: [ + * { label: 'submenu 1', data: 'hello from submenu' } + * ] + * } + * ] + * fin.me.showPopupMenu({ template }).then(r => { + * if (r.result === 'closed') { + * console.log('nothing happened'); + * } else { + * console.log(r.data) + * } + * }) + * ``` + * + * Overriding the built in context menu (note: that this can be done per element or document wide): + * ```js + * document.addEventListener('contextmenu', e => { + * e.preventDefault(); + * const template = [ + * { + * label: 'Menu Item 1', + * data: 'hello from item 1' + * }, + * { type: 'separator' }, + * { + * label: 'Menu Item 2', + * type: 'checkbox', + * checked: true, + * data: 'The user clicked the checkbox' + * }, + * { + * label: 'see more', + * enabled: false, + * submenu: [ + * { label: 'submenu 1', data: 'hello from submenu' } + * ] + * } + * ] + * fin.me.showPopupMenu({ template, x: e.x, y: e.y }).then(r => { + * if (r.result === 'closed') { + * console.log('nothing happened'); + * } else { + * console.log(r.data) + * } + * }) + * }) + * ``` + */ + async showPopupMenu(options) { + const { payload } = await this.wire.sendAction('show-popup-menu', { options, ...this.identity }); + return payload.data; + } + /** + * Closes the window's popup menu, if one exists. + * @experimental + * + * @remarks Only one popup menu will ever be showing at a time. Calling `showPopupMenu` will automatically close + * any existing popup menu. + * + * + * @example + * This could be used to close a popup menu if the user's mouse leaves an element for example. + * + * ```js + * await fin.me.closePopupMenu(); + * ``` + */ + async closePopupMenu() { + return this.wire.sendAction('close-popup-menu', { ...this.identity }).then(() => undefined); + } + /** + * Dispatch a result to the caller of `showPopupWindow`. + * + * @remarks If this window isn't currently being shown as a popup, this call will silently fail. + * @param data Serializable data to send to the caller window. + * + * @example + * ```js + * await fin.me.dispatchPopupResult({ + * foo: 'bar' + * }); + * ``` + */ + async dispatchPopupResult(data) { + this.wire.sendAction('window-dispatch-popup-result', this.identity).catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + await this.wire.sendAction('dispatch-popup-result', { data, ...this.identity }); + } + /** + * Prints the contents of the window. + * + * @param options Configuration for the print task. + * @remarks When `silent` is set to `true`, the API will pick the system's default printer if deviceName is empty + * and the default settings for printing. + * + * Use the CSS style `page-break-before: always;` to force print to a new page. + * + * @example + * ```js + * const win = fin.Window.getCurrentSync(); + * + * win.print({ silent: false, deviceName: 'system-printer-name' }).then(() => { + * console.log('print call has been sent to the system'); + * }); + * ``` + * + * If a window has embedded views, those views will not print by default. To print a window's contents including embedded views, + * use the `content` option: + * + * ```js + * const win = fin.Window.getCurrentSync(); + * + * // Print embedded views + * win.print({ content: 'views' }); + * + * // Print screenshot of current window + * win.print({ content: 'screenshot' }) + * ``` + * + * When `content` is set to `views`, the embedded views in the platform window will be concatenated and printed as + * individual pages. If `includeSelf` is set to `true`, the platform window itself will be printed as the first + * page - be aware that this page will *not* include the embedded views - it will only include the contents of + * the platform window itself (e.g. tab stacks), with blank spaces where the view contents would be embedded. + * + * Due to a known issue, view contents that are not visible at the time `print` is called will not appear when + * printing `contents: views`. This includes views that are obscured behind other active UI elements. + * + * To print the views embedded in their page context, set `content` to `screenshot`. + */ + async print(options = { content: 'self' }) { + switch (options.content) { + case undefined: + case 'self': + return super.print(options); + case 'screenshot': + return this.wire.sendAction('print-screenshot', this.identity).then(() => undefined); + case 'views': + return this.wire.sendAction('print-views', { ...this.identity, options }).then(() => undefined); + default: + return undefined; + } + } + } + Instance$7._Window = _Window; + return Instance$7; +} + +var hasRequiredFactory$1; + +function requireFactory$1 () { + if (hasRequiredFactory$1) return Factory$8; + hasRequiredFactory$1 = 1; + Object.defineProperty(Factory$8, "__esModule", { value: true }); + Factory$8._WindowModule = void 0; + const base_1 = base; + const validate_1 = validate; + const Instance_1 = requireInstance(); + /** + * Static namespace for OpenFin API methods that interact with the {@link _Window} class, available under `fin.Window`. + */ + class _WindowModule extends base_1.Base { + /** + * Asynchronously returns an API handle for the given Window identity. + * + * @remarks Wrapping a Window identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a Window throughout its entire lifecycle. + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.wrap.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * createWin().then(() => fin.Window.wrap({ uuid: 'app-1', name: 'myApp' })) + * .then(win => console.log('wrapped window')) + * .catch(err => console.log(err)); + * ``` + */ + async wrap(identity) { + this.wire.sendAction('window-wrap').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1._Window(this.wire, identity); + } + /** + * Synchronously returns an API handle for the given Window identity. + * + * @remarks Wrapping a Window identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a Window throughout its entire lifecycle. + * + * @example + * ```js + * async function createWin() { + * const app = await fin.Application.start({ + * name: 'myApp', + * uuid: 'app-1', + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.wrapSync.html', + * autoShow: true + * }); + * return await app.getWindow(); + * } + * await createWin(); + * let win = fin.Window.wrapSync({ uuid: 'app-1', name: 'myApp' }); + * ``` + */ + wrapSync(identity) { + this.wire.sendAction('window-wrap-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1._Window(this.wire, identity); + } + /** + * Creates a new Window. + * @param options - Window creation options + * + * @example + * ```js + * async function createWindow() { + * const winOption = { + * name:'child', + * defaultWidth: 300, + * defaultHeight: 300, + * url: 'https://cdn.openfin.co/docs/javascript/stable/tutorial-Window.create.html', + * frame: true, + * autoShow: true + * }; + * return await fin.Window.create(winOption); + * } + * + * createWindow().then(() => console.log('Window is created')).catch(err => console.log(err)); + * ``` + */ + create(options) { + this.wire.sendAction('create-window').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const win = new Instance_1._Window(this.wire, { uuid: this.me.uuid, name: options.name }); + return win.createWindow(options); + } + /** + * Asynchronously returns a Window object that represents the current window + * + * @example + * ```js + * fin.Window.getCurrent() + * .then(wnd => console.log('current window')) + * .catch(err => console.log(err)); + * + * ``` + */ + getCurrent() { + this.wire.sendAction('get-current-window').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (!this.wire.me.isWindow) { + throw new Error('You are not in a Window context'); + } + const { uuid, name } = this.wire.me; + return this.wrap({ uuid, name }); + } + /** + * Synchronously returns a Window object that represents the current window + * + * @example + * ```js + * const wnd = fin.Window.getCurrentSync(); + * const info = await wnd.getInfo(); + * console.log(info); + * + * ``` + */ + getCurrentSync() { + this.wire.sendAction('get-current-window-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (!this.wire.me.isWindow) { + throw new Error('You are not in a Window context'); + } + const { uuid, name } = this.wire.me; + return this.wrapSync({ uuid, name }); + } + } + Factory$8._WindowModule = _WindowModule; + return Factory$8; +} + +var hasRequiredWindow; + +function requireWindow () { + if (hasRequiredWindow) return window$1; + hasRequiredWindow = 1; + (function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + /** + * Entry points for the OpenFin `Window` API (`fin.Window`). + * + * * {@link _WindowModule} contains static members of the `Window` API, accessible through `fin.Window`. + * * {@link _Window} describes an instance of an OpenFin Window, e.g. as returned by `fin.Window.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * Underscore prefixing of OpenFin types that alias DOM entities will be fixed in a future version. + * + * @packageDocumentation + */ + __exportStar(requireFactory$1(), exports); + __exportStar(requireInstance(), exports); + } (window$1)); + return window$1; +} + +/** + * Entry point for the OpenFin `System` API (`fin.System`). + * + * * {@link System} contains static members of the `System` API (available under `fin.System`) + * + * @packageDocumentation + */ +Object.defineProperty(system, "__esModule", { value: true }); +system.System = void 0; +const base_1$i = base; +const transport_errors_1$1 = transportErrors; +const window_1 = requireWindow(); +const events_1$6 = require$$0; +/** + * An object representing the core of OpenFin Runtime. Allows the developer + * to perform system-level actions, such as accessing logs, viewing processes, + * clearing the cache and exiting the runtime as well as listen to {@link OpenFin.SystemEvents system events}. + * + */ +class System extends base_1$i.EmitterBase { + /** + * @internal + */ + constructor(wire) { + super(wire, 'system'); + } + sendExternalProcessRequest(action, options) { + return new Promise((resolve, reject) => { + const exitEventKey = 'external-process-exited'; + let processUuid; + let exitPayload; + let externalProcessExitHandler; + let ofWindow; + if (typeof options.listener === 'function') { + externalProcessExitHandler = (payload) => { + const data = payload || {}; + exitPayload = { + topic: 'exited', + uuid: data.processUuid || '', + exitCode: data.exitCode || 0 + }; + if (processUuid === payload.processUuid) { + options.listener(exitPayload); + ofWindow.removeListener(exitEventKey, externalProcessExitHandler); + } + }; + // window constructor expects the name is not undefined + if (!this.wire.me.name) { + this.wire.me.name = this.wire.me.uuid; + } + ofWindow = new window_1._Window(this.wire, this.wire.me); + ofWindow.on(exitEventKey, externalProcessExitHandler); + } + this.wire + .sendAction(action, options) + .then(({ payload }) => { + processUuid = payload.data.uuid; + resolve(payload.data); + if (exitPayload && processUuid === exitPayload.uuid) { + options.listener(exitPayload); + ofWindow.removeListener(exitEventKey, externalProcessExitHandler); + } + }) + .catch((err) => { + if (ofWindow) { + ofWindow.removeListener(exitEventKey, externalProcessExitHandler); + } + reject(err); + }); + }); + } + /** + * Returns the version of the runtime. The version contains the major, minor, + * build and revision numbers. + * + * @example + * ```js + * fin.System.getVersion().then(v => console.log(v)).catch(err => console.log(err)); + * ``` + */ + getVersion() { + return this.wire.sendAction('get-version').then(({ payload }) => payload.data); + } + /** + * Clears cached data containing application resource + * files (images, HTML, JavaScript files), cookies, and items stored in the + * Local Storage. + * @param options - See below for details. + * + * @remarks For more information on the accepted options, see the following pages: + * * cache: browsing data cache for html files and images ([caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching)) + * * cookies: browser [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) + * * localStorage: browser data that can be used across sessions ([local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)) + * * appcache: html5 [application cache](https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache) + * @example + * ```js + * const clearCacheOptions = { + * appcache: true, + * cache: true, + * cookies: true, + * localStorage: true + * }; + * fin.System.clearCache(clearCacheOptions).then(() => console.log('Cache cleared')).catch(err => console.log(err)); + * ``` + * + */ + clearCache(options) { + return this.wire.sendAction('clear-cache', options).then(() => undefined); + } + /** + * Clears all cached data when OpenFin Runtime exits. + * + * @example + * ```js + * fin.System.deleteCacheOnExit().then(() => console.log('Deleted Cache')).catch(err => console.log(err)); + * ``` + */ + deleteCacheOnExit() { + return this.wire.sendAction('delete-cache-request').then(() => undefined); + } + /** + * Exits the Runtime. + * + * @example + * ```js + * fin.System.exit().then(() => console.log('exit')).catch(err => console.log(err)); + * ``` + */ + exit() { + return this.wire.sendAction('exit-desktop').then(() => undefined); + } + /** + * Fetches a JSON manifest using the browser process and returns a Javascript object. + * @param manifestUrl The URL of the manifest to fetch. + * + * @example + * ```js + * const manifest = await fin.System.fetchManifest('https://www.path-to-manifest.com'); + * console.log(manifest); + * ``` + */ + async fetchManifest(manifestUrl) { + const { payload: { data } } = await this.wire.sendAction('fetch-manifest', { manifestUrl }); + return data; + } + /** + * Writes any unwritten cookies data to disk. + * + * @example + * ```js + * fin.System.flushCookieStore() + * .then(() => console.log('success')) + * .catch(err => console.error(err)); + * ``` + */ + flushCookieStore() { + return this.wire.sendAction('flush-cookie-store').then(() => undefined); + } + /** + * Retrieves an array of data (name, ids, bounds) for all application windows. + * + * @example + * ```js + * fin.System.getAllWindows().then(wins => console.log(wins)).catch(err => console.log(err)); + * ``` + */ + getAllWindows() { + return this.wire.sendAction('get-all-windows').then(({ payload }) => payload.data); + } + /** + * Retrieves an array of data for all applications. + * + * @example + * ```js + * fin.System.getAllApplications().then(apps => console.log(apps)).catch(err => console.log(err)); + * ``` + */ + getAllApplications() { + return this.wire.sendAction('get-all-applications').then(({ payload }) => payload.data); + } + /** + * Retrieves the command line argument string that started OpenFin Runtime. + * + * @example + * ```js + * fin.System.getCommandLineArguments().then(args => console.log(args)).catch(err => console.log(err)); + * ``` + */ + getCommandLineArguments() { + return this.wire.sendAction('get-command-line-arguments').then(({ payload }) => payload.data); + } + /** + * Get the current state of the crash reporter. + * + * @example + * ```js + * fin.System.getCrashReporterState().then(state => console.log(state)).catch(err => console.log(err)); + * ``` + */ + async getCrashReporterState() { + const { payload: { data: { diagnosticMode, isRunning } } } = await this.wire.sendAction('get-crash-reporter-state'); + console.warn('diagnosticMode property is deprecated. It will be removed in a future version'); + return { + // diagnosticMode will be removed in a future version + diagnosticMode, + diagnosticsMode: diagnosticMode, + isRunning + }; + } + /** + * Start the crash reporter if not already running. + * @param options - configure crash reporter + * + * @remarks You can optionally specify `diagnosticsMode` to have the logs sent to + * OpenFin on runtime close. (NOTE: `diagnosticsMode` will turn on verbose logging and disable the sandbox + * for newly launched renderer processes. See https://developers.openfin.co/of-docs/docs/debugging#diagnostics-mode for + * more details.) + * + * @example + * ```js + * fin.System.startCrashReporter({diagnosticsMode: true}).then(reporter => console.log(reporter)).catch(err => console.log(err)); + * ``` + */ + async startCrashReporter(options) { + const opts = options; + const newOpts = { ...opts, diagnosticMode: opts.diagnosticsMode || opts.diagnosticMode }; + const { payload: { data: { diagnosticMode, isRunning } } } = await this.wire.sendAction('start-crash-reporter', newOpts); + return { + // diagnosticMode will be removed in a future version + diagnosticMode, + diagnosticsMode: diagnosticMode, + isRunning + }; + } + /** + * Returns a hex encoded hash of the machine id and the currently logged in user name. + * This is the recommended way to uniquely identify a user / machine combination. + * + * @remarks For Windows systems this is a sha256 hash of the machine ID set in the registry key: + * `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid` and `USERNAME`. + * + * For OSX systems, a native-level call is used to get the machine ID. + * + * @example + * ```js + * fin.System.getUniqueUserId().then(id => console.log(id)).catch(err => console.log(err)); + * ``` + */ + getUniqueUserId() { + return this.wire.sendAction('get-unique-user-id').then(({ payload }) => payload.data); + } + /** + * Retrieves a frame info object for the uuid and name passed in + * @param uuid - The UUID of the target. + * @param name - The name of the target. + * + * @remarks The possible types are 'window', 'iframe', 'external connection' or 'unknown'. + * @example + * ```js + * const entityUuid = 'OpenfinPOC'; + * const entityName = '40c74b5d-ed98-40f7-853f-e3d3c2699175'; + * fin.System.getEntityInfo(entityUuid, entityName).then(info => console.log(info)).catch(err => console.log(err)); + * + * // example info shape + * { + * "uuid": "OpenfinPOC", + * "name": "40c74b5d-ed98-40f7-853f-e3d3c2699175", + * "parent": { + * "uuid": "OpenfinPOC", + * "name": "OpenfinPOC" + * }, + * "entityType": "iframe" + * } + * ``` + */ + getEntityInfo(uuid, name) { + return this.wire.sendAction('get-entity-info', { uuid, name }).then(({ payload }) => payload.data); + } + /** + * Gets the value of a given environment variable on the computer on which the runtime is installed + * + * @example + * ```js + * fin.System.getEnvironmentVariable('HOME').then(env => console.log(env)).catch(err => console.log(err)); + * ``` + */ + getEnvironmentVariable(envName) { + return this.wire + .sendAction('get-environment-variable', { + environmentVariables: envName + }) + .then(({ payload }) => payload.data); + } + /** + * Get currently focused Window. + * If a View currently has focus, returns the identity of View's parent Window. + * Use {@link Window._Window#getFocusedContent Window.getFocusedContent} to directly access currently focused Window or View. + * + * @example + * ```js + * fin.System.getFocusedWindow().then(winInfo => console.log(winInfo)).catch(err => console.log(err)); + * ``` + */ + getFocusedWindow() { + return this.wire.sendAction('get-focused-window').then(({ payload }) => payload.data); + } + /** + * Get currently focused content. Returns identity of entity with `entityType`. + * + * @example + * ```js + * fin.System.getFocusedContent().then(contentIdentity => console.log(contentIdentity)).catch(err => console.log(err)); + * ``` + */ + getFocusedContent() { + return this.wire.sendAction('get-focused-content').then(({ payload }) => payload.data); + } + /** + * Returns information about the given app's certification status + * + * @example + * ```js + * const manifestUrl = "http://localhost:1234/app.json" + * try { + * const certificationInfo = await fin.System.isAppCertified(manifestUrl); + * } catch(err) { + * console.error(err) + * } + * ``` + */ + async isAppCertified(manifestUrl) { + const { payload: { data: { certifiedInfo } } } = await this.wire.sendAction('is-app-certified', { manifestUrl }); + return certifiedInfo; + } + /** + * Returns an array of all the installed runtime versions in an object. + * + * @example + * ```js + * fin.System.getInstalledRuntimes().then(runtimes => console.log(runtimes)).catch(err => console.log(err)); + * ``` + */ + // incompatible with standalone node process. + getInstalledRuntimes() { + return this.wire.sendAction('get-installed-runtimes').then(({ payload }) => payload.data.runtimes); + } + // incompatible with standalone node process. + async getInstalledApps() { + const { payload: { data: { installedApps } } } = await this.wire.sendAction('get-installed-apps'); + return installedApps; + } + /** + * Retrieves the contents of the log with the specified filename. + * @param options A object that id defined by the GetLogRequestType interface + * + * @example + * ```js + * async function getLog() { + * const logs = await fin.System.getLogList(); + * return await fin.System.getLog(logs[0]); + * } + * + * getLog().then(log => console.log(log)).catch(err => console.log(err)); + * ``` + */ + getLog(options) { + return this.wire.sendAction('view-log', options).then(({ payload }) => payload.data); + } + /** + * Returns a unique identifier (UUID) provided by the machine. + * + * @example + * ```js + * fin.System.getMachineId().then(id => console.log(id)).catch(err => console.log(err)); + * ``` + */ + getMachineId() { + return this.wire.sendAction('get-machine-id').then(({ payload }) => payload.data); + } + /** + * Returns the minimum (inclusive) logging level that is currently being written to the log. + * + * @example + * ```js + * fin.System.getMinLogLevel().then(level => console.log(level)).catch(err => console.log(err)); + * ``` + */ + getMinLogLevel() { + return this.wire.sendAction('get-min-log-level').then(({ payload }) => payload.data); + } + /** + * Retrieves an array containing information for each log file. + * + * @example + * ```js + * fin.System.getLogList().then(logList => console.log(logList)).catch(err => console.log(err)); + * ``` + */ + getLogList() { + return this.wire.sendAction('list-logs').then(({ payload }) => payload.data); + } + /** + * Retrieves an object that contains data about the monitor setup of the + * computer that the runtime is running on. + * + * @example + * ```js + * fin.System.getMonitorInfo().then(monitorInfo => console.log(monitorInfo)).catch(err => console.log(err)); + * ``` + */ + getMonitorInfo() { + return this.wire.sendAction('get-monitor-info').then(({ payload }) => payload.data); + } + /** + * Returns the mouse in virtual screen coordinates (left, top). + * + * @example + * ```js + * fin.System.getMousePosition().then(mousePosition => console.log(mousePosition)).catch(err => console.log(err)); + * ``` + */ + getMousePosition() { + return this.wire.sendAction('get-mouse-position').then(({ payload }) => payload.data); + } + /** + * Retrieves an array of all of the runtime processes that are currently + * running. Each element in the array is an object containing the uuid + * and the name of the application to which the process belongs. + * @deprecated Please use our new set of process APIs: + * {@link Window._Window#getProcessInfo Window.getProcessInfo} + * {@link View.View#getProcessInfo View.getProcessInfo} + * {@link Application.Application#getProcessInfo Application.getProcessInfo} + * {@link System#getAllProcessInfo System.getAllProcessInfo} + * + * @example + * ```js + * fin.System.getProcessList().then(ProcessList => console.log(ProcessList)).catch(err => console.log(err)); + * ``` + */ + getProcessList() { + // eslint-disable-next-line no-console + console.warn('System.getProcessList has been deprecated. Please consider using our new process APIs: Window.getProcessInfo, View.getProcessInfo, Application.getProcessInfo, System.getAllProcessInfo'); + return this.wire.sendAction('process-snapshot').then(({ payload }) => payload.data); + } + /** + * Retrieves all process information. + * + * @remarks This includes the browser process and every process associated to all entities (windows and views). + * + * @example + * ```js + * const allProcessInfo = await fin.System.getAllProcessInfo(); + * ``` + * @experimental + */ + async getAllProcessInfo() { + const { payload: { data } } = await this.wire.sendAction('get-all-process-info', this.identity); + return data; + } + /** + * Retrieves the Proxy settings. + * + * @example + * ```js + * fin.System.getProxySettings().then(ProxySetting => console.log(ProxySetting)).catch(err => console.log(err)); + * + * //This response has the following shape: + * { + * config: { + * proxyAddress: "proxyAddress", //the configured Proxy Address + * proxyPort: 0, //the configured Proxy port + * type: "system" //Proxy Type + * }, + * system: { + * autoConfigUrl: "", + * bypass: "", + * enabled: false, + * proxy: "" + * } + * } + * ``` + */ + getProxySettings() { + return this.wire.sendAction('get-proxy-settings').then(({ payload }) => payload.data); + } + /** + * Returns information about the running Runtime in an object. + * + * @example + * ```js + * fin.System.getRuntimeInfo().then(RuntimeInfo => console.log(RuntimeInfo)).catch(err => console.log(err)); + * ``` + */ + getRuntimeInfo() { + return this.wire.sendAction('get-runtime-info').then(({ payload }) => payload.data); + } + /** + * Returns information about the running RVM in an object. + * + * @example + * ```js + * fin.System.getRvmInfo().then(RvmInfo => console.log(RvmInfo)).catch(err => console.log(err)); + * ``` + */ + // incompatible with standalone node process. + getRvmInfo() { + return this.wire.sendAction('get-rvm-info').then(({ payload }) => payload.data); + } + /** + * Retrieves general system information. If you need more detailed information about the + * OS and the currently logged in user, use `fin.System.getOSInfo()` instead. + * + * @example + * ```js + * fin.System.getHostSpecs().then(specs => console.log(specs)).catch(err => console.log(err)); + * ``` + */ + getHostSpecs() { + return this.wire.sendAction('get-host-specs').then(({ payload }) => payload.data); + } + /** + * Retrieves information about the OS and the currently logged in user. + * + * @example + * ```js + * fin.System.getOSInfo().then(specs => console.log(specs)).catch(err => console.log(err)); + * ``` + */ + getOSInfo() { + return this.wire.sendAction('get-os-info').then(({ payload }) => payload.data); + } + /** + * Runs an executable or batch file. A path to the file must be included in options. + *
A uuid may be optionally provided. If not provided, OpenFin will create a uuid for the new process. + *
Note: This method is restricted by default and must be enabled via + * API security settings. Also, this api has an enhanced permission set to make it less dangerous. So application owners can only allow to launch the assets owned by the application, the enabled downloaded files or the restricted executables. + * @param options A object that is defined in the ExternalProcessRequestType interface + * + * @remarks If an unused UUID is provided in options, it will be used. If no UUID is provided, OpenFin will assign one. + * This api has an enhanced permission set to make it less dangerous. So application owners can only allow to launch the + * assets owned by the application, the enabled downloaded files or the restricted executables. + * + * **Note:** Since _appAssets_ relies on the RVM, which is missing on MAC_OS, 'alias' is not available. Instead provide + * the full path e.g. _/Applications/Calculator.app/Contents/MacOS/Calculator_. + * + * @example + * Basic Example: + * ```js + * fin.System.launchExternalProcess({ + * path: 'notepad', + * arguments: '', + * listener: function (result) { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * Promise resolution: + * + * ```js + * //This response has the following shape: + * { + * uuid: "FB3E6E36-0976-4C2B-9A09-FB2E54D2F1BB" // The mapped UUID which identifies the launched process + * } + * ``` + * + * Listener callback: + * ```js + * //This response has the following shape: + * { + * topic: "exited", // Or "released" on a call to releaseExternalProcess + * uuid: "FB3E6E36-0976-4C2B-9A09-FB2E54D2F1BB", // The mapped UUID which identifies the launched process + * exitCode: 0 // Process exit code + * } + * ``` + * + * By specifying a lifetime, an external process can live as long the window/application that launched it or + * persist after the application exits. The default value is null, which is equivalent to 'persist', meaning + * the process lives on after the application exits: + * + * ```js + * fin.System.launchExternalProcess({ + * path: 'notepad', + * arguments: '', + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * }, + * lifetime: 'window' + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * Note: A process that exits when the window/application exits cannot be released via fin.desktop.System.releaseExternalProcess. + * + * By specifying a cwd, it will set current working directory when launching an external process: + * + * ```js + * fin.System.launchExternalProcess({ + * path: 'cmd.exe', + * cwd: 'c:\\temp', + * arguments: '', + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * Example using an alias from app.json appAssets property: + * + * ```json + * "appAssets": [ + * { + * "src": "exe.zip", + * "alias": "myApp", + * "version": "4.12.8", + * "target": "myApp.exe", + * "args": "a b c d" + * }, + * ] + * ``` + * + * ```js + * // When called, if no arguments are passed then the arguments (if any) + * // are taken from the 'app.json' file, from the 'args' parameter + * // of the 'appAssets' Object with the relevant 'alias'. + * fin.System.launchExternalProcess({ + * //Additionally note that the executable found in the zip file specified in appAssets + * //will default to the one mentioned by appAssets.target + * //If the the path below refers to a specific path it will override this default + * alias: 'myApp', + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * Example using an alias but overriding the arguments: + * + * ```json + * "appAssets": [ + * { + * "src": "exe.zip", + * "alias": "myApp", + * "version": "4.12.8", + * "target": "myApp.exe", + * "args": "a b c d" + * }, + * ] + * ``` + * + * ```js + * // If 'arguments' is passed as a parameter it takes precedence + * // over any 'args' set in the 'app.json'. + * fin.System.launchExternalProcess({ + * alias: 'myApp', + * arguments: 'e f g', + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * It is now possible to optionally perform any combination of the following certificate checks + * against an absolute target via `fin.desktop.System.launchExternalProcess()`: + * + * ```js + * "certificate": { + * "serial": "3c a5 ...", // A hex string with or without spaces + * "subject": "O=OpenFin INC., L=New York, ...", // An internally tokenized and comma delimited string allowing partial or full checks of the subject fields + * "publickey": "3c a5 ...", // A hex string with or without spaces + * "thumbprint": "3c a5 ...", // A hex string with or without spaces + * "trusted": true // A boolean indicating that the certificate is trusted and not revoked + * } + * ``` + * + * Providing this information as part of the default configurations for assets in an application's manifest + * will be added in a future RVM update: + * + * ```js + * fin.System.launchExternalProcess({ + * path: 'C:\\Users\\ExampleUser\\AppData\\Local\\OpenFin\\OpenFinRVM.exe', + * arguments: '--version', + * certificate: { + * trusted: true, + * subject: 'O=OpenFin INC., L=New York, S=NY, C=US', + * thumbprint: '‎3c a5 28 19 83 05 fe 69 88 e6 8f 4b 3a af c5 c5 1b 07 80 5b' + * }, + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * ``` + * + * It is possible to launch files that have been downloaded by the user by listening to the window + * `file-download-completed` event and using the `fileUuid` provided by the event: + * + * ```js + * const win = fin.Window.getCurrentSync(); + * win.addListener('file-download-completed', (evt) => { + * if (evt.state === 'completed') { + * fin.System.launchExternalProcess({ + * fileUuid: evt.fileUuid, + * arguments: '', + * listener: (result) => { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => { + * console.log(processIdentity); + * }).catch(error => { + * console.log(error); + * }); + * } + * }); + * ``` + * + * Launching assets specified in the app manifest: + * + * Sample appAssets section in app.json + * ```js + * "appAssets": [ + * { + * "src": "http://filesamples.com/exe.zip", + * "alias": "myApp", + * "version": "4.12.8", + * "target": "myApp.exe", + * "args": "a b c d" + * }, + * { + * "src": "http://examples.com/exe.zip", + * "alias": "myApp2", + * "version": "5.12.8", + * "target": "myApp2.exe", + * "args": "a b c" + * } + * ] + * ``` + * + * This permission allows for launching of all assets specified in the above appAssets section. ("myApp" and "myApp2"): + * + * ```js + * "permissions": { + * "System": { + * "launchExternalProcess": { + * "enabled": true, + * "assets": { + * "enabled": true + * } + * } + * } + * } + * ``` + * + * This permission allows for launching of _only_ the "myApp" asset in the above appAssets section, as defined in `srcRules`: + * ```js + * "permissions": { + * "System": { + * "launchExternalProcess": { + * "enabled": true, + * "assets": { + * "enabled": true + * "srcRules": [ + * { + * "match": [ + * "*://filesamples.com/*" + * ], + * "behavior": "allow" + * }, + * { + * "match": [ + * "" + * ], + * "behavior": "block" + * } + * ] + * } + * } + * } + * } + * ``` + * + * Launching downloaded files: + * ```js + * "permissions": { + * "System": { + * "launchExternalProcess": { + * "enabled": true, + * "downloads": { + * "enabled": true + * } + * } + * } + * } + * ``` + * + * This permission allows to launch all the executables: + * ```js + * "permissions": { + * "System": { + * "launchExternalProcess": { + * "enabled": true, + * "executables": { + * "enabled": true + * } + * } + * } + * } + * ``` + * + * + * This permission only allows launching of executables whose file paths match the corresponding `pathRules`: + * ```js + * "permissions": { + * "System": { + * "launchExternalProcess": { + * "enabled": true, + * "executables": { + * "enabled": true + * "pathRules": [ + * { + * "match": [ + * "/Windows/System32/*.exe" + * ], + * "behavior": "allow" + * }, + * { + * "match": [ + * "*.exe" + * ], + * "behavior": "block" + * } + * ] + * } + * } + * } + * } + * ``` + */ + launchExternalProcess(options) { + return this.sendExternalProcessRequest('launch-external-process', options); + } + /** + * Monitors a running process. A pid for the process must be included in options. + *
A uuid may be optionally provided. If not provided, OpenFin will create a uuid for the new process. + * + * @remarks If an unused uuid is provided in options, it will be used. If no uuid is provided, OpefinFin will assign a uuid. + * @example + * ```js + * fin.System.monitorExternalProcess({ + * pid: 10208, + * uuid: 'my-external-process', // optional + * listener: function (result) { + * console.log('the exit code', result.exitCode); + * } + * }).then(processIdentity => console.log(processIdentity)).catch(err => console.log(err)); + * ``` + */ + monitorExternalProcess(options) { + return this.sendExternalProcessRequest('monitor-external-process', options); + } + /** + * Writes the passed message into both the log file and the console. + * @param level The log level for the entry. Can be either "info", "warning" or "error" + * @param message The log message text + * + * @example + * ```js + * fin.System.log("info", "An example log message").then(() => console.log('Log info message')).catch(err => console.log(err)); + * ``` + */ + log(level, message) { + return this.wire.sendAction('write-to-log', { level, message }).then(() => undefined); + } + /** + * Opens the passed URL in the default web browser. + * + * @remarks It only supports http(s) and fin(s) protocols by default. + * In order to use other custom protocols, they have to be enabled via + * [API security settings](https://developers.openfin.co/docs/api-security). + * File protocol and file path are not supported. + * @param url The URL to open + * + * @example + * ```js + * fin.System.openUrlWithBrowser('https://cdn.openfin.co/docs/javascript/stable/tutorial-System.openUrlWithBrowser.html') + * .then(() => console.log('Opened URL')) + * .catch(err => console.log(err)); + * ``` + * + * Example of permission definition to enable non-default protocols: + * + * Note: permission definition should be specified in an app manifest file if there is no DOS settings. + * Otherwise it has to be specified in both DOS and app manifest files. + * + * ```js + * "permissions": { + * "System": { + * "openUrlWithBrowser": { + * "enabled": true, + * "protocols": [ "msteams", "slack"] + * } + * } + * } + * ``` + */ + openUrlWithBrowser(url) { + return this.wire.sendAction('open-url-with-browser', { url }).then(() => undefined); + } + /** + * Creates a new registry entry under the HKCU root Windows registry key if the given custom protocol name doesn't exist or + * overwrites the existing registry entry if the given custom protocol name already exists. + * + * Note: This method is restricted by default and must be enabled via + * {@link https://developers.openfin.co/docs/api-security API security settings}. It requires RVM 12 or higher version. + * + * + * @remarks These protocols are reserved and cannot be registered: + * - fin + * - fins + * - openfin + * - URI Schemes registered with {@link https://en.wikipedia.org/wiki/List_of_URI_schemes#Official_IANA-registered_schemes IANA} + * + * @throws if a given custom protocol failed to be registered. + * @throws if a manifest URL contains the '%1' string. + * @throws if a manifest URL contains a query string parameter which name equals to the Protocol Launch Request Parameter Name. + * @throws if the full length of the command string that is to be written to the registry exceeds 2048 bytes. + * + * @example + * ```js + * fin.System.registerCustomProtocol({protocolName:'protocol1'}).then(console.log).catch(console.error); + * ``` + */ + async registerCustomProtocol(options) { + if (typeof options !== 'object') { + throw new Error('Must provide an object with a `protocolName` property having a string value.'); + } + await this.wire.sendAction('register-custom-protocol', options); + } + /** + * Removes the registry entry for a given custom protocol. + * + * Note: This method is restricted by default and must be enabled via + * {@link https://developers.openfin.co/docs/api-security API security settings}. It requires RVM 12 or higher version. + * + * + * @remarks These protocols are reserved and cannot be unregistered: + * - fin + * - fins + * - openfin + * - URI Schemes registered with {@link https://en.wikipedia.org/wiki/List_of_URI_schemes#Official_IANA-registered_schemes IANA} + * + * @throws if a protocol entry failed to be removed in registry. + * + * @example + * ```js + * await fin.System.unregisterCustomProtocol('protocol1'); + * ``` + */ + async unregisterCustomProtocol(protocolName) { + await this.wire.sendAction('unregister-custom-protocol', { protocolName }); + } + /** + * Retrieves the registration state for a given custom protocol. + * + * Note: This method is restricted by default and must be enabled via + * {@link https://developers.openfin.co/docs/api-security API security settings}. It requires RVM 12 or higher version. + * + * @remarks These protocols are reserved and cannot get states for them: + * - fin + * - fins + * - openfin + * - URI Schemes registered with {@link https://en.wikipedia.org/wiki/List_of_URI_schemes#Official_IANA-registered_schemes IANA} + * + * + * @example + * ```js + * const protocolState = await fin.System.getCustomProtocolState('protocol1'); + */ + async getCustomProtocolState(protocolName) { + return this.wire.sendAction('get-custom-protocol-state', { protocolName }).then(({ payload }) => payload.data); + } + /** + * Removes the process entry for the passed UUID obtained from a prior call + * of fin.System.launchExternalProcess(). + * @param uuid The UUID for a process obtained from a prior call to fin.desktop.System.launchExternalProcess() + * + * @example + * ```js + * fin.System.launchExternalProcess({ + * path: "notepad", + * listener: function (result) { + * console.log("The exit code", result.exitCode); + * } + * }) + * .then(identity => fin.System.releaseExternalProcess(identity.uuid)) + * .then(() => console.log('Process has been unmapped!')) + * .catch(err => console.log(err)); + * ``` + */ + releaseExternalProcess(uuid) { + return this.wire.sendAction('release-external-process', { uuid }).then(() => undefined); + } + /** + * Shows the Chromium Developer Tools for the specified window + * @param identity This is a object that is defined by the Identity interface + * + * @tutorial System.showDeveloperTools + */ + showDeveloperTools(identity) { + return this.wire.sendAction('show-developer-tools', identity).then(() => undefined); + } + /** + * Attempt to close an external process. The process will be terminated if it + * has not closed after the elapsed timeout in milliseconds. + * + * Note: This method is restricted by default and must be enabled via + * API security settings. + * @param options A object defined in the TerminateExternalRequestType interface + * + * @example + * ```js + * fin.System.launchExternalProcess({ + * path: "notepad", + * listener: function (result) { + * console.log("The exit code", result.exitCode); + * } + * }) + * .then(identity => fin.System.terminateExternalProcess({uuid: identity.uuid, timeout:2000, killTree: false})) + * .then(() => console.log('Terminate the process')) + * .catch(err => console.log(err)); + * ``` + */ + terminateExternalProcess(options) { + return this.wire.sendAction('terminate-external-process', options).then(() => undefined); + } + /** + * Update the OpenFin Runtime Proxy settings. + * @param options A config object defined in the ProxyConfig interface + * + * @example + * ```js + * fin.System.updateProxySettings({proxyAddress:'127.0.0.1', proxyPort:8080, type:'http'}) + * .then(() => console.log('Update proxy successfully')) + * .catch(err => console.error(err)); + * ``` + */ + updateProxySettings(options) { + return this.wire.sendAction('update-proxy', options).then(() => undefined); + } + /** + * Downloads the given application asset. + * + * Note: This method is restricted by default and must be enabled via + * API security settings. + * @param appAsset App asset object + * + * @example + * ```js + * async function downloadAsset() { + * const appAsset = { + * src: `${ location.origin }/assets.zip`, + * alias: 'dirApp', + * version: '1.23.24', + * target: 'assets/run.bat' + * }; + * + * return fin.System.downloadAsset(appAsset, (progress => { + * //Print progress as we download the asset. + * const downloadedPercent = Math.floor((progress.downloadedBytes / progress.totalBytes) * 100); + * console.log(`Downloaded ${downloadedPercent}%`); + * })); + * } + * + * downloadAsset() + * .then(() => console.log('Success')) + * .catch(err => console.error(err)); + * + * ``` + */ + // incompatible with standalone node process. + async downloadAsset(appAsset, progressListener) { + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-empty-function + const noop = () => { }; + let resolve = noop; + let reject = noop; + const downloadCompletePromise = new Promise((y, n) => { + resolve = y; + reject = n; + }); + // node.js environment not supported + if (this.wire.environment.type !== 'openfin') { + throw new transport_errors_1$1.NotSupportedError('downloadAsset only supported in an OpenFin Render process'); + } + const callSite = transport_errors_1$1.RuntimeError.getCallSite(); + const downloadId = this.wire.environment.getNextMessageId().toString(); + const dlProgressKey = `asset-download-progress-${downloadId}`; + const dlErrorKey = `asset-download-error-${downloadId}`; + const dlCompleteKey = `asset-download-complete-${downloadId}`; + const dlProgress = (progress) => { + const p = { + downloadedBytes: progress.downloadedBytes, + totalBytes: progress.totalBytes + }; + progressListener(p); + }; + const cleanListeners = () => { + // TODO: fix internal types + // @ts-expect-error + this.removeListener(dlProgressKey, dlProgress); + }; + const dlError = (payload) => { + cleanListeners(); + const { reason, err: error } = payload; + reject(new transport_errors_1$1.RuntimeError({ reason, error }, callSite)); + }; + const dlComplete = () => { + cleanListeners(); + resolve(); + }; + await Promise.all([ + // TODO: fix internal types + // @ts-expect-error + this.on(dlProgressKey, dlProgress), + // TODO: fix internal types + // @ts-expect-error + this.once(dlErrorKey, dlError), + // TODO: fix internal types + // @ts-expect-error + this.once(dlCompleteKey, dlComplete) + ]); + const downloadOptions = Object.assign(appAsset, { downloadId }); + await this.wire.sendAction('download-asset', downloadOptions).catch((err) => { + cleanListeners(); + throw err; + }); + return downloadCompletePromise; + } + /** + * Downloads a version of the runtime. + * @param options - Download options. + * @param progressListener - called as the runtime is downloaded with progress information. + * + * @remarks Only supported in an OpenFin Render process. + * + * @example + * ```js + * var downloadOptions = { + * //Specific version number required, if given a release channel the call will produce an error. + * version: '9.61.30.1' + * }; + * + * function onProgress(progress) { + * console.log(`${Math.floor((progress.downloadedBytes / progress.totalBytes) * 100)}%`); + * } + * + * fin.System.downloadRuntime(downloadOptions, onProgress).then(() => { + * console.log('Download complete'); + * }).catch(err => { + * console.log(`Download Failed, we could retry: ${err.message}`); + * console.log(err); + * }); + * ``` + */ + downloadRuntime(options, progressListener) { + const callsites = transport_errors_1$1.RuntimeError.getCallSite(); + return new Promise((resolve, reject) => { + // node.js environment not supported + if (this.wire.environment.type !== 'openfin') { + reject(new transport_errors_1$1.NotSupportedError('downloadRuntime only supported in an OpenFin Render process')); + return; + } + const downloadId = this.wire.environment.getNextMessageId().toString(); + const dlProgressKey = `runtime-download-progress-${downloadId}`; + const dlErrorKey = `runtime-download-error-${downloadId}`; + const dlCompleteKey = `runtime-download-complete-${downloadId}`; + const dlProgress = (progress) => { + const p = { + downloadedBytes: progress.downloadedBytes, + totalBytes: progress.totalBytes + }; + progressListener(p); + }; + const cleanListeners = () => { + // TODO: fix internal types + // @ts-expect-error + this.removeListener(dlProgressKey, dlProgress); + }; + const dlError = (payload) => { + cleanListeners(); + const { reason, err: error } = payload; + reject(new transport_errors_1$1.RuntimeError({ reason, error }, callsites)); + }; + const dlComplete = () => { + cleanListeners(); + resolve(); + }; + // TODO: fix internal types + // @ts-expect-error + this.on(dlProgressKey, dlProgress); + // TODO: fix internal types + // @ts-expect-error + this.once(dlErrorKey, dlError); + // TODO: fix internal types + // @ts-expect-error + this.once(dlCompleteKey, dlComplete); + const downloadOptions = Object.assign(options, { downloadId }); + this.wire.sendAction('download-runtime', downloadOptions).catch((err) => { + cleanListeners(); + reject(err); + }); + }); + } + /** + * Download preload scripts from given URLs + * @param scripts - URLs of preload scripts. + * + * @example + * ```js + * const scripts = [ + * { url: 'http://.../preload.js' }, + * { url: 'http://.../preload2.js' } + * ]; + * + * fin.System.downloadPreloadScripts(scripts).then(results => { + * results.forEach(({url, success, error}) => { + * console.log(`URL: ${url}`); + * console.log(`Success: ${success}`); + * if (error) { + * console.log(`Error: ${error}`); + * } + * }); + * }); + * ``` + */ + downloadPreloadScripts(scripts) { + return this.wire.sendAction('download-preload-scripts', { scripts }).then(({ payload }) => payload.data); + } + /** + * Retrieves an array of data (name, ids, bounds) for all application windows. + * + * @example + * ```js + * fin.System.getAllExternalApplications() + * .then(externalApps => console.log('Total external apps: ' + externalApps.length)) + * .catch(err => console.log(err)); + * ``` + */ + getAllExternalApplications() { + return this.wire.sendAction('get-all-external-applications').then(({ payload }) => payload.data); + } + /** + * Retrieves app asset information. + * @param options + * + * @example + * ```js + * fin.System.getAppAssetInfo({alias:'procexp'}).then(assetInfo => console.log(assetInfo)).catch(err => console.log(err)); + * ``` + */ + getAppAssetInfo(options) { + return this.wire.sendAction('get-app-asset-info', options).then(({ payload }) => payload.data); + } + /** + * Get additional info of cookies. + * + * @example + * ```js + * fin.System.getCookies({name: 'myCookie'}).then(cookies => console.log(cookies)).catch(err => console.log(err)); + * ``` + */ + getCookies(options) { + const url = this.wire.environment.getUrl(); + const newOptions = Object.assign(options, { url }); + return this.wire.sendAction('get-cookies', newOptions).then(({ payload }) => payload.data); + } + /** + * Set the minimum log level above which logs will be written to the OpenFin log + * @param The minimum level (inclusive) above which all calls to log will be written + * + * @example + * ```js + * fin.System.setMinLogLevel("verbose").then(() => console.log("log level is set to verbose")).catch(err => console.log(err)); + * ``` + */ + setMinLogLevel(level) { + return this.wire.sendAction('set-min-log-level', { level }).then(() => undefined); + } + /** + * Retrieves the UUID of the computer on which the runtime is installed + * @param uuid The uuid of the running application + * + * @example + * ```js + * fin.System.resolveUuid('OpenfinPOC').then(entity => console.log(entity)).catch(err => console.log(err)); + * ``` + */ + resolveUuid(uuid) { + return this.wire + .sendAction('resolve-uuid', { + entityKey: uuid + }) + .then(({ payload }) => payload.data); + } + /** + * Retrieves an array of data for all external applications + * @param requestingIdentity This object is described in the Identity typedef + * @param data Any data type to pass to the method + * + * @ignore + */ + executeOnRemote(requestingIdentity, data) { + data.requestingIdentity = requestingIdentity; + return this.wire.ferryAction(data); + } + /** + * Reads the specifed value from the registry. + * @remarks This method is restricted by default and must be enabled via + * [API security settings](https://developers.openfin.co/docs/api-security). + * @param rootKey - The registry root key. + * @param subkey - The registry key. + * @param value - The registry value name. + * + * @example + * ```js + * fin.System.readRegistryValue("HKEY_LOCAL_MACHINE", "HARDWARE\\DESCRIPTION\\System", "BootArchitecture").then(val => console.log(val)).catch(err => console.log(err)); + * ``` + * + * See {@link https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx here} for Window's error code definitions. + * + * Example payloads of different registry types: + * + * See list of types {@link https://msdn.microsoft.com/en-us/library/windows/desktop/ms724884(v=vs.85).aspx here}. + * + * ```js + * // REG_DWORD + * { + * data: 1, + * rootKey: "HKEY_LOCAL_MACHINE", + * subkey: "Foo\Bar", + * type: "REG_DWORD", + * value: "Baz" + * } + * + * // REG_QWORD + * { + * data: 13108146671334112, + * rootKey: "HKEY_LOCAL_MACHINE", + * subkey: "Foo\Bar", + * type: "REG_QWORD", + * value: "Baz" + * } + * + * // REG_SZ + * { + * data: "FooBarBaz", + * rootKey: "HKEY_LOCAL_MACHINE", + * subkey: "Foo\Bar", + * type: "REG_SZ", + * value: "Baz" + * } + * + * // REG_EXPAND_SZ + * { + * data: "C:\User\JohnDoe\AppData\Local", + * rootKey: "HKEY_CURRENT_USER", + * subkey: "Foo\Bar", + * type: "REG_EXPAND_SZ", + * value: "Baz" + * } + * + * // REG_MULTI_SZ + * { + * data: [ + * "Foo", + * "Bar", + * "Baz" + * ], + * rootKey: "HKEY_CURRENT_USER", + * subkey: "Foo\Bar", + * type: "REG_MULTI_SZ", + * value: "Baz" + * } + * + * // REG_BINARY + * { + * data: { + * data: [ + * 255, + * 255, + * 0, + * 43, + * 55, + * 0, + * 0, + * 255, + * 255 + * ], + * type: "Buffer" + * }, + * rootKey: "HKEY_CURRENT_USER", + * subkey: "Foo\Bar", + * type: "REG_BINARY", + * value: "Baz" + * } + * ``` + */ + readRegistryValue(rootKey, subkey, value) { + return this.wire + .sendAction('read-registry-value', { + rootKey, + subkey, + value + }) + .then(({ payload }) => payload.data); + } + /** + * This function call will register a unique id and produce a token. + * The token can be used to broker an external connection. + * @param uuid - A UUID for the remote connection. + * + * @example + * ```js + * fin.System.registerExternalConnection("remote-connection-uuid").then(conn => console.log(conn)).catch(err => console.log(err)); + * + * + * // object comes back with + * // token: "0489EAC5-6404-4F0D-993B-92BB8EAB445D", // this will be unique each time + * // uuid: "remote-connection-uuid" + * + * ``` + */ + registerExternalConnection(uuid) { + return this.wire.sendAction('register-external-connection', { uuid }).then(({ payload }) => payload.data); + } + /** + * Returns the json blob found in the [desktop owner settings](https://openfin.co/documentation/desktop-owner-settings/) + * for the specified service. + * @param serviceIdentifier An object containing a name key that identifies the service. + * + * @remarks More information about desktop services can be found [here](https://developers.openfin.co/docs/desktop-services). + * This call will reject if the desktop owner settings file is not present, not correctly formatted, or if the service requested is not configured or configured incorrectly. + * + * @example + * ```js + * // Here we are using the [layouts](https://github.com/HadoukenIO/layouts-service) service. + * fin.System.getServiceConfiguration({name:'layouts'}).then(console.log).catch(console.error); + * ``` + */ + async getServiceConfiguration(serviceIdentifier) { + if (typeof serviceIdentifier.name !== 'string') { + throw new Error('Must provide an object with a `name` property having a string value'); + } + const { name } = serviceIdentifier; + return this.wire.sendAction('get-service-configuration', { name }).then(({ payload }) => payload.data); + } + async getSystemAppConfig(name) { + if (typeof name !== 'string') { + throw new Error('Must provide a string value for name of system app'); + } + return this.wire.sendAction('get-system-app-configuration', { name }).then(({ payload }) => payload.data); + } + /** + * Registers a system shutdown handler so user can do some cleanup before system is shutting down. + * @remarks Once system shutdown starts, you are unable to cancel it. + * @param handler system shutdown handler + * + * @example + * ```js + * fin.System.registerShutdownHandler((shutdownEvent) => { + * // save state or cleanup + * console.log('do some cleanup before shutdown'); + * // Notify app is ready for termination. + * shutdownEvent.proceed(); + * }) + * .then(() => console.log('Shutdown handler registered!')) + * .catch(err => console.log(err)); + * ``` + * @experimental + */ + async registerShutdownHandler(handler) { + this.wire.sendAction('system-register-shutdown-handler').catch((e) => { + // don't expose, analytics-only call + }); + const SystemShutdownEventName = 'system-shutdown'; + const SystemShutdownHandledEventName = 'system-shutdown-handled'; + const { uuid, name } = this.wire.me; + const shutdownHandler = (payload) => { + const proceed = () => { + // notify core that the app is ready for shutdown + this.wire.environment.raiseEvent(`application/${SystemShutdownHandledEventName}`, { + uuid, + name, + topic: 'application' + }); + }; + handler({ proceed }); + }; + this.on(SystemShutdownEventName, shutdownHandler); + } + /** + * Signals the RVM to perform a health check and returns the results as json. + * + * @remarks Requires RVM 5.5+ + * + * @example + * ```js + * try { + * const results = await fin.System.runRvmHealthCheck(); + * console.log(results); + * } catch(e) { + * console.error(e); + * } + * ``` + */ + runRvmHealthCheck() { + return this.wire.sendAction('run-rvm-health-check').then(({ payload }) => payload.data); + } + /** + * Launch application using a manifest URL/path. It differs from Application.startFromManifest in that this API can accept a manifest using the fin protocol. + * @param manifestUrl - The manifest's URL or path. + * @param opts - Parameters that the RVM will use. + * + * @experimental + * @remarks Supports protocols http/s and fin/s, and also a local path. + * + * Note: This API is Windows only. + * + * @example + * + * This API can handle most manifest types. Some examples below. + * + * Traditional: + * ```js + * const manifest = await fin.System.launchManifest( + * 'https://demoappdirectory.openf.in/desktop/config/apps/OpenFin/HelloOpenFin/app.json'); + * console.log(manifest); + * ``` + * + * Platform: + * ```js + * const manifest = await fin.System.launchManifest('https://openfin.github.io/platform-api-project-seed/public.json'); + * console.log(manifest); + * ``` + * + * Launching traditional manifest into a platform: + * ```js + * const manifest = await fin.System.launchManifest( + * 'https://openfin.github.io/platform-api-project-seed/public.json?\ + * $$appManifestUrl=https://demoappdirectory.openf.in/desktop/config/\ + * apps/OpenFin/HelloOpenFin/app.json'); + * console.log(manifest); + * ``` + * + * Launching with RVM options: + * ```js + * const manifest = await fin.System.launchManifest('https://openfin.github.io/platform-api-project-seed/public.json', + * { noUi: true, userAppConfigArgs: { abc: '123', xyz: '789' } }); + * console.log(manifest); + * ``` + * + * Local Path: + * ```js + * const manifest = await fin.System.launchManifest('file://c:\\path\\to\\manifest\\file.json'); + * console.log(manifest); + * ``` + * + * Launching with RVM 'subscribe' option: + * + * This option allows users to subscribe to app version resolver events when + * calling launchManifest with fallbackManifests specified. + * + * ```js + * fin.System.launchManifest('fins://system-apps/notifications/app.json', { subscribe: (launch) => { + * launch.on('app-version-progress', (progress) => { + * console.log("Trying manifest " + progress.manifest) + * }); + * + * launch.on('runtime-status', (status) => { + * console.log("Runtime status: " + JSON.stringify(status)); + * }); + * + * // RVM has successfully found the target runtime version + * launch.on('app-version-complete', (complete) => { + * console.log("Parent app " + complete.srcManifest + " resolved to " + complete.manifest); + * launch.removeAllListeners(); + * }); + * + * // RVM failed to find an available runtime version + * launch.on('app-version-error', (error) => { + * console.log("Failed to resolve " + error.srcManifest + " from the fallbackManifests"); + * launch.removeAllListeners(); + * }); + * } + * }); + * ``` + */ + async launchManifest(manifestUrl, opts = {}) { + const { subscribe, ..._sendOpts } = opts; + const sendOpts = _sendOpts; + if (subscribe) { + const launchEmitter = new events_1$6.EventEmitter(); + subscribe(launchEmitter); + const AppVersionProgressEventName = 'app-version-progress'; + const RuntimeStatusEventName = 'runtime-status'; + const AppVersionCompleteEventName = 'app-version-complete'; + const AppVersionErrorEventName = 'app-version-error'; + // add id to avoid multiple api calls getting duplicated events + const id = this.wire.environment.getNextMessageId().toString(); + sendOpts.appVersionId = id; + const supportedEvents = [ + AppVersionCompleteEventName, + AppVersionProgressEventName, + RuntimeStatusEventName, + AppVersionErrorEventName + ]; + const cleanEventPayload = (payload) => { + // We need to do type castings below to make sure the return type is correct. + const { appVersionId, topic, type: typeWithId, ...rest } = payload; + const type = supportedEvents.find((x) => typeWithId.includes(x)); + return { + ...rest, + type + }; + }; + const appVersionListener = (payload) => { + const cleanPayload = cleanEventPayload(payload); + launchEmitter.emit(cleanPayload.type, cleanPayload); + }; + const removeAllListeners = () => { + this.removeListener(`${AppVersionProgressEventName}.${id}`, appVersionListener); + this.removeListener(`${RuntimeStatusEventName}.${id}`, appVersionListener); + this.removeListener(`${AppVersionCompleteEventName}.${id}`, appVersionListener); + this.removeListener(`${AppVersionErrorEventName}.${id}`, appVersionListener); + this.removeListener(`${AppVersionCompleteEventName}.${id}`, removeAllListeners); + this.removeListener(`${AppVersionErrorEventName}.${id}`, removeAllListeners); + }; + await Promise.all([ + this.on(`${AppVersionProgressEventName}.${id}`, appVersionListener), + this.on(`${RuntimeStatusEventName}.${id}`, appVersionListener), + this.once(`${AppVersionCompleteEventName}.${id}`, appVersionListener), + this.once(`${AppVersionErrorEventName}.${id}`, appVersionListener), + this.once(`${AppVersionCompleteEventName}.${id}`, removeAllListeners), + this.once(`${AppVersionErrorEventName}.${id}`, removeAllListeners) + ]); + } + const response = await this.wire.sendAction('launch-manifest', { + manifestUrl, + opts: sendOpts + }); + return response.payload.data.manifest; + } + /** + * Query permission of a secured api in current context. + * + * @param apiName - The full name of a secured API. + * + * @remarks If a function has a structured permission value, the value of `granted` will reflect the `enabled` key + * of the call's permissions literal. In this case, *permission may still be denied to a call* pending arguments or other + * runtime state. This is indicated with `state: unavailable`. + * + * @example + * ```js + * fin.System.queryPermissionForCurrentContext('System.launchExternalProcess').then(result => console.log(result)).catch(err => console.log(err)); + * + * //This response has the following shape: + * { + * permission: 'System.launchExternalProcess', // api full name + * state: 'granted', // state of permission + * granted: true + * } + * ``` + */ + async queryPermissionForCurrentContext(apiName) { + const identity = { uuid: this.wire.me.uuid, name: this.wire.me.name }; + const response = await this.wire.sendAction('query-permission-for-current-context', { + apiName, + identity + }); + return response.payload.data; + } + // Not documenting, internal use only. + async enableNativeWindowIntegrationProvider(permissions) { + const { payload } = await this.wire.sendAction('enable-native-window-integration-provider', { permissions }); + return payload.data; + } + /** + * (Internal) Register the usage of a component with a platform + * @param options - Object with data and type + * + * @example + * ```js + * async function registerUsage() { + * const app = await fin.System.getCurrent(); + * return await fin.System.registerUsage({ + * type: 'workspace-licensing', + * // example values for the following data object + * data: { + * apiVersion: '1.0', + * componentName: 'home', + * componentVersion: '1.0', + * allowed: true, + * rejectionCode: '' + * } + * }); + * } + * + * registerUsage().then(() => console.log('Successfully registered component application')).catch(err => console.log(err)); + * ``` + */ + async registerUsage({ data, type }) { + await this.wire.sendAction('register-usage', { data, type }); + } + /** + * Returns an array with all printers of the caller and not all the printers on the desktop. + * + * @example + * ```js + * fin.System.getPrinters() + * .then((printers) => { + * printers.forEach((printer) => { + * if (printer.isDefault) { + * console.log(printer); + * } + * }); + * }) + * .catch((err) => { + * console.log(err); + * }); + * ``` + */ + async getPrinters() { + const { payload } = await this.wire.sendAction('system-get-printers'); + return payload.data; + } + /** + * Updates Process Logging values: periodic interval and outlier detection entries and interval. + * @param options Process Logging updatable options. + * + * @remarks When enabling verbose mode, additional process information is logged to the debug.log: + * + * 1. Periodically process usage (memory, cpu, etc) will be logged for each PID along with the windows, views and + * iframes that belong to them. The default is every 30 seconds. Updatable by passing the interval option. + * 2. When Windows and Views are created or navigated the PID they belong to and their options will be logged. + * 3. When Windows and Views are destroyed their last known process usage will be logged. + * 4. Whenever an outlier memory usage is detected it will be logged. By default, on an interval of 5 seconds we will + * collect process usage for all PIDs and when 144 such entries are collected, we will start analyzing the data for any + * possible outliers in the following entries. The interval and maximum number of entries stored in the running buffer + * can be updatable by passing the outlierDetection.interval and outlierDetection.entries options. + * + * @example + * + * ```js + * await fin.System.updateProcessLoggingOptions({ + * interval: 10, + * outlierDetection: { + * interval: 15, + * entries: 200 + * } + * }); + * ``` + */ + async updateProcessLoggingOptions(options) { + await this.wire.sendAction('system-update-process-logging-options', { options }); + } + /** + * Returns domain settings for the current application. + * Initial settings are configured with the defaultDomainSettings application option via manifest. + * Domain settings can be overwritten during runtime with System.setDomainSettings. + * @example + * ```js + * const domainSettings = await fin.System.getDomainSettings(); + * // { + * // "rules": [ + * // { + * // "match": [ + * // "https://openfin.co" + * // ], + * // "options": { + * // "downloadSettings": { + * // "rules": [ + * // { + * // "match": [ + * // "" + * // ], + * // "behavior": "prompt" + * // } + * // ] + * // } + * // } + * // } + * // ] + * // } + * ``` + */ + async getDomainSettings() { + const { payload: { data } } = await this.wire.sendAction('get-domain-settings', this.identity); + return data; + } + /** + * Sets the domain settings for the current application. + * @param domainSettings - domain settings object + * @example + * ```js + * const domainSettings = await fin.System.getDomainSettings(); + * // { + * // "rules": [ + * // { + * // "match": [ + * // "https://openfin.co" + * // ], + * // "options": { + * // "downloadSettings": { + * // "rules": [ + * // { + * // "match": [ + * // "" + * // ], + * // "behavior": "prompt" + * // } + * // ] + * // } + * // } + * // } + * // ] + * // } + * + * // Valid rule behaviors are 'prompt' and 'no-prompt' + * domainSettings.rules[0].options.downloadSettings.rules[0].behavior = 'no-prompt'; + * + * await fin.System.setDomainSettings(domainSettings); + * + * const newDomainSettings = await fin.System.getDomainSettings(); + * // { + * // "rules": [ + * // { + * // "match": [ + * // "https://openfin.co" + * // ], + * // "options": { + * // "downloadSettings": { + * // "rules": [ + * // { + * // "match": [ + * // "" + * // ], + * // "behavior": "no-prompt" + * // } + * // ] + * // } + * // } + * // } + * // ] + * // } + * ``` + */ + async setDomainSettings(domainSettings) { + await this.wire.sendAction('set-domain-settings', { domainSettings, ...this.identity }); + } + /** + * Attempts to install and enable extensions for the security realm. Users may want to call this function in response + * to an `extensions-install-failed` event. Only extensions allowed by every application on the current security realm + * will be installed/enabled. + */ + async refreshExtensions() { + const { payload } = await this.wire.sendAction('refresh-extensions'); + return payload.data; + } + /** + * Gets the currently-installed + */ + async getInstalledExtensions() { + const { payload } = await this.wire.sendAction('get-installed-extensions'); + return payload.data; + } +} +system.System = System; + +var interappbus = {}; + +var refCounter = {}; + +Object.defineProperty(refCounter, "__esModule", { value: true }); +refCounter.RefCounter = void 0; +class RefCounter { + constructor() { + this.topicRefMap = new Map(); + } + // returns the ref count after incrementing + incRefCount(key) { + const refCount = this.topicRefMap.get(key); + let returnCount; + if (!refCount) { + this.topicRefMap.set(key, 1); + returnCount = 1; + } + else { + const newRefCount = refCount + 1; + returnCount = newRefCount; + this.topicRefMap.set(key, newRefCount); + } + return returnCount; + } + // returns the ref count after decrementing, or -1 if the key already had no references + decRefCount(key) { + const refCount = this.topicRefMap.get(key); + let returnCount; + if (refCount) { + const newRefCount = refCount - 1; + this.topicRefMap.set(key, newRefCount); + returnCount = newRefCount; + } + else { + returnCount = -1; + } + return returnCount; + } + // Execute firstAction if it is the first such ref, else execute nonFirstAction. + // In either case the return value is that of the action executed + actOnFirst(key, firstAction, nonFirstAction) { + const numRefs = this.incRefCount(key); + const isFirstRef = numRefs === 1; + return isFirstRef ? firstAction() : nonFirstAction(); + } + // Execute lastAction if it is the first such ref, else execute nonLastAction. + // In either case the return value is that of the action executed + actOnLast(key, lastAction, nonLastAction) { + const numRefs = this.decRefCount(key); + const isLastRef = numRefs === 0; + return isLastRef ? lastAction() : nonLastAction(); + } +} +refCounter.RefCounter = RefCounter; + +var channel$1 = {}; + +var client = {}; + +var channel = {}; + +Object.defineProperty(channel, "__esModule", { value: true }); +channel.ChannelBase = channel.ProtectedItems = void 0; +const resultOrPayload = (func) => async (topic, payload, senderIdentity) => { + const res = await func(topic, payload, senderIdentity); + return res === undefined ? payload : res; +}; +class ProtectedItems { + /** + * @internal + */ + // eslint-disable-next-line no-useless-constructor + constructor(providerIdentity, close) { + this.providerIdentity = providerIdentity; + this.close = close; + } +} +channel.ProtectedItems = ProtectedItems; +class ChannelBase { + static defaultAction(topic) { + throw new Error(`No action registered at target for ${topic}`); + } + constructor() { + this.subscriptions = new Map(); + } + async processAction(topic, payload, senderIdentity) { + try { + const mainAction = this.subscriptions.has(topic) + ? this.subscriptions.get(topic) + : (currentPayload, id) => (this.defaultAction ?? ChannelBase.defaultAction)(topic, currentPayload, id); + const preActionProcessed = this.preAction ? await this.preAction(topic, payload, senderIdentity) : payload; + const actionProcessed = await mainAction(preActionProcessed, senderIdentity); + return this.postAction ? await this.postAction(topic, actionProcessed, senderIdentity) : actionProcessed; + } + catch (e) { + if (this.errorMiddleware) { + return this.errorMiddleware(topic, e, senderIdentity); + } + throw e; + } + } + /** + * Register middleware that fires before the action. + * + * @param func + * + * @example + * + * Channel Provider: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * provider.register('provider-action', (payload, identity) => { + * console.log(payload, identity); + * return { + * echo: payload + * }; + * }); + * + * provider.beforeAction((action, payload, identity) => { + * //The payload can be altered here before handling the action. + * payload.received = Date.now(); + * return payload; + * }); + * + * })(); + * ``` + * + * Channel Client: + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * client.register('client-action', (payload, identity) => { + * console.log(payload, identity); + * return { + * echo: payload + * }; + * }); + * + * client.beforeAction((action, payload, identity) => { + * //The payload can be altered here before handling the action. + * payload.received = Date.now(); + * return payload; + * }); + * + * const providerResponse = await client.dispatch('provider-action', { message: 'Hello From the client' }); + * console.log(providerResponse); + * })(); + * ``` + */ + beforeAction(func) { + if (this.preAction) { + throw new Error('Already registered beforeAction middleware'); + } + this.preAction = resultOrPayload(func); + } + /** + * Register an error handler. This is called before responding on any error. + * + * @param func + * + * Channel Provider: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * provider.register('provider-action', (payload, identity) => { + * console.log(payload); + * throw new Error('Action error'); + * return { + * echo: payload + * }; + * }); + * + * provider.onError((action, error, identity) => { + * console.log('uncaught Exception in action:', action); + * console.error(error); + * }); + * + * })(); + * ``` + * + * Channel Client: + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * client.register('client-action', (payload, identity) => { + * console.log(payload); + * throw new Error('Action error'); + * return { + * echo: payload + * }; + * }); + * + * client.onError((action, error, identity) => { + * console.log('uncaught Exception in action:', action); + * console.error(error); + * }); + * })(); + * ``` + */ + onError(func) { + if (this.errorMiddleware) { + throw new Error('Already registered error middleware'); + } + this.errorMiddleware = func; + } + /** + * Register middleware that fires after the action. + * + * @param func + * + * @remarks If the action does not return the payload, then the afterAction will not have access to the payload object. + * + * @example + * + * Channel Provider: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.register('provider-action', (payload, identity) => { + * return { + * echo: payload + * }; + * }); + * + * await provider.afterAction((action, payload, identity) => { + * //the payload can be altered here after handling the action but before sending an acknowledgement. + * payload.sent = date.now(); + * return payload; + * }); + * + * })(); + * ``` + * + * Channel Client: + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.register('client-action', (payload, identity) => { + * return { + * echo: payload + * }; + * }); + * + * await client.afterAction((action, payload, identity) => { + * //the payload can be altered here after handling the action but before sending an acknowledgement. + * payload.sent = date.now(); + * return payload; + * }); + * + * })(); + * ``` + */ + afterAction(func) { + if (this.postAction) { + throw new Error('Already registered afterAction middleware'); + } + this.postAction = resultOrPayload(func); + } + /** + * Remove an action by action name. + * + * @param action + * + * @example + * + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.register('provider-action', (payload, identity) => { + * console.log(payload); + * return { + * echo: payload + * }; + * }); + * + * await provider.remove('provider-action'); + * + * })(); + * ``` + */ + remove(action) { + this.subscriptions.delete(action); + } + /** + * Registers a default action. This is used any time an action that has not been registered is invoked. + * + * @example + * + * Channel Provider: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.setDefaultAction((action, payload, identity) => { + * console.log(`Client with identity ${JSON.stringify(identity)} has attempted to dispatch unregistered action: ${action}.`); + * + * return { + * echo: payload + * }; + * }); + * + * })(); + * ``` + * + * Channel Client: + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.setDefaultAction((action, payload, identity) => { + * console.log(`Provider with identity ${JSON.stringify(identity)} has attempted to dispatch unregistered action: ${action}.`); + * + * return { + * echo: payload + * }; + * }); + * + * })(); + * ``` + * @param func + */ + setDefaultAction(func) { + if (this.defaultAction) { + throw new Error('default action can only be set once'); + } + else { + this.defaultAction = func; + } + } + /** + * Register an action to be called by dispatching from any channelClient or channelProvider. + * + * @param topic + * @param listener + * + * @remarks The return value will be sent back as an acknowledgement to the original caller. You can throw an + * error to send a negative-acknowledgement and the error will reject the promise returned to the sender by the + * dispatch call. Once a listener is registered for a particular action, it stays in place receiving and responding + * to incoming messages until it is removed. This messaging mechanism works exactly the same when messages are + * dispatched from the provider to a client. However, the provider has an additional publish method that sends messages + * to all connected clients. + * + * Because multiple clients can share the same `name` and `uuid`, in order to distinguish between individual clients, + * the `identity` argument in a provider's registered action callback contains an `endpointId` property. When dispatching + * from a provider to a client, the `endpointId` property must be provided in order to send an action to a specific client. + * + * @example + * + * Channel Provider: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.register('provider-action', (payload, identity) => { + * console.log('Action dispatched by client: ', identity); + * console.log('Payload sent in dispatch: ', payload); + * + * return { echo: payload }; + * }); + * })(); + * ``` + * + * Channel Client: + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.register('client-action', (payload, identity) => { + * console.log('Action dispatched by client: ', identity); + * console.log('Payload sent in dispatch: ', payload); + * + * return { echo: payload }; + * }); + * })(); + * ``` + */ + register(topic, listener) { + if (this.subscriptions.has(topic)) { + throw new Error(`Subscription already registered for action: ${topic}. Unsubscribe before adding new subscription`); + } + else { + this.subscriptions.set(topic, listener); + return true; + } + } +} +channel.ChannelBase = ChannelBase; + +var __classPrivateFieldGet$c = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet$a = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _ChannelClient_protectedObj, _ChannelClient_strategy, _ChannelClient_close; +Object.defineProperty(client, "__esModule", { value: true }); +client.ChannelClient = void 0; +const channel_1$1 = channel; +const channelClientsByEndpointId = new Map(); +/** + * Instance created to enable use of a channel as a client. Allows for communication with the + * {@link ChannelProvider ChannelProvider} by invoking an action on the + * provider via {@link ChannelClient#dispatch dispatch} and to listen for communication + * from the provider by registering an action via {@link ChannelClient#register register}. + * + * ### Synchronous Methods: + * * {@link ChannelClient#onDisconnection onDisconnection(listener)} + * * {@link ChannelClient#register register(action, listener)} + * * {@link ChannelClient#remove remove(action)} + * + * ### Asynchronous Methods: + * * {@link ChannelClient#disconnect disconnect()} + * * {@link ChannelClient#dispatch dispatch(action, payload)} + * + * ### Middleware: + * Middleware functions receive the following arguments: (action, payload, senderId). + * The return value of the middleware function will be passed on as the payload from beforeAction, to the action listener, to afterAction + * unless it is undefined, in which case the original payload is used. Middleware can be used for side effects. + * * {@link ChannelClient#setDefaultAction setDefaultAction(middleware)} + * * {@link ChannelClient#onError onError(middleware)} + * * {@link ChannelClient#beforeAction beforeAction(middleware)} + * * {@link ChannelClient#afterAction afterAction(middleware)} + */ +class ChannelClient extends channel_1$1.ChannelBase { + /** + * @internal + */ + static closeChannelByEndpointId(id) { + const channel = channelClientsByEndpointId.get(id); + if (channel) { + __classPrivateFieldGet$c(channel, _ChannelClient_close, "f").call(channel); + } + } + /** + * @internal + * closes the corresponding channel and invokes the disconnect listener if an event payload is passed. + */ + static handleProviderDisconnect(eventPayload) { + for (const channelClient of channelClientsByEndpointId.values()) { + if (channelClient.providerIdentity.channelId === eventPayload.channelId) { + channelClient.disconnectListener(eventPayload); + __classPrivateFieldGet$c(channelClient, _ChannelClient_close, "f").call(channelClient); + } + } + } + /** + * @internal + */ + constructor(routingInfo, close, strategy) { + super(); + _ChannelClient_protectedObj.set(this, void 0); + _ChannelClient_strategy.set(this, void 0); + // needs to be bound; + this.processAction = (action, payload, senderIdentity) => super.processAction(action, payload, senderIdentity); + _ChannelClient_close.set(this, () => { + channelClientsByEndpointId.delete(this.endpointId); + __classPrivateFieldGet$c(this, _ChannelClient_strategy, "f").close(); + }); + __classPrivateFieldSet$a(this, _ChannelClient_protectedObj, new channel_1$1.ProtectedItems(routingInfo, close), "f"); + this.disconnectListener = () => undefined; + this.endpointId = routingInfo.endpointId; + __classPrivateFieldSet$a(this, _ChannelClient_strategy, strategy, "f"); + channelClientsByEndpointId.set(this.endpointId, this); + strategy.receive(this.processAction); + } + /** + * a read-only provider identity + */ + get providerIdentity() { + const protectedObj = __classPrivateFieldGet$c(this, _ChannelClient_protectedObj, "f"); + return protectedObj.providerIdentity; + } + /** + * Dispatch the given action to the channel provider. Returns a promise that resolves with the response from + * the provider for that action. + * + * @param action + * @param payload + * + * @example + * + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.register('client-action', (payload, identity) => { + * console.log(payload, identity); + * return { + * echo: payload + * }; + * }); + * + * const providerResponse = await client.dispatch('provider-action', { message: 'Hello From the client'}); + * console.log(providerResponse); + * })(); + * ``` + */ + async dispatch(action, payload) { + if (__classPrivateFieldGet$c(this, _ChannelClient_strategy, "f").isEndpointConnected(this.providerIdentity.channelId)) { + return __classPrivateFieldGet$c(this, _ChannelClient_strategy, "f").send(this.providerIdentity.channelId, action, payload); + } + throw new Error('The client you are trying to dispatch from is disconnected from the target provider.'); + } + /** + * Register a listener that is called on provider disconnection. It is passed the disconnection event of the + * disconnecting provider. + * + * @param listener + * + * @example + * + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.onDisconnection(evt => { + * console.log('Provider disconnected', `uuid: ${evt.uuid}, name: ${evt.name}`); + * }); + * })(); + * ``` + */ + onDisconnection(listener) { + this.disconnectListener = (payload) => { + try { + listener(payload); + } + catch (err) { + throw new Error(`Error while calling the onDisconnection callback: ${err.message}`); + } + finally { + this.disconnectListener = () => undefined; + } + }; + } + /** + * Disconnects the client from the channel. + * + * @example + * + * ```js + * (async ()=> { + * const client = await fin.InterApplicationBus.Channel.connect('channelName'); + * + * await client.disconnect(); + * })(); + * ``` + */ + async disconnect() { + await this.sendDisconnectAction(); + __classPrivateFieldGet$c(this, _ChannelClient_close, "f").call(this); + } + async sendDisconnectAction() { + const protectedObj = __classPrivateFieldGet$c(this, _ChannelClient_protectedObj, "f"); + await protectedObj.close(); + } + /** + * @internal + * Writing this as a static to keep code together, but in environments with a wire, this will be DI'd into the protectedObject class as close. + */ + static async wireClose(wire, providerIdentity, endpointId) { + const { channelName, uuid, name } = providerIdentity; + await wire.sendAction('disconnect-from-channel', { + channelName, + uuid, + name, + endpointId + }); + } +} +client.ChannelClient = ChannelClient; +_ChannelClient_protectedObj = new WeakMap(), _ChannelClient_strategy = new WeakMap(), _ChannelClient_close = new WeakMap(); + +var connectionManager = {}; + +var exhaustive = {}; + +Object.defineProperty(exhaustive, "__esModule", { value: true }); +exhaustive.exhaustiveCheck = void 0; +function exhaustiveCheck(value, allowed) { + throw new Error(`Unsupported value: ${value}${allowed ? `\n Supported values are: ${allowed.join('')}` : ''}`); +} +exhaustive.exhaustiveCheck = exhaustiveCheck; + +var strategy$3 = {}; + +var __classPrivateFieldSet$9 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$b = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _ClassicStrategy_wire, _ClassicStrategy_endpointIdentityMap, _ClassicStrategy_pendingMessagesByEndpointId; +Object.defineProperty(strategy$3, "__esModule", { value: true }); +strategy$3.ClassicInfo = strategy$3.ClassicStrategy = void 0; +/* +This is used to abstract out ipc messaging from the channels implementation. It is only concerned with sending messages and registration with the MessageReceiver +*/ +class ClassicStrategy { + constructor(wire, messageReceiver, endpointId, // Provider endpointId is channelId + providerIdentity) { + this.messageReceiver = messageReceiver; + this.endpointId = endpointId; + this.providerIdentity = providerIdentity; + _ClassicStrategy_wire.set(this, void 0); + // Store full endpointIdentity by endpointId of all known endpoints for this strategy instance. + // (clients will only have 1: the provider, the provider will have all clients) + _ClassicStrategy_endpointIdentityMap.set(this, new Map()); + // Store a set of cancellable promises to be able to reject them when client + // connection problems occur + _ClassicStrategy_pendingMessagesByEndpointId.set(this, new Map); + this.send = async (endpointId, action, payload) => { + const to = __classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").get(endpointId); + if (!to) { + throw new Error(`Could not locate routing info for endpoint ${endpointId}`); + } + // as casting to any because typescript complains. The following is only relevant if this is a locally set endpointId on a ClientIdentity. + // We delete these properties to not change backwards compatibility. + const cleanId = { ...to }; + if (cleanId.isLocalEndpointId) { + delete cleanId.endpointId; + } + delete cleanId.isLocalEndpointId; + // grab the promise before awaiting it to save in our pending messages map + const p = __classPrivateFieldGet$b(this, _ClassicStrategy_wire, "f") + .sendAction('send-channel-message', { + ...cleanId, + providerIdentity: this.providerIdentity, + action, + payload + }); + __classPrivateFieldGet$b(this, _ClassicStrategy_pendingMessagesByEndpointId, "f").get(endpointId)?.add(p); + const raw = await p.catch((error) => { + throw new Error(error.message); + }).finally(() => { + // clean up the pending promise + __classPrivateFieldGet$b(this, _ClassicStrategy_pendingMessagesByEndpointId, "f").get(endpointId)?.delete(p); + }); + return raw.payload.data.result; + }; + this.close = async () => { + this.messageReceiver.removeEndpoint(this.providerIdentity.channelId, this.endpointId); + [...__classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").keys()].forEach((id) => this.closeEndpoint(id)); + __classPrivateFieldSet$9(this, _ClassicStrategy_endpointIdentityMap, new Map(), "f"); + }; + __classPrivateFieldSet$9(this, _ClassicStrategy_wire, wire, "f"); + } + onEndpointDisconnect(endpointId, listener) { + // Never fires for 'classic'. + } + receive(listener) { + this.messageReceiver.addEndpoint(listener, this.providerIdentity.channelId, this.endpointId); + } + async closeEndpoint(endpointId) { + const id = __classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").get(endpointId); + __classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").delete(endpointId); + const pendingSet = __classPrivateFieldGet$b(this, _ClassicStrategy_pendingMessagesByEndpointId, "f").get(endpointId); + pendingSet?.forEach((p) => { + const errorMsg = `Channel connection with identity uuid: ${id?.uuid} / name: ${id?.name} / endpointId: ${endpointId} no longer connected.`; + p.cancel(new Error(errorMsg)); + }); + } + isEndpointConnected(endpointId) { + return __classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").has(endpointId); + } + addEndpoint(endpointId, payload) { + __classPrivateFieldGet$b(this, _ClassicStrategy_endpointIdentityMap, "f").set(endpointId, payload.endpointIdentity); + __classPrivateFieldGet$b(this, _ClassicStrategy_pendingMessagesByEndpointId, "f").set(endpointId, new Set()); + } + isValidEndpointPayload(payload) { + return (typeof payload?.endpointIdentity?.endpointId === 'string' || + typeof payload?.endpointIdentity?.channelId === 'string'); + } +} +strategy$3.ClassicStrategy = ClassicStrategy; +_ClassicStrategy_wire = new WeakMap(), _ClassicStrategy_endpointIdentityMap = new WeakMap(), _ClassicStrategy_pendingMessagesByEndpointId = new WeakMap(); +// Arbitrarily starting at 5 to leave the door open to backfilling pre endpointId etc. +strategy$3.ClassicInfo = { version: 5, minimumVersion: 0, type: 'classic' }; + +var strategy$2 = {}; + +var endpoint = {}; + +var errors = {}; + +Object.defineProperty(errors, "__esModule", { value: true }); +errors.errorToPOJO = void 0; +function errorToPOJO(error) { + return { + stack: error.stack, + name: error.name, + message: error.message, + // support the case where stack is empty or missing + toString: () => error.stack || error.toString() + }; +} +errors.errorToPOJO = errorToPOJO; + +var __classPrivateFieldGet$a = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet$8 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _RTCEndpoint_processAction, _RTCEndpoint_disconnectListener; +Object.defineProperty(endpoint, "__esModule", { value: true }); +endpoint.RTCEndpoint = void 0; +/* eslint-disable @typescript-eslint/no-unused-vars */ +const errors_1$1 = errors; +/* +This handles sending RTC messages between RTC connections over the request and response data channels. +*/ +class RTCEndpoint { + static isValidEndpointPayload(payload) { + const isObject = (x) => { + return typeof x === 'object' && x !== null; + }; + return ( + // TODO in factory PR: + // payload.type === 'rtc' && + isObject(payload) && + isObject(payload.endpointIdentity) && + isObject(payload.rtc) && + typeof payload.endpointIdentity.endpointId === 'string'); + } + constructor({ rtc, endpointIdentity }) { + this.responseMap = new Map(); + _RTCEndpoint_processAction.set(this, null); + _RTCEndpoint_disconnectListener.set(this, void 0); + this.connectionStateChangeHandler = (event) => { + if (this.rtc.rtcClient.connectionState !== 'connected') { + this.rtc.rtcClient.removeEventListener('connectionstatechange', this.connectionStateChangeHandler); + this.close(); + if (__classPrivateFieldGet$a(this, _RTCEndpoint_disconnectListener, "f")) { + __classPrivateFieldGet$a(this, _RTCEndpoint_disconnectListener, "f").call(this); + } + } + }; + this.send = async (action, payload) => { + const messageId = `message-${Math.random()}`; + const promise = new Promise((resolve, reject) => { + this.responseMap.set(messageId, { resolve, reject }); + }); + this.rtc.channels.request.send(JSON.stringify({ action, payload, messageId })); + return promise; + }; + this.close = () => { + this.responseMap.forEach((response) => response.reject('Connection has closed.')); + this.responseMap = new Map(); + this.rtc.channels.request.close(); + this.rtc.channels.response.close(); + this.rtc.rtcClient.close(); + }; + this.rtc = rtc; + this.endpointIdentity = endpointIdentity; + this.rtc.channels.response.addEventListener('message', (e) => { + let { data } = e; + if (e.data instanceof ArrayBuffer) { + data = new TextDecoder().decode(e.data); + } + const { messageId, payload, success, error } = JSON.parse(data); + const { resolve, reject } = this.responseMap.get(messageId) ?? {}; + if (resolve && reject) { + this.responseMap.delete(messageId); + if (success) { + resolve(payload); + } + else { + reject(error); + } + } + else { + console.log('Could not find id in responseMap.'); + console.log(e); + } + }); + this.rtc.channels.request.addEventListener('message', async (e) => { + let { data } = e; + if (e.data instanceof ArrayBuffer) { + data = new TextDecoder().decode(e.data); + } + const { messageId, action, payload } = JSON.parse(data); + if (__classPrivateFieldGet$a(this, _RTCEndpoint_processAction, "f")) { + try { + const res = await __classPrivateFieldGet$a(this, _RTCEndpoint_processAction, "f").call(this, action, payload, endpointIdentity); + this.rtc.channels.response.send(JSON.stringify({ + messageId, + payload: res, + success: true + })); + } + catch (error) { + // Check if RTCDataChannel is open before sending, error gets swallowed here in the case where + // client dispatched then closed or disconnected before the dispatch resolves. + if (this.rtc.channels.response.readyState === 'open') { + this.rtc.channels.response.send(JSON.stringify({ + messageId, + error: (0, errors_1$1.errorToPOJO)(error), + success: false + })); + } + } + // Check if RTCDataChannel is open for same reason as catch block above. + } + else if (this.rtc.channels.response.readyState === 'open') { + this.rtc.channels.response.send(JSON.stringify({ + messageId, + success: false, + error: 'Connection not ready.' + })); + } + }); + this.rtc.rtcClient.addEventListener('connectionstatechange', this.connectionStateChangeHandler); + // Disconnect if data channels close unexpectedly, e.g. can happen due to message size > ~255kB (RTCPeerConnection.sctp.maxMessageSizeLimit: 262144) + Object.values(this.rtc.channels).forEach((datachannel) => { + datachannel.onclose = (e) => { + [...this.responseMap.values()].forEach((promise) => promise.reject(new Error('RTCDataChannel closed unexpectedly, this is most commonly caused by message size. Note: RTC Channels have a message size limit of ~255kB.'))); + this.close(); + if (__classPrivateFieldGet$a(this, _RTCEndpoint_disconnectListener, "f")) { + __classPrivateFieldGet$a(this, _RTCEndpoint_disconnectListener, "f").call(this); + } + }; + }); + } + onDisconnect(listener) { + if (!__classPrivateFieldGet$a(this, _RTCEndpoint_disconnectListener, "f")) { + __classPrivateFieldSet$8(this, _RTCEndpoint_disconnectListener, listener, "f"); + } + else { + throw new Error('RTCEndpoint disconnectListener cannot be set twice.'); + } + } + receive(listener) { + if (__classPrivateFieldGet$a(this, _RTCEndpoint_processAction, "f")) { + throw new Error('You have already set a listener for this RTC Endpoint.'); + } + __classPrivateFieldSet$8(this, _RTCEndpoint_processAction, listener, "f"); + } + get connected() { + return this.rtc.rtcClient.connectionState === 'connected'; + } +} +endpoint.RTCEndpoint = RTCEndpoint; +_RTCEndpoint_processAction = new WeakMap(), _RTCEndpoint_disconnectListener = new WeakMap(); + +var strategy$1 = {}; + +var __classPrivateFieldGet$9 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet$7 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _EndpointStrategy_processAction, _EndpointStrategy_endpointMap, _EndpointStrategy_connected; +Object.defineProperty(strategy$1, "__esModule", { value: true }); +strategy$1.EndpointStrategy = void 0; +class EndpointStrategy { + // Need to pass in validate endpoint separately from constructor because ts interfaces don't do well with static methods + constructor(EndpointType, validateEndpoint, StrategyName) { + this.EndpointType = EndpointType; + this.StrategyName = StrategyName; + _EndpointStrategy_processAction.set(this, null); + _EndpointStrategy_endpointMap.set(this, new Map()); + _EndpointStrategy_connected.set(this, true); + this.send = async (endpointId, action, payload) => { + return this.getEndpointById(endpointId).send(action, payload); + }; + this.close = async () => { + if (__classPrivateFieldGet$9(this, _EndpointStrategy_connected, "f")) { + __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").forEach((endpoint) => endpoint.close()); + __classPrivateFieldSet$7(this, _EndpointStrategy_endpointMap, new Map(), "f"); + } + __classPrivateFieldSet$7(this, _EndpointStrategy_connected, false, "f"); + }; + this.isValidEndpointPayload = validateEndpoint; + } + onEndpointDisconnect(endpointId, listener) { + this.getEndpointById(endpointId).onDisconnect(listener); + } + receive(listener) { + if (__classPrivateFieldGet$9(this, _EndpointStrategy_processAction, "f")) { + throw new Error(`You have already set a listener for this ${this.StrategyName} Strategy`); + } + __classPrivateFieldSet$7(this, _EndpointStrategy_processAction, listener, "f"); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").forEach((endpoint) => endpoint.receive(__classPrivateFieldGet$9(this, _EndpointStrategy_processAction, "f"))); + } + getEndpointById(endpointId) { + const endpoint = __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").get(endpointId); + if (!endpoint) { + throw new Error(`Client with endpoint id ${endpointId} is not connected`); + } + return endpoint; + } + get connected() { + return __classPrivateFieldGet$9(this, _EndpointStrategy_connected, "f"); + } + isEndpointConnected(endpointId) { + return __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").has(endpointId); + } + addEndpoint(endpointId, payload) { + if (!__classPrivateFieldGet$9(this, _EndpointStrategy_connected, "f")) { + console.warn(`Adding endpoint to disconnected ${this.StrategyName} Strategy`); + return; + } + const clientStrat = new this.EndpointType(payload); + if (__classPrivateFieldGet$9(this, _EndpointStrategy_processAction, "f")) { + clientStrat.receive(__classPrivateFieldGet$9(this, _EndpointStrategy_processAction, "f")); + } + __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").set(endpointId, clientStrat); + } + async closeEndpoint(endpointId) { + __classPrivateFieldGet$9(this, _EndpointStrategy_endpointMap, "f").delete(endpointId); + } +} +strategy$1.EndpointStrategy = EndpointStrategy; +_EndpointStrategy_processAction = new WeakMap(), _EndpointStrategy_endpointMap = new WeakMap(), _EndpointStrategy_connected = new WeakMap(); + +Object.defineProperty(strategy$2, "__esModule", { value: true }); +strategy$2.RTCInfo = strategy$2.RTCStrategy = void 0; +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable class-methods-use-this */ +const endpoint_1 = endpoint; +const strategy_1$1 = strategy$1; +/* +This is used to abstract out rtc messaging from the channels implementation using RTCEndpoints. +*/ +class RTCStrategy extends strategy_1$1.EndpointStrategy { + constructor() { + super(endpoint_1.RTCEndpoint, endpoint_1.RTCEndpoint.isValidEndpointPayload, 'RTC'); + } +} +strategy$2.RTCStrategy = RTCStrategy; +strategy$2.RTCInfo = { version: 2, minimumVersion: 0, type: 'rtc' }; + +var iceManager = {}; + +Object.defineProperty(iceManager, "__esModule", { value: true }); +iceManager.RTCICEManager = void 0; +const base_1$h = base; +/* +Singleton that facilitates Offer and Answer exchange required for establishing RTC connections. +*/ +class RTCICEManager extends base_1$h.EmitterBase { + constructor(wire) { + super(wire, 'channel'); + this.ensureChannelOpened = (channel) => { + return new Promise((resolve, reject) => { + if (channel.readyState === 'open') { + resolve(); + } + else if (channel.readyState === 'connecting') { + const listener = () => { + channel.removeEventListener('open', listener); + resolve(); + }; + channel.addEventListener('open', listener); + } + else { + reject(new Error('This Channel has already closed')); + } + }); + }; + } + static createDataChannelPromise(label, rtcClient) { + let resolver; + const promise = new Promise((resolve) => { + resolver = resolve; + }); + const listener = (e) => { + const openListener = () => { + e.channel.removeEventListener('open', openListener); + resolver(e.channel); + }; + if (e.channel.label === label) { + e.channel.addEventListener('open', openListener); + rtcClient.removeEventListener('datachannel', listener); + } + }; + rtcClient.addEventListener('datachannel', listener); + return promise; + } + async listenForProviderIce(rtcConnectionId, listener) { + await this.on(this.createProviderEventName(rtcConnectionId), listener, { timestamp: Date.now() }); + } + async raiseProviderIce(rtcConnectionId, payload) { + await this.wire.environment.raiseEvent(this.createRouteString(this.createProviderEventName(rtcConnectionId)), payload); + } + async listenForClientIce(rtcConnectionId, listener) { + await this.on(this.createClientEventName(rtcConnectionId), listener, { timestamp: Date.now() }); + } + async raiseClientIce(rtcConnectionId, payload) { + await this.wire.environment.raiseEvent(this.createRouteString(this.createClientEventName(rtcConnectionId)), payload); + } + cleanupIceListeners(rtcConnectionId) { + this.removeAllListeners(this.createClientEventName(rtcConnectionId)); + this.removeAllListeners(this.createProviderEventName(rtcConnectionId)); + } + createClientEventName(rtcConnectionId) { + return `ice-client-${rtcConnectionId}`; + } + createProviderEventName(rtcConnectionId) { + return `ice-provider-${rtcConnectionId}`; + } + createRouteString(name) { + return `channel/${name}`; + } + createRtcPeer() { + return this.wire.environment.getRtcPeer(); + } + async startClientOffer() { + // TODO replace with real guid. + const rtcConnectionId = Math.random().toString(); + const rtcClient = this.createRtcPeer(); + rtcClient.addEventListener('icecandidate', async (e) => { + if (e.candidate) { + await this.raiseClientIce(rtcConnectionId, { candidate: e.candidate?.toJSON() }); + } + }); + await this.listenForProviderIce(rtcConnectionId, async (payload) => { + await rtcClient.addIceCandidate(payload.candidate); + }); + const channels = { + request: rtcClient.createDataChannel('request'), + response: rtcClient.createDataChannel('response') + }; + const offer = await rtcClient.createOffer(); + await rtcClient.setLocalDescription(offer); + const channelsOpened = Promise.all([channels.request, channels.response].map(this.ensureChannelOpened)).then(() => undefined); + return { rtcClient, channels, offer, rtcConnectionId, channelsOpened }; + } + async finishClientOffer(rtcClient, answer, providerReady) { + await rtcClient.setRemoteDescription(answer); + await providerReady; + return true; + } + async createProviderAnswer(rtcConnectionId, offer) { + const rtcClient = this.createRtcPeer(); + const requestChannelPromise = RTCICEManager.createDataChannelPromise('request', rtcClient); + const responseChannelPromise = RTCICEManager.createDataChannelPromise('response', rtcClient); + rtcClient.addEventListener('icecandidate', async (e) => { + if (e.candidate) { + await this.raiseProviderIce(rtcConnectionId, { candidate: e.candidate?.toJSON() }); + } + }); + await this.listenForClientIce(rtcConnectionId, async (payload) => { + await rtcClient.addIceCandidate(payload.candidate); + }); + await rtcClient.setRemoteDescription(offer); + const answer = await rtcClient.createAnswer(); + await rtcClient.setLocalDescription(answer); + const channels = Promise.all([requestChannelPromise, responseChannelPromise]).then(([request, response]) => { + // Clean up ice events. + this.cleanupIceListeners(rtcConnectionId); + return { request, response }; + }); + return { + rtcClient, + answer, + channels + }; + } +} +iceManager.RTCICEManager = RTCICEManager; + +var provider = {}; + +var runtimeVersioning = {}; + +Object.defineProperty(runtimeVersioning, "__esModule", { value: true }); +runtimeVersioning.runtimeUuidMeetsMinimumRuntimeVersion = runtimeVersioning.parseRuntimeUuid = runtimeVersioning.meetsMinimumRuntimeVersion = void 0; +function vNum(x) { + return [...x.split('.').reverse().entries()].reduce((p, [i, v]) => p + +v * 10000 ** i, 0); +} +/* + Compares runtime versions to see if the current runtime meets your desired minimum. +*/ +function meetsMinimumRuntimeVersion(currentVersion, minVersion) { + const currentVersionParsed = vNum(currentVersion); + const minVersionParsed = vNum(minVersion); + return currentVersionParsed >= minVersionParsed; +} +runtimeVersioning.meetsMinimumRuntimeVersion = meetsMinimumRuntimeVersion; +// Strips the port info from the runtimeUuid, leaving just the runtime version. +function parseRuntimeUuid(runtimeUuid) { + return runtimeUuid.split('/')[0]; +} +runtimeVersioning.parseRuntimeUuid = parseRuntimeUuid; +function runtimeUuidMeetsMinimumRuntimeVersion(runtimeUuid, minVersion) { + const runtimeVersion = parseRuntimeUuid(runtimeUuid); + return meetsMinimumRuntimeVersion(runtimeVersion, minVersion); +} +runtimeVersioning.runtimeUuidMeetsMinimumRuntimeVersion = runtimeUuidMeetsMinimumRuntimeVersion; + +var __classPrivateFieldGet$8 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet$6 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _ChannelProvider_connections, _ChannelProvider_protectedObj, _ChannelProvider_strategy, _ChannelProvider_removeEndpoint, _ChannelProvider_close; +Object.defineProperty(provider, "__esModule", { value: true }); +provider.ChannelProvider = void 0; +const channel_1 = channel; +const runtimeVersioning_1 = runtimeVersioning; +/** + * Instance created to enable use of a channel as a provider. Allows for communication with the {@link ChannelClient ChannelClients} by invoking an action on + * a single client via {@link ChannelProvider#dispatch dispatch} or all clients via {@link ChannelProvider#publish publish} + * and to listen for communication from clients by registering an action via {@link ChannelProvider#register register}. + * + * ### Synchronous Methods: + * * {@link ChannelProvider#onConnection onConnection(listener)} + * * {@link ChannelProvider#onDisconnection onDisconnection(listener)} + * * {@link ChannelProvider#publish publish(action, payload)} + * * {@link ChannelProvider#register register(action, listener)} + * * {@link ChannelProvider#remove remove(action)} + * + * ### Asynchronous Methods: + * * {@link ChannelProvider#destroy destroy()} + * * {@link ChannelProvider#dispatch dispatch(to, action, payload)} + * * {@link ChannelProvider#getAllClientInfo getAllClientInfo()} + * + * ### Middleware: + * Middleware functions receive the following arguments: (action, payload, senderId). + * The return value of the middleware function will be passed on as the payload from beforeAction, to the action listener, to afterAction + * unless it is undefined, in which case the most recently defined payload is used. Middleware can be used for side effects. + * * {@link ChannelProvider#setDefaultAction setDefaultAction(middleware)} + * * {@link ChannelProvider#onError onError(middleware)} + * * {@link ChannelProvider#beforeAction beforeAction(middleware)} + * * {@link ChannelProvider#afterAction afterAction(middleware)} + */ +class ChannelProvider extends channel_1.ChannelBase { + /** + * a read-only array containing all the identities of connecting clients. + */ + get connections() { + return [...__classPrivateFieldGet$8(this, _ChannelProvider_connections, "f")]; + } + static handleClientDisconnection(channel, payload) { + const removeById = channel.connections.find((identity) => identity.endpointId === payload.endpointId); + if (removeById) { + __classPrivateFieldGet$8(channel, _ChannelProvider_removeEndpoint, "f").call(channel, removeById); + } + else { + const multipleRemoves = channel.connections.filter((identity) => { + return identity.uuid === payload.uuid && identity.name === payload.name; + }); + multipleRemoves.forEach(__classPrivateFieldGet$8(channel, _ChannelProvider_removeEndpoint, "f")); + } + channel.disconnectListener(payload); + } + static setProviderRemoval(provider, remove) { + ChannelProvider.removalMap.set(provider, remove); + } + /** + * @internal + */ + constructor(providerIdentity, close, strategy) { + super(); + _ChannelProvider_connections.set(this, void 0); + _ChannelProvider_protectedObj.set(this, void 0); + _ChannelProvider_strategy.set(this, void 0); + _ChannelProvider_removeEndpoint.set(this, (identity) => { + const remainingConnections = this.connections.filter((clientIdentity) => clientIdentity.endpointId !== identity.endpointId); + __classPrivateFieldGet$8(this, _ChannelProvider_strategy, "f").closeEndpoint(identity.endpointId); + __classPrivateFieldSet$6(this, _ChannelProvider_connections, remainingConnections, "f"); + }); + // Must be bound. + this.processAction = async (action, payload, senderIdentity) => { + if (ChannelProvider.clientIsMultiRuntime(senderIdentity) && + !(0, runtimeVersioning_1.runtimeUuidMeetsMinimumRuntimeVersion)(senderIdentity.runtimeUuid, '18.87.56.0')) { + this.handleMultiRuntimeLegacyClient(senderIdentity); + } + else { + this.checkForClientConnection(senderIdentity); + } + return super.processAction(action, payload, senderIdentity); + }; + _ChannelProvider_close.set(this, () => { + __classPrivateFieldGet$8(this, _ChannelProvider_strategy, "f").close(); + const remove = ChannelProvider.removalMap.get(this); + if (remove) { + remove(); + } + }); + __classPrivateFieldSet$6(this, _ChannelProvider_protectedObj, new channel_1.ProtectedItems(providerIdentity, close), "f"); + this.connectListener = () => undefined; + this.disconnectListener = () => undefined; + __classPrivateFieldSet$6(this, _ChannelProvider_connections, [], "f"); + __classPrivateFieldSet$6(this, _ChannelProvider_strategy, strategy, "f"); + strategy.receive(this.processAction); + } + /** + * Dispatch an action to a specified client. Returns a promise for the result of executing that action on the client side. + * + * @param to - Identity of the target client. + * @param action - Name of the action to be invoked by the client. + * @param payload - Payload to be sent along with the action. + * + * @remarks + * + * Because multiple clients can share the same `name` and `uuid`, when dispatching from a provider to a client, + * the `identity` you provide must include the client's unique `endpointId` property. This `endpointId` is + * passed to the provider in both the `Provider.onConnection` callback and in any registered action callbacks. + * + * @example + * + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.register('provider-action', async (payload, identity) => { + * console.log(payload, identity); + * return await provider.dispatch(identity, 'client-action', 'Hello, World!'); + * }); + * })(); + * ``` + */ + dispatch(to, action, payload) { + const endpointId = to.endpointId ?? this.getEndpointIdForOpenFinId(to, action); + if (endpointId && __classPrivateFieldGet$8(this, _ChannelProvider_strategy, "f").isEndpointConnected(endpointId)) { + return __classPrivateFieldGet$8(this, _ChannelProvider_strategy, "f").send(endpointId, action, payload); + } + return Promise.reject(new Error(`Client connection with identity uuid: ${to.uuid} / name: ${to.name} / endpointId: ${endpointId} no longer connected.`)); + } + async processConnection(senderId, payload) { + __classPrivateFieldGet$8(this, _ChannelProvider_connections, "f").push(senderId); + return this.connectListener(senderId, payload); + } + /** + * Publish an action and payload to every connected client. + * Synchronously returns an array of promises for each action (see dispatch). + * + * @param action + * @param payload + * + * @example + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.register('provider-action', async (payload, identity) => { + * console.log(payload, identity); + * return await Promise.all(provider.publish('client-action', { message: 'Broadcast from provider'})); + * }); + * })(); + * ``` + */ + publish(action, payload) { + return this.connections.map((to) => __classPrivateFieldGet$8(this, _ChannelProvider_strategy, "f").send(to.endpointId, action, payload)); + } + /** + * Register a listener that is called on every new client connection. + * + * @remarks It is passed the identity of the connecting client and a payload if it was provided to Channel.connect. + * If you wish to reject the connection, throw an error. Be sure to synchronously provide an onConnection upon receipt of + * the channelProvider to ensure all potential client connections are caught by the listener. + * + * Because multiple clients can exist at the same `name` and `uuid`, in order to distinguish between individual clients, + * the `identity` argument in a provider's `onConnection` callback contains an `endpointId` property. When dispatching from a + * provider to a client, the `endpointId` property must be provided in order to send an action to a specific client. + * + * @example + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * provider.onConnection(identity => { + * console.log('Client connected', identity); + * }); + * })(); + * ``` + * + * Reject connection: + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * provider.onConnection(identity => { + * throw new Error('Connection Rejected'); + * }); + * })(); + * ``` + * @param listener + */ + onConnection(listener) { + this.connectListener = listener; + } + /** + * Register a listener that is called on client disconnection. It is passed the disconnection event of the disconnecting + * client. + * + * @param listener + * + * @example + * + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.onDisconnection(evt => { + * console.log('Client disconnected', `uuid: ${evt.uuid}, name: ${evt.name}`); + * }); + * })(); + * ``` + */ + onDisconnection(listener) { + this.disconnectListener = listener; + } + /** + * Destroy the channel, raises `disconnected` events on all connected channel clients. + * + * @example + * + * ```js + * (async ()=> { + * const provider = await fin.InterApplicationBus.Channel.create('channelName'); + * + * await provider.destroy(); + * })(); + * ``` + */ + async destroy() { + const protectedObj = __classPrivateFieldGet$8(this, _ChannelProvider_protectedObj, "f"); + protectedObj.providerIdentity; + __classPrivateFieldSet$6(this, _ChannelProvider_connections, [], "f"); + await protectedObj.close(); + __classPrivateFieldGet$8(this, _ChannelProvider_close, "f").call(this); + } + /** + * Returns an array with info on every Client connected to the Provider + * + * @example + * + * ```js + * const provider = await fin.InterApplicationBus.Channel.create('openfin'); + * const client = await fin.InterApplicationBus.Channel.connect('openfin'); + * const clientInfo = await provider.getAllClientInfo(); + * + * console.log(clientInfo); + * + * // [ + * // { + * // "uuid": "openfin", + * // "name": "openfin-view", + * // "endpointId": "6d4c7ca8-4a74-4634-87f8-760558229613", + * // "entityType": "view", + * // "url": "https://openfin.co" + * // }, + * // { + * // "uuid": "openfin2", + * // "name": "openfin-view2", + * // "endpointId": "4z5d8ab9-2b81-3691-91ex-142179382511", + * // "entityType": "view", + * // "url": "https://example.com" + * // } + * //] + * ``` + */ + async getAllClientInfo() { + return this.connections.map((clientInfo) => { + const { uuid, name, endpointId, entityType, connectionUrl } = clientInfo; + return { uuid, name, endpointId, entityType, connectionUrl }; + }); + } + checkForClientConnection(clientIdentity) { + if (!this.isClientConnected(clientIdentity)) { + throw new Error(`This action was sent from a client that is not connected to the provider. + Client Identity: {uuid: ${clientIdentity.uuid}, name: ${clientIdentity.name}, endpointId: ${clientIdentity.endpointId}}`); + } + } + isClientConnected(clientIdentity) { + if (ChannelProvider.clientIdentityIncludesEndpointId(clientIdentity)) { + return this.connections.some((identity) => { + return ( + // Might be redundant to check for uuid and name here after we get an endpointId match, but just in case + identity.endpointId === clientIdentity.endpointId && + identity.uuid === clientIdentity.uuid && + identity.name === clientIdentity.name); + }); + } + return this.isLegacyClientConnected(clientIdentity); + } + isLegacyClientConnected(clientIdentity) { + return this.connections.some((identity) => { + return identity.uuid === clientIdentity.uuid && identity.name === clientIdentity.name; + }); + } + handleMultiRuntimeLegacyClient(senderIdentity) { + if (!this.isLegacyClientConnected(senderIdentity)) { + throw new Error(`This action was sent from a client that is not connected to the provider. Client Identity: + {uuid: ${senderIdentity.uuid}, name: ${senderIdentity.name}, endpointId: ${senderIdentity.endpointId}}`); + } + } + getEndpointIdForOpenFinId(clientIdentity, action) { + const matchingConnections = this.connections.filter((c) => c.name === clientIdentity.name && c.uuid === clientIdentity.uuid); + if (matchingConnections.length >= 2) { + const protectedObj = __classPrivateFieldGet$8(this, _ChannelProvider_protectedObj, "f"); + const { uuid, name } = clientIdentity; + const providerUuid = protectedObj?.providerIdentity.uuid; + const providerName = protectedObj?.providerIdentity.name; + // eslint-disable-next-line no-console + console.warn(`WARNING: Dispatch call may have unintended results. The "to" argument of your dispatch call is missing the + "endpointId" parameter. The identity you are dispatching to ({uuid: ${uuid}, name: ${name}}) + has multiple channelClients for this channel. Your dispatched action: (${action}) from the provider: + ({uuid: ${providerUuid}, name: ${providerName}}) will only be processed by the most recently-created client.`); + } + // Pop to return the most recently created endpointId. + return matchingConnections.pop()?.endpointId; + } + // eslint-disable-next-line class-methods-use-this + static clientIdentityIncludesEndpointId(subscriptionIdentity) { + return subscriptionIdentity.endpointId !== undefined; + } + // eslint-disable-next-line class-methods-use-this + static clientIsMultiRuntime(subscriptionIdentity) { + return subscriptionIdentity.runtimeUuid !== undefined; + } + static async wireClose(wire, channelName) { + await wire.sendAction('destroy-channel', { channelName }); + } +} +provider.ChannelProvider = ChannelProvider; +_ChannelProvider_connections = new WeakMap(), _ChannelProvider_protectedObj = new WeakMap(), _ChannelProvider_strategy = new WeakMap(), _ChannelProvider_removeEndpoint = new WeakMap(), _ChannelProvider_close = new WeakMap(); +// The following line should be changed following a typescript update. +// static #removalMap = new WeakMap(); +ChannelProvider.removalMap = new WeakMap(); + +var messageReceiver = {}; + +Object.defineProperty(messageReceiver, "__esModule", { value: true }); +messageReceiver.MessageReceiver = void 0; +const client_1$1 = client; +const base_1$g = base; +/* +This is a singleton (per fin object) tasked with routing messages coming off the ipc to the correct endpoint. +It needs to be a singleton because there can only be one per wire. It tracks both clients and providers' processAction passed in via the strategy. +If functionality is not about receiving messages, it does not belong here. +*/ +class MessageReceiver extends base_1$g.Base { + constructor(wire) { + super(wire); + this.onmessage = (msg) => { + if (msg.action === 'process-channel-message') { + this.processChannelMessage(msg); + return true; + } + return false; + }; + this.endpointMap = new Map(); + this.latestEndpointIdByChannelId = new Map(); + wire.registerMessageHandler(this.onmessage.bind(this)); + } + async processChannelMessage(msg) { + const { senderIdentity, providerIdentity, action, ackToSender, payload, intendedTargetIdentity } = msg.payload; + const key = intendedTargetIdentity.channelId ?? // The recipient is a provider + intendedTargetIdentity.endpointId ?? // The recipient is a client + this.latestEndpointIdByChannelId.get(providerIdentity.channelId); // No endpointId was passed, make best attempt + const handler = this.endpointMap.get(key); + if (!handler) { + ackToSender.payload.success = false; + ackToSender.payload.reason = `Client connection with identity uuid: ${this.wire.me.uuid} / name: ${this.wire.me.name} / endpointId: ${key} no longer connected.`; + return this.wire.sendRaw(ackToSender); + } + try { + const res = await handler(action, payload, senderIdentity); + ackToSender.payload.payload = ackToSender.payload.payload || {}; + ackToSender.payload.payload.result = res; + return this.wire.sendRaw(ackToSender); + } + catch (e) { + ackToSender.payload.success = false; + ackToSender.payload.reason = e.message; + return this.wire.sendRaw(ackToSender); + } + } + addEndpoint(handler, channelId, endpointId) { + this.endpointMap.set(endpointId, handler); + // Providers have the same endpointId and channelId. + // This is only used when clients are receiving messages from providers, so we shouldn't save provider endpointId here. + if (channelId !== endpointId) { + this.latestEndpointIdByChannelId.set(channelId, endpointId); + } + } + removeEndpoint(channelId, endpointId) { + this.endpointMap.delete(endpointId); + if (this.latestEndpointIdByChannelId.get(channelId) === endpointId) { + this.latestEndpointIdByChannelId.delete(channelId); + } + } + checkForPreviousClientConnection(channelId) { + const endpointIdFromPreviousConnection = this.latestEndpointIdByChannelId.get(channelId); + if (endpointIdFromPreviousConnection) { + // Not convinced by this way of doing things, but pushing up for now. + client_1$1.ChannelClient.closeChannelByEndpointId(endpointIdFromPreviousConnection); + // eslint-disable-next-line no-console + console.warn('You have created a second connection to an older provider. First connection has been removed from the clientMap'); + // eslint-disable-next-line no-console + console.warn('If the provider calls publish(), you may receive multiple messages.'); + } + } +} +messageReceiver.MessageReceiver = MessageReceiver; + +var protocolManager = {}; + +Object.defineProperty(protocolManager, "__esModule", { value: true }); +protocolManager.ProtocolManager = void 0; +/* +This should be agnostic of any actual openfin code to be unit testable. +Dependencies on the actual srategies should be handled in ConnectionManager +*/ +class ProtocolManager { + // eslint-disable-next-line no-useless-constructor + constructor(ProtocolsInPreferenceOrder) { + this.ProtocolsInPreferenceOrder = ProtocolsInPreferenceOrder; + this.DefaultClientProtocols = ['classic']; + this.DefaultProviderProtocols = ['classic']; + this.getClientProtocols = (protocols) => { + const supported = protocols + ? this.ProtocolsInPreferenceOrder.filter((x) => protocols.includes(x)) + : this.DefaultClientProtocols; + if (!supported.length) { + throw new Error(`No valid protocols were passed in. Accepted values are: ${this.ProtocolsInPreferenceOrder.join(', ')}.`); + } + return supported; + }; + this.getProviderProtocols = (protocols) => { + const supported = protocols + ? this.ProtocolsInPreferenceOrder.filter((x) => protocols.includes(x)) + : this.DefaultProviderProtocols; + if (!supported.length) { + throw new Error(`No valid protocols were passed in. Accepted values are: ${this.ProtocolsInPreferenceOrder.join(', ')}.`); + } + return supported; + }; + this.getCompatibleProtocols = (providerProtocols, clientOffer) => { + const supported = clientOffer.supportedProtocols.filter((clientProtocol) => providerProtocols.some((providerProtocol) => providerProtocol.type === clientProtocol.type && + clientProtocol.version >= providerProtocol.minimumVersion && + providerProtocol.version >= (clientProtocol.minimumVersion ?? 0))); + return supported.slice(0, clientOffer.maxProtocols); + }; + } +} +protocolManager.ProtocolManager = ProtocolManager; + +var strategy = {}; + +Object.defineProperty(strategy, "__esModule", { value: true }); +class CombinedStrategy { + // Making this a static method because the constructor can't be typed. + // Otherwise it will error when calling addEndpoint but I'd rather the whole instance be typed as never. + static combine(a, b) { + return new CombinedStrategy(a, b); + } + // eslint-disable-next-line no-useless-constructor + constructor(primary, secondary) { + this.primary = primary; + this.secondary = secondary; + } + onEndpointDisconnect(endpointId, listener) { + this.primary.onEndpointDisconnect(endpointId, () => { + if (!this.secondary.isEndpointConnected(endpointId)) { + listener(); + } + }); + this.secondary.onEndpointDisconnect(endpointId, () => { + if (!this.primary.isEndpointConnected(endpointId)) { + listener(); + } + }); + } + isValidEndpointPayload(payload) { + return this.primary.isValidEndpointPayload(payload) || this.secondary.isValidEndpointPayload(payload); + } + async closeEndpoint(endpointId) { + await this.primary.closeEndpoint(endpointId); + await this.secondary.closeEndpoint(endpointId); + } + isEndpointConnected(endpoint) { + return this.primary.isEndpointConnected(endpoint) || this.secondary.isEndpointConnected(endpoint); + } + async addEndpoint(endpoint, payload) { + if (this.primary.isValidEndpointPayload(payload)) { + await this.primary.addEndpoint(endpoint, payload); + } + if (this.secondary.isValidEndpointPayload(payload)) { + await this.secondary.addEndpoint(endpoint, payload); + } + } + receive(listener) { + this.primary.receive(listener); + this.secondary.receive(listener); + } + send(endpointId, action, payload) { + if (this.primary.isEndpointConnected(endpointId)) { + return this.primary.send(endpointId, action, payload); + } + return this.secondary.send(endpointId, action, payload); + } + async close() { + await Promise.all([this.primary.close(), this.secondary.close()]); + } +} +strategy.default = CombinedStrategy; + +var __classPrivateFieldSet$5 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$7 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault$1 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _ConnectionManager_messageReceiver, _ConnectionManager_rtcConnectionManager; +Object.defineProperty(connectionManager, "__esModule", { value: true }); +connectionManager.ConnectionManager = void 0; +const exhaustive_1 = exhaustive; +const base_1$f = base; +const strategy_1 = strategy$3; +const strategy_2 = strategy$2; +const ice_manager_1 = iceManager; +const provider_1$1 = provider; +const message_receiver_1 = messageReceiver; +const protocol_manager_1 = protocolManager; +const strategy_3 = __importDefault$1(strategy); +class ConnectionManager extends base_1$f.Base { + static getProtocolOptionsFromStrings(protocols) { + return protocols.map((protocol) => { + switch (protocol) { + case 'rtc': + return strategy_2.RTCInfo; + case 'classic': + return strategy_1.ClassicInfo; + default: + return (0, exhaustive_1.exhaustiveCheck)(protocol, ['rtc', 'classic']); + } + }); + } + constructor(wire) { + super(wire); + _ConnectionManager_messageReceiver.set(this, void 0); + _ConnectionManager_rtcConnectionManager.set(this, void 0); + this.removeChannelFromProviderMap = (channelId) => { + this.providerMap.delete(channelId); + }; + this.onmessage = (msg) => { + if (msg.action === 'process-channel-connection') { + this.processChannelConnection(msg); + return true; + } + return false; + }; + this.providerMap = new Map(); + this.protocolManager = new protocol_manager_1.ProtocolManager(this.wire.environment.type === 'node' ? ['classic'] : ['rtc', 'classic']); + __classPrivateFieldSet$5(this, _ConnectionManager_messageReceiver, new message_receiver_1.MessageReceiver(wire), "f"); + __classPrivateFieldSet$5(this, _ConnectionManager_rtcConnectionManager, new ice_manager_1.RTCICEManager(wire), "f"); + wire.registerMessageHandler(this.onmessage.bind(this)); + } + createProvider(options, providerIdentity) { + const opts = Object.assign(this.wire.environment.getDefaultChannelOptions().create, options || {}); + const protocols = this.protocolManager.getProviderProtocols(opts?.protocols); + const createSingleStrategy = (stratType) => { + switch (stratType) { + case 'rtc': + return new strategy_2.RTCStrategy(); + case 'classic': + return new strategy_1.ClassicStrategy(this.wire, __classPrivateFieldGet$7(this, _ConnectionManager_messageReceiver, "f"), + // Providers do not have an endpointId, use channelId as endpointId in the strategy. + providerIdentity.channelId, providerIdentity); + default: + return (0, exhaustive_1.exhaustiveCheck)(stratType, ['rtc', 'classic']); + } + }; + const strategies = protocols.map(createSingleStrategy); + let strategy; + if (strategies.length === 2) { + const [a, b] = strategies; + strategy = strategy_3.default.combine(a, b); + } + else if (strategies.length === 1) { + [strategy] = strategies; + } + else { + // Should be impossible. + throw new Error('failed to combine strategies'); + } + const channel = new provider_1$1.ChannelProvider(providerIdentity, () => provider_1$1.ChannelProvider.wireClose(this.wire, providerIdentity.channelName), strategy); + const key = providerIdentity.channelId; + this.providerMap.set(key, { + provider: channel, + strategy, + supportedProtocols: ConnectionManager.getProtocolOptionsFromStrings(protocols) + }); + provider_1$1.ChannelProvider.setProviderRemoval(channel, this.removeChannelFromProviderMap.bind(this)); + return channel; + } + async createClientOffer(options) { + const protocols = this.protocolManager.getClientProtocols(options?.protocols); + let rtcPacket; + const supportedProtocols = await Promise.all(protocols.map(async (type) => { + switch (type) { + case 'rtc': { + const { rtcClient, channels, offer, rtcConnectionId, channelsOpened } = await __classPrivateFieldGet$7(this, _ConnectionManager_rtcConnectionManager, "f").startClientOffer(); + rtcPacket = { rtcClient, channels, channelsOpened }; + return { + type: 'rtc', + version: strategy_2.RTCInfo.version, + payload: { offer, rtcConnectionId } + }; + } + case 'classic': + return { type: 'classic', version: strategy_1.ClassicInfo.version }; + default: + return (0, exhaustive_1.exhaustiveCheck)(type, ['rtc', 'classic']); + } + })); + return { + offer: { + supportedProtocols, + maxProtocols: 2 + }, + rtc: rtcPacket + }; + } + async createClientStrategy(rtcPacket, routingInfo) { + if (!routingInfo.endpointId) { + routingInfo.endpointId = this.wire.environment.getNextMessageId(); + // For New Clients connecting to Old Providers. To prevent multi-dispatching and publishing, we delete previously-connected + // clients that are in the same context as the newly-connected client. + __classPrivateFieldGet$7(this, _ConnectionManager_messageReceiver, "f").checkForPreviousClientConnection(routingInfo.channelId); + } + const answer = routingInfo.answer ?? { + supportedProtocols: [{ type: 'classic', version: 1 }] + }; + const createStrategyFromAnswer = async (protocol) => { + if (protocol.type === 'rtc' && rtcPacket) { + await __classPrivateFieldGet$7(this, _ConnectionManager_rtcConnectionManager, "f").finishClientOffer(rtcPacket.rtcClient, protocol.payload.answer, rtcPacket.channelsOpened); + return new strategy_2.RTCStrategy(); + } + if (protocol.type === 'classic') { + return new strategy_1.ClassicStrategy(this.wire, __classPrivateFieldGet$7(this, _ConnectionManager_messageReceiver, "f"), routingInfo.endpointId, routingInfo); + } + return null; + }; + const allProtocols = (await Promise.all(answer.supportedProtocols.map(createStrategyFromAnswer))).filter((x) => x !== null); + // Clean up logic if provider didn't support rtc. + if (rtcPacket && !allProtocols.some((x) => x instanceof strategy_2.RTCStrategy)) { + if (rtcPacket) { + rtcPacket.rtcClient.close(); + } + } + let strategy; + if (allProtocols.length >= 2) { + strategy = strategy_3.default.combine(allProtocols[0], allProtocols[1]); + } + else if (allProtocols.length) { + [strategy] = allProtocols; + } + else { + // Should be impossible. + throw new Error('No compatible protocols'); + } + // as casting rtcPacket because we won't have an rtcStrategy if rtcPacket is undefined; + const endpointPayload = { endpointIdentity: routingInfo, rtc: rtcPacket }; + strategy.addEndpoint(routingInfo.channelId, endpointPayload); + return strategy; + } + async processChannelConnection(msg) { + const { clientIdentity, providerIdentity, ackToSender, payload, offer: clientOffer } = msg.payload; + if (!clientIdentity.endpointId) { + // Should be polyfilled by core but not in cases of node connecting to an old runtime. + clientIdentity.endpointId = this.wire.environment.getNextMessageId(); + clientIdentity.isLocalEndpointId = true; + } + else { + clientIdentity.isLocalEndpointId = false; + } + const key = providerIdentity.channelId; + const bus = this.providerMap.get(key); + if (!bus) { + ackToSender.payload.success = false; + ackToSender.payload.reason = `Channel "${providerIdentity.channelName}" has been destroyed.`; + return this.wire.sendRaw(ackToSender); + } + const { provider, strategy, supportedProtocols } = bus; + try { + if (!(provider instanceof provider_1$1.ChannelProvider)) { + throw Error('Cannot connect to a channel client'); + } + const offer = clientOffer ?? { + supportedProtocols: [{ type: 'classic', version: 1 }], + maxProtocols: 1 + }; + const overlappingProtocols = this.protocolManager.getCompatibleProtocols(supportedProtocols, offer); + if (!overlappingProtocols.length) { + throw new Error('This provider does not support any of the offered protocols.'); + } + const res = await provider.processConnection(clientIdentity, payload); + ackToSender.payload.payload = ackToSender.payload.payload || {}; + // Loop through all supported protocols and accumulate them into the answer + // addEndpoint is tricky but we need to wait for channel resolution before adding the endpoint. + let clientAnswer = { + supportedProtocols: [], + endpointPayloadPromise: Promise.resolve({ endpointIdentity: clientIdentity }) + }; + clientAnswer = await overlappingProtocols.reduce(async (accumP, protocolToUse) => { + const answer = await accumP; + if (protocolToUse.type === 'rtc') { + const { answer: rtcAnswer, rtcClient, channels } = await __classPrivateFieldGet$7(this, _ConnectionManager_rtcConnectionManager, "f").createProviderAnswer(protocolToUse.payload.rtcConnectionId, protocolToUse.payload.offer); + answer.supportedProtocols.push({ + type: 'rtc', + version: strategy_2.RTCInfo.version, + payload: { + answer: rtcAnswer + } + }); + answer.endpointPayloadPromise = answer.endpointPayloadPromise.then((endpointPayload) => channels.then((resolvedChannels) => { + return { + ...endpointPayload, + rtc: { + rtcClient, + channels: resolvedChannels + } + }; + })); + } + else { + answer.supportedProtocols.push({ type: 'classic', version: strategy_1.ClassicInfo.version }); + } + return answer; + }, Promise.resolve(clientAnswer)); + // Need to as cast here. + clientAnswer.endpointPayloadPromise.then((endpointPayload) => strategy.addEndpoint(clientIdentity.endpointId, endpointPayload)); + ackToSender.payload.payload.result = res; + ackToSender.payload.payload.answer = clientAnswer; + return this.wire.sendRaw(ackToSender); + } + catch (e) { + ackToSender.payload.success = false; + ackToSender.payload.reason = e.message; + return this.wire.sendRaw(ackToSender); + } + } +} +connectionManager.ConnectionManager = ConnectionManager; +_ConnectionManager_messageReceiver = new WeakMap(), _ConnectionManager_rtcConnectionManager = new WeakMap(); + +/** + * Entry points for the `Channel` subset of the `InterApplicationBus` API (`fin.InterApplicationBus.Channel`). + * + * * {@link Channel} contains static members of the `Channel` API, accessible through `fin.InterApplicationBus.Channel`. + * * {@link OpenFin.ChannelClient} describes a client of a channel, e.g. as returned by `fin.InterApplicationBus.Channel.connect`. + * * {@link OpenFin.ChannelProvider} describes a provider of a channel, e.g. as returned by `fin.InterApplicationBus.Channel.create`. + * + * @packageDocumentation + */ +var __classPrivateFieldSet$4 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$6 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _Channel_connectionManager, _Channel_internalEmitter, _Channel_readyToConnect; +Object.defineProperty(channel$1, "__esModule", { value: true }); +channel$1.Channel = void 0; +/* eslint-disable no-console */ +const events_1$5 = require$$0; +const lazy_1$1 = lazy; +const base_1$e = base; +const client_1 = client; +const connection_manager_1 = connectionManager; +const provider_1 = provider; +function retryDelay(count) { + const interval = 500; // base delay + const steps = 10; // How many retries to do before incrementing the delay + const base = 2; // How much to multiply the previous delay by + const max = 30000; // max delay + const step = Math.floor(count / steps); + const delay = Math.min(max, interval * base ** step); + return new Promise((resolve) => { + setTimeout(() => { + resolve(false); + }, delay); + }); +} +/** + * The Channel API allows an OpenFin application to create a channel as a {@link ChannelProvider ChannelProvider}, + * or connect to a channel as a {@link ChannelClient ChannelClient}. + * @remarks The "handshake" between the communication partners is + * simplified when using a channel. A request to connect to a channel as a client will return a promise that resolves if/when the channel has been created. Both the + * provider and client can dispatch actions that have been registered on their opposites, and dispatch returns a promise that resolves with a payload from the other + * communication participant. There can be only one provider per channel, but many clients. Version `9.61.35.*` or later is required for both communication partners. + * + * Asynchronous Methods: + * * {@link Channel.create create(channelName, options)} + * * {@link Channel.connect connect(channelName, options)} + * * {@link Channel.onChannelConnect onChannelConnect(listener)} + * * {@link Channel.onChannelDisconnect onChannelDisconnect(listener)} + */ +class Channel extends base_1$e.EmitterBase { + /** + * @internal + */ + constructor(wire) { + super(wire, 'channel'); + _Channel_connectionManager.set(this, void 0); + _Channel_internalEmitter.set(this, new events_1$5.EventEmitter()); + // OpenFin API has not been injected at construction time, *must* wait for API to be ready. + _Channel_readyToConnect.set(this, new lazy_1$1.AsyncRetryableLazy(async () => { + await Promise.all([ + this.on('disconnected', (eventPayload) => { + client_1.ChannelClient.handleProviderDisconnect(eventPayload); + }), + this.on('connected', (...args) => { + __classPrivateFieldGet$6(this, _Channel_internalEmitter, "f").emit('connected', ...args); + }) + ]).catch(() => new Error('error setting up channel connection listeners')); + })); + __classPrivateFieldSet$4(this, _Channel_connectionManager, new connection_manager_1.ConnectionManager(wire), "f"); + } + /** + * + * @internal + */ + async getAllChannels() { + return this.wire.sendAction('get-all-channels').then(({ payload }) => payload.data); + } + /** + * Listens for channel connections. + * + * @param listener - callback to execute. + * + * @example + * + * ```js + * const listener = (channelPayload) => console.log(channelPayload); // see return value below + * + * fin.InterApplicationBus.Channel.onChannelConnect(listener); + * + * // example shape + * { + * "topic": "channel", + * "type": "connected", + * "uuid": "OpenfinPOC", + * "name": "OpenfinPOC", + * "channelName": "counter", + * "channelId": "OpenfinPOC/OpenfinPOC/counter" + * } + * + * ``` + */ + async onChannelConnect(listener) { + await this.on('connected', listener); + } + /** + * Listen for channel disconnections. + * + * @param listener - callback to execute. + * + * @example + * + * ```js + * const listener = (channelPayload) => console.log(channelPayload); // see return value below + * + * fin.InterApplicationBus.Channel.onChannelDisconnect(listener); + * + * // example shape + * { + * "topic": "channel", + * "type": "disconnected", + * "uuid": "OpenfinPOC", + * "name": "OpenfinPOC", + * "channelName": "counter", + * "channelId": "OpenfinPOC/OpenfinPOC/counter" + * } + * + * ``` + */ + async onChannelDisconnect(listener) { + await this.on('disconnected', listener); + } + async safeConnect(channelName, shouldWait, connectPayload) { + const retryInfo = { count: 0 }; + /* eslint-disable no-await-in-loop, no-constant-condition */ + do { + // setup a listener and a connected promise to await in case we connect before the channel is ready + let connectedListener = () => undefined; + const connectedPromise = new Promise((resolve) => { + connectedListener = (payload) => { + if (channelName === payload.channelName) { + resolve(true); + } + }; + __classPrivateFieldGet$6(this, _Channel_internalEmitter, "f").on('connected', connectedListener); + }); + try { + if (retryInfo.count > 0) { + // Wait before retrying + // Delay returns false connectedPromise returns true so we can know if a retry is due to connected event + retryInfo.gotConnectedEvent = await Promise.race([retryDelay(retryInfo.count), connectedPromise]); + const result = await this.wire.sendAction('connect-to-channel', { ...connectPayload, retryInfo }); + // log only if there was a retry + console.log(`Successfully connected to channelName: ${channelName}`); + return result.payload.data; + } + // Send retryInfo to the core for debug log inclusion + const sentMessagePromise = this.wire.sendAction('connect-to-channel', connectPayload); + // Save messageId from the first connection attempt + retryInfo.originalMessageId = sentMessagePromise.messageId; + const result = await sentMessagePromise; + return result.payload.data; + } + catch (error) { + if (!error.message.includes('internal-nack')) { + // Not an internal nack, break the loop + throw error; + } + if (shouldWait && retryInfo.count === 0) { + // start waiting on the next iteration, warn the user + console.warn(`No channel found for channelName: ${channelName}. Waiting for connection...`); + } + } + finally { + retryInfo.count += 1; + // in case of other errors, remove our listener + __classPrivateFieldGet$6(this, _Channel_internalEmitter, "f").removeListener('connected', connectedListener); + } + } while (shouldWait); // If we're waiting we retry the above loop + // Should wait was false, no channel was found. + throw new Error(`No channel found for channelName: ${channelName}.`); + /* eslint-enable no-await-in-loop, no-constant-condition */ + } + /** + * Connect to a channel. If you wish to send a payload to the provider, add a payload property to the options argument. + * EXPERIMENTAL: pass { protocols: ['rtc'] } as options to opt-in to High Throughput Channels. + * + * @param channelName - Name of the target channel. + * @param options - Connection options. + * @returns Returns a promise that resolves with an instance of {@link ChannelClient ChannelClient}. + * + * @remarks The connection request will be routed to the channelProvider if/when the channel is created. If the connect + * request is sent prior to creation, the promise will not resolve or reject until the channel is created by a channelProvider + * (whether or not to wait for creation is configurable in the connectOptions). + * + * The connect call returns a promise that will resolve with a channelClient bus if accepted by the channelProvider, or reject if + * the channelProvider throws an error to reject the connection. This bus can communicate with the Provider, but not to other + * clients on the channel. Using the bus, the channelClient can register actions and middleware. Channel lifecycle can also be + * handled with an onDisconnection listener. + * + * @example + * + * ```js + * async function makeClient(channelName) { + * // A payload can be sent along with channel connection requests to help with authentication + * const connectPayload = { payload: 'token' }; + * + * // If the channel has been created this request will be sent to the provider. If not, the + * // promise will not be resolved or rejected until the channel has been created. + * const clientBus = await fin.InterApplicationBus.Channel.connect(channelName, connectPayload); + * + * clientBus.onDisconnection(channelInfo => { + * // handle the channel lifecycle here - we can connect again which will return a promise + * // that will resolve if/when the channel is re-created. + * makeClient(channelInfo.channelName); + * }) + * + * clientBus.register('topic', (payload, identity) => { + * // register a callback for a topic to which the channel provider can dispatch an action + * console.log('Action dispatched by provider: ', JSON.stringify(identity)); + * console.log('Payload sent in dispatch: ', JSON.stringify(payload)); + * return { + * echo: payload + * }; + * }); + * } + * + * makeClient('channelName') + * .then(() => console.log('Connected')) + * .catch(console.error); + * ``` + */ + async connect(channelName, options = {}) { + // Make sure we don't connect before listeners are set up + // This also errors if we're not in OpenFin, ensuring we don't run unnecessary code + await __classPrivateFieldGet$6(this, _Channel_readyToConnect, "f").getValue(); + if (!channelName || typeof channelName !== 'string') { + throw new Error('Please provide a channelName string to connect to a channel.'); + } + const opts = { wait: true, ...this.wire.environment.getDefaultChannelOptions().connect, ...options }; + const { offer, rtc: rtcPacket } = await __classPrivateFieldGet$6(this, _Channel_connectionManager, "f").createClientOffer(opts); + let connectionUrl; + if (this.fin.me.isFrame || this.fin.me.isView || this.fin.me.isWindow) { + connectionUrl = (await this.fin.me.getInfo()).url; + } + const connectPayload = { + channelName, + ...opts, + offer, + connectionUrl + }; + const routingInfo = await this.safeConnect(channelName, opts.wait, connectPayload); + const strategy = await __classPrivateFieldGet$6(this, _Channel_connectionManager, "f").createClientStrategy(rtcPacket, routingInfo); + const channel = new client_1.ChannelClient(routingInfo, () => client_1.ChannelClient.wireClose(this.wire, routingInfo, routingInfo.endpointId), strategy); + // It is the client's responsibility to handle endpoint disconnection to the provider. + // If the endpoint dies, the client will force a disconnection through the core. + // The provider does not care about endpoint disconnection. + strategy.onEndpointDisconnect(routingInfo.channelId, async () => { + try { + await channel.sendDisconnectAction(); + } + catch (error) { + console.warn(`Something went wrong during disconnect for client with uuid: ${routingInfo.uuid} / name: ${routingInfo.name} / endpointId: ${routingInfo.endpointId}.`); + } + finally { + client_1.ChannelClient.handleProviderDisconnect(routingInfo); + } + }); + return channel; + } + /** + * Create a new channel. + * You must provide a unique channelName. If a channelName is not provided, or it is not unique, the creation will fail. + * EXPERIMENTAL: pass { protocols: ['rtc'] } as options to opt-in to High Throughput Channels. + * + * @param channelName - Name of the channel to be created. + * @param options - Creation options. + * @returns Returns a promise that resolves with an instance of {@link ChannelProvider ChannelProvider}. + * + * @remarks If successful, the create method returns a promise that resolves to an instance of the channelProvider bus. The caller + * then becomes the “channel provider” and can use the channelProvider bus to register actions and middleware. + * + * The caller can also set an onConnection and/or onDisconnection listener that will execute on any new channel + * connection/disconnection attempt from a channel client. To reject a connection, simply throw an error in the + * onConnection listener. The default behavior is to accept all new connections. + * + * A map of client connections is updated automatically on client connection and disconnection and saved in the + * [read-only] `connections` property on the channelProvider bus. The channel will exist until the provider + * destroys it or disconnects by closing or destroying the context (navigating or reloading). To setup a channel + * as a channelProvider, call `Channel.create` with a unique channel name. A map of client connections is updated + * automatically on client connection and disconnection. + * + * @example + * + * ```js + * (async ()=> { + * // entity creates a channel and becomes the channelProvider + * const providerBus = await fin.InterApplicationBus.Channel.create('channelName'); + * + * providerBus.onConnection((identity, payload) => { + * // can reject a connection here by throwing an error + * console.log('Client connection request identity: ', JSON.stringify(identity)); + * console.log('Client connection request payload: ', JSON.stringify(payload)); + * }); + * + * providerBus.register('topic', (payload, identity) => { + * // register a callback for a 'topic' to which clients can dispatch an action + * console.log('Action dispatched by client: ', JSON.stringify(identity)); + * console.log('Payload sent in dispatch: ', JSON.stringify(payload)); + * return { + * echo: payload + * }; + * }); + * })(); + * ``` + */ + async create(channelName, options) { + if (!channelName) { + throw new Error('Please provide a channelName to create a channel'); + } + const { payload: { data: providerIdentity } } = await this.wire.sendAction('create-channel', { channelName }); + const channel = __classPrivateFieldGet$6(this, _Channel_connectionManager, "f").createProvider(options, providerIdentity); + // TODO: fix typing (internal) + // @ts-expect-error + this.on('client-disconnected', (eventPayload) => { + if (eventPayload.channelName === channelName) { + provider_1.ChannelProvider.handleClientDisconnection(channel, eventPayload); + } + }); + return channel; + } +} +channel$1.Channel = Channel; +_Channel_connectionManager = new WeakMap(), _Channel_internalEmitter = new WeakMap(), _Channel_readyToConnect = new WeakMap(); + +Object.defineProperty(interappbus, "__esModule", { value: true }); +interappbus.InterAppPayload = interappbus.InterApplicationBus = void 0; +/** + * Entry point for the OpenFin `InterApplicationBus` API (`fin.InterApplicationBus`). + * + * * {@link InterApplicationBus} contains static members of the `InterApplicationBus` API, accessible through `fin.InterApplicationBus`. + * + * @packageDocumentation + */ +const events_1$4 = require$$0; +const base_1$d = base; +const ref_counter_1 = refCounter; +const index_1$2 = channel$1; +const validate_1$3 = validate; +/** + * A messaging bus that allows for pub/sub messaging between different applications. + * + */ +class InterApplicationBus extends base_1$d.Base { + /** + * @internal + */ + constructor(wire) { + super(wire); + this.events = { + subscriberAdded: 'subscriber-added', + subscriberRemoved: 'subscriber-removed' + }; + this.refCounter = new ref_counter_1.RefCounter(); + this.Channel = new index_1$2.Channel(wire); + this.emitter = new events_1$4.EventEmitter(); + wire.registerMessageHandler(this.onmessage.bind(this)); + this.on = this.emitter.on.bind(this.emitter); + this.removeAllListeners = this.emitter.removeAllListeners.bind(this.emitter); + } + /** + * Publishes a message to all applications running on OpenFin Runtime that + * are subscribed to the specified topic. + * @param topic The topic on which the message is sent + * @param message The message to be published. Can be either a primitive + * data type (string, number, or boolean) or composite data type (object, array) + * that is composed of other primitive or composite data types + * + * @example + * ```js + * fin.InterApplicationBus.publish('topic', 'hello').then(() => console.log('Published')).catch(err => console.log(err)); + * ``` + */ + async publish(topic, message) { + await this.wire.sendAction('publish-message', { + topic, + message, + sourceWindowName: this.me.name + }); + } + /** + * Sends a message to a specific application on a specific topic. + * @param destination The identity of the application to which the message is sent + * @param topic The topic on which the message is sent + * @param message The message to be sent. Can be either a primitive data + * type (string, number, or boolean) or composite data type (object, array) that + * is composed of other primitive or composite data types + * + * @example + * ```js + * fin.InterApplicationBus.send(fin.me, 'topic', 'Hello there!').then(() => console.log('Message sent')).catch(err => console.log(err)); + * ``` + */ + async send(destination, topic, message) { + const errorMsg = (0, validate_1$3.validateIdentity)(destination); + if (errorMsg) { + throw new Error(errorMsg); + } + await this.wire.sendAction('send-message', { + destinationUuid: destination.uuid, + destinationWindowName: destination.name, + topic, + message, + sourceWindowName: this.me.name + }); + } + /** + * Subscribes to messages from the specified application on the specified topic. + * @param source This object is described in the Identity in the typedef + * @param topic The topic on which the message is sent + * @param listener A function that is called when a message has + * been received. It is passed the message, uuid and name of the sending application. + * The message can be either a primitive data type (string, number, or boolean) or + * composite data type (object, array) that is composed of other primitive or composite + * data types + * + * @example + * ```js + * // subscribe to a specified application + * fin.InterApplicationBus.subscribe(fin.me, 'topic', sub_msg => console.log(sub_msg)).then(() => console.log('Subscribed to the specified application')).catch(err => console.log(err)); + * + * // subscribe to wildcard + * fin.InterApplicationBus.subscribe({ uuid: '*' }, 'topic', sub_msg => console.log(sub_msg)).then(() => console.log('Subscribed to *')).catch(err => console.log(err)); + * ``` + */ + subscribe(source, topic, listener) { + const subKey = this.createSubscriptionKey(source.uuid, source.name || '*', topic); + const sendSubscription = async () => { + await this.wire.sendAction('subscribe', { + sourceUuid: source.uuid, + sourceWindowName: source.name || '*', + topic, + destinationWindowName: this.me.name + }); + }; + const alreadySubscribed = () => { + return Promise.resolve(); + }; + this.emitter.on(subKey, listener); + return this.refCounter.actOnFirst(subKey, sendSubscription, alreadySubscribed); + } + /** + * Unsubscribes to messages from the specified application on the specified topic. + * + * @remarks If you are listening to all apps on a topic, (i.e you passed `{ uuid:'*' }` to the subscribe function) + * then you need to pass `{ uuid:'*' }` to unsubscribe as well. If you are listening to a specific application, + * (i.e you passed `{ uuid:'some_app' }` to the subscribe function) then you need to provide the same identifier to + * unsubscribe, unsubscribing to `*` on that same topic will not unhook your initial listener otherwise. + * + * @param source This object is described in the Identity in the typedef + * @param topic The topic on which the message is sent + * @param listener A callback previously registered with subscribe() + * + * @example + * ```js + * const listener = console.log; + * + * // If any application publishes a message on topic `foo`, our listener will be called. + * await fin.InterApplicationBus.subscribe({ uuid:'*' }, 'foo', listener) + * + * // When you want to unsubscribe, you need to specify the uuid of the app you'd like to + * // unsubscribe from (or `*`) and provide the same function you gave the subscribe function + * await fin.InterApplicationBus.unsubscribe({ uuid:'*' }, 'foo', listener) + * ``` + */ + unsubscribe(source, topic, listener) { + const sourceWindowName = source.name || '*'; + const subKey = this.createSubscriptionKey(source.uuid, sourceWindowName, topic); + const sendUnsubscription = async () => { + await this.wire.sendAction('unsubscribe', { + sourceUuid: source.uuid, + sourceWindowName, + topic, + destinationWindowName: this.me.name + }); + }; + const dontSendUnsubscription = () => { + return new Promise((r) => r).then(() => undefined); + }; + this.emitter.removeListener(subKey, listener); + return this.refCounter.actOnLast(subKey, sendUnsubscription, dontSendUnsubscription); + } + processMessage(message) { + const { payload: { message: payloadMessage, sourceWindowName, sourceUuid, topic } } = message; + const keys = [ + this.createSubscriptionKey(sourceUuid, sourceWindowName, topic), + this.createSubscriptionKey(sourceUuid, '*', topic), + this.createSubscriptionKey('*', '*', topic) + ]; + const idOfSender = { uuid: sourceUuid, name: sourceWindowName }; + keys.forEach((key) => { + this.emitter.emit(key, payloadMessage, idOfSender); + }); + } + emitSubscriverEvent(type, message) { + const { payload: { targetName: name, uuid, topic } } = message; + const payload = { name, uuid, topic }; + this.emitter.emit(type, payload); + } + // eslint-disable-next-line class-methods-use-this + createSubscriptionKey(uuid, name, topic) { + const n = name || '*'; + if (!(uuid && n && topic)) { + throw new Error('Missing uuid, name, or topic string'); + } + return createKey(uuid, n, topic); + } + onmessage(message) { + const { action } = message; + switch (action) { + case 'process-message': + this.processMessage(message); + break; + case this.events.subscriberAdded: + this.emitSubscriverEvent(this.events.subscriberAdded, message); + break; + case this.events.subscriberRemoved: + this.emitSubscriverEvent(this.events.subscriberRemoved, message); + break; + } + return true; + } +} +interappbus.InterApplicationBus = InterApplicationBus; +/** + * @internal + */ +class InterAppPayload { +} +interappbus.InterAppPayload = InterAppPayload; +function createKey(...toHash) { + return toHash + .map((item) => { + return Buffer.from(`${item}`).toString('base64'); + }) + .join('/'); +} + +var clipboard = {}; + +/** + * Entry point for the OpenFin `Clipboard` API (`fin.Clipboard`). + * + * * {@link Clipboard} contains static members of the `Clipboard` API, accessible through `fin.Clipboard`. + * + * @packageDocumentation + */ +Object.defineProperty(clipboard, "__esModule", { value: true }); +clipboard.Clipboard = void 0; +const base_1$c = base; +/** + * The Clipboard API allows reading and writing to the clipboard in multiple formats. + * + */ +class Clipboard extends base_1$c.Base { + /** + * Writes data into the clipboard as plain text + * @param writeObj The object for writing data into the clipboard + * + * @example + * ```js + * fin.Clipboard.writeText({ + * data: 'hello, world' + * }).then(() => console.log('Text On clipboard')).catch(err => console.log(err)); + * ``` + */ + async writeText(writeObj) { + await this.wire.sendAction('clipboard-write-text', writeObj); + } + /** + * Read the content of the clipboard as plain text + * @param type Clipboard Type defaults to 'clipboard', use 'selection' for linux + * + * @example + * ```js + * fin.Clipboard.readText().then(text => console.log(text)).catch(err => console.log(err)); + * ``` + */ + async readText(type) { + // NOTE: When we start supporting linux, we could detect the OS and choose 'selection' automatically for the user + const { payload } = await this.wire.sendAction('clipboard-read-text', { type }); + return payload.data; + } + /** + * Writes data into the clipboard as an Image + * @param writeRequest The object to write an image to the clipboard + * + * @example + * ```js + * fin.Clipboard.writeImage({ + * // raw base64 string, or dataURL of either data:image/png or data:image/jpeg type + * image: '...' + * }).then(() => console.log('Image written to clipboard')).catch(err => console.log(err)); + * ``` + */ + async writeImage(writeRequest) { + await this.wire.sendAction('clipboard-write-image', writeRequest); + } + /** + * Read the content of the clipboard as a base64 string or a dataURL based on the input parameter 'format', defaults to 'dataURL' + * @param readRequest Clipboard Read Image request with formatting options + * + * @example + * ```js + * // see TS type: OpenFin.ImageFormatOptions + * + * const pngOrDataURLOrBmpOptions = { + * format: 'png', // can be: 'png' | 'dataURL' | 'bmp' + * }; + * + * const jpgOptions = { + * format: 'jpg', + * quality: 80 // optional, if omitted defaults to 100 + * }; + * + * fin.Clipboard.readImage(pngOrDataURLOrBmpOptions) + * .then(image => console.log('Image read from clipboard as PNG, DataURL or BMP', image)) + * .catch(err => console.log(err)); + * + * fin.Clipboard.readImage(jpgOptions) + * .then(image => console.log('Image read from clipboard as JPG', image)) + * .catch(err => console.log(err)); + * + * // defaults to {format: 'dataURL'} + * fin.Clipboard.readImage() + * .then(image => console.log('Image read from clipboard as DataURL', image)) + * .catch(err => console.log(err)); + * + * ``` + */ + async readImage(readRequest = { format: 'dataURL' }) { + const { payload } = await this.wire.sendAction('clipboard-read-image', readRequest); + return payload.data; + } + /** + * Writes data into the clipboard as Html + * @param writeObj The object for writing data into the clipboard + * + * @example + * ```js + * fin.Clipboard.writeHtml({ + * data: '

Hello, World!

' + * }).then(() => console.log('HTML On clipboard')).catch(err => console.log(err)); + * ``` + */ + async writeHtml(writeObj) { + await this.wire.sendAction('clipboard-write-html', writeObj); + } + /** + * Read the content of the clipboard as Html + * @param type Clipboard Type defaults to 'clipboard', use 'selection' for linux + * + * @example + * ```js + * fin.Clipboard.readHtml().then(html => console.log(html)).catch(err => console.log(err)); + * ``` + */ + async readHtml(type) { + const { payload } = await this.wire.sendAction('clipboard-read-html', { type }); + return payload.data; + } + /** + * Writes data into the clipboard as Rtf + * @param writeObj The object for writing data into the clipboard + * + * @example + * ```js + * fin.Clipboard.writeRtf({ + * data: 'some text goes here' + * }).then(() => console.log('RTF On clipboard')).catch(err => console.log(err)); + * ``` + */ + async writeRtf(writeObj) { + await this.wire.sendAction('clipboard-write-rtf', writeObj); + } + /** + * Read the content of the clipboard as Rtf + * @param type Clipboard Type defaults to 'clipboard', use 'selection' for linux + * + * @example + * + * ```js + * const writeObj = { + * data: 'some text goes here' + * }; + * async function readRtf() { + * await fin.Clipboard.writeRtf(writeObj); + * return await fin.Clipboard.readRtf(); + * } + * readRtf().then(rtf => console.log(rtf)).catch(err => console.log(err)); + * ``` + */ + async readRtf(type) { + const { payload } = await this.wire.sendAction('clipboard-read-rtf', { type }); + return payload.data; + } + /** + * Writes data into the clipboard + * @param writeObj The object for writing data into the clipboard + * + * @example + * ```js + * fin.Clipboard.write({ + * data: { + * text: 'a', + * html: 'b', + * rtf: 'c', + * // Can be either a base64 string, or a DataURL string. If using DataURL, the + * // supported formats are `data:image/png[;base64],` and `data:image/jpeg[;base64],`. + * // Using other image/ DataURLs will throw an Error. + * image: '...' + * } + * }).then(() => console.log('write data into clipboard')).catch(err => console.log(err)); + * ``` + */ + async write(writeObj) { + await this.wire.sendAction('clipboard-write', writeObj); + } + /** + * Reads available formats for the clipboard type + * @param type Clipboard Type defaults to 'clipboard', use 'selection' for linux + * + * @example + * ```js + * fin.Clipboard.getAvailableFormats().then(formats => console.log(formats)).catch(err => console.log(err)); + * ``` + */ + async getAvailableFormats(type) { + const { payload } = await this.wire.sendAction('clipboard-read-formats', { type }); + return payload.data; + } +} +clipboard.Clipboard = Clipboard; + +var externalApplication = {}; + +var Factory$5 = {}; + +var Instance$4 = {}; + +Object.defineProperty(Instance$4, "__esModule", { value: true }); +Instance$4.ExternalApplication = void 0; +/* eslint-disable import/prefer-default-export */ +const base_1$b = base; +/** + * An ExternalApplication object representing native language adapter connections to the runtime. Allows + * the developer to listen to {@link OpenFin.ExternalApplicationEvents external application events}. + * Discovery of connections is provided by {@link System.System.getAllExternalApplications getAllExternalApplications}. + * + * Processes that can be wrapped as `ExternalApplication`s include the following: + * - Processes which have connected to an OpenFin runtime via an adapter + * - Processes started via `System.launchExternalApplication` + * - Processes monitored via `System.monitorExternalProcess` + */ +class ExternalApplication extends base_1$b.EmitterBase { + /** + * @internal + */ + constructor(wire, identity) { + super(wire, 'external-application', identity.uuid); + this.identity = identity; + } + /** + * Retrieves information about the external application. + * + * @example + * ```js + * async function getInfo() { + * const extApp = await fin.ExternalApplication.wrap('javaApp-uuid'); + * return await extApp.getInfo(); + * } + * getInfo().then(info => console.log(info)).catch(err => console.log(err)); + * ``` + */ + getInfo() { + return this.wire.sendAction('get-external-application-info', this.identity).then(({ payload }) => payload.data); + } +} +Instance$4.ExternalApplication = ExternalApplication; + +Object.defineProperty(Factory$5, "__esModule", { value: true }); +Factory$5.ExternalApplicationModule = void 0; +const base_1$a = base; +const Instance_1$4 = Instance$4; +/** + * Static namespace for OpenFin API methods that interact with the {@link ExternalApplication} class, available under `fin.ExternalApplication`. + */ +class ExternalApplicationModule extends base_1$a.Base { + /** + * Asynchronously returns an External Application object that represents an external application. + *
It is possible to wrap a process that does not yet exist, (for example, to listen for startup-related events) + * provided its uuid is already known. + * @param uuid The UUID of the external application to be wrapped + * + * @example + * ```js + * fin.ExternalApplication.wrap('javaApp-uuid'); + * .then(extApp => console.log('wrapped external application')) + * .catch(err => console.log(err)); + * ``` + */ + wrap(uuid) { + this.wire.sendAction('external-application-wrap').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return Promise.resolve(new Instance_1$4.ExternalApplication(this.wire, { uuid })); + } + /** + * Synchronously returns an External Application object that represents an external application. + *
It is possible to wrap a process that does not yet exist, (for example, to listen for startup-related events) + * provided its uuid is already known. + * @param uuid The UUID of the external application to be wrapped + * + * @example + * ```js + * const extApp = fin.ExternalApplication.wrapSync('javaApp-uuid'); + * const info = await extApp.getInfo(); + * console.log(info); + * ``` + */ + wrapSync(uuid) { + this.wire.sendAction('external-application-wrap-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return new Instance_1$4.ExternalApplication(this.wire, { uuid }); + } +} +Factory$5.ExternalApplicationModule = ExternalApplicationModule; + +(function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + /** + * Entry points for the OpenFin `ExternalApplication` API (`fin.ExternalApplication`). + * + * * {@link ExternalApplicationModule} contains static members of the `ExternalApplication` type, accessible through `fin.ExternalApplication`. + * * {@link ExternalApplication} describes an instance of an OpenFin ExternalApplication, e.g. as returned by `fin.ExternalApplication.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + */ + __exportStar(Factory$5, exports); + __exportStar(Instance$4, exports); +} (externalApplication)); + +var frame = {}; + +var Factory$4 = {}; + +var Instance$3 = {}; + +Object.defineProperty(Instance$3, "__esModule", { value: true }); +Instance$3._Frame = void 0; +/* eslint-disable import/prefer-default-export */ +const base_1$9 = base; +/** + * An iframe represents an embedded HTML page within a parent HTML page. Because this embedded page + * has its own DOM and global JS context (which may or may not be linked to that of the parent depending + * on if it is considered out of the root domain or not), it represents a unique endpoint as an OpenFin + * connection. Iframes may be generated dynamically, or be present on initial page load and each non-CORS + * iframe has the OpenFin API injected by default. It is possible to opt into cross-origin iframes having + * the API by setting api.iframe.crossOriginInjection to true in a window's options. To block all iframes + * from getting the API injected you can set api.frame.sameOriginInjection + * to false ({@link OpenFin.WindowCreationOptions see Window Options}). + * + * To be able to directly address this context for eventing and messaging purposes, it needs a + * unique uuid name pairing. For OpenFin applications and windows this is provided via a configuration + * object in the form of a manifest URL or options object, but there is no configuration object for iframes. + * Just as a call to window.open outside of our Window API returns a new window with a random GUID assigned + * for the name, each iframe that has the API injected will be assigned a GUID as its name, the UUID will be + * the same as the parent window's. + * + * The fin.Frame namespace represents a way to interact with `iframes` and facilitates the discovery of current context + * (iframe or main window) as well as the ability to listen for {@link OpenFin.FrameEvents frame-specific events}. + */ +class _Frame extends base_1$9.EmitterBase { + /** + * @internal + */ + constructor(wire, identity) { + super(wire, 'frame', identity.uuid, identity.name); + this.identity = identity; + } + /** + * Returns a frame info object for the represented frame. + * + * @example + * ```js + * async function getInfo() { + * const frm = await fin.Frame.getCurrent(); + * return await frm.getInfo(); + * } + * getInfo().then(info => console.log(info)).catch(err => console.log(err)); + * ``` + */ + getInfo() { + return this.wire.sendAction('get-frame-info', this.identity).then(({ payload }) => payload.data); + } + /** + * Returns a frame info object representing the window that the referenced iframe is + * currently embedded in. + * + * @remarks If the frame is embedded in a view, this will return an invalid stub with empty fields. + * + * @example + * ```js + * async function getParentWindow() { + * const frm = await fin.Frame.getCurrent(); + * return await frm.getParentWindow(); + * } + * getParentWindow().then(winInfo => console.log(winInfo)).catch(err => console.log(err)); + * ``` + */ + getParentWindow() { + return this.wire.sendAction('get-parent-window', this.identity).then(({ payload }) => payload.data); + } +} +Instance$3._Frame = _Frame; + +Object.defineProperty(Factory$4, "__esModule", { value: true }); +Factory$4._FrameModule = void 0; +const base_1$8 = base; +const validate_1$2 = validate; +const Instance_1$3 = Instance$3; +/** + * Static namespace for OpenFin API methods that interact with the {@link _Frame} class, available under `fin.Frame`. + */ +class _FrameModule extends base_1$8.Base { + /** + * Asynchronously returns an API handle for the given Frame identity. + * + * @remarks Wrapping a Frame identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a Frame throughout its entire lifecycle. + * + * @example + * ```js + * fin.Frame.wrap({ uuid: 'testFrame', name: 'testFrame' }) + * .then(frm => console.log('wrapped frame')) + * .catch(err => console.log(err)); + * ``` + */ + async wrap(identity) { + this.wire.sendAction('frame-wrap').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1$2.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1$3._Frame(this.wire, identity); + } + /** + * Synchronously returns an API handle for the given Frame identity. + * + * @remarks Wrapping a Frame identity that does not yet exist will *not* throw an error, and instead + * returns a stub object that cannot yet perform rendering tasks. This can be useful for plumbing eventing + * for a Frame throughout its entire lifecycle. + * + * @example + * ```js + * const frm = fin.Frame.wrapSync({ uuid: 'testFrame', name: 'testFrame' }); + * const info = await frm.getInfo(); + * console.log(info); + * ``` + */ + wrapSync(identity) { + this.wire.sendAction('frame-wrap-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const errorMsg = (0, validate_1$2.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + return new Instance_1$3._Frame(this.wire, identity); + } + /** + * Asynchronously returns a reference to the current frame + * + * @example + * ```js + * fin.Frame.getCurrent() + * .then(frm => console.log('current frame')) + * .catch(err => console.log(err)); + * ``` + */ + getCurrent() { + this.wire.sendAction('frame-get-current').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return Promise.resolve(new Instance_1$3._Frame(this.wire, this.wire.environment.getCurrentEntityIdentity())); + } + /** + * Synchronously returns a reference to the current frame + * + * @example + * ```js + * const frm = fin.Frame.getCurrentSync(); + * const info = await frm.getInfo(); + * console.log(info); + * ``` + */ + getCurrentSync() { + this.wire.sendAction('frame-get-current-sync').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return new Instance_1$3._Frame(this.wire, this.wire.environment.getCurrentEntityIdentity()); + } +} +Factory$4._FrameModule = _FrameModule; + +(function (exports) { + /** + * Entry points for the OpenFin `Frame` API (`fin.Frame`). + * + * * {@link _FrameModule} contains static members of the `Frame` API, accessible through `fin.Frame`. + * * {@link _Frame} describes an instance of an OpenFin Frame, e.g. as returned by `fin.Frame.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * Underscore prefixing of OpenFin types that alias DOM entities will be fixed in a future version. + * + * @packageDocumentation + */ + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(Factory$4, exports); + __exportStar(Instance$3, exports); +} (frame)); + +var globalHotkey = {}; + +Object.defineProperty(globalHotkey, "__esModule", { value: true }); +globalHotkey.GlobalHotkey = void 0; +const base_1$7 = base; +/** + * The GlobalHotkey module can register/unregister a global hotkeys. + * + */ +class GlobalHotkey extends base_1$7.EmitterBase { + /** + * @internal + */ + constructor(wire) { + super(wire, 'global-hotkey'); + } + /** + * Registers a global hotkey with the operating system. + * @param hotkey a hotkey string + * @param listener called when the registered hotkey is pressed by the user. + * @throws If the `hotkey` is reserved, see list below. + * @throws if the `hotkey` is already registered by another application. + * + * @remarks The `hotkey` parameter expects an electron compatible [accelerator](https://github.com/electron/electron/blob/master/docs/api/accelerator.md) and the `listener` will be called if the `hotkey` is pressed by the user. + * If successfull, the hotkey will be 'claimed' by the application, meaning that this register call can be called multiple times from within the same application but will fail if another application has registered the hotkey. + *
The register call will fail if given any of these reserved Hotkeys: + * * `CommandOrControl+0` + * * `CommandOrControl+=` + * * `CommandOrControl+Plus` + * * `CommandOrControl+-` + * * `CommandOrControl+_` + * * `CommandOrControl+Shift+I` + * * `F5` + * * `CommandOrControl+R` + * * `Shift+F5` + * * `CommandOrControl+Shift+R` + * + * Raises the `registered` event. + * + * @example + * ```js + * const hotkey = 'CommandOrControl+X'; + * + * fin.GlobalHotkey.register(hotkey, () => { + * console.log(`${hotkey} pressed`); + * }) + * .then(() => { + * console.log('Success'); + * }) + * .catch(err => { + * console.log('Error registering the hotkey', err); + * }); + * ``` + */ + async register(hotkey, listener) { + // TODO: fix typing (hotkey events are not typed) + // @ts-expect-error + await this.on(hotkey, listener); + await this.wire.sendAction('global-hotkey-register', { hotkey }); + return undefined; + } + /** + * Unregisters a global hotkey with the operating system. + * @param hotkey a hotkey string + * + * @remarks This method will unregister all existing registrations of the hotkey within the application. + * Raises the `unregistered` event. + * + * @example + * ```js + * const hotkey = 'CommandOrControl+X'; + * + * fin.GlobalHotkey.unregister(hotkey) + * .then(() => { + * console.log('Success'); + * }) + * .catch(err => { + * console.log('Error unregistering the hotkey', err); + * }); + * ``` + */ + async unregister(hotkey) { + // TODO: fix typing (hotkey events are not typed) + // @ts-expect-error + await this.removeAllListeners(hotkey); + await this.wire.sendAction('global-hotkey-unregister', { hotkey }); + return undefined; + } + /** + * Unregisters all global hotkeys for the current application. + * + * @remarks Raises the `unregistered` event for each hotkey unregistered. + * + * @example + * ```js + * fin.GlobalHotkey.unregisterAll() + * .then(() => { + * console.log('Success'); + * }) + * .catch(err => { + * console.log('Error unregistering all hotkeys for this application', err); + * }); + * ``` + */ + async unregisterAll() { + await Promise.all(this.eventNames() + .filter((name) => !(name === 'registered' || name === 'unregistered')) + // TODO: fix typing (hotkey events are not typed) + // @ts-expect-error + .map((name) => this.removeAllListeners(name))); + await this.wire.sendAction('global-hotkey-unregister-all', {}); + return undefined; + } + /** + * Checks if a given hotkey has been registered by an application within the current runtime. + * @param hotkey a hotkey string + * + * @example + * ```js + * const hotkey = 'CommandOrControl+X'; + * + * fin.GlobalHotkey.isRegistered(hotkey) + * .then((registered) => { + * console.log(`hotkey ${hotkey} is registered ? ${registered}`); + * }) + * .catch(err => { + * console.log('Error unregistering the hotkey', err); + * }); + * ``` + */ + async isRegistered(hotkey) { + const { payload: { data } } = await this.wire.sendAction('global-hotkey-is-registered', { hotkey }); + return data; + } +} +globalHotkey.GlobalHotkey = GlobalHotkey; + +var platform = {}; + +var Factory$3 = {}; + +var Instance$2 = {}; + +var __classPrivateFieldGet$5 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _Platform_connectToProvider; +Object.defineProperty(Instance$2, "__esModule", { value: true }); +Instance$2.Platform = void 0; +/* eslint-disable import/prefer-default-export, no-undef */ +const base_1$6 = base; +const validate_1$1 = validate; +// Reuse clients to avoid overwriting already-registered client in provider +const clientMap = new Map(); +/** Manages the life cycle of windows and views in the application. + * + * Enables taking snapshots of itself and applying them to restore a previous configuration + * as well as listen to {@link OpenFin.PlatformEvents platform events}. + */ +class Platform extends base_1$6.EmitterBase { + /** + * @internal + */ + // eslint-disable-next-line no-shadow + constructor(identity, channel) { + // we piggyback off of application event emitter because from the core's perspective platform is just an app. + super(channel.wire, 'application', identity.uuid); + this.getClient = (identity) => { + this.wire.sendAction('platform-get-client', this.identity).catch((e) => { + // don't expose + }); + const target = identity || this.identity; + const { uuid } = target; + if (!clientMap.has(uuid)) { + const clientPromise = __classPrivateFieldGet$5(this, _Platform_connectToProvider, "f").call(this, uuid); + clientMap.set(uuid, clientPromise); + } + // we set it above + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return clientMap.get(uuid); + }; + _Platform_connectToProvider.set(this, async (uuid) => { + try { + const channelName = `custom-frame-${uuid}`; + const client = await this._channel.connect(channelName, { wait: false }); + client.onDisconnection(() => { + clientMap.delete(uuid); + }); + return client; + } + catch (e) { + clientMap.delete(uuid); + throw new Error('The targeted Platform is not currently running. Listen for application-started event for the given Uuid.'); + } + }); + /** + * @deprecated (renamed) + * @ignore + */ + this.launchLegacyManifest = this.launchContentManifest; + const errorMsg = (0, validate_1$1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + this._channel = channel; + this.identity = { uuid: identity.uuid }; + this.Layout = this.fin.Platform.Layout; + this.Application = this.fin.Application.wrapSync(this.identity); + } + /** + * Creates a new view and attaches it to a specified target window. + * @param viewOptions View creation options + * @param target The window to which the new view is to be attached. If no target, create a view in a new window. + * @param targetView If provided, the new view will be added to the same tabstrip as targetView. + * + * @remarks If the view already exists, will reparent the view to the new target. You do not need to set a name for a View. + * Views that are not passed a name get a randomly generated one. + * + * @example + * ```js + * let windowIdentity; + * if (fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const platform = fin.Platform.getCurrentSync(); + * + * platform.createView({ + * name: 'test_view', + * url: 'https://developers.openfin.co/docs/platform-api' + * }, windowIdentity).then(console.log); + * ``` + * + * Reparenting a view: + * ```js + * let windowIdentity; + * if (fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * let platform = fin.Platform.getCurrentSync(); + * let viewOptions = { + * name: 'example_view', + * url: 'https://example.com' + * }; + * // a new view will now show in the current window + * await platform.createView(viewOptions, windowIdentity); + * + * const view = fin.View.wrapSync({ uuid: windowIdentity.uuid, name: 'yahoo_view' }); + * // reparent `example_view` when a view in the new window is shown + * view.on('shown', async () => { + * let viewIdentity = { uuid: windowIdentity.uuid, name: 'example_view'}; + * let target = {uuid: windowIdentity.uuid, name: 'test_win'}; + * platform.createView(viewOptions, target); + * }); + * + * // create a new window + * await platform.createWindow({ + * name: "test_win", + * layout: { + * content: [ + * { + * type: 'stack', + * content: [ + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'yahoo_view', + * url: 'https://yahoo.com' + * } + * } + * ] + * } + * ] + * } + * }).then(console.log); + * ``` + */ + async createView(viewOptions, target, targetView) { + this.wire.sendAction('platform-create-view', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + const response = await client.dispatch('create-view', { + target, + opts: viewOptions, + targetView + }); + if (!response || (0, validate_1$1.validateIdentity)(response.identity)) { + throw new Error(`When overwriting the createView call, please return an object that has a valid 'identity' property: ${JSON.stringify(response)}`); + } + return this.fin.View.wrapSync(response.identity); + } + /** + * Creates a new Window. + * @param options Window creation options + * + * @remarks There are two Window types at your disposal while using OpenFin Platforms - Default Window and Custom Window. + * + * The Default Window uses the standard OpenFin Window UI. It contains the standard close, maximize and minimize buttons, + * and will automatically render the Window's layout if one is specified. + * + * For deeper customization, you can bring your own Window code into a Platform. This is called a Custom Window. + * + * @example + * + * + * The example below will create a Default Window which uses OpenFin default Window UI.
+ * The Window contains two Views in a stack Layout: + * + * ```js + * const platform = fin.Platform.getCurrentSync(); + * platform.createWindow({ + * layout: { + * content: [ + * { + * type: 'stack', + * content: [ + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'test_view_1', + * url: 'https://cdn.openfin.co/docs/javascript/canary/Platform.html' + * } + * }, + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'test_view_2', + * url: 'https://cdn.openfin.co/docs/javascript/canary/Platform.html' + * } + * } + * ] + * } + * ] + * } + * }).then(console.log); + * ``` + * The Default Window's design can be customized by specifying the `stylesheetUrl` property in the manifest: + * + * ```json + * { + * platform: { + * defaultWindowOptions: { + * stylesheetUrl: 'some-url.css', + * ... + * } + * } + * } + * ``` + * For a list of common Layout CSS classes you can override in your custom stylesheet, see Useful Layout CSS Classes + ** + * To specify a Platform Custom Window, provide a `url` property when creating a Window. + * If you intend to render a Layout in your Custom Window, you must also specify an `HTMLElement` that the Layout will inject into and set its `id` property to `"layout-container"`. + * + * The example below will create a Platform Custom Window: + * + * ```js + * // in an OpenFin app: + * const platform = fin.Platform.getCurrentSync(); + * const windowConfig = + * { + * url: "https://www.my-domain.com/my-custom-window.html", // here we point to where the Custom Frame is hosted. + * layout: { + * content: [ + * { + * type: "stack", + * content: [ + * { + * type: "component", + * componentName: "view", + * componentState: { + * name: "app #1", + * url: "https://cdn.openfin.co/docs/javascript/canary/Platform.html" + * } + * }, + * { + * type: "component", + * componentName: "view", + * componentState: { + * name: "app #2", + * url: "https://cdn.openfin.co/docs/javascript/canary/Platform.html" + * } + * } + * ] + * } + * ] + * } + * }; + * platform.createWindow(windowConfig); + * ``` + * + * Here's an example of a minimalist Custom Platform Window implementation: + * ```html + * + * + * + * + * + * + * + *
+ *
+ *
+ *
This is a custom frame!
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * + *
+ * + * + * ``` + * Your Custom Window can use in-domain resources for further customization (such as CSS, scripts, etc.).
+ * For a list of common Layout CSS classes you can override in your stylesheet, see Useful Layout CSS Classes + * + * The example above will require the `body` element to have `height: 100%;` set in order to render the layout correctly. + */ + async createWindow(options) { + this.wire.sendAction('platform-create-window', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + if (!options.reason) { + options.reason = 'api-call'; + } + const response = await client.dispatch('create-view-container', options); + if (!response || (0, validate_1$1.validateIdentity)(response.identity)) { + throw new Error(`When overwriting the createWindow call, please return an object that has a valid 'identity' property: ${JSON.stringify(response)}`); + } + const { identity } = response; + const res = this.fin.Window.wrapSync(identity); + // we add the identity at the top level for backwards compatibility. + res.name = identity.name; + res.uuid = identity.uuid; + return res; + } + /** + * Closes current platform, all its windows, and their views. + * + * @example + * ```js + * const platform = await fin.Platform.getCurrent(); + * platform.quit(); + * // All windows/views in current layout platform will close and platform will shut down + * ``` + */ + async quit() { + this.wire.sendAction('platform-quit', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + return client.dispatch('quit'); + } + /** + * Closes a specified view in a target window. + * @param viewIdentity View identity + * + * @example + * ```js + * let windowIdentity; + * if (fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const viewOptions = { + * name: 'test_view', + * url: 'https://example.com' + * }; + * + * function sleep(ms) { + * return new Promise(resolve => setTimeout(resolve, ms)); + * } + * + * const platform = await fin.Platform.getCurrent(); + * + * await platform.createView(viewOptions, windowIdentity); + * // a new view will now show in the current window + * + * await sleep(5000); + * + * const viewIdentity = { uuid: windowIdentity.uuid, name: 'test_view'}; + * platform.closeView(viewIdentity); + * // the view will now close + * ``` + */ + async closeView(viewIdentity) { + this.wire.sendAction('platform-close-view', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + await client.dispatch('close-view', { + view: viewIdentity + }); + } + /** + * ***DEPRECATED - please use {@link Platform.createView Platform.createView}.*** + * Reparents a specified view in a new target window. + * @param viewIdentity View identity + * @param target new owner window identity + * + */ + async reparentView(viewIdentity, target) { + // eslint-disable-next-line no-console + console.warn('Platform.reparentView has been deprecated, please use Platform.createView'); + this.wire.sendAction('platform-reparent-view', this.identity).catch((e) => { + // don't expose + }); + const normalizedViewIdentity = { + ...viewIdentity, + uuid: viewIdentity.uuid ?? this.identity.uuid + }; + const view = await this.fin.View.wrap(normalizedViewIdentity); + const viewOptions = await view.getOptions(); + return this.createView(viewOptions, target); + } + /** + * Returns a snapshot of the platform in its current state. You can pass the returning object to + * [Platform.applySnapshot]{@link Platform#applySnapshot} to launch it. + * + * @remarks The snapshot will include details such as an [ISO format](https://en.wikipedia.org/wiki/ISO_8601) + * timestamp of when the snapshot was taken, OpenFin runtime version the platform is running on, monitor information + * and the list of currently running windows. + * + * @example + * ```js + * const platform = await fin.Platform.getCurrent(); + * const snapshot = await platform.getSnapshot(); + * ``` + */ + async getSnapshot() { + this.wire.sendAction('platform-get-snapshot', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + return client.dispatch('get-snapshot'); + } + /** + * **NOTE**: Internal use only. It is not recommended to manage the state of individual views. + * + * Returns a snapshot of a single view's options in its current state. + * + * Can be used to restore a view to a previous state. + * + * @param viewIdentity View identity + * + * @internal + * @experimental + * @remarks This slice of snapshot state is equivalent to what is stored as `componentState` for views + * when capturing platform state using [Platform.getSnapshot]{@link Platform#getSnapshot}. + * + * @example + * ```js + * const platform = await fin.Platform.getCurrent(); + * const url = 'https://google.com'; + * const view = await fin.View.create({ name: 'my-view', target: fin.me.identity, url }); + * + * await view.navigate(url); + * + * const viewState = await platform.getViewSnapshot(view.identity); + * + * console.log(viewState); + * ``` + */ + async getViewSnapshot(viewIdentity) { + const client = await this.getClient(); + return client.dispatch('get-view-snapshot', { viewIdentity }); + } + /** + * Adds a snapshot to a running Platform. + * Requested snapshot must be a valid Snapshot object, or a url or filepath to such an object. + * + * Can optionally close existing windows and overwrite current platform state with that of a snapshot. + * + * The function accepts either a snapshot taken using {@link Platform#getSnapshot getSnapshot}, + * or a url or filepath to a snapshot JSON object. + * @param requestedSnapshot Snapshot to apply, or a url or filepath. + * @param options Optional parameters to specify whether existing windows should be closed. + * + * @remarks Will create any windows and views that are not running but are passed in the snapshot object. Any View + * specified in the snapshot is assigned a randomly generated name to avoid collisions. + * + * @example + * ```js + * // Get a wrapped layout platform instance + * const platform = await fin.Platform.getCurrent(); + * + * const snapshot = { + * windows: [ + * { + * layout: { + * content: [ + * { + * type: 'stack', + * content: [ + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'component_X', + * url: 'https://www.openfin.co' + * } + * }, + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'component_Y', + * url: 'https://cdn.openfin.co/embed-web/chart.html' + * } + * } + * ] + * } + * ] + * } + * } + * ] + * } + * + * platform.applySnapshot(snapshot); + * ``` + * + * In place of a snapshot object, `applySnapshot` can take a url or filepath and to retrieve a JSON snapshot. + * + * ```js + * const platform = await fin.Platform.getCurrent(); + * platform.applySnapshot('https://api.jsonbin.io/b/5e6f903ef4331e681fc1231d/1'); + * ``` + * + * Optionally, `applySnapshot` can close existing windows and restore a Platform to a previously saved state. + * This is accomplished by providing `{ closeExistingWindows: true }` as an option. + * + * ```js + * // Get a wrapped layout platform instance + * const platform = await fin.Platform.getCurrent(); + * + * async function addViewToWindow(winId) { + * return await platform.createView({ + * name: 'test_view_3', + * url: 'https://openfin.co' + * }, winId); + * } + * + * async function createWindowWithTwoViews() { + * const platform = await fin.Platform.getCurrent(); + * + * return platform.createWindow({ + * layout: { + * content: [ + * { + * type: 'stack', + * content: [ + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'test_view_1', + * url: 'https://example.com' + * } + * }, + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'test_view_2', + * url: 'https://yahoo.com' + * } + * } + * ] + * } + * ] + * } + * }); + * } + * + * const win = await createWindowWithTwoViews(); + * // ... you will now see a new window with two views in it + * + * // we take a snapshot of the current state of the app, before changing it + * const snapshotOfInitialAppState = await platform.getSnapshot(); + * + * // now let's change the state of the app: + * await addViewToWindow(win.identity); + * // ... the window now has three views in it + * + * await platform.applySnapshot(snapshotOfInitialAppState, { closeExistingWindows: true }); + * // ... the window will revert to previous state, with just two views + * + * ``` + */ + async applySnapshot(requestedSnapshot, options) { + this.wire.sendAction('platform-apply-snapshot', this.identity).catch((e) => { + // don't expose + }); + const errMsg = 'Requested snapshot must be a valid Snapshot object, or a url or filepath to such an object.'; + let snapshot; + if (typeof requestedSnapshot === 'string') { + // Fetch and parse snapshot + try { + const response = await this._channel.wire.sendAction('get-application-manifest', { + manifestUrl: requestedSnapshot + }); + snapshot = response.payload.data; + } + catch (err) { + throw new Error(`${errMsg}: ${err}`); + } + } + else { + snapshot = requestedSnapshot; + } + if (!snapshot.windows) { + throw new Error(errMsg); + } + const client = await this.getClient(); + await client.dispatch('apply-snapshot', { + snapshot, + options + }); + return this; + } + /** + * Fetches a JSON manifest using the browser process and returns a Javascript object. + * Can be overwritten using {@link Platform.PlatformModule.init Platform.init}. + * @param manifestUrl The URL of the manifest to fetch. + * + * @remarks Can be overwritten using {@link Platform#init Platform.init}. + * + * @example + * + * ```js + * const platform = fin.Platform.getCurrentSync(); + * const manifest = await platform.fetchManifest('https://www.path-to-manifest.com/app.json'); + * console.log(manifest); + * ``` + */ + async fetchManifest(manifestUrl) { + const client = await this.getClient(); + return client.dispatch('platform-fetch-manifest', { manifestUrl }); + } + /** + * Retrieves a manifest by url and launches a legacy application manifest or snapshot into the platform. Returns a promise that + * resolves to the wrapped Platform. + * @param manifestUrl - The URL of the manifest that will be launched into the platform. If this app manifest + * contains a snapshot, that will be launched into the platform. If not, the application described in startup_app options + * will be launched into the platform. The applicable startup_app options will become {@link OpenFin.ViewCreationOptions View Options}. + * + * @remarks If the app manifest contains a snapshot, that will be launched into the platform. If not, the + * application described in startup_app options will be launched into the platform as a window with a single view. + * The applicable startup_app options will become View Options. + * + * @example + * ```js + * try { + * const platform = fin.Platform.getCurrentSync(); + * await platform.launchContentManifest('http://localhost:5555/app.json'); + * console.log(`content launched successfully into platform`); + * } catch(e) { + * console.error(e); + * } + * // For a local manifest file: + * try { + * const platform = fin.Platform.getCurrentSync(); + * platform.launchContentManifest('file:///C:/somefolder/app.json'); + * console.log(`content launched successfully into platform`); + * } catch(e) { + * console.error(e); + * } + * ``` + * @experimental + */ + async launchContentManifest(manifestUrl) { + this.wire.sendAction('platform-launch-content-manifest', this.identity).catch(() => { + // don't expose + }); + const client = await this.getClient(); + const manifest = await this.fetchManifest(manifestUrl); + client.dispatch('launch-into-platform', { manifest, manifestUrl }); + return this; + } + /** + * Set the context of a host window. The context will be available to the window itself, and to its child Views. It will be saved in any platform snapshots. + * It can be retrieved using {@link Platform#getWindowContext getWindowContext}. + * @param context - A field where serializable context data can be stored to be saved in platform snapshots. + * @param target - A target window or view may optionally be provided. If no target is provided, the update will be applied + * to the current window (if called from a Window) or the current host window (if called from a View). + * + * @remarks The context data must be serializable. This can only be called from a window or view that has been launched into a + * platform. + * This method can be called from the window itself, or from any child view. Context data is shared by all + * entities within a window. + * + * @example + * Setting own context: + * ```js + * const platform = fin.Platform.getCurrentSync(); + * const contextData = { + * security: 'STOCK', + * currentView: 'detailed' + * } + * + * await platform.setWindowContext(contextData); + * // Context of current window is now set to `contextData` + * ``` + * + * Setting the context of another window or view: + * ```js + * const platform = fin.Platform.getCurrentSync(); + * const contextData = { + * security: 'STOCK', + * currentView: 'detailed' + * } + * + * const windowOrViewIdentity = { uuid: fin.me.uuid, name: 'nameOfWindowOrView' }; + * await platform.setWindowContext(contextData, windowOrViewIdentity); + * // Context of the target window or view is now set to `contextData` + * ``` + * + * A view can listen to changes to its host window's context by listening to the `host-context-changed` event. + * This event will fire when a host window's context is updated or when the view is reparented to a new window: + * + * ```js + * // From a view + * const contextChangeHandler = ({ context }) => { + * console.log('Host window\'s context has changed. New context data:', context); + * // react to new context data here + * } + * await fin.me.on('host-context-changed', contextChangeHandler); + * + * const platform = await fin.Platform.getCurrentSync(); + * const contextData = { + * security: 'STOCK', + * currentView: 'detailed' + * } + * platform.setWindowContext(contextData) // contextChangeHandler will log the new context + * ``` + * + * To listen to a window's context updates, use the `context-changed` event: + * ```js + * // From a window + * const contextChangeHandler = ({ context }) => { + * console.log('This window\'s context has changed. New context data:', context); + * // react to new context data here + * } + * await fin.me.on('context-changed', contextChangeHandler); + * + * const platform = await fin.Platform.getCurrentSync(); + * const contextData = { + * security: 'STOCK', + * currentView: 'detailed' + * } + * platform.setWindowContext(contextData) // contextChangeHandler will log the new context + * ``` + * @experimental + */ + async setWindowContext(context = {}, target) { + this.wire.sendAction('platform-set-window-context', this.identity).catch((e) => { + // don't expose + }); + if (!context) { + throw new Error('Please provide a serializable object or string to set the context.'); + } + const client = await this.getClient(); + const { entityType } = target ? await this.fin.System.getEntityInfo(target.uuid, target.name) : this.fin.me; + await client.dispatch('set-window-context', { + context, + entityType, + target: target || { uuid: this.fin.me.uuid, name: this.fin.me.name } + }); + } + /** + * Get the context context of a host window that was previously set using {@link Platform#setWindowContext setWindowContext}. + * The context will be saved in any platform snapshots. Returns a promise that resolves to the context. + * @param target - A target window or view may optionally be provided. If no target is provided, target will be + * the current window (if called from a Window) or the current host window (if called from a View). + * + * @remarks This method can be called from the window itself, or from any child view. Context data is shared + * by all entities within a window. + * + * @example + * + * Retrieving context from current window: + * ```js + * const platform = fin.Platform.getCurrentSync(); + * const customContext = { answer: 42 }; + * await platform.setWindowContext(customContext); + * + * const myContext = await platform.getWindowContext(); + * console.log(myContext); // { answer: 42 } + * ``` + * + * Retrieving the context of another window or view: + * ```js + * const platform = fin.Platform.getCurrentSync(); + * + * const windowOrViewIdentity = { uuid: fin.me.uuid, name: 'nameOfWindowOrView' }; + * + * const targetWindowContext = await platform.getWindowContext(windowOrViewIdentity); + * console.log(targetWindowContext); // context of target window + * ``` + * @experimental + */ + async getWindowContext(target) { + this.wire.sendAction('platform-get-window-context', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + const { entityType } = target ? await this.fin.System.getEntityInfo(target.uuid, target.name) : this.fin.me; + return client.dispatch('get-window-context', { + target: target || { uuid: this.fin.me.uuid, name: this.fin.me.name }, + entityType + }); + } + /** + * Closes a window. If enableBeforeUnload is enabled in the Platform options, any beforeunload handler set on Views will fire + * This behavior can be disabled by setting skipBeforeUnload to false in the options parameter. + * @param winId + * @param options + * + * @remarks This method works by setting a `close-requested` handler on the Platform Window. If you have your own `close-requested` handler set on the Platform Window as well, + * it is recommended to move that logic over to the [PlatformProvider.closeWindow]{@link PlatformProvider#closeWindow} override to ensure it runs when the Window closes. + * + * @example + * + * ```js + * // Close the current Window inside a Window context + * const platform = await fin.Platform.getCurrent(); + * platform.closeWindow(fin.me.identity); + * + * // Close the Window from inside a View context + * const platform = await fin.Platform.getCurrent(); + * const parentWindow = await fin.me.getCurrentWindow(); + * platform.closeWindow(parentWindow.identity); + * + * // Close the Window and do not fire the before unload handler on Views + * const platform = await fin.Platform.getCurrent(); + * platform.closeWindow(fin.me.identity, { skipBeforeUnload: true }); + * ``` + * @experimental + */ + async closeWindow(windowId, options = { skipBeforeUnload: false }) { + this.wire.sendAction('platform-close-window', this.identity).catch((e) => { + // don't expose + }); + const client = await this.getClient(); + return client.dispatch('close-window', { windowId, options }); + } +} +Instance$2.Platform = Platform; +_Platform_connectToProvider = new WeakMap(); + +var layout = {}; + +var Factory$2 = {}; + +var Instance$1 = {}; + +var commonUtils = {}; + +Object.defineProperty(commonUtils, "__esModule", { value: true }); +commonUtils.overrideFromComposables = commonUtils.isValidPresetType = void 0; +function isValidPresetType(type) { + switch (type) { + case 'columns': + case 'grid': + case 'rows': + case 'tabs': + return true; + default: + return false; + } +} +commonUtils.isValidPresetType = isValidPresetType; +function overrideFromComposables(...overrides) { + return (base) => overrides.reduceRight((p, c) => (b) => c(p(b)), (x) => x)(base); +} +commonUtils.overrideFromComposables = overrideFromComposables; +commonUtils.default = { isValidPresetType }; + +var __classPrivateFieldGet$4 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _Layout_layoutClient; +Object.defineProperty(Instance$1, "__esModule", { value: true }); +Instance$1.Layout = void 0; +const lazy_1 = lazy; +const validate_1 = validate; +const base_1$5 = base; +const common_utils_1 = commonUtils; +const layout_entities_1 = layoutEntities; +const layout_constants_1$1 = layout_constants; +/** + * + * Layouts give app providers the ability to embed multiple views in a single window. The Layout namespace + * enables the initialization and manipulation of a window's Layout. A Layout will + * emit events locally on the DOM element representing the layout-container. + * + * + * ### Layout.DOMEvents + * + * When a Layout is created, it emits events onto the DOM element representing the Layout container. + * This Layout container is the DOM element referenced by containerId in {@link Layout.LayoutModule#init Layout.init}. + * You can use the built-in event emitter to listen to these events using [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener). + * The events are emitted synchronously and only in the process where the Layout exists. + * Any values returned by the called listeners are ignored and will be discarded. + * If the target DOM element is destroyed, any events that have been set up on that element will be destroyed. + * + * @remarks The built-in event emitter is not an OpenFin event emitter so it doesn't share propagation semantics. + * + * #### {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener addEventListener(type, listener [, options]);} + * Adds a listener to the end of the listeners array for the specified event. + * @example + * ```js + * const myLayoutContainer = document.getElementById('layout-container'); + * + * myLayoutContainer.addEventListener('tab-created', function(event) { + * const { tabSelector } = event.detail; + * const tabElement = document.getElementById(tabSelector); + * const existingColor = tabElement.style.backgroundColor; + * tabElement.style.backgroundColor = "red"; + * setTimeout(() => { + * tabElement.style.backgroundColor = existingColor; + * }, 2000); + * }); + * ``` + * + * #### {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener removeEventListener(type, listener [, options]);} + * Adds a listener to the end of the listeners array for the specified event. + * @example + * ```js + * const myLayoutContainer = document.getElementById('layout-container'); + * + * const listener = function(event) { + * console.log(event.detail); + * console.log('container-created event fired once, removing listener'); + * myLayoutContainer.removeEventListener('container-created', listener); + * }; + * + * myLayoutContainer.addEventListener('container-created', listener); + * ``` + * + * ### Supported event types are: + * + * * tab-created + * * container-created + * * layout-state-changed + * * tab-closed + * * tab-dropped + * + * ### Layout DOM Node Events + * + * #### tab-created + * Generated when a tab is created. As a user drags and drops tabs within window, new tabs are created. A single view may have multiple tabs created and destroyed during its lifetime attached to a single window. + * ```js + * // The response has the following shape in event.detail: + * { + * containerSelector: "container-component_A", + * name: "component_A", + * tabSelector: "tab-component_A", + * topic: "openfin-DOM-event", + * type: "tab-created", + * uuid: "OpenFin POC" + * } + * ``` + * + * #### container-created + * Generated when a container is created. A single view will have only one container during its lifetime attached to a single window and the container's lifecycle is tied to the view. To discover when the container is destroyed, please listen to view-detached event. + * ```js + * // The response has the following shape in event.detail: + * { + * containerSelector: "container-component_A", + * name: "component_A", + * tabSelector: "tab-component_A", + * topic: "openfin-DOM-event", + * type: "container-created", + * uuid: "OpenFin POC" + * } + * ``` + * + * ### layout-state-changed + * Generated when the state of the layout changes in any way, such as a view added/removed/replaced. Note that this event can fire frequently as the underlying layout can change multiple components from all kinds of changes (resizing for example). Given this, it is recommended to debounce this event and then you can use the {@link Layout#getConfig Layout.getConfig} API to retrieve the most up-to-date state. + * ```js + * // The response has the following shape in event.detail + * { + * containerSelector: "container-component_A", + * name: "component_A", + * tabSelector: "tab-component_A", + * topic: "openfin-DOM-event", + * type: "layout-state-changed", + * uuid: "OpenFin POC" + * } + * ``` + * + * #### tab-closed + * Generated when a tab is closed. + * ```js + * // The response has the following shape in event.detail: + * { + * containerSelector: "container-component_A", + * name: "component_A", + * tabSelector: "tab-component_A", + * topic: "openfin-DOM-event", + * type: "tab-closed", + * uuid: "OpenFin POC", + * url: "http://openfin.co" // The url of the view that was closed. + * } + * ``` + * + * #### tab-dropped + * Generated when a tab is dropped. + * ```js + * // The response has the following shape in event.detail: + * { + * containerSelector: "container-component_A", + * name: "component_A", + * tabSelector: "tab-component_A", + * topic: "openfin-DOM-event", + * type: "tab-dropped", + * uuid: "OpenFin POC", + * url: "http://openfin.co" // The url of the view linked to the dropped tab. + * } + * ``` + */ +class Layout extends base_1$5.Base { + /** + * @internal + */ + // eslint-disable-next-line no-shadow + constructor(identity, wire) { + super(wire); + /** + * @internal + * Lazily constructed {@link LayoutEntitiesClient} bound to this platform's client and identity + * The client is for {@link LayoutEntitiesController} + */ + _Layout_layoutClient.set(this, new lazy_1.Lazy(async () => layout_entities_1.LayoutNode.newLayoutEntitiesClient(await this.platform.getClient(), layout_constants_1$1.LAYOUT_CONTROLLER_ID, this.identity))); + /** + * Replaces a Platform window's layout with a new layout. + * + * @remarks Any views that were in the old layout but not the new layout will be destroyed. Views will be assigned a randomly generated name to avoid collisions. + * @example + * ```js + * let windowIdentity; + * if (fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const layout = fin.Platform.Layout.wrapSync(windowIdentity); + * + * const newLayout = { + * content: [ + * { + * type: 'stack', + * content: [ + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'new_component_A1', + * processAffinity: 'ps_1', + * url: 'https://www.example.com' + * } + * }, + * { + * type: 'component', + * componentName: 'view', + * componentState: { + * name: 'new_component_A2', + * url: 'https://cdn.openfin.co/embed-web/chart.html' + * } + * } + * ] + * } + * ] + * }; + * + * layout.replace(newLayout); + * ``` + */ + this.replace = async (layout) => { + this.wire.sendAction('layout-replace').catch((e) => { + // don't expose + }); + const client = await this.platform.getClient(); + await client.dispatch('replace-layout', { + target: this.identity, + opts: { layout } + }); + }; + /** + * Replaces the specified view with a view with the provided configuration. + * + * @remarks The old view is stripped of its listeners and either closed or attached to the provider window + * depending on `detachOnClose` view option. + * + * @param viewToReplace Identity of the view to be replaced + * @param newView Creation options of the new view. + * + * @example + * ```js + * let currentWindow; + * if (fin.me.isWindow) { + * currentWindow = fin.me; + * } else if (fin.me.isView) { + * currentWindow = await fin.me.getCurrentWindow(); + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const layout = fin.Platform.Layout.wrapSync(currentWindow.identity); + * const viewToReplace = (await currentWindow.getCurrentViews())[0]; + * const newViewConfig = {url: 'https://example.com'}; + * await layout.replaceView(viewToReplace.identity, newViewConfig); + * ``` + */ + this.replaceView = async (viewToReplace, newView) => { + this.wire.sendAction('layout-replace-view').catch((e) => { + // don't expose + }); + const client = await this.platform.getClient(); + await client.dispatch('replace-view', { + target: this.identity, + opts: { viewToReplace, newView } + }); + }; + /** + * Replaces a Platform window's layout with a preset layout arrangement using the existing Views attached to the window. + * The preset options are `columns`, `grid`, `rows`, and `tabs`. + * @param options Mandatory object with `presetType` property that sets which preset layout arrangement to use. + * The preset options are `columns`, `grid`, `rows`, and `tabs`. + * + * @example + * ```js + * let windowIdentity; + * if (fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const layout = fin.Platform.Layout.wrapSync(windowIdentity); + * await layout.applyPreset({ presetType: 'grid' }); + * + * // wait 5 seconds until you change the layout from grid to tabs + * await new Promise (res => setTimeout(res, 5000)); + * await layout.applyPreset({ presetType: 'tabs' }); + * ``` + */ + this.applyPreset = async (options) => { + this.wire.sendAction('layout-apply-preset').catch((e) => { + // don't expose + }); + const client = await this.platform.getClient(); + const { presetType } = options; + if (!presetType || !(0, common_utils_1.isValidPresetType)(presetType)) { + throw new Error('Cannot apply preset layout, please include an applicable presetType property in the PresetLayoutOptions.'); + } + await client.dispatch('apply-preset-layout', { + target: this.identity, + opts: { presetType } + }); + }; + const errorMsg = (0, validate_1.validateIdentity)(identity); + if (errorMsg) { + throw new Error(errorMsg); + } + this.identity = identity; + this.platform = this.fin.Platform.wrapSync({ uuid: identity.uuid }); + if (identity.uuid === this.fin.me.uuid && identity.name === this.fin.me.name) { + this.init = this.fin.Platform.Layout.init; + } + } + /** + * Returns the configuration of the window's layout. Returns the same information that is returned for all windows in getSnapshot. + * + * @remarks Cannot be called from a View. + * + * + * @example + * ```js + * const layout = fin.Platform.Layout.getCurrentSync(); + * // Use wrapped instance to get the layout configuration of the current window's Layout: + * const layoutConfig = await layout.getConfig(); + * ``` + */ + async getConfig() { + this.wire.sendAction('layout-get-config').catch((e) => { + // don't expose + }); + const client = await this.platform.getClient(); + return client.dispatch('get-frame-snapshot', { + target: this.identity + }); + } + /** + * Retrieves the attached views in current window layout. + * + * @example + * ```js + * const layout = fin.Platform.Layout.getCurrentSync(); + * const views = await layout.getCurrentViews(); + * ``` + */ + async getCurrentViews() { + this.wire.sendAction('layout-get-views').catch((e) => { + // don't expose + }); + const client = await this.platform.getClient(); + const viewIdentities = await client.dispatch('get-layout-views', { + target: this.identity + }); + return viewIdentities.map((identity) => this.fin.View.wrapSync(identity)); + } + /** + * Retrieves the top level content item of the layout. + * + * @remarks Cannot be called from a view. + * + * + * + * @example + * ```js + * if (!fin.me.isWindow) { + * throw new Error('Not running in a platform View.'); + * } + * + * // From the layout window + * const layout = fin.Platform.Layout.getCurrentSync(); + * // Retrieves the ColumnOrRow instance + * const rootItem = await layout.getRootItem(); + * const content = await rootItem.getContent(); + * console.log(`The root ColumnOrRow instance has ${content.length} item(s)`); + * ``` + */ + async getRootItem() { + this.wire.sendAction('layout-get-root-item').catch(() => { + // don't expose + }); + const client = await __classPrivateFieldGet$4(this, _Layout_layoutClient, "f").getValue(); + const root = await client.getRoot('layoutName' in this.identity ? this.identity : undefined); + return layout_entities_1.LayoutNode.getEntity(root, client); + } +} +Instance$1.Layout = Layout; +_Layout_layoutClient = new WeakMap(); + +var __classPrivateFieldGet$3 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet$3 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _LayoutModule_instances, _LayoutModule_layoutInitializationAttempted, _LayoutModule_layoutManager, _LayoutModule_getLayoutManagerSpy, _LayoutModule_getSafeLayoutManager; +Object.defineProperty(Factory$2, "__esModule", { value: true }); +Factory$2.LayoutModule = void 0; +const base_1$4 = base; +const Instance_1$2 = Instance$1; +const layout_constants_1 = layout_constants; +/** + * Static namespace for OpenFin API methods that interact with the {@link Layout} class, available under `fin.Platform.Layout`. + */ +class LayoutModule extends base_1$4.Base { + constructor() { + super(...arguments); + _LayoutModule_instances.add(this); + _LayoutModule_layoutInitializationAttempted.set(this, false); + _LayoutModule_layoutManager.set(this, null); + /** + * Initialize the window's Layout. + * + * @remarks Must be called from a custom window that has a 'layout' option set upon creation of that window. + * If a containerId is not provided, this method attempts to find an element with the id `layout-container`. + * A Layout will emit events locally on the DOM element representing the layout-container. + * In order to capture the relevant events during Layout initiation, set up the listeners on the DOM element prior to calling `init`. + * @param options - Layout init options. + * + * @experimental + * + * @example + * ```js + * // If no options are included, the layout in the window options is initialized in an element with the id `layout-container` + * const layout = await fin.Platform.Layout.init(); + * ``` + *
+ * + * ```js + * const containerId = 'my-custom-container-id'; + * + * const myLayoutContainer = document.getElementById(containerId); + * + * myLayoutContainer.addEventListener('tab-created', function(event) { + * const { tabSelector } = event.detail; + * const tabElement = document.getElementById(tabSelector); + * const existingColor = tabElement.style.backgroundColor; + * tabElement.style.backgroundColor = "red"; + * setTimeout(() => { + * tabElement.style.backgroundColor = existingColor; + * }, 2000); + * }); + * + * // initialize the layout into an existing HTML element with the div `my-custom-container-id` + * // the window must have been created with a layout in its window options + * const layout = await fin.Platform.Layout.init({ containerId }); + * ``` + */ + this.init = async (options = {}) => { + this.wire.sendAction('layout-init').catch((e) => { + // don't expose + }); + if (!this.wire.environment.layoutAllowedInContext(this.fin)) { + throw new Error('Layout.init can only be called from a Window context.'); + } + if (__classPrivateFieldGet$3(this, _LayoutModule_layoutInitializationAttempted, "f")) { + throw new Error('Layout.init was already called, please use Layout.create to add additional layouts.'); + } + if (this.wire.environment.type === 'openfin') { + // preload the client + await this.fin.Platform.getCurrentSync().getClient(); + } + __classPrivateFieldSet$3(this, _LayoutModule_layoutInitializationAttempted, true, "f"); + // TODO: rename to createLayoutManager + __classPrivateFieldSet$3(this, _LayoutModule_layoutManager, await this.wire.environment.initLayoutManager(this.fin, this.wire, options), "f"); + await this.wire.environment.applyLayoutSnapshot(this.fin, __classPrivateFieldGet$3(this, _LayoutModule_layoutManager, "f"), options); + const meIdentity = { name: this.fin.me.name, uuid: this.fin.me.uuid }; + if (!options.layoutManagerOverride) { + // CORE-1081 to be removed when we actually delete the `layoutManager` prop + // in single-layout case, we return the undocumented layoutManager type + const layoutIdentity = { layoutName: layout_constants_1.DEFAULT_LAYOUT_KEY, ...meIdentity }; + return __classPrivateFieldGet$3(this, _LayoutModule_getLayoutManagerSpy, "f").call(this, layoutIdentity); + } + return this.wrapSync(meIdentity); + }; + _LayoutModule_getLayoutManagerSpy.set(this, (layoutIdentity) => { + const msg = '[Layout] You are using a deprecated property `layoutManager` - it will throw if you access it starting in v37.'; + const managerProxy = new Proxy({}, { + get(target, key) { + console.warn(`[Layout-mgr-proxy] accessing ${key.toString()}`); + throw new Error(msg); + } + }); + const layout = Object.assign(this.wrapSync(layoutIdentity), { layoutManager: managerProxy }); + const layoutProxy = new Proxy(layout, { + get(target, key) { + if (key === 'layoutManager') { + console.warn(`[Layout-proxy] accessing ${key.toString()}`); + throw new Error(msg); + } + return target[key]; + } + }); + return layoutProxy; + }); + /** + * Returns the layout manager for the current window + * @returns + */ + this.getCurrentLayoutManagerSync = () => { + return __classPrivateFieldGet$3(this, _LayoutModule_instances, "m", _LayoutModule_getSafeLayoutManager).call(this, `fin.Platform.Layout.getCurrentLayoutManagerSync()`); + }; + this.create = async (options) => { + return this.wire.environment.createLayout(__classPrivateFieldGet$3(this, _LayoutModule_instances, "m", _LayoutModule_getSafeLayoutManager).call(this, `fin.Platform.Layout.create()`), options); + }; + this.destroy = async (layoutIdentity) => { + return this.wire.environment.destroyLayout(__classPrivateFieldGet$3(this, _LayoutModule_instances, "m", _LayoutModule_getSafeLayoutManager).call(this, `fin.Platform.Layout.destroy()`), layoutIdentity); + }; + } + /** + * Asynchronously returns a Layout object that represents a Window's layout. + * + * @example + * ```js + * let windowIdentity; + * if (!fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const layout = await fin.Platform.Layout.wrap(windowIdentity); + * // Use wrapped instance to control layout, e.g.: + * const layoutConfig = await layout.getConfig(); + * ``` + */ + async wrap(identity) { + this.wire.sendAction('layout-wrap').catch((e) => { + // don't expose + }); + return new Instance_1$2.Layout(identity, this.wire); + } + /** + * Synchronously returns a Layout object that represents a Window's layout. + * + * @example + * ```js + * let windowIdentity; + * if (!fin.me.isWindow) { + * windowIdentity = fin.me.identity; + * } else if (fin.me.isView) { + * windowIdentity = (await fin.me.getCurrentWindow()).identity; + * } else { + * throw new Error('Not running in a platform View or Window'); + * } + * + * const layout = fin.Platform.Layout.wrapSync(windowIdentity); + * // Use wrapped instance to control layout, e.g.: + * const layoutConfig = await layout.getConfig(); + * ``` + */ + wrapSync(identity) { + this.wire.sendAction('layout-wrap-sync').catch((e) => { + // don't expose + }); + return new Instance_1$2.Layout(identity, this.wire); + } + /** + * Asynchronously returns a Layout object that represents a Window's layout. + * + * @example + * ```js + * const layout = await fin.Platform.Layout.getCurrent(); + * // Use wrapped instance to control layout, e.g.: + * const layoutConfig = await layout.getConfig(); + * ``` + */ + async getCurrent() { + this.wire.sendAction('layout-get-current').catch((e) => { + // don't expose + }); + if (!this.fin.me.isWindow) { + throw new Error('You are not in a Window context. Only Windows can have a Layout.'); + } + const { uuid, name } = this.fin.me; + return this.wrap({ uuid, name }); + } + /** + * Synchronously returns a Layout object that represents a Window's layout. + * + * @remarks Cannot be called from a view. + * + * + * @example + * ```js + * const layout = fin.Platform.Layout.getCurrentSync(); + * // Use wrapped instance to control layout, e.g.: + * const layoutConfig = await layout.getConfig(); + * ``` + */ + getCurrentSync() { + this.wire.sendAction('layout-get-current-sync').catch((e) => { + // don't expose + }); + if (!this.fin.me.isWindow) { + throw new Error('You are not in a Window context. Only Windows can have a Layout.'); + } + const { uuid, name } = this.fin.me; + return this.wrapSync({ uuid, name }); + } +} +Factory$2.LayoutModule = LayoutModule; +_LayoutModule_layoutInitializationAttempted = new WeakMap(), _LayoutModule_layoutManager = new WeakMap(), _LayoutModule_getLayoutManagerSpy = new WeakMap(), _LayoutModule_instances = new WeakSet(), _LayoutModule_getSafeLayoutManager = function _LayoutModule_getSafeLayoutManager(method) { + if (!__classPrivateFieldGet$3(this, _LayoutModule_layoutManager, "f")) { + throw new Error(`You must call init before using the API ${method}`); + } + return __classPrivateFieldGet$3(this, _LayoutModule_layoutManager, "f"); +}; + +(function (exports) { + /** + * Entry point for the OpenFin `Layout` subset of the `Platform` API (`fin.Platform.Layout`). + * + * * {@link LayoutModule} contains static members of the `Layout` API, accessible through `fin.Platform.Layout`. + * * {@link Layout} describes an instance of an OpenFin Layout, e.g. as returned by `fin.Platform.Layout.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + * + */ + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(Factory$2, exports); + __exportStar(Instance$1, exports); +} (layout)); + +Object.defineProperty(Factory$3, "__esModule", { value: true }); +Factory$3.PlatformModule = void 0; +const base_1$3 = base; +const Instance_1$1 = Instance$2; +const index_1$1 = layout; +/** + * Static namespace for OpenFin API methods that interact with the {@link Platform} class, available under `fin.Platform`. + */ +class PlatformModule extends base_1$3.Base { + /** + * @internal + */ + constructor(wire, channel) { + super(wire); + this._channel = channel; + /** + * + * @desc Layouts give app providers the ability to embed multiple views in a single window. The Layout namespace + * enables the initialization and manipulation of a window's Layout. A Layout will + * emit events locally on the DOM element representing the layout-container. + */ + this.Layout = new index_1$1.LayoutModule(this.wire); + } + /** + * Initializes a Platform. Must be called from the Provider when using a custom provider. + * @param options - platform options including a callback function that can be used to extend or replace + * default Provider behavior. + * + * @remarks Must be called from the Provider when using a custom provider. + * + * @example + * + * ```js + * // From Provider context + * await fin.Platform.init(); + * // Platform API is now hooked up and windows contained in the manifest snapshot are open. + * ``` + * + * `Platform.init` accepts an options object that can contain a callback function which can be used to extend or + * replace default Provider behavior. As an argument, this function will receive the `Provider` class, which is + * used to handle Platform actions. The function must return an object with methods to handle Platform API actions. + * The recommended approach is to extend the `Provider` class, overriding the methods you wish to alter, and return an + * instance of your subclass: + * + * ```js + * const overrideCallback = async (PlatformProvider) => { + * // Actions can be performed before initialization. + * // e.g. we might authenticate a user, set up a Channel, etc before initializing the Platform. + * const { manifestUrl } = await fin.Application.getCurrentSync().getInfo(); + * + * // Extend or replace default PlatformProvider behavior by extending the PlatformProvider class. + * class MyOverride extends PlatformProvider { + * // Default behavior can be changed by implementing methods with the same names as those used by the default PlatformProvider. + * async getSnapshot() { + * // Since we are extending the class, we can call `super` methods to access default behavior. + * const snapshot = await super.getSnapshot(); + * // But we can modify return values. + * return { ...snapshot, answer: 42, manifestUrl }; + * } + * async replaceLayout({ opts, target }) { + * // To disable an API method, overwrite with a noop function. + * return; + * } + * } + * // Return instance with methods to be consumed by Platform. + * // The returned object must implement all methods of the PlatformProvider class. + * // By extending the class, we can simply inherit methods we do not wish to alter. + * return new MyOverride(); + * }; + * + * fin.Platform.init({overrideCallback}); + * ``` + * @experimental + */ + async init(options) { + if (!fin.__internal_.isPlatform || fin.me.name !== fin.me.uuid) { + throw new Error('fin.Platform.init should only be called from a custom platform provider running in the main window of the application.'); + } + return this.wire.environment.initPlatform(this.fin, options); + } + /** + * Asynchronously returns a Platform object that represents an existing platform. + * + * @example + * ```js + * const { identity } = fin.me; + * const platform = await fin.Platform.wrap(identity); + * // Use wrapped instance to control layout, e.g.: + * const snapshot = await platform.getSnapshot(); + * ``` + */ + async wrap(identity) { + this.wire.sendAction('platform-wrap').catch((e) => { + // don't expose + }); + return new Instance_1$1.Platform({ uuid: identity.uuid }, this._channel); + } + /** + * Synchronously returns a Platform object that represents an existing platform. + * + * @example + * ```js + * const { identity } = fin.me; + * const platform = fin.Platform.wrapSync(identity); + * // Use wrapped instance to control layout, e.g.: + * const snapshot = await platform.getSnapshot(); + * ``` + */ + wrapSync(identity) { + this.wire.sendAction('platform-wrap-sync').catch((e) => { + // don't expose + }); + return new Instance_1$1.Platform({ uuid: identity.uuid }, this._channel); + } + /** + * Asynchronously returns a Platform object that represents the current platform. + * + * @example + * ```js + * const platform = await fin.Platform.getCurrent(); + * // Use wrapped instance to control layout, e.g.: + * const snapshot = await platform.getSnapshot(); + * ``` + */ + async getCurrent() { + this.wire.sendAction('platform-get-current').catch((e) => { + // don't expose + }); + return this.wrap({ uuid: this.wire.me.uuid }); + } + /** + * Synchronously returns a Platform object that represents the current platform. + * + * @example + * ```js + * const platform = fin.Platform.getCurrentSync(); + * // Use wrapped instance to control layout, e.g.: + * const snapshot = await platform.getSnapshot(); + * ``` + */ + getCurrentSync() { + this.wire.sendAction('platform-get-current-sync').catch((e) => { + // don't expose + }); + return this.wrapSync({ uuid: this.wire.me.uuid }); + } + /** + * Creates and starts a Platform and returns a wrapped and running Platform instance. The wrapped Platform methods can + * be used to launch content into the platform. Promise will reject if the platform is already running. + * + * @example + * ```js + * try { + * const platform = await fin.Platform.start({ + * uuid: 'platform-1', + * autoShow: false, + * defaultWindowOptions: { + * stylesheetUrl: 'css-sheet-url', + * cornerRounding: { + * height: 10, + * width: 10 + * } + * } + * }); + * console.log('Platform is running', platform); + * } catch(e) { + * console.error(e); + * } + * ``` + */ + start(platformOptions) { + this.wire.sendAction('platform-start').catch((e) => { + // don't expose + }); + // eslint-disable-next-line no-async-promise-executor + return new Promise(async (resolve, reject) => { + try { + const { uuid } = platformOptions; + // @ts-expect-error using private variable. + const app = await this.fin.Application._create({ ...platformOptions, isPlatformController: true }); + // TODO: fix typing (internal) + // @ts-expect-error + app.once('platform-api-ready', () => resolve(this.wrapSync({ uuid }))); + // @ts-expect-error using private variable. + app._run({ uuid }); + } + catch (e) { + reject(e); + } + }); + } + /** + * Retrieves platforms's manifest and returns a wrapped and running Platform. If there is a snapshot in the manifest, + * it will be launched into the platform. + * @param manifestUrl - The URL of platform's manifest. + * @param opts - Parameters that the RVM will use. + * + * @example + * ```js + * try { + * const platform = await fin.Platform.startFromManifest('https://openfin.github.io/golden-prototype/public.json'); + * console.log('Platform is running, wrapped platform: ', platform); + * } catch(e) { + * console.error(e); + * } + * // For a local manifest file: + * try { + * const platform = await fin.Platform.startFromManifest('file:///C:/somefolder/app.json'); + * console.log('Platform is running, wrapped platform: ', platform); + * } catch(e) { + * console.error(e); + * } + * ``` + */ + startFromManifest(manifestUrl, opts) { + this.wire.sendAction('platform-start-from-manifest').catch((e) => { + // don't expose + }); + // eslint-disable-next-line no-async-promise-executor + return new Promise(async (resolve, reject) => { + try { + // @ts-expect-error using private variable. + const app = await this.fin.Application._createFromManifest(manifestUrl); + // TODO: fix typing (internal) + // @ts-expect-error + app.once('platform-api-ready', () => resolve(this.wrapSync({ uuid: app.identity.uuid }))); + // @ts-expect-error using private method without warning. + app._run(opts); + } + catch (e) { + reject(e); + } + }); + } +} +Factory$3.PlatformModule = PlatformModule; + +(function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + /** + * Entry points for the OpenFin `Platform` API (`fin.Platform`) + * + * * {@link PlatformModule} contains static members of the `Platform` API, accessible through `fin.Platform`. + * * {@link Platform} describes an instance of an OpenFin Platform, e.g. as returned by `fin.Platform.getCurrent`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + */ + __exportStar(Factory$3, exports); + __exportStar(Instance$2, exports); +} (platform)); + +var me = {}; + +(function (exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + exports.getMe = exports.getBaseMe = exports.environmentUnsupportedMessage = void 0; + const view_1 = requireView(); + const frame_1 = frame; + const window_1 = requireWindow(); + const external_application_1 = externalApplication; + exports.environmentUnsupportedMessage = 'You are not running in OpenFin.'; + function getBaseMe(entityType, uuid, name) { + const entityTypeHelpers = { + isView: entityType === 'view', + isWindow: entityType === 'window', + isFrame: entityType === 'iframe', + isExternal: entityType === 'external connection' + }; + return { ...entityTypeHelpers, uuid, name, entityType }; + } + exports.getBaseMe = getBaseMe; + // We need to do a lot of casting as unknown here because the compiler get's confused about matching types. What matters is that it works on the outside + function getMe(wire) { + const { uuid, name, entityType } = wire.me; + const unsupportedInterop = { + setContext() { + throw new Error(exports.environmentUnsupportedMessage); + }, + addContextHandler() { + throw new Error(exports.environmentUnsupportedMessage); + }, + getContextGroups() { + throw new Error(exports.environmentUnsupportedMessage); + }, + joinContextGroup() { + throw new Error(exports.environmentUnsupportedMessage); + }, + removeFromContextGroup() { + throw new Error(exports.environmentUnsupportedMessage); + }, + getAllClientsInContextGroup() { + throw new Error(exports.environmentUnsupportedMessage); + }, + getInfoForContextGroup() { + throw new Error(exports.environmentUnsupportedMessage); + } + }; + const fallbackErrorMessage = 'Interop API has not been instantiated. Either connection has failed or you have not declared interop in your config.'; + const fallbackInterop = { + setContext() { + throw new Error(fallbackErrorMessage); + }, + addContextHandler() { + throw new Error(fallbackErrorMessage); + }, + getContextGroups() { + throw new Error(fallbackErrorMessage); + }, + joinContextGroup() { + throw new Error(fallbackErrorMessage); + }, + removeFromContextGroup() { + throw new Error(fallbackErrorMessage); + }, + getAllClientsInContextGroup() { + throw new Error(fallbackErrorMessage); + }, + getInfoForContextGroup() { + throw new Error(fallbackErrorMessage); + } + }; + const unsupportedEventBase = { + eventNames: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + emit: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + listeners: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + listenerCount: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + on: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + addListener: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + once: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + prependListener: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + prependOnceListener: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + removeListener: () => { + throw new Error(exports.environmentUnsupportedMessage); + }, + removeAllListeners: () => { + throw new Error(exports.environmentUnsupportedMessage); + } + }; + switch (entityType) { + case 'view': + return Object.assign(new view_1.View(wire, { uuid, name }), getBaseMe(entityType, uuid, name), { + interop: fallbackInterop, + isOpenFin: true + }); + case 'window': + return Object.assign(new window_1._Window(wire, { uuid, name }), getBaseMe(entityType, uuid, name), { + interop: fallbackInterop, + isOpenFin: true + }); + case 'iframe': + return Object.assign(new frame_1._Frame(wire, { uuid, name }), getBaseMe(entityType, uuid, name), { + interop: fallbackInterop, + isOpenFin: true + }); + case 'external connection': + return Object.assign(new external_application_1.ExternalApplication(wire, { uuid }), getBaseMe(entityType, uuid, name), { + interop: fallbackInterop, + isOpenFin: false + }); + default: + return { + ...getBaseMe(entityType, uuid, name), + ...unsupportedEventBase, + interop: unsupportedInterop, + isOpenFin: false + }; + } + } + exports.getMe = getMe; +} (me)); + +var interop = {}; + +var Factory$1 = {}; + +var inaccessibleObject = {}; + +Object.defineProperty(inaccessibleObject, "__esModule", { value: true }); +inaccessibleObject.createWarningObject = inaccessibleObject.createUnusableObject = void 0; +function createUnusableObject(message) { + const handle = () => { + throw new Error(message); + }; + return new Proxy({}, { + apply: handle, + construct: handle, + defineProperty: handle, + deleteProperty: handle, + get: handle, + getOwnPropertyDescriptor: handle, + getPrototypeOf: handle, + has: handle, + isExtensible: handle, + ownKeys: handle, + preventExtensions: handle, + set: handle, + setPrototypeOf: handle + }); +} +inaccessibleObject.createUnusableObject = createUnusableObject; +function createWarningObject(message, obj) { + return new Proxy(obj, { + get: (...args) => { + // eslint-disable-next-line no-console + console.warn(message); + return Reflect.get(...args); + }, + set: (...args) => { + // eslint-disable-next-line no-console + console.warn(message); + return Reflect.set(...args); + }, + getOwnPropertyDescriptor: (...args) => { + // eslint-disable-next-line no-console + console.warn(message); + return Reflect.getOwnPropertyDescriptor(...args); + }, + ownKeys: (...args) => { + // eslint-disable-next-line no-console + console.warn(message); + return Reflect.ownKeys(...args); + } + }); +} +inaccessibleObject.createWarningObject = createWarningObject; + +var InteropBroker = {}; + +var SessionContextGroupBroker = {}; + +var hasRequiredSessionContextGroupBroker; + +function requireSessionContextGroupBroker () { + if (hasRequiredSessionContextGroupBroker) return SessionContextGroupBroker; + hasRequiredSessionContextGroupBroker = 1; + Object.defineProperty(SessionContextGroupBroker, "__esModule", { value: true }); + const _1 = requireInterop(); + let SessionContextGroupBroker$1 = class SessionContextGroupBroker { + constructor(provider, id) { + this.provider = provider; + this.id = id; + this.lastContext = undefined; + this.contextGroupMap = new Map(); + this.clients = new Map(); + this.registerListeners(); + } + registerListeners() { + this.provider.register(`sessionContextGroup:getContext-${this.id}`, this.getCurrentContext.bind(this)); + this.provider.register(`sessionContextGroup:setContext-${this.id}`, this.setContext.bind(this)); + this.provider.register(`sessionContextGroup:handlerAdded-${this.id}`, this.handlerAdded.bind(this)); + this.provider.register(`sessionContextGroup:handlerRemoved-${this.id}`, this.handlerRemoved.bind(this)); + } + getCurrentContext(payload) { + return payload.type ? this.contextGroupMap.get(payload.type) : this.lastContext; + } + setContext(payload, clientIdentity) { + const { context } = payload; + const contextIntegrityCheckResult = _1.InteropBroker.checkContextIntegrity(context); + if (contextIntegrityCheckResult.isValid === false) { + throw new Error(`Failed to set Context - bad Context. Reason: ${contextIntegrityCheckResult.reason}. Context: ${JSON.stringify(context)}`); + } + const clientState = this.getClientState(clientIdentity); + if (!clientState) { + // This shouldn't get hit. + throw new Error(`Client with Identity: ${clientIdentity.uuid} ${clientIdentity.name} not in Session Client State Map`); + } + // set the context + this.contextGroupMap.set(context.type, context); + this.lastContext = context; + const clientSubscriptionStates = Array.from(this.clients.values()); + clientSubscriptionStates.forEach((client) => { + // eslint-disable-next-line no-unused-expressions + client.contextHandlers.get(context.type)?.forEach((handlerId) => { + this.provider.dispatch(client.clientIdentity, handlerId, context); + }); + if (client.globalHandler) { + this.provider.dispatch(client.clientIdentity, client.globalHandler, context); + } + }); + } + getClientState(id) { + return this.clients.get(id.endpointId); + } + async handlerAdded(payload, clientIdentity) { + const { handlerId, contextType } = payload; + const clientSubscriptionState = this.getClientState(clientIdentity); + if (!clientSubscriptionState) { + throw new Error(`Client with Identity: ${clientIdentity.uuid} ${clientIdentity.name} not in Client State Map`); + } + if (contextType) { + const currentHandlerList = clientSubscriptionState.contextHandlers.get(contextType) || []; + clientSubscriptionState.contextHandlers.set(contextType, [...currentHandlerList, handlerId]); + const currentContext = this.contextGroupMap.get(contextType); + if (currentContext) { + await this.provider.dispatch(clientIdentity, handlerId, currentContext); + } + } + else { + clientSubscriptionState.globalHandler = handlerId; + const globalDispatchPromises = [...this.contextGroupMap.keys()].map(async (currentContextType) => { + const currentContext = this.contextGroupMap.get(currentContextType); + if (currentContext) { + await this.provider.dispatch(clientIdentity, handlerId, currentContext); + } + }); + await Promise.all(globalDispatchPromises); + } + } + handlerRemoved(payload, clientIdentity) { + const { handlerId } = payload; + const client = this.clients.get(clientIdentity.endpointId); + if (client) { + Array.from(client.contextHandlers).forEach(([, handlers]) => { + const index = handlers.indexOf(handlerId); + if (index > -1) { + handlers.splice(index, 1); + } + }); + if (client.globalHandler === handlerId) { + client.globalHandler = undefined; + } + } + else { + console.warn(`Trying to remove a handler from a client that isn't mapped. handlerId: ${handlerId}. clientIdentity: ${clientIdentity}`); + } + } + registerNewClient(clientIdentity) { + if (!this.clients.has(clientIdentity.endpointId)) { + const clientSubscriptionState = { + contextHandlers: new Map(), + clientIdentity, + globalHandler: undefined + }; + this.clients.set(clientIdentity.endpointId, clientSubscriptionState); + } + } + onDisconnection(clientIdentity) { + this.clients.delete(clientIdentity.endpointId); + } + }; + SessionContextGroupBroker.default = SessionContextGroupBroker$1; + return SessionContextGroupBroker; +} + +var utils$3 = {}; + +(function (exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + exports.wrapIntentHandler = exports.BROKER_ERRORS = exports.generateOverrideWarning = exports.generateOverrideError = exports.wrapContextHandler = exports.wrapInTryCatch = exports.generateId = void 0; + const generateId = () => `${Math.random()}${Date.now()}`; + exports.generateId = generateId; + const wrapInTryCatch = (f, prefix) => (...args) => { + try { + return f(...args); + } + catch (e) { + throw new Error((prefix || '') + e); + } + }; + exports.wrapInTryCatch = wrapInTryCatch; + const wrapContextHandler = (handler, handlerId) => { + return async (context) => { + try { + await handler(context); + } + catch (error) { + console.error(`Error thrown by handler ${handlerId} for context type ${context.type}: ${error}`); + throw error; + } + }; + }; + exports.wrapContextHandler = wrapContextHandler; + const generateOverrideError = (clientApi, brokerApi) => { + return `You have tried to to use ${clientApi} but ${brokerApi} has not been overridden in the Interop Broker. Please override this function. Refer to our documentation for more info.`; + }; + exports.generateOverrideError = generateOverrideError; + const generateOverrideWarning = (fdc3ClientApi, brokerApi, identity, interopClientApi) => { + const { uuid, name } = identity; + const message = interopClientApi + ? `Entity with identity: ${uuid}/${name} has called ${interopClientApi} or ${fdc3ClientApi} but ${brokerApi} has not been overridden.` + : `Entity with identity: ${uuid}/${name} has called ${fdc3ClientApi} but ${brokerApi} has not been overridden.`; + return message; + }; + exports.generateOverrideWarning = generateOverrideWarning; + exports.BROKER_ERRORS = { + fireIntent: (0, exports.generateOverrideError)('fireIntent', 'handleFiredIntent'), + fireIntentForContext: (0, exports.generateOverrideError)('fireIntentForContext', 'handleFiredIntentForContext'), + getInfoForIntent: (0, exports.generateOverrideError)('getInfoForIntent', 'handleInfoForIntent'), + getInfoForIntentsByContext: (0, exports.generateOverrideError)('getInfoForIntentsByContext', 'handleInfoForIntentsByContext'), + joinSessionContextGroupWithJoinContextGroup: 'The Context Group you have tried to join is a Session Context Group. Custom Context Groups can only be defined by the Interop Broker through code or manifest configuration. Please use joinSessionContextGroup.', + fdc3Open: (0, exports.generateOverrideError)('fdc3.open', 'fdc3HandleOpen'), + fdc3FindInstances: (0, exports.generateOverrideError)('fdc3.findInstances', 'fdc3HandleFindInstances'), + fdc3GetAppMetadata: (0, exports.generateOverrideError)('fdc3.getAppMetadata', 'fdc3HandleGetAppMetadata'), + fdc3GetInfo: (0, exports.generateOverrideError)('fdc3.getInfo', 'fdc3HandleGetInfo') + }; + const wrapIntentHandler = (handler, handlerId) => { + return async (intent) => { + try { + return handler(intent); + } + catch (error) { + console.error(`Error thrown by handler ${handlerId}: ${error}`); + throw error; + } + }; + }; + exports.wrapIntentHandler = wrapIntentHandler; +} (utils$3)); + +var PrivateChannelProvider = {}; + +var hasRequiredPrivateChannelProvider; + +function requirePrivateChannelProvider () { + if (hasRequiredPrivateChannelProvider) return PrivateChannelProvider; + hasRequiredPrivateChannelProvider = 1; + Object.defineProperty(PrivateChannelProvider, "__esModule", { value: true }); + PrivateChannelProvider.PrivateChannelProvider = void 0; + const InteropBroker_1 = requireInteropBroker(); + let PrivateChannelProvider$1 = class PrivateChannelProvider { + constructor(provider, id) { + this.provider = provider; + this.id = id; + this.clients = new Map(); + this.registerListeners(); + this.contextByContextType = new Map(); + this.lastContext = undefined; + this.provider.onConnection((clientIdentity) => this.registerNewClient(clientIdentity)); + this.provider.onDisconnection(async (clientIdentity) => { + const { endpointId } = clientIdentity; + if (this.clients.has(endpointId)) { + await this.handleClientDisconnecting(clientIdentity); + } + if ((await this.provider.getAllClientInfo()).length === 0) { + this.provider.destroy(); + } + }); + } + getClientState(id) { + return this.clients.get(id.endpointId); + } + registerListeners() { + this.provider.register('broadcast', this.broadcast.bind(this)); + this.provider.register('getCurrentContext', this.getCurrentContext.bind(this)); + this.provider.register('contextHandlerAdded', this.contextHandlerAdded.bind(this)); + this.provider.register('contextHandlerRemoved', this.contextHandlerRemoved.bind(this)); + this.provider.register('nonStandardHandlerRemoved', this.nonStandardHandlerRemoved.bind(this)); + this.provider.register('onAddContextHandlerAdded', this.onAddContextHandlerAdded.bind(this)); + this.provider.register('onDisconnectHandlerAdded', this.onDisconnectHandlerAdded.bind(this)); + this.provider.register('onUnsubscribeHandlerAdded', this.onUnsubscribeHandlerAdded.bind(this)); + this.provider.register('clientDisconnecting', (payload, clientIdentity) => { + this.handleClientDisconnecting(clientIdentity); + }); + } + broadcast(payload, broadcasterClientIdentity) { + const { context } = payload; + const broadcasterClientState = this.getClientState(broadcasterClientIdentity); + if (!broadcasterClientState) { + throw new Error(`Client with Identity: ${broadcasterClientIdentity.uuid} ${broadcasterClientIdentity.name}, tried to call broadcast, is not connected to this Private Channel`); + } + const contextIntegrityCheckResult = InteropBroker_1.InteropBroker.checkContextIntegrity(context); + if (contextIntegrityCheckResult.isValid === false) { + throw new Error(`Failed to broadcast - bad Context. Reason: ${contextIntegrityCheckResult.reason}. Context: ${JSON.stringify(context)}`); + } + this.contextByContextType.set(context.type, context); + this.lastContext = context; + Array.from(this.clients.values()).forEach((currClientState) => { + const handlerIdsForContextType = currClientState.handlerIdsByContextTypes.get(context.type); + if (handlerIdsForContextType) { + handlerIdsForContextType.forEach((handlerId) => { + this.provider.dispatch(currClientState.clientIdentity, handlerId, context); + }); + } + if (currClientState.globalHandler) { + this.provider.dispatch(currClientState.clientIdentity, currClientState.globalHandler, context); + } + }); + } + getCurrentContext(payload, senderClientIdentity) { + const { contextType } = payload; + const clientState = this.getClientState(senderClientIdentity); + if (!clientState) { + throw new Error(`Client with Identity: ${senderClientIdentity.uuid} ${senderClientIdentity.name}, tried to call getCurrentContext, is not connected to this Private Channel`); + } + if (contextType !== undefined) { + const currentContext = this.contextByContextType.get(contextType); + if (currentContext) + return currentContext; + return null; + } + return this.lastContext ? this.lastContext : null; + } + contextHandlerAdded(payload, senderClientIdentity) { + const { handlerId, contextType } = payload; + const senderClientState = this.getClientState(senderClientIdentity); + if (!senderClientState) { + throw new Error(`Client with Identity: ${senderClientIdentity.uuid} ${senderClientIdentity.name}, tried to call addContextListener, is not connected to this Private Channel`); + } + if (contextType) { + const currentHandlersList = senderClientState.handlerIdsByContextTypes.get(contextType) || []; + senderClientState.handlerIdsByContextTypes.set(contextType, [...currentHandlersList, handlerId]); + } + else { + senderClientState.globalHandler = handlerId; + } + Array.from(this.clients.values()).forEach((currClientState) => { + if (currClientState.clientIdentity.endpointId !== senderClientIdentity.endpointId && + currClientState.onAddContextListenerHandlerId) { + this.provider.dispatch(currClientState.clientIdentity, currClientState.onAddContextListenerHandlerId, contextType); + } + }); + } + async contextHandlerRemoved(payload, removingClientIdentity) { + // MC: Made this removal async to ensure that onUnsubscribe handlers are hit before anything else happens. + const { handlerId } = payload; + const removingClientState = this.getClientState(removingClientIdentity); + if (removingClientState) { + let contextType; + if (removingClientState.globalHandler === handlerId) { + removingClientState.globalHandler = undefined; + } + else { + for (const [currContextType, handlersIds] of removingClientState.handlerIdsByContextTypes) { + const index = handlersIds.indexOf(handlerId); + if (index > -1) { + handlersIds.splice(index, 1); + contextType = currContextType; + } + } + } + // getting only valid client connections here, it is possible we haven't removed a disconnected client from the map yet + // so we need to ensure we don't dispatch to any disconnected client + // TODO: Take a look at our client disconnection logic and see if we can handle client disconnection cleanly + const clientsToDispatchTo = await this.getConnectedClients(); + const dispatchPromises = clientsToDispatchTo.map(async (otherClientState) => { + const { clientIdentity, clientIdentity: { endpointId }, onUnsubscribeHandlerId } = otherClientState; + if (endpointId !== removingClientIdentity.endpointId && onUnsubscribeHandlerId) { + await this.provider.dispatch(clientIdentity, onUnsubscribeHandlerId, contextType); + } + }); + try { + await Promise.all(dispatchPromises); + } + catch (error) { + console.error(`Problem when attempting to dispatch to onUnsubscribeHandlers. Error: ${error} Removing Client: ${handlerId}. uuid: ${removingClientIdentity.uuid}. name: ${removingClientIdentity.name}. endpointId: ${removingClientIdentity.endpointId}`); + throw new Error(error); + } + } + else { + console.warn(`Trying to remove a handler from a client that isn't mapped. handlerId: ${handlerId}. uuid: ${removingClientIdentity.uuid}. name: ${removingClientIdentity.name}. endpointId: ${removingClientIdentity.endpointId}.`); + } + } + nonStandardHandlerRemoved(payload, id) { + const { handlerId } = payload; + const clientState = this.getClientState(id); + if (clientState) { + if (clientState.onDisconnectHandlerId === handlerId) { + clientState.onDisconnectHandlerId = undefined; + } + else if (clientState.onAddContextListenerHandlerId === handlerId) { + clientState.onAddContextListenerHandlerId = undefined; + } + else if (clientState.onUnsubscribeHandlerId === handlerId) { + clientState.onUnsubscribeHandlerId = undefined; + } + } + else { + console.warn(`Trying to remove a handler from a client that isn't mapped. handlerId: ${handlerId}. clientIdentity: ${id}`); + } + } + onAddContextHandlerAdded(payload, senderClientIdentity) { + const clientState = this.getClientState(senderClientIdentity); + const { handlerId } = payload; + if (!clientState) { + throw new Error(`Client with Identity: ${senderClientIdentity.uuid} ${senderClientIdentity.name}, tried to call onAddContextListener, is not connected to this Private Channel`); + } + clientState.onAddContextListenerHandlerId = handlerId; + // FDC3 Spec says that the added listener should fire for all previously-registered addContextListeners from the other client + Array.from(this.clients.values()).forEach((otherClientState) => { + if (otherClientState.clientIdentity.endpointId !== senderClientIdentity.endpointId) { + Array.from(otherClientState.handlerIdsByContextTypes.keys()).forEach((subscribedContextType) => { + this.provider.dispatch(senderClientIdentity, handlerId, subscribedContextType); + }); + } + }); + } + onDisconnectHandlerAdded(payload, id) { + const clientState = this.getClientState(id); + const { handlerId } = payload; + if (!clientState) { + throw new Error(`Client with Identity: ${id.uuid} ${id.name}, tried to call onDisconnect, is not connected to this Private Channel`); + } + clientState.onDisconnectHandlerId = handlerId; + } + onUnsubscribeHandlerAdded(payload, id) { + const clientState = this.getClientState(id); + const { handlerId } = payload; + if (!clientState) { + throw new Error(`Client with Identity: ${id.uuid} ${id.name}, tried to call onUnsubscribe, is not connected to this Private Channel`); + } + clientState.onUnsubscribeHandlerId = handlerId; + } + removeClient(disconnectingClientIdentity) { + const disconnectingClientState = this.getClientState(disconnectingClientIdentity); + if (!disconnectingClientState) { + throw new Error(`Client with Identity: ${disconnectingClientIdentity.uuid} ${disconnectingClientIdentity.name}, tried to call disconnect, is not connected to this Private Channel`); + } + disconnectingClientState.handlerIdsByContextTypes.clear(); + this.clients.delete(disconnectingClientIdentity.endpointId); + } + async fireOnDisconnectForOtherClients(disconnectingClientIdentity) { + // TODO: call onDisconnect Handler of the other client only. + // CURRENTLY, just calling the onDisconnect handler for all the other clients. Once we limit it to just one other client, we can eliminate all the iteration code. + const { endpointId } = disconnectingClientIdentity; + // getting only valid client connections here, it is possible we haven't removed a disconnected client from the map yet + // so we need to ensure we don't dispatch to any disconnected client + // TODO: Take a look at our client disconnection logic and see if we can handle client disconnection cleanly + const clientsToDispatchTo = await this.getConnectedClients(); + const dispatchPromises = clientsToDispatchTo.map(async (otherClientState) => { + const { clientIdentity: { endpointId: otherClientEndpointId }, onDisconnectHandlerId } = otherClientState; + if (otherClientEndpointId !== endpointId && onDisconnectHandlerId) { + await this.provider.dispatch(otherClientState.clientIdentity, onDisconnectHandlerId); + } + }); + try { + await Promise.all(dispatchPromises); + } + catch (error) { + console.error(`Problem when attempting to dispatch to onDisconnectHandlers. Error: ${error} Disconnecting Client: uuid: ${disconnectingClientIdentity.uuid}. name: ${disconnectingClientIdentity.name}. endpointId: ${disconnectingClientIdentity.endpointId}`); + throw new Error(error); + } + } + async unsubscribeAll(clientIdentity) { + const { endpointId } = clientIdentity; + const state = this.clients.get(endpointId); + if (state) { + const contextTypeHandlerIds = Array.from(state.handlerIdsByContextTypes.values()).flat(); + const globalHandlerId = state.globalHandler; + if (contextTypeHandlerIds.length > 0) { + const unsubPromises = contextTypeHandlerIds.map(async (handlerId) => { + return this.contextHandlerRemoved({ handlerId }, clientIdentity); + }); + try { + await Promise.all(unsubPromises); + } + catch (error) { + console.error(error.message); + } + } + if (globalHandlerId) { + try { + await this.contextHandlerRemoved({ handlerId: globalHandlerId }, clientIdentity); + } + catch (error) { + console.error(error.message); + } + } + } + } + async handleClientDisconnecting(disconnectingClientIdentity) { + await this.unsubscribeAll(disconnectingClientIdentity); + this.removeClient(disconnectingClientIdentity); + await this.fireOnDisconnectForOtherClients(disconnectingClientIdentity); + } + registerNewClient(clientIdentity) { + if (!this.clients.has(clientIdentity.endpointId)) { + const clientSubscriptionState = { + clientIdentity, + handlerIdsByContextTypes: new Map(), + globalHandler: undefined, + onAddContextListenerHandlerId: undefined, + onUnsubscribeHandlerId: undefined, + onDisconnectHandlerId: undefined + }; + this.clients.set(clientIdentity.endpointId, clientSubscriptionState); + } + } + async getConnectedClients() { + const allClientInfo = await this.provider.getAllClientInfo(); + return Array.from(this.clients.values()).filter((clientState) => { + const { uuid, name } = clientState.clientIdentity; + return allClientInfo.some((clientInfo) => { + return name === clientInfo.name && uuid === clientInfo.uuid; + }); + }); + } + static init(channelProvider, id) { + return new PrivateChannelProvider(channelProvider, id); + } + }; + PrivateChannelProvider.PrivateChannelProvider = PrivateChannelProvider$1; + return PrivateChannelProvider; +} + +var hasRequiredInteropBroker; + +function requireInteropBroker () { + if (hasRequiredInteropBroker) return InteropBroker; + hasRequiredInteropBroker = 1; + var __classPrivateFieldSet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; + }; + var __classPrivateFieldGet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + var _InteropBroker_fdc3Info, _InteropBroker_contextGroups, _InteropBroker_providerPromise; + Object.defineProperty(InteropBroker, "__esModule", { value: true }); + InteropBroker.InteropBroker = void 0; + const base_1 = base; + const SessionContextGroupBroker_1 = __importDefault(requireSessionContextGroupBroker()); + const utils_1 = utils$3; + const isEqual_1 = __importDefault(require$$3); + const PrivateChannelProvider_1 = requirePrivateChannelProvider(); + const lazy_1 = lazy; + const defaultContextGroups = [ + { + id: 'green', + displayMetadata: { + color: '#00CC88', + name: 'green' + } + }, + { + id: 'purple', + displayMetadata: { + color: '#8C61FF', + name: 'purple' + } + }, + { + id: 'orange', + displayMetadata: { + color: '#FF8C4C', + name: 'orange' + } + }, + { + id: 'red', + displayMetadata: { + color: '#FF5E60', + name: 'red' + } + }, + { + id: 'pink', + displayMetadata: { + color: '#FF8FB8', + name: 'pink' + } + }, + { + id: 'yellow', + displayMetadata: { + color: '#E9FF8F', + name: 'yellow' + } + } + ]; + /** + * {@link https://developers.openfin.co/of-docs/docs/enable-color-linking} + * + * The Interop Broker is responsible for keeping track of the Interop state of the Platform, and for directing messages to the proper locations. + * + * @remarks This class contains some types related to FDC3 that are specific to OpenFin. {@link https://developers.openfin.co/of-docs/docs/fdc3-support-in-openfin OpenFin's FDC3 support} is forward- and backward-compatible. + * Standard types for {@link https://fdc3.finos.org/ FDC3} do not appear in OpenFin’s API documentation, to avoid duplication. + * + * --- + * + * There are 2 ways to inject custom functionality into the Interop Broker: + * + * **1. Configuration** + * + * At the moment, you can configure the default context groups for the Interop Broker without having to override it. To do so, include the `interopBrokerConfiguration` `contextGroups` option in your `platform` options in your manifest. This is the preferred method. + * ```js + * { + * "runtime": { + * "arguments": "--v=1 --inspect", + * "version": "alpha-v19" + * }, + * "platform": { + * "uuid": "platform_customization_local", + * "applicationIcon": "https://openfin.github.io/golden-prototype/favicon.ico", + * "autoShow": false, + * "providerUrl": "http://localhost:5555/provider.html", + * "interopBrokerConfiguration": { + * "contextGroups": [ + * { + * "id": "green", + * "displayMetadata": { + * "color": "#00CC88", + * "name": "green" + * } + * }, + * { + * "id": "purple", + * "displayMetadata": { + * "color": "#8C61FF", + * "name": "purple" + * } + * }, + * ] + * } + * } + * } + * ``` + * + * By default the Interop Broker logs all actions to the console. You can disable this by using the logging option in `interopBrokerConfiguration`: + * ```js + * { + * "runtime": { + * "arguments": "--v=1 --inspect", + * "version": "alpha-v19" + * }, + * "platform": { + * "uuid": "platform_customization_local", + * "applicationIcon": "https://openfin.github.io/golden-prototype/favicon.ico", + * "autoShow": false, + * "providerUrl": "http://localhost:5555/provider.html", + * "interopBrokerConfiguration": { + * "logging": { + * "beforeAction": { + * "enabled": false + * }, + * "afterAction": { + * "enabled": false + * } + * } + * } + * } + * } + * ``` + * + * --- + * **2. Overriding** + * + * Similarly to how {@link https://developers.openfin.co/docs/platform-customization#section-customizing-platform-behavior Platform Overriding} works, you can override functions in the Interop Broker in `fin.Platform.init`. An example of that is shown below. Overriding `isConnectionAuthorized` and `isActionAuthorized` will allow you to control allowed connections and allowed actions. + * + * However, if there is custom functionality you wish to include in the Interop Broker, please let us know. We would like to provide better configuration options so that you don't have to continually maintain your own override code. + * + * ```js + * fin.Platform.init({ + * overrideCallback: async (Provider) => { + * class Override extends Provider { + * async getSnapshot() { + * console.log('before getSnapshot') + * const snapshot = await super.getSnapshot(); + * console.log('after getSnapshot') + * return snapshot; + * } + * + * async applySnapshot({ snapshot, options }) { + * console.log('before applySnapshot') + * const originalPromise = super.applySnapshot({ snapshot, options }); + * console.log('after applySnapshot') + * + * return originalPromise; + * } + * }; + * return new Override(); + * }, + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async joinContextGroup(channelName = 'default', target) { + * console.log('before super joinContextGroup') + * super.joinContextGroup(channelName, target); + * console.log('after super joinContextGroup') + * } + * } + * + * return new Override(); + * } + * }); + * ``` + * + * --- + * + */ + let InteropBroker$1 = class InteropBroker extends base_1.Base { + /** + * @internal + */ + constructor(wire, createProvider, options) { + // Tip from Pierre and Michael from the overrideCheck work: Don't use bound methods for overrideable InteropBroker functions. + super(wire); + _InteropBroker_fdc3Info.set(this, void 0); + _InteropBroker_contextGroups.set(this, void 0); + _InteropBroker_providerPromise.set(this, void 0); + this.getProvider = () => { + return __classPrivateFieldGet(this, _InteropBroker_providerPromise, "f").getValue(); + }; + this.interopClients = new Map(); + this.contextGroupsById = new Map(); + __classPrivateFieldSet(this, _InteropBroker_contextGroups, options.contextGroups ?? [...defaultContextGroups], "f"); + __classPrivateFieldSet(this, _InteropBroker_fdc3Info, options.fdc3Info, "f"); + if (options?.logging) { + this.logging = options.logging; + } + this.intentClientMap = new Map(); + this.lastContextMap = new Map(); + this.sessionContextGroupMap = new Map(); + __classPrivateFieldSet(this, _InteropBroker_providerPromise, new lazy_1.Lazy(createProvider), "f"); + this.setContextGroupMap(); + this.setupChannelProvider(); + } + static createClosedConstructor(...args) { + return class OverrideableBroker extends InteropBroker { + constructor(...unused) { + if (unused.length) { + const [_ignore1, ignore2, opts] = unused; + if (opts && typeof opts === 'object' && !(0, isEqual_1.default)(opts, args[2])) { + // eslint-disable-next-line no-console + console.warn('You have modified the parameters of the InteropOverride constructor. This behavior is deprecated and will be removed in a future version. You can modify these options in your manifest. Please consult our Interop docs for guidance on migrating to the new override scheme.'); + super(args[0], args[1], opts); + return; + } + // eslint-disable-next-line no-console + console.warn('You are attempting to pass arguments to the InteropOverride constructor. This is not necessary, and these passed arguments will be ignored. You are likely using an older InteropBroker override scheme. Please consult our Interop docs for guidance on migrating to the new override scheme.'); + } + super(...args); + } + }; + } + /* + Client API + */ + /** + * Sets a context for the context group of the incoming current entity. + * @param setContextOptions - New context to set. + * @param clientIdentity - Identity of the client sender. + * + */ + setContext({ context }, clientIdentity) { + this.wire.sendAction('interop-broker-set-context').catch((e) => { + // don't expose, analytics-only call + }); + const clientState = this.getClientState(clientIdentity); + if (clientState && clientState.contextGroupId) { + const { contextGroupId } = clientState; + this.setContextForGroup({ context }, contextGroupId); + } + else if (clientState) { + // Client has not joined any context group behavior. + throw new Error('You must join a context group before you can set context.'); + } + else { + // This shouldn't get hit. + throw new Error(`Client with Identity: ${clientIdentity.uuid} ${clientIdentity.name} not in Client State Map`); + } + } + /** + * Sets a context for the context group. + * @param setContextOptions - New context to set. + * @param contextGroupId - Context group id. + * + */ + setContextForGroup({ context }, contextGroupId) { + this.wire.sendAction('interop-broker-set-context-for-group').catch((e) => { + // don't expose, analytics-only call + }); + const contextGroupState = this.contextGroupsById.get(contextGroupId); + if (!contextGroupState) { + throw new Error(`Unable to set context for context group that isn't in the context group mapping: ${contextGroupId}.`); + } + const contextIntegrityCheckResult = InteropBroker.checkContextIntegrity(context); + if (contextIntegrityCheckResult.isValid === false) { + throw new Error(`Failed to set Context - bad Context. Reason: ${contextIntegrityCheckResult.reason}. Context: ${JSON.stringify(context)}`); + } + const broadcastedContextType = context.type; + contextGroupState.set(broadcastedContextType, context); + this.lastContextMap.set(contextGroupId, broadcastedContextType); + const clientsInSameContextGroup = Array.from(this.interopClients.values()).filter((connectedClient) => connectedClient.contextGroupId === contextGroupId); + clientsInSameContextGroup.forEach((client) => { + for (const [, handlerInfo] of client.contextHandlers) { + if (InteropBroker.isContextTypeCompatible(broadcastedContextType, handlerInfo.contextType)) { + this.invokeContextHandler(client.clientIdentity, handlerInfo.handlerId, context); + } + } + }); + } + /** + * Get current context for a client subscribed to a Context Group. + * + * @remarks It takes an optional Context Type argument and returns the last context of that type. + * + * @param getContextOptions - Options for getting context + * @param clientIdentity - Identity of the client sender. + * + */ + getCurrentContext(getCurrentContextOptions, clientIdentity) { + this.wire.sendAction('interop-broker-get-current-context').catch((e) => { + // don't expose, analytics-only call + }); + const clientState = this.getClientState(clientIdentity); + if (!clientState?.contextGroupId) { + throw new Error('You must be a member of a context group to call getCurrentContext'); + } + const { contextGroupId } = clientState; + const contextGroupState = this.contextGroupsById.get(contextGroupId); + const lastContextType = this.lastContextMap.get(contextGroupId); + const contextType = getCurrentContextOptions?.contextType ?? lastContextType; + return contextGroupState && contextType ? contextGroupState.get(contextType) : undefined; + } + /* + Platform Window APIs + */ + // joinContextGroup and addClientToContextGroup are separate functions here, for easier overrides and separation of concerns. + // joinContextGroup checks all connections for matching identities, in case we have multiple connection from an entity. + /** + * Join all connections at the given identity (or just one if endpointId provided) to context group `contextGroupId`. + * If no target is specified, it adds the sender to the context group. + * joinContextGroup is responsible for checking connections at the incoming identity. It calls {@link InteropBroker#addClientToContextGroup InteropBroker.addClientToContextGroup} to actually group the client. + * Used by Platform Windows. + * + * @param joinContextGroupOptions - Id of the Context Group and identity of the entity to join to the group. + * @param senderIdentity - Identity of the client sender. + */ + async joinContextGroup({ contextGroupId, target }, senderIdentity) { + this.wire.sendAction('interop-broker-join-context-group').catch((e) => { + // don't expose, analytics-only call + }); + if (this.sessionContextGroupMap.has(contextGroupId)) { + throw new Error(utils_1.BROKER_ERRORS.joinSessionContextGroupWithJoinContextGroup); + } + if (target) { + // If an endpointId is provided, use that. This will likely be used by external adapters. + if (InteropBroker.hasEndpointId(target)) { + await this.addClientToContextGroup({ contextGroupId }, target); + } + // Sanity check here in case a single app has multiple connections + try { + const allConnections = this.channel.connections.filter((x) => x.uuid === target.uuid && x.name === target.name); + if (!allConnections.length) { + throw new Error(`Given Identity ${target.uuid} ${target.name} is not connected to the Interop Broker.`); + } + if (allConnections.length > 1) { + // Should figure out how we want to handle this situation. In the meantime, just change context group for all connections. + console.warn(`More than one connection found for identity ${target.uuid} ${target.name}`); + } + const promises = []; + for (const connection of allConnections) { + promises.push(this.addClientToContextGroup({ contextGroupId }, connection)); + } + await Promise.all(promises); + } + catch (error) { + throw new Error(error); + } + } + else { + // No target provided, add the sender to the context group. + await this.addClientToContextGroup({ contextGroupId }, senderIdentity); + } + } + // addClientToContextGroup does the actual addition of the client to the Context Group + /** + * Helper function for {@link InteropBroker#joinContextGroup InteropBroker.joinContextGroup}. Does the work of actually adding the client to the Context Group. + * Used by Platform Windows. + * + * @param addClientToContextGroupOptions - Contains the contextGroupId + * @param clientIdentity - Identity of the client sender. + */ + async addClientToContextGroup({ contextGroupId }, clientIdentity) { + this.wire.sendAction('interop-broker-add-client-to-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const clientSubscriptionState = this.getClientState(clientIdentity); + if (!clientSubscriptionState) { + throw new Error(`Client with Identity: ${clientIdentity.uuid} ${clientIdentity.name} not in Client State Map`); + } + if (!this.getContextGroups().find((contextGroupInfo) => contextGroupInfo.id === contextGroupId)) { + throw new Error(`Attempting to join a context group that does not exist: ${contextGroupId}. You may only join existing context groups.`); + } + const oldContextGroupId = clientSubscriptionState.contextGroupId; + if (oldContextGroupId !== contextGroupId) { + clientSubscriptionState.contextGroupId = contextGroupId; + await this.setCurrentContextGroupInClientOptions(clientIdentity, contextGroupId); + const contextGroupMap = this.contextGroupsById.get(contextGroupId); + for (const [, handlerInfo] of clientSubscriptionState.contextHandlers) { + const { contextType, handlerId } = handlerInfo; + if (contextType === undefined) { + // Send this single handler all of the context, because it accepts all. + contextGroupMap.forEach((context, _) => { + this.invokeContextHandler(clientIdentity, handlerId, context); + }); + } + else if (contextGroupMap.has(contextType)) { + const contextForType = contextGroupMap.get(contextType); + if (contextForType) { + this.invokeContextHandler(clientIdentity, handlerId, contextForType); + } + } + } + } + } + // Removes the target from its context group. Similar structure to joinContextGroup. + /** + * Removes the specified target from a context group. + * If no target is specified, it removes the sender from their context group. + * removeFromContextGroup is responsible for checking connections at the incoming identity. + * + * @remarks It calls {@link InteropBroker#removeClientFromContextGroup InteropBroker.removeClientFromContextGroup} to actually ungroup + * the client. Used by Platform Windows. + * + * @param removeFromContextGroupOptions - Contains the target identity to remove. + * @param senderIdentity - Identity of the client sender. + */ + async removeFromContextGroup({ target }, senderIdentity) { + this.wire.sendAction('interop-broker-remove-from-context-group').catch((e) => { + // don't expose, analytics-only call + }); + if (target) { + // If an endpointId is provided, use that. This will likely be used by external adapters. + if (InteropBroker.hasEndpointId(target)) { + await this.removeClientFromContextGroup(target); + } + try { + // Sanity check here in case a single app has multiple connections + const allConnections = this.channel.connections.filter((x) => x.uuid === target.uuid && x.name === target.name); + if (!allConnections.length) { + throw new Error(`No connection found for given Identity ${target.uuid} ${target.name}`); + } + if (allConnections.length > 1) { + console.warn(`More than one connection found for identity ${target.uuid} ${target.name}`); + } + const promises = []; + for (const connection of allConnections) { + promises.push(this.removeClientFromContextGroup(connection)); + } + await Promise.all(promises); + } + catch (error) { + throw new Error(error); + } + } + else { + // No target provided, remove the sender from the context group. + await this.removeClientFromContextGroup(senderIdentity); + } + } + // removeClientFromContextGroup does the actual remove of the client from the Context Group + /** + * Helper function for {@link InteropBroker#removeFromContextGroup InteropBroker.removeFromContextGroup}. Does the work of actually removing the client from the Context Group. + * Used by Platform Windows. + * + * @property { ClientIdentity } clientIdentity - Identity of the client sender. + */ + async removeClientFromContextGroup(clientIdentity) { + this.wire.sendAction('interop-broker-remove-client-from-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const clientState = this.getClientState(clientIdentity); + if (clientState) { + clientState.contextGroupId = undefined; + } + await this.setCurrentContextGroupInClientOptions(clientIdentity, null); + } + // Used by platform windows to know what client groups the provider has declared. Also used internally to access context groups. Overrideable so that the platform developer can modify it. + /** + * Returns the Interop-Broker-defined context groups available for an entity to join. Because this function is used in the rest of the Interop Broker to fetch the Context Groups, overriding this allows you to customize the Context Groups for the Interop Broker. However, we recommend customizing the context groups through configuration instead. + * Used by Platform Windows. + * + */ + // eslint-disable-next-line class-methods-use-this + getContextGroups() { + this.wire.sendAction('interop-broker-get-context-groups').catch((e) => { + // don't expose, analytics-only call + }); + // Create copy for immutability + return __classPrivateFieldGet(this, _InteropBroker_contextGroups, "f").map((contextGroup) => { + return { ...contextGroup }; + }); + } + // Used to by platform windows to get display metadata for a context group. + /** + * Gets display info for a context group + * + * @remarks Used by Platform Windows. + * + * @param getInfoForContextGroupOptions - Contains contextGroupId, the context group you wish to get display info for. + * + */ + getInfoForContextGroup({ contextGroupId }) { + this.wire.sendAction('interop-broker-get-info-for-context-group').catch((e) => { + // don't expose, analytics-only call + }); + return this.getContextGroups().find((contextGroup) => contextGroup.id === contextGroupId); + } + // Used by platform windows to get all clients for a context group. + /** + * Gets all clients for a context group. + * + * @remarks **This is primarily used for platform windows. Views within a platform should not have to use this API.** + * Returns the Interop-Broker-defined context groups available for an entity to join. + * + * @param getAllClientsInContextGroupOptions - Contains contextGroupId, the context group you wish to get clients for. + * + */ + getAllClientsInContextGroup({ contextGroupId }) { + this.wire.sendAction('interop-broker-get-all-clients-in-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const clientsInContextGroup = Array.from(this.interopClients.values()) + .filter((connectedClient) => connectedClient.contextGroupId === contextGroupId) + .map((subscriptionState) => { + return subscriptionState.clientIdentity; + }); + return clientsInContextGroup; + } + /** + * Responsible for launching of applications that can handle a given intent, and delegation of intents to those applications. + * Must be overridden. + * + * @remarks To make this call FDC3-Compliant it would need to return an IntentResolution. + * + * ```js + * interface IntentResolution { + * source: TargetApp; + * // deprecated, not assignable from intent listeners + * data?: object; + * version: string; + * } + * ``` + * + * More information on the IntentResolution type can be found in the [FDC3 documentation](https://fdc3.finos.org/docs/api/ref/IntentResolution). + * + * @param intent The combination of an action and a context that is passed to an application for resolution. + * @param clientIdentity Identity of the Client making the request. + * + * @example + * ```js + * // override call so we set intent target and create view that will handle it + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async handleFiredIntent(intent) { + * super.setIntentTarget(intent, { uuid: 'platform-uuid', name: 'intent-view' }); + * const platform = fin.Platform.getCurrentSync(); + * const win = fin.Window.wrapSync({ name: 'foo', uuid: 'platform-uuid' }); + * const createdView = await platform.createView({ url: 'http://openfin.co', name: 'intent-view' }, win.identity); + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + // eslint-disable-next-line class-methods-use-this + async handleFiredIntent(intent, clientIdentity // TODO(CORE-811): remove inline intersected type + ) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.raiseIntent', 'InteropBroker.handleFiredIntent', clientIdentity, 'interopClient.fireIntent'); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.fireIntent); + } + /** + * Should be called in {@link InteropBroker#handleFiredIntent InteropBroker.handleFiredIntent}. + * While handleFiredIntent is responsible for launching applications, setIntentTarget is used to tell the InteropBroker which application should receive the intent when it is ready. + * @param intent The combination of an action and a context that is passed to an application for resolution. + * @param target - Identity of the target that will handle the intent. + * + */ + async setIntentTarget(intent, target) { + this.wire.sendAction('interop-broker-set-intent-target').catch((e) => { + // don't expose, this is only for api analytics purposes + }); + const targetInfo = this.intentClientMap.get(target.name); + const handlerId = `intent-handler-${intent.name}`; + if (!targetInfo) { + this.intentClientMap.set(target.name, new Map()); + const newHandlerInfoMap = this.intentClientMap.get(target.name); + if (newHandlerInfoMap) { + newHandlerInfoMap.set(handlerId, { isReady: false, pendingIntents: [intent] }); + } + } + else { + const handlerInfo = targetInfo.get(handlerId); + if (!handlerInfo) { + targetInfo.set(handlerId, { isReady: false, pendingIntents: [intent] }); + } + else { + handlerInfo.pendingIntents.push(intent); + if (handlerInfo.clientIdentity && handlerInfo.isReady) { + const { clientIdentity, pendingIntents } = handlerInfo; + try { + const intentToSend = pendingIntents[pendingIntents.length - 1]; + await this.invokeIntentHandler(clientIdentity, handlerId, intentToSend); + handlerInfo.pendingIntents = []; + } + catch (error) { + console.error(`Error invoking intent handler for client ${clientIdentity.uuid}/${clientIdentity.name}/${clientIdentity.endpointId}`); + handlerInfo.isReady = false; + } + } + } + } + } + /** + * Responsible for returning information on a particular Intent. + * + * @remarks Whenever InteropClient.getInfoForIntent is called this function will fire. The options argument gives you + * access to the intent name and any optional context that was passed and clientIdentity is the identity of the client + * that made the call. Ideally here you would fetch the info for the intent and return it with the shape that the + * InteropClient.getInfoForIntent call is expecting. + * + * To make this call FDC3-Compliant it would need to return an App Intent: + * + * ```js + * // { + * // intent: { name: "StartChat", displayName: "Chat" }, + * // apps: [{ name: "Skype" }, { name: "Symphony" }, { name: "Slack" }] + * // } + * ``` + * + * More information on the AppIntent type can be found in the [FDC3 documentation](https://fdc3.finos.org/docs/api/ref/AppIntent). + * + * @param options + * @param clientIdentity Identity of the Client making the request. + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async handleInfoForIntent(options, clientIdentity) { + * // Your code goes here. + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + // eslint-disable-next-line class-methods-use-this + async handleInfoForIntent(options, clientIdentity // TODO(CORE-811): remove inline intersected type + ) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.findIntent', 'InteropBroker.handleInfoForIntent', clientIdentity, 'interopClient.getInfoForIntent'); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.getInfoForIntent); + } + /** + * Responsible for returning information on which Intents are meant to handle a specific Context. + * Must be overridden. + * + * @remarks Responsible for returning information on which Intents are meant to handle a specific Context. Must be overridden. + * + * Whenever InteropClient.getInfoForIntentsByContext is called this function will fire. The context argument gives you access to the context that the client wants information on and clientIdentity is the identity of the client that made the call. Ideally here you would fetch the info for any intent that can handle and return it with the shape that the InteropClient.getInfoForIntentsByContext call is expecting. + * + * To make this call FDC3-Compliant it would need to return an array of AppIntents: + * + * ```js + * // [{ + * // intent: { name: "StartCall", displayName: "Call" }, + * // apps: [{ name: "Skype" }] + * // }, + * // { + * // intent: { name: "StartChat", displayName: "Chat" }, + * // apps: [{ name: "Skype" }, { name: "Symphony" }, { name: "Slack" }] + * // }]; + * ``` + * + * More information on the AppIntent type can be found in the [FDC3 documentation](https://fdc3.finos.org/docs/api/ref/AppIntent). + * + * @param context Data passed between entities and applications. + * @param clientIdentity Identity of the Client making the request. + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async handleInfoForIntentsByContext(context, clientIdentity) { + * // Your code goes here. + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + // eslint-disable-next-line class-methods-use-this + async handleInfoForIntentsByContext(context, clientIdentity // TODO(CORE-811): remove inline intersected type + ) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.findIntentsByContext', 'InteropBroker.handleInfoForIntentsByContext', clientIdentity, 'interopClient.getInfoForIntentsByContext'); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.getInfoForIntentsByContext); + } + /** + * Responsible for resolving an Intent based on a specific Context. + * Must be overridden. + * + * @remarks Whenever InteropClient.fireIntentForContext is called this function will fire. The contextForIntent argument + * gives you access to the context that will be resolved to an intent. It also can optionally contain any metadata relevant + * to resolving it, like a specific app the client wants the context to be handled by. The clientIdentity is the identity + * of the client that made the call. + * + * To make this call FDC3-Compliant it would need to return an IntentResolution: + * + * ```js + * // { + * // intent: { name: "StartChat", displayName: "Chat" }, + * // apps: [{ name: "Skype" }, { name: "Symphony" }, { name: "Slack" }] + * // } + * ``` + * + * More information on the IntentResolution type can be found in the [FDC3 documentation](https://fdc3.finos.org/docs/api/ref/Metadata#intentresolution). + * + * @param contextForIntent Data passed between entities and applications. + * @param clientIdentity Identity of the Client making the request. + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async handleFiredIntentForContext(contextForIntent, clientIdentity) { + * // Your code goes here. + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + // eslint-disable-next-line class-methods-use-this + async handleFiredIntentForContext(contextForIntent, clientIdentity) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.raiseIntentForContext', 'InteropBroker.handleFiredIntentForContext', clientIdentity, 'interopClient.fireIntentForContext'); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.fireIntentForContext); + } + /** + * Provides the identity of any Interop Client that disconnects from the Interop Broker. It is meant to be overriden. + * @param clientIdentity + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async clientDisconnected(clientIdentity) { + * const { uuid, name } = clientIdentity; + * console.log(`Client with identity ${uuid}/${name} has been disconnected`); + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + // eslint-disable-next-line class-methods-use-this + async clientDisconnected(clientIdentity) { + // This function is called in channel.onDisconnection. + // It is meant to be overridden to inform when an Interop Client has been disconnected. + } + /** + * Responsible for resolving an fdc3.open call. + * Must be overridden. + * @param fdc3OpenOptions fdc3.open options + * @param clientIdentity Identity of the Client making the request. + */ + // eslint-disable-next-line class-methods-use-this + async fdc3HandleOpen({ app, context }, clientIdentity) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.open', 'InteropBroker.fdc3HandleOpen', clientIdentity); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.fdc3Open); + } + /** + * Responsible for resolving the fdc3.findInstances call. + * Must be overridden + * @param app AppIdentifier that was passed to fdc3.findInstances + * @param clientIdentity Identity of the Client making the request. + */ + // eslint-disable-next-line class-methods-use-this + async fdc3HandleFindInstances(app, clientIdentity) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.open', 'InteropBroker.fdc3HandleFindInstances', clientIdentity); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.fdc3FindInstances); + } + /** + * Responsible for resolving the fdc3.getAppMetadata call. + * Must be overridden + * @param app AppIdentifier that was passed to fdc3.getAppMetadata + * @param clientIdentity Identity of the Client making the request. + */ + // eslint-disable-next-line class-methods-use-this + async fdc3HandleGetAppMetadata(app, clientIdentity) { + const warning = (0, utils_1.generateOverrideWarning)('fdc3.getAppMetadata', 'InteropBroker.fdc3HandleGetAppMetadata', clientIdentity); + console.warn(warning); + throw new Error(utils_1.BROKER_ERRORS.fdc3GetAppMetadata); + } + /** + * This function is called by the Interop Broker whenever a Context handler would fire. + * For FDC3 2.0 you would need to override this function and add the contextMetadata as + * part of the Context object. Then would you need to call + * super.invokeContextHandler passing it this new Context object along with the clientIdentity and handlerId + * @param clientIdentity + * @param handlerId + * @param context + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async invokeContextHandler(clientIdentity, handlerId, context) { + * return super.invokeContextHandler(clientIdentity, handlerId, { + * ...context, + * contextMetadata: { + * source: { + * appId: 'openfin-app', + * instanceId: '3D54D456D9HT0' + * } + * } + * }); + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + async invokeContextHandler(clientIdentity, handlerId, context) { + const provider = await this.getProvider(); + try { + await provider.dispatch(clientIdentity, handlerId, context); + } + catch (error) { + console.error(`Error invoking context handler ${handlerId} for context type ${context.type} in client ${clientIdentity.uuid}/${clientIdentity.name}/${clientIdentity.endpointId}`, error); + } + } + /** + * This function is called by the Interop Broker whenever an Intent handler would fire. + * For FDC3 2.0 you would need to override this function and add the contextMetadata as + * part of the Context object inside the Intent object. Then would you need to call + * super.invokeIntentHandler passing it this new Intent object along with the clientIdentity and handlerId + * @param ClientIdentity + * @param handlerId + * @param context + * + * @example + * ```js + * fin.Platform.init({ + * interopOverride: async (InteropBroker) => { + * class Override extends InteropBroker { + * async invokeIntentHandler(clientIdentity, handlerId, context) { + * const { context } = intent; + * return super.invokeIntentHandler(clientIdentity, handlerId, { + * ...intent, + * context: { + * ...context, + * contextMetadata: { + * source: { + * appId: 'openfin-app', + * instanceId: '3D54D456D9HT0' + * } + * } + * } + * }); + * } + * } + * return new Override(); + * } + * }); + * ``` + */ + async invokeIntentHandler(clientIdentity, handlerId, intent) { + const provider = await this.getProvider(); + await provider.dispatch(clientIdentity, handlerId, intent); + } + /** + * Responsible for resolving fdc3.getInfo for FDC3 2.0 + * Would need to return the optionalFeatures and appMetadata for the {@link https://fdc3.finos.org/docs/api/ref/Metadata#implementationmetadata ImplementationMetadata}. + * Must be overridden. + * @param clientIdentity + * + */ + // eslint-disable-next-line class-methods-use-this + async fdc3HandleGetInfo(payload, clientIdentity) { + const { fdc3Version } = payload; + return { + fdc3Version, + ...__classPrivateFieldGet(this, _InteropBroker_fdc3Info, "f"), + optionalFeatures: { + OriginatingAppMetadata: false, + UserChannelMembershipAPIs: true + }, + appMetadata: { + appId: '', + instanceId: '' + } + }; + } + /** + * Returns an array of info for each Interop Client connected to the Interop Broker. + * + * FDC3 2.0: Use the endpointId in the ClientInfo as the instanceId when generating + * an AppIdentifier. + * + * @remarks FDC3 2.0 Note: When needing an instanceId to generate an AppIdentifier use this call to + * get the endpointId and use it as the instanceId. In the Example below we override handleFiredIntent + * and then call super.getAllClientInfo to generate the AppIdentifier for the IntentResolution. + * + * + * @example + * ```js + * // FDC3 2.0 Example: + * fin.Platform.init({ + * interopOverride: async (InteropBroker, ...args) => { + * class Override extends InteropBroker { + * async handleFiredIntent(intent) { + * super.setIntentTarget(intent, { uuid: 'platform-uuid', name: 'intent-view' }); + * const platform = fin.Platform.getCurrentSync(); + * const win = fin.Window.wrapSync({ name: 'foo', uuid: 'platform-uuid' }); + * const createdView = await platform.createView({ url: 'http://openfin.co', name: 'intent-view' }, win.identity); + * + * const allClientInfo = await super.getAllClientInfo(); + * + * const infoForTarget = allClientInfo.find((clientInfo) => { + * return clientInfo.uuid === 'platform-uuid' && clientInfo.name === 'intent-view'; + * }); + * + * const source = { + * appId: 'intent-view', + * instanceId: infoForTarget.endpointId + * } + * + * return { + * source, + * intent: intent.name + * } + * + * } + * } + * return new Override(...args); + * } + * }); + * ``` + */ + async getAllClientInfo() { + const provider = await this.getProvider(); + return provider.getAllClientInfo(); + } + /* + Snapshot APIs + */ + // Used to save interop broker state in snapshots + decorateSnapshot(snapshot) { + return { ...snapshot, interopSnapshotDetails: { contextGroupStates: this.getContextGroupStates() } }; + } + // Used to restore interop broker state in snapshots. + applySnapshot(snapshot, options) { + const contextGroupStates = snapshot?.interopSnapshotDetails?.contextGroupStates; + if (contextGroupStates) { + if (!options?.closeExistingWindows) { + this.updateExistingClients(contextGroupStates); + } + this.rehydrateContextGroupStates(contextGroupStates); + } + } + updateExistingClients(contextGroupStates) { + const clients = this.interopClients; + clients.forEach((subState) => { + const { clientIdentity, contextGroupId, contextHandlers } = subState; + if (contextGroupId) { + const groupContexts = contextGroupStates[contextGroupId]; + for (const [, context] of Object.entries(groupContexts)) { + contextHandlers.forEach((contextHandler) => { + const { handlerId, contextType } = contextHandler; + if (InteropBroker.isContextTypeCompatible(context.type, contextType)) { + this.invokeContextHandler(clientIdentity, handlerId, context); + } + }); + } + } + }); + } + // Used to store context group state in snapshots + getContextGroupStates() { + return InteropBroker.toObject(this.contextGroupsById); + } + // Used to rehydrate the context state from a snapshot + rehydrateContextGroupStates(incomingContextGroupStates) { + const contextGroupStates = Object.entries(incomingContextGroupStates); + for (const [contextGroupId, contexts] of contextGroupStates) { + const contextObjects = Object.entries(contexts); + for (const [contextType, context] of contextObjects) { + if (this.contextGroupsById.has(contextGroupId)) { + const currentContextGroupState = this.contextGroupsById.get(contextGroupId); + currentContextGroupState.set(contextType, context); + } + else { + // This logic will change when dynamic context group creation comes in. + console.warn(`Attempting to set a context group that isn't in the context group mapping. Skipping context group rehydration for: ${contextGroupId}`); + } + } + } + } + /* + Internal Context Handler APIs + */ + // Used to give context to a client that has registered their context handler + contextHandlerRegistered({ contextType, handlerId }, clientIdentity) { + const handlerInfo = { contextType, handlerId }; + const clientState = this.getClientState(clientIdentity); + clientState?.contextHandlers.set(handlerId, handlerInfo); + if (clientState && clientState.contextGroupId) { + const { contextGroupId } = clientState; + const contextGroupMap = this.contextGroupsById.get(contextGroupId); + if (contextType === undefined) { + // Send this single handler all of the context, because it accepts all. + contextGroupMap.forEach((context, _) => { + this.invokeContextHandler(clientIdentity, handlerId, context); + }); + } + else if (contextGroupMap.has(contextType)) { + const contextForType = contextGroupMap.get(contextType); + if (contextForType) { + this.invokeContextHandler(clientIdentity, handlerId, contextForType); + } + } + } + } + // eslint-disable-next-line class-methods-use-this + async intentHandlerRegistered(payload, clientIdentity) { + const { handlerId } = payload; + const clientIntentInfo = this.intentClientMap.get(clientIdentity.name); + const handlerInfo = clientIntentInfo?.get(handlerId); + if (!clientIntentInfo) { + this.intentClientMap.set(clientIdentity.name, new Map()); + const newHandlerInfoMap = this.intentClientMap.get(clientIdentity.name); + if (newHandlerInfoMap) { + newHandlerInfoMap.set(handlerId, { isReady: true, pendingIntents: [], clientIdentity }); + } + } + else if (!handlerInfo) { + clientIntentInfo.set(handlerId, { isReady: true, pendingIntents: [], clientIdentity }); + } + else { + const { pendingIntents } = handlerInfo; + handlerInfo.clientIdentity = clientIdentity; + handlerInfo.isReady = true; + try { + if (pendingIntents.length > 0) { + const intentToSend = pendingIntents[pendingIntents.length - 1]; + await this.invokeIntentHandler(clientIdentity, handlerId, intentToSend); + handlerInfo.pendingIntents = []; + } + } + catch (error) { + console.error(`Error invoking intent handler: ${handlerId} for client ${clientIdentity.uuid}/${clientIdentity.name}/${clientIdentity.endpointId}`); + } + } + } + // Used to remove a context handler for a client + removeContextHandler({ handlerId }, clientIdentity) { + const clientState = this.getClientState(clientIdentity); + if (clientState) { + clientState.contextHandlers.delete(handlerId); + } + } + handleJoinSessionContextGroup({ sessionContextGroupId }, clientIdentity) { + try { + if (!sessionContextGroupId) { + throw new Error('Failed to join session context group: must specify group id.'); + } + const sessionContextGroup = this.sessionContextGroupMap.get(sessionContextGroupId); + if (sessionContextGroup) { + sessionContextGroup.registerNewClient(clientIdentity); + } + else { + const newSessionContextGroupBroker = new SessionContextGroupBroker_1.default(this.channel, sessionContextGroupId); + newSessionContextGroupBroker.registerNewClient(clientIdentity); + this.sessionContextGroupMap.set(sessionContextGroupId, newSessionContextGroupBroker); + } + return { hasConflict: this.contextGroupsById.has(sessionContextGroupId) }; + } + catch (error) { + throw new Error(error); + } + } + /* + Internal Utilties + */ + // Getter for interop info for a client. + getClientState(id) { + return this.interopClients.get(id.endpointId); + } + // Util for getContextGroupStates. Serializes the contextGroupStates object so we can store it. + static toObject(map) { + const objectFromMap = Object.fromEntries(map); + const newObject = {}; + Object.entries(objectFromMap).forEach(([contextGroupId, contextMap]) => { + const newContextObject = Object.fromEntries(contextMap); + newObject[contextGroupId] = newContextObject; + }); + return newObject; + } + static checkContextIntegrity(context) { + if (!context) { + return { isValid: false, reason: 'No context supplied' }; + } + if (typeof context !== 'object') { + return { isValid: false, reason: 'Context must be an Object' }; + } + if (!context.type) { + return { isValid: false, reason: 'Context must have a type property' }; + } + if (context.id && typeof context.id !== 'object') { + return { + isValid: false, + reason: 'Context id must be an Object populated with key-value identifiers (if set)' + }; + } + if (context.id) { + const { id } = context; + const keys = Object.keys(id); + let foundBadIdentifier = false; + if (!keys.length) { + return { isValid: false, reason: 'Context id must have at least one key-value identifier' }; + } + keys.forEach((key) => { + if (typeof key !== 'string' || typeof id[key] !== 'string') { + foundBadIdentifier = true; + } + }); + if (foundBadIdentifier) { + return { isValid: false, reason: 'Context id key-value identifiers must be of type string' }; + } + } + if (context.name && typeof context.name !== 'string') { + return { isValid: false, reason: 'Context name must be of string type (if set)' }; + } + return { isValid: true }; + } + // Util to check a client identity. + static hasEndpointId(target) { + return target.endpointId !== undefined; + } + // Util to check if we should send a context to a handler. + static isContextTypeCompatible(contextType, registeredContextType) { + return typeof registeredContextType === 'undefined' || contextType === registeredContextType; + } + // Setup function for state mapping + setContextGroupMap() { + // This way, if a user overrides this.getContextGroups, it's reflected in the contextGroupMapping. + for (const contextGroupInfo of this.getContextGroups()) { + this.contextGroupsById.set(contextGroupInfo.id, new Map()); + } + } + async setCurrentContextGroupInClientOptions(clientIdentity, contextGroupId) { + try { + const entityInfo = await this.fin.System.getEntityInfo(clientIdentity.uuid, clientIdentity.name); + let entity; + if (entityInfo.entityType === 'view') { + entity = await this.fin.View.wrap(clientIdentity); + } + else if (entityInfo.entityType === 'window') { + entity = await this.fin.Window.wrap(clientIdentity); + } + if (entity) { + await entity.updateOptions({ + interop: { + currentContextGroup: contextGroupId + } + }); + } + } + catch (error) { + // May file in interop + } + } + async setupChannelProvider() { + try { + const channel = await this.getProvider(); + this.channel = channel; + this.wireChannel(channel); + } + catch (error) { + throw new Error(`Error setting up Interop Broker Channel Provider: ${error}`); + } + } + // Setup Channel Connection Logic + wireChannel(channel) { + channel.onConnection(async (clientIdentity, // TODO(CORE-811): remove inline intersected type + payload) => { + if (!(await this.isConnectionAuthorized(clientIdentity, payload))) { + throw new Error(`Connection not authorized for ${clientIdentity.uuid}, ${clientIdentity.name}`); + } + if (!clientIdentity.endpointId) { + throw new Error('Version too old to be compatible with Interop. Please upgrade your runtime to a more recent version.'); + } + const clientSubscriptionState = { + contextGroupId: undefined, + contextHandlers: new Map(), + clientIdentity + }; + // Only allow the client to join a contextGroup that actually exists. + if (payload?.currentContextGroup && this.contextGroupsById.has(payload.currentContextGroup)) { + clientSubscriptionState.contextGroupId = payload?.currentContextGroup; + } + this.interopClients.set(clientIdentity.endpointId, clientSubscriptionState); + }); + channel.onDisconnection((clientIdentity) => { + this.interopClients.delete(clientIdentity.endpointId); + const targetInfo = this.intentClientMap.get(clientIdentity.name); + if (targetInfo && clientIdentity.uuid === this.fin.me.uuid) { + targetInfo.forEach((handler) => { + handler.isReady = false; + }); + } + this.sessionContextGroupMap.forEach((sessionContextGroup) => { + sessionContextGroup.onDisconnection(clientIdentity); + }); + this.clientDisconnected(clientIdentity); + }); + channel.beforeAction(async (action, payload, clientIdentity) => { + if (!(await this.isActionAuthorized(action, payload, clientIdentity))) { + throw new Error(`Action (${action}) not authorized for ${clientIdentity.uuid}, ${clientIdentity.name}`); + } + if (this.logging?.beforeAction?.enabled) { + console.log(action, payload, clientIdentity); + } + }); + channel.afterAction((action, payload, clientIdentity) => { + if (this.logging?.afterAction?.enabled) { + console.log(action, payload, clientIdentity); + } + }); + // Client functions + channel.register('setContext', this.setContext.bind(this)); + channel.register('fireIntent', this.handleFiredIntent.bind(this)); + channel.register('getCurrentContext', this.getCurrentContext.bind(this)); + channel.register('getInfoForIntent', this.handleInfoForIntent.bind(this)); + channel.register('getInfoForIntentsByContext', this.handleInfoForIntentsByContext.bind(this)); + channel.register('fireIntentForContext', this.handleFiredIntentForContext.bind(this)); + // Platform window functions + channel.register('getContextGroups', this.getContextGroups.bind(this)); + channel.register('joinContextGroup', this.joinContextGroup.bind(this)); + channel.register('removeFromContextGroup', this.removeFromContextGroup.bind(this)); + channel.register('getAllClientsInContextGroup', this.getAllClientsInContextGroup.bind(this)); + channel.register('getInfoForContextGroup', this.getInfoForContextGroup.bind(this)); + // Internal methods + channel.register('contextHandlerRegistered', this.contextHandlerRegistered.bind(this)); + channel.register('intentHandlerRegistered', this.intentHandlerRegistered.bind(this)); + channel.register('removeContextHandler', this.removeContextHandler.bind(this)); + channel.register('sessionContextGroup:createIfNeeded', this.handleJoinSessionContextGroup.bind(this)); + // fdc3 only methods + channel.register('fdc3Open', this.fdc3HandleOpen.bind(this)); + channel.register('fdc3v2FindIntentsByContext', this.handleInfoForIntentsByContext.bind(this)); + channel.register('fdc3FindInstances', this.fdc3HandleFindInstances.bind(this)); + channel.register('fdc3GetAppMetadata', this.fdc3HandleGetAppMetadata.bind(this)); + channel.register('fdc3v2GetInfo', async (payload, clientIdentity) => { + return this.fdc3HandleGetInfo.bind(this)(payload, clientIdentity); + }); + channel.register('createPrivateChannelProvider', async (payload) => { + const { channelId } = payload; + const channelProvider = await this.fin.InterApplicationBus.Channel.create(channelId); + PrivateChannelProvider_1.PrivateChannelProvider.init(channelProvider, channelId); + }); + } + /** + * Can be used to completely prevent a connection. Return false to prevent connections. Allows all connections by default. + * @param _id the identity tryinc to connect + * @param _connectionPayload optional payload to use in custom implementations, will be undefined by default + */ + isConnectionAuthorized(_id, _connectionPayload) { + this.wire.sendAction('interop-broker-is-connection-authorized').catch((e) => { + // don't expose, analytics-only call + }); + return Promise.resolve(true); + } + /** + * Called before every action to check if this entity should be allowed to take the action. + * Return false to prevent the action + * @param _action the string action to authorize in camel case + * @param _payload the data being sent for this action + * @param _identity the connection attempting to dispatch this action + */ + isActionAuthorized(_action, _payload, _identity) { + this.wire.sendAction('interop-broker-is-action-authorized').catch((e) => { + // don't expose, analytics-only call + }); + return Promise.resolve(true); + } + }; + InteropBroker.InteropBroker = InteropBroker$1; + _InteropBroker_fdc3Info = new WeakMap(), _InteropBroker_contextGroups = new WeakMap(), _InteropBroker_providerPromise = new WeakMap(); + return InteropBroker; +} + +var InteropClient = {}; + +var SessionContextGroupClient$1 = {}; + +var __classPrivateFieldSet$2 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$2 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _SessionContextGroupClient_clientPromise; +Object.defineProperty(SessionContextGroupClient$1, "__esModule", { value: true }); +const base_1$2 = base; +const utils_1$2 = utils$3; +class SessionContextGroupClient extends base_1$2.Base { + constructor(wire, client, id) { + super(wire); + _SessionContextGroupClient_clientPromise.set(this, void 0); + this.id = id; + __classPrivateFieldSet$2(this, _SessionContextGroupClient_clientPromise, client, "f"); + } + /** + * Sets a context for the session context group. + * @param context - New context to set. + * + * @tutorial interop.setContext + */ + async setContext(context) { + this.wire.sendAction('interop-session-context-group-set-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet$2(this, _SessionContextGroupClient_clientPromise, "f"); + return client.dispatch(`sessionContextGroup:setContext-${this.id}`, { + sessionContextGroupId: this.id, + context + }); + } + async getCurrentContext(type) { + this.wire.sendAction('interop-session-context-group-get-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet$2(this, _SessionContextGroupClient_clientPromise, "f"); + return client.dispatch(`sessionContextGroup:getContext-${this.id}`, { + sessionContextGroupId: this.id, + type + }); + } + async addContextHandler(contextHandler, contextType) { + this.wire.sendAction('interop-session-context-group-add-handler').catch((e) => { + // don't expose, analytics-only call + }); + if (typeof contextHandler !== 'function') { + throw new Error("Non-function argument passed to the first parameter 'handler'. Be aware that the argument order does not match the FDC3 standard."); + } + const client = await __classPrivateFieldGet$2(this, _SessionContextGroupClient_clientPromise, "f"); + let handlerId; + if (contextType) { + handlerId = `sessionContextHandler:invoke-${this.id}-${contextType}-${(0, utils_1$2.generateId)()}`; + } + else { + handlerId = `sessionContextHandler:invoke-${this.id}`; + } + client.register(handlerId, (0, utils_1$2.wrapContextHandler)(contextHandler, handlerId)); + await client.dispatch(`sessionContextGroup:handlerAdded-${this.id}`, { handlerId, contextType }); + return { unsubscribe: await this.createUnsubscribeCb(handlerId) }; + } + async createUnsubscribeCb(handlerId) { + const client = await __classPrivateFieldGet$2(this, _SessionContextGroupClient_clientPromise, "f"); + return async () => { + client.remove(handlerId); + await client.dispatch(`sessionContextGroup:handlerRemoved-${this.id}`, { handlerId }); + }; + } + getUserInstance() { + return { + id: this.id, + setContext: (0, utils_1$2.wrapInTryCatch)(this.setContext.bind(this), 'Failed to set context: '), + getCurrentContext: (0, utils_1$2.wrapInTryCatch)(this.getCurrentContext.bind(this), 'Failed to get context: '), + addContextHandler: (0, utils_1$2.wrapInTryCatch)(this.addContextHandler.bind(this), 'Failed to add context handler: ') + }; + } +} +SessionContextGroupClient$1.default = SessionContextGroupClient; +_SessionContextGroupClient_clientPromise = new WeakMap(); + +var fdc31_2 = {}; + +var fdc3Common = {}; + +var utils$2 = {}; + +var PrivateChannelClient$1 = {}; + +var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(PrivateChannelClient$1, "__esModule", { value: true }); +PrivateChannelClient$1.PrivateChannelClient = void 0; +const utils$1 = __importStar(utils$3); +class PrivateChannelClient { + constructor(client, id) { + this.id = id; + this.client = client; + this.listeners = new Map(); + } + async broadcast(context) { + return this.client.dispatch('broadcast', { context }); + } + async getCurrentContext(contextType) { + return this.client.dispatch('getCurrentContext', { contextType }); + } + async addContextListener(contextType, handler) { + if (typeof handler !== 'function') { + throw new Error("Non-function argument passed to the second parameter 'handler'. Be aware that the argument order does not match the FDC3 standard."); + } + let handlerId; + if (contextType) { + handlerId = `contextHandler:invoke-${this.id}-${contextType}-${utils$1.generateId()}`; + } + else { + handlerId = `contextHandler:invoke-${this.id}-${utils$1.generateId()}`; + } + this.client.register(handlerId, utils$1.wrapContextHandler(handler, handlerId)); + const listener = { unsubscribe: await this.createContextUnsubscribeCb(handlerId) }; + this.listeners.set(handlerId, listener); + await this.client.dispatch(`contextHandlerAdded`, { handlerId, contextType }); + return listener; + } + createNonStandardUnsubscribeCb(handlerId) { + return async () => { + this.client.remove(handlerId); + this.listeners.delete(handlerId); + await this.client.dispatch('nonStandardHandlerRemoved', { handlerId }); + }; + } + createContextUnsubscribeCb(handlerId) { + return async () => { + this.client.remove(handlerId); + this.listeners.delete(handlerId); + await this.client.dispatch('contextHandlerRemoved', { handlerId }); + }; + } + onAddContextListener(handler) { + const handlerId = `onContextHandlerAdded:invoke-${this.id}-${utils$1.generateId()}`; + this.client.register(handlerId, handler); + const listener = { unsubscribe: this.createNonStandardUnsubscribeCb(handlerId) }; + this.listeners.set(handlerId, listener); + this.client.dispatch(`onAddContextHandlerAdded`, { handlerId }); + return listener; + } + onDisconnect(handler) { + const handlerId = `onDisconnect:invoke-${this.id}-${utils$1.generateId()}`; + this.client.register(handlerId, handler); + const listener = { unsubscribe: this.createNonStandardUnsubscribeCb(handlerId) }; + this.listeners.set(handlerId, listener); + this.client.dispatch(`onDisconnectHandlerAdded`, { handlerId }); + return listener; + } + onUnsubscribe(handler) { + const handlerId = `onUnsubscribe:invoke-${this.id}-${utils$1.generateId()}`; + this.client.register(handlerId, handler); + const listener = { unsubscribe: this.createNonStandardUnsubscribeCb(handlerId) }; + this.listeners.set(handlerId, listener); + this.client.dispatch(`onUnsubscribeHandlerAdded`, { handlerId }); + return listener; + } + async cleanUpAllSubs() { + const listenerUnsubscribers = Array.from(this.listeners.keys()); + listenerUnsubscribers.forEach((handlerId) => { + this.client.remove(handlerId); + this.listeners.delete(handlerId); + }); + } + async disconnect() { + try { + await this.client.dispatch('clientDisconnecting'); + await this.cleanUpAllSubs(); + await this.client.disconnect(); + } + catch (error) { + throw new Error(error.message); + } + } +} +PrivateChannelClient$1.PrivateChannelClient = PrivateChannelClient; + +(function (exports) { + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.getIntentResolution = exports.isChannel = exports.isContext = exports.connectPrivateChannel = exports.buildAppChannelObject = exports.buildPrivateChannelObject = exports.ChannelError = exports.ResultError = exports.UnsupportedChannelApiError = exports.getUnsupportedChannelApis = void 0; + const utils_1 = utils$3; + const PrivateChannelClient_1 = PrivateChannelClient$1; + const isEqual_1 = __importDefault(require$$3); + const getUnsupportedChannelApis = (channelType) => { + return { + addContextListener: () => { + throw new UnsupportedChannelApiError('Channel.addContextListener', channelType); + }, + broadcast: () => { + throw new UnsupportedChannelApiError('Channel.broadcast', channelType); + }, + getCurrentContext: () => { + throw new UnsupportedChannelApiError('Channel.getCurrentContext', channelType); + } + }; + }; + exports.getUnsupportedChannelApis = getUnsupportedChannelApis; + class UnsupportedChannelApiError extends Error { + constructor(apiName, channelType = 'System') { + super(apiName); + this.message = `Calling ${apiName} on an instance of a ${channelType} Channel returned by fdc3.get${channelType}Channels is not supported. If you would like to use a ${channelType} Channel, please use fdc3.joinChannel, fdc3.addContextListener, and fdc3.broadcast instead.`; + } + } + exports.UnsupportedChannelApiError = UnsupportedChannelApiError; + var ResultError; + (function (ResultError) { + /** Returned if the `IntentHandler` exited without returning a Promise or that + * Promise was not resolved with a Context or Channel object. + */ + ResultError["NoResultReturned"] = "NoResultReturned"; + /** Returned if the `IntentHandler` function processing the raised intent + * throws an error or rejects the Promise it returned. + */ + ResultError["IntentHandlerRejected"] = "IntentHandlerRejected"; + })(ResultError = exports.ResultError || (exports.ResultError = {})); + (function (ChannelError) { + /** Returned if the specified channel is not found when attempting to join a + * channel via the `joinUserChannel` function of the DesktopAgent (`fdc3`). + */ + ChannelError["NoChannelFound"] = "NoChannelFound"; + /** SHOULD be returned when a request to join a user channel or to a retrieve + * a Channel object via the `joinUserChannel` or `getOrCreateChannel` methods + * of the DesktopAgent (`fdc3`) object is denied. + */ + ChannelError["AccessDenied"] = "AccessDenied"; + /** SHOULD be returned when a channel cannot be created or retrieved via the + * `getOrCreateChannel` method of the DesktopAgent (`fdc3`). + */ + ChannelError["CreationFailed"] = "CreationFailed"; + })(exports.ChannelError || (exports.ChannelError = {})); + const buildPrivateChannelObject = (privateChannelClient) => { + let clientDisconnected = false; + const checkIfClientDisconnected = () => { + if (clientDisconnected) { + throw new Error('Private Channel Client has been disconnected from the Private Channel'); + } + }; + return { + id: privateChannelClient.id, + type: 'private', + broadcast: async (context) => { + checkIfClientDisconnected(); + return privateChannelClient.broadcast(context); + }, + getCurrentContext: async (contextType) => { + checkIfClientDisconnected(); + return privateChannelClient.getCurrentContext(contextType); + }, + // @ts-expect-error TODO [CORE-1524] + addContextListener: async (contextType, handler) => { + checkIfClientDisconnected(); + let handlerInUse = handler; + let contextTypeInUse = contextType; + if (typeof contextType === 'function') { + console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)'); + handlerInUse = contextType; + contextTypeInUse = null; + } + const listener = privateChannelClient.addContextListener(contextTypeInUse, handlerInUse); + return listener; + }, + onAddContextListener: (handler) => { + checkIfClientDisconnected(); + return privateChannelClient.onAddContextListener(handler); + }, + disconnect: async () => { + checkIfClientDisconnected(); + clientDisconnected = true; + return privateChannelClient.disconnect(); + }, + onDisconnect: (handler) => { + checkIfClientDisconnected(); + return privateChannelClient.onDisconnect(handler); + }, + onUnsubscribe: (handler) => { + checkIfClientDisconnected(); + return privateChannelClient.onUnsubscribe(handler); + } + }; + }; + exports.buildPrivateChannelObject = buildPrivateChannelObject; + const buildAppChannelObject = (sessionContextGroup) => { + return { + id: sessionContextGroup.id, + type: 'app', + broadcast: sessionContextGroup.setContext, + getCurrentContext: async (contextType) => { + const context = await sessionContextGroup.getCurrentContext(contextType); + return context === undefined ? null : context; + }, + // @ts-expect-error TODO [CORE-1524] + addContextListener: (contextType, handler) => { + let realHandler; + let realType; + if (typeof contextType === 'function') { + console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)'); + realHandler = contextType; + } + else { + realHandler = handler; + if (typeof contextType === 'string') { + realType = contextType; + } + } + const listener = (async () => { + let first = true; + const currentContext = await sessionContextGroup.getCurrentContext(realType); + const wrappedHandler = (context, contextMetadata) => { + if (first) { + first = false; + if ((0, isEqual_1.default)(currentContext, context)) { + return; + } + } + // eslint-disable-next-line consistent-return + return realHandler(context, contextMetadata); + }; + return sessionContextGroup.addContextHandler(wrappedHandler, realType); + })(); + return { + ...listener, + unsubscribe: () => listener.then((l) => l.unsubscribe()) + }; + } + }; + }; + exports.buildAppChannelObject = buildAppChannelObject; + const connectPrivateChannel = async (channelId) => { + try { + const channelClient = await fin.InterApplicationBus.Channel.connect(channelId); + const privateChannelClient = new PrivateChannelClient_1.PrivateChannelClient(channelClient, channelId); + return (0, exports.buildPrivateChannelObject)(privateChannelClient); + } + catch (error) { + throw new Error(`Private Channel with id: ${channelId} doesn't exist`); + } + }; + exports.connectPrivateChannel = connectPrivateChannel; + const isContext = (context) => { + if (context && typeof context === 'object' && 'type' in context) { + const { type } = context; + return typeof type === 'string'; + } + return false; + }; + exports.isContext = isContext; + const isChannel = (channel) => { + if (channel && typeof channel === 'object' && 'type' in channel && 'id' in channel) { + const { type, id } = channel; + return typeof type === 'string' && typeof id === 'string' && (type === 'app' || type === 'private'); + } + return false; + }; + exports.isChannel = isChannel; + const getIntentResolution = async (interopModule, context, app, intent) => { + // Generate an ID to make a session context group with. We will pass that ID to the Broker. + // The broker will then setContext on that session context group later with our Intent Result, + const guid = (0, utils_1.generateId)(); // TODO make this undefined in web + // Promise we'll use in getResult + const getResultPromise = new Promise((resolve, reject) => { + fin.InterApplicationBus.subscribe({ uuid: '*' }, guid, (intentResult) => { + resolve(intentResult); + }).catch(() => reject(new Error('getResult is not supported in this environment'))); + }); + // Adding the intentResolutionResultId to the intentObj. Because fireIntent only accepts a single arg, we have to slap it in here. + const metadata = app ? { target: app, intentResolutionResultId: guid } : { intentResolutionResultId: guid }; + const intentObj = intent ? { name: intent, context, metadata } : { ...context, metadata }; + // Set up the getResult call. + const getResult = async () => { + let intentResult = await getResultPromise; + if (!intentResult || typeof intentResult !== 'object') { + throw new Error(ResultError.NoResultReturned); + } + const { error } = intentResult; + if (error) { + throw new Error(ResultError.IntentHandlerRejected); + } + if ((0, exports.isChannel)(intentResult)) { + const { id, type } = intentResult; + switch (type) { + case 'private': { + intentResult = await (0, exports.connectPrivateChannel)(id); + break; + } + case 'app': { + const sessionContextGroup = await interopModule.joinSessionContextGroup(id); + intentResult = (0, exports.buildAppChannelObject)(sessionContextGroup); + break; + } + } + } + else if (!(0, exports.isContext)(intentResult)) { + throw new Error(ResultError.NoResultReturned); + } + return intentResult; + }; + // Finally fire the intent. + const intentResolutionInfoFromBroker = intent + ? await interopModule.fireIntent(intentObj) + : await interopModule.fireIntentForContext(intentObj); + if (typeof intentResolutionInfoFromBroker !== 'object') { + return { + source: { + appId: '', + instanceId: '' + }, + intent: '', + version: '2.0', + getResult + }; + } + return { ...intentResolutionInfoFromBroker, getResult }; + }; + exports.getIntentResolution = getIntentResolution; +} (utils$2)); + +var hasRequiredFdc3Common; + +function requireFdc3Common () { + if (hasRequiredFdc3Common) return fdc3Common; + hasRequiredFdc3Common = 1; + var __classPrivateFieldGet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + var __classPrivateFieldSet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; + }; + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + var _FDC3ModuleBase_producer; + Object.defineProperty(fdc3Common, "__esModule", { value: true }); + fdc3Common.FDC3ModuleBase = void 0; + const utils_1 = utils$2; + const utils_2 = utils$3; + const InteropClient_1 = requireInteropClient(); + const isEqual_1 = __importDefault(require$$3); + class FDC3ModuleBase { + get client() { + return __classPrivateFieldGet(this, _FDC3ModuleBase_producer, "f").call(this); + } + get fin() { + return this.wire.getFin(); + } + // eslint-disable-next-line no-useless-constructor + constructor(producer, wire) { + this.wire = wire; + _FDC3ModuleBase_producer.set(this, void 0); + __classPrivateFieldSet(this, _FDC3ModuleBase_producer, producer, "f"); + } + /** + * Broadcasts a context for the channel of the current entity. + * @param context - New context to set. + * + * @tutorial fdc3.broadcast + * @static + */ + async broadcast(context) { + this.wire.sendAction('fdc3-broadcast').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.client.setContext(context); + } + /** + * Launches an app with target information, which can either be a string or an AppMetadata object. + * @param app + * @param context + * + * @tutorial fdc3.open + */ + async _open(app, context) { + this.wire.sendAction('fdc3-open').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'fdc3Open', { app, context }); + } + catch (error) { + const errorToThrow = error.message === utils_2.BROKER_ERRORS.fdc3Open ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + async _getChannels() { + const channels = await this.client.getContextGroups(); + // fdc3 implementation of getSystemChannels returns an array of channels, have to decorate over + // this so people know that these APIs are not supported + return channels.map((channel) => { + return { ...channel, type: 'system', ...(0, utils_1.getUnsupportedChannelApis)() }; + }); + } + /** + * Returns a Channel object for the specified channel, creating it as an App Channel if it does not exist. + * @param channelId + * + * @tutorial fdc3.getOrCreateChannel + */ + async getOrCreateChannel(channelId) { + this.wire.sendAction('fdc3-get-or-create-channel').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const systemChannels = await this._getChannels(); + const userChannel = systemChannels.find((channel) => channel.id === channelId); + if (userChannel) { + return { ...userChannel, type: 'system', ...(0, utils_1.getUnsupportedChannelApis)() }; + } + try { + const sessionContextGroup = await this.client.joinSessionContextGroup(channelId); + return (0, utils_1.buildAppChannelObject)(sessionContextGroup); + } + catch (error) { + console.error(error.message); + throw new Error(utils_1.ChannelError.CreationFailed); + } + } + /** + * Returns the Interop-Broker-defined context groups available for an entity to join. + * + * @tutorial fdc3.getSystemChannels + * @static + */ + async getSystemChannels() { + this.wire.sendAction('fdc3-get-system-channels').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this._getChannels(); + } + /** + * Join all Interop Clients at the given identity to context group `contextGroupId`. + * If no target is specified, it adds the sender to the context group. + * Because multiple Channel connections/Interop Clients can potentially exist at a `uuid`/`name` combo, we currently join all Channel connections/Interop Clients at the given identity to the context group. + * If an `endpointId` is provided (which is unlikely, unless the call is coming from an external adapter), then we only join that single connection to the context group. + * For all intents and purposes, there will only be 1 connection present in Platform and Browser implementations, so this point is more-or-less moot. + * @param channelId - Id of the context group. + * + * @tutorial fdc3.joinChannel + * @static + */ + async joinChannel(channelId) { + this.wire.sendAction('fdc3-join-channel').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await this.client.joinContextGroup(channelId); + } + catch (error) { + if (error.message === utils_2.BROKER_ERRORS.joinSessionContextGroupWithJoinContextGroup) { + console.error('The Channel you have tried to join is an App Channel. Custom Channels can only be defined by the Interop Broker through code or manifest configuration. Please use getOrCreateChannel.'); + } + else { + console.error(error.message); + } + if (error.message.startsWith('Attempting to join a context group that does not exist')) { + throw new Error(utils_1.ChannelError.NoChannelFound); + } + throw new Error(utils_1.ChannelError.AccessDenied); + } + } + /** + * Returns the Channel that the entity is subscribed to. Returns null if not joined to a channel. + * + * @tutorial fdc3.getCurrentChannel + */ + async getCurrentChannel() { + this.wire.sendAction('fdc3-get-current-channel').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const currentContextGroupInfo = await this.getCurrentContextGroupInfo(); + if (!currentContextGroupInfo) { + return null; + } + return this.buildChannelObject(currentContextGroupInfo); + } + /** + * Removes the specified target from a context group. + * If no target is specified, it removes the sender from their context group. + * + * @tutorial fdc3.leaveCurrentChannel + * @static + */ + async leaveCurrentChannel() { + this.wire.sendAction('fdc3-leave-current-channel').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + return this.client.removeFromContextGroup(); + } + // utils + // eslint-disable-next-line class-methods-use-this + async getCurrentContextGroupInfo() { + const contextGroups = await this.client.getContextGroups(); + const clientsInCtxGroupsPromise = contextGroups.map(async (ctxGroup) => { + return this.client.getAllClientsInContextGroup(ctxGroup.id); + }); + const clientsInCtxGroups = await Promise.all(clientsInCtxGroupsPromise); + const clientIdx = clientsInCtxGroups.findIndex((clientIdentityArr) => { + return clientIdentityArr.some((clientIdentity) => { + const { uuid, name } = clientIdentity; + return this.wire.me.uuid === uuid && this.wire.me.name === name; + }); + }); + return contextGroups[clientIdx]; + } + async buildChannelObject(currentContextGroupInfo) { + // @ts-expect-error + return { + ...currentContextGroupInfo, + type: 'system', + addContextListener: (...[contextType, handler]) => { + let realHandler; + let realType; + if (typeof contextType === 'function') { + console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)'); + realHandler = contextType; + } + else { + realHandler = handler; + if (typeof contextType === 'string') { + realType = contextType; + } + } + const listener = (async () => { + let first = true; + const currentContext = await this.client.getCurrentContext(realType); + const wrappedHandler = (context, contextMetadata) => { + if (first) { + first = false; + if ((0, isEqual_1.default)(currentContext, context)) { + return; + } + } + // eslint-disable-next-line consistent-return + return realHandler(context, contextMetadata); + }; + return this.client.addContextHandler(wrappedHandler, realType); + })(); + // @ts-expect-error TODO [CORE-1524] + return { + ...listener, + unsubscribe: () => listener.then((l) => l.unsubscribe()) + }; + }, + broadcast: this.broadcast.bind(this), + // @ts-expect-error Typescript fails to infer the returntype is a Promise + getCurrentContext: async (contextType) => { + const context = await this.client.getCurrentContext(contextType); + // @ts-expect-error Typescript fails to infer the returntype is a Promise + return context === undefined ? null : context; + } + }; + } + } + fdc3Common.FDC3ModuleBase = FDC3ModuleBase; + _FDC3ModuleBase_producer = new WeakMap(); + return fdc3Common; +} + +var hasRequiredFdc31_2; + +function requireFdc31_2 () { + if (hasRequiredFdc31_2) return fdc31_2; + hasRequiredFdc31_2 = 1; + Object.defineProperty(fdc31_2, "__esModule", { value: true }); + fdc31_2.Fdc3Module = void 0; + const utils_1 = utils$3; + const fdc3_common_1 = requireFdc3Common(); + /** + * @version 1.2 + * The FDC3 Client Library provides a set APIs to be used for FDC3 compliance, + * while using our Interop API under the hood. In order to use this set of APIs + * you will need to set up your own {@link InteropBroker InteropBroker} or use a Platform application, which does the setup for you. Refer to our documentation on + * our {@link https://developers.openfin.co/of-docs/docs/enable-color-linking Interop API}. + * + * To enable the FDC3 APIs in a {@link Window Window} or {@link View View}, add the fdc3InteropApi + * property to its options: + * + * ```js + * { + * autoShow: false, + * saveWindowState: true, + * url: 'https://openfin.co', + * fdc3InteropApi: '1.2' + * } + * ``` + * + * If using a {@link Platform Platform } application, you can set this property in defaultWindowOptions and defaultViewOptions. + * + * In order to ensure that the FDC3 Api is ready before use, you can use the 'fdc3Ready' event fired on the DOM Window object: + * + * ```js + * function fdc3Action() { + * // Make some fdc3 API calls here + * } + * + * if (window.fdc3) { + * fdc3Action(); + * } else { + * window.addEventListener('fdc3Ready', fdc3Action); + * } + * ``` + */ + class Fdc3Module extends fdc3_common_1.FDC3ModuleBase { + async open(app, context) { + // eslint-disable-next-line no-underscore-dangle + await super._open(app, context); + } + /** + * Add a context handler for incoming context. If an entity is part of a context group, and then sets its context handler, it will receive all of its declared contexts. If you wish to listen for all incoming contexts, pass `null` for the contextType argument. + * @param contextType - The type of context you wish to handle. + * @param handler - Handler for incoming context. + * + * @tutorial fdc3.addContextListener + * @static + */ + // @ts-expect-error TODO [CORE-1524] + addContextListener(contextType, handler) { + this.wire.sendAction('fdc3-add-context-listener').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + let listener; + if (typeof contextType === 'function') { + console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)'); + listener = this.client.addContextHandler(contextType); + } + else { + listener = this.client.addContextHandler(handler, contextType === null ? undefined : contextType); + } + return { + ...listener, + unsubscribe: () => listener.then((l) => l.unsubscribe()) + }; + } + /** + * Adds a listener for incoming Intents. + * @param intent - Name of the Intent + * @param handler - Handler for incoming Intent + * + * @tutorial fdc3.addIntentListener + * @static + */ + addIntentListener(intent, handler) { + this.wire.sendAction('fdc3-add-intent-listener').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const contextHandler = (raisedIntent) => { + const { context, metadata: intentMetadata } = raisedIntent; + const { metadata } = context; + const intentResolutionResultId = intentMetadata?.intentResolutionResultId || metadata?.intentResolutionResultId; + if (intentResolutionResultId) { + this.fin.InterApplicationBus.publish(intentResolutionResultId, null).catch(() => null); + } + handler(raisedIntent.context); + }; + const listener = this.client.registerIntentHandler(contextHandler, intent, { + fdc3Version: '1.2' + }); + return { + ...listener, + unsubscribe: () => listener.then((l) => l.unsubscribe()) + }; + } + /** + * Raises a specific intent. + * @param intent Name of the Intent. + * @param context Context associated with the Intent. + * @param app App that will resolve the Intent. This is added as metadata to the Intent. Can be accessed by the app provider in {@link InteropBroker#handleFiredIntent InteropBroker.handleFiredIntent}. + * + * @tutorial fdc3.raiseIntent + * @static + */ + async raiseIntent(intent, context, app) { + this.wire.sendAction('fdc3-raise-intent').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const intentObj = app + ? { name: intent, context, metadata: { target: app } } + : { name: intent, context }; + try { + return await this.client.fireIntent(intentObj); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fireIntent ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Find out more information about a particular intent by passing its name, and optionally its context. + * @param intent Name of the Intent + * @param context + * + * @tutorial fdc3.findIntent + */ + async findIntent(intent, context) { + this.wire.sendAction('fdc3-find-intent').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await this.client.getInfoForIntent({ name: intent, context }); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.getInfoForIntent ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Find all the available intents for a particular context. + * @param context + * + * @tutorial fdc3.findIntentsByContext + */ + async findIntentsByContext(context) { + this.wire.sendAction('fdc3-find-intents-by-context').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await this.client.getInfoForIntentsByContext(context); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.getInfoForIntentsByContext ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Finds and raises an intent against a target app based purely on context data. + * @param context + * @param app + * + * @tutorial fdc3.raiseIntentForContext + */ + async raiseIntentForContext(context, app) { + this.wire.sendAction('fdc3-raise-intent-for-context').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await this.client.fireIntentForContext({ ...context, metadata: { target: app } }); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fireIntentForContext ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Returns a Channel object for the specified channel, creating it as an App Channel if it does not exist. + * @param channelId + * + * @tutorial fdc3.getOrCreateChannel + */ + async getOrCreateChannel(channelId) { + return super.getOrCreateChannel(channelId); + } + /** + * Returns metadata relating to the FDC3 object and its provider, including the supported version of the FDC3 specification and the name of the provider of the implementation. + * + * @tutorial fdc3.getInfo + */ + getInfo() { + this.wire.sendAction('fdc3-get-info').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const version = this.wire.environment.getAdapterVersionSync(); + return { + providerVersion: version, + provider: `openfin-${this.wire.me.uuid}`, + fdc3Version: '1.2' + }; + } + } + fdc31_2.Fdc3Module = Fdc3Module; + return fdc31_2; +} + +var fdc32_0 = {}; + +var hasRequiredFdc32_0; + +function requireFdc32_0 () { + if (hasRequiredFdc32_0) return fdc32_0; + hasRequiredFdc32_0 = 1; + Object.defineProperty(fdc32_0, "__esModule", { value: true }); + fdc32_0.Fdc3Module2 = void 0; + const fdc3_common_1 = requireFdc3Common(); + const utils_1 = utils$3; + const InteropClient_1 = requireInteropClient(); + const utils_2 = utils$2; + const PrivateChannelClient_1 = PrivateChannelClient$1; + /** + * @version 2.0 + * The FDC3 Client Library provides a set APIs to be used for FDC3 compliance, + * while using our Interop API under the hood. In order to use this set of APIs + * you will need to set up your own {@link InteropBroker InteropBroker} or use a Platform application, which does the setup for you. Refer to our documentation on + * our {@link https://developers.openfin.co/of-docs/docs/enable-context-sharing Interop API}. + * + * To enable the FDC3 APIs in a {@link Window Window} or {@link View View}, add the fdc3InteropApi + * property to its options: + * + * ```js + * { + * autoShow: false, + * saveWindowState: true, + * url: 'https://openfin.co', + * fdc3InteropApi: '2.0' + * } + * ``` + * + * If using a {@link Platform Platform } application, you can set this property in defaultWindowOptions and defaultViewOptions. + * + * In order to ensure that the FDC3 Api is ready before use, you can use the 'fdc3Ready' event fired on the DOM Window object: + * + * ```js + * function fdc3Action() { + * // Make some fdc3 API calls here + * } + * + * if (window.fdc3) { + * fdc3Action(); + * } else { + * window.addEventListener('fdc3Ready', fdc3Action); + * } + * ``` + */ + class Fdc3Module2 extends fdc3_common_1.FDC3ModuleBase { + /** + * Launches an app, specified via an AppIdentifier object. + * @param app + * @param context + * + * @tutorial fdc3.open + */ + async open(app, context) { + if (typeof app === 'string') { + console.warn('Passing a string as the app parameter is deprecated, please use an AppIdentifier ({ appId: string; instanceId?: string }).'); + } + // eslint-disable-next-line no-underscore-dangle + return super._open(app, context); + } + /** + * Find all the available instances for a particular application. + * @param app + * + * @tutorial fdc3v2.findInstances + */ + async findInstances(app) { + this.wire.sendAction('fdc3-find-instances').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'fdc3FindInstances', app); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fdc3FindInstances ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Retrieves the AppMetadata for an AppIdentifier, which provides additional metadata (such as icons, a title and description) from the App Directory record for the application, that may be used for display purposes. + * @param app + * + * @tutorial fdc3v2.getAppMetadata + */ + async getAppMetadata(app) { + this.wire.sendAction('fdc3-get-app-metadata').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'fdc3GetAppMetadata', app); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fdc3GetAppMetadata ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Add a context handler for incoming context. If an entity is part of a context group, and then sets its context handler, it will receive all of its declared contexts. If you wish to listen for all incoming contexts, pass `null` for the contextType argument. + * @param contextType + * @param handler + * + * @tutorial fdc3.addContextListener + */ + // @ts-expect-error TODO [CORE-1524] + async addContextListener(contextType, handler) { + this.wire.sendAction('fdc3-add-context-listener').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + // The FDC3 ContextHandler only expects the context and optional ContextMetadata, so we wrap the handler + // here so it only gets passed these parameters + const getWrappedHandler = (handlerToWrap) => { + return (context) => { + const { contextMetadata, ...rest } = context; + const args = contextMetadata ? [{ ...rest }, contextMetadata] : [context, null]; + handlerToWrap(...args); + }; + }; + let actualHandler = handler; + let wrappedHandler = getWrappedHandler(actualHandler); + if (typeof contextType === 'function') { + console.warn('addContextListener(handler) has been deprecated. Please use addContextListener(null, handler)'); + actualHandler = contextType; + wrappedHandler = getWrappedHandler(actualHandler); + return this.client.addContextHandler(wrappedHandler); + } + return this.client.addContextHandler(wrappedHandler, contextType === null ? undefined : contextType); + } + /** + * Find out more information about a particular intent by passing its name, and optionally its context and resultType. + * @param intent Name of the Intent + * @param context Context + * @param resultType The type of result returned for any intent specified during resolution. + * + * @tutorial fdc3.findIntent + */ + async findIntent(intent, context, resultType) { + this.wire.sendAction('fdc3-find-intent').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + return await this.client.getInfoForIntent({ name: intent, context, metadata: { resultType } }); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.getInfoForIntent ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Find all the available intents for a particular context. + * @param context + * @param resultType The type of result returned for any intent specified during resolution. + * + * @tutorial fdc3v2.findIntentsByContext + */ + async findIntentsByContext(context, resultType) { + this.wire.sendAction('fdc3-find-intents-by-context').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + const payload = resultType ? { context, metadata: { resultType } } : context; + try { + return await InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'fdc3v2FindIntentsByContext', payload); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.getInfoForIntentsByContext ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Raises a specific intent for resolution against apps registered with the desktop agent. + * @param intent Name of the Intent + * @param context Context associated with the Intent + * @param app + * + * @tutorial fdc3v2.raiseIntent + */ + async raiseIntent(intent, context, app) { + this.wire.sendAction('fdc3-raise-intent').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + if (typeof app === 'string') { + console.warn('Passing a string as the app parameter is deprecated, please use an AppIdentifier ({ appId: string; instanceId?: string }).'); + } + return (0, utils_2.getIntentResolution)(this.client, context, app, intent); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fireIntent ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Finds and raises an intent against apps registered with the desktop agent based purely on the type of the context data. + * @param context Context associated with the Intent + * @param app + * + * @tutorial fdc3v2.raiseIntentForContext + */ + async raiseIntentForContext(context, app) { + // TODO: We have to do the same thing we do for raiseIntent here as well. + this.wire.sendAction('fdc3-raise-intent-for-context').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + try { + if (typeof app === 'string') { + console.warn('Passing a string as the app parameter is deprecated, please use an AppIdentifier ({ appId: string; instanceId?: string }).'); + } + return (0, utils_2.getIntentResolution)(this.client, context, app); + } + catch (error) { + const errorToThrow = error.message === utils_1.BROKER_ERRORS.fireIntent ? 'ResolverUnavailable' : error.message; + throw new Error(errorToThrow); + } + } + /** + * Adds a listener for incoming intents. + * @param intent Name of the Intent + * @param handler A callback that handles a context event and may return a promise of a Context or Channel object to be returned to the application that raised the intent. + * + * @tutorial fdc3.addIntentListener + */ + async addIntentListener(intent, handler) { + this.wire.sendAction('fdc3-add-intent-listener').catch((e) => { + // we do not want to expose this error, just continue if this analytics-only call fails + }); + if (typeof intent !== 'string') { + throw new Error('First argument must be an Intent name'); + } + // The FDC3 Intenter handler only expects the context and contextMetadata to be passed to the handler, + // so we wrap it here and only pass those paramaters. + const contextHandler = async (raisedIntent) => { + let intentResult; + let intentResultToSend; + const { context, metadata: intentMetadata } = raisedIntent; + const { contextMetadata, metadata, ...rest } = context; + const intentResolutionResultId = intentMetadata?.intentResolutionResultId || metadata?.intentResolutionResultId; + try { + const newContext = metadata ? { metadata, ...rest } : { ...rest }; + intentResult = await handler(newContext, contextMetadata); + intentResultToSend = intentResult; + } + catch (error) { + intentResult = error; + intentResultToSend = { error: true }; + } + if (intentResolutionResultId) { + this.fin.InterApplicationBus.publish(intentResolutionResultId, intentResultToSend).catch(() => null); + } + if (intentResult instanceof Error) { + throw new Error(intentResult.message); + } + return intentResult; + }; + return this.client.registerIntentHandler(contextHandler, intent, { fdc3Version: '2.0' }); + } + /** + * Returns a Channel object for the specified channel, creating it as an App Channel if it does not exist. + * @param channelId + * + * @tutorial fdc3.getOrCreateChannel + */ + async getOrCreateChannel(channelId) { + return super.getOrCreateChannel(channelId); + } + /** + * Returns a Channel with an auto-generated identity that is intended for private communication between applications. Primarily used to create channels that will be returned to other applications via an IntentResolution for a raised intent. + * + * @tutorial fdc3v2.createPrivateChannel + */ + async createPrivateChannel() { + const channelId = (0, utils_1.generateId)(); + await InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'createPrivateChannelProvider', { channelId }); + const channelClient = await this.fin.InterApplicationBus.Channel.connect(channelId); + const newPrivateChannelClient = new PrivateChannelClient_1.PrivateChannelClient(channelClient, channelId); + return (0, utils_2.buildPrivateChannelObject)(newPrivateChannelClient); + } + /** + * Retrieves a list of the User Channels available for the app to join. + * + * @tutorial fdc3v2.getUserChannels + */ + async getUserChannels() { + const channels = await this.client.getContextGroups(); + // fdc3 implementation of getUserChannels returns on array of channels, have to decorate over + // this so people know that these APIs are not supported + return channels.map((channel) => { + // @ts-expect-error TODO [CORE-1524] + return { ...channel, type: 'user', ...(0, utils_2.getUnsupportedChannelApis)('User') }; + }); + } + /** + * Retrieves a list of the User Channels available for the app to join. + * + * @deprecated Please use {@link fdc3.getUserChannels fdc3.getUserChannels} instead + * @tutorial fdc3.getSystemChannels + */ + async getSystemChannels() { + console.warn('This API has been deprecated. Please use fdc3.getUserChannels instead.'); + return super.getSystemChannels(); + } + /** + * Join an app to a specified User channel. + * @param channelId Channel name + * + * @tutorial fdc3v2.joinUserChannel + */ + async joinUserChannel(channelId) { + return super.joinChannel(channelId); + } + /** + * Join an app to a specified User channel. + * @param channelId Channel name + * @deprecated Please use {@link fdc3.joinUserChannel fdc3.joinUserChannel} instead + * + * @tutorial fdc3.joinChannel + */ + async joinChannel(channelId) { + console.warn('This API has been deprecated. Please use fdc3.joinUserChannel instead.'); + return super.joinChannel(channelId); + } + /** + * Returns the Channel object for the current User channel membership + * + * @tutorial fdc3.getCurrentChannel + */ + async getCurrentChannel() { + const currentChannel = await super.getCurrentChannel(); + if (!currentChannel) { + return null; + } + return { + ...currentChannel, + type: 'user', + broadcast: this.broadcast.bind(this) + }; + } + /** + * Retrieves information about the FDC3 implementation, including the supported version of the FDC3 specification, the name of the provider of the implementation, its own version number, details of whether optional API features are implemented and the metadata of the calling application according to the desktop agent. + * fdc3HandleGetInfo must be overridden in the InteropBroker so that the ImplementationMetadata will have the appMetadata info. + * + * @tutorial fdc3v2.getInfo + */ + async getInfo() { + return InteropClient_1.InteropClient.ferryFdc3Call(this.client, 'fdc3v2GetInfo', { fdc3Version: '2.0' }); + } + } + fdc32_0.Fdc3Module2 = Fdc3Module2; + return fdc32_0; +} + +var hasRequiredInteropClient; + +function requireInteropClient () { + if (hasRequiredInteropClient) return InteropClient; + hasRequiredInteropClient = 1; + var __classPrivateFieldSet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; + }; + var __classPrivateFieldGet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + var _InteropClient_clientPromise, _InteropClient_sessionContextGroups; + Object.defineProperty(InteropClient, "__esModule", { value: true }); + InteropClient.InteropClient = void 0; + const base_1 = base; + const SessionContextGroupClient_1 = __importDefault(SessionContextGroupClient$1); + const fdc3_1_2_1 = requireFdc31_2(); + const fdc3_2_0_1 = requireFdc32_0(); + const utils_1 = utils$3; + /** + * The Interop Client API is broken up into two groups: + * + * **Content Facing APIs** - For Application Developers putting Views into a Platform Window, who care about Context. These are APIs that send out and receive the Context data that flows between applications. Think of this as the Water in the Interop Pipes. + * + * **Context Grouping APIs** - For Platform Developers, to add and remove Views to and from Context Groups. These APIs are utilized under-the-hood in Platforms, so they don't need to be used to participate in Interop. These are the APIs that decide which entities the context data flows between. Think of these as the valves or pipes that control the flow of Context Data for Interop. + * + * --- + * + * All APIs are available at the `fin.me.interop` namespace. + * + * --- + * + * **You only need 2 things to participate in Interop Context Grouping:** + * * A Context Handler for incoming context: {@link InteropClient#addContextHandler addContextHandler(handler, contextType?)} + * * Call setContext on your context group when you want to share context with other group members: {@link InteropClient#setContext setContext(context)} + * + * --- + * + * ##### Constructor + * Returned by {@link Interop.connectSync Interop.connectSync}. + * + * --- + * + * ##### Interop methods intended for Views + * + * + * **Context Groups API** + * * {@link InteropClient#addContextHandler addContextHandler(handler, contextType?)} + * * {@link InteropClient#setContext setContext(context)} + * * {@link InteropClient#getCurrentContext getCurrentContext(contextType?)} + * * {@link InteropClient#joinSessionContextGroup joinSessionContextGroup(sessionContextGroupId)} + * + * + * **Intents API** + * * {@link InteropClient#fireIntent fireIntent(intent)} + * * {@link InteropClient#registerIntentHandler registerIntentHandler(intentHandler, intentName)} + * * {@link InteropClient#getInfoForIntent getInfoForIntent(infoForIntentOptions)} + * * {@link InteropClient#getInfoForIntentsByContext getInfoForIntentsByContext(context)} + * * {@link InteropClient#fireIntentForContext fireIntentForContext(contextForIntent)} + * + * ##### Interop methods intended for Windows + * * {@link InteropClient#getContextGroups getContextGroups()} + * * {@link InteropClient#joinContextGroup joinContextGroup(contextGroupId, target?)} + * * {@link InteropClient#removeFromContextGroup removeFromContextGroup(target?)} + * * {@link InteropClient#getInfoForContextGroup getInfoForContextGroup(contextGroupId)} + * * {@link InteropClient#getAllClientsInContextGroup getAllClientsInContextGroup(contextGroupId)} + * + */ + let InteropClient$1 = class InteropClient extends base_1.Base { + /** + * @internal + */ + constructor(wire, clientPromise) { + super(wire); + _InteropClient_clientPromise.set(this, void 0); + _InteropClient_sessionContextGroups.set(this, void 0); + __classPrivateFieldSet(this, _InteropClient_sessionContextGroups, new Map(), "f"); + __classPrivateFieldSet(this, _InteropClient_clientPromise, clientPromise, "f"); + } + /* + Client APIs + */ + /** + * Sets a context for the context group of the current entity. + * + * @remarks The entity must be part of a context group in order set a context. + * + * @param context - New context to set. + * + * @example + * ```js + * setInstrumentContext = async (ticker) => { + * fin.me.interop.setContext({type: 'instrument', id: {ticker}}) + * } + * + * // The user clicks an instrument of interest. We want to set that Instrument context so that the rest of our workflow updates with information for that instrument + * instrumentElement.on('click', (evt) => { + * setInstrumentContext(evt.ticker) + * }) + * ``` + */ + async setContext(context) { + this.wire.sendAction('interop-client-set-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('setContext', { context }); + } + /** + * Add a context handler for incoming context. If an entity is part of a context group, and then sets its context handler, + * it will receive all of its declared contexts. + * + * @param handler - Handler for incoming context. + * @param contextType - The type of context you wish to handle. + * + * @example + * ```js + * function handleIncomingContext(contextInfo) { + * const { type, id } = contextInfo; + * switch (type) { + * case 'instrument': + * handleInstrumentContext(contextInfo); + * break; + * case 'country': + * handleCountryContext(contextInfo); + * break; + * + * default: + * break; + * } + * } + * + * + * function handleInstrumentContext(contextInfo) { + * const { type, id } = contextInfo; + * console.log('contextInfo for instrument', contextInfo) + * } + * + * function handleCountryContext(contextInfo) { + * const { type, id } = contextInfo; + * console.log('contextInfo for country', contextInfo) + * } + * + * fin.me.interop.addContextHandler(handleIncomingContext); + * ``` + * + * + * Passing in a context type as the second parameter will cause the handler to only be invoked with that context type. + * + * ```js + * function handleInstrumentContext(contextInfo) { + * const { type, id } = contextInfo; + * console.log('contextInfo for instrument', contextInfo) + * } + * + * function handleCountryContext(contextInfo) { + * const { type, id } = contextInfo; + * console.log('contextInfo for country', contextInfo) + * } + * + * + * fin.me.interop.addContextHandler(handleInstrumentContext, 'instrument') + * fin.me.interop.addContextHandler(handleCountryContext, 'country') + * ``` + */ + async addContextHandler(handler, contextType) { + this.wire.sendAction('interop-client-add-context-handler').catch((e) => { + // don't expose, analytics-only call + }); + if (typeof handler !== 'function') { + throw new Error("Non-function argument passed to the first parameter 'handler'. Be aware that the argument order does not match the FDC3 standard."); + } + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + let handlerId; + if (contextType) { + handlerId = `invokeContextHandler-${contextType}-${(0, utils_1.generateId)()}`; + } + else { + handlerId = 'invokeContextHandler'; + } + const wrappedHandler = (0, utils_1.wrapContextHandler)(handler, handlerId); + client.register(handlerId, wrappedHandler); + await client.dispatch('contextHandlerRegistered', { handlerId, contextType }); + return { + unsubscribe: async () => { + client.remove(handlerId); + await client.dispatch('removeContextHandler', { handlerId }); + } + }; + } + /* + Platform Window APIs + */ + /** + * Returns the Interop-Broker-defined context groups available for an entity to join. + * Used by Platform Windows. + * + * @example + * ```js + * fin.me.interop.getContextGroups() + * .then(contextGroups => { + * contextGroups.forEach(contextGroup => { + * console.log(contextGroup.displayMetadata.name) + * console.log(contextGroup.displayMetadata.color) + * }) + * }) + * ``` + */ + async getContextGroups() { + this.wire.sendAction('interop-client-get-context-groups').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('getContextGroups'); + } + /** + * Join all Interop Clients at the given identity to context group `contextGroupId`. + * If no target is specified, it adds the sender to the context group. + * + * @remarks Because multiple Channel connections/Interop Clients can potentially exist at a `uuid`/`name` combo, we currently join all Channel connections/Interop Clients at the given identity to the context group. + * If an `endpointId` is provided (which is unlikely, unless the call is coming from an external adapter), then we only join that single connection to the context group. + * For all intents and purposes, there will only be 1 connection present in Platform and Browser implmentations, so this point is more-or-less moot. + * Used by Platform Windows. + * + * @param contextGroupId - Id of the context group. + * @param target - Identity of the entity you wish to join to a context group. + * + * @example + * ```js + * joinViewToContextGroup = async (contextGroupId, view) => { + * await fin.me.interop.joinContextGroup(contextGroupId, view); + * } + * + * getLastFocusedView() + * .then(lastFocusedViewIdentity => { + * joinViewToContextGroup('red', lastFocusedViewIdentity) + * }) + * ``` + */ + async joinContextGroup(contextGroupId, target) { + this.wire.sendAction('interop-client-join-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + if (!contextGroupId) { + throw new Error('No contextGroupId specified for joinContextGroup.'); + } + return client.dispatch('joinContextGroup', { contextGroupId, target }); + } + /** + * Removes the specified target from a context group. + * If no target is specified, it removes the sender from their context group. + * Used by Platform Windows. + * + * @param target - Identity of the entity you wish to join to a context group. + * + * @example + * ```js + * removeViewFromContextGroup = async (view) => { + * await fin.me.interop.removeFromContextGroup(view); + * } + * + * getLastFocusedView() + * .then(lastFocusedViewIdentity => { + * removeViewFromContextGroup(lastFocusedViewIdentity) + * }) + * ``` + */ + async removeFromContextGroup(target) { + this.wire.sendAction('interop-client-remove-from-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('removeFromContextGroup', { target }); + } + /** + * Gets all clients for a context group. + * + * @remarks **This is primarily used for platform windows. Views within a platform should not have to use this API.** + * + * Returns the Interop-Broker-defined context groups available for an entity to join. + * @param contextGroupId - The id of context group you wish to get clients for. + * + * @example + * ```js + * fin.me.interop.getAllClientsInContextGroup('red') + * .then(clientsInContextGroup => { + * console.log(clientsInContextGroup) + * }) + * ``` + */ + async getAllClientsInContextGroup(contextGroupId) { + this.wire.sendAction('interop-client-get-all-clients-in-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + if (!contextGroupId) { + throw new Error('No contextGroupId specified for getAllClientsInContextGroup.'); + } + return client.dispatch('getAllClientsInContextGroup', { contextGroupId }); + } + /** + * Gets display info for a context group + * + * @remarks Used by Platform Windows. + * @param contextGroupId - The id of context group you wish to get display info for. + * + * @example + * ```js + * fin.me.interop.getInfoForContextGroup('red') + * .then(contextGroupInfo => { + * console.log(contextGroupInfo.displayMetadata.name) + * console.log(contextGroupInfo.displayMetadata.color) + * }) + * ``` + */ + async getInfoForContextGroup(contextGroupId) { + this.wire.sendAction('interop-client-get-info-for-context-group').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + if (!contextGroupId) { + throw new Error('No contextGroupId specified for getInfoForContextGroup.'); + } + return client.dispatch('getInfoForContextGroup', { contextGroupId }); + } + /** + * Sends an intent to the Interop Broker to resolve. + * @param intent - The combination of an action and a context that is passed to an application for resolution. + * + * @example + * ```js + * // View wants to fire an Intent after a user clicks on a ticker + * tickerElement.on('click', (element) => { + * const ticker = element.innerText; + * const intent = { + * name: 'ViewChart', + * context: {type: 'fdc3.instrument', id: { ticker }} + * } + * + * fin.me.interop.fireIntent(intent); + * }) + * ``` + */ + async fireIntent(intent) { + this.wire.sendAction('interop-client-fire-intent').catch((e) => { + // don't expose, this is only for api analytics purposes + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('fireIntent', intent); + } + /** + * Adds an intent handler for incoming intents. The last intent sent of the name subscribed to will be received. + * @param handler - Registered function meant to handle a specific intent type. + * @param intentName - The name of an intent. + * + * @example + * ```js + * const intentHandler = (intent) => { + * const { context } = intent; + * myViewChartHandler(context); + * }; + * + * const subscription = await fin.me.interop.registerIntentHandler(intentHandler, 'ViewChart'); + * + * function myAppCloseSequence() { + * // to unsubscribe the handler, simply call: + * subscription.unsubscribe(); + * } + * ``` + */ + async registerIntentHandler(handler, intentName, options) { + this.wire.sendAction('interop-client-register-intent-handler').catch((e) => { + // don't expose, this is only for api analytics purposes + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + const handlerId = `intent-handler-${intentName}`; + const wrappedHandler = (0, utils_1.wrapIntentHandler)(handler, handlerId); + try { + await client.register(handlerId, wrappedHandler); + await client.dispatch('intentHandlerRegistered', { handlerId, ...options }); + } + catch (error) { + throw new Error('Unable to register intent handler'); + } + return { + unsubscribe: async () => { + client.remove(handlerId); + } + }; + } + /** + * Gets the last context of the Context Group currently subscribed to. It takes an optional Context Type and returns the + * last context of that type. + * @param contextType + * + * @example + * ```js + * await fin.me.interop.joinContextGroup('yellow'); + * await fin.me.interop.setContext({ type: 'instrument', id: { ticker: 'FOO' }}); + * const currentContext = await fin.me.interop.getCurrentContext(); + * + * // with a specific context + * await fin.me.interop.joinContextGroup('yellow'); + * await fin.me.interop.setContext({ type: 'country', id: { ISOALPHA3: 'US' }}); + * await fin.me.interop.setContext({ type: 'instrument', id: { ticker: 'FOO' }}); + * const currentContext = await fin.me.interop.getCurrentContext('country'); + * ``` + */ + async getCurrentContext(contextType) { + this.wire.sendAction('interop-client-get-current-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('getCurrentContext', { contextType }); + } + /** + * Get information for a particular Intent from the Interop Broker. + * + * @remarks To resolve this info, the function handleInfoForIntent is meant to be overridden in the Interop Broker. + * The format for the response will be determined by the App Provider overriding the function. + * + * @param options + * + * @example + * ```js + * const intentInfo = await fin.me.interop.getInfoForIntent('ViewChart'); + * ``` + */ + async getInfoForIntent(options) { + this.wire.sendAction('interop-client-get-info-for-intent').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('getInfoForIntent', options); + } + /** + * Get information from the Interop Broker on all Intents that are meant to handle a particular context. + * + * @remarks To resolve this info, the function handleInfoForIntentsByContext is meant to be overridden in the Interop Broker. + * The format for the response will be determined by the App Provider overriding the function. + * + * @param context + * + * @example + * ```js + * tickerElement.on('click', (element) => { + * const ticker = element.innerText; + * + * const context = { + * type: 'fdc3.instrument', + * id: { + * ticker + * } + * } + * + * const intentsInfo = await fin.me.interop.getInfoForIntentByContext(context); + * }) + * ``` + */ + async getInfoForIntentsByContext(context) { + this.wire.sendAction('interop-client-get-info-for-intents-by-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('getInfoForIntentsByContext', context); + } + /** + * Sends a Context that will be resolved to an Intent by the Interop Broker. + * This context accepts a metadata property. + * + * @remarks To resolve this info, the function handleFiredIntentByContext is meant to be overridden in the Interop Broker. + * The format for the response will be determined by the App Provider overriding the function. + * + * @param context + * + * @example + * ```js + * tickerElement.on('click', (element) => { + * const ticker = element.innerText; + * + * const context = { + * type: 'fdc3.instrument', + * id: { + * ticker + * } + * } + * + * const intentResolution = await fin.me.interop.fireIntentForContext(context); + * }) + * ``` + */ + async fireIntentForContext(context) { + this.wire.sendAction('interop-client-fire-intent-for-context').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.dispatch('fireIntentForContext', context); + } + /** + * Join the current entity to session context group `sessionContextGroupId` and return a sessionContextGroup instance. + * If the sessionContextGroup doesn't exist, one will get created. + * + * @remarks Session Context Groups do not persist between runs and aren't present on snapshots. + * @param sessionContextGroupId - Id of the context group. + * + * @example + * Say we want to have a Session Context Group that holds UI theme information for all apps to consume: + * + * My color-picker View: + * ```js + * const themeSessionContextGroup = await fin.me.interop.joinSessionContextGroup('theme'); + * + * const myColorPickerElement = document.getElementById('color-palette-picker'); + * myColorPickerElement.addEventListener('change', event => { + * themeSessionContextGroup.setContext({ type: 'color-palette', selection: event.value }); + * }); + * ``` + * + * In other views: + * ```js + * const themeSessionContextGroup = await fin.me.interop.joinSessionContextGroup('theme'); + * + * const changeColorPalette = ({ selection }) => { + * // change the color palette to the selection + * }; + * + * // If the context is already set by the time the handler was set, the handler will get invoked immediately with the current context. + * themeSessionContextGroup.addContextHandler(changeColorPalette, 'color-palette'); + * ``` + */ + async joinSessionContextGroup(sessionContextGroupId) { + try { + const currentSessionContextGroup = __classPrivateFieldGet(this, _InteropClient_sessionContextGroups, "f").get(sessionContextGroupId); + if (currentSessionContextGroup) { + return currentSessionContextGroup.getUserInstance(); + } + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + const { hasConflict } = await client.dispatch('sessionContextGroup:createIfNeeded', { + sessionContextGroupId + }); + if (hasConflict) { + console.warn(`A (non-session) context group with the name "${sessionContextGroupId}" already exists. If you are trying to join a Context Group, call joinContextGroup instead.`); + } + const newSessionContextGroup = new SessionContextGroupClient_1.default(this.wire, __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"), sessionContextGroupId); + __classPrivateFieldGet(this, _InteropClient_sessionContextGroups, "f").set(sessionContextGroupId, newSessionContextGroup); + return newSessionContextGroup.getUserInstance(); + } + catch (error) { + console.error(`Error thrown trying to create Session Context Group with id "${sessionContextGroupId}": ${error}`); + throw error; + } + } + /** + * Register a listener that is called when the Interop Client has been disconnected from the Interop Broker. + * Only one listener per Interop Client can be set. + * @param listener + * + * @example + * ```js + * const listener = (event) => { + * const { type, topic, brokerName} = event; + * console.log(`Disconnected from Interop Broker ${brokerName} `); + * } + * + * await fin.me.interop.onDisconnection(listener); + * ``` + */ + async onDisconnection(listener) { + this.wire.sendAction('interop-client-add-ondisconnection-listener').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet(this, _InteropClient_clientPromise, "f"); + return client.onDisconnection((event) => { + const { uuid } = event; + listener({ type: 'interop-broker', topic: 'disconnected', brokerName: uuid }); + }); + } + getFDC3Sync(version) { + switch (version) { + case '1.2': + return new fdc3_1_2_1.Fdc3Module(() => this, this.wire); + case '2.0': + return new fdc3_2_0_1.Fdc3Module2(() => this, this.wire); + default: + throw new Error(`Invalid FDC3 version provided: ${version}. Must be '1.2' or '2.0'`); + } + } + async getFDC3(version) { + return this.getFDC3Sync(version); + } + /** + * @internal + * + * Used to ferry fdc3-only calls from the fdc3 shim to the Interop Broker + */ + static async ferryFdc3Call(interopClient, action, payload) { + const client = await __classPrivateFieldGet(interopClient, _InteropClient_clientPromise, "f"); + return client.dispatch(action, payload || null); + } + }; + InteropClient.InteropClient = InteropClient$1; + _InteropClient_clientPromise = new WeakMap(), _InteropClient_sessionContextGroups = new WeakMap(); + return InteropClient; +} + +var overrideCheck = {}; + +var hasRequiredOverrideCheck; + +function requireOverrideCheck () { + if (hasRequiredOverrideCheck) return overrideCheck; + hasRequiredOverrideCheck = 1; + Object.defineProperty(overrideCheck, "__esModule", { value: true }); + overrideCheck.overrideCheck = overrideCheck.checkFDC32Overrides = overrideCheck.getDefaultViewFdc3VersionFromAppInfo = void 0; + const InteropBroker_1 = requireInteropBroker(); + function getDefaultViewFdc3VersionFromAppInfo({ manifest, initialOptions }) { + const setVersion = manifest?.platform?.defaultViewOptions?.fdc3InteropApi ?? initialOptions.defaultViewOptions?.fdc3InteropApi; + return ['1.2', '2.0'].includes(setVersion ?? '') ? setVersion : undefined; + } + overrideCheck.getDefaultViewFdc3VersionFromAppInfo = getDefaultViewFdc3VersionFromAppInfo; + function checkFDC32Overrides(overriddenBroker) { + // These are the APIs that must be overridden for FDC3 2.0 compliance + const mustOverrideAPIs = [ + 'fdc3HandleFindInstances', + 'handleInfoForIntent', + 'handleInfoForIntentsByContext', + 'fdc3HandleGetAppMetadata', + 'fdc3HandleGetInfo', + 'fdc3HandleOpen', + 'handleFiredIntent', + 'handleFiredIntentForContext' + ]; + return mustOverrideAPIs.filter((api) => { + return overriddenBroker[api] === InteropBroker_1.InteropBroker.prototype[api]; + }); + } + overrideCheck.checkFDC32Overrides = checkFDC32Overrides; + function overrideCheck$1(overriddenBroker, fdc3InteropApi) { + if (fdc3InteropApi && fdc3InteropApi === '2.0') { + const notOverridden = checkFDC32Overrides(overriddenBroker); + if (notOverridden.length > 0) { + console.warn(`WARNING: FDC3 2.0 has been set as a default option for Views in this Platform, but the required InteropBroker APIs for FDC3 2.0 compliance have not all been overridden.\nThe following APIs need to be overridden:\n${notOverridden.join('\n')}`); + } + } + } + overrideCheck.overrideCheck = overrideCheck$1; + return overrideCheck; +} + +var hasRequiredFactory; + +function requireFactory () { + if (hasRequiredFactory) return Factory$1; + hasRequiredFactory = 1; + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + Object.defineProperty(Factory$1, "__esModule", { value: true }); + Factory$1.InteropModule = void 0; + const cloneDeep_1 = __importDefault(require$$0$1); + const inaccessibleObject_1 = inaccessibleObject; + const base_1 = base; + const InteropBroker_1 = requireInteropBroker(); + const InteropClient_1 = requireInteropClient(); + const overrideCheck_1 = requireOverrideCheck(); + const common_utils_1 = commonUtils; + const defaultOverride = (Class) => new Class(); + const BrokerParamAccessError = 'You have attempted to use or modify InteropBroker parameters, which is not allowed. You are likely using an older InteropBroker override scheme. Please consult our Interop docs for guidance on migrating to the new override scheme.'; + /** + * Manages creation of Interop Brokers and Interop Clients. These APIs are called under-the-hood in Platforms. + * + */ + class InteropModule extends base_1.Base { + /** + * Initializes an Interop Broker. This is called under-the-hood for Platforms. + * + * @remarks For Platforms, this is set up automatically. We advise to only create your own Interop Broker + * when not using a Platform app. You can override functions in the Interop Broker. More info {@link InteropBroker here}. + * + * @param name - Name of the Interop Broker. + * @param override - A callback function or array of callback functions that can be used to extend or replace default Interop Broker behavior. + * + * @example + * ``` js + * const interopBroker = await fin.Interop.init('openfin'); + * const contextGroups = await interopBroker.getContextGroups(); + * console.log(contextGroups); + * ``` + */ + async init(name, override = defaultOverride) { + this.wire.sendAction('interop-init').catch(() => { + // don't expose, analytics-only call + }); + // Allows for manifest-level configuration, without having to override. (e.g. specifying custom context groups) + const options = await this.wire.environment.getInteropInfo(this.wire.getFin()); + const objectThatThrows = (0, inaccessibleObject_1.createUnusableObject)(BrokerParamAccessError); + const warningOptsClone = (0, inaccessibleObject_1.createWarningObject)(BrokerParamAccessError, (0, cloneDeep_1.default)(options)); + const getProvider = () => { + return this.fin.InterApplicationBus.Channel.create(`interop-broker-${name}`); + }; + const throwingGetProvider = async () => { + // eslint-disable-next-line no-console + throw new Error(BrokerParamAccessError); + }; + const OverrideableBroker = InteropBroker_1.InteropBroker.createClosedConstructor(this.wire, getProvider, options); + let broker; + if (Array.isArray(override)) { + const BrokerConstructor = (0, common_utils_1.overrideFromComposables)(...override)(OverrideableBroker); + // We need to use these objects because removing them entirely would be a breaking change and we want an informative error + // @ts-expect-error + broker = new BrokerConstructor(objectThatThrows, throwingGetProvider, warningOptsClone); + } + else { + // We need to use these objects because removing them entirely would be a breaking change and we want an informative error + // @ts-expect-error + broker = await override(OverrideableBroker, objectThatThrows, throwingGetProvider, warningOptsClone); + } + (0, overrideCheck_1.overrideCheck)(broker, options.fdc3Version); + return broker; + } + /** + * Connects a client to an Interop broker. This is called under-the-hood for Views in a Platform. + * + * @remarks + * @param name - The name of the Interop Broker to connect to. For Platforms, this will default to the uuid of the Platform. + * @param interopConfig - Information relevant to the Interop Broker. Typically a declaration of + * what context(s) the entity wants to subscribe to, and the current Context Group of the entity. + * + * @example + * ```js + * const interopConfig = { + * currentContextGroup: 'green' + * } + * + * const interopBroker = await fin.Interop.init('openfin'); + * const client = await fin.Interop.connectSync('openfin', interopConfig); + * const contextGroupInfo = await client.getInfoForContextGroup(); + * console.log(contextGroupInfo); + * ``` + */ + connectSync(name, interopConfig) { + this.wire.sendAction('interop-connect-sync').catch(() => { + // don't expose, analytics-only call + }); + return new InteropClient_1.InteropClient(this.wire, this.wire.environment.whenReady().then(() => { + return this.fin.InterApplicationBus.Channel.connect(`interop-broker-${name}`, { + payload: interopConfig + }); + })); + } + } + Factory$1.InteropModule = InteropModule; + return Factory$1; +} + +var hasRequiredInterop; + +function requireInterop () { + if (hasRequiredInterop) return interop; + hasRequiredInterop = 1; + (function (exports) { + /** + * Entry point for the OpenFin `Interop` API (`fin.Interop`). + * + * * {@link InteropModule} contains static members of the `Interop` API (available under `fin.Interop`) + * * {@link InteropClient} and {@link InteropBroker} document instances of their respective classes. + * + * @packageDocumentation + */ + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(requireFactory(), exports); + __exportStar(requireInteropClient(), exports); + __exportStar(requireInteropBroker(), exports); + } (interop)); + return interop; +} + +var snapshotSource = {}; + +var Factory = {}; + +var Instance = {}; + +var utils = {}; + +Object.defineProperty(utils, "__esModule", { value: true }); +utils.getSnapshotSourceChannelName = void 0; +const channelPrefix = 'snapshot-source-provider-'; +const getSnapshotSourceChannelName = (id) => `${channelPrefix}${id.uuid}`; +utils.getSnapshotSourceChannelName = getSnapshotSourceChannelName; + +var __classPrivateFieldSet$1 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet$1 = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _SnapshotSource_identity, _SnapshotSource_getConnection, _SnapshotSource_getClient, _SnapshotSource_startConnection, _SnapshotSource_setUpConnectionListener; +Object.defineProperty(Instance, "__esModule", { value: true }); +Instance.SnapshotSource = void 0; +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +const base_1$1 = base; +const utils_1$1 = utils; +const connectionMap = new Map(); +/** + * Enables configuring a SnapshotSource with custom getSnapshot and applySnapshot methods. + * + * @typeParam Snapshot Implementation-defined shape of an application snapshot. Allows + * custom snapshot implementations for legacy applications to define their own snapshot format. + */ +class SnapshotSource extends base_1$1.Base { + /** + * @internal + */ + constructor(wire, id) { + super(wire); + _SnapshotSource_identity.set(this, void 0); + _SnapshotSource_getConnection.set(this, () => { + if (!connectionMap.has(this.identity.uuid)) { + connectionMap.set(this.identity.uuid, { eventFired: null, clientPromise: null }); + } + return connectionMap.get(this.identity.uuid); + }); + _SnapshotSource_getClient.set(this, () => { + if (!__classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).clientPromise) { + __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).clientPromise = __classPrivateFieldGet$1(this, _SnapshotSource_startConnection, "f").call(this); + } + return __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).clientPromise; + }); + _SnapshotSource_startConnection.set(this, async () => { + const channelName = (0, utils_1$1.getSnapshotSourceChannelName)(this.identity); + try { + if (!__classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).eventFired) { + await __classPrivateFieldGet$1(this, _SnapshotSource_setUpConnectionListener, "f").call(this); + } + const client = await this.fin.InterApplicationBus.Channel.connect(channelName, { wait: false }); + client.onDisconnection(() => { + __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).clientPromise = null; + __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).eventFired = null; + }); + return client; + } + catch (e) { + __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).clientPromise = null; + throw new Error("The targeted SnapshotSource is not currently initialized. Await this object's ready() method."); + } + }); + _SnapshotSource_setUpConnectionListener.set(this, async () => { + const channelName = (0, utils_1$1.getSnapshotSourceChannelName)(this.identity); + let resolve; + let reject; + const eventFired = new Promise((y, n) => { + resolve = y; + reject = n; + }); + __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).eventFired = eventFired; + const listener = async (e) => { + try { + if (e.channelName === channelName) { + resolve(); + await this.fin.InterApplicationBus.Channel.removeListener('connected', listener); + } + } + catch (err) { + reject(err); + } + }; + await this.fin.InterApplicationBus.Channel.on('connected', listener); + }); + __classPrivateFieldSet$1(this, _SnapshotSource_identity, id, "f"); + } + get identity() { + return __classPrivateFieldGet$1(this, _SnapshotSource_identity, "f"); + } + /** + * Method to determine if the SnapshotSource has been initialized. + * + * @remarks Use when the parent application is starting up to ensure the SnapshotSource is able to accept and + * apply a snapshot using the {@link SnapshotSource#applySnapshot applySnapshot} method. + * + * @example + * ```js + * let snapshotSource = fin.SnapshotSource.wrapSync(fin.me); + * + * const snapshotProvider = { + * async getSnapshot() { return 'foo' }, + * async applySnapshot(snapshot) { + * console.log(snapshot); + * return undefined; + * } + * } + * await fin.SnapshotSource.init(snapshotProvider); + * + * try { + * await snapshotSource.ready(); + * await snapshotSource.applySnapshot('foo'); + * } catch (err) { + * console.log(err) + * } + * ``` + */ + async ready() { + this.wire.sendAction('snapshot-source-ready').catch((e) => { + // don't expose, analytics-only call + }); + // eslint-disable-next-line no-async-promise-executor + try { + // If getClient was already called before this, do we have a timing issue where the channel might have been created but we missed the event but this still fails? + await __classPrivateFieldGet$1(this, _SnapshotSource_getClient, "f").call(this); + } + catch (e) { + // it was not running. + await __classPrivateFieldGet$1(this, _SnapshotSource_getConnection, "f").call(this).eventFired; + } + } + /** + * Call the SnapshotSource's getSnapshot method defined by {@link SnapshotSource.SnapshotSourceModule#init init}. + * + */ + async getSnapshot() { + this.wire.sendAction('snapshot-source-get-snapshot').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet$1(this, _SnapshotSource_getClient, "f").call(this); + const response = (await client.dispatch('get-snapshot')); + return (await response).snapshot; + } + /** + * Call the SnapshotSource's applySnapshot method defined by {@link SnapshotSource.SnapshotSourceModule#init init}. + * + */ + async applySnapshot(snapshot) { + this.wire.sendAction('snapshot-source-apply-snapshot').catch((e) => { + // don't expose, analytics-only call + }); + const client = await __classPrivateFieldGet$1(this, _SnapshotSource_getClient, "f").call(this); + return client.dispatch('apply-snapshot', { snapshot }); + } +} +Instance.SnapshotSource = SnapshotSource; +_SnapshotSource_identity = new WeakMap(), _SnapshotSource_getConnection = new WeakMap(), _SnapshotSource_getClient = new WeakMap(), _SnapshotSource_startConnection = new WeakMap(), _SnapshotSource_setUpConnectionListener = new WeakMap(); + +Object.defineProperty(Factory, "__esModule", { value: true }); +Factory.SnapshotSourceModule = void 0; +const base_1 = base; +const Instance_1 = Instance; +const utils_1 = utils; +/** + * Static namespace for OpenFin API methods that interact with the {@link SnapshotSource} class, available under `fin.SnapshotSource`. + */ +class SnapshotSourceModule extends base_1.Base { + /** + * Initializes a SnapshotSource with the getSnapshot and applySnapshot methods defined. + * + * @typeParam Snapshot Implementation-defined shape of an application snapshot. Allows + * custom snapshot implementations for legacy applications to define their own snapshot format. + * + * @example + * ```js + * const snapshotProvider = { + * async getSnapshot() { + * const bounds = await fin.me.getBounds(); + * return bounds; + * }, + * async applySnapshot(snapshot) { + * await fin.me.setBounds(snapshot); + * return undefined; + * } + * } + * + * await fin.SnapshotSource.init(snapshotProvider); + * ``` + * + */ + async init(provider) { + this.wire.sendAction('snapshot-source-init').catch((e) => { + // don't expose, analytics-only call + }); + if (typeof provider !== 'object' || + typeof provider.getSnapshot !== 'function' || + typeof provider.applySnapshot !== 'function') { + throw new Error('you must pass in a valid SnapshotProvider'); + } + const channel = await this.fin.InterApplicationBus.Channel.create((0, utils_1.getSnapshotSourceChannelName)(this.fin.me)); + channel.register('get-snapshot', async () => { + const snapshot = await provider.getSnapshot(); + return { snapshot }; + }); + channel.register('apply-snapshot', ({ snapshot }) => provider.applySnapshot(snapshot)); + } + /** + * Synchronously returns a SnapshotSource object that represents the current SnapshotSource. + * + * @example + * ```js + * const snapshotSource = fin.SnapshotSource.wrapSync(fin.me); + * // Use wrapped instance's getSnapshot method, e.g.: + * const snapshot = await snapshotSource.getSnapshot(); + * ``` + */ + wrapSync(identity) { + this.wire.sendAction('snapshot-source-wrap-sync').catch((e) => { + // don't expose, analytics-only call + }); + return new Instance_1.SnapshotSource(this.wire, identity); + } + /** + * Asynchronously returns a SnapshotSource object that represents the current SnapshotSource. + * + * @example + * ```js + * const snapshotSource = await fin.SnapshotSource.wrap(fin.me); + * // Use wrapped instance's getSnapshot method, e.g.: + * const snapshot = await snapshotSource.getSnapshot(); + * ``` + */ + async wrap(identity) { + this.wire.sendAction('snapshot-source-wrap').catch((e) => { + // don't expose, analytics-only call + }); + return this.wrapSync(identity); + } +} +Factory.SnapshotSourceModule = SnapshotSourceModule; + +(function (exports) { + /** + * Entry points for the OpenFin `SnapshotSource` API (`fin.SnapshotSource`). + * + * * {@link SnapshotSourceModule} contains static members of the `SnapshotSource` API, accessible through `fin.SnapshotSource`. + * * {@link SnapshotSource} describes an instance of an OpenFin SnapshotSource, e.g. as returned by `fin.SnapshotSource.wrap`. + * + * These are separate code entities, and are documented separately. In the [previous version of the API documentation](https://cdn.openfin.co/docs/javascript/32.114.76.10/index.html), + * both of these were documented on the same page. + * + * @packageDocumentation + */ + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + __exportStar(Factory, exports); + __exportStar(Instance, exports); +} (snapshotSource)); + +Object.defineProperty(fin$2, "__esModule", { value: true }); +var Fin_1 = fin$2.Fin = void 0; +const events_1$3 = require$$0; +// Import from the file rather than the directory in case someone consuming types is using module resolution other than "node" +const index_1 = system; +const index_2 = requireWindow(); +const index_3 = requireApplication(); +const index_4 = interappbus; +const index_5 = clipboard; +const index_6 = externalApplication; +const index_7 = frame; +const index_8 = globalHotkey; +const index_9 = requireView(); +const index_10 = platform; +const me_1$2 = me; +const interop_1 = requireInterop(); +const snapshot_source_1 = snapshotSource; +/** + * @internal + */ +class Fin extends events_1$3.EventEmitter { + /** + * @internal + */ + constructor(wire) { + super(); + this.wire = wire; + this.System = new index_1.System(wire); + this.Window = new index_2._WindowModule(wire); + this.Application = new index_3.ApplicationModule(wire); + this.InterApplicationBus = new index_4.InterApplicationBus(wire); + this.Clipboard = new index_5.Clipboard(wire); + this.ExternalApplication = new index_6.ExternalApplicationModule(wire); + this.Frame = new index_7._FrameModule(wire); + this.GlobalHotkey = new index_8.GlobalHotkey(wire); + this.Platform = new index_10.PlatformModule(wire, this.InterApplicationBus.Channel); + this.View = new index_9.ViewModule(wire); + this.Interop = new interop_1.InteropModule(wire); + this.SnapshotSource = new snapshot_source_1.SnapshotSourceModule(wire); + wire.registerFin(this); + this.me = (0, me_1$2.getMe)(wire); + // Handle disconnect events + wire.on('disconnected', () => { + this.emit('disconnected'); + }); + } +} +Fin_1 = fin$2.Fin = Fin; + +var transport = {}; + +var wire = {}; + +Object.defineProperty(wire, "__esModule", { value: true }); +wire.isInternalConnectConfig = wire.isPortDiscoveryConfig = wire.isNewConnectConfig = wire.isConfigWithReceiver = wire.isRemoteConfig = wire.isExistingConnectConfig = wire.isExternalConfig = void 0; +function isExternalConfig(config) { + if (typeof config.manifestUrl === 'string') { + return true; + } + return false; +} +wire.isExternalConfig = isExternalConfig; +function isExistingConnectConfig(config) { + return hasUuid(config) && typeof config.address === 'string'; +} +wire.isExistingConnectConfig = isExistingConnectConfig; +function isRemoteConfig(config) { + return isExistingConnectConfig(config) && typeof config.token === 'string'; +} +wire.isRemoteConfig = isRemoteConfig; +function isConfigWithReceiver(config) { + return typeof config.receiver === 'object' && isRemoteConfig({ ...config, address: '' }); +} +wire.isConfigWithReceiver = isConfigWithReceiver; +function hasUuid(config) { + return typeof config.uuid === 'string'; +} +function hasRuntimeVersion(config) { + return config.runtime && typeof config.runtime.version === 'string'; +} +function isNewConnectConfig(config) { + return hasUuid(config) && hasRuntimeVersion(config); +} +wire.isNewConnectConfig = isNewConnectConfig; +function isPortDiscoveryConfig(config) { + return (isExternalConfig(config) && hasRuntimeVersion(config)) || isNewConnectConfig(config); +} +wire.isPortDiscoveryConfig = isPortDiscoveryConfig; +function isInternalConnectConfig(config) { + return isExistingConnectConfig(config) || isNewConnectConfig(config); +} +wire.isInternalConnectConfig = isInternalConnectConfig; + +var eventAggregator = {}; + +var emitterMap = {}; + +Object.defineProperty(emitterMap, "__esModule", { value: true }); +emitterMap.EmitterMap = void 0; +const events_1$2 = require$$0; +class EmitterMap { + constructor() { + this.storage = new Map(); + } + // eslint-disable-next-line class-methods-use-this + hashKeys(keys) { + const hashed = keys.map(normalizeString); + return hashed.join('/'); + } + getOrCreate(keys) { + const hash = this.hashKeys(keys); + if (!this.storage.has(hash)) { + this.storage.set(hash, new events_1$2.EventEmitter()); + } + // We set it above + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return this.storage.get(hash); + } + has(keys) { + return this.storage.has(this.hashKeys(keys)); + } + delete(keys) { + const hash = this.hashKeys(keys); + return this.storage.delete(hash); + } +} +emitterMap.EmitterMap = EmitterMap; +function normalizeString(s) { + const b = Buffer.from(s); + return b.toString('base64'); +} + +Object.defineProperty(eventAggregator, "__esModule", { value: true }); +const emitterMap_1 = emitterMap; +function isEventMessage(message) { + return message.action === 'process-desktop-event'; +} +function mapKeyFromEvent(event) { + const { topic } = event; + if (topic === 'frame' || topic === 'window' || topic === 'view') { + const { uuid, name } = event; + return [topic, uuid, name]; + } + if (topic === 'application') { + const { uuid } = event; + return [topic, uuid]; + } + return [topic]; +} +class EventAggregator extends emitterMap_1.EmitterMap { + constructor() { + super(...arguments); + this.dispatchEvent = (message) => { + if (isEventMessage(message)) { + const { payload } = message; + const accessor = mapKeyFromEvent(payload); + if (this.has(accessor)) { + this.getOrCreate(accessor).emit(payload.type, payload); + return true; + } + } + return false; + }; + } +} +eventAggregator.default = EventAggregator; + +var __classPrivateFieldSet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (commonjsGlobal && commonjsGlobal.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _Transport_wire, _Transport_fin; +Object.defineProperty(transport, "__esModule", { value: true }); +var Transport_1 = transport.Transport = void 0; +const events_1$1 = require$$0; +const wire_1 = wire; +const transport_errors_1 = transportErrors; +const eventAggregator_1 = __importDefault(eventAggregator); +const me_1$1 = me; +const errors_1 = errors; +class Transport extends events_1$1.EventEmitter { + constructor(WireType, environment, config) { + super(); + this.wireListeners = new Map(); + this.topicRefMap = new Map(); + this.eventAggregator = new eventAggregator_1.default(); + this.messageHandlers = [this.eventAggregator.dispatchEvent]; + _Transport_wire.set(this, void 0); + // Typing as unknown to avoid circular dependency, should not be used directly. + _Transport_fin.set(this, void 0); + this.connectSync = () => { + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + wire.connectSync(); + }; + // This function is only used in our tests. + this.getPort = () => { + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + return wire.getPort(); + }; + __classPrivateFieldSet(this, _Transport_wire, new WireType(this.onmessage.bind(this)), "f"); + this.environment = environment; + this.sendRaw = __classPrivateFieldGet(this, _Transport_wire, "f").send.bind(__classPrivateFieldGet(this, _Transport_wire, "f")); + this.registerMessageHandler(this.handleMessage.bind(this)); + __classPrivateFieldGet(this, _Transport_wire, "f").on('disconnected', () => { + for (const [, { handleNack }] of this.wireListeners) { + handleNack({ reason: 'Remote connection has closed' }); + } + this.wireListeners.clear(); + this.emit('disconnected'); + }); + const { uuid, name } = config; + const entityType = this.environment.getCurrentEntityType(); + this.me = (0, me_1$1.getBaseMe)(entityType, uuid, name); + } + getFin() { + if (!__classPrivateFieldGet(this, _Transport_fin, "f")) { + throw new Error('No Fin object registered for this transport'); + } + return __classPrivateFieldGet(this, _Transport_fin, "f"); + } + registerFin(_fin) { + if (__classPrivateFieldGet(this, _Transport_fin, "f")) { + throw new Error('Fin object has already been registered for this transport'); + } + __classPrivateFieldSet(this, _Transport_fin, _fin, "f"); + } + shutdown() { + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + return wire.shutdown(); + } + async connect(config) { + if ((0, wire_1.isConfigWithReceiver)(config)) { + await __classPrivateFieldGet(this, _Transport_wire, "f").connect(config.receiver); + return this.authorize(config); + } + if ((0, wire_1.isRemoteConfig)(config)) { + return this.connectRemote(config); + } + if ((0, wire_1.isExistingConnectConfig)(config)) { + return this.connectByPort(config); + } + if ((0, wire_1.isNewConnectConfig)(config)) { + const port = await this.environment.retrievePort(config); + return this.connectByPort({ ...config, address: `ws://localhost:${port}` }); + } + return undefined; + } + async connectRemote(config) { + await __classPrivateFieldGet(this, _Transport_wire, "f").connect(new (this.environment.getWsConstructor())(config.address)); + return this.authorize(config); + } + async connectByPort(config) { + const { address, uuid } = config; + const reqAuthPayload = { ...config, type: 'file-token' }; + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + await wire.connect(new (this.environment.getWsConstructor())(config.address)); + const requestExtAuthRet = await this.sendAction('request-external-authorization', { + uuid, + type: 'file-token' + }, true); + if (requestExtAuthRet.action !== 'external-authorization-response') { + throw new transport_errors_1.UnexpectedActionError(requestExtAuthRet.action); + } + await this.environment.writeToken(requestExtAuthRet.payload.file, requestExtAuthRet.payload.token); + return this.authorize(reqAuthPayload); + } + async authorize(reqAuthPayload) { + const requestAuthRet = await this.sendAction('request-authorization', reqAuthPayload, true); + if (requestAuthRet.action !== 'authorization-response') { + throw new transport_errors_1.UnexpectedActionError(requestAuthRet.action); + } + else if (requestAuthRet.payload.success !== true) { + throw new transport_errors_1.RuntimeError(requestAuthRet.payload); + } + } + sendAction(action, payload = {}, uncorrelated = false + // specialResponse type is only used for 'requestAuthorization' + ) { + // eslint-disable-next-line @typescript-eslint/no-empty-function + let cancel = () => { }; + // We want the callsite from the caller of this function, not from here. + const callSites = transport_errors_1.RuntimeError.getCallSite(1); + const messageId = this.environment.getNextMessageId(); + const prom = new Promise((resolve, reject) => { + cancel = reject; + const msg = { + action, + payload, + messageId + }; + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + this.addWireListener(messageId, resolve, (payload) => this.nackHandler(payload, reject, callSites), uncorrelated); + return wire.send(msg).catch(reject); + }); + return Object.assign(prom, { cancel, messageId }); + } + nackHandler(payloadOrMessage, reject, callSites) { + if (typeof payloadOrMessage === 'string') { + // NOTE: this is for backwards compatibility to support plain string rejections + reject(payloadOrMessage); + } + else { + reject(new transport_errors_1.RuntimeError(payloadOrMessage, callSites)); + } + } + ferryAction(origData) { + return new Promise((resolve, reject) => { + const id = this.environment.getNextMessageId(); + origData.messageId = id; + const resolver = (data) => { + resolve(data.payload); + }; + const wire = __classPrivateFieldGet(this, _Transport_wire, "f"); + return wire + .send(origData) + .then(() => this.addWireListener(id, resolver, (payload) => this.nackHandler(payload, reject), false)) + .catch(reject); + }); + } + registerMessageHandler(handler) { + this.messageHandlers.push(handler); + } + addWireListener(id, resolve, handleNack, uncorrelated) { + if (uncorrelated) { + this.uncorrelatedListener = resolve; + } + else if (this.wireListeners.has(id)) { + handleNack({ + reason: 'Duplicate handler id', + error: (0, errors_1.errorToPOJO)(new transport_errors_1.DuplicateCorrelationError(String(id))) + }); + } + else { + this.wireListeners.set(id, { resolve, handleNack }); + } + // Timeout and reject()? + } + // This method executes message handlers until the _one_ that handles the message (returns truthy) has run + onmessage(data) { + for (const h of this.messageHandlers) { + h.call(null, data); + } + } + handleMessage(data) { + const id = data.correlationId || NaN; + if (!('correlationId' in data)) { + if (this.uncorrelatedListener) { + this.uncorrelatedListener.call(null, data); + } + this.uncorrelatedListener = () => { + // empty block + }; + } + else if (!this.wireListeners.has(id)) { + return false; + } + else { + // We just checked for existence above + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const { resolve, handleNack } = this.wireListeners.get(id); + if (data.action !== 'ack') { + handleNack({ reason: 'Did not receive ack action', error: (0, errors_1.errorToPOJO)(new transport_errors_1.NoAckError(data.action)) }); + } + else if (!('payload' in data)) { + // I'm not sure when this code would actually run, but passing in something that doeesn't have a reason to the runtimeerror constructor will not end well. + // @ts-expect-error + if (typeof data.reason === 'string') { + handleNack(data); + } + else { + console.warn('Received invalid response from core', data); + handleNack({ reason: 'invalid response shape' }); + } + } + else if (!data.payload.success) { + handleNack(data.payload); + } + else { + resolve.call(null, data); + } + this.wireListeners.delete(id); + } + return true; + } +} +Transport_1 = transport.Transport = Transport; +_Transport_wire = new WeakMap(), _Transport_fin = new WeakMap(); + +var mockEnvironment = {}; + +Object.defineProperty(mockEnvironment, "__esModule", { value: true }); +var MockEnvironment_1 = mockEnvironment.MockEnvironment = void 0; +const me_1 = me; +class MockEnvironment { + constructor() { + this.type = 'other'; + this.childViews = true; + } + getAdapterVersionSync() { + throw new Error(me_1.environmentUnsupportedMessage); + } + async getInteropInfo() { + throw new Error(me_1.environmentUnsupportedMessage); + } + getDefaultChannelOptions() { + throw new Error(me_1.environmentUnsupportedMessage); + } + getRtcPeer() { + throw new Error(me_1.environmentUnsupportedMessage); + } + layoutAllowedInContext(_fin) { + throw new Error(me_1.environmentUnsupportedMessage); + } + initLayoutManager() { + throw new Error(me_1.environmentUnsupportedMessage); + } + applyLayoutSnapshot() { + throw new Error(me_1.environmentUnsupportedMessage); + } + async createLayout() { + throw new Error(me_1.environmentUnsupportedMessage); + } + async destroyLayout() { + throw new Error(me_1.environmentUnsupportedMessage); + } + async resolveLayout() { + throw new Error(me_1.environmentUnsupportedMessage); + } + initPlatform() { + throw new Error(me_1.environmentUnsupportedMessage); + } + observeBounds() { + throw new Error(me_1.environmentUnsupportedMessage); + } + writeToken(path, token) { + throw new Error(me_1.environmentUnsupportedMessage); + } + retrievePort(config) { + throw new Error(me_1.environmentUnsupportedMessage); + } + getNextMessageId() { + return `mock-message-id-${Math.random()}`; + } + getRandomId() { + throw new Error(me_1.environmentUnsupportedMessage); + } + createChildContent(options) { + throw new Error(me_1.environmentUnsupportedMessage); + } + getWebWindow(identity) { + throw new Error(me_1.environmentUnsupportedMessage); + } + getCurrentEntityIdentity() { + throw new Error(me_1.environmentUnsupportedMessage); + } + getCurrentEntityType() { + return 'unknown'; + } + raiseEvent(eventName, eventArgs) { + throw new Error(me_1.environmentUnsupportedMessage); + } + getUrl() { + throw new Error(me_1.environmentUnsupportedMessage); + } + whenReady() { + throw new Error(me_1.environmentUnsupportedMessage); + } + getWsConstructor() { + throw new Error('Method not implemented.'); + } +} +MockEnvironment_1 = mockEnvironment.MockEnvironment = MockEnvironment; + +var mockWire = {}; + +Object.defineProperty(mockWire, "__esModule", { value: true }); +var MockWire_1 = mockWire.MockWire = void 0; +/* eslint-disable @typescript-eslint/no-unused-vars */ +const events_1 = require$$0; +class MockWire extends events_1.EventEmitter { + connect() { + throw new Error('You are not running in OpenFin.'); + } + connectSync() { + throw new Error('You are not running in OpenFin.'); + } + send(data) { + throw new Error('You are not running in OpenFin.'); + } + shutdown() { + throw new Error('You are not running in OpenFin.'); + } + getPort() { + throw new Error('This transport has no port'); + } + // eslint-disable-next-line no-useless-constructor + constructor() { + super(); + } +} +MockWire_1 = mockWire.MockWire = MockWire; + +const fin$1 = ((typeof window !== 'undefined' && window?.fin) || + (() => { + const environment = new MockEnvironment_1(); + const transport = new Transport_1(MockWire_1, environment, { + uuid: '', + name: '' + }); + return new Fin_1(transport); + })()); + +exports.OpenFin = OpenFin$1; +exports["default"] = OpenFin$1; +exports.fin = fin$1; + + +/***/ }), + +/***/ "../../../node_modules/events/events.js": +/*!**********************************************!*\ + !*** ../../../node_modules/events/events.js ***! + \**********************************************/ +/***/ ((module) => { + +"use strict"; +// 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. + + + +var R = typeof Reflect === 'object' ? Reflect : null +var ReflectApply = R && typeof R.apply === 'function' + ? R.apply + : function ReflectApply(target, receiver, args) { + return Function.prototype.apply.call(target, receiver, args); + } + +var ReflectOwnKeys +if (R && typeof R.ownKeys === 'function') { + ReflectOwnKeys = R.ownKeys +} else if (Object.getOwnPropertySymbols) { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target) + .concat(Object.getOwnPropertySymbols(target)); + }; +} else { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target); + }; +} + +function ProcessEmitWarning(warning) { + if (console && console.warn) console.warn(warning); +} + +var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { + return value !== value; +} + +function EventEmitter() { + EventEmitter.init.call(this); +} +module.exports = EventEmitter; +module.exports.once = once; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._eventsCount = 0; +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. +var defaultMaxListeners = 10; + +function checkListener(listener) { + if (typeof listener !== 'function') { + throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); + } +} + +Object.defineProperty(EventEmitter, 'defaultMaxListeners', { + enumerable: true, + get: function() { + return defaultMaxListeners; + }, + set: function(arg) { + if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { + throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); + } + defaultMaxListeners = arg; + } +}); + +EventEmitter.init = function() { + + if (this._events === undefined || + this._events === Object.getPrototypeOf(this)._events) { + this._events = Object.create(null); + this._eventsCount = 0; + } + + this._maxListeners = this._maxListeners || undefined; +}; + +// 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 setMaxListeners(n) { + if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { + throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); + } + this._maxListeners = n; + return this; +}; + +function _getMaxListeners(that) { + if (that._maxListeners === undefined) + return EventEmitter.defaultMaxListeners; + return that._maxListeners; +} + +EventEmitter.prototype.getMaxListeners = function getMaxListeners() { + return _getMaxListeners(this); +}; + +EventEmitter.prototype.emit = function emit(type) { + var args = []; + for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); + var doError = (type === 'error'); + + var events = this._events; + if (events !== undefined) + doError = (doError && events.error === undefined); + else if (!doError) + return false; + + // If there is no 'error' event listener then throw. + if (doError) { + var er; + if (args.length > 0) + er = args[0]; + if (er instanceof Error) { + // Note: The comments on the `throw` lines are intentional, they show + // up in Node's output if this results in an unhandled exception. + throw er; // Unhandled 'error' event + } + // At least give some kind of context to the user + var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); + err.context = er; + throw err; // Unhandled 'error' event + } + + var handler = events[type]; + + if (handler === undefined) + return false; + + if (typeof handler === 'function') { + ReflectApply(handler, this, args); + } else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + ReflectApply(listeners[i], this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + checkListener(listener); + + events = target._events; + if (events === undefined) { + events = target._events = Object.create(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener !== undefined) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (existing === undefined) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + // If we've already got an array, just append. + } else if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + + // Check for listener leak + m = _getMaxListeners(target); + if (m > 0 && existing.length > m && !existing.warned) { + existing.warned = true; + // No error code for this since it is a Warning + // eslint-disable-next-line no-restricted-syntax + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' ' + String(type) + ' listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + ProcessEmitWarning(w); + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + if (arguments.length === 0) + return this.listener.call(this.target); + return this.listener.apply(this.target, arguments); + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = onceWrapper.bind(state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + checkListener(listener); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + checkListener(listener); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + checkListener(listener); + + events = this._events; + if (events === undefined) + return this; + + list = events[type]; + if (list === undefined) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else { + spliceOne(list, position); + } + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener !== undefined) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (events === undefined) + return this; + + // not listening for removeListener, no need to emit + if (events.removeListener === undefined) { + if (arguments.length === 0) { + this._events = Object.create(null); + this._eventsCount = 0; + } else if (events[type] !== undefined) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = Object.keys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = Object.create(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners !== undefined) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (events === undefined) + return []; + + var evlistener = events[type]; + if (evlistener === undefined) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? + unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events !== undefined) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener !== undefined) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; +}; + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function spliceOne(list, index) { + for (; index + 1 < list.length; index++) + list[index] = list[index + 1]; + list.pop(); +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function once(emitter, name) { + return new Promise(function (resolve, reject) { + function errorListener(err) { + emitter.removeListener(name, resolver); + reject(err); + } + + function resolver() { + if (typeof emitter.removeListener === 'function') { + emitter.removeListener('error', errorListener); + } + resolve([].slice.call(arguments)); + }; + + eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); + if (name !== 'error') { + addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); + } + }); +} + +function addErrorHandlerIfEventEmitter(emitter, handler, flags) { + if (typeof emitter.on === 'function') { + eventTargetAgnosticAddListener(emitter, 'error', handler, flags); + } +} + +function eventTargetAgnosticAddListener(emitter, name, listener, flags) { + if (typeof emitter.on === 'function') { + if (flags.once) { + emitter.once(name, listener); + } else { + emitter.on(name, listener); + } + } else if (typeof emitter.addEventListener === 'function') { + // EventTarget does not have `error` event semantics like Node + // EventEmitters, we do not listen for `error` events here. + emitter.addEventListener(name, function wrapListener(arg) { + // IE does not have builtin `{ once: true }` support so we + // have to do it manually. + if (flags.once) { + emitter.removeEventListener(name, wrapListener); + } + listener(arg); + }); + } else { + throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter); + } +} + + +/***/ }), + +/***/ "../../../node_modules/lodash/_DataView.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_DataView.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../../node_modules/lodash/_getNative.js"), + root = __webpack_require__(/*! ./_root */ "../../../node_modules/lodash/_root.js"); + +/* Built-in method references that are verified to be native. */ +var DataView = getNative(root, 'DataView'); + +module.exports = DataView; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_Hash.js": +/*!*********************************************!*\ + !*** ../../../node_modules/lodash/_Hash.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var hashClear = __webpack_require__(/*! ./_hashClear */ "../../../node_modules/lodash/_hashClear.js"), + hashDelete = __webpack_require__(/*! ./_hashDelete */ "../../../node_modules/lodash/_hashDelete.js"), + hashGet = __webpack_require__(/*! ./_hashGet */ "../../../node_modules/lodash/_hashGet.js"), + hashHas = __webpack_require__(/*! ./_hashHas */ "../../../node_modules/lodash/_hashHas.js"), + hashSet = __webpack_require__(/*! ./_hashSet */ "../../../node_modules/lodash/_hashSet.js"); + +/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Hash(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `Hash`. +Hash.prototype.clear = hashClear; +Hash.prototype['delete'] = hashDelete; +Hash.prototype.get = hashGet; +Hash.prototype.has = hashHas; +Hash.prototype.set = hashSet; + +module.exports = Hash; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_ListCache.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_ListCache.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var listCacheClear = __webpack_require__(/*! ./_listCacheClear */ "../../../node_modules/lodash/_listCacheClear.js"), + listCacheDelete = __webpack_require__(/*! ./_listCacheDelete */ "../../../node_modules/lodash/_listCacheDelete.js"), + listCacheGet = __webpack_require__(/*! ./_listCacheGet */ "../../../node_modules/lodash/_listCacheGet.js"), + listCacheHas = __webpack_require__(/*! ./_listCacheHas */ "../../../node_modules/lodash/_listCacheHas.js"), + listCacheSet = __webpack_require__(/*! ./_listCacheSet */ "../../../node_modules/lodash/_listCacheSet.js"); + +/** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `ListCache`. +ListCache.prototype.clear = listCacheClear; +ListCache.prototype['delete'] = listCacheDelete; +ListCache.prototype.get = listCacheGet; +ListCache.prototype.has = listCacheHas; +ListCache.prototype.set = listCacheSet; + +module.exports = ListCache; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_Map.js": +/*!********************************************!*\ + !*** ../../../node_modules/lodash/_Map.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../../node_modules/lodash/_getNative.js"), + root = __webpack_require__(/*! ./_root */ "../../../node_modules/lodash/_root.js"); + +/* Built-in method references that are verified to be native. */ +var Map = getNative(root, 'Map'); + +module.exports = Map; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_MapCache.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_MapCache.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var mapCacheClear = __webpack_require__(/*! ./_mapCacheClear */ "../../../node_modules/lodash/_mapCacheClear.js"), + mapCacheDelete = __webpack_require__(/*! ./_mapCacheDelete */ "../../../node_modules/lodash/_mapCacheDelete.js"), + mapCacheGet = __webpack_require__(/*! ./_mapCacheGet */ "../../../node_modules/lodash/_mapCacheGet.js"), + mapCacheHas = __webpack_require__(/*! ./_mapCacheHas */ "../../../node_modules/lodash/_mapCacheHas.js"), + mapCacheSet = __webpack_require__(/*! ./_mapCacheSet */ "../../../node_modules/lodash/_mapCacheSet.js"); + +/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `MapCache`. +MapCache.prototype.clear = mapCacheClear; +MapCache.prototype['delete'] = mapCacheDelete; +MapCache.prototype.get = mapCacheGet; +MapCache.prototype.has = mapCacheHas; +MapCache.prototype.set = mapCacheSet; + +module.exports = MapCache; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_Promise.js": +/*!************************************************!*\ + !*** ../../../node_modules/lodash/_Promise.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../../node_modules/lodash/_getNative.js"), + root = __webpack_require__(/*! ./_root */ "../../../node_modules/lodash/_root.js"); + +/* Built-in method references that are verified to be native. */ +var Promise = getNative(root, 'Promise'); + +module.exports = Promise; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_Set.js": +/*!********************************************!*\ + !*** ../../../node_modules/lodash/_Set.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../../node_modules/lodash/_getNative.js"), + root = __webpack_require__(/*! ./_root */ "../../../node_modules/lodash/_root.js"); + +/* Built-in method references that are verified to be native. */ +var Set = getNative(root, 'Set'); + +module.exports = Set; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_SetCache.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_SetCache.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var MapCache = __webpack_require__(/*! ./_MapCache */ "../../../node_modules/lodash/_MapCache.js"), + setCacheAdd = __webpack_require__(/*! ./_setCacheAdd */ "../../../node_modules/lodash/_setCacheAdd.js"), + setCacheHas = __webpack_require__(/*! ./_setCacheHas */ "../../../node_modules/lodash/_setCacheHas.js"); + +/** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ +function SetCache(values) { + var index = -1, + length = values == null ? 0 : values.length; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } +} + +// Add methods to `SetCache`. +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; +SetCache.prototype.has = setCacheHas; + +module.exports = SetCache; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_Stack.js": +/*!**********************************************!*\ + !*** ../../../node_modules/lodash/_Stack.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var ListCache = __webpack_require__(/*! ./_ListCache */ "../../../node_modules/lodash/_ListCache.js"), + stackClear = __webpack_require__(/*! ./_stackClear */ "../../../node_modules/lodash/_stackClear.js"), + stackDelete = __webpack_require__(/*! ./_stackDelete */ "../../../node_modules/lodash/_stackDelete.js"), + stackGet = __webpack_require__(/*! ./_stackGet */ "../../../node_modules/lodash/_stackGet.js"), + stackHas = __webpack_require__(/*! ./_stackHas */ "../../../node_modules/lodash/_stackHas.js"), + stackSet = __webpack_require__(/*! ./_stackSet */ "../../../node_modules/lodash/_stackSet.js"); + +/** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; +} + +// Add methods to `Stack`. +Stack.prototype.clear = stackClear; +Stack.prototype['delete'] = stackDelete; +Stack.prototype.get = stackGet; +Stack.prototype.has = stackHas; +Stack.prototype.set = stackSet; + +module.exports = Stack; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_Symbol.js": +/*!***********************************************!*\ + !*** ../../../node_modules/lodash/_Symbol.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var root = __webpack_require__(/*! ./_root */ "../../../node_modules/lodash/_root.js"); + +/** Built-in value references. */ +var Symbol = root.Symbol; + +module.exports = Symbol; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_Uint8Array.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_Uint8Array.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var root = __webpack_require__(/*! ./_root */ "../../../node_modules/lodash/_root.js"); + +/** Built-in value references. */ +var Uint8Array = root.Uint8Array; + +module.exports = Uint8Array; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_WeakMap.js": +/*!************************************************!*\ + !*** ../../../node_modules/lodash/_WeakMap.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../../node_modules/lodash/_getNative.js"), + root = __webpack_require__(/*! ./_root */ "../../../node_modules/lodash/_root.js"); + +/* Built-in method references that are verified to be native. */ +var WeakMap = getNative(root, 'WeakMap'); + +module.exports = WeakMap; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_arrayEach.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_arrayEach.js ***! + \**************************************************/ +/***/ ((module) => { + +/** + * A specialized version of `_.forEach` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ +function arrayEach(array, iteratee) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; +} + +module.exports = arrayEach; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_arrayFilter.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_arrayFilter.js ***! + \****************************************************/ +/***/ ((module) => { + +/** + * A specialized version of `_.filter` for arrays without support for + * iteratee shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {Array} Returns the new filtered array. + */ +function arrayFilter(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length, + resIndex = 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (predicate(value, index, array)) { + result[resIndex++] = value; + } + } + return result; +} + +module.exports = arrayFilter; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_arrayLikeKeys.js": +/*!******************************************************!*\ + !*** ../../../node_modules/lodash/_arrayLikeKeys.js ***! + \******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseTimes = __webpack_require__(/*! ./_baseTimes */ "../../../node_modules/lodash/_baseTimes.js"), + isArguments = __webpack_require__(/*! ./isArguments */ "../../../node_modules/lodash/isArguments.js"), + isArray = __webpack_require__(/*! ./isArray */ "../../../node_modules/lodash/isArray.js"), + isBuffer = __webpack_require__(/*! ./isBuffer */ "../../../node_modules/lodash/isBuffer.js"), + isIndex = __webpack_require__(/*! ./_isIndex */ "../../../node_modules/lodash/_isIndex.js"), + isTypedArray = __webpack_require__(/*! ./isTypedArray */ "../../../node_modules/lodash/isTypedArray.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ +function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; +} + +module.exports = arrayLikeKeys; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_arrayPush.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_arrayPush.js ***! + \**************************************************/ +/***/ ((module) => { + +/** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ +function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} + +module.exports = arrayPush; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_arraySome.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_arraySome.js ***! + \**************************************************/ +/***/ ((module) => { + +/** + * A specialized version of `_.some` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ +function arraySome(array, predicate) { + var index = -1, + length = array == null ? 0 : array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; +} + +module.exports = arraySome; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_assignValue.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_assignValue.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseAssignValue = __webpack_require__(/*! ./_baseAssignValue */ "../../../node_modules/lodash/_baseAssignValue.js"), + eq = __webpack_require__(/*! ./eq */ "../../../node_modules/lodash/eq.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Assigns `value` to `key` of `object` if the existing value is not equivalent + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignValue(object, key, value) { + var objValue = object[key]; + if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } +} + +module.exports = assignValue; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_assocIndexOf.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_assocIndexOf.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var eq = __webpack_require__(/*! ./eq */ "../../../node_modules/lodash/eq.js"); + +/** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +module.exports = assocIndexOf; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseAssign.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_baseAssign.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var copyObject = __webpack_require__(/*! ./_copyObject */ "../../../node_modules/lodash/_copyObject.js"), + keys = __webpack_require__(/*! ./keys */ "../../../node_modules/lodash/keys.js"); + +/** + * The base implementation of `_.assign` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ +function baseAssign(object, source) { + return object && copyObject(source, keys(source), object); +} + +module.exports = baseAssign; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseAssignIn.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_baseAssignIn.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var copyObject = __webpack_require__(/*! ./_copyObject */ "../../../node_modules/lodash/_copyObject.js"), + keysIn = __webpack_require__(/*! ./keysIn */ "../../../node_modules/lodash/keysIn.js"); + +/** + * The base implementation of `_.assignIn` without support for multiple sources + * or `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ +function baseAssignIn(object, source) { + return object && copyObject(source, keysIn(source), object); +} + +module.exports = baseAssignIn; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseAssignValue.js": +/*!********************************************************!*\ + !*** ../../../node_modules/lodash/_baseAssignValue.js ***! + \********************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var defineProperty = __webpack_require__(/*! ./_defineProperty */ "../../../node_modules/lodash/_defineProperty.js"); + +/** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } +} + +module.exports = baseAssignValue; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseClone.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_baseClone.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Stack = __webpack_require__(/*! ./_Stack */ "../../../node_modules/lodash/_Stack.js"), + arrayEach = __webpack_require__(/*! ./_arrayEach */ "../../../node_modules/lodash/_arrayEach.js"), + assignValue = __webpack_require__(/*! ./_assignValue */ "../../../node_modules/lodash/_assignValue.js"), + baseAssign = __webpack_require__(/*! ./_baseAssign */ "../../../node_modules/lodash/_baseAssign.js"), + baseAssignIn = __webpack_require__(/*! ./_baseAssignIn */ "../../../node_modules/lodash/_baseAssignIn.js"), + cloneBuffer = __webpack_require__(/*! ./_cloneBuffer */ "../../../node_modules/lodash/_cloneBuffer.js"), + copyArray = __webpack_require__(/*! ./_copyArray */ "../../../node_modules/lodash/_copyArray.js"), + copySymbols = __webpack_require__(/*! ./_copySymbols */ "../../../node_modules/lodash/_copySymbols.js"), + copySymbolsIn = __webpack_require__(/*! ./_copySymbolsIn */ "../../../node_modules/lodash/_copySymbolsIn.js"), + getAllKeys = __webpack_require__(/*! ./_getAllKeys */ "../../../node_modules/lodash/_getAllKeys.js"), + getAllKeysIn = __webpack_require__(/*! ./_getAllKeysIn */ "../../../node_modules/lodash/_getAllKeysIn.js"), + getTag = __webpack_require__(/*! ./_getTag */ "../../../node_modules/lodash/_getTag.js"), + initCloneArray = __webpack_require__(/*! ./_initCloneArray */ "../../../node_modules/lodash/_initCloneArray.js"), + initCloneByTag = __webpack_require__(/*! ./_initCloneByTag */ "../../../node_modules/lodash/_initCloneByTag.js"), + initCloneObject = __webpack_require__(/*! ./_initCloneObject */ "../../../node_modules/lodash/_initCloneObject.js"), + isArray = __webpack_require__(/*! ./isArray */ "../../../node_modules/lodash/isArray.js"), + isBuffer = __webpack_require__(/*! ./isBuffer */ "../../../node_modules/lodash/isBuffer.js"), + isMap = __webpack_require__(/*! ./isMap */ "../../../node_modules/lodash/isMap.js"), + isObject = __webpack_require__(/*! ./isObject */ "../../../node_modules/lodash/isObject.js"), + isSet = __webpack_require__(/*! ./isSet */ "../../../node_modules/lodash/isSet.js"), + keys = __webpack_require__(/*! ./keys */ "../../../node_modules/lodash/keys.js"), + keysIn = __webpack_require__(/*! ./keysIn */ "../../../node_modules/lodash/keysIn.js"); + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG = 1, + CLONE_FLAT_FLAG = 2, + CLONE_SYMBOLS_FLAG = 4; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]', + weakMapTag = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values supported by `_.clone`. */ +var cloneableTags = {}; +cloneableTags[argsTag] = cloneableTags[arrayTag] = +cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = +cloneableTags[boolTag] = cloneableTags[dateTag] = +cloneableTags[float32Tag] = cloneableTags[float64Tag] = +cloneableTags[int8Tag] = cloneableTags[int16Tag] = +cloneableTags[int32Tag] = cloneableTags[mapTag] = +cloneableTags[numberTag] = cloneableTags[objectTag] = +cloneableTags[regexpTag] = cloneableTags[setTag] = +cloneableTags[stringTag] = cloneableTags[symbolTag] = +cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = +cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; +cloneableTags[errorTag] = cloneableTags[funcTag] = +cloneableTags[weakMapTag] = false; + +/** + * The base implementation of `_.clone` and `_.cloneDeep` which tracks + * traversed objects. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} bitmask The bitmask flags. + * 1 - Deep clone + * 2 - Flatten inherited properties + * 4 - Clone symbols + * @param {Function} [customizer] The function to customize cloning. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The parent object of `value`. + * @param {Object} [stack] Tracks traversed objects and their clone counterparts. + * @returns {*} Returns the cloned value. + */ +function baseClone(value, bitmask, customizer, key, object, stack) { + var result, + isDeep = bitmask & CLONE_DEEP_FLAG, + isFlat = bitmask & CLONE_FLAT_FLAG, + isFull = bitmask & CLONE_SYMBOLS_FLAG; + + if (customizer) { + result = object ? customizer(value, key, object, stack) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return copyArray(value, result); + } + } else { + var tag = getTag(value), + isFunc = tag == funcTag || tag == genTag; + + if (isBuffer(value)) { + return cloneBuffer(value, isDeep); + } + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + result = (isFlat || isFunc) ? {} : initCloneObject(value); + if (!isDeep) { + return isFlat + ? copySymbolsIn(value, baseAssignIn(result, value)) + : copySymbols(value, baseAssign(result, value)); + } + } else { + if (!cloneableTags[tag]) { + return object ? value : {}; + } + result = initCloneByTag(value, tag, isDeep); + } + } + // Check for circular references and return its corresponding clone. + stack || (stack = new Stack); + var stacked = stack.get(value); + if (stacked) { + return stacked; + } + stack.set(value, result); + + if (isSet(value)) { + value.forEach(function(subValue) { + result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); + }); + } else if (isMap(value)) { + value.forEach(function(subValue, key) { + result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + } + + var keysFunc = isFull + ? (isFlat ? getAllKeysIn : getAllKeys) + : (isFlat ? keysIn : keys); + + var props = isArr ? undefined : keysFunc(value); + arrayEach(props || value, function(subValue, key) { + if (props) { + key = subValue; + subValue = value[key]; + } + // Recursively populate clone (susceptible to call stack limits). + assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); + }); + return result; +} + +module.exports = baseClone; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseCreate.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_baseCreate.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isObject = __webpack_require__(/*! ./isObject */ "../../../node_modules/lodash/isObject.js"); + +/** Built-in value references. */ +var objectCreate = Object.create; + +/** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} proto The object to inherit from. + * @returns {Object} Returns the new object. + */ +var baseCreate = (function() { + function object() {} + return function(proto) { + if (!isObject(proto)) { + return {}; + } + if (objectCreate) { + return objectCreate(proto); + } + object.prototype = proto; + var result = new object; + object.prototype = undefined; + return result; + }; +}()); + +module.exports = baseCreate; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseGetAllKeys.js": +/*!*******************************************************!*\ + !*** ../../../node_modules/lodash/_baseGetAllKeys.js ***! + \*******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var arrayPush = __webpack_require__(/*! ./_arrayPush */ "../../../node_modules/lodash/_arrayPush.js"), + isArray = __webpack_require__(/*! ./isArray */ "../../../node_modules/lodash/isArray.js"); + +/** + * The base implementation of `getAllKeys` and `getAllKeysIn` which uses + * `keysFunc` and `symbolsFunc` to get the enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {Function} keysFunc The function to get the keys of `object`. + * @param {Function} symbolsFunc The function to get the symbols of `object`. + * @returns {Array} Returns the array of property names and symbols. + */ +function baseGetAllKeys(object, keysFunc, symbolsFunc) { + var result = keysFunc(object); + return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); +} + +module.exports = baseGetAllKeys; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseGetTag.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_baseGetTag.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Symbol = __webpack_require__(/*! ./_Symbol */ "../../../node_modules/lodash/_Symbol.js"), + getRawTag = __webpack_require__(/*! ./_getRawTag */ "../../../node_modules/lodash/_getRawTag.js"), + objectToString = __webpack_require__(/*! ./_objectToString */ "../../../node_modules/lodash/_objectToString.js"); + +/** `Object#toString` result references. */ +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); +} + +module.exports = baseGetTag; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseIsArguments.js": +/*!********************************************************!*\ + !*** ../../../node_modules/lodash/_baseIsArguments.js ***! + \********************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseGetTag = __webpack_require__(/*! ./_baseGetTag */ "../../../node_modules/lodash/_baseGetTag.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../../node_modules/lodash/isObjectLike.js"); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]'; + +/** + * The base implementation of `_.isArguments`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + */ +function baseIsArguments(value) { + return isObjectLike(value) && baseGetTag(value) == argsTag; +} + +module.exports = baseIsArguments; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseIsEqual.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_baseIsEqual.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsEqualDeep = __webpack_require__(/*! ./_baseIsEqualDeep */ "../../../node_modules/lodash/_baseIsEqualDeep.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../../node_modules/lodash/isObjectLike.js"); + +/** + * The base implementation of `_.isEqual` which supports partial comparisons + * and tracks traversed objects. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {boolean} bitmask The bitmask flags. + * 1 - Unordered comparison + * 2 - Partial comparison + * @param {Function} [customizer] The function to customize comparisons. + * @param {Object} [stack] Tracks traversed `value` and `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ +function baseIsEqual(value, other, bitmask, customizer, stack) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); +} + +module.exports = baseIsEqual; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseIsEqualDeep.js": +/*!********************************************************!*\ + !*** ../../../node_modules/lodash/_baseIsEqualDeep.js ***! + \********************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Stack = __webpack_require__(/*! ./_Stack */ "../../../node_modules/lodash/_Stack.js"), + equalArrays = __webpack_require__(/*! ./_equalArrays */ "../../../node_modules/lodash/_equalArrays.js"), + equalByTag = __webpack_require__(/*! ./_equalByTag */ "../../../node_modules/lodash/_equalByTag.js"), + equalObjects = __webpack_require__(/*! ./_equalObjects */ "../../../node_modules/lodash/_equalObjects.js"), + getTag = __webpack_require__(/*! ./_getTag */ "../../../node_modules/lodash/_getTag.js"), + isArray = __webpack_require__(/*! ./isArray */ "../../../node_modules/lodash/isArray.js"), + isBuffer = __webpack_require__(/*! ./isBuffer */ "../../../node_modules/lodash/isBuffer.js"), + isTypedArray = __webpack_require__(/*! ./isTypedArray */ "../../../node_modules/lodash/isTypedArray.js"); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + objectTag = '[object Object]'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} [stack] Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = objIsArr ? arrayTag : getTag(object), + othTag = othIsArr ? arrayTag : getTag(other); + + objTag = objTag == argsTag ? objectTag : objTag; + othTag = othTag == argsTag ? objectTag : othTag; + + var objIsObj = objTag == objectTag, + othIsObj = othTag == objectTag, + isSameTag = objTag == othTag; + + if (isSameTag && isBuffer(object)) { + if (!isBuffer(other)) { + return false; + } + objIsArr = true; + objIsObj = false; + } + if (isSameTag && !objIsObj) { + stack || (stack = new Stack); + return (objIsArr || isTypedArray(object)) + ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) + : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); + } + if (!(bitmask & COMPARE_PARTIAL_FLAG)) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + var objUnwrapped = objIsWrapped ? object.value() : object, + othUnwrapped = othIsWrapped ? other.value() : other; + + stack || (stack = new Stack); + return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); + } + } + if (!isSameTag) { + return false; + } + stack || (stack = new Stack); + return equalObjects(object, other, bitmask, customizer, equalFunc, stack); +} + +module.exports = baseIsEqualDeep; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseIsMap.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_baseIsMap.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getTag = __webpack_require__(/*! ./_getTag */ "../../../node_modules/lodash/_getTag.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../../node_modules/lodash/isObjectLike.js"); + +/** `Object#toString` result references. */ +var mapTag = '[object Map]'; + +/** + * The base implementation of `_.isMap` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + */ +function baseIsMap(value) { + return isObjectLike(value) && getTag(value) == mapTag; +} + +module.exports = baseIsMap; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseIsNative.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_baseIsNative.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isFunction = __webpack_require__(/*! ./isFunction */ "../../../node_modules/lodash/isFunction.js"), + isMasked = __webpack_require__(/*! ./_isMasked */ "../../../node_modules/lodash/_isMasked.js"), + isObject = __webpack_require__(/*! ./isObject */ "../../../node_modules/lodash/isObject.js"), + toSource = __webpack_require__(/*! ./_toSource */ "../../../node_modules/lodash/_toSource.js"); + +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + +/** Used to detect host constructors (Safari). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** Used for built-in method references. */ +var funcProto = Function.prototype, + objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ +function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = isFunction(value) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); +} + +module.exports = baseIsNative; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseIsSet.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_baseIsSet.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getTag = __webpack_require__(/*! ./_getTag */ "../../../node_modules/lodash/_getTag.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../../node_modules/lodash/isObjectLike.js"); + +/** `Object#toString` result references. */ +var setTag = '[object Set]'; + +/** + * The base implementation of `_.isSet` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + */ +function baseIsSet(value) { + return isObjectLike(value) && getTag(value) == setTag; +} + +module.exports = baseIsSet; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseIsTypedArray.js": +/*!*********************************************************!*\ + !*** ../../../node_modules/lodash/_baseIsTypedArray.js ***! + \*********************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseGetTag = __webpack_require__(/*! ./_baseGetTag */ "../../../node_modules/lodash/_baseGetTag.js"), + isLength = __webpack_require__(/*! ./isLength */ "../../../node_modules/lodash/isLength.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../../node_modules/lodash/isObjectLike.js"); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values of typed arrays. */ +var typedArrayTags = {}; +typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = +typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = +typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = +typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = +typedArrayTags[uint32Tag] = true; +typedArrayTags[argsTag] = typedArrayTags[arrayTag] = +typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = +typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = +typedArrayTags[errorTag] = typedArrayTags[funcTag] = +typedArrayTags[mapTag] = typedArrayTags[numberTag] = +typedArrayTags[objectTag] = typedArrayTags[regexpTag] = +typedArrayTags[setTag] = typedArrayTags[stringTag] = +typedArrayTags[weakMapTag] = false; + +/** + * The base implementation of `_.isTypedArray` without Node.js optimizations. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + */ +function baseIsTypedArray(value) { + return isObjectLike(value) && + isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; +} + +module.exports = baseIsTypedArray; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseKeys.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_baseKeys.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isPrototype = __webpack_require__(/*! ./_isPrototype */ "../../../node_modules/lodash/_isPrototype.js"), + nativeKeys = __webpack_require__(/*! ./_nativeKeys */ "../../../node_modules/lodash/_nativeKeys.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; +} + +module.exports = baseKeys; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseKeysIn.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_baseKeysIn.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isObject = __webpack_require__(/*! ./isObject */ "../../../node_modules/lodash/isObject.js"), + isPrototype = __webpack_require__(/*! ./_isPrototype */ "../../../node_modules/lodash/_isPrototype.js"), + nativeKeysIn = __webpack_require__(/*! ./_nativeKeysIn */ "../../../node_modules/lodash/_nativeKeysIn.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function baseKeysIn(object) { + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; + + for (var key in object) { + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + return result; +} + +module.exports = baseKeysIn; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseTimes.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_baseTimes.js ***! + \**************************************************/ +/***/ ((module) => { + +/** + * The base implementation of `_.times` without support for iteratee shorthands + * or max array length checks. + * + * @private + * @param {number} n The number of times to invoke `iteratee`. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the array of results. + */ +function baseTimes(n, iteratee) { + var index = -1, + result = Array(n); + + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} + +module.exports = baseTimes; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_baseUnary.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_baseUnary.js ***! + \**************************************************/ +/***/ ((module) => { + +/** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ +function baseUnary(func) { + return function(value) { + return func(value); + }; +} + +module.exports = baseUnary; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_cacheHas.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_cacheHas.js ***! + \*************************************************/ +/***/ ((module) => { + +/** + * Checks if a `cache` value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function cacheHas(cache, key) { + return cache.has(key); +} + +module.exports = cacheHas; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_cloneArrayBuffer.js": +/*!*********************************************************!*\ + !*** ../../../node_modules/lodash/_cloneArrayBuffer.js ***! + \*********************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Uint8Array = __webpack_require__(/*! ./_Uint8Array */ "../../../node_modules/lodash/_Uint8Array.js"); + +/** + * Creates a clone of `arrayBuffer`. + * + * @private + * @param {ArrayBuffer} arrayBuffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ +function cloneArrayBuffer(arrayBuffer) { + var result = new arrayBuffer.constructor(arrayBuffer.byteLength); + new Uint8Array(result).set(new Uint8Array(arrayBuffer)); + return result; +} + +module.exports = cloneArrayBuffer; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_cloneBuffer.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_cloneBuffer.js ***! + \****************************************************/ +/***/ ((module, exports, __webpack_require__) => { + +/* module decorator */ module = __webpack_require__.nmd(module); +var root = __webpack_require__(/*! ./_root */ "../../../node_modules/lodash/_root.js"); + +/** Detect free variable `exports`. */ +var freeExports = true && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && "object" == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? root.Buffer : undefined, + allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined; + +/** + * Creates a clone of `buffer`. + * + * @private + * @param {Buffer} buffer The buffer to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Buffer} Returns the cloned buffer. + */ +function cloneBuffer(buffer, isDeep) { + if (isDeep) { + return buffer.slice(); + } + var length = buffer.length, + result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); + + buffer.copy(result); + return result; +} + +module.exports = cloneBuffer; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_cloneDataView.js": +/*!******************************************************!*\ + !*** ../../../node_modules/lodash/_cloneDataView.js ***! + \******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var cloneArrayBuffer = __webpack_require__(/*! ./_cloneArrayBuffer */ "../../../node_modules/lodash/_cloneArrayBuffer.js"); + +/** + * Creates a clone of `dataView`. + * + * @private + * @param {Object} dataView The data view to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned data view. + */ +function cloneDataView(dataView, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; + return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); +} + +module.exports = cloneDataView; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_cloneRegExp.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_cloneRegExp.js ***! + \****************************************************/ +/***/ ((module) => { + +/** Used to match `RegExp` flags from their coerced string values. */ +var reFlags = /\w*$/; + +/** + * Creates a clone of `regexp`. + * + * @private + * @param {Object} regexp The regexp to clone. + * @returns {Object} Returns the cloned regexp. + */ +function cloneRegExp(regexp) { + var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); + result.lastIndex = regexp.lastIndex; + return result; +} + +module.exports = cloneRegExp; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_cloneSymbol.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_cloneSymbol.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Symbol = __webpack_require__(/*! ./_Symbol */ "../../../node_modules/lodash/_Symbol.js"); + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined; + +/** + * Creates a clone of the `symbol` object. + * + * @private + * @param {Object} symbol The symbol object to clone. + * @returns {Object} Returns the cloned symbol object. + */ +function cloneSymbol(symbol) { + return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; +} + +module.exports = cloneSymbol; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_cloneTypedArray.js": +/*!********************************************************!*\ + !*** ../../../node_modules/lodash/_cloneTypedArray.js ***! + \********************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var cloneArrayBuffer = __webpack_require__(/*! ./_cloneArrayBuffer */ "../../../node_modules/lodash/_cloneArrayBuffer.js"); + +/** + * Creates a clone of `typedArray`. + * + * @private + * @param {Object} typedArray The typed array to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the cloned typed array. + */ +function cloneTypedArray(typedArray, isDeep) { + var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; + return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); +} + +module.exports = cloneTypedArray; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_copyArray.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_copyArray.js ***! + \**************************************************/ +/***/ ((module) => { + +/** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ +function copyArray(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; +} + +module.exports = copyArray; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_copyObject.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_copyObject.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var assignValue = __webpack_require__(/*! ./_assignValue */ "../../../node_modules/lodash/_assignValue.js"), + baseAssignValue = __webpack_require__(/*! ./_baseAssignValue */ "../../../node_modules/lodash/_baseAssignValue.js"); + +/** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property identifiers to copy. + * @param {Object} [object={}] The object to copy properties to. + * @param {Function} [customizer] The function to customize copied values. + * @returns {Object} Returns `object`. + */ +function copyObject(source, props, object, customizer) { + var isNew = !object; + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + + var newValue = customizer + ? customizer(object[key], source[key], key, object, source) + : undefined; + + if (newValue === undefined) { + newValue = source[key]; + } + if (isNew) { + baseAssignValue(object, key, newValue); + } else { + assignValue(object, key, newValue); + } + } + return object; +} + +module.exports = copyObject; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_copySymbols.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_copySymbols.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var copyObject = __webpack_require__(/*! ./_copyObject */ "../../../node_modules/lodash/_copyObject.js"), + getSymbols = __webpack_require__(/*! ./_getSymbols */ "../../../node_modules/lodash/_getSymbols.js"); + +/** + * Copies own symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ +function copySymbols(source, object) { + return copyObject(source, getSymbols(source), object); +} + +module.exports = copySymbols; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_copySymbolsIn.js": +/*!******************************************************!*\ + !*** ../../../node_modules/lodash/_copySymbolsIn.js ***! + \******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var copyObject = __webpack_require__(/*! ./_copyObject */ "../../../node_modules/lodash/_copyObject.js"), + getSymbolsIn = __webpack_require__(/*! ./_getSymbolsIn */ "../../../node_modules/lodash/_getSymbolsIn.js"); + +/** + * Copies own and inherited symbols of `source` to `object`. + * + * @private + * @param {Object} source The object to copy symbols from. + * @param {Object} [object={}] The object to copy symbols to. + * @returns {Object} Returns `object`. + */ +function copySymbolsIn(source, object) { + return copyObject(source, getSymbolsIn(source), object); +} + +module.exports = copySymbolsIn; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_coreJsData.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_coreJsData.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var root = __webpack_require__(/*! ./_root */ "../../../node_modules/lodash/_root.js"); + +/** Used to detect overreaching core-js shims. */ +var coreJsData = root['__core-js_shared__']; + +module.exports = coreJsData; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_defineProperty.js": +/*!*******************************************************!*\ + !*** ../../../node_modules/lodash/_defineProperty.js ***! + \*******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../../node_modules/lodash/_getNative.js"); + +var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} +}()); + +module.exports = defineProperty; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_equalArrays.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_equalArrays.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var SetCache = __webpack_require__(/*! ./_SetCache */ "../../../node_modules/lodash/_SetCache.js"), + arraySome = __webpack_require__(/*! ./_arraySome */ "../../../node_modules/lodash/_arraySome.js"), + cacheHas = __webpack_require__(/*! ./_cacheHas */ "../../../node_modules/lodash/_cacheHas.js"); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ +function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Check that cyclic values are equal. + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; +} + +module.exports = equalArrays; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_equalByTag.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_equalByTag.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Symbol = __webpack_require__(/*! ./_Symbol */ "../../../node_modules/lodash/_Symbol.js"), + Uint8Array = __webpack_require__(/*! ./_Uint8Array */ "../../../node_modules/lodash/_Uint8Array.js"), + eq = __webpack_require__(/*! ./eq */ "../../../node_modules/lodash/eq.js"), + equalArrays = __webpack_require__(/*! ./_equalArrays */ "../../../node_modules/lodash/_equalArrays.js"), + mapToArray = __webpack_require__(/*! ./_mapToArray */ "../../../node_modules/lodash/_mapToArray.js"), + setToArray = __webpack_require__(/*! ./_setToArray */ "../../../node_modules/lodash/_setToArray.js"); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + mapTag = '[object Map]', + numberTag = '[object Number]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]'; + +/** Used to convert symbols to primitives and strings. */ +var symbolProto = Symbol ? Symbol.prototype : undefined, + symbolValueOf = symbolProto ? symbolProto.valueOf : undefined; + +/** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { + switch (tag) { + case dataViewTag: + if ((object.byteLength != other.byteLength) || + (object.byteOffset != other.byteOffset)) { + return false; + } + object = object.buffer; + other = other.buffer; + + case arrayBufferTag: + if ((object.byteLength != other.byteLength) || + !equalFunc(new Uint8Array(object), new Uint8Array(other))) { + return false; + } + return true; + + case boolTag: + case dateTag: + case numberTag: + // Coerce booleans to `1` or `0` and dates to milliseconds. + // Invalid dates are coerced to `NaN`. + return eq(+object, +other); + + case errorTag: + return object.name == other.name && object.message == other.message; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings, primitives and objects, + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring + // for more details. + return object == (other + ''); + + case mapTag: + var convert = mapToArray; + + case setTag: + var isPartial = bitmask & COMPARE_PARTIAL_FLAG; + convert || (convert = setToArray); + + if (object.size != other.size && !isPartial) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(object); + if (stacked) { + return stacked == other; + } + bitmask |= COMPARE_UNORDERED_FLAG; + + // Recursively compare objects (susceptible to call stack limits). + stack.set(object, other); + var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); + stack['delete'](object); + return result; + + case symbolTag: + if (symbolValueOf) { + return symbolValueOf.call(object) == symbolValueOf.call(other); + } + } + return false; +} + +module.exports = equalByTag; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_equalObjects.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_equalObjects.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getAllKeys = __webpack_require__(/*! ./_getAllKeys */ "../../../node_modules/lodash/_getAllKeys.js"); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `object` and `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + objProps = getAllKeys(object), + objLength = objProps.length, + othProps = getAllKeys(other), + othLength = othProps.length; + + if (objLength != othLength && !isPartial) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + // Check that cyclic values are equal. + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; + } + var result = true; + stack.set(object, other); + stack.set(other, object); + + var skipCtor = isPartial; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, objValue, key, other, object, stack) + : customizer(objValue, othValue, key, object, other, stack); + } + // Recursively compare objects (susceptible to call stack limits). + if (!(compared === undefined + ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) + : compared + )) { + result = false; + break; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (result && !skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + result = false; + } + } + stack['delete'](object); + stack['delete'](other); + return result; +} + +module.exports = equalObjects; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_freeGlobal.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_freeGlobal.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof __webpack_require__.g == 'object' && __webpack_require__.g && __webpack_require__.g.Object === Object && __webpack_require__.g; + +module.exports = freeGlobal; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_getAllKeys.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_getAllKeys.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseGetAllKeys = __webpack_require__(/*! ./_baseGetAllKeys */ "../../../node_modules/lodash/_baseGetAllKeys.js"), + getSymbols = __webpack_require__(/*! ./_getSymbols */ "../../../node_modules/lodash/_getSymbols.js"), + keys = __webpack_require__(/*! ./keys */ "../../../node_modules/lodash/keys.js"); + +/** + * Creates an array of own enumerable property names and symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeys(object) { + return baseGetAllKeys(object, keys, getSymbols); +} + +module.exports = getAllKeys; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_getAllKeysIn.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_getAllKeysIn.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseGetAllKeys = __webpack_require__(/*! ./_baseGetAllKeys */ "../../../node_modules/lodash/_baseGetAllKeys.js"), + getSymbolsIn = __webpack_require__(/*! ./_getSymbolsIn */ "../../../node_modules/lodash/_getSymbolsIn.js"), + keysIn = __webpack_require__(/*! ./keysIn */ "../../../node_modules/lodash/keysIn.js"); + +/** + * Creates an array of own and inherited enumerable property names and + * symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names and symbols. + */ +function getAllKeysIn(object) { + return baseGetAllKeys(object, keysIn, getSymbolsIn); +} + +module.exports = getAllKeysIn; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_getMapData.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_getMapData.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isKeyable = __webpack_require__(/*! ./_isKeyable */ "../../../node_modules/lodash/_isKeyable.js"); + +/** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ +function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; +} + +module.exports = getMapData; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_getNative.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_getNative.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsNative = __webpack_require__(/*! ./_baseIsNative */ "../../../node_modules/lodash/_baseIsNative.js"), + getValue = __webpack_require__(/*! ./_getValue */ "../../../node_modules/lodash/_getValue.js"); + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; +} + +module.exports = getNative; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_getPrototype.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_getPrototype.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var overArg = __webpack_require__(/*! ./_overArg */ "../../../node_modules/lodash/_overArg.js"); + +/** Built-in value references. */ +var getPrototype = overArg(Object.getPrototypeOf, Object); + +module.exports = getPrototype; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_getRawTag.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_getRawTag.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Symbol = __webpack_require__(/*! ./_Symbol */ "../../../node_modules/lodash/_Symbol.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ +function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} + +module.exports = getRawTag; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_getSymbols.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_getSymbols.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var arrayFilter = __webpack_require__(/*! ./_arrayFilter */ "../../../node_modules/lodash/_arrayFilter.js"), + stubArray = __webpack_require__(/*! ./stubArray */ "../../../node_modules/lodash/stubArray.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbols = !nativeGetSymbols ? stubArray : function(object) { + if (object == null) { + return []; + } + object = Object(object); + return arrayFilter(nativeGetSymbols(object), function(symbol) { + return propertyIsEnumerable.call(object, symbol); + }); +}; + +module.exports = getSymbols; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_getSymbolsIn.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_getSymbolsIn.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var arrayPush = __webpack_require__(/*! ./_arrayPush */ "../../../node_modules/lodash/_arrayPush.js"), + getPrototype = __webpack_require__(/*! ./_getPrototype */ "../../../node_modules/lodash/_getPrototype.js"), + getSymbols = __webpack_require__(/*! ./_getSymbols */ "../../../node_modules/lodash/_getSymbols.js"), + stubArray = __webpack_require__(/*! ./stubArray */ "../../../node_modules/lodash/stubArray.js"); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeGetSymbols = Object.getOwnPropertySymbols; + +/** + * Creates an array of the own and inherited enumerable symbols of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of symbols. + */ +var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { + var result = []; + while (object) { + arrayPush(result, getSymbols(object)); + object = getPrototype(object); + } + return result; +}; + +module.exports = getSymbolsIn; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_getTag.js": +/*!***********************************************!*\ + !*** ../../../node_modules/lodash/_getTag.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var DataView = __webpack_require__(/*! ./_DataView */ "../../../node_modules/lodash/_DataView.js"), + Map = __webpack_require__(/*! ./_Map */ "../../../node_modules/lodash/_Map.js"), + Promise = __webpack_require__(/*! ./_Promise */ "../../../node_modules/lodash/_Promise.js"), + Set = __webpack_require__(/*! ./_Set */ "../../../node_modules/lodash/_Set.js"), + WeakMap = __webpack_require__(/*! ./_WeakMap */ "../../../node_modules/lodash/_WeakMap.js"), + baseGetTag = __webpack_require__(/*! ./_baseGetTag */ "../../../node_modules/lodash/_baseGetTag.js"), + toSource = __webpack_require__(/*! ./_toSource */ "../../../node_modules/lodash/_toSource.js"); + +/** `Object#toString` result references. */ +var mapTag = '[object Map]', + objectTag = '[object Object]', + promiseTag = '[object Promise]', + setTag = '[object Set]', + weakMapTag = '[object WeakMap]'; + +var dataViewTag = '[object DataView]'; + +/** Used to detect maps, sets, and weakmaps. */ +var dataViewCtorString = toSource(DataView), + mapCtorString = toSource(Map), + promiseCtorString = toSource(Promise), + setCtorString = toSource(Set), + weakMapCtorString = toSource(WeakMap); + +/** + * Gets the `toStringTag` of `value`. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +var getTag = baseGetTag; + +// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. +if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || + (Map && getTag(new Map) != mapTag) || + (Promise && getTag(Promise.resolve()) != promiseTag) || + (Set && getTag(new Set) != setTag) || + (WeakMap && getTag(new WeakMap) != weakMapTag)) { + getTag = function(value) { + var result = baseGetTag(value), + Ctor = result == objectTag ? value.constructor : undefined, + ctorString = Ctor ? toSource(Ctor) : ''; + + if (ctorString) { + switch (ctorString) { + case dataViewCtorString: return dataViewTag; + case mapCtorString: return mapTag; + case promiseCtorString: return promiseTag; + case setCtorString: return setTag; + case weakMapCtorString: return weakMapTag; + } + } + return result; + }; +} + +module.exports = getTag; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_getValue.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_getValue.js ***! + \*************************************************/ +/***/ ((module) => { + +/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function getValue(object, key) { + return object == null ? undefined : object[key]; +} + +module.exports = getValue; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_hashClear.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_hashClear.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var nativeCreate = __webpack_require__(/*! ./_nativeCreate */ "../../../node_modules/lodash/_nativeCreate.js"); + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; + this.size = 0; +} + +module.exports = hashClear; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_hashDelete.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_hashDelete.js ***! + \***************************************************/ +/***/ ((module) => { + +/** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete(key) { + var result = this.has(key) && delete this.__data__[key]; + this.size -= result ? 1 : 0; + return result; +} + +module.exports = hashDelete; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_hashGet.js": +/*!************************************************!*\ + !*** ../../../node_modules/lodash/_hashGet.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var nativeCreate = __webpack_require__(/*! ./_nativeCreate */ "../../../node_modules/lodash/_nativeCreate.js"); + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; +} + +module.exports = hashGet; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_hashHas.js": +/*!************************************************!*\ + !*** ../../../node_modules/lodash/_hashHas.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var nativeCreate = __webpack_require__(/*! ./_nativeCreate */ "../../../node_modules/lodash/_nativeCreate.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function hashHas(key) { + var data = this.__data__; + return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); +} + +module.exports = hashHas; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_hashSet.js": +/*!************************************************!*\ + !*** ../../../node_modules/lodash/_hashSet.js ***! + \************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var nativeCreate = __webpack_require__(/*! ./_nativeCreate */ "../../../node_modules/lodash/_nativeCreate.js"); + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ +function hashSet(key, value) { + var data = this.__data__; + this.size += this.has(key) ? 0 : 1; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; +} + +module.exports = hashSet; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_initCloneArray.js": +/*!*******************************************************!*\ + !*** ../../../node_modules/lodash/_initCloneArray.js ***! + \*******************************************************/ +/***/ ((module) => { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ +function initCloneArray(array) { + var length = array.length, + result = new array.constructor(length); + + // Add properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; +} + +module.exports = initCloneArray; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_initCloneByTag.js": +/*!*******************************************************!*\ + !*** ../../../node_modules/lodash/_initCloneByTag.js ***! + \*******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var cloneArrayBuffer = __webpack_require__(/*! ./_cloneArrayBuffer */ "../../../node_modules/lodash/_cloneArrayBuffer.js"), + cloneDataView = __webpack_require__(/*! ./_cloneDataView */ "../../../node_modules/lodash/_cloneDataView.js"), + cloneRegExp = __webpack_require__(/*! ./_cloneRegExp */ "../../../node_modules/lodash/_cloneRegExp.js"), + cloneSymbol = __webpack_require__(/*! ./_cloneSymbol */ "../../../node_modules/lodash/_cloneSymbol.js"), + cloneTypedArray = __webpack_require__(/*! ./_cloneTypedArray */ "../../../node_modules/lodash/_cloneTypedArray.js"); + +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]', + dateTag = '[object Date]', + mapTag = '[object Map]', + numberTag = '[object Number]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + symbolTag = '[object Symbol]'; + +var arrayBufferTag = '[object ArrayBuffer]', + dataViewTag = '[object DataView]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return cloneArrayBuffer(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case dataViewTag: + return cloneDataView(object, isDeep); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + return cloneTypedArray(object, isDeep); + + case mapTag: + return new Ctor; + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + return cloneRegExp(object); + + case setTag: + return new Ctor; + + case symbolTag: + return cloneSymbol(object); + } +} + +module.exports = initCloneByTag; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_initCloneObject.js": +/*!********************************************************!*\ + !*** ../../../node_modules/lodash/_initCloneObject.js ***! + \********************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseCreate = __webpack_require__(/*! ./_baseCreate */ "../../../node_modules/lodash/_baseCreate.js"), + getPrototype = __webpack_require__(/*! ./_getPrototype */ "../../../node_modules/lodash/_getPrototype.js"), + isPrototype = __webpack_require__(/*! ./_isPrototype */ "../../../node_modules/lodash/_isPrototype.js"); + +/** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneObject(object) { + return (typeof object.constructor == 'function' && !isPrototype(object)) + ? baseCreate(getPrototype(object)) + : {}; +} + +module.exports = initCloneObject; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_isIndex.js": +/*!************************************************!*\ + !*** ../../../node_modules/lodash/_isIndex.js ***! + \************************************************/ +/***/ ((module) => { + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?:0|[1-9]\d*)$/; + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); +} + +module.exports = isIndex; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_isKeyable.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/_isKeyable.js ***! + \**************************************************/ +/***/ ((module) => { + +/** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ +function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); +} + +module.exports = isKeyable; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_isMasked.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_isMasked.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var coreJsData = __webpack_require__(/*! ./_coreJsData */ "../../../node_modules/lodash/_coreJsData.js"); + +/** Used to detect methods masquerading as native. */ +var maskSrcKey = (function() { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; +}()); + +/** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ +function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); +} + +module.exports = isMasked; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_isPrototype.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_isPrototype.js ***! + \****************************************************/ +/***/ ((module) => { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ +function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; +} + +module.exports = isPrototype; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_listCacheClear.js": +/*!*******************************************************!*\ + !*** ../../../node_modules/lodash/_listCacheClear.js ***! + \*******************************************************/ +/***/ ((module) => { + +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear() { + this.__data__ = []; + this.size = 0; +} + +module.exports = listCacheClear; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_listCacheDelete.js": +/*!********************************************************!*\ + !*** ../../../node_modules/lodash/_listCacheDelete.js ***! + \********************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var assocIndexOf = __webpack_require__(/*! ./_assocIndexOf */ "../../../node_modules/lodash/_assocIndexOf.js"); + +/** Used for built-in method references. */ +var arrayProto = Array.prototype; + +/** Built-in value references. */ +var splice = arrayProto.splice; + +/** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + --this.size; + return true; +} + +module.exports = listCacheDelete; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_listCacheGet.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_listCacheGet.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var assocIndexOf = __webpack_require__(/*! ./_assocIndexOf */ "../../../node_modules/lodash/_assocIndexOf.js"); + +/** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; +} + +module.exports = listCacheGet; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_listCacheHas.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_listCacheHas.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var assocIndexOf = __webpack_require__(/*! ./_assocIndexOf */ "../../../node_modules/lodash/_assocIndexOf.js"); + +/** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; +} + +module.exports = listCacheHas; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_listCacheSet.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_listCacheSet.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var assocIndexOf = __webpack_require__(/*! ./_assocIndexOf */ "../../../node_modules/lodash/_assocIndexOf.js"); + +/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ +function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + ++this.size; + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} + +module.exports = listCacheSet; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_mapCacheClear.js": +/*!******************************************************!*\ + !*** ../../../node_modules/lodash/_mapCacheClear.js ***! + \******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var Hash = __webpack_require__(/*! ./_Hash */ "../../../node_modules/lodash/_Hash.js"), + ListCache = __webpack_require__(/*! ./_ListCache */ "../../../node_modules/lodash/_ListCache.js"), + Map = __webpack_require__(/*! ./_Map */ "../../../node_modules/lodash/_Map.js"); + +/** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear() { + this.size = 0; + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; +} + +module.exports = mapCacheClear; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_mapCacheDelete.js": +/*!*******************************************************!*\ + !*** ../../../node_modules/lodash/_mapCacheDelete.js ***! + \*******************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getMapData = __webpack_require__(/*! ./_getMapData */ "../../../node_modules/lodash/_getMapData.js"); + +/** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function mapCacheDelete(key) { + var result = getMapData(this, key)['delete'](key); + this.size -= result ? 1 : 0; + return result; +} + +module.exports = mapCacheDelete; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_mapCacheGet.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_mapCacheGet.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getMapData = __webpack_require__(/*! ./_getMapData */ "../../../node_modules/lodash/_getMapData.js"); + +/** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function mapCacheGet(key) { + return getMapData(this, key).get(key); +} + +module.exports = mapCacheGet; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_mapCacheHas.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_mapCacheHas.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getMapData = __webpack_require__(/*! ./_getMapData */ "../../../node_modules/lodash/_getMapData.js"); + +/** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function mapCacheHas(key) { + return getMapData(this, key).has(key); +} + +module.exports = mapCacheHas; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_mapCacheSet.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_mapCacheSet.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getMapData = __webpack_require__(/*! ./_getMapData */ "../../../node_modules/lodash/_getMapData.js"); + +/** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ +function mapCacheSet(key, value) { + var data = getMapData(this, key), + size = data.size; + + data.set(key, value); + this.size += data.size == size ? 0 : 1; + return this; +} + +module.exports = mapCacheSet; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_mapToArray.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_mapToArray.js ***! + \***************************************************/ +/***/ ((module) => { + +/** + * Converts `map` to its key-value pairs. + * + * @private + * @param {Object} map The map to convert. + * @returns {Array} Returns the key-value pairs. + */ +function mapToArray(map) { + var index = -1, + result = Array(map.size); + + map.forEach(function(value, key) { + result[++index] = [key, value]; + }); + return result; +} + +module.exports = mapToArray; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_nativeCreate.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_nativeCreate.js ***! + \*****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var getNative = __webpack_require__(/*! ./_getNative */ "../../../node_modules/lodash/_getNative.js"); + +/* Built-in method references that are verified to be native. */ +var nativeCreate = getNative(Object, 'create'); + +module.exports = nativeCreate; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_nativeKeys.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_nativeKeys.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var overArg = __webpack_require__(/*! ./_overArg */ "../../../node_modules/lodash/_overArg.js"); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeKeys = overArg(Object.keys, Object); + +module.exports = nativeKeys; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_nativeKeysIn.js": +/*!*****************************************************!*\ + !*** ../../../node_modules/lodash/_nativeKeysIn.js ***! + \*****************************************************/ +/***/ ((module) => { + +/** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; +} + +module.exports = nativeKeysIn; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_nodeUtil.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_nodeUtil.js ***! + \*************************************************/ +/***/ ((module, exports, __webpack_require__) => { + +/* module decorator */ module = __webpack_require__.nmd(module); +var freeGlobal = __webpack_require__(/*! ./_freeGlobal */ "../../../node_modules/lodash/_freeGlobal.js"); + +/** Detect free variable `exports`. */ +var freeExports = true && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && "object" == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Detect free variable `process` from Node.js. */ +var freeProcess = moduleExports && freeGlobal.process; + +/** Used to access faster Node.js helpers. */ +var nodeUtil = (function() { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule && freeModule.require && freeModule.require('util').types; + + if (types) { + return types; + } + + // Legacy `process.binding('util')` for Node.js < 10. + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} +}()); + +module.exports = nodeUtil; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_objectToString.js": +/*!*******************************************************!*\ + !*** ../../../node_modules/lodash/_objectToString.js ***! + \*******************************************************/ +/***/ ((module) => { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ +function objectToString(value) { + return nativeObjectToString.call(value); +} + +module.exports = objectToString; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_overArg.js": +/*!************************************************!*\ + !*** ../../../node_modules/lodash/_overArg.js ***! + \************************************************/ +/***/ ((module) => { + +/** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} + +module.exports = overArg; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_root.js": +/*!*********************************************!*\ + !*** ../../../node_modules/lodash/_root.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var freeGlobal = __webpack_require__(/*! ./_freeGlobal */ "../../../node_modules/lodash/_freeGlobal.js"); + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +module.exports = root; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_setCacheAdd.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_setCacheAdd.js ***! + \****************************************************/ +/***/ ((module) => { + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ +function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; +} + +module.exports = setCacheAdd; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_setCacheHas.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_setCacheHas.js ***! + \****************************************************/ +/***/ ((module) => { + +/** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ +function setCacheHas(value) { + return this.__data__.has(value); +} + +module.exports = setCacheHas; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_setToArray.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_setToArray.js ***! + \***************************************************/ +/***/ ((module) => { + +/** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ +function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function(value) { + result[++index] = value; + }); + return result; +} + +module.exports = setToArray; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_stackClear.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/_stackClear.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var ListCache = __webpack_require__(/*! ./_ListCache */ "../../../node_modules/lodash/_ListCache.js"); + +/** + * Removes all key-value entries from the stack. + * + * @private + * @name clear + * @memberOf Stack + */ +function stackClear() { + this.__data__ = new ListCache; + this.size = 0; +} + +module.exports = stackClear; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_stackDelete.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/_stackDelete.js ***! + \****************************************************/ +/***/ ((module) => { + +/** + * Removes `key` and its value from the stack. + * + * @private + * @name delete + * @memberOf Stack + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function stackDelete(key) { + var data = this.__data__, + result = data['delete'](key); + + this.size = data.size; + return result; +} + +module.exports = stackDelete; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_stackGet.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_stackGet.js ***! + \*************************************************/ +/***/ ((module) => { + +/** + * Gets the stack value for `key`. + * + * @private + * @name get + * @memberOf Stack + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function stackGet(key) { + return this.__data__.get(key); +} + +module.exports = stackGet; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_stackHas.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_stackHas.js ***! + \*************************************************/ +/***/ ((module) => { + +/** + * Checks if a stack value for `key` exists. + * + * @private + * @name has + * @memberOf Stack + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function stackHas(key) { + return this.__data__.has(key); +} + +module.exports = stackHas; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_stackSet.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_stackSet.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var ListCache = __webpack_require__(/*! ./_ListCache */ "../../../node_modules/lodash/_ListCache.js"), + Map = __webpack_require__(/*! ./_Map */ "../../../node_modules/lodash/_Map.js"), + MapCache = __webpack_require__(/*! ./_MapCache */ "../../../node_modules/lodash/_MapCache.js"); + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** + * Sets the stack `key` to `value`. + * + * @private + * @name set + * @memberOf Stack + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the stack cache instance. + */ +function stackSet(key, value) { + var data = this.__data__; + if (data instanceof ListCache) { + var pairs = data.__data__; + if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { + pairs.push([key, value]); + this.size = ++data.size; + return this; + } + data = this.__data__ = new MapCache(pairs); + } + data.set(key, value); + this.size = data.size; + return this; +} + +module.exports = stackSet; + + +/***/ }), + +/***/ "../../../node_modules/lodash/_toSource.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/_toSource.js ***! + \*************************************************/ +/***/ ((module) => { + +/** Used for built-in method references. */ +var funcProto = Function.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ +function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; +} + +module.exports = toSource; + + +/***/ }), + +/***/ "../../../node_modules/lodash/cloneDeep.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/cloneDeep.js ***! + \*************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseClone = __webpack_require__(/*! ./_baseClone */ "../../../node_modules/lodash/_baseClone.js"); + +/** Used to compose bitmasks for cloning. */ +var CLONE_DEEP_FLAG = 1, + CLONE_SYMBOLS_FLAG = 4; + +/** + * This method is like `_.clone` except that it recursively clones `value`. + * + * @static + * @memberOf _ + * @since 1.0.0 + * @category Lang + * @param {*} value The value to recursively clone. + * @returns {*} Returns the deep cloned value. + * @see _.clone + * @example + * + * var objects = [{ 'a': 1 }, { 'b': 2 }]; + * + * var deep = _.cloneDeep(objects); + * console.log(deep[0] === objects[0]); + * // => false + */ +function cloneDeep(value) { + return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); +} + +module.exports = cloneDeep; + + +/***/ }), + +/***/ "../../../node_modules/lodash/eq.js": +/*!******************************************!*\ + !*** ../../../node_modules/lodash/eq.js ***! + \******************************************/ +/***/ ((module) => { + +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +module.exports = eq; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isArguments.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/isArguments.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsArguments = __webpack_require__(/*! ./_baseIsArguments */ "../../../node_modules/lodash/_baseIsArguments.js"), + isObjectLike = __webpack_require__(/*! ./isObjectLike */ "../../../node_modules/lodash/isObjectLike.js"); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); +}; + +module.exports = isArguments; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isArray.js": +/*!***********************************************!*\ + !*** ../../../node_modules/lodash/isArray.js ***! + \***********************************************/ +/***/ ((module) => { + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +module.exports = isArray; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isArrayLike.js": +/*!***************************************************!*\ + !*** ../../../node_modules/lodash/isArrayLike.js ***! + \***************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var isFunction = __webpack_require__(/*! ./isFunction */ "../../../node_modules/lodash/isFunction.js"), + isLength = __webpack_require__(/*! ./isLength */ "../../../node_modules/lodash/isLength.js"); + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +module.exports = isArrayLike; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isBuffer.js": +/*!************************************************!*\ + !*** ../../../node_modules/lodash/isBuffer.js ***! + \************************************************/ +/***/ ((module, exports, __webpack_require__) => { + +/* module decorator */ module = __webpack_require__.nmd(module); +var root = __webpack_require__(/*! ./_root */ "../../../node_modules/lodash/_root.js"), + stubFalse = __webpack_require__(/*! ./stubFalse */ "../../../node_modules/lodash/stubFalse.js"); + +/** Detect free variable `exports`. */ +var freeExports = true && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && "object" == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? root.Buffer : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; + +/** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ +var isBuffer = nativeIsBuffer || stubFalse; + +module.exports = isBuffer; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isEqual.js": +/*!***********************************************!*\ + !*** ../../../node_modules/lodash/isEqual.js ***! + \***********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsEqual = __webpack_require__(/*! ./_baseIsEqual */ "../../../node_modules/lodash/_baseIsEqual.js"); + +/** + * Performs a deep comparison between two values to determine if they are + * equivalent. + * + * **Note:** This method supports comparing arrays, array buffers, booleans, + * date objects, error objects, maps, numbers, `Object` objects, regexes, + * sets, strings, symbols, and typed arrays. `Object` objects are compared + * by their own, not inherited, enumerable properties. Functions and DOM + * nodes are compared by strict equality, i.e. `===`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.isEqual(object, other); + * // => true + * + * object === other; + * // => false + */ +function isEqual(value, other) { + return baseIsEqual(value, other); +} + +module.exports = isEqual; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isFunction.js": +/*!**************************************************!*\ + !*** ../../../node_modules/lodash/isFunction.js ***! + \**************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseGetTag = __webpack_require__(/*! ./_baseGetTag */ "../../../node_modules/lodash/_baseGetTag.js"), + isObject = __webpack_require__(/*! ./isObject */ "../../../node_modules/lodash/isObject.js"); + +/** `Object#toString` result references. */ +var asyncTag = '[object AsyncFunction]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[object Proxy]'; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; +} + +module.exports = isFunction; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isLength.js": +/*!************************************************!*\ + !*** ../../../node_modules/lodash/isLength.js ***! + \************************************************/ +/***/ ((module) => { + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +module.exports = isLength; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isMap.js": +/*!*********************************************!*\ + !*** ../../../node_modules/lodash/isMap.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsMap = __webpack_require__(/*! ./_baseIsMap */ "../../../node_modules/lodash/_baseIsMap.js"), + baseUnary = __webpack_require__(/*! ./_baseUnary */ "../../../node_modules/lodash/_baseUnary.js"), + nodeUtil = __webpack_require__(/*! ./_nodeUtil */ "../../../node_modules/lodash/_nodeUtil.js"); + +/* Node.js helper references. */ +var nodeIsMap = nodeUtil && nodeUtil.isMap; + +/** + * Checks if `value` is classified as a `Map` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a map, else `false`. + * @example + * + * _.isMap(new Map); + * // => true + * + * _.isMap(new WeakMap); + * // => false + */ +var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; + +module.exports = isMap; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isObject.js": +/*!************************************************!*\ + !*** ../../../node_modules/lodash/isObject.js ***! + \************************************************/ +/***/ ((module) => { + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +module.exports = isObject; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isObjectLike.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/isObjectLike.js ***! + \****************************************************/ +/***/ ((module) => { + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +module.exports = isObjectLike; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isSet.js": +/*!*********************************************!*\ + !*** ../../../node_modules/lodash/isSet.js ***! + \*********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsSet = __webpack_require__(/*! ./_baseIsSet */ "../../../node_modules/lodash/_baseIsSet.js"), + baseUnary = __webpack_require__(/*! ./_baseUnary */ "../../../node_modules/lodash/_baseUnary.js"), + nodeUtil = __webpack_require__(/*! ./_nodeUtil */ "../../../node_modules/lodash/_nodeUtil.js"); + +/* Node.js helper references. */ +var nodeIsSet = nodeUtil && nodeUtil.isSet; + +/** + * Checks if `value` is classified as a `Set` object. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a set, else `false`. + * @example + * + * _.isSet(new Set); + * // => true + * + * _.isSet(new WeakSet); + * // => false + */ +var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; + +module.exports = isSet; + + +/***/ }), + +/***/ "../../../node_modules/lodash/isTypedArray.js": +/*!****************************************************!*\ + !*** ../../../node_modules/lodash/isTypedArray.js ***! + \****************************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var baseIsTypedArray = __webpack_require__(/*! ./_baseIsTypedArray */ "../../../node_modules/lodash/_baseIsTypedArray.js"), + baseUnary = __webpack_require__(/*! ./_baseUnary */ "../../../node_modules/lodash/_baseUnary.js"), + nodeUtil = __webpack_require__(/*! ./_nodeUtil */ "../../../node_modules/lodash/_nodeUtil.js"); + +/* Node.js helper references. */ +var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + +/** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ +var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + +module.exports = isTypedArray; + + +/***/ }), + +/***/ "../../../node_modules/lodash/keys.js": +/*!********************************************!*\ + !*** ../../../node_modules/lodash/keys.js ***! + \********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var arrayLikeKeys = __webpack_require__(/*! ./_arrayLikeKeys */ "../../../node_modules/lodash/_arrayLikeKeys.js"), + baseKeys = __webpack_require__(/*! ./_baseKeys */ "../../../node_modules/lodash/_baseKeys.js"), + isArrayLike = __webpack_require__(/*! ./isArrayLike */ "../../../node_modules/lodash/isArrayLike.js"); + +/** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * for more details. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ +function keys(object) { + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); +} + +module.exports = keys; + + +/***/ }), + +/***/ "../../../node_modules/lodash/keysIn.js": +/*!**********************************************!*\ + !*** ../../../node_modules/lodash/keysIn.js ***! + \**********************************************/ +/***/ ((module, __unused_webpack_exports, __webpack_require__) => { + +var arrayLikeKeys = __webpack_require__(/*! ./_arrayLikeKeys */ "../../../node_modules/lodash/_arrayLikeKeys.js"), + baseKeysIn = __webpack_require__(/*! ./_baseKeysIn */ "../../../node_modules/lodash/_baseKeysIn.js"), + isArrayLike = __webpack_require__(/*! ./isArrayLike */ "../../../node_modules/lodash/isArrayLike.js"); + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); +} + +module.exports = keysIn; + + +/***/ }), + +/***/ "../../../node_modules/lodash/stubArray.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/stubArray.js ***! + \*************************************************/ +/***/ ((module) => { + +/** + * This method returns a new empty array. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {Array} Returns the new empty array. + * @example + * + * var arrays = _.times(2, _.stubArray); + * + * console.log(arrays); + * // => [[], []] + * + * console.log(arrays[0] === arrays[1]); + * // => false + */ +function stubArray() { + return []; +} + +module.exports = stubArray; + + +/***/ }), + +/***/ "../../../node_modules/lodash/stubFalse.js": +/*!*************************************************!*\ + !*** ../../../node_modules/lodash/stubFalse.js ***! + \*************************************************/ +/***/ ((module) => { + +/** + * This method returns `false`. + * + * @static + * @memberOf _ + * @since 4.13.0 + * @category Util + * @returns {boolean} Returns `false`. + * @example + * + * _.times(2, _.stubFalse); + * // => [false, false] + */ +function stubFalse() { + return false; +} + +module.exports = stubFalse; + + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ id: moduleId, +/******/ loaded: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/node module decorator */ +/******/ (() => { +/******/ __webpack_require__.nmd = (module) => { +/******/ module.paths = []; +/******/ if (!module.children) module.children = []; +/******/ return module; +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be in strict mode. +(() => { +"use strict"; +/*!******************************!*\ + !*** ./client/src/dialog.ts ***! + \******************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _openfin_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @openfin/core */ "../../../node_modules/@openfin/core/out/mock.js"); + +document.addEventListener("DOMContentLoaded", async () => { + const okay = document.querySelector("#okay"); + const cancel = document.querySelector("#cancel"); + if (okay) { + okay.addEventListener("click", async () => { + await handleClose(true); + }); + } + if (cancel) { + cancel.addEventListener("click", async () => { + await handleClose(false); + }); + } + populate(); +}); +/** + * Populate the list of views the were prevented. + * @param views The list of views. + */ +function populatePreventedViews(views) { + for (const view of views) { + console.log("add view", view); + const viewP = document.createElement("p"); + viewP.innerHTML = view.name; + const v = document.querySelector("#views"); + if (v) { + v.append(viewP); + } + } +} +/** + * Populate the views. + */ +function populate() { + const params = new URLSearchParams(window.location.search); + const closeType = params.get("closeType"); + if (closeType === "view") { + const p = document.createElement("p"); + p.innerHTML = "Are you sure you want to close this view? It may have unsaved changes."; + const t = document.querySelector("#text"); + if (t) { + t.append(p); + } + } + if (closeType === "window") { + const views = JSON.parse(params.get("views") ?? "").views; + const p1 = document.createElement("p"); + p1.innerHTML = "Are you sure you want to close this window?"; + const t1 = document.querySelector("#text"); + if (t1) { + t1.append(p1); + } + const p2 = document.createElement("p"); + p2.innerHTML = "The following views may have unsaved changes:"; + const t2 = document.querySelector("#text"); + if (t2) { + t2.append(p2); + } + populatePreventedViews(views); + } +} +/** + * Handle the close event. + * @param userDecision The decision the user made. + */ +async function handleClose(userDecision) { + try { + const client = await _openfin_core__WEBPACK_IMPORTED_MODULE_0__.fin.InterApplicationBus.Channel.connect("userDecisionProvider"); + await client.dispatch("get-user-decision", userDecision); + window.close(); + } + catch (error) { + console.log(error); + } +} + +})(); + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtRUFBbUU7QUFDbkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxRUFBcUU7QUFDckU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxzQkFBc0I7QUFDNUU7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxzQkFBc0I7QUFDNUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxzQkFBc0I7QUFDNUU7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0RBQXNELHNCQUFzQjtBQUM1RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRC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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEVBQThFLFNBQVM7QUFDdkY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLFNBQVM7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVEQUF1RCx5QkFBeUI7QUFDaEY7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvRkFBb0YsU0FBUztBQUM3RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUIsVUFBVTtBQUMzQjtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIsMENBQTBDO0FBQ25FO0FBQ0E7QUFDQSwrQ0FBK0M7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5Qix5Q0FBeUM7QUFDbEU7QUFDQTtBQUNBLCtDQUErQztBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrRUFBK0UsU0FBUztBQUN4RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtGQUFrRixTQUFTO0FBQzNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0ZBQWdGLFNBQVM7QUFDekY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdELFdBQVc7QUFDM0Q7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyxXQUFXO0FBQ3JEO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxpQ0FBaUM7QUFDMUU7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlGQUFpRixTQUFTO0FBQzFGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtFQUFrRSxTQUFTO0FBQzNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0VBQWdFLFNBQVM7QUFDekU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDREQUE0RCxTQUFTO0FBQ3JFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQsU0FBUztBQUN2RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRCxTQUFTO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQSxRQUFRO0FBQ1I7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxnQkFBZ0I7QUFDdEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrREFBK0QsS0FBSztBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLDRFQUE0RTtBQUNwRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULHFCQUFxQixTQUFTO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRSxNQUFNLFVBQVUsU0FBUztBQUMvRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkMsZUFBZTtBQUMxRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsT0FBTztBQUN2QixtRUFBbUUsTUFBTSxVQUFVLFNBQVM7QUFDNUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRSxNQUFNLFVBQVUsU0FBUztBQUMvRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxnQkFBZ0IsYUFBYTtBQUM3QjtBQUNBO0FBQ0E7QUFDQSxnRUFBZ0Us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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQSw4RUFBOEUsU0FBUztBQUN2RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLFdBQVcsU0FBUztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQsa0NBQWtDO0FBQzlGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLFVBQVU7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLFVBQVU7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEsa0RBQWtELGFBQWE7QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQSwrQ0FBK0MsYUFBYTtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4REFBOEQsTUFBTTtBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0EsK0VBQStFLGtDQUFrQztBQUNqSDtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1osUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRCwwQkFBMEIsaURBQWlELE9BQU87QUFDckk7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRCwwQkFBMEIsaURBQWlELE9BQU87QUFDdkk7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSx1REFBdUQsYUFBYTtBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJGQUEyRiwyQ0FBMkM7QUFDdEk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJGQUEyRiwyQ0FBMkM7QUFDdEk7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGdEQUFnRCxhQUFhO0FBQzdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QztBQUM3QztBQUNBO0FBQ0EseURBQXlELGFBQWE7QUFDdEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0MsK0NBQStDO0FBQ3ZGO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEMseUJBQXlCO0FBQ3pCO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxtSUFBbUkseUJBQXlCO0FBQzVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0VBQStFO0FBQy9FO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFJQUFxSSx5QkFBeUI7QUFDOUo7QUFDQSxnQkFBZ0IsV0FBVztBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FB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QUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLG9CQUFvQixTQUFTO0FBQzdCO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7O0FBRUEsa0NBQWtDLFFBQVE7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixpQkFBaUI7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQSx1Q0FBdUMsUUFBUTtBQUMvQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCLE9BQU87QUFDekI7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUyx5QkFBeUI7QUFDbEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxrQkFBa0IsZ0JBQWdCO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsOERBQThELFlBQVk7QUFDMUU7QUFDQSw4REFBOEQsWUFBWTtBQUMxRTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EscUNBQXFDLFlBQVk7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJO0FBQ0o7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQ2hmQSxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYztBQUN0QyxXQUFXLG1CQUFPLENBQUMsc0RBQVM7O0FBRTVCO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDTkEsZ0JBQWdCLG1CQUFPLENBQUMsZ0VBQWM7QUFDdEMsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7QUFDeEMsY0FBYyxtQkFBTyxDQUFDLDREQUFZO0FBQ2xDLGNBQWMsbUJBQU8sQ0FBQyw0REFBWTtBQUNsQyxjQUFjLG1CQUFPLENBQUMsNERBQVk7O0FBRWxDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUMvQkEscUJBQXFCLG1CQUFPLENBQUMsMEVBQW1CO0FBQ2hELHNCQUFzQixtQkFBTyxDQUFDLDRFQUFvQjtBQUNsRCxtQkFBbUIsbUJBQU8sQ0FBQyxzRUFBaUI7QUFDNUMsbUJBQW1CLG1CQUFPLENBQUMsc0VBQWlCO0FBQzVDLG1CQUFtQixtQkFBTyxDQUFDLHNFQUFpQjs7QUFFNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQy9CQSxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYztBQUN0QyxXQUFXLG1CQUFPLENBQUMsc0RBQVM7O0FBRTVCO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDTkEsb0JBQW9CLG1CQUFPLENBQUMsd0VBQWtCO0FBQzlDLHFCQUFxQixtQkFBTyxDQUFDLDBFQUFtQjtBQUNoRCxrQkFBa0IsbUJBQU8sQ0FBQyxvRUFBZ0I7QUFDMUMsa0JBQWtCLG1CQUFPLENBQUMsb0VBQWdCO0FBQzFDLGtCQUFrQixtQkFBTyxDQUFDLG9FQUFnQjs7QUFFMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQy9CQSxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYztBQUN0QyxXQUFXLG1CQUFPLENBQUMsc0RBQVM7O0FBRTVCO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDTkEsZ0JBQWdCLG1CQUFPLENBQUMsZ0VBQWM7QUFDdEMsV0FBVyxtQkFBTyxDQUFDLHNEQUFTOztBQUU1QjtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ05BLGVBQWUsbUJBQU8sQ0FBQyw4REFBYTtBQUNwQyxrQkFBa0IsbUJBQU8sQ0FBQyxvRUFBZ0I7QUFDMUMsa0JBQWtCLG1CQUFPLENBQUMsb0VBQWdCOztBQUUxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDMUJBLGdCQUFnQixtQkFBTyxDQUFDLGdFQUFjO0FBQ3RDLGlCQUFpQixtQkFBTyxDQUFDLGtFQUFlO0FBQ3hDLGtCQUFrQixtQkFBTyxDQUFDLG9FQUFnQjtBQUMxQyxlQUFlLG1CQUFPLENBQUMsOERBQWE7QUFDcEMsZUFBZSxtQkFBTyxDQUFDLDhEQUFhO0FBQ3BDLGVBQWUsbUJBQU8sQ0FBQyw4REFBYTs7QUFFcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUMxQkEsV0FBVyxtQkFBTyxDQUFDLHNEQUFTOztBQUU1QjtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ0xBLFdBQVcsbUJBQU8sQ0FBQyxzREFBUzs7QUFFNUI7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNMQSxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYztBQUN0QyxXQUFXLG1CQUFPLENBQUMsc0RBQVM7O0FBRTVCO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLFVBQVU7QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsVUFBVTtBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDeEJBLGdCQUFnQixtQkFBTyxDQUFDLGdFQUFjO0FBQ3RDLGtCQUFrQixtQkFBTyxDQUFDLGtFQUFlO0FBQ3pDLGNBQWMsbUJBQU8sQ0FBQywwREFBVztBQUNqQyxlQUFlLG1CQUFPLENBQUMsNERBQVk7QUFDbkMsY0FBYyxtQkFBTyxDQUFDLDREQUFZO0FBQ2xDLG1CQUFtQixtQkFBTyxDQUFDLG9FQUFnQjs7QUFFM0M7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsV0FBVyxTQUFTO0FBQ3BCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxVQUFVO0FBQ3JCLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ3RCQSxzQkFBc0IsbUJBQU8sQ0FBQyw0RUFBb0I7QUFDbEQsU0FBUyxtQkFBTyxDQUFDLGdEQUFNOztBQUV2QjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQixXQUFXLEdBQUc7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQzNCQSxTQUFTLG1CQUFPLENBQUMsZ0RBQU07O0FBRXZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsR0FBRztBQUNkLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNwQkEsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7QUFDeEMsV0FBVyxtQkFBTyxDQUFDLG9EQUFROztBQUUzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDaEJBLGlCQUFpQixtQkFBTyxDQUFDLGtFQUFlO0FBQ3hDLGFBQWEsbUJBQU8sQ0FBQyx3REFBVTs7QUFFL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2hCQSxxQkFBcUIsbUJBQU8sQ0FBQywwRUFBbUI7O0FBRWhEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLFdBQVcsR0FBRztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUN4QkEsWUFBWSxtQkFBTyxDQUFDLHdEQUFVO0FBQzlCLGdCQUFnQixtQkFBTyxDQUFDLGdFQUFjO0FBQ3RDLGtCQUFrQixtQkFBTyxDQUFDLG9FQUFnQjtBQUMxQyxpQkFBaUIsbUJBQU8sQ0FBQyxrRUFBZTtBQUN4QyxtQkFBbUIsbUJBQU8sQ0FBQyxzRUFBaUI7QUFDNUMsa0JBQWtCLG1CQUFPLENBQUMsb0VBQWdCO0FBQzFDLGdCQUFnQixtQkFBTyxDQUFDLGdFQUFjO0FBQ3RDLGtCQUFrQixtQkFBTyxDQUFDLG9FQUFnQjtBQUMxQyxvQkFBb0IsbUJBQU8sQ0FBQyx3RUFBa0I7QUFDOUMsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7QUFDeEMsbUJBQW1CLG1CQUFPLENBQUMsc0VBQWlCO0FBQzVDLGFBQWEsbUJBQU8sQ0FBQywwREFBVztBQUNoQyxxQkFBcUIsbUJBQU8sQ0FBQywwRUFBbUI7QUFDaEQscUJBQXFCLG1CQUFPLENBQUMsMEVBQW1CO0FBQ2hELHNCQUFzQixtQkFBTyxDQUFDLDRFQUFvQjtBQUNsRCxjQUFjLG1CQUFPLENBQUMsMERBQVc7QUFDakMsZUFBZSxtQkFBTyxDQUFDLDREQUFZO0FBQ25DLFlBQVksbUJBQU8sQ0FBQyxzREFBUztBQUM3QixlQUFlLG1CQUFPLENBQUMsNERBQVk7QUFDbkMsWUFBWSxtQkFBTyxDQUFDLHNEQUFTO0FBQzdCLFdBQVcsbUJBQU8sQ0FBQyxvREFBUTtBQUMzQixhQUFhLG1CQUFPLENBQUMsd0RBQVU7O0FBRS9CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZCxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0EsV0FBVyxVQUFVO0FBQ3JCLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLGFBQWEsR0FBRztBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsSUFBSTtBQUNKO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNyS0EsZUFBZSxtQkFBTyxDQUFDLDREQUFZOztBQUVuQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7Ozs7Ozs7Ozs7O0FDN0JBLGdCQUFnQixtQkFBTyxDQUFDLGdFQUFjO0FBQ3RDLGNBQWMsbUJBQU8sQ0FBQywwREFBVzs7QUFFakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsVUFBVTtBQUNyQixXQUFXLFVBQVU7QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDbkJBLGFBQWEsbUJBQU8sQ0FBQywwREFBVztBQUNoQyxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYztBQUN0QyxxQkFBcUIsbUJBQU8sQ0FBQywwRUFBbUI7O0FBRWhEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUMzQkEsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7QUFDeEMsbUJBQW1CLG1CQUFPLENBQUMsb0VBQWdCOztBQUUzQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2pCQSxzQkFBc0IsbUJBQU8sQ0FBQyw0RUFBb0I7QUFDbEQsbUJBQW1CLG1CQUFPLENBQUMsb0VBQWdCOztBQUUzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsV0FBVyxHQUFHO0FBQ2QsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQSxXQUFXLFVBQVU7QUFDckIsV0FBVyxRQUFRO0FBQ25CLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUMzQkEsWUFBWSxtQkFBTyxDQUFDLHdEQUFVO0FBQzlCLGtCQUFrQixtQkFBTyxDQUFDLG9FQUFnQjtBQUMxQyxpQkFBaUIsbUJBQU8sQ0FBQyxrRUFBZTtBQUN4QyxtQkFBbUIsbUJBQU8sQ0FBQyxzRUFBaUI7QUFDNUMsYUFBYSxtQkFBTyxDQUFDLDBEQUFXO0FBQ2hDLGNBQWMsbUJBQU8sQ0FBQywwREFBVztBQUNqQyxlQUFlLG1CQUFPLENBQUMsNERBQVk7QUFDbkMsbUJBQW1CLG1CQUFPLENBQUMsb0VBQWdCOztBQUUzQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQixXQUFXLFVBQVU7QUFDckIsV0FBVyxVQUFVO0FBQ3JCLFdBQVcsUUFBUTtBQUNuQixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNsRkEsYUFBYSxtQkFBTyxDQUFDLDBEQUFXO0FBQ2hDLG1CQUFtQixtQkFBTyxDQUFDLG9FQUFnQjs7QUFFM0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNqQkEsaUJBQWlCLG1CQUFPLENBQUMsZ0VBQWM7QUFDdkMsZUFBZSxtQkFBTyxDQUFDLDhEQUFhO0FBQ3BDLGVBQWUsbUJBQU8sQ0FBQyw0REFBWTtBQUNuQyxlQUFlLG1CQUFPLENBQUMsOERBQWE7O0FBRXBDO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DOztBQUVwQztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDOUNBLGFBQWEsbUJBQU8sQ0FBQywwREFBVztBQUNoQyxtQkFBbUIsbUJBQU8sQ0FBQyxvRUFBZ0I7O0FBRTNDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZCxhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDakJBLGlCQUFpQixtQkFBTyxDQUFDLGtFQUFlO0FBQ3hDLGVBQWUsbUJBQU8sQ0FBQyw0REFBWTtBQUNuQyxtQkFBbUIsbUJBQU8sQ0FBQyxvRUFBZ0I7O0FBRTNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZCxhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUMzREEsa0JBQWtCLG1CQUFPLENBQUMsb0VBQWdCO0FBQzFDLGlCQUFpQixtQkFBTyxDQUFDLGtFQUFlOztBQUV4QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQzdCQSxlQUFlLG1CQUFPLENBQUMsNERBQVk7QUFDbkMsa0JBQWtCLG1CQUFPLENBQUMsb0VBQWdCO0FBQzFDLG1CQUFtQixtQkFBTyxDQUFDLHNFQUFpQjs7QUFFNUM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFVBQVU7QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxVQUFVO0FBQ3JCLGFBQWEsVUFBVTtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNaQSxpQkFBaUIsbUJBQU8sQ0FBQyxrRUFBZTs7QUFFeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLGFBQWE7QUFDeEIsYUFBYSxhQUFhO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7O0FDZkEsV0FBVyxtQkFBTyxDQUFDLHNEQUFTOztBQUU1QjtBQUNBLGtCQUFrQixLQUEwQjs7QUFFNUM7QUFDQSxnQ0FBZ0MsUUFBYTs7QUFFN0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxTQUFTO0FBQ3BCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDbENBLHVCQUF1QixtQkFBTyxDQUFDLDhFQUFxQjs7QUFFcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxTQUFTO0FBQ3BCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2ZBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNoQkEsYUFBYSxtQkFBTyxDQUFDLDBEQUFXOztBQUVoQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2pCQSx1QkFBdUIsbUJBQU8sQ0FBQyw4RUFBcUI7O0FBRXBEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsU0FBUztBQUNwQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNuQkEsa0JBQWtCLG1CQUFPLENBQUMsb0VBQWdCO0FBQzFDLHNCQUFzQixtQkFBTyxDQUFDLDRFQUFvQjs7QUFFbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsUUFBUSxVQUFVO0FBQzdCLFdBQVcsVUFBVTtBQUNyQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCOztBQUV4QjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUN2Q0EsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7QUFDeEMsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7O0FBRXhDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUSxVQUFVO0FBQzdCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNmQSxpQkFBaUIsbUJBQU8sQ0FBQyxrRUFBZTtBQUN4QyxtQkFBbUIsbUJBQU8sQ0FBQyxzRUFBaUI7O0FBRTVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUSxVQUFVO0FBQzdCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNmQSxXQUFXLG1CQUFPLENBQUMsc0RBQVM7O0FBRTVCO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDTEEsZ0JBQWdCLG1CQUFPLENBQUMsZ0VBQWM7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLElBQUk7QUFDSixDQUFDOztBQUVEOzs7Ozs7Ozs7OztBQ1ZBLGVBQWUsbUJBQU8sQ0FBQyw4REFBYTtBQUNwQyxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYztBQUN0QyxlQUFlLG1CQUFPLENBQUMsOERBQWE7O0FBRXBDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixXQUFXLFFBQVE7QUFDbkIsV0FBVyxVQUFVO0FBQ3JCLFdBQVcsVUFBVTtBQUNyQixXQUFXLFFBQVE7QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDbkZBLGFBQWEsbUJBQU8sQ0FBQywwREFBVztBQUNoQyxpQkFBaUIsbUJBQU8sQ0FBQyxrRUFBZTtBQUN4QyxTQUFTLG1CQUFPLENBQUMsZ0RBQU07QUFDdkIsa0JBQWtCLG1CQUFPLENBQUMsb0VBQWdCO0FBQzFDLGlCQUFpQixtQkFBTyxDQUFDLGtFQUFlO0FBQ3hDLGlCQUFpQixtQkFBTyxDQUFDLGtFQUFlOztBQUV4QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQixXQUFXLFVBQVU7QUFDckIsV0FBVyxVQUFVO0FBQ3JCLFdBQVcsUUFBUTtBQUNuQixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUMvR0EsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7O0FBRXhDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQixXQUFXLFVBQVU7QUFDckIsV0FBVyxVQUFVO0FBQ3JCLFdBQVcsUUFBUTtBQUNuQixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ3pGQTtBQUNBLHdCQUF3QixxQkFBTSxnQkFBZ0IscUJBQU0sSUFBSSxxQkFBTSxzQkFBc0IscUJBQU07O0FBRTFGOzs7Ozs7Ozs7OztBQ0hBLHFCQUFxQixtQkFBTyxDQUFDLDBFQUFtQjtBQUNoRCxpQkFBaUIsbUJBQU8sQ0FBQyxrRUFBZTtBQUN4QyxXQUFXLG1CQUFPLENBQUMsb0RBQVE7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNmQSxxQkFBcUIsbUJBQU8sQ0FBQywwRUFBbUI7QUFDaEQsbUJBQW1CLG1CQUFPLENBQUMsc0VBQWlCO0FBQzVDLGFBQWEsbUJBQU8sQ0FBQyx3REFBVTs7QUFFL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDaEJBLGdCQUFnQixtQkFBTyxDQUFDLGdFQUFjOztBQUV0QztBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsYUFBYSxHQUFHO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2pCQSxtQkFBbUIsbUJBQU8sQ0FBQyxzRUFBaUI7QUFDNUMsZUFBZSxtQkFBTyxDQUFDLDhEQUFhOztBQUVwQztBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsYUFBYSxHQUFHO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDaEJBLGNBQWMsbUJBQU8sQ0FBQyw0REFBWTs7QUFFbEM7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNMQSxhQUFhLG1CQUFPLENBQUMsMERBQVc7O0FBRWhDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDN0NBLGtCQUFrQixtQkFBTyxDQUFDLG9FQUFnQjtBQUMxQyxnQkFBZ0IsbUJBQU8sQ0FBQyw4REFBYTs7QUFFckM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7Ozs7Ozs7Ozs7O0FDN0JBLGdCQUFnQixtQkFBTyxDQUFDLGdFQUFjO0FBQ3RDLG1CQUFtQixtQkFBTyxDQUFDLHNFQUFpQjtBQUM1QyxpQkFBaUIsbUJBQU8sQ0FBQyxrRUFBZTtBQUN4QyxnQkFBZ0IsbUJBQU8sQ0FBQyw4REFBYTs7QUFFckM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ3hCQSxlQUFlLG1CQUFPLENBQUMsOERBQWE7QUFDcEMsVUFBVSxtQkFBTyxDQUFDLG9EQUFRO0FBQzFCLGNBQWMsbUJBQU8sQ0FBQyw0REFBWTtBQUNsQyxVQUFVLG1CQUFPLENBQUMsb0RBQVE7QUFDMUIsY0FBYyxtQkFBTyxDQUFDLDREQUFZO0FBQ2xDLGlCQUFpQixtQkFBTyxDQUFDLGtFQUFlO0FBQ3hDLGVBQWUsbUJBQU8sQ0FBQyw4REFBYTs7QUFFcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWEsUUFBUTtBQUNyQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUN6REE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLGFBQWEsR0FBRztBQUNoQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNaQSxtQkFBbUIsbUJBQU8sQ0FBQyxzRUFBaUI7O0FBRTVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2hCQSxtQkFBbUIsbUJBQU8sQ0FBQyxzRUFBaUI7O0FBRTVDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhLEdBQUc7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQzdCQSxtQkFBbUIsbUJBQU8sQ0FBQyxzRUFBaUI7O0FBRTVDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDdEJBLG1CQUFtQixtQkFBTyxDQUFDLHNFQUFpQjs7QUFFNUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxHQUFHO0FBQ2QsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ3RCQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ3pCQSx1QkFBdUIsbUJBQU8sQ0FBQyw4RUFBcUI7QUFDcEQsb0JBQW9CLG1CQUFPLENBQUMsd0VBQWtCO0FBQzlDLGtCQUFrQixtQkFBTyxDQUFDLG9FQUFnQjtBQUMxQyxrQkFBa0IsbUJBQU8sQ0FBQyxvRUFBZ0I7QUFDMUMsc0JBQXNCLG1CQUFPLENBQUMsNEVBQW9COztBQUVsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsV0FBVyxTQUFTO0FBQ3BCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQzVFQSxpQkFBaUIsbUJBQU8sQ0FBQyxrRUFBZTtBQUN4QyxtQkFBbUIsbUJBQU8sQ0FBQyxzRUFBaUI7QUFDNUMsa0JBQWtCLG1CQUFPLENBQUMsb0VBQWdCOztBQUUxQztBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2pCQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZCxXQUFXLFFBQVE7QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2RBLGlCQUFpQixtQkFBTyxDQUFDLGtFQUFlOztBQUV4QztBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFVBQVU7QUFDckIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ25CQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDWkEsbUJBQW1CLG1CQUFPLENBQUMsc0VBQWlCOztBQUU1QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNsQ0EsbUJBQW1CLG1CQUFPLENBQUMsc0VBQWlCOztBQUU1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxHQUFHO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDbEJBLG1CQUFtQixtQkFBTyxDQUFDLHNFQUFpQjs7QUFFNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNmQSxtQkFBbUIsbUJBQU8sQ0FBQyxzRUFBaUI7O0FBRTVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLEdBQUc7QUFDZCxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ3pCQSxXQUFXLG1CQUFPLENBQUMsc0RBQVM7QUFDNUIsZ0JBQWdCLG1CQUFPLENBQUMsZ0VBQWM7QUFDdEMsVUFBVSxtQkFBTyxDQUFDLG9EQUFROztBQUUxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDcEJBLGlCQUFpQixtQkFBTyxDQUFDLGtFQUFlOztBQUV4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNqQkEsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7O0FBRXhDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhLEdBQUc7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDZkEsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7O0FBRXhDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDZkEsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7O0FBRXhDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLEdBQUc7QUFDZCxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDakJBLGdCQUFnQixtQkFBTyxDQUFDLGdFQUFjOztBQUV0QztBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ0xBLGNBQWMsbUJBQU8sQ0FBQyw0REFBWTs7QUFFbEM7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7Ozs7QUNuQkEsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7O0FBRXhDO0FBQ0Esa0JBQWtCLEtBQTBCOztBQUU1QztBQUNBLGdDQUFnQyxRQUFhOztBQUU3QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSixDQUFDOztBQUVEOzs7Ozs7Ozs7OztBQzdCQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFVBQVU7QUFDckIsV0FBVyxVQUFVO0FBQ3JCLGFBQWEsVUFBVTtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDZEEsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7O0FBRXhDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNSQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2pCQSxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYzs7QUFFdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLGFBQWEsR0FBRztBQUNoQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2JBLGdCQUFnQixtQkFBTyxDQUFDLGdFQUFjO0FBQ3RDLFVBQVUsbUJBQU8sQ0FBQyxvREFBUTtBQUMxQixlQUFlLG1CQUFPLENBQUMsOERBQWE7O0FBRXBDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsR0FBRztBQUNkLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNqQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxVQUFVO0FBQ3JCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ3pCQSxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYzs7QUFFdEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxHQUFHO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixRQUFRLElBQUksUUFBUTtBQUN4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZCxXQUFXLEdBQUc7QUFDZCxhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBLGtCQUFrQjtBQUNsQixpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDcENBLHNCQUFzQixtQkFBTyxDQUFDLDRFQUFvQjtBQUNsRCxtQkFBbUIsbUJBQU8sQ0FBQyxvRUFBZ0I7O0FBRTNDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixtQkFBbUI7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQyxtQkFBbUI7QUFDbEU7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ25DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDekJBLGlCQUFpQixtQkFBTyxDQUFDLGdFQUFjO0FBQ3ZDLGVBQWUsbUJBQU8sQ0FBQyw0REFBWTs7QUFFbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7OztBQ2hDQSxXQUFXLG1CQUFPLENBQUMsc0RBQVM7QUFDNUIsZ0JBQWdCLG1CQUFPLENBQUMsOERBQWE7O0FBRXJDO0FBQ0Esa0JBQWtCLEtBQTBCOztBQUU1QztBQUNBLGdDQUFnQyxRQUFhOztBQUU3QztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDckNBLGtCQUFrQixtQkFBTyxDQUFDLG9FQUFnQjs7QUFFMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLFdBQVcsR0FBRztBQUNkLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUNsQ0EsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7QUFDeEMsZUFBZSxtQkFBTyxDQUFDLDREQUFZOztBQUVuQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDcENBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZCxhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ2xDQSxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYztBQUN0QyxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYztBQUN0QyxlQUFlLG1CQUFPLENBQUMsOERBQWE7O0FBRXBDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZCxhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZCxhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7Ozs7Ozs7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZCxhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQzVCQSxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYztBQUN0QyxnQkFBZ0IsbUJBQU8sQ0FBQyxnRUFBYztBQUN0QyxlQUFlLG1CQUFPLENBQUMsOERBQWE7O0FBRXBDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLEdBQUc7QUFDZCxhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQzFCQSx1QkFBdUIsbUJBQU8sQ0FBQyw4RUFBcUI7QUFDcEQsZ0JBQWdCLG1CQUFPLENBQUMsZ0VBQWM7QUFDdEMsZUFBZSxtQkFBTyxDQUFDLDhEQUFhOztBQUVwQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUMxQkEsb0JBQW9CLG1CQUFPLENBQUMsd0VBQWtCO0FBQzlDLGVBQWUsbUJBQU8sQ0FBQyw4REFBYTtBQUNwQyxrQkFBa0IsbUJBQU8sQ0FBQyxrRUFBZTs7QUFFekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQ3BDQSxvQkFBb0IsbUJBQU8sQ0FBQyx3RUFBa0I7QUFDOUMsaUJBQWlCLG1CQUFPLENBQUMsa0VBQWU7QUFDeEMsa0JBQWtCLG1CQUFPLENBQUMsa0VBQWU7O0FBRXpDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7Ozs7Ozs7OztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7Ozs7Ozs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFNBQVM7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7OztVQ2pCQTtVQUNBOztVQUVBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBOztVQUVBO1VBQ0E7O1VBRUE7VUFDQTs7VUFFQTtVQUNBO1VBQ0E7Ozs7O1dDekJBO1dBQ0E7V0FDQTtXQUNBO1dBQ0EsR0FBRztXQUNIO1dBQ0E7V0FDQSxDQUFDOzs7OztXQ1BEO1dBQ0E7V0FDQTtXQUNBLHVEQUF1RCxpQkFBaUI7V0FDeEU7V0FDQSxnREFBZ0QsYUFBYTtXQUM3RDs7Ozs7V0NOQTtXQUNBO1dBQ0E7V0FDQTtXQUNBOzs7Ozs7Ozs7Ozs7O0FDSm9DO0FBRXBDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN4RCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzdDLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFakQsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNWLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDekMsTUFBTSxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekIsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNaLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDM0MsTUFBTSxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDMUIsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQsUUFBUSxFQUFFLENBQUM7QUFDWixDQUFDLENBQUMsQ0FBQztBQUVIOzs7R0FHRztBQUNILFNBQVMsc0JBQXNCLENBQUMsS0FBeUI7SUFDeEQsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUMxQixPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM5QixNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUM1QixNQUFNLENBQUMsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDUCxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pCLENBQUM7SUFDRixDQUFDO0FBQ0YsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxRQUFRO0lBQ2hCLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBZSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDM0QsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUUxQyxJQUFJLFNBQVMsS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUMxQixNQUFNLENBQUMsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3RDLENBQUMsQ0FBQyxTQUFTLEdBQUcsd0VBQXdFLENBQUM7UUFDdkYsTUFBTSxDQUFDLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ1AsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNiLENBQUM7SUFDRixDQUFDO0lBRUQsSUFBSSxTQUFTLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDNUIsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUUxRCxNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLEVBQUUsQ0FBQyxTQUFTLEdBQUcsNkNBQTZDLENBQUM7UUFDN0QsTUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMzQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQ1IsRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNmLENBQUM7UUFFRCxNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLEVBQUUsQ0FBQyxTQUFTLEdBQUcsK0NBQStDLENBQUM7UUFDL0QsTUFBTSxFQUFFLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMzQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQ1IsRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNmLENBQUM7UUFFRCxzQkFBc0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMvQixDQUFDO0FBQ0YsQ0FBQztBQUVEOzs7R0FHRztBQUNILEtBQUssVUFBVSxXQUFXLENBQUMsWUFBcUI7SUFDL0MsSUFBSSxDQUFDO1FBQ0osTUFBTSxNQUFNLEdBQUcsTUFBTSw4Q0FBRyxDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUNyRixNQUFNLE1BQU0sQ0FBQyxRQUFRLENBQUMsbUJBQW1CLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDekQsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2hCLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDcEIsQ0FBQztBQUNGLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvQG9wZW5maW4vY29yZS9vdXQvbW9jay5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19EYXRhVmlldy5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19IYXNoLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX0xpc3RDYWNoZS5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19NYXAuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fTWFwQ2FjaGUuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fUHJvbWlzZS5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19TZXQuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fU2V0Q2FjaGUuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fU3RhY2suanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fU3ltYm9sLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX1VpbnQ4QXJyYXkuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fV2Vha01hcC5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19hcnJheUVhY2guanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYXJyYXlGaWx0ZXIuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYXJyYXlMaWtlS2V5cy5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19hcnJheVB1c2guanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYXJyYXlTb21lLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Fzc2lnblZhbHVlLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Fzc29jSW5kZXhPZi5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19iYXNlQXNzaWduLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Jhc2VBc3NpZ25Jbi5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19iYXNlQXNzaWduVmFsdWUuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUNsb25lLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Jhc2VDcmVhdGUuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUdldEFsbEtleXMuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUdldFRhZy5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19iYXNlSXNBcmd1bWVudHMuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUlzRXF1YWwuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUlzRXF1YWxEZWVwLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Jhc2VJc01hcC5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19iYXNlSXNOYXRpdmUuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUlzU2V0LmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Jhc2VJc1R5cGVkQXJyYXkuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUtleXMuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZUtleXNJbi5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19iYXNlVGltZXMuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fYmFzZVVuYXJ5LmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2NhY2hlSGFzLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2Nsb25lQXJyYXlCdWZmZXIuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fY2xvbmVCdWZmZXIuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fY2xvbmVEYXRhVmlldy5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19jbG9uZVJlZ0V4cC5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19jbG9uZVN5bWJvbC5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19jbG9uZVR5cGVkQXJyYXkuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fY29weUFycmF5LmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2NvcHlPYmplY3QuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fY29weVN5bWJvbHMuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fY29weVN5bWJvbHNJbi5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19jb3JlSnNEYXRhLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2RlZmluZVByb3BlcnR5LmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2VxdWFsQXJyYXlzLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2VxdWFsQnlUYWcuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZXF1YWxPYmplY3RzLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2ZyZWVHbG9iYWwuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZ2V0QWxsS2V5cy5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19nZXRBbGxLZXlzSW4uanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZ2V0TWFwRGF0YS5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19nZXROYXRpdmUuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZ2V0UHJvdG90eXBlLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2dldFJhd1RhZy5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19nZXRTeW1ib2xzLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2dldFN5bWJvbHNJbi5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19nZXRUYWcuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fZ2V0VmFsdWUuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faGFzaENsZWFyLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2hhc2hEZWxldGUuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faGFzaEdldC5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19oYXNoSGFzLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2hhc2hTZXQuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faW5pdENsb25lQXJyYXkuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faW5pdENsb25lQnlUYWcuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faW5pdENsb25lT2JqZWN0LmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2lzSW5kZXguanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9faXNLZXlhYmxlLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2lzTWFza2VkLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2lzUHJvdG90eXBlLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2xpc3RDYWNoZUNsZWFyLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2xpc3RDYWNoZURlbGV0ZS5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19saXN0Q2FjaGVHZXQuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fbGlzdENhY2hlSGFzLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX2xpc3RDYWNoZVNldC5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19tYXBDYWNoZUNsZWFyLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX21hcENhY2hlRGVsZXRlLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX21hcENhY2hlR2V0LmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX21hcENhY2hlSGFzLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX21hcENhY2hlU2V0LmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX21hcFRvQXJyYXkuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fbmF0aXZlQ3JlYXRlLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX25hdGl2ZUtleXMuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fbmF0aXZlS2V5c0luLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX25vZGVVdGlsLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX29iamVjdFRvU3RyaW5nLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX292ZXJBcmcuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fcm9vdC5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19zZXRDYWNoZUFkZC5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19zZXRDYWNoZUhhcy5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL19zZXRUb0FycmF5LmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvX3N0YWNrQ2xlYXIuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fc3RhY2tEZWxldGUuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fc3RhY2tHZXQuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fc3RhY2tIYXMuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fc3RhY2tTZXQuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9fdG9Tb3VyY2UuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9jbG9uZURlZXAuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9lcS5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2lzQXJndW1lbnRzLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvaXNBcnJheS5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2lzQXJyYXlMaWtlLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvaXNCdWZmZXIuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9pc0VxdWFsLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvaXNGdW5jdGlvbi5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2lzTGVuZ3RoLmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvaXNNYXAuanMiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2xvZGFzaC9pc09iamVjdC5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2lzT2JqZWN0TGlrZS5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2lzU2V0LmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gvaXNUeXBlZEFycmF5LmpzIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nLy4uLy4uLy4uL25vZGVfbW9kdWxlcy9sb2Rhc2gva2V5cy5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL2tleXNJbi5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL3N0dWJBcnJheS5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uLi8uLi8uLi9ub2RlX21vZHVsZXMvbG9kYXNoL3N0dWJGYWxzZS5qcyIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy93ZWJwYWNrL3J1bnRpbWUvZ2xvYmFsIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvd2VicGFjay9ydW50aW1lL25vZGUgbW9kdWxlIGRlY29yYXRvciIsIndlYnBhY2s6Ly93YXJuLWJlZm9yZS1jbG9zaW5nLWRpYWxvZy8uL2NsaWVudC9zcmMvZGlhbG9nLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIHJlcXVpcmUkJDAgPSByZXF1aXJlKCdldmVudHMnKTtcbnZhciByZXF1aXJlJCQwJDEgPSByZXF1aXJlKCdsb2Rhc2gvY2xvbmVEZWVwJyk7XG52YXIgcmVxdWlyZSQkMyA9IHJlcXVpcmUoJ2xvZGFzaC9pc0VxdWFsJyk7XG5cbmZ1bmN0aW9uIF9tZXJnZU5hbWVzcGFjZXMobiwgbSkge1xuXHRtLmZvckVhY2goZnVuY3Rpb24gKGUpIHtcblx0XHRlICYmIHR5cGVvZiBlICE9PSAnc3RyaW5nJyAmJiAhQXJyYXkuaXNBcnJheShlKSAmJiBPYmplY3Qua2V5cyhlKS5mb3JFYWNoKGZ1bmN0aW9uIChrKSB7XG5cdFx0XHRpZiAoayAhPT0gJ2RlZmF1bHQnICYmICEoayBpbiBuKSkge1xuXHRcdFx0XHR2YXIgZCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoZSwgayk7XG5cdFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShuLCBrLCBkLmdldCA/IGQgOiB7XG5cdFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcblx0XHRcdFx0XHRnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGVba107IH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xuXHRyZXR1cm4gT2JqZWN0LmZyZWV6ZShuKTtcbn1cblxudmFyIGNvbW1vbmpzR2xvYmFsID0gdHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsVGhpcyA6IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcgPyBzZWxmIDoge307XG5cbmZ1bmN0aW9uIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzICh4KSB7XG5cdHJldHVybiB4ICYmIHguX19lc01vZHVsZSAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoeCwgJ2RlZmF1bHQnKSA/IHhbJ2RlZmF1bHQnXSA6IHg7XG59XG5cbnZhciBPcGVuRmluJDIgPSB7fTtcblxudmFyIGV2ZW50cyA9IHt9O1xuXG52YXIgYXBwbGljYXRpb24kMSA9IHt9O1xuXG4vKipcbiAqIE5hbWVzcGFjZSBmb3IgZXZlbnRzIHRoYXQgY2FuIGJlIGVtaXR0ZWQgYnkgYW4ge0BsaW5rIE9wZW5GaW4uQXBwbGljYXRpb259LiAgSW5jbHVkZXMgZXZlbnRzXG4gKiByZS1wcm9wYWdhdGVkIGZyb20gdGhlIHtAbGluayBPcGVuRmluLldpbmRvd30gKGFuZCwgdHJhbnNpdGl2ZWx5LCB7QGxpbmsgT3BlbkZpbi5WaWV3fSkgbGV2ZWwsIHByZWZpeGVkIHdpdGggYHdpbmRvdy1gIChhbmQgYWxzbywgaWYgYXBwbGljYWJsZSwgYHZpZXctYCkuXG4gKiBGb3IgZXhhbXBsZSwgYSB2aWV3J3MgXCJhdHRhY2hlZFwiIGV2ZW50IHdpbGwgZmlyZSBhcyAnd2luZG93LXZpZXctYXR0YWNoZWQnIGF0IHRoZSBhcHBsaWNhdGlvbiBsZXZlbC5cbiAqXG4gKiBFdmVudCBwYXlsb2FkcyBhcmUgZG9jdW1lbnRlZCBhcyBpbnRlcmZhY2VzLCB3aGlsZSBhbGdlYnJhaWMgaGVscGVyIHR5cGVzIGFuZCBkZXJpdmVkIHR5cGVzIGFyZSBkb2N1bWVudGVkIGFzIHR5cGUgYWxpYXNlcy5cbiAqIEV2ZW50cyBnYWluIG1ldGFkYXRhIGFzIHRoZXkgcHJvcGFnYXRlLCB3aGljaCBpcyAqbm90KiBwcmVzZW50IG9uIHRoZSBleHBsaWNpdCBwYXlsb2FkIGludGVyZmFjZXMuICBUbyByZWZlciB0byB0aGUgZnVsbCB0eXBlXG4gKiBvZiBhbiBldmVudCBhcyBpdCB3b3VsZCBiZSByYWlzZWQgb24gdGhpcyBlbWl0dGVyLCB1c2Uge0BsaW5rIFBheWxvYWR9LlxuICpcbiAqIFRoaXMgbmFtZXNwYWNlIGNvbnRhaW5zIG9ubHkgcGF5bG9hZCBzaGFwZXMgZm9yIGV2ZW50cyB0aGF0IGFyZSB1bmlxdWUgdG8gYEFwcGxpY2F0aW9uYC4gIEV2ZW50cyB0aGF0IHByb3BhZ2F0ZSB0byBgQXBwbGljYXRpb25gIGZyb21cbiAqIGNoaWxkIHtAbGluayBPcGVuRmluLldpbmRvdyB3aW5kb3dzfSBhbmQge0BsaW5rIE9wZW5GaW4uVmlldyB2aWV3c30gYXJlIGRlZmluZWQgaW4gdGhlIHtAbGluayBPcGVuRmluLldpbmRvd0V2ZW50c30gYW5kXG4gKiB7QGxpbmsgT3BlbkZpbi5WaWV3RXZlbnRzfSBuYW1lc3BhY2VzLiAgRm9yIGEgbGlzdCBvZiB2YWxpZCBzdHJpbmcga2V5cyBmb3IgKmFsbCogYXBwbGljYXRpb24gZXZlbnRzLCBzZWUge0BsaW5rIEFwcGxpY2F0aW9uLm9uIEFwcGxpY2F0aW9uLm9ufS5cbiAqXG4gKiB7QGxpbmsgQXBwbGljYXRpb25Tb3VyY2VkRXZlbnQgQXBwbGljYXRpb24tc291cmNlZCBldmVudHN9IChpLmUuIHRob3NlIHRoYXQgaGF2ZSBub3QgcHJvcGFnYXRlZCBmcm9tIHtAbGluayBPcGVuRmluLlZpZXdFdmVudHMgVmlld3N9XG4gKiBvciB7QGxpbmsgT3BlbkZpbi5XaW5kb3dFdmVudHMgV2luZG93c30gcmUtcHJvcGFnYXRlIHRvIHtAbGluayBPcGVuRmluLlN5c3RlbUV2ZW50cyBTeXN0ZW19IHdpdGggdGhlaXIgdHlwZSBzdHJpbmcgcHJlZml4ZWQgd2l0aCBgYXBwbGljYXRpb24tYC5cbiAqIHtAbGluayBBcHBsaWNhdGlvbldpbmRvd0V2ZW50IEFwcGxpY2F0aW9uIGV2ZW50cyB0aGF0IGFyZSB0aWVkIHRvIFdpbmRvd3MgYnV0IGRvIG5vdCBwcm9wYWdhdGUgZnJvbSB0aGVtfVxuICogYXJlIHByb3BhZ2F0ZWQgdG8gYFN5c3RlbWAgd2l0aG91dCBhbnkgdHlwZSBzdHJpbmcgcHJlZml4aW5nLlxuICpcbiAqIFwiUmVxdWVzdGVkXCIgZXZlbnRzIChlLmcuIHtAbGluayBSdW5SZXF1ZXN0ZWRFdmVudH0pIGRvIG5vdCBwcm9wYWdhdGUuXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShhcHBsaWNhdGlvbiQxLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIGJhc2UkMSA9IHt9O1xuXG4vKipcbiAqIE5hbWVzcGFjZSBmb3Igc2hhcmVkIGV2ZW50IHBheWxvYWRzIGFuZCB1dGlsaXR5IHR5cGVzIGNvbW1vbiB0byBhbGwgZXZlbnQgZW1pdHRlcnMuXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShiYXNlJDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG52YXIgZXh0ZXJuYWxBcHBsaWNhdGlvbiQxID0ge307XG5cbi8qKlxuICogTmFtZXNwYWNlIGZvciBldmVudHMgdGhhdCBjYW4gYmUgdHJhbnNtaXR0ZWQgYnkgYW4ge0BsaW5rIE9wZW5GaW4uRXh0ZXJuYWxBcHBsaWNhdGlvbn0uXG4gKlxuICogRXZlbnQgcGF5bG9hZHMgYXJlIGRvY3VtZW50ZWQgYXMgaW50ZXJmYWNlcywgd2hpbGUgYWxnZWJyYWljIGhlbHBlciB0eXBlcyBhbmQgZGVyaXZlZCB0eXBlcyBhcmUgZG9jdW1lbnRlZCBhcyB0eXBlIGFsaWFzZXMuXG4gKiBFdmVudHMgZ2FpbiBtZXRhZGF0YSBhcyB0aGV5IHByb3BhZ2F0ZSwgd2hpY2ggaXMgKm5vdCogcHJlc2VudCBvbiB0aGUgZXhwbGljaXQgcGF5bG9hZCBpbnRlcmZhY2VzLiAgVG8gcmVmZXIgdG8gdGhlIGZ1bGwgdHlwZVxuICogb2YgYW4gZXZlbnQgYXMgaXQgd291bGQgYmUgcmFpc2VkIG9uIHRoaXMgZW1pdHRlciwgdXNlIHtAbGluayBQYXlsb2FkfS5cbiAqXG4gKiBGb3IgYSBsaXN0IG9mIHZhbGlkIHN0cmluZyBrZXlzIGZvciBleHRlcm5hbCBhcHBsaWNhdGlvbiBldmVudHMsIHNlZSB7QGxpbmsgRXh0ZXJuYWxBcHBsaWNhdGlvbi5vbiBFeHRlcm5hbEFwcGxpY2F0aW9uLm9ufS5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4dGVybmFsQXBwbGljYXRpb24kMSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cbnZhciBmcmFtZSQxID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShmcmFtZSQxLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIGdsb2JhbEhvdGtleSQxID0ge307XG5cbi8qKlxuICpcbiAqIE5hbWVzcGFjZSBmb3IgZXZlbnRzIHRoYXQgY2FuIGJlIHRyYW5zbWl0dGVkIGJ5IHtAbGluayBHbG9iYWxIb3RrZXkuR2xvYmFsSG90a2V5fS5cbiAqXG4gKiBFdmVudCBwYXlsb2FkcyBhcmUgZG9jdW1lbnRlZCBhcyBpbnRlcmZhY2VzLCB3aGlsZSBhbGdlYnJhaWMgaGVscGVyIHR5cGVzIGFuZCBkZXJpdmVkIHR5cGVzIGFyZSBkb2N1bWVudGVkIGFzIHR5cGUgYWxpYXNlcy5cbiAqIEV2ZW50cyBnYWluIG1ldGFkYXRhIGFzIHRoZXkgcHJvcGFnYXRlLCB3aGljaCBpcyAqbm90KiBwcmVzZW50IG9uIHRoZSBleHBsaWNpdCBwYXlsb2FkIGludGVyZmFjZXMuICBUbyByZWZlciB0byB0aGUgZnVsbCB0eXBlXG4gKiBvZiBhbiBldmVudCBhcyBpdCB3b3VsZCBiZSByYWlzZWQgb24gdGhpcyBlbWl0dGVyLCB1c2Uge0BsaW5rIFBheWxvYWR9LlxuICpcbiAqIEZvciBhIGxpc3Qgb2YgdmFsaWQgc3RyaW5nIGtleXMgZm9yIGdsb2JhbCBob3RrZXkgZXZlbnRzLCBzZWUge0BsaW5rIEdsb2JhbEhvdGtleS5HbG9iYWxIb3RrZXkub24gR2xvYmFsSG90a2V5Lm9ufS5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGdsb2JhbEhvdGtleSQxLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIHBsYXRmb3JtJDEgPSB7fTtcblxuLyoqXG4gKlxuICogTmFtZXNwYWNlIGZvciBldmVudHMgdGhhdCBjYW4gZW1pdHRlZCBieSBhIHtAbGluayBPcGVuRmluLlBsYXRmb3JtfS5cbiAqXG4gKiBFdmVudCBwYXlsb2FkcyBhcmUgZG9jdW1lbnRlZCBhcyBpbnRlcmZhY2VzLCB3aGlsZSBhbGdlYnJhaWMgaGVscGVyIHR5cGVzIGFuZCBkZXJpdmVkIHR5cGVzIGFyZSBkb2N1bWVudGVkIGFzIHR5cGUgYWxpYXNlcy5cbiAqIEV2ZW50cyBnYWluIG1ldGFkYXRhIGFzIHRoZXkgcHJvcGFnYXRlLCB3aGljaCBpcyAqbm90KiBwcmVzZW50IG9uIHRoZSBleHBsaWNpdCBwYXlsb2FkIGludGVyZmFjZXMuICBUbyByZWZlciB0byB0aGUgZnVsbCB0eXBlXG4gKiBvZiBhbiBldmVudCBhcyBpdCB3b3VsZCBiZSByYWlzZWQgb24gdGhpcyBlbWl0dGVyLCB1c2Uge0BsaW5rIFBheWxvYWR9LlxuICpcbiAqIFRoZSBQbGF0Zm9ybSBgRXZlbnRFbWl0dGVyYCBpcyBhIHN1cGVyc2V0IG9mIHRoZSB7QGxpbmsgT3BlbkZpbi5BcHBsaWNhdGlvbn0gYEV2ZW50RW1pdHRlcmAsXG4gKiBtZWFuaW5nIGl0IGNhbiBsaXN0ZW4gdG8gYWxsIHtAbGluayBPcGVuRmluLkFwcGxpY2F0aW9uRXZlbnRzIEFwcGxpY2F0aW9uIGV2ZW50c30gaW4gYWRkaXRpb24gdG8gdGhlXG4gKiBQbGF0Zm9ybS1zcGVjaWZpYyBldmVudHMgbGlzdGVkIGhlcmUuICBGb3IgYSBsaXN0IG9mIHZhbGlkIHN0cmluZyBrZXlzIGZvciAqYWxsKiBwbGF0Zm9ybSBldmVudHMsIHNlZVxuICoge0BsaW5rIFBsYXRmb3JtLm9uIFBsYXRmb3JtLm9ufS5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KHBsYXRmb3JtJDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG52YXIgc3lzdGVtJDEgPSB7fTtcblxuLyoqXG4gKiBOYW1lc3BhY2UgZm9yIHJ1bnRpbWUtd2lkZSBPcGVuRmluIGV2ZW50cyBlbWl0dGVkIGJ5IHtAbGluayBTeXN0ZW0uU3lzdGVtfS4gIEluY2x1ZGVzIGV2ZW50c1xuICogcmUtcHJvcGFnYXRlZCBmcm9tIHtAbGluayBPcGVuRmluLkFwcGxpY2F0aW9ufSwge0BsaW5rIE9wZW5GaW4uV2luZG93fSwgYW5kIHtAbGluayBPcGVuRmluLlZpZXd9IChwcmVmaXhlZCB3aXRoIGBhcHBsaWNhdGlvbi1gLCBgd2luZG93LWAsIGFuZCBgdmlldy1gKS4gIEFsbFxuICogZXZlbnQgcHJvcGFnYXRpb25zIGFyZSB2aXNpYmxlIGF0IHRoZSBTeXN0ZW0gbGV2ZWwuIFByb3BhZ2F0ZWQgZXZlbnRzIGZyb20gV2ViQ29udGVudHMgKHdpbmRvd3MsIHZpZXdzLCBmcmFtZXMpIHRvIHRoZSBBcHBsaWNhdGlvbiBsZXZlbCB3aWxsICpub3QqXG4gKiB0cmFuc2l0aXZlbHkgcmUtcHJvcGFnYXRlIHRvIHRoZSBTeXN0ZW0gbGV2ZWwsIGJlY2F1c2UgdGhleSBhcmUgYWxyZWFkeSB2aXNpYmxlIGF0IHRoZSBzeXN0ZW0gbGV2ZWwgYW5kIGNvbnRhaW4gdGhlIGlkZW50aXR5XG4gKiBvZiB0aGUgYXBwbGljYXRpb24uICBGb3IgZXhhbXBsZSwgYW4gYXBwbGljYXRpb24ncyBcImNsb3NlZFwiIGV2ZW50IHdpbGwgZmlyZSBhcyAnYXBwbGljYXRpb24tY2xvc2VkJyBhdCB0aGUgc3lzdGVtIGxldmVsLiAgQSB2aWV3J3MgJ3Nob3duJyBldmVudFxuICogd2lsbCBiZSB2aXNpYmxlIGFzICd2aWV3LXNob3duJyBhdCB0aGUgc3lzdGVtIGxldmVsLCBidXQgKm5vdCogYXMgYGFwcGxpY2F0aW9uLXdpbmRvdy12aWV3LXNob3duYC5cbiAqXG4gKiBFdmVudCBwYXlsb2FkcyBhcmUgZG9jdW1lbnRlZCBhcyBpbnRlcmZhY2VzLCB3aGlsZSBhbGdlYnJhaWMgaGVscGVyIHR5cGVzIGFuZCBkZXJpdmVkIHR5cGVzIGFyZSBkb2N1bWVudGVkIGFzIHR5cGUgYWxpYXNlcy5cbiAqIEV2ZW50cyBnYWluIG1ldGFkYXRhIGFzIHRoZXkgcHJvcGFnYXRlLCB3aGljaCBpcyAqbm90KiBwcmVzZW50IG9uIHRoZSBleHBsaWNpdCBwYXlsb2FkIGludGVyZmFjZXMuICBUbyByZWZlciB0byB0aGUgZnVsbCB0eXBlXG4gKiBvZiBhbiBldmVudCBhcyBpdCB3b3VsZCBiZSByYWlzZWQgb24gdGhpcyBlbWl0dGVyLCB1c2Uge0BsaW5rIFBheWxvYWR9LlxuICpcbiAqIFRoaXMgbmFtZXNwYWNlIGNvbnRhaW5zIG9ubHkgcGF5bG9hZCBzaGFwZXMgZm9yIGV2ZW50cyB0aGF0IGFyZSB1bmlxdWUgdG8gYFN5c3RlbWAuICBFdmVudHMgdGhhdCBwcm9wYWdhdGUgdG8gYFN5c3RlbWAgZnJvbVxuICogY2hpbGQge0BsaW5rIE9wZW5GaW4uQXBwbGljYXRpb24gYXBwbGljYXRpb25zfSwge0BsaW5rIE9wZW5GaW4uV2luZG93IHdpbmRvd3N9LCBhbmQge0BsaW5rIE9wZW5GaW4uVmlldyB2aWV3c30gYXJlIGRlZmluZWQgaW4gdGhlXG4gKiB7QGxpbmsgT3BlbkZpbi5BcHBsaWNhdGlvbkV2ZW50c30sIHtAbGluayBPcGVuRmluLldpbmRvd0V2ZW50c30sIGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3RXZlbnRzfSBuYW1lc3BhY2VzLiAgRm9yIGEgbGlzdCBvZiB2YWxpZCBzdHJpbmcga2V5cyBmb3IgKmFsbCpcbiAqIHN5c3RlbSBldmVudHMsIHNlZSB7QGxpbmsgU3lzdGVtLm9uIFN5c3RlbS5vbn0uXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShzeXN0ZW0kMSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cbnZhciB2aWV3JDEgPSB7fTtcblxuLyoqXG4gKiBOYW1lc3BhY2UgZm9yIGV2ZW50cyB0aGF0IGNhbiBiZSBlbWl0dGVkIGJ5IGEge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gKlxuICogRXZlbnQgcGF5bG9hZHMgYXJlIGRvY3VtZW50ZWQgYXMgaW50ZXJmYWNlcywgd2hpbGUgYWxnZWJyYWljIGhlbHBlciB0eXBlcyBhbmQgZGVyaXZlZCB0eXBlcyBhcmUgZG9jdW1lbnRlZCBhcyB0eXBlIGFsaWFzZXMuXG4gKiBFdmVudHMgZ2FpbiBtZXRhZGF0YSBhcyB0aGV5IHByb3BhZ2F0ZSwgd2hpY2ggaXMgKm5vdCogcHJlc2VudCBvbiB0aGUgZXhwbGljaXQgcGF5bG9hZCBpbnRlcmZhY2VzLiAgVG8gcmVmZXIgdG8gdGhlIGZ1bGwgdHlwZVxuICogb2YgYW4gZXZlbnQgYXMgaXQgd291bGQgYmUgcmFpc2VkIG9uIHRoaXMgZW1pdHRlciwgdXNlIHtAbGluayBQYXlsb2FkfS5cbiAqXG4gKiBUaGlzIG5hbWVzcGFjZSBjb250YWlucyBvbmx5IHBheWxvYWQgc2hhcGVzIGZvciBldmVudHMgdGhhdCBhcmUgdW5pcXVlIHRvIGBWaWV3YC4gIEV2ZW50cyB0aGF0IGFyZSBzaGFyZWQgYmV0d2VlbiBhbGwgYFdlYkNvbnRlbnRzYFxuICogKGkuZS4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSwge0BsaW5rIE9wZW5GaW4uVmlld30pIGFyZSBkZWZpbmVkIGluIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzfS4gIEZvciBhIGxpc3RcbiAqIG9mIHZhbGlkIHN0cmluZyBrZXlzIGZvciAqYWxsKiBWaWV3IGV2ZW50cywgc2VlIHtAbGluayBWaWV3Lm9uIFZpZXcub259LlxuICpcbiAqIFZpZXcgZXZlbnRzIHByb3BhZ2F0ZSB0byB0aGVpciBwYXJlbnQge0BsaW5rIE9wZW5GaW4uV2luZG93RXZlbnRzIFdpbmRvd30sIHtAbGluayBPcGVuRmluLkFwcGxpY2F0aW9uRXZlbnRzIEFwcGxpY2F0aW9ufSxcbiAqIGFuZCB7QGxpbmsgT3BlbkZpbi5TeXN0ZW1FdmVudHMgU3lzdGVtfSB3aXRoIGFuIGFkZGVkIGB2aWV3SWRlbnRpdHlgIHByb3BlcnR5IGFuZCB0aGVpciBldmVudCB0eXBlcyBwcmVmaXhlZCB3aXRoIGAndmlldy0nYC5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KHZpZXckMSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cbnZhciB3ZWJjb250ZW50cyA9IHt9O1xuXG4vKipcbiAqIE5hbWVzcGFjZSBmb3IgZXZlbnRzIHNoYXJlZCBieSBhbGwgT3BlbkZpbiBXZWJDb250ZW50cyBlbGVtZW50cyAoaS5lLiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9LFxuICoge0BsaW5rIE9wZW5GaW4uVmlld30pLlxuICpcbiAqIFdlYkNvbnRlbnRzIGV2ZW50cyB3aWxsIHJlLWVtaXQgb24gcGFyZW50IGVudGl0aWVzIC0gZS5nLiwgYSBwcm9wYWdhdGluZyBldmVudCBpbiBhIHZpZXcgd2lsbCBhbHNvIGJlIGVtaXR0ZWQgb24gdGhlIHZpZXcnc1xuICogcGFyZW50IHdpbmRvdywgYW5kIHByb3BhZ2F0aW5nIGV2ZW50cyBpbiBhIHdpbmRvdyB3aWxsIGFsc28gYmUgZW1pdHRlZCBvbiB0aGUgd2luZG93J3MgcGFyZW50IHtAbGluayBPcGVuRmluLkFwcGxpY2F0aW9ufS5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KHdlYmNvbnRlbnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIHdpbmRvdyQyID0ge307XG5cbi8qKlxuICogTmFtZXNwYWNlIGZvciBldmVudHMgdGhhdCBjYW4gYmUgZW1pdHRlZCBieSBhIHtAbGluayBPcGVuRmluLldpbmRvd30uXG4gKlxuICogRXZlbnQgcGF5bG9hZHMgYXJlIGRvY3VtZW50ZWQgYXMgaW50ZXJmYWNlcywgd2hpbGUgYWxnZWJyYWljIGhlbHBlciB0eXBlcyBhbmQgZGVyaXZlZCB0eXBlcyBhcmUgZG9jdW1lbnRlZCBhcyB0eXBlIGFsaWFzZXMuXG4gKiBFdmVudHMgZ2FpbiBtZXRhZGF0YSBhcyB0aGV5IHByb3BhZ2F0ZSwgd2hpY2ggaXMgKm5vdCogcHJlc2VudCBvbiB0aGUgZXhwbGljaXQgcGF5bG9hZCBpbnRlcmZhY2VzLiAgVG8gcmVmZXIgdG8gdGhlIGZ1bGwgdHlwZVxuICogb2YgYW4gZXZlbnQgYXMgaXQgd291bGQgYmUgcmFpc2VkIG9uIHRoaXMgZW1pdHRlciwgdXNlIHtAbGluayBQYXlsb2FkfS5cbiAqXG4gKiBUaGlzIG5hbWVzcGFjZSBjb250YWlucyBvbmx5IHBheWxvYWQgc2hhcGVzIGZvciBldmVudHMgdGhhdCBhcmUgdW5pcXVlIHRvIGBXaW5kb3dgLiAgRXZlbnRzIHRoYXQgYXJlIHNoYXJlZCBiZXR3ZWVuIGFsbCBgV2ViQ29udGVudHNgXG4gKiAoaS5lLiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9LCB7QGxpbmsgT3BlbkZpbi5WaWV3fSkgYXJlIGRlZmluZWQgaW4ge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHN9LiBFdmVudHMgdGhhdFxuICogcHJvcGFnYXRlIGZyb20gYFZpZXdgIGFyZSBkZWZpbmVkIGluIHtAbGluayBPcGVuRmluLlZpZXdFdmVudHN9LiBGb3IgYSBsaXN0IG9mIHZhbGlkIHN0cmluZyBrZXlzIGZvciAqYWxsKiBXaW5kb3cgZXZlbnRzLCBzZWVcbiAqIHtAbGluayBXaW5kb3cub24gV2luZG93Lm9ufVxuICpcbiAqIHtAbGluayBPcGVuRmluLldpbmRvd0V2ZW50cy5XaW5kb3dTb3VyY2VkRXZlbnQgV2luZG93LXNvdXJjZWQgZXZlbnRzfSAoaS5lLiB0aG9zZSB0aGF0IGFyZSBub3QgcHJvcGFnYXRlZCBmcm9tIGFcbiAqIHtAbGluayBPcGVuRmluLlZpZXdFdmVudHMgVmlld30pIHByb3BhZ2F0ZSB0byB0aGVpciBwYXJlbnQge0BsaW5rIE9wZW5GaW4uQXBwbGljYXRpb25FdmVudHMgQXBwbGljYXRpb259IGFuZFxuICoge0BsaW5rIE9wZW5GaW4uU3lzdGVtRXZlbnRzIFN5c3RlbX0gd2l0aCB0aGVpciBldmVudCB0eXBlcyBwcmVmaXhlZCB3aXRoIGAnd2luZG93LSdgKS5cbiAqXG4gKiBcIlJlcXVlc3RlZFwiIGV2ZW50cyAoZS5nLiB7QGxpbmsgQXV0aFJlcXVlc3RlZEV2ZW50fSkgZG8gbm90IHByb3BhZ2F0ZSB0byBgU3lzdGVtLiAgVGhlIHtAbGluayBPcGVuRmluLldpbmRvd0V2ZW50cy5XaW5kb3dDbG9zZVJlcXVlc3RlZEV2ZW50fVxuICogZG9lcyBub3QgcHJvcGFnYXRlIGF0IGFsbC5cbiAqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KHdpbmRvdyQyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblxuLyoqXG4gKiBOYW1lc3BhY2UgZm9yIE9wZW5GaW4gZXZlbnQgdHlwZXMuIEVhY2ggZW50aXR5IHRoYXQgZW1pdHMgT3BlbkZpbiBldmVudHMgaGFzIGl0cyBvd24gc3ViLW5hbWVzcGFjZS4gRXZlbnQgcGF5bG9hZHNcbiAqIHRoZW1zZWx2ZXMgYXJlIGRvY3VtZW50ZWQgYXMgaW50ZXJmYWNlcywgd2hpbGUgYWxnZWJyYWljIGhlbHBlciB0eXBlcyBhbmQgZGVyaXZlZCB0eXBlcyBhcmUgZG9jdW1lbnRlZCBhcyB0eXBlIGFsaWFzZXMuXG4gKlxuICogIyMjIyBFdmVudCBlbWl0dGVyc1xuICpcbiAqIFRoZSBmb2xsb3dpbmcgZW50aXRpZXMgZW1pdCBPcGVuRmluIGV2ZW50cywgYW5kIGhhdmUgY29ycmVzcG9uZGluZyBzdWItbmFtZXNwYWNlczpcbiAqXG4gKiAqIHtAbGluayBPcGVuRmluLkFwcGxpY2F0aW9ufToge0BsaW5rIE9wZW5GaW4uQXBwbGljYXRpb25FdmVudHN9XG4gKiAqIHtAbGluayBPcGVuRmluLkV4dGVybmFsQXBwbGljYXRpb259OiB7QGxpbmsgT3BlbkZpbi5FeHRlcm5hbEFwcGxpY2F0aW9uRXZlbnRzfVxuICogKiB7QGxpbmsgT3BlbkZpbi5GcmFtZX06IHtAbGluayBPcGVuRmluLkZyYW1lRXZlbnRzfVxuICogKiB7QGxpbmsgT3BlbkZpbi5HbG9iYWxIb3RrZXl9OiB7QGxpbmsgT3BlbkZpbi5HbG9iYWxIb3RrZXlFdmVudHN9XG4gKiAqIHtAbGluayBPcGVuRmluLlBsYXRmb3JtfToge0BsaW5rIE9wZW5GaW4uUGxhdGZvcm1FdmVudHN9XG4gKiAqIHtAbGluayBPcGVuRmluLlN5c3RlbX06IHtAbGluayBPcGVuRmluLlN5c3RlbUV2ZW50c31cbiAqICoge0BsaW5rIE9wZW5GaW4uVmlld306IHtAbGluayBPcGVuRmluLlZpZXdFdmVudHN9XG4gKiAqIHtAbGluayBPcGVuRmluLldpbmRvd306IHtAbGluayBPcGVuRmluLldpbmRvd0V2ZW50c31cbiAqXG4gKiBUaGVzZSBgRXZlbnRFbWl0dGVyYCBlbnRpdGllcyBzaGFyZSBhIGNvbW1vbiBzZXQgb2YgbWV0aG9kcyBmb3IgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgT3BlbkZpbiBldmVudCBidXMsIHdoaWNoIGNhbiBiZVxuICogc2VlbiBvbiB0aGUgaW5kaXZpZHVhbCBkb2N1bWVudGF0aW9uIHBhZ2VzIGZvciBlYWNoIGVudGl0eSB0eXBlLlxuICpcbiAqIFJlZ2lzdGVyaW5nIGV2ZW50IGhhbmRsZXJzIGlzIGFuIGFzeW5jaHJvbm91cyBvcGVyYXRpb24uIEl0IGlzIGltcG9ydGFudCB0byBlbnN1cmUgdGhhdCB0aGUgcmV0dXJuZWQgUHJvbWlzZXMgYXJlIGF3YWl0ZWQgdG8gcmVkdWNlIHRoZVxuICogcmlzayBvZiByYWNlIGNvbmRpdGlvbnMuXG4gKlxuICogV2hlbiB0aGUgYEV2ZW50RW1pdHRlcmAgcmVjZWl2ZXMgYW4gZXZlbnQgZnJvbSB0aGUgYnJvd3NlciBwcm9jZXNzIGFuZCBlbWl0cyBvbiB0aGUgcmVuZGVyZXIsIGFsbCBvZiB0aGUgZnVuY3Rpb25zIGF0dGFjaGVkIHRvIHRoYXRcbiAqIHNwZWNpZmljIGV2ZW50IGFyZSBjYWxsZWQgc3luY2hyb25vdXNseS4gQW55IHZhbHVlcyByZXR1cm5lZCBieSB0aGUgY2FsbGVkIGxpc3RlbmVycyBhcmUgaWdub3JlZCBhbmQgd2lsbCBiZSBkaXNjYXJkZWQuICBJZiB0aGUgd2luZG93IGRvY3VtZW50XG4gKiBpcyBkZXN0cm95ZWQgYnkgcGFnZSBuYXZpZ2F0aW9uIG9yIHJlbG9hZCwgaXRzIHJlZ2lzdGVyZWQgZXZlbnQgbGlzdGVuZXJzIHdpbGwgYmUgcmVtb3ZlZC5cbiAqXG4gKiBXZSByZWNvbW1lbmQgdXNpbmcgQXJyb3cgRnVuY3Rpb25zIGZvciBldmVudCBsaXN0ZW5lcnMgdG8gZW5zdXJlIHRoZSB0aGlzIHNjb3BlIGlzIGNvbnNpc3RlbnQgd2l0aCB0aGUgb3JpZ2luYWwgZnVuY3Rpb24gY29udGV4dC5cbiAqXG4gKiBFdmVudHMgcmUtcHJvcGFnYXRlIGZyb20gc21hbGxlci9tb3JlLWxvY2FsIHNjb3BlcyB0byBsYXJnZXIvbW9yZS1nbG9iYWwgc2NvcGVzLiAgRm9yIGV4YW1wbGUsIGFuIGV2ZW50IGVtaXR0ZWQgb24gYSBzcGVjaWZpY1xuICogdmlldyB3aWxsIHByb3BhZ2F0ZSB0byB0aGUgd2luZG93IGluIHdoaWNoIHRoZSB2aWV3IGlzIGVtYmVkZGVkLCBhbmQgdGhlbiB0byB0aGUgYXBwbGljYXRpb24gaW4gd2hpY2ggdGhlIHdpbmRvdyBpcyBydW5uaW5nLCBhbmRcbiAqIGZpbmFsbHkgdG8gdGhlIE9wZW5GaW4gcnVudGltZSBpdHNlbGYgYXQgdGhlIFwic3lzdGVtXCIgbGV2ZWwuICBGb3IgZGV0YWlscyBvbiBwcm9wYWdhdGlvbiBzZW1hbnRpY3MsIHNlZSB0aGUgbmFtZXNwYWNlIGZvclxuICogdGhlIHByb3BhZ2F0aW5nIChvciBwcm9wYWdhdGVkLXRvKSBlbnRpdHkuXG4gKlxuICogSWYgeW91IG5lZWQgdGhlIHBheWxvYWQgdHlwZSBmb3IgYSBzcGVjaWZpYyB0eXBlIG9mIGV2ZW50IChlc3BlY2lhbGx5IHByb3BhZ2F0ZWQgZXZlbnRzKSwgdXNlIHRoZSBlbWl0dGluZyB0b3BpYydzIGBQYXlsb2FkYCBnZW5lcmljXG4gKiAoZS5nLiB7QGxpbmsgV2luZG93RXZlbnRzLlBheWxvYWR9KSB3aXRoIHRoZSBldmVudCdzIGB0eXBlYCBzdHJpbmcuICBGb3IgZXhhbXBsZSwgdGhlIHBheWxvYWQgb2ZcbiAqIGEge0BsaW5rIFZpZXdFdmVudHMuQ3JlYXRlZEV2ZW50fSBhZnRlciBpdCBoYXMgcHJvcGFnYXRlZCB0byBpdHMgcGFyZW50IHtAbGluayBXaW5kb3dFdmVudHMgV2luZG93fSBjYW4gYmUgZm91bmQgd2l0aFxuICogYFdpbmRvd0V2ZW50cy5QYXlsb2FkPCd2aWV3LWNyZWF0ZWQnPmAuXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cbnZhciBfX2NyZWF0ZUJpbmRpbmckMSA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcbiAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XG4gICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcbiAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG4gICAgb1trMl0gPSBtW2tdO1xufSkpO1xudmFyIF9fc2V0TW9kdWxlRGVmYXVsdCQxID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fc2V0TW9kdWxlRGVmYXVsdCkgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBcImRlZmF1bHRcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCB2YWx1ZTogdiB9KTtcbn0pIDogZnVuY3Rpb24obywgdikge1xuICAgIG9bXCJkZWZhdWx0XCJdID0gdjtcbn0pO1xudmFyIF9faW1wb3J0U3RhciQxID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9faW1wb3J0U3RhcikgfHwgZnVuY3Rpb24gKG1vZCkge1xuICAgIGlmIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpIHJldHVybiBtb2Q7XG4gICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChrICE9PSBcImRlZmF1bHRcIiAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kLCBrKSkgX19jcmVhdGVCaW5kaW5nJDEocmVzdWx0LCBtb2QsIGspO1xuICAgIF9fc2V0TW9kdWxlRGVmYXVsdCQxKHJlc3VsdCwgbW9kKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShldmVudHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXZlbnRzLldpbmRvd0V2ZW50cyA9IGV2ZW50cy5XZWJDb250ZW50c0V2ZW50cyA9IGV2ZW50cy5WaWV3RXZlbnRzID0gZXZlbnRzLlN5c3RlbUV2ZW50cyA9IGV2ZW50cy5QbGF0Zm9ybUV2ZW50cyA9IGV2ZW50cy5HbG9iYWxIb3RrZXlFdmVudHMgPSBldmVudHMuRnJhbWVFdmVudHMgPSBldmVudHMuRXh0ZXJuYWxBcHBsaWNhdGlvbkV2ZW50cyA9IGV2ZW50cy5CYXNlRXZlbnRzID0gZXZlbnRzLkFwcGxpY2F0aW9uRXZlbnRzID0gdm9pZCAwO1xuY29uc3QgQXBwbGljYXRpb25FdmVudHMgPSBfX2ltcG9ydFN0YXIkMShhcHBsaWNhdGlvbiQxKTtcbmV2ZW50cy5BcHBsaWNhdGlvbkV2ZW50cyA9IEFwcGxpY2F0aW9uRXZlbnRzO1xuY29uc3QgQmFzZUV2ZW50cyA9IF9faW1wb3J0U3RhciQxKGJhc2UkMSk7XG5ldmVudHMuQmFzZUV2ZW50cyA9IEJhc2VFdmVudHM7XG5jb25zdCBFeHRlcm5hbEFwcGxpY2F0aW9uRXZlbnRzID0gX19pbXBvcnRTdGFyJDEoZXh0ZXJuYWxBcHBsaWNhdGlvbiQxKTtcbmV2ZW50cy5FeHRlcm5hbEFwcGxpY2F0aW9uRXZlbnRzID0gRXh0ZXJuYWxBcHBsaWNhdGlvbkV2ZW50cztcbmNvbnN0IEZyYW1lRXZlbnRzID0gX19pbXBvcnRTdGFyJDEoZnJhbWUkMSk7XG5ldmVudHMuRnJhbWVFdmVudHMgPSBGcmFtZUV2ZW50cztcbmNvbnN0IEdsb2JhbEhvdGtleUV2ZW50cyA9IF9faW1wb3J0U3RhciQxKGdsb2JhbEhvdGtleSQxKTtcbmV2ZW50cy5HbG9iYWxIb3RrZXlFdmVudHMgPSBHbG9iYWxIb3RrZXlFdmVudHM7XG5jb25zdCBQbGF0Zm9ybUV2ZW50cyA9IF9faW1wb3J0U3RhciQxKHBsYXRmb3JtJDEpO1xuZXZlbnRzLlBsYXRmb3JtRXZlbnRzID0gUGxhdGZvcm1FdmVudHM7XG5jb25zdCBTeXN0ZW1FdmVudHMgPSBfX2ltcG9ydFN0YXIkMShzeXN0ZW0kMSk7XG5ldmVudHMuU3lzdGVtRXZlbnRzID0gU3lzdGVtRXZlbnRzO1xuY29uc3QgVmlld0V2ZW50cyA9IF9faW1wb3J0U3RhciQxKHZpZXckMSk7XG5ldmVudHMuVmlld0V2ZW50cyA9IFZpZXdFdmVudHM7XG5jb25zdCBXZWJDb250ZW50c0V2ZW50cyA9IF9faW1wb3J0U3RhciQxKHdlYmNvbnRlbnRzKTtcbmV2ZW50cy5XZWJDb250ZW50c0V2ZW50cyA9IFdlYkNvbnRlbnRzRXZlbnRzO1xuY29uc3QgV2luZG93RXZlbnRzID0gX19pbXBvcnRTdGFyJDEod2luZG93JDIpO1xuZXZlbnRzLldpbmRvd0V2ZW50cyA9IFdpbmRvd0V2ZW50cztcblxuKGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdC8qKlxuXHQgKiBUb3AtbGV2ZWwgbmFtZXNwYWNlIGZvciB0eXBlcyByZWZlcmVuY2VkIGJ5IHRoZSBPcGVuRmluIEFQSS4gIENvbnRhaW5zOlxuXHQgKlxuXHQgKiAqIFRoZSB0eXBlIG9mIHRoZSBnbG9iYWwgYGZpbmAgZW50cnkgcG9pbnQgKHtAbGluayBGaW5BcGl9KVxuXHQgKiAqIENsYXNzZXMgdGhhdCBhY3QgYXMgc3RhdGljIG5hbWVzcGFjZXMgcmV0dXJuZWQgZnJvbSB0aGUgYGZpbmAgZ2xvYmFsIChlLmcuIHtAbGluayBBcHBsaWNhdGlvbk1vZHVsZX0sIGFjY2Vzc2libGUgdmlhIGBmaW4uQXBwbGljYXRpb25gKVxuXHQgKiAqIEluc3RhbmNlIGNsYXNzZXMgdGhhdCBhcmUgcmV0dXJuZWQgZnJvbSBBUEkgY2FsbHMgKGUuZy4ge0BsaW5rIEFwcGxpY2F0aW9ufSwgYWNjZXNzaWJsZSB2aWEgYGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50U3luYygpYClcblx0ICogKiBQYXJhbWV0ZXIgc2hhcGVzIGZvciBBUEkgbWV0aG9kcyAoZS5nLiB7QGxpbmsgQXBwbGljYXRpb25PcHRpb25zfSwgdXNlZCBpbiBgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KClgKVxuXHQgKiAqIEV2ZW50IG5hbWVzcGFjZXMgYW5kIHBheWxvYWQgdW5pb24gdHlwZXMgKGUuZy4ge0BsaW5rIEFwcGxpY2F0aW9uRXZlbnRzfSBhbmQge0BsaW5rIEFwcGxpY2F0aW9uRXZlbnR9KVxuXHQgKlxuXHQgKiBAcGFja2FnZURvY3VtZW50YXRpb25cblx0ICovXG5cdHZhciBfX2NyZWF0ZUJpbmRpbmcgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcblx0ICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XG5cdCAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XG5cdCAgICB9XG5cdCAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xuXHR9KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIG9bazJdID0gbVtrXTtcblx0fSkpO1xuXHR2YXIgX19leHBvcnRTdGFyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fZXhwb3J0U3RhcikgfHwgZnVuY3Rpb24obSwgZXhwb3J0cykge1xuXHQgICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChleHBvcnRzLCBwKSkgX19jcmVhdGVCaW5kaW5nKGV4cG9ydHMsIG0sIHApO1xuXHR9O1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdC8vIERlcHJlY2F0ZWQgc2hpbSB0byBwcmVzZXJ2ZSB2MzAgbmFtZXNwYWNlIG5hbWVzXG5cdF9fZXhwb3J0U3RhcihldmVudHMsIGV4cG9ydHMpOyBcbn0gKE9wZW5GaW4kMikpO1xuXG52YXIgT3BlbkZpbiA9IC8qQF9fUFVSRV9fKi9nZXREZWZhdWx0RXhwb3J0RnJvbUNqcyhPcGVuRmluJDIpO1xuXG52YXIgT3BlbkZpbiQxID0gLyojX19QVVJFX18qL19tZXJnZU5hbWVzcGFjZXMoe1xuXHRfX3Byb3RvX186IG51bGwsXG5cdGRlZmF1bHQ6IE9wZW5GaW5cbn0sIFtPcGVuRmluJDJdKTtcblxudmFyIGZpbiQyID0ge307XG5cbnZhciBzeXN0ZW0gPSB7fTtcblxudmFyIGJhc2UgPSB7fTtcblxudmFyIHByb21pc2VzID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm9taXNlcywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5wcm9taXNlcy5wcm9taXNlTWFwU2VyaWFsID0gcHJvbWlzZXMuc2VyaWFsID0gcHJvbWlzZXMucHJvbWlzZU1hcCA9IHByb21pc2VzLnByb21pc2lmeSA9IHZvaWQgMDtcbmZ1bmN0aW9uIHByb21pc2lmeShmdW5jKSB7XG4gICAgcmV0dXJuICguLi5hcmdzKSA9PiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGZ1bmMoLi4uYXJncywgKGVyciwgdmFsKSA9PiAoZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHZhbCkpKTtcbiAgICB9KTtcbn1cbnByb21pc2VzLnByb21pc2lmeSA9IHByb21pc2lmeTtcbmFzeW5jIGZ1bmN0aW9uIHByb21pc2VNYXAoYXJyLCBhc3luY0YpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoYXJyLm1hcChhc3luY0YpKTtcbn1cbnByb21pc2VzLnByb21pc2VNYXAgPSBwcm9taXNlTWFwO1xuYXN5bmMgZnVuY3Rpb24gc2VyaWFsKGFycikge1xuICAgIGNvbnN0IHJldCA9IFtdO1xuICAgIGZvciAoY29uc3QgZnVuYyBvZiBhcnIpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWF3YWl0LWluLWxvb3BcbiAgICAgICAgY29uc3QgbmV4dCA9IGF3YWl0IGZ1bmMoKTtcbiAgICAgICAgcmV0LnB1c2gobmV4dCk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG59XG5wcm9taXNlcy5zZXJpYWwgPSBzZXJpYWw7XG5hc3luYyBmdW5jdGlvbiBwcm9taXNlTWFwU2VyaWFsKGFyciwgZnVuYykge1xuICAgIHJldHVybiBzZXJpYWwoYXJyLm1hcCgodmFsdWUsIGluZGV4LCBhcnJheSkgPT4gKCkgPT4gZnVuYyh2YWx1ZSwgaW5kZXgsIGFycmF5KSkpO1xufVxucHJvbWlzZXMucHJvbWlzZU1hcFNlcmlhbCA9IHByb21pc2VNYXBTZXJpYWw7XG5cbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JGMgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XG59O1xudmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZSA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9FbWl0dGVyQmFzZV9lbWl0dGVyQWNjZXNzb3I7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoYmFzZSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5iYXNlLlJlcGx5ID0gYmFzZS5FbWl0dGVyQmFzZSA9IGJhc2UuQmFzZSA9IHZvaWQgMDtcbmNvbnN0IHByb21pc2VzXzEgPSBwcm9taXNlcztcbmNsYXNzIEJhc2Uge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHdpcmUpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBpbnRlcm5hbFxuICAgICAgICAgKiBAZGVwcmVjYXRlZFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5pc05vZGVFbnZpcm9ubWVudCA9ICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuZW52aXJvbm1lbnQudHlwZSA9PT0gJ25vZGUnO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQGludGVybmFsXG4gICAgICAgICAqIEBkZXByZWNhdGVkXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmlzT3BlbkZpbkVudmlyb25tZW50ID0gKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5lbnZpcm9ubWVudC50eXBlID09PSAnb3BlbmZpbic7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAaW50ZXJuYWxcbiAgICAgICAgICogQGRlcHJlY2F0ZWRcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaXNCcm93c2VyRW52aXJvbm1lbnQgPSAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aXJlLmVudmlyb25tZW50LnR5cGUgPT09ICdvdGhlcic7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMud2lyZSA9IHdpcmU7XG4gICAgfVxuICAgIGdldCBmaW4oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuZ2V0RmluKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFByb3ZpZGVzIGFjY2VzcyB0byB0aGUgT3BlbkZpbiByZXByZXNlbnRhdGlvbiBvZiB0aGUgY3VycmVudCBjb2RlIGNvbnRleHQgKHVzdWFsbHkgYSBkb2N1bWVudFxuICAgICAqIHN1Y2ggYXMgYSB7QGxpbmsgT3BlbkZpbi5WaWV3fSBvciB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9KSwgYXMgd2VsbCBhcyB0byB0aGUgY3VycmVudCBgSW50ZXJvcGAgY29udGV4dC5cbiAgICAgKlxuICAgICAqIFVzZWZ1bCBmb3IgZGVidWdnaW5nIGluIHRoZSBkZXZ0b29scyBjb25zb2xlLCB3aGVyZSB0aGlzIHdpbGwgaW50ZWxsaWdlbnRseSB0eXBlIGl0c2VsZiBiYXNlZFxuICAgICAqIG9uIHRoZSBjb250ZXh0IGluIHdoaWNoIHRoZSBkZXZ0b29scyBwYW5lbCB3YXMgb3BlbmVkLlxuICAgICAqL1xuICAgIGdldCBtZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5tZTtcbiAgICB9XG59XG5iYXNlLkJhc2UgPSBCYXNlO1xuLyoqXG4gKiBBbiBlbnRpdHkgdGhhdCBlbWl0cyBPcGVuRmluIGV2ZW50cy5cbiAqXG4gKiBAcmVtYXJrcyBFdmVudC1iaW5kaW5nIG1ldGhvZHMgYXJlIGFzeW5jaHJvbm91cyBhcyB0aGV5IG11c3QgY3Jvc3MgcHJvY2VzcyBib3VuZGFyaWVzXG4gKiBhbmQgc2V0dXAgdGhlIGxpc3RlbmVyIGluIHRoZSBicm93c2VyIHByb2Nlc3MuICBXaGVuIHRoZSBgRXZlbnRFbWl0dGVyYCByZWNlaXZlcyBhbiBldmVudCBmcm9tIHRoZSBicm93c2VyIHByb2Nlc3NcbiAqIGFuZCBlbWl0cyBvbiB0aGUgcmVuZGVyZXIsIGFsbCBvZiB0aGUgZnVuY3Rpb25zIGF0dGFjaGVkIHRvIHRoYXQgc3BlY2lmaWMgZXZlbnQgYXJlIGNhbGxlZCBzeW5jaHJvbm91c2x5LiAgQW55IHZhbHVlc1xuICogcmV0dXJuZWQgYnkgdGhlIGNhbGxlZCBsaXN0ZW5lcnMgYXJlIGlnbm9yZWQgYW5kIHdpbGwgYmUgZGlzY2FyZGVkLiAgSWYgdGhlIGV4ZWN1dGlvbiBjb250ZXh0IG9mIHRoZSB3aW5kb3cgaXMgZGVzdHJveWVkXG4gKiBieSBwYWdlIG5hdmlnYXRpb24gb3IgcmVsb2FkLCBhbnkgZXZlbnRzIHRoYXQgaGF2ZSBiZWVuIHNldHVwIGluIHRoYXQgY29udGV4dCB3aWxsIGJlIGRlc3Ryb3llZC5cbiAqXG4gKiBJdCBpcyBpbXBvcnRhbnQgdG8ga2VlcCBpbiBtaW5kIHRoYXQgd2hlbiBhbiBvcmRpbmFyeSBsaXN0ZW5lciBmdW5jdGlvbiBpcyBjYWxsZWQsIHRoZSBzdGFuZGFyZCBgdGhpc2Aga2V5d29yZCBpcyBpbnRlbnRpb25hbGx5XG4gKiBzZXQgdG8gcmVmZXJlbmNlIHRoZSBgRXZlbnRFbWl0dGVyYCBpbnN0YW5jZSB0byB3aGljaCB0aGUgbGlzdGVuZXIgaXMgYXR0YWNoZWQuICBJdCBpcyBwb3NzaWJsZSB0byB1c2UgRVM2IEFycm93IEZ1bmN0aW9ucyBhc1xuICogbGlzdGVuZXJzLCBob3dldmVyLCB3aGVuIGRvaW5nIHNvLCB0aGUgYHRoaXNgIGtleXdvcmQgd2lsbCBubyBsb25nZXIgcmVmZXJlbmNlIHRoZSBgRXZlbnRFbWl0dGVyYCBpbnN0YW5jZS5cbiAqXG4gKiBFdmVudHMgcmUtcHJvcGFnYXRlIGZyb20gc21hbGxlci9tb3JlLWxvY2FsIHNjb3BlcyB0byBsYXJnZXIvbW9yZS1nbG9iYWwgc2NvcGVzLiAgRm9yIGV4YW1wbGUsIGFuIGV2ZW50IGVtaXR0ZWQgb24gYSBzcGVjaWZpY1xuICogdmlldyB3aWxsIHByb3BhZ2F0ZSB0byB0aGUgd2luZG93IGluIHdoaWNoIHRoZSB2aWV3IGlzIGVtYmVkZGVkLCBhbmQgdGhlbiB0byB0aGUgYXBwbGljYXRpb24gaW4gd2hpY2ggdGhlIHdpbmRvdyBpcyBydW5uaW5nLCBhbmRcbiAqIGZpbmFsbHkgdG8gdGhlIE9wZW5GaW4gcnVudGltZSBpdHNlbGYgYXQgdGhlIFwic3lzdGVtXCIgbGV2ZWwuICBSZS1wcm9wYWdhdGVkIGV2ZW50cyBhcmUgcHJlZml4ZWQgd2l0aCB0aGUgbmFtZSBvZiB0aGUgc2NvcGUgaW4gd2hpY2hcbiAqIHRoZXkgb3JpZ2luYXRlZCAtIGZvciBleGFtcGxlLCBhIFwic2hvd25cIiBldmVudCBlbWl0dGVkIG9uIGEgdmlldyB3aWxsIGJlIHJlLXByb3BhZ2F0ZWQgYXQgdGhlIHdpbmRvdyBsZXZlbCBhcyBcInZpZXctc2hvd25cIiwgYW5kXG4gKiB0aGVuIHRvIHRoZSBhcHBsaWNhdGlvbiBhcyBcIndpbmRvdy12aWV3LXNob3duXCIsIGFuZCBmaW5hbGx5IGF0IHRoZSBzeXN0ZW0gbGV2ZWwgYXMgXCJhcHBsaWNhdGlvbi13aW5kb3ctdmlldy1zaG93blwiLlxuICpcbiAqIEFsbCBldmVudCBwcm9wYWdhdGlvbnMgYXJlIHZpc2libGUgYXQgdGhlIFN5c3RlbSBsZXZlbCwgcmVnYXJkbGVzcyBvZiBzb3VyY2UsIHNvIHRyYW5zaXRpdmUgcmUtcHJvcGFnYXRpb25zIChlLmcuIGZyb20gdmlldyB0byB3aW5kb3dcbiAqIHRvIGFwcGxpY2F0aW9uKSBhcmUgdmlzaWJsZSBpbiB0aGVpciBlbnRpcmV0eSBhdCB0aGUgc3lzdGVtIGxldmVsLiAgU28sIHdlIGNhbiBsaXN0ZW4gdG8gdGhlIGFib3ZlIGV2ZW50IGFzIFwic2hvd25cIiwgXCJ2aWV3LXNob3duXCIsXG4gKiBcIndpbmRvdy12aWV3LXNob3duXCIsIG9yIFwiYXBwbGljYXRpb24td2luZG93LXZpZXctc2hvd24uXCJcbiAqL1xuY2xhc3MgRW1pdHRlckJhc2UgZXh0ZW5kcyBCYXNlIHtcbiAgICBjb25zdHJ1Y3Rvcih3aXJlLCB0b3BpYywgLi4uYWRkaXRpb25hbEFjY2Vzc29ycykge1xuICAgICAgICBzdXBlcih3aXJlKTtcbiAgICAgICAgdGhpcy50b3BpYyA9IHRvcGljO1xuICAgICAgICBfRW1pdHRlckJhc2VfZW1pdHRlckFjY2Vzc29yLnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICB0aGlzLmV2ZW50TmFtZXMgPSAoKSA9PiAodGhpcy5oYXNFbWl0dGVyKCkgPyB0aGlzLmdldE9yQ3JlYXRlRW1pdHRlcigpLmV2ZW50TmFtZXMoKSA6IFtdKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBpbnRlcm5hbFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5lbWl0ID0gKGV2ZW50VHlwZSwgcGF5bG9hZCwgLi4uYXJncykgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGFzRW1pdHRlcigpID8gdGhpcy5nZXRPckNyZWF0ZUVtaXR0ZXIoKS5lbWl0KGV2ZW50VHlwZSwgcGF5bG9hZCwgLi4uYXJncykgOiBmYWxzZTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5oYXNFbWl0dGVyID0gKCkgPT4gdGhpcy53aXJlLmV2ZW50QWdncmVnYXRvci5oYXMoX19jbGFzc1ByaXZhdGVGaWVsZEdldCRlKHRoaXMsIF9FbWl0dGVyQmFzZV9lbWl0dGVyQWNjZXNzb3IsIFwiZlwiKSk7XG4gICAgICAgIHRoaXMuZ2V0T3JDcmVhdGVFbWl0dGVyID0gKCkgPT4gdGhpcy53aXJlLmV2ZW50QWdncmVnYXRvci5nZXRPckNyZWF0ZShfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGUodGhpcywgX0VtaXR0ZXJCYXNlX2VtaXR0ZXJBY2Nlc3NvciwgXCJmXCIpKTtcbiAgICAgICAgdGhpcy5saXN0ZW5lcnMgPSAodHlwZSkgPT4gdGhpcy5oYXNFbWl0dGVyKCkgPyB0aGlzLmdldE9yQ3JlYXRlRW1pdHRlcigpLmxpc3RlbmVycyh0eXBlKSA6IFtdO1xuICAgICAgICB0aGlzLmxpc3RlbmVyQ291bnQgPSAodHlwZSkgPT4gdGhpcy5oYXNFbWl0dGVyKCkgPyB0aGlzLmdldE9yQ3JlYXRlRW1pdHRlcigpLmxpc3RlbmVyQ291bnQodHlwZSkgOiAwO1xuICAgICAgICB0aGlzLnJlZ2lzdGVyRXZlbnRMaXN0ZW5lciA9IGFzeW5jIChldmVudFR5cGUsIG9wdGlvbnMgPSB7fSwgYXBwbHlTdWJzY3JpcHRpb24sIHVuZG9TdWJzY3JpcHRpb24pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJ1bnRpbWVFdmVudCA9IHtcbiAgICAgICAgICAgICAgICAuLi50aGlzLmlkZW50aXR5LFxuICAgICAgICAgICAgICAgIHRpbWVzdGFtcDogb3B0aW9ucy50aW1lc3RhbXAgfHwgRGF0ZS5ub3coKSxcbiAgICAgICAgICAgICAgICB0b3BpYzogdGhpcy50b3BpYyxcbiAgICAgICAgICAgICAgICB0eXBlOiBldmVudFR5cGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBlbWl0dGVyID0gdGhpcy5nZXRPckNyZWF0ZUVtaXR0ZXIoKTtcbiAgICAgICAgICAgIC8vIFdlIGFwcGx5IHRoZSBzdWJzY3JpcHRpb24gYW5kIHRoZW4gdW5kbyBpZiB0aGUgYXN5bmMgY2FsbCBmYWlscyB0byBhdm9pZFxuICAgICAgICAgICAgLy8gaW5kZXRlcm1pbmFjeSBpbiBzdWJzY3JpcHRpb24gYXBwbGljYXRpb24gb3JkZXIsIHdoaWNoIGNhbiBicmVhayB0aGluZ3MgZWxzZXdoZXJlXG4gICAgICAgICAgICBhcHBseVN1YnNjcmlwdGlvbihlbWl0dGVyKTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3N1YnNjcmliZS10by1kZXNrdG9wLWV2ZW50JywgcnVudGltZUV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgdW5kb1N1YnNjcmlwdGlvbihlbWl0dGVyKTtcbiAgICAgICAgICAgICAgICB0aGlzLmRlbGV0ZUVtaXR0ZXJJZk5vdGhpbmdSZWdpc3RlcmVkKGVtaXR0ZXIpO1xuICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZGVyZWdpc3RlckV2ZW50TGlzdGVuZXIgPSBhc3luYyAoZXZlbnRUeXBlLCBvcHRpb25zID0ge30pID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0VtaXR0ZXIoKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJ1bnRpbWVFdmVudCA9IHtcbiAgICAgICAgICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eSxcbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBvcHRpb25zLnRpbWVzdGFtcCB8fCBEYXRlLm5vdygpLFxuICAgICAgICAgICAgICAgICAgICB0b3BpYzogdGhpcy50b3BpYyxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogZXZlbnRUeXBlXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbigndW5zdWJzY3JpYmUtdG8tZGVza3RvcC1ldmVudCcsIHJ1bnRpbWVFdmVudCkuY2F0Y2goKCkgPT4gbnVsbCk7XG4gICAgICAgICAgICAgICAgY29uc3QgZW1pdHRlciA9IHRoaXMuZ2V0T3JDcmVhdGVFbWl0dGVyKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVtaXR0ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUaGlzIHdpbGwgb25seSBiZSByZWFjaGVkIGlmIHVuc3Vic2NyaWJlIGZyb20gZXZlbnQgdGhhdCBkb2VzIG5vdCBleGlzdCBidXQgZG8gbm90IHdhbnQgdG8gZXJyb3IgaGVyZVxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9O1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JGModGhpcywgX0VtaXR0ZXJCYXNlX2VtaXR0ZXJBY2Nlc3NvciwgW3RvcGljLCAuLi5hZGRpdGlvbmFsQWNjZXNzb3JzXSwgXCJmXCIpO1xuICAgICAgICB0aGlzLmxpc3RlbmVycyA9IChldmVudCkgPT4gdGhpcy5oYXNFbWl0dGVyKCkgPyB0aGlzLmdldE9yQ3JlYXRlRW1pdHRlcigpLmxpc3RlbmVycyhldmVudCkgOiBbXTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBlbmQgb2YgdGhlIGxpc3RlbmVycyBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIEV2ZW50IHBheWxvYWRzIGFyZSBkb2N1bWVudGVkIGluIHRoZSB7QGxpbmsgT3BlbkZpbi5FdmVudHN9IG5hbWVzcGFjZS5cbiAgICAgKi9cbiAgICBhc3luYyBvbihldmVudFR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKSB7XG4gICAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgb3B0aW9ucywgKGVtaXR0ZXIpID0+IHtcbiAgICAgICAgICAgIGVtaXR0ZXIub24oZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgICAgIH0sIChlbWl0dGVyKSA9PiB7XG4gICAgICAgICAgICBlbWl0dGVyLnJlbW92ZUxpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFkZHMgYSBsaXN0ZW5lciB0byB0aGUgZW5kIG9mIHRoZSBsaXN0ZW5lcnMgYXJyYXkgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gICAgICovXG4gICAgYXN5bmMgYWRkTGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lciwgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy5vbihldmVudFR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWRkcyBhIG9uZSB0aW1lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnQuIFRoZSBsaXN0ZW5lciBpcyBpbnZva2VkIG9ubHkgdGhlIGZpcnN0IHRpbWUgdGhlIGV2ZW50IGlzIGZpcmVkLCBhZnRlciB3aGljaCBpdCBpcyByZW1vdmVkLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgRXZlbnQgcGF5bG9hZHMgYXJlIGRvY3VtZW50ZWQgaW4gdGhlIHtAbGluayBPcGVuRmluLkV2ZW50c30gbmFtZXNwYWNlLlxuICAgICAqL1xuICAgIGFzeW5jIG9uY2UoZXZlbnRUeXBlLCBsaXN0ZW5lciwgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBkZXJlZ2lzdGVyID0gKCkgPT4gdGhpcy5kZXJlZ2lzdGVyRXZlbnRMaXN0ZW5lcihldmVudFR5cGUpO1xuICAgICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyRXZlbnRMaXN0ZW5lcihldmVudFR5cGUsIG9wdGlvbnMsIChlbWl0dGVyKSA9PiB7XG4gICAgICAgICAgICBlbWl0dGVyLm9uY2UoZXZlbnRUeXBlLCBkZXJlZ2lzdGVyKTtcbiAgICAgICAgICAgIGVtaXR0ZXIub25jZShldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICAgICAgfSwgKGVtaXR0ZXIpID0+IHtcbiAgICAgICAgICAgIGVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIoZXZlbnRUeXBlLCBkZXJlZ2lzdGVyKTtcbiAgICAgICAgICAgIGVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGxpc3RlbmVycyBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIEV2ZW50IHBheWxvYWRzIGFyZSBkb2N1bWVudGVkIGluIHRoZSB7QGxpbmsgT3BlbkZpbi5FdmVudHN9IG5hbWVzcGFjZS5cbiAgICAgKi9cbiAgICBhc3luYyBwcmVwZW5kTGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lciwgb3B0aW9ucykge1xuICAgICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyRXZlbnRMaXN0ZW5lcihldmVudFR5cGUsIG9wdGlvbnMsIChlbWl0dGVyKSA9PiB7XG4gICAgICAgICAgICBlbWl0dGVyLnByZXBlbmRMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICAgICAgfSwgKGVtaXR0ZXIpID0+IHtcbiAgICAgICAgICAgIGVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIoZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgLyoqXG4gICAgICogQWRkcyBhIG9uZSB0aW1lIGxpc3RlbmVyIGZvciB0aGUgZXZlbnQuIFRoZSBsaXN0ZW5lciBpcyBpbnZva2VkIG9ubHkgdGhlIGZpcnN0IHRpbWUgdGhlIGV2ZW50IGlzIGZpcmVkLFxuICAgICAqIGFmdGVyIHdoaWNoIGl0IGlzIHJlbW92ZWQuIFRoZSBsaXN0ZW5lciBpcyBhZGRlZCB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaXN0ZW5lcnMgYXJyYXkuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBFdmVudCBwYXlsb2FkcyBhcmUgZG9jdW1lbnRlZCBpbiB0aGUge0BsaW5rIE9wZW5GaW4uRXZlbnRzfSBuYW1lc3BhY2UuXG4gICAgICovXG4gICAgYXN5bmMgcHJlcGVuZE9uY2VMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGRlcmVnaXN0ZXIgPSAoKSA9PiB0aGlzLmRlcmVnaXN0ZXJFdmVudExpc3RlbmVyKGV2ZW50VHlwZSk7XG4gICAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgb3B0aW9ucywgKGVtaXR0ZXIpID0+IHtcbiAgICAgICAgICAgIGVtaXR0ZXIucHJlcGVuZE9uY2VMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICAgICAgICAgIGVtaXR0ZXIub25jZShldmVudFR5cGUsIGRlcmVnaXN0ZXIpO1xuICAgICAgICB9LCAoZW1pdHRlcikgPT4ge1xuICAgICAgICAgICAgZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyKTtcbiAgICAgICAgICAgIGVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIoZXZlbnRUeXBlLCBkZXJlZ2lzdGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYSBsaXN0ZW5lciBmcm9tIHRoZSBsaXN0ZW5lciBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIENhdXRpb246IENhbGxpbmcgdGhpcyBtZXRob2QgY2hhbmdlcyB0aGUgYXJyYXkgaW5kaWNlcyBpbiB0aGUgbGlzdGVuZXIgYXJyYXkgYmVoaW5kIHRoZSBsaXN0ZW5lci5cbiAgICAgKi9cbiAgICBhc3luYyByZW1vdmVMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGVtaXR0ZXIgPSBhd2FpdCB0aGlzLmRlcmVnaXN0ZXJFdmVudExpc3RlbmVyKGV2ZW50VHlwZSwgb3B0aW9ucyk7XG4gICAgICAgIGlmIChlbWl0dGVyKSB7XG4gICAgICAgICAgICBlbWl0dGVyLnJlbW92ZUxpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgICAgICAgICAgdGhpcy5kZWxldGVFbWl0dGVySWZOb3RoaW5nUmVnaXN0ZXJlZChlbWl0dGVyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgYXN5bmMgZGVyZWdpc3RlckFsbExpc3RlbmVycyhldmVudFR5cGUpIHtcbiAgICAgICAgY29uc3QgcnVudGltZUV2ZW50ID0geyAuLi50aGlzLmlkZW50aXR5LCB0eXBlOiBldmVudFR5cGUsIHRvcGljOiB0aGlzLnRvcGljIH07XG4gICAgICAgIGlmICh0aGlzLmhhc0VtaXR0ZXIoKSkge1xuICAgICAgICAgICAgY29uc3QgZW1pdHRlciA9IHRoaXMuZ2V0T3JDcmVhdGVFbWl0dGVyKCk7XG4gICAgICAgICAgICBjb25zdCByZWZDb3VudCA9IGVtaXR0ZXIubGlzdGVuZXJDb3VudChydW50aW1lRXZlbnQudHlwZSk7XG4gICAgICAgICAgICBjb25zdCB1bnN1YnNjcmliZVByb21pc2VzID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJlZkNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICB1bnN1YnNjcmliZVByb21pc2VzLnB1c2godGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Vuc3Vic2NyaWJlLXRvLWRlc2t0b3AtZXZlbnQnLCBydW50aW1lRXZlbnQpLmNhdGNoKCgpID0+IG51bGwpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHVuc3Vic2NyaWJlUHJvbWlzZXMpO1xuICAgICAgICAgICAgcmV0dXJuIGVtaXR0ZXI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzLCBvciB0aG9zZSBvZiB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqXG4gICAgICovXG4gICAgYXN5bmMgcmVtb3ZlQWxsTGlzdGVuZXJzKGV2ZW50VHlwZSkge1xuICAgICAgICBjb25zdCByZW1vdmVCeUV2ZW50ID0gYXN5bmMgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBlbWl0dGVyID0gYXdhaXQgdGhpcy5kZXJlZ2lzdGVyQWxsTGlzdGVuZXJzKGV2ZW50KTtcbiAgICAgICAgICAgIGlmIChlbWl0dGVyKSB7XG4gICAgICAgICAgICAgICAgZW1pdHRlci5yZW1vdmVBbGxMaXN0ZW5lcnMoZXZlbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVsZXRlRW1pdHRlcklmTm90aGluZ1JlZ2lzdGVyZWQoZW1pdHRlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGlmIChldmVudFR5cGUpIHtcbiAgICAgICAgICAgIGF3YWl0IHJlbW92ZUJ5RXZlbnQoZXZlbnRUeXBlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0aGlzLmhhc0VtaXR0ZXIoKSkge1xuICAgICAgICAgICAgY29uc3QgZXZlbnRzID0gdGhpcy5nZXRPckNyZWF0ZUVtaXR0ZXIoKS5ldmVudE5hbWVzKCk7XG4gICAgICAgICAgICBhd2FpdCAoMCwgcHJvbWlzZXNfMS5wcm9taXNlTWFwKShldmVudHMsIHJlbW92ZUJ5RXZlbnQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBkZWxldGVFbWl0dGVySWZOb3RoaW5nUmVnaXN0ZXJlZChlbWl0dGVyKSB7XG4gICAgICAgIGlmIChlbWl0dGVyLmV2ZW50TmFtZXMoKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMud2lyZS5ldmVudEFnZ3JlZ2F0b3IuZGVsZXRlKF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZSh0aGlzLCBfRW1pdHRlckJhc2VfZW1pdHRlckFjY2Vzc29yLCBcImZcIikpO1xuICAgICAgICB9XG4gICAgfVxufVxuYmFzZS5FbWl0dGVyQmFzZSA9IEVtaXR0ZXJCYXNlO1xuX0VtaXR0ZXJCYXNlX2VtaXR0ZXJBY2Nlc3NvciA9IG5ldyBXZWFrTWFwKCk7XG5jbGFzcyBSZXBseSB7XG59XG5iYXNlLlJlcGx5ID0gUmVwbHk7XG5cbnZhciB0cmFuc3BvcnRFcnJvcnMgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHRyYW5zcG9ydEVycm9ycywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG50cmFuc3BvcnRFcnJvcnMuUnVudGltZUVycm9yID0gdHJhbnNwb3J0RXJyb3JzLk5vdFN1cHBvcnRlZEVycm9yID0gdHJhbnNwb3J0RXJyb3JzLk5vdEltcGxlbWVudGVkRXJyb3IgPSB0cmFuc3BvcnRFcnJvcnMuTm9BY2tFcnJvciA9IHRyYW5zcG9ydEVycm9ycy5EdXBsaWNhdGVDb3JyZWxhdGlvbkVycm9yID0gdHJhbnNwb3J0RXJyb3JzLlVuZXhwZWN0ZWRBY3Rpb25FcnJvciA9IHRyYW5zcG9ydEVycm9ycy5EaXNjb25uZWN0ZWRFcnJvciA9IHZvaWQgMDtcbmNsYXNzIERpc2Nvbm5lY3RlZEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHJlYWR5U3RhdGUpIHtcbiAgICAgICAgc3VwZXIoYEV4cGVjdGVkIHdlYnNvY2tldCBzdGF0ZSBPUEVOIGJ1dCBmb3VuZCAke3JlYWR5U3RhdGV9YCk7XG4gICAgICAgIHRoaXMucmVhZHlTdGF0ZSA9IHJlYWR5U3RhdGU7XG4gICAgfVxufVxudHJhbnNwb3J0RXJyb3JzLkRpc2Nvbm5lY3RlZEVycm9yID0gRGlzY29ubmVjdGVkRXJyb3I7XG5jbGFzcyBVbmV4cGVjdGVkQWN0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG59XG50cmFuc3BvcnRFcnJvcnMuVW5leHBlY3RlZEFjdGlvbkVycm9yID0gVW5leHBlY3RlZEFjdGlvbkVycm9yO1xuY2xhc3MgRHVwbGljYXRlQ29ycmVsYXRpb25FcnJvciBleHRlbmRzIEVycm9yIHtcbn1cbnRyYW5zcG9ydEVycm9ycy5EdXBsaWNhdGVDb3JyZWxhdGlvbkVycm9yID0gRHVwbGljYXRlQ29ycmVsYXRpb25FcnJvcjtcbmNsYXNzIE5vQWNrRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG59XG50cmFuc3BvcnRFcnJvcnMuTm9BY2tFcnJvciA9IE5vQWNrRXJyb3I7XG5jbGFzcyBOb3RJbXBsZW1lbnRlZEVycm9yIGV4dGVuZHMgRXJyb3Ige1xufVxudHJhbnNwb3J0RXJyb3JzLk5vdEltcGxlbWVudGVkRXJyb3IgPSBOb3RJbXBsZW1lbnRlZEVycm9yO1xuY2xhc3MgTm90U3VwcG9ydGVkRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG59XG50cmFuc3BvcnRFcnJvcnMuTm90U3VwcG9ydGVkRXJyb3IgPSBOb3RTdXBwb3J0ZWRFcnJvcjtcbmNsYXNzIEludGVybmFsRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IoZXJyKSB7XG4gICAgICAgIGNvbnN0IHsgbWVzc2FnZSwgbmFtZSwgc3RhY2ssIC4uLnJlc3QgfSA9IGVycjtcbiAgICAgICAgc3VwZXIobWVzc2FnZSk7XG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWUgfHwgJ0Vycm9yJztcbiAgICAgICAgdGhpcy5zdGFjayA9IHN0YWNrID8/IHRoaXMudG9TdHJpbmcoKTtcbiAgICAgICAgT2JqZWN0LmtleXMocmVzdCkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICAgICAgdGhpc1trZXldID0gcmVzdFtrZXldO1xuICAgICAgICB9KTtcbiAgICB9XG59XG4vLyBGb3IgZG9jdW1lbnRhdGlvbiBvZiB0aGUgZXJyb3IgbWV0aG9kcyBiZWluZyB1c2VkIHNlZSBoZXJlOiBodHRwczovL3Y4LmRldi9kb2NzL3N0YWNrLXRyYWNlLWFwaVxuY2xhc3MgUnVudGltZUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAgIHN0YXRpYyBnZXRDYWxsU2l0ZShjYWxsc1RvUmVtb3ZlID0gMCkge1xuICAgICAgICBjb25zdCBsZW5ndGggPSBFcnJvci5zdGFja1RyYWNlTGltaXQ7XG4gICAgICAgIGNvbnN0IHJlYWxDYWxsc1RvUmVtb3ZlID0gY2FsbHNUb1JlbW92ZSArIDE7IC8vIHJlbW92ZSB0aGlzIGNhbGw7XG4gICAgICAgIEVycm9yLnN0YWNrVHJhY2VMaW1pdCA9IGxlbmd0aCArIHJlYWxDYWxsc1RvUmVtb3ZlO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZXJzY29yZS1kYW5nbGVcbiAgICAgICAgY29uc3QgX3ByZXBhcmVTdGFja1RyYWNlID0gRXJyb3IucHJlcGFyZVN0YWNrVHJhY2U7XG4gICAgICAgIC8vIFRoaXMgd2lsbCBiZSBjYWxsZWQgd2hlbiB3ZSBhY2Nlc3MgdGhlIGBzdGFja2AgcHJvcGVydHlcbiAgICAgICAgRXJyb3IucHJlcGFyZVN0YWNrVHJhY2UgPSAoXywgc3RhY2spID0+IHN0YWNrO1xuICAgICAgICAvLyBzdGFjayBpcyBvcHRpb25hbCBpbiBub24gY2hyb21pdW0gY29udGV4dHNcbiAgICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaz8uc2xpY2UocmVhbENhbGxzVG9SZW1vdmUpID8/IFtdO1xuICAgICAgICBFcnJvci5wcmVwYXJlU3RhY2tUcmFjZSA9IF9wcmVwYXJlU3RhY2tUcmFjZTtcbiAgICAgICAgRXJyb3Iuc3RhY2tUcmFjZUxpbWl0ID0gbGVuZ3RoO1xuICAgICAgICByZXR1cm4gc3RhY2s7XG4gICAgfVxuICAgIHN0YXRpYyBwcmVwYXJlU3RhY2tUcmFjZShlcnIsIGNhbGxTaXRlcykge1xuICAgICAgICBpZiAodHlwZW9mIEVycm9yLnByZXBhcmVTdGFja1RyYWNlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXR1cm4gRXJyb3IucHJlcGFyZVN0YWNrVHJhY2UoZXJyLCBjYWxsU2l0ZXMpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBzdHJpbmcgPSBcIlwiO1xuICAgICAgICBzdHJpbmcgKz0gZXJyLm5hbWUgfHwgXCJFcnJvclwiO1xuICAgICAgICBzdHJpbmcgKz0gYDogJHtlcnIubWVzc2FnZSB8fCBcIlwifWA7XG4gICAgICAgIGZvciAoY29uc3QgY2FsbFNpdGUgb2YgY2FsbFNpdGVzKSB7XG4gICAgICAgICAgICBzdHJpbmcgKz0gYFxcbiAgICBhdCAke2NhbGxTaXRlLnRvU3RyaW5nKCl9YDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgIH1cbiAgICA7XG4gICAgY29uc3RydWN0b3IocGF5bG9hZCwgY2FsbFNpdGVzKSB7XG4gICAgICAgIGNvbnN0IHsgcmVhc29uLCBlcnJvciB9ID0gcGF5bG9hZDtcbiAgICAgICAgc3VwZXIocmVhc29uKTtcbiAgICAgICAgdGhpcy5uYW1lID0gJ1J1bnRpbWVFcnJvcic7XG4gICAgICAgIGlmIChlcnJvcj8uc3RhY2spIHtcbiAgICAgICAgICAgIHRoaXMuY2F1c2UgPSBuZXcgSW50ZXJuYWxFcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNhbGxTaXRlcykge1xuICAgICAgICAgICAgdGhpcy5zdGFjayA9IFJ1bnRpbWVFcnJvci5wcmVwYXJlU3RhY2tUcmFjZSh0aGlzLCBjYWxsU2l0ZXMpO1xuICAgICAgICB9XG4gICAgfVxufVxudHJhbnNwb3J0RXJyb3JzLlJ1bnRpbWVFcnJvciA9IFJ1bnRpbWVFcnJvcjtcblxudmFyIHdpbmRvdyQxID0ge307XG5cbnZhciBGYWN0b3J5JDggPSB7fTtcblxudmFyIHZhbGlkYXRlID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh2YWxpZGF0ZSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YWxpZGF0ZS52YWxpZGF0ZUlkZW50aXR5ID0gdm9pZCAwO1xuZnVuY3Rpb24gdmFsaWRhdGVJZGVudGl0eShpZGVudGl0eSkge1xuICAgIGxldCBlcnJvck1zZztcbiAgICBpZiAodHlwZW9mIGlkZW50aXR5ICE9PSAnb2JqZWN0JyB8fCB0eXBlb2YgaWRlbnRpdHkudXVpZCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgZXJyb3JNc2cgPSAnTm90IGEgdmFsaWQgaWRlbnRpdHkgb2JqZWN0JztcbiAgICB9XG4gICAgcmV0dXJuIGVycm9yTXNnO1xufVxudmFsaWRhdGUudmFsaWRhdGVJZGVudGl0eSA9IHZhbGlkYXRlSWRlbnRpdHk7XG5cbnZhciBJbnN0YW5jZSQ3ID0ge307XG5cbnZhciBhcHBsaWNhdGlvbiA9IHt9O1xuXG52YXIgRmFjdG9yeSQ3ID0ge307XG5cbnZhciBJbnN0YW5jZSQ2ID0ge307XG5cbnZhciB2aWV3ID0ge307XG5cbnZhciBGYWN0b3J5JDYgPSB7fTtcblxudmFyIHdhcm5pbmdzID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3YXJuaW5ncywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG53YXJuaW5ncy5oYW5kbGVEZXByZWNhdGVkV2FybmluZ3MgPSB2b2lkIDA7XG5jb25zdCBoYW5kbGVEZXByZWNhdGVkV2FybmluZ3MgPSAob3B0aW9ucykgPT4ge1xuICAgIGlmIChvcHRpb25zLmNvbnRlbnROYXZpZ2F0aW9uPy53aGl0ZWxpc3QgfHxcbiAgICAgICAgb3B0aW9ucy5jb250ZW50TmF2aWdhdGlvbj8uYmxhY2tsaXN0IHx8XG4gICAgICAgIG9wdGlvbnMuY29udGVudFJlZGlyZWN0Py53aGl0ZWxpc3QgfHxcbiAgICAgICAgb3B0aW9ucy5jb250ZW50UmVkaXJlY3Q/LmJsYWNrbGlzdCkge1xuICAgICAgICBjb25zb2xlLndhcm4oYFRoZSBwcm9wZXJ0aWVzICd3aGl0ZWxpc3QnIGFuZCAnYmxhY2tsaXN0JyBoYXZlIGJlZW4gbWFya2VkIGFzIGRlcHJlY2F0ZWQgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiBhIGZ1dHVyZSB2ZXJzaW9uLiBQbGVhc2UgdXNlICdhbGxvd2xpc3QnIGFuZCAnZGVueWxpc3QnLmApO1xuICAgIH1cbn07XG53YXJuaW5ncy5oYW5kbGVEZXByZWNhdGVkV2FybmluZ3MgPSBoYW5kbGVEZXByZWNhdGVkV2FybmluZ3M7XG5cbnZhciBoYXNSZXF1aXJlZEZhY3RvcnkkMztcblxuZnVuY3Rpb24gcmVxdWlyZUZhY3RvcnkkMyAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEZhY3RvcnkkMykgcmV0dXJuIEZhY3RvcnkkNjtcblx0aGFzUmVxdWlyZWRGYWN0b3J5JDMgPSAxO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoRmFjdG9yeSQ2LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0RmFjdG9yeSQ2LlZpZXdNb2R1bGUgPSB2b2lkIDA7XG5cdGNvbnN0IGJhc2VfMSA9IGJhc2U7XG5cdGNvbnN0IHZhbGlkYXRlXzEgPSB2YWxpZGF0ZTtcblx0Y29uc3QgaW5kZXhfMSA9IHJlcXVpcmVWaWV3KCk7XG5cdGNvbnN0IHdhcm5pbmdzXzEgPSB3YXJuaW5ncztcblx0LyoqXG5cdCAqIFN0YXRpYyBuYW1lc3BhY2UgZm9yIE9wZW5GaW4gQVBJIG1ldGhvZHMgdGhhdCBpbnRlcmFjdCB3aXRoIHRoZSB7QGxpbmsgVmlld30gY2xhc3MsIGF2YWlsYWJsZSB1bmRlciBgZmluLlZpZXdgLlxuXHQgKi9cblx0Y2xhc3MgVmlld01vZHVsZSBleHRlbmRzIGJhc2VfMS5CYXNlIHtcblx0ICAgIC8qKlxuXHQgICAgICogQ3JlYXRlcyBhIG5ldyBWaWV3LlxuXHQgICAgICogQHBhcmFtIG9wdGlvbnMgLSBWaWV3IGNyZWF0aW9uIG9wdGlvbnNcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGxldCB2aWV3O1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlVmlldygpIHtcblx0ICAgICAqICAgICBjb25zdCBtZSA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBmaW4uVmlldy5jcmVhdGUoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAndmlld05hbWVDcmVhdGUnLFxuXHQgICAgICogICAgICAgICB0YXJnZXQ6IG1lLmlkZW50aXR5LFxuXHQgICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogY3JlYXRlVmlldygpXG5cdCAgICAgKiAgICAgLnRoZW4oKGNyZWF0ZWRWaWV3KSA9PiB7XG5cdCAgICAgKiAgICAgICAgIHZpZXcgPSBjcmVhdGVkVmlldztcblx0ICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ1ZpZXcgY3JlYXRlZC4nLCB2aWV3KTtcblx0ICAgICAqICAgICAgICAgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9nb29nbGUuY29tJyk7XG5cdCAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCdWaWV3IG5hdmlnYXRlZCB0byBnaXZlbiB1cmwuJyk7XG5cdCAgICAgKiAgICAgfSlcblx0ICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKiBOb3RlIHRoYXQgY3JlYXRlZCB2aWV3cyBuZWVkcyB0byBuYXZpZ2F0ZSBzb21ld2hlcmUgZm9yIHRoZW0gdG8gYWN0dWFsbHkgcmVuZGVyIGEgd2Vic2l0ZS5cblx0ICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgY3JlYXRlKG9wdGlvbnMpIHtcblx0ICAgICAgICBjb25zdCB7IHV1aWQgfSA9IHRoaXMud2lyZS5tZTtcblx0ICAgICAgICBpZiAoIW9wdGlvbnMubmFtZSB8fCB0eXBlb2Ygb3B0aW9ucy5uYW1lICE9PSAnc3RyaW5nJykge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BsZWFzZSBwcm92aWRlIGEgbmFtZSBwcm9wZXJ0eSBhcyBhIHN0cmluZyBpbiBvcmRlciB0byBjcmVhdGUgYSBWaWV3LicpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICAoMCwgd2FybmluZ3NfMS5oYW5kbGVEZXByZWNhdGVkV2FybmluZ3MpKG9wdGlvbnMpO1xuXHQgICAgICAgIGlmICh0aGlzLndpcmUuZW52aXJvbm1lbnQuY2hpbGRWaWV3cykge1xuXHQgICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuZW52aXJvbm1lbnQuY3JlYXRlQ2hpbGRDb250ZW50KHtcblx0ICAgICAgICAgICAgICAgIGVudGl0eVR5cGU6ICd2aWV3Jyxcblx0ICAgICAgICAgICAgICAgIG9wdGlvbnM6IHsgLi4ub3B0aW9ucywgdXVpZCB9XG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NyZWF0ZS12aWV3JywgeyAuLi5vcHRpb25zLCB1dWlkIH0pO1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4gdGhpcy53cmFwU3luYyh7IHV1aWQsIG5hbWU6IG9wdGlvbnMubmFtZSB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhbiBBUEkgaGFuZGxlIGZvciB0aGUgZ2l2ZW4gVmlldyBpZGVudGl0eS5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBXcmFwcGluZyBhIFZpZXcgaWRlbnRpdHkgdGhhdCBkb2VzIG5vdCB5ZXQgZXhpc3Qgd2lsbCAqbm90KiB0aHJvdyBhbiBlcnJvciwgYW5kIGluc3RlYWRcblx0ICAgICAqIHJldHVybnMgYSBzdHViIG9iamVjdCB0aGF0IGNhbm5vdCB5ZXQgcGVyZm9ybSByZW5kZXJpbmcgdGFza3MuIFRoaXMgY2FuIGJlIHVzZWZ1bCBmb3IgcGx1bWJpbmcgZXZlbnRpbmdcblx0ICAgICAqIGZvciBhIFZpZXcgdGhyb3VnaG91dCBpdHMgZW50aXJlIGxpZmVjeWNsZS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5WaWV3LndyYXAoeyB1dWlkOiAndGVzdFZpZXdVdWlkJywgbmFtZTogJ3Rlc3RWaWV3TmFtZScgfSkpXG5cdCAgICAgKiAgICAgLnRoZW4odmlldyA9PiBjb25zb2xlLmxvZygnd3JhcHBlZCB2aWV3JywgdmlldykpXG5cdCAgICAgKiAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICovXG5cdCAgICBhc3luYyB3cmFwKGlkZW50aXR5KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3ZpZXctd3JhcCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGVycm9yTXNnID0gKDAsIHZhbGlkYXRlXzEudmFsaWRhdGVJZGVudGl0eSkoaWRlbnRpdHkpO1xuXHQgICAgICAgIGlmIChlcnJvck1zZykge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNc2cpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4gbmV3IGluZGV4XzEuVmlldyh0aGlzLndpcmUsIGlkZW50aXR5KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGFuIEFQSSBoYW5kbGUgZm9yIHRoZSBnaXZlbiBWaWV3IGlkZW50aXR5LlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFdyYXBwaW5nIGEgVmlldyBpZGVudGl0eSB0aGF0IGRvZXMgbm90IHlldCBleGlzdCB3aWxsICpub3QqIHRocm93IGFuIGVycm9yLCBhbmQgaW5zdGVhZFxuXHQgICAgICogcmV0dXJucyBhIHN0dWIgb2JqZWN0IHRoYXQgY2Fubm90IHlldCBwZXJmb3JtIHJlbmRlcmluZyB0YXNrcy4gVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBwbHVtYmluZyBldmVudGluZ1xuXHQgICAgICogZm9yIGEgVmlldyB0aHJvdWdob3V0IGl0cyBlbnRpcmUgbGlmZWN5Y2xlLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3QgdmlldyA9IGZpbi5WaWV3LndyYXBTeW5jKHsgdXVpZDogJ3Rlc3RWaWV3JywgbmFtZTogJ3Rlc3RWaWV3TmFtZScgfSk7XG5cdCAgICAgKiBhd2FpdCB2aWV3LmhpZGUoKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICovXG5cdCAgICB3cmFwU3luYyhpZGVudGl0eSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd2aWV3LXdyYXAtc3luYycpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGVycm9yTXNnID0gKDAsIHZhbGlkYXRlXzEudmFsaWRhdGVJZGVudGl0eSkoaWRlbnRpdHkpO1xuXHQgICAgICAgIGlmIChlcnJvck1zZykge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNc2cpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4gbmV3IGluZGV4XzEuVmlldyh0aGlzLndpcmUsIGlkZW50aXR5KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhIFZpZXcgb2JqZWN0IHRoYXQgcmVwcmVzZW50cyB0aGUgY3VycmVudCB2aWV3XG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBmaW4uVmlldy5nZXRDdXJyZW50KClcblx0ICAgICAqICAgICAudGhlbih2aWV3ID0+IGNvbnNvbGUubG9nKCdjdXJyZW50IHZpZXcnLCB2aWV3KSlcblx0ICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICpcblx0ICAgICAqIGBgYFxuXHQgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICovXG5cdCAgICBnZXRDdXJyZW50KCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd2aWV3LWdldC1jdXJyZW50JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgaWYgKCF0aGlzLndpcmUubWUuaXNWaWV3KSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IGFyZSBub3QgaW4gYSBWaWV3IGNvbnRleHQnKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSB0aGlzLndpcmUubWU7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud3JhcCh7IHV1aWQsIG5hbWUgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFN5bmNocm9ub3VzbHkgcmV0dXJucyBhIFZpZXcgb2JqZWN0IHRoYXQgcmVwcmVzZW50cyB0aGUgY3VycmVudCB2aWV3XG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCB2aWV3ID0gZmluLlZpZXcuZ2V0Q3VycmVudFN5bmMoKTtcblx0ICAgICAqIGNvbnNvbGUubG9nKHZpZXcpO1xuXHQgICAgICpcblx0ICAgICAqIGBgYFxuXHQgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICovXG5cdCAgICBnZXRDdXJyZW50U3luYygpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigndmlldy1nZXQtY3VycmVudC1zeW5jJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgaWYgKCF0aGlzLndpcmUubWUuaXNWaWV3KSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IGFyZSBub3QgaW4gYSBWaWV3IGNvbnRleHQnKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSB0aGlzLndpcmUubWU7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud3JhcFN5bmMoeyB1dWlkLCBuYW1lIH0pO1xuXHQgICAgfVxuXHR9XG5cdEZhY3RvcnkkNi5WaWV3TW9kdWxlID0gVmlld01vZHVsZTtcblx0cmV0dXJuIEZhY3RvcnkkNjtcbn1cblxudmFyIEluc3RhbmNlJDUgPSB7fTtcblxudmFyIGxhenkgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGxhenksIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xubGF6eS5Bc3luY1JldHJ5YWJsZUxhenkgPSBsYXp5LkxhenkgPSB2b2lkIDA7XG4vKipcbiAqIEhhbmR5IGNsYXNzIGZvciBtYW5hZ2luZyBhc3luY2hyb25vdXMgZGVwZW5kZW5jaWVzIG9mIGNsYXNzZXMuXG4gKlxuICogV2lsbCBjYWxsIHRoZSBwcm9kdWNlciBmdW5jdGlvbiBvbmNlIGFuZCBvbmx5IG9uY2Ugd2hlbiBnZXRWYWx1ZSBpcyBjYWxsZWQsXG4gKiByZXR1cm5pbmcgdGhlIHJlc3VsdGFudCB2YWx1ZSBmb3IgZXZlcnkgc3Vic2VxdWVudCBjYWxsLlxuICovXG5jbGFzcyBMYXp5IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICBjb25zdHJ1Y3Rvcihwcm9kdWNlckZuKSB7XG4gICAgICAgIHRoaXMucHJvZHVjZXJGbiA9IHByb2R1Y2VyRm47XG4gICAgfVxuICAgIC8qKlxuICAgICAqIExhemlseSBnZXQgdGhlIHZhbHVlIHJldHVybmVkIGJ5IHRoZSBwcm9kdWNlci5cbiAgICAgKiBAcmV0dXJucyBUaGUgdmFsdWUgcmV0dXJuZWQgZnJvbSB0aGUgcHJvZHVjZXIgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBnZXRWYWx1ZSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy5wcm9kdWNlckZuKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gICAgfVxufVxubGF6eS5MYXp5ID0gTGF6eTtcbi8qKlxuICogSGFuZHkgY2xhc3MgZm9yIG1hbmFnaW5nIGFzeW5jaHJvbm91cyBkZXBlbmRlbmNpZXMgb2YgY2xhc3Nlcy5cbiAqXG4gKiBXaWxsIGNhbGwgYXN5bmNocm9ub3VzIHByb2R1Y2VyIG9ubHkgYWZ0ZXIgYGdldFZhbHVlYCBpcyBjYWxsZWQuICBJZiB0aGVcbiAqIGRlZmVycmVkIGNvZGUgZXJyb3JzLCB3ZSBjYW4gdHJ5IGl0IGFnYWluIGJ5IHJlLWNhbGxpbmcgYGdldFZhbHVlYCBhZnRlclxuICogdGhlIHByb21pc2UgcmVqZWN0cy5cbiAqL1xuY2xhc3MgQXN5bmNSZXRyeWFibGVMYXp5IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICBjb25zdHJ1Y3Rvcihwcm9kdWNlckZuKSB7XG4gICAgICAgIHRoaXMucHJvZHVjZXJGbiA9IHByb2R1Y2VyRm47XG4gICAgfVxuICAgIC8qKlxuICAgICAqIExhemlseSBnZXQgdGhlIHZhbHVlIHJldHVybmVkIGJ5IHRoZSBhc3luYyBwcm9kdWNlci5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSB2YWx1ZSByZXR1cm5lZCBmcm9tIHRoZSBwcm9kdWNlciBmdW5jdGlvblxuICAgICAqL1xuICAgIGFzeW5jIGdldFZhbHVlKCkge1xuICAgICAgICBpZiAoIXRoaXMucHJvbWlzZSkge1xuICAgICAgICAgICAgdGhpcy5wcm9taXNlID0gdGhpcy5wcm9kdWNlckZuKCkuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5wcm9taXNlO1xuICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5wcm9taXNlO1xuICAgIH1cbn1cbmxhenkuQXN5bmNSZXRyeWFibGVMYXp5ID0gQXN5bmNSZXRyeWFibGVMYXp5O1xuXG52YXIgbGF5b3V0RW50aXRpZXMgPSB7fTtcblxudmFyIGFwaUV4cG9zZXIkMSA9IHt9O1xuXG52YXIgYXBpQ29uc3VtZXIgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGFwaUNvbnN1bWVyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmFwaUNvbnN1bWVyLkFwaUNvbnN1bWVyID0gdm9pZCAwO1xuLyoqXG4gKiBDb25zdW1lciBmb3IgYXBpcyBleHBvc2VkIHdpdGgge0BzZWUgQXBpRXhwb3Nlcn0uXG4gKlxuICogQSBzdHJhdGVneSB0aGF0IG1hdGNoZXMgdGhlIHN0cmF0ZWd5IHVzZWQgdG8gZXhwb3NlIGEgdGFyZ2V0IEFQSSBtdXN0IGJlIHByb3ZpZGVkLlxuICovXG5jbGFzcyBBcGlDb25zdW1lciB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgY29uc3RydWN0b3Ioc3RyYXRlZ3kpIHtcbiAgICAgICAgdGhpcy5zdHJhdGVneSA9IHN0cmF0ZWd5O1xuICAgICAgICAvKipcbiAgICAgICAgICogQ29uc3VtZXMgYW4gYXBpIGV4cG9zZWQgdXNpbmcgYSBnaXZlbiB0cmFuc3BvcnQgc3RyYXRlZ3ksIGFuZCBnZW5lcmF0ZXMgYSBjbGllbnRcbiAgICAgICAgICogZm9yIGVhc3ksIHR5cGUgc2FmZSBjb25zdW1wdGlvbiBvZiB0aGF0IGNsaWVudC5cbiAgICAgICAgICogQHBhcmFtIG9wdGlvbnMgU3RyYXRlZ3kgc3BlY2lmaWMgY29uc3VtcHRpb24gb3B0aW9ucy5cbiAgICAgICAgICogQHJldHVybnMgQW4gYXBpIGNsaWVudCBtYXRjaGluZyB0aGUgZ2l2ZW4gdHlwZS5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuY29uc3VtZSA9IGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBleHBvc2VkUHJvcGVydGllcyA9IGF3YWl0IHRoaXMuc3RyYXRlZ3kuZ2V0RXhwb3NlZEZ1bmN0aW9ucyhvcHRpb25zKTtcbiAgICAgICAgICAgIHJldHVybiBleHBvc2VkUHJvcGVydGllcy5yZWR1Y2UoKGNsaWVudCwgcHJvcCkgPT4gKHtcbiAgICAgICAgICAgICAgICAuLi5jbGllbnQsXG4gICAgICAgICAgICAgICAgW3Byb3Aua2V5XTogdGhpcy5zdHJhdGVneS5jcmVhdGVGdW5jdGlvbihwcm9wLCBvcHRpb25zKVxuICAgICAgICAgICAgfSksIHt9KTtcbiAgICAgICAgfTtcbiAgICB9XG59XG5hcGlDb25zdW1lci5BcGlDb25zdW1lciA9IEFwaUNvbnN1bWVyO1xuXG52YXIgYXBpRXhwb3NlciA9IHt9O1xuXG52YXIgZGVjb3JhdG9ycyA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZGVjb3JhdG9ycywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5kZWNvcmF0b3JzLmV4cG9zZSA9IGRlY29yYXRvcnMuZ2V0RXhwb3NlZFByb3BlcnRpZXMgPSB2b2lkIDA7XG5jb25zdCBleHBvc2VkUHJvcGVydGllcyA9IFN5bWJvbCgnZXhwb3NlZFByb3BlcnRpZXMnKTtcbmNvbnN0IGdldEV4cG9zZWRQcm9wZXJ0aWVzID0gKHRhcmdldCkgPT4ge1xuICAgIHJldHVybiB0YXJnZXRbZXhwb3NlZFByb3BlcnRpZXNdIHx8IHRhcmdldC5wcm90b3R5cGVbZXhwb3NlZFByb3BlcnRpZXNdIHx8IFtdO1xufTtcbmRlY29yYXRvcnMuZ2V0RXhwb3NlZFByb3BlcnRpZXMgPSBnZXRFeHBvc2VkUHJvcGVydGllcztcbi8qKlxuICogSW5kaWNhdGVzIHRoYXQgYSBjbGFzcyBtZW1iZXIgZnVuY3Rpb24gY2FuIGJlIGV4cG9zZWQgdXNpbmcge0BsaW5rIEFwaUV4cG9zZXJ9LlxuICogQHBhcmFtIG9wdGlvbnMgT3B0aW9ucyBzcGVjaWZpYyB0byB0aGUgc3RyYXRlZ3kgdXNlZCBpbiB7QGxpbmsgQXBpRXhwb3Nlcn1cbiAqL1xuLy8gUmV0dXJucyBhbnkgYXMgZGVjb3JhdG9yIHR5cGluZyBpcyB3ZWlyZC5cbmNvbnN0IGV4cG9zZSA9IChvcHRpb25zKSA9PiAodGFyZ2V0LCBrZXksIGRlc2NyaXB0b3IpID0+IHtcbiAgICB0YXJnZXRbZXhwb3NlZFByb3BlcnRpZXNdID0gdGFyZ2V0W2V4cG9zZWRQcm9wZXJ0aWVzXSB8fCBbXTtcbiAgICB0YXJnZXRbZXhwb3NlZFByb3BlcnRpZXNdLnB1c2goeyBrZXksIGRlc2NyaXB0b3IsIG9wdGlvbnMgfSk7XG59O1xuZGVjb3JhdG9ycy5leHBvc2UgPSBleHBvc2U7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShhcGlFeHBvc2VyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmFwaUV4cG9zZXIuQXBpRXhwb3NlciA9IHZvaWQgMDtcbmNvbnN0IGRlY29yYXRvcnNfMSA9IGRlY29yYXRvcnM7XG4vKipcbiAqIEV4cG9zZXMgYXBpIHNlcnZpY2VzIG9uIHRoZSB0cmFuc3BvcnQgb2YgY2hvaWNlLlxuICovXG5jbGFzcyBBcGlFeHBvc2VyIHtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gc3RyYXRlZ3kgVGhlIGV4cG9zZSBzdHJhdGVneSB0byB1c2UgdG8gZXhwb3NlIGluc3RhbmNlcy5cbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICBjb25zdHJ1Y3RvcihzdHJhdGVneSkge1xuICAgICAgICB0aGlzLnN0cmF0ZWd5ID0gc3RyYXRlZ3k7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFeHBvc2VzIGFuIGluc3RhbmNlIG9mIGEgZ2l2ZW4gYXBpIG9uXG4gICAgICAgICAqIEBwYXJhbSBpbnN0YW5jZSBJbnN0YW5jZSBvZiBhIGNsYXNzIHdoaWNoIGhhcyBiZWVuIGRlY29yYXRlZCB0byBpbmRpY2F0ZSB3aGljaCBmdW5jdGlvbnMgY2FuIGJlIGV4cG9zZWQuXG4gICAgICAgICAqIEBwYXJhbSBpbnN0YW5jZU9wdGlvbnMgVHJhbnNwb3J0IHN0cmF0ZWd5IHNwZWNpZmljIG9wdGlvbnMgdG8gdXNlIHdoZW4gZXhwb3NpbmcuXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmV4cG9zZUluc3RhbmNlID0gYXN5bmMgKGluc3RhbmNlLCBpbnN0YW5jZU9wdGlvbnMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGV4cG9zYWJsZVByb3BzID0gKDAsIGRlY29yYXRvcnNfMS5nZXRFeHBvc2VkUHJvcGVydGllcykoaW5zdGFuY2UpO1xuICAgICAgICAgICAgY29uc3QgZXhwb3NlZFByb3BzID0gYXdhaXQgUHJvbWlzZS5hbGwoZXhwb3NhYmxlUHJvcHMubWFwKGFzeW5jICh7IGtleSwgb3B0aW9ucyB9KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY3VzdG9tQ29uc3VtcHRpb25PcHRpb25zID0gYXdhaXQgdGhpcy5zdHJhdGVneS5leHBvc2VGdW5jdGlvbihpbnN0YW5jZVtrZXldLmJpbmQoaW5zdGFuY2UpLCB7XG4gICAgICAgICAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgbWV0YTogaW5zdGFuY2VPcHRpb25zXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5LFxuICAgICAgICAgICAgICAgICAgICBvcHRpb25zOiBjdXN0b21Db25zdW1wdGlvbk9wdGlvbnNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zdHJhdGVneS5leHBvc2VNZXRhKGluc3RhbmNlT3B0aW9ucywgZXhwb3NlZFByb3BzKTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgO1xufVxuYXBpRXhwb3Nlci5BcGlFeHBvc2VyID0gQXBpRXhwb3NlcjtcblxudmFyIHN0cmF0ZWdpZXMgPSB7fTtcblxudmFyIG9wZW5maW5DaGFubmVscyA9IHt9O1xuXG52YXIgY2hhbm5lbHNDb25zdW1lciA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoY2hhbm5lbHNDb25zdW1lciwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jaGFubmVsc0NvbnN1bWVyLkNoYW5uZWxzQ29uc3VtZXIgPSB2b2lkIDA7XG5jbGFzcyBDaGFubmVsc0NvbnN1bWVyIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICBjb25zdHJ1Y3RvcihjaGFubmVsKSB7XG4gICAgICAgIHRoaXMuY2hhbm5lbCA9IGNoYW5uZWw7XG4gICAgICAgIHRoaXMuZ2V0RXhwb3NlZEZ1bmN0aW9ucyA9IGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IGlkIH0gPSBvcHRpb25zO1xuICAgICAgICAgICAgY29uc3QgeyBwcm9wcyB9ID0gYXdhaXQgdGhpcy5jaGFubmVsLmRpc3BhdGNoKGBhcGktbWV0YToke2lkfWApO1xuICAgICAgICAgICAgcmV0dXJuIHByb3BzO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNyZWF0ZUZ1bmN0aW9uID0gKHByb3ApID0+ICguLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IGFjdGlvbiB9ID0gcHJvcC5vcHRpb25zO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2hhbm5lbC5kaXNwYXRjaChhY3Rpb24sIHsgYXJncyB9KTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgO1xufVxuY2hhbm5lbHNDb25zdW1lci5DaGFubmVsc0NvbnN1bWVyID0gQ2hhbm5lbHNDb25zdW1lcjtcblxudmFyIGNoYW5uZWxzRXhwb3NlciA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoY2hhbm5lbHNFeHBvc2VyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNoYW5uZWxzRXhwb3Nlci5DaGFubmVsc0V4cG9zZXIgPSB2b2lkIDA7XG5jbGFzcyBDaGFubmVsc0V4cG9zZXIge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnN0cnVjdG9yKGNoYW5uZWxQcm92aWRlck9yQ2xpZW50KSB7XG4gICAgICAgIHRoaXMuY2hhbm5lbFByb3ZpZGVyT3JDbGllbnQgPSBjaGFubmVsUHJvdmlkZXJPckNsaWVudDtcbiAgICAgICAgdGhpcy5leHBvc2VGdW5jdGlvbiA9IGFzeW5jICh0YXJnZXQsIGNvbmZpZykgPT4ge1xuICAgICAgICAgICAgY29uc3QgeyBrZXksIG9wdGlvbnMsIG1ldGEgfSA9IGNvbmZpZztcbiAgICAgICAgICAgIGNvbnN0IHsgaWQgfSA9IG1ldGE7XG4gICAgICAgICAgICBjb25zdCBhY3Rpb24gPSBgJHtpZH0uJHtvcHRpb25zPy5hY3Rpb24gfHwga2V5fWA7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNoYW5uZWxQcm92aWRlck9yQ2xpZW50LnJlZ2lzdGVyKGFjdGlvbiwgYXN5bmMgKHsgYXJncyB9KSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRhcmdldCguLi5hcmdzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHsgYWN0aW9uIH07XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZXhwb3NlTWV0YSA9IGFzeW5jICh7IGlkIH0sIHByb3BzKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBhY3Rpb24gPSBgYXBpLW1ldGE6JHtpZH1gO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5jaGFubmVsUHJvdmlkZXJPckNsaWVudC5yZWdpc3RlcihhY3Rpb24sICgpID0+ICh7IHByb3BzIH0pKTtcbiAgICAgICAgfTtcbiAgICB9XG59XG5jaGFubmVsc0V4cG9zZXIuQ2hhbm5lbHNFeHBvc2VyID0gQ2hhbm5lbHNFeHBvc2VyO1xuXG4oZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0ICAgIH1cblx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgb1trMl0gPSBtW2tdO1xuXHR9KSk7XG5cdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0X19leHBvcnRTdGFyKGNoYW5uZWxzQ29uc3VtZXIsIGV4cG9ydHMpO1xuXHRfX2V4cG9ydFN0YXIoY2hhbm5lbHNFeHBvc2VyLCBleHBvcnRzKTsgXG59IChvcGVuZmluQ2hhbm5lbHMpKTtcblxuKGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdHZhciBfX2NyZWF0ZUJpbmRpbmcgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcblx0ICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XG5cdCAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XG5cdCAgICB9XG5cdCAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xuXHR9KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIG9bazJdID0gbVtrXTtcblx0fSkpO1xuXHR2YXIgX19leHBvcnRTdGFyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fZXhwb3J0U3RhcikgfHwgZnVuY3Rpb24obSwgZXhwb3J0cykge1xuXHQgICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChleHBvcnRzLCBwKSkgX19jcmVhdGVCaW5kaW5nKGV4cG9ydHMsIG0sIHApO1xuXHR9O1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdF9fZXhwb3J0U3RhcihvcGVuZmluQ2hhbm5lbHMsIGV4cG9ydHMpOyBcbn0gKHN0cmF0ZWdpZXMpKTtcblxuKGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdHZhciBfX2NyZWF0ZUJpbmRpbmcgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcblx0ICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XG5cdCAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XG5cdCAgICB9XG5cdCAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xuXHR9KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIG9bazJdID0gbVtrXTtcblx0fSkpO1xuXHR2YXIgX19leHBvcnRTdGFyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fZXhwb3J0U3RhcikgfHwgZnVuY3Rpb24obSwgZXhwb3J0cykge1xuXHQgICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChleHBvcnRzLCBwKSkgX19jcmVhdGVCaW5kaW5nKGV4cG9ydHMsIG0sIHApO1xuXHR9O1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdF9fZXhwb3J0U3RhcihhcGlDb25zdW1lciwgZXhwb3J0cyk7XG5cdF9fZXhwb3J0U3RhcihhcGlFeHBvc2VyLCBleHBvcnRzKTtcblx0X19leHBvcnRTdGFyKHN0cmF0ZWdpZXMsIGV4cG9ydHMpO1xuXHRfX2V4cG9ydFN0YXIoZGVjb3JhdG9ycywgZXhwb3J0cyk7IFxufSAoYXBpRXhwb3NlciQxKSk7XG5cbnZhciBjaGFubmVsQXBpUmVsYXkgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGNoYW5uZWxBcGlSZWxheSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jaGFubmVsQXBpUmVsYXkuY3JlYXRlUmVsYXllZERpc3BhdGNoID0gY2hhbm5lbEFwaVJlbGF5LnJlbGF5Q2hhbm5lbENsaWVudEFwaSA9IHZvaWQgMDtcbmNvbnN0IEVYUEVDVEVEX0VSUk9SUyA9IFtcbiAgICAnbm8gbG9uZ2VyIGNvbm5lY3RlZCcsXG4gICAgJ1JUQ0RhdGFDaGFubmVsIGNsb3NlZCB1bmV4cGVjdGVkbHknLFxuICAgICdUaGUgY2xpZW50IHlvdSBhcmUgdHJ5aW5nIHRvIGRpc3BhdGNoIGZyb20gaXMgZGlzY29ubmVjdGVkIGZyb20gdGhlIHRhcmdldCBwcm92aWRlcicsXG5dO1xuLy8gQ2hlY2tzIHBvc3NpYmxlIGVycm9yIG1lc3NhZ2VzIHRoYXQgd2Ugd2FudCB0byB0cmFwLCBjbGllbnQgZXJyb3IgbWVzc2FnZSBjYW4gb3JpZ2luYXRlXG4vLyBmcm9tIENoYW5uZWxQcm92aWRlcjo6ZGlzcGF0Y2ggT1IgQ2xhc3NpY1N0cmF0ZWd5OjpjbG9zZUVuZHBvaW50IE9SIFJUQ0VuZFBvaW50OjpkYXRhQ2hhbm5lbDo6b25jbG9zZVxuY29uc3QgaXNEaXNjb25uZWN0ZWRFcnJvciA9IChlcnJvck1zZykgPT4ge1xuICAgIHJldHVybiBFWFBFQ1RFRF9FUlJPUlMuc29tZShlID0+IGVycm9yTXNnLmluY2x1ZGVzKGUpKTtcbn07XG4vKipcbiAqIEBpbnRlcm5hbFxuICogQ3JlYXRlIGEgY2hhbm5lbCByZWxheSBmb3IgYSBnaXZlbiBjaGFubmVsIGV4cG9zaXRpb24sIGFsbG93aW5nIGEgc2luZ2xlIHByb3ZpZGVyIHRvIHJvdXRlXG4gKiBhY3Rpb25zIHRvIHRoZSBkZXNpZ25hdGVkIGNsaWVudHMuXG4gKlxuICogRGVzaWduZWQgdG8gYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIEBleHBvc2VcbiAqXG4gKiBAcGFyYW0gY2hhbm5lbFByb3ZpZGVyIFRoZSBjaGFubmVsIHByb3ZpZGVyIHRvIHJlbGF5IHRoZSBhY3Rpb25zIG9uLlxuICogQHBhcmFtIGNvbmZpZyBEZXRlcm1pbmVzIHdoaWNoIGFjdGlvbnMgdG8gcmVsYXkuIFBsZWFzZSBlbnN1cmUgYWN0aW9uIHByZWZpeCBtYXRjaGVzIHRoZSBleHBvc2VkIGFwaS5cbiAqL1xuY29uc3QgcmVsYXlDaGFubmVsQ2xpZW50QXBpID0gYXN5bmMgKGNoYW5uZWxQcm92aWRlciwgcmVsYXlJZCkgPT4ge1xuICAgIGNoYW5uZWxQcm92aWRlci5yZWdpc3RlcihgcmVsYXk6JHtyZWxheUlkfWAsICh7IGFjdGlvbiwgdGFyZ2V0LCBwYXlsb2FkIH0pID0+IHtcbiAgICAgICAgcmV0dXJuIGNoYW5uZWxQcm92aWRlci5kaXNwYXRjaCh0YXJnZXQsIGFjdGlvbiwgcGF5bG9hZCk7XG4gICAgfSk7XG4gICAgYXdhaXQgUHJvbWlzZS5yZXNvbHZlKCk7XG59O1xuY2hhbm5lbEFwaVJlbGF5LnJlbGF5Q2hhbm5lbENsaWVudEFwaSA9IHJlbGF5Q2hhbm5lbENsaWVudEFwaTtcbmNvbnN0IGNyZWF0ZVJlbGF5ZWREaXNwYXRjaCA9IChjbGllbnQsIHRhcmdldCwgcmVsYXlJZCwgcmVsYXlFcnJvck1zZykgPT4gYXN5bmMgKGFjdGlvbiwgcGF5bG9hZCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBjbGllbnQuZGlzcGF0Y2goYHJlbGF5OiR7cmVsYXlJZH1gLCB7XG4gICAgICAgICAgICBhY3Rpb24sXG4gICAgICAgICAgICBwYXlsb2FkLFxuICAgICAgICAgICAgdGFyZ2V0XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoaXNEaXNjb25uZWN0ZWRFcnJvcihlLm1lc3NhZ2UpICYmIHJlbGF5RXJyb3JNc2cpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihyZWxheUVycm9yTXNnKTtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlO1xuICAgIH1cbn07XG5jaGFubmVsQXBpUmVsYXkuY3JlYXRlUmVsYXllZERpc3BhdGNoID0gY3JlYXRlUmVsYXllZERpc3BhdGNoO1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCRiID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xufTtcbnZhciBfTGF5b3V0Tm9kZV9jbGllbnQsIF9UYWJTdGFja19jbGllbnQsIF9Db2x1bW5PclJvd19jbGllbnQ7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkobGF5b3V0RW50aXRpZXMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xubGF5b3V0RW50aXRpZXMuQ29sdW1uT3JSb3cgPSBsYXlvdXRFbnRpdGllcy5UYWJTdGFjayA9IGxheW91dEVudGl0aWVzLkxheW91dE5vZGUgPSB2b2lkIDA7XG5jb25zdCBhcGlfZXhwb3Nlcl8xID0gYXBpRXhwb3NlciQxO1xuY29uc3QgY2hhbm5lbF9hcGlfcmVsYXlfMSA9IGNoYW5uZWxBcGlSZWxheTtcbi8qXG4gICAgVGhpcyBmaWxlIGluY2x1ZGVzIExheW91dE5vZGUsIENvbHVtbk9yUm93IGFuZCBUYWJTdGFjayBjbGFzc2VzLCB3aGljaCBhcmUgYWxsIGNsb3NlbHlcbiAgICBpbnRlcnR3aW5lZCwgYW5kIHNoYXJlIG1lbWJlcnMgdmlhIHBhcmVudCBhYnN0cmFjdCBjbGFzcyBMYXlvdXROb2RlLiBUbyBwcmV2ZW50IGNpcmN1bGFyXG4gICAgcmVmcywgd2UgZGVmaW5lIGFuZCBleHBvcnQgYWxsIHRoZSBjbGFzc2VzIGhlcmUuXG4qL1xuLyoqXG4gKiBAaWdub3JlXG4gKiBAaW50ZXJuYWxcbiAqIFN1cHBsaWVzIGFuIEFwaUNsaWVudCBmb3Ige0BsaW5rIExheW91dEVudGl0aWVzQ29udHJvbGxlcn0gYW5kIGhlbHBlciBtZXRob2RzXG4gKiBmb3IgdGhlIGVudGl0aWVzIHtAbGluayBUYWJTdGFja30gQU5EIHtAbGluayBDb2x1bW5PclJvd30gdG8gdXNlLlxuICovXG5jbGFzcyBMYXlvdXROb2RlIHtcbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKiBAaWdub3JlXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2xpZW50LCBlbnRpdHlJZCkge1xuICAgICAgICAvKipcbiAgICAgICAgICogQGlnbm9yZVxuICAgICAgICAgKiBAaW50ZXJuYWxcbiAgICAgICAgICogQXBpQ2xpZW50IGZvciB7QGxpbmsgTGF5b3V0RW50aXRpZXNDb250cm9sbGVyfVxuICAgICAgICAgKi9cbiAgICAgICAgX0xheW91dE5vZGVfY2xpZW50LnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICAvKipcbiAgICAgICAgICogQ2hlY2tzIGlmIHRoZSBUYWJTdGFjayBvciBDb2x1bW5PclJvdyBpcyB0aGUgcm9vdCBjb250ZW50IGl0ZW1cbiAgICAgICAgICpcbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogaWYgKCFmaW4ubWUuaXNWaWV3KSB7XG4gICAgICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldy4nKTtcbiAgICAgICAgICogfVxuICAgICAgICAgKlxuICAgICAgICAgKiBjb25zdCBzdGFjayA9IGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50U3RhY2soKTtcbiAgICAgICAgICogY29uc3QgaXNSb290ID0gYXdhaXQgc3RhY2suaXNSb290KCk7XG4gICAgICAgICAqIC8vIFRoZSBUYWJTdGFjayBpcyByb290OiBmYWxzZVxuICAgICAgICAgKiBjb25zb2xlLmxvZyhgVGhlIFRhYlN0YWNrIGlzIHJvb3Q6ICR7aXNSb290fWApO1xuICAgICAgICAgKlxuICAgICAgICAgKiAvLyBSZXRyaWV2ZXMgdGhlIHBhcmVudCBDb2x1bW5PclJvd1xuICAgICAgICAgKiBjb25zdCBwYXJlbnQgPSBhd2FpdCBzdGFjay5nZXRQYXJlbnQoKTtcbiAgICAgICAgICogY29uc3QgcGFyZW50SXNSb290ID0gYXdhaXQgcGFyZW50LmlzUm9vdCgpO1xuICAgICAgICAgKiAvLyBUaGUgcGFyZW50IENvbHVtbk9yUm93IGlzIHJvb3Q6IHRydWVcbiAgICAgICAgICogY29uc29sZS5sb2coYFRoZSBwYXJlbnQgQ29sdW1uT3JSb3cgaXMgcm9vdDogJHtwYXJlbnRJc1Jvb3R9YCk7XG4gICAgICAgICAqIGBgYFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5pc1Jvb3QgPSAoKSA9PiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX0xheW91dE5vZGVfY2xpZW50LCBcImZcIikuaXNSb290KHRoaXMuZW50aXR5SWQpO1xuICAgICAgICAvKipcbiAgICAgICAgICogQ2hlY2tzIGlmIHRoZSBUYWJTdGFjayBvciBDb2x1bW5PclJvdyBleGlzdHNcbiAgICAgICAgICpcbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogaWYgKCFmaW4ubWUuaXNWaWV3KSB7XG4gICAgICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldy4nKTtcbiAgICAgICAgICogfVxuICAgICAgICAgKlxuICAgICAgICAgKiBjb25zdCBzdGFjayA9IGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50U3RhY2soKTtcbiAgICAgICAgICogLy8gUmV0cmlldmVzIHRoZSBwYXJlbnQgQ29sdW1uT3JSb3dcbiAgICAgICAgICogY29uc3QgY29sdW1uT3JSb3cgPSBhd2FpdCBzdGFjay5nZXRQYXJlbnQoKTtcbiAgICAgICAgICogbGV0IGV4aXN0cyA9IGF3YWl0IHN0YWNrLmV4aXN0cygpO1xuICAgICAgICAgKiAvLyBvclxuICAgICAgICAgKiBsZXQgZXhpc3RzID0gYXdhaXQgY29sdW1uT3JSb3cuZXhpc3RzKCk7XG4gICAgICAgICAqIC8vIFRoZSBlbnRpdHkgZXhpc3RzOiB0cnVlXG4gICAgICAgICAqIGNvbnNvbGUubG9nKGBUaGUgZW50aXR5IGV4aXN0czogJHtleGlzdHN9YCk7XG4gICAgICAgICAqIGBgYFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5leGlzdHMgPSAoKSA9PiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX0xheW91dE5vZGVfY2xpZW50LCBcImZcIikuZXhpc3RzKHRoaXMuZW50aXR5SWQpO1xuICAgICAgICAvKipcbiAgICAgICAgICogUmV0cmlldmVzIHRoZSBwYXJlbnQgb2YgdGhlIFRhYlN0YWNrIG9yIENvbHVtbk9yUm93XG4gICAgICAgICAqXG4gICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAqIGBgYGpzXG4gICAgICAgICAqIGlmICghZmluLm1lLmlzVmlldykge1xuICAgICAgICAgKiAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgcnVubmluZyBpbiBhIHBsYXRmb3JtIFZpZXcuJyk7XG4gICAgICAgICAqIH1cbiAgICAgICAgICpcbiAgICAgICAgICogY29uc3Qgc3RhY2sgPSBhd2FpdCBmaW4ubWUuZ2V0Q3VycmVudFN0YWNrKCk7XG4gICAgICAgICAqIC8vIFJldHJpZXZlcyB0aGUgcGFyZW50IENvbHVtbk9yUm93XG4gICAgICAgICAqIGNvbnN0IGNvbHVtbk9yUm93ID0gYXdhaXQgc3RhY2suZ2V0UGFyZW50KCk7XG4gICAgICAgICAqXG4gICAgICAgICAqIC8vIHVuZGVmaW5lZCBpZiBlbnRpdHkgaXMgdGhlIHJvb3QgaXRlbVxuICAgICAgICAgKiBsZXQgcGFyZW50ID0gYXdhaXQgY29sdW1uT3JSb3cuZ2V0UGFyZW50KCk7XG4gICAgICAgICAqIC8vIG9yXG4gICAgICAgICAqIGxldCBwYXJlbnQgPSBhd2FpdCBzdGFjay5nZXRQYXJlbnQoKTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmdldFBhcmVudCA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBhcmVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZCh0aGlzLCBfTGF5b3V0Tm9kZV9jbGllbnQsIFwiZlwiKS5nZXRQYXJlbnQodGhpcy5lbnRpdHlJZCk7XG4gICAgICAgICAgICBpZiAoIXBhcmVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gTGF5b3V0Tm9kZS5nZXRFbnRpdHkocGFyZW50LCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX0xheW91dE5vZGVfY2xpZW50LCBcImZcIikpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBUYWJTdGFjayBhZGphY2VudCB0byB0aGUgZ2l2ZW4gVGFiU3RhY2sgb3IgQ29sdW1uT3JSb3cuIElucHV0cyBjYW4gYmUgbmV3IHZpZXdzIHRvIGNyZWF0ZSwgb3IgZXhpc3Rpbmcgdmlld3MuXG4gICAgICAgICAqXG4gICAgICAgICAqIEtub3duIElzc3VlOiBJZiB0aGUgbnVtYmVyIG9mIHZpZXdzIHRvIGFkZCBvdmVyZmxvd3MgdGhlIHRhYi1jb250YWluZXIsIHRoZSBhZGRlZCB2aWV3cyB3aWxsIGJlIHNldCBhcyBhY3RpdmVcbiAgICAgICAgICogZHVyaW5nIGVhY2ggcmVuZGVyLCBhbmQgdGhlbiBwbGFjZWQgYXQgdGhlIGZyb250IG9mIHRoZSB0YWItc3RhY2ssIHdoaWxlIHRoZSB1bmRlcmx5aW5nIG9yZGVyIG9mIHRhYnMgd2lsbCByZW1haW4gdW5jaGFuZ2VkLlxuICAgICAgICAgKiBUaGlzIG1lYW5zIHRoZSB2aWV3cyB5b3UgcGFzcyB0byBjcmVhdGVBZGphY2VudFN0YWNrKCkgbWF5IG5vdCByZW5kZXIgaW4gdGhlIG9yZGVyIGdpdmVuIGJ5IHRoZSBhcnJheS5cbiAgICAgICAgICogVW50aWwgZml4ZWQsIHRoaXMgcHJvYmxlbSBjYW4gYmUgYXZvaWRlZCBvbmx5IGlmIHlvdXIgd2luZG93IGlzIHdpZGUgZW5vdWdoIHRvIGZpdCBjcmVhdGluZyBhbGwgdGhlIHZpZXdzIGluIHRoZSB0YWJzdGFjay5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHZpZXdzIFRoZSB2aWV3cyB0aGF0IHdpbGwgcG9wdWxhdGUgdGhlIG5ldyBUYWJTdGFjay5cbiAgICAgICAgICogQHBhcmFtIG9wdGlvbnMgQWRkaXRpb25hbCBvcHRpb25zIHRoYXQgY29udHJvbCBuZXcgVGFiU3RhY2sgY3JlYXRpb24uXG4gICAgICAgICAqIEByZXR1cm5zIFRoZSBuZXdseS1jcmVhdGVkIFRhYlN0YWNrLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBpZiAoIWZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3LicpO1xuICAgICAgICAgKiB9XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiBjb25zdCBjb2x1bW5PclJvdyA9IGF3YWl0IHN0YWNrLmdldFBhcmVudCgpO1xuICAgICAgICAgKlxuICAgICAgICAgKiAvLyBDcmVhdGUgdmlldyByZWZlcmVuY2VzIGJ5IHN1cHBseWluZyBhICduYW1lJyBhbmQgJ3VybCdcbiAgICAgICAgICogY29uc3Qgdmlld3MgPSBbXG4gICAgICAgICAqICAgICAvLyBpZiAnbmFtZScgaXMgdW5kZWZpbmVkLCBvbmUgd2lsbCBiZSBnZW5lcmF0ZWRcbiAgICAgICAgICogICAgIC8vIGlmICd1cmwnIGlzIHVuZGVmaW5lZCwgaXQgd2lsbCBkZWZhdWx0IHRoZSB2aWV3IFVSTCB0byAnYWJvdXQ6YmxhbmsnXG4gICAgICAgICAqICAgICB7IG5hbWU6ICdnb29nbGUtdmlldycsIHVybDogJ2h0dHA6Ly9nb29nbGUuY29tLyd9LFxuICAgICAgICAgKiAgICAgeyBuYW1lOiAnb2YtZGV2ZWxvcGVycy12aWV3JywgdXJsOiAnaHR0cDovL2RldmVsb3BlcnMub3BlbmZpbi5jby8nfSxcbiAgICAgICAgICogXTtcbiAgICAgICAgICpcbiAgICAgICAgICogLy8gQ3JlYXRlIGEgdmlldyBiZWZvcmVoYW5kIHRvIGJlIGluY2x1ZGVkIGluIHRoZSBuZXcgdGFiIHN0YWNrXG4gICAgICAgICAqIGNvbnN0IG91dHNpZGVWaWV3ID0gYXdhaXQgZmluLlZpZXcuY3JlYXRlKHtcbiAgICAgICAgICogICAgIG5hbWU6ICdvdXRzaWRlLWJsb29tYmVyZy12aWV3JyxcbiAgICAgICAgICogICAgIHVybDogJ2h0dHBzOi8vYmxvb21iZXJnLmNvbS8nLFxuICAgICAgICAgKiAgICAgdGFyZ2V0OiBmaW4ubWUuaWRlbnRpdHksXG4gICAgICAgICAqIH0pO1xuICAgICAgICAgKlxuICAgICAgICAgKiAvLyBWaWV3cyB0byBhZGQgY2FuIGJlIGlkZW50aXRpZXMsIG9yIHRoZSByZWZlcmVuY2Ugdmlld3MgbWVudGlvbmVkIGFib3ZlXG4gICAgICAgICAqIGNvbnN0IHZpZXdzVG9BZGQgPSBbb3V0c2lkZVZpZXcuaWRlbnRpdHksIC4uLnZpZXdzXTtcbiAgICAgICAgICpcbiAgICAgICAgICogLy8gUG9zc2libGUgcG9zaXRpb24gaW5wdXRzOiAncmlnaHQnIHwgJ2xlZnQnIHwgJ3RvcCcgfCAnYm90dG9tJ1xuICAgICAgICAgKiBsZXQgc3RhY2tGcm9tID0gYXdhaXQgY29sdW1uT3JSb3cuY3JlYXRlQWRqYWNlbnRTdGFjayh2aWV3c1RvQWRkLCB7IHBvc2l0aW9uOiAncmlnaHQnIH0pO1xuICAgICAgICAgKiAvLyBPclxuICAgICAgICAgKiBsZXQgbmV3U3RhY2sgPSBhd2FpdCBzdGFjay5jcmVhdGVBZGphY2VudFN0YWNrKHZpZXdzVG9BZGQsIHsgcG9zaXRpb246ICdyaWdodCcgfSk7XG4gICAgICAgICAqIGNvbnNvbGUubG9nKGBBIG5ldyBUYWJTdGFjayBjcmVhdGVkIHRvIHRoZSByaWdodCBoYXMgJHtuZXdTdGFjay5sZW5ndGh9IHZpZXdzIGluIGl0YCk7XG4gICAgICAgICAqXG4gICAgICAgICAqIGBgYFxuICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmNyZWF0ZUFkamFjZW50U3RhY2sgPSBhc3luYyAodmlld3MsIG9wdGlvbnMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVudGl0eUlkID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRkKHRoaXMsIF9MYXlvdXROb2RlX2NsaWVudCwgXCJmXCIpLmNyZWF0ZUFkamFjZW50U3RhY2sodGhpcy5lbnRpdHlJZCwgdmlld3MsIG9wdGlvbnMpO1xuICAgICAgICAgICAgcmV0dXJuIExheW91dE5vZGUuZ2V0RW50aXR5KHsgZW50aXR5SWQsIHR5cGU6ICdzdGFjaycgfSwgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRkKHRoaXMsIF9MYXlvdXROb2RlX2NsaWVudCwgXCJmXCIpKTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHJpZXZlcyB0aGUgYWRqYWNlbnQgVGFiU3RhY2tzIG9mIHRoZSBnaXZlbiBUYWJTdGFjayBvciBDb2x1bW5PclJvdy5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIGVkZ2UgRWRnZSB3aG9zZSBhZGphY2VudCBUYWJTdGFja3Mgd2lsbCBiZSByZXR1cm5lZC5cbiAgICAgICAgICpcbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogaWYgKCFmaW4ubWUuaXNWaWV3KSB7XG4gICAgICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldy4nKTtcbiAgICAgICAgICogfVxuICAgICAgICAgKlxuICAgICAgICAgKiBjb25zdCBzdGFjayA9IGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50U3RhY2soKTtcbiAgICAgICAgICogY29uc3QgY29sdW1uT3JSb3cgPSBhd2FpdCBzdGFjay5nZXRQYXJlbnQoKTtcbiAgICAgICAgICogLy8gUG9zc2libGUgcG9zaXRpb24gaW5wdXRzOiAncmlnaHQnIHwgJ2xlZnQnIHwgJ3RvcCcgfCAnYm90dG9tJ1xuICAgICAgICAgKiBsZXQgcmlnaHRTdGFja3MgPSBhd2FpdCBjb2x1bW5PclJvdy5nZXRBZGphY2VudFN0YWNrcygncmlnaHQnKTtcbiAgICAgICAgICogbGV0IGxlZnRTdGFja3MgPSBhd2FpdCBjb2x1bW5PclJvdy5nZXRBZGphY2VudFN0YWNrcygnbGVmdCcpO1xuICAgICAgICAgKiAvLyBvclxuICAgICAgICAgKiBsZXQgcmlnaHRTdGFja3MgPSBhd2FpdCBzdGFjay5nZXRBZGphY2VudFN0YWNrcygncmlnaHQnKTtcbiAgICAgICAgICogbGV0IGxlZnRTdGFja3MgPSBhd2FpdCBzdGFjay5nZXRBZGphY2VudFN0YWNrcygnbGVmdCcpO1xuICAgICAgICAgKlxuICAgICAgICAgKiBjb25zb2xlLmxvZyhgVGhlIGVudGl0eSBoYXMgJHtyaWdodFN0YWNrcy5sZW5ndGh9IHN0YWNrcyB0byB0aGUgcmlnaHQsIGFuZCAke2xlZnRTdGFja3MubGVuZ3RofSBzdGFja3MgdG8gdGhlIGxlZnRgKTtcbiAgICAgICAgICpcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBleHBlcmltZW50YWxcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuZ2V0QWRqYWNlbnRTdGFja3MgPSBhc3luYyAoZWRnZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgYWRqYWNlbnRTdGFja3MgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX0xheW91dE5vZGVfY2xpZW50LCBcImZcIikuZ2V0QWRqYWNlbnRTdGFja3Moe1xuICAgICAgICAgICAgICAgIHRhcmdldElkOiB0aGlzLmVudGl0eUlkLFxuICAgICAgICAgICAgICAgIGVkZ2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIGFkamFjZW50U3RhY2tzLm1hcCgoc3RhY2spID0+IExheW91dE5vZGUuZ2V0RW50aXR5KHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnc3RhY2snLFxuICAgICAgICAgICAgICAgIGVudGl0eUlkOiBzdGFjay5lbnRpdHlJZFxuICAgICAgICAgICAgfSwgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRkKHRoaXMsIF9MYXlvdXROb2RlX2NsaWVudCwgXCJmXCIpKSk7XG4gICAgICAgIH07XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkYih0aGlzLCBfTGF5b3V0Tm9kZV9jbGllbnQsIGNsaWVudCwgXCJmXCIpO1xuICAgICAgICB0aGlzLmVudGl0eUlkID0gZW50aXR5SWQ7XG4gICAgfVxufVxubGF5b3V0RW50aXRpZXMuTGF5b3V0Tm9kZSA9IExheW91dE5vZGU7XG5fTGF5b3V0Tm9kZV9jbGllbnQgPSBuZXcgV2Vha01hcCgpO1xuLyoqXG4gKiBAaWdub3JlXG4gKiBAaW50ZXJuYWxcbiAqIEVuY2Fwc3VsYXRlcyBBcGkgY29uc3VtcHRpb24gb2Yge0BsaW5rIExheW91dEVudGl0aWVzQ2xpZW50fSB3aXRoIGEgcmVsYXllZCBkaXNwYXRjaFxuICogQHBhcmFtIGNsaWVudFxuICogQHBhcmFtIGNvbnRyb2xsZXJJZFxuICogQHBhcmFtIGlkZW50aXR5XG4gKiBAcmV0dXJucyBhIG5ldyBpbnN0YW5jZSBvZiB7QGxpbmsgTGF5b3V0RW50aXRpZXNDbGllbnR9IHdpdGggYm91bmQgdG8gdGhlIGNvbnRyb2xsZXJJZFxuICovXG5MYXlvdXROb2RlLm5ld0xheW91dEVudGl0aWVzQ2xpZW50ID0gYXN5bmMgKGNsaWVudCwgY29udHJvbGxlcklkLCBpZGVudGl0eSkgPT4ge1xuICAgIGNvbnN0IGRpc3BhdGNoID0gKDAsIGNoYW5uZWxfYXBpX3JlbGF5XzEuY3JlYXRlUmVsYXllZERpc3BhdGNoKShjbGllbnQsIGlkZW50aXR5LCAnbGF5b3V0LXJlbGF5JywgJ1lvdSBhcmUgdHJ5aW5nIHRvIGludGVyYWN0IHdpdGggYSBsYXlvdXQgY29tcG9uZW50IG9uIGEgd2luZG93IHRoYXQgZG9lcyBub3QgZXhpc3Qgb3IgaGFzIGJlZW4gZGVzdHJveWVkLicpO1xuICAgIGNvbnN0IGNvbnN1bWVyID0gbmV3IGFwaV9leHBvc2VyXzEuQXBpQ29uc3VtZXIobmV3IGFwaV9leHBvc2VyXzEuQ2hhbm5lbHNDb25zdW1lcih7IGRpc3BhdGNoIH0pKTtcbiAgICByZXR1cm4gY29uc3VtZXIuY29uc3VtZSh7IGlkOiBjb250cm9sbGVySWQgfSk7XG59O1xuTGF5b3V0Tm9kZS5nZXRFbnRpdHkgPSAoZGVmaW5pdGlvbiwgY2xpZW50KSA9PiB7XG4gICAgY29uc3QgeyBlbnRpdHlJZCwgdHlwZSB9ID0gZGVmaW5pdGlvbjtcbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSAnY29sdW1uJzpcbiAgICAgICAgY2FzZSAncm93JzpcbiAgICAgICAgICAgIHJldHVybiBuZXcgQ29sdW1uT3JSb3coY2xpZW50LCBlbnRpdHlJZCwgdHlwZSk7XG4gICAgICAgIGNhc2UgJ3N0YWNrJzpcbiAgICAgICAgICAgIHJldHVybiBuZXcgVGFiU3RhY2soY2xpZW50LCBlbnRpdHlJZCk7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVucmVjb2duaXNlZCBMYXlvdXQgRW50aXR5IGVuY291bnRlcmVkICgnJHtKU09OLnN0cmluZ2lmeShkZWZpbml0aW9uKX0pYCk7XG4gICAgfVxufTtcbi8qKlxuICogQSBUYWJTdGFjayBpcyB1c2VkIHRvIG1hbmFnZSB0aGUgc3RhdGUgb2YgYSBzdGFjayBvZiB0YWJzIHdpdGhpbiBhbiBPcGVuRmluIExheW91dC5cbiAqL1xuY2xhc3MgVGFiU3RhY2sgZXh0ZW5kcyBMYXlvdXROb2RlIHtcbiAgICAvKiogQGludGVybmFsICovXG4gICAgY29uc3RydWN0b3IoY2xpZW50LCBlbnRpdHlJZCkge1xuICAgICAgICBzdXBlcihjbGllbnQsIGVudGl0eUlkKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBpbnRlcm5hbFxuICAgICAgICAgKiBBcGlDbGllbnQgZm9yIHtAbGluayBMYXlvdXRFbnRpdGllc0NvbnRyb2xsZXJ9XG4gICAgICAgICAqL1xuICAgICAgICBfVGFiU3RhY2tfY2xpZW50LnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICAvKipcbiAgICAgICAgICogVHlwZSBvZiB0aGUgY29udGVudCBpdGVtLiBBbHdheXMgc3RhY2ssIGJ1dCB1c2VmdWwgZm9yIGRpc3Rpbmd1aXNoaW5nIGJldHdlZW4gYSB7QGxpbmsgVGFiU3RhY2t9IGFuZCB7QGxpbmsgQ29sdW1uT3JSb3d9LlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy50eXBlID0gJ3N0YWNrJztcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJldHJpZXZlcyBhIGxpc3Qgb2YgYWxsIHZpZXdzIGJlbG9uZ2luZyB0byB0aGlzIHtAbGluayBUYWJTdGFja30uXG4gICAgICAgICAqXG4gICAgICAgICAqIEtub3duIElzc3VlOiBJZiBhZGRpbmcgYSB2aWV3IG92ZXJmbG93cyB0aGUgdGFiLWNvbnRhaW5lciB3aWR0aCwgdGhlIGFkZGVkIHZpZXcgd2lsbCBiZSBzZXQgYXMgYWN0aXZlXG4gICAgICAgICAqIGFuZCByZW5kZXJlZCBhdCB0aGUgZnJvbnQgb2YgdGhlIHRhYi1zdGFjaywgd2hpbGUgdGhlIHVuZGVybHlpbmcgb3JkZXIgb2YgdGFicyB3aWxsIHJlbWFpbiB1bmNoYW5nZWQuXG4gICAgICAgICAqIElmIHRoYXQgaGFwcGVucyBhbmQgdGhlbiBnZXRWaWV3cygpIGlzIGNhbGxlZCwgaXQgd2lsbCByZXR1cm4gdGhlIGlkZW50aXRpZXMgaW4gYSBkaWZmZXJlbnQgb3JkZXIgdGhhblxuICAgICAgICAgKiB0aGFuIHRoZSBjdXJyZW50bHkgcmVuZGVyZWQgdGFiIG9yZGVyLlxuICAgICAgICAgKlxuICAgICAgICAgKlxuICAgICAgICAgKiBAdGhyb3dzIElmIHRoZSB7QGxpbmsgVGFiU3RhY2t9IGhhcyBiZWVuIGRlc3Ryb3llZC5cbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogaWYgKCFmaW4ubWUuaXNWaWV3KSB7XG4gICAgICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldy4nKTtcbiAgICAgICAgICogfVxuICAgICAgICAgKlxuICAgICAgICAgKiBjb25zdCBzdGFjayA9IGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50U3RhY2soKTtcbiAgICAgICAgICogLy8gQWx0ZXJuYXRpdmVseSwgeW91IGNhbiB3cmFwIGFueSB2aWV3IGFuZCBnZXQgdGhlIHN0YWNrIGZyb20gdGhlcmVcbiAgICAgICAgICogLy8gY29uc3Qgdmlld0Zyb21Tb21ld2hlcmUgPSBmaW4uVmlldy53cmFwU3luYyhzb21lVmlldy5pZGVudGl0eSk7XG4gICAgICAgICAqIC8vIGNvbnN0IHN0YWNrID0gYXdhaXQgdmlld0Zyb21Tb21ld2hlcmUuZ2V0Q3VycmVudFN0YWNrKCk7XG4gICAgICAgICAqIGNvbnN0IHZpZXdzID0gYXdhaXQgc3RhY2suZ2V0Vmlld3MoKTtcbiAgICAgICAgICogY29uc29sZS5sb2coYFN0YWNrIGNvbnRhaW5zICR7dmlld3MubGVuZ3RofSB2aWV3KHMpYCk7XG4gICAgICAgICAqIGBgYFxuICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmdldFZpZXdzID0gKCkgPT4gX19jbGFzc1ByaXZhdGVGaWVsZEdldCRkKHRoaXMsIF9UYWJTdGFja19jbGllbnQsIFwiZlwiKS5nZXRTdGFja1ZpZXdzKHRoaXMuZW50aXR5SWQpO1xuICAgICAgICAvKipcbiAgICAgICAgICogQWRkcyBvciBjcmVhdGVzIGEgdmlldyBpbiB0aGlzIHtAbGluayBUYWJTdGFja30uXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZW1hcmtzIEtub3duIElzc3VlOiBJZiBhZGRpbmcgYSB2aWV3IG92ZXJmbG93cyB0aGUgdGFiLWNvbnRhaW5lciwgdGhlIGFkZGVkIHZpZXcgd2lsbCBiZSBzZXQgYXMgYWN0aXZlXG4gICAgICAgICAqIGFuZCByZW5kZXJlZCBhdCB0aGUgZnJvbnQgb2YgdGhlIHRhYi1zdGFjaywgd2hpbGUgdGhlIHVuZGVybHlpbmcgb3JkZXIgb2YgdGFicyB3aWxsIHJlbWFpbiB1bmNoYW5nZWQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBwYXJhbSB2aWV3IFRoZSBpZGVudGl0eSBvZiBhbiBleGlzdGluZyB2aWV3IHRvIGFkZCwgb3Igb3B0aW9ucyB0byBjcmVhdGUgYSB2aWV3LlxuICAgICAgICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25hbCB2aWV3IG9wdGlvbnM6IGluZGV4IG51bWJlciB1c2VkIHRvIGluc2VydCB0aGUgdmlldyBpbnRvIHRoZSBzdGFjayBhdCB0aGF0IGluZGV4LiBEZWZhdWx0cyB0byAwIChmcm9udCBvZiB0aGUgc3RhY2spXG4gICAgICAgICAqIEByZXR1cm5zIFJlc29sdmVzIHdpdGggdGhlIHtAbGluayBPcGVuRmluLklkZW50aXR5IGlkZW50aXR5fSBvZiB0aGUgYWRkZWQgdmlldy5cbiAgICAgICAgICogQHRocm93cyBJZiB0aGUgdmlldyBkb2VzIG5vdCBleGlzdCBvciBmYWlscyB0byBjcmVhdGUuXG4gICAgICAgICAqIEB0aHJvd3MgSWYgdGhlIHtAbGluayBUYWJTdGFja30gaGFzIGJlZW4gZGVzdHJveWVkLlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBpZiAoIWZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3LicpO1xuICAgICAgICAgKiB9XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiAvLyBBbHRlcm5hdGl2ZWx5LCB5b3UgY2FuIHdyYXAgYW55IHZpZXcgYW5kIGdldCB0aGUgc3RhY2sgZnJvbSB0aGVyZVxuICAgICAgICAgKiAvLyBjb25zdCB2aWV3RnJvbVNvbWV3aGVyZSA9IGZpbi5WaWV3LndyYXBTeW5jKHNvbWVWaWV3LmlkZW50aXR5KTtcbiAgICAgICAgICogLy8gY29uc3Qgc3RhY2sgPSBhd2FpdCB2aWV3RnJvbVNvbWV3aGVyZS5nZXRDdXJyZW50U3RhY2soKTtcbiAgICAgICAgICogY29uc3QgZ29vZ2xlVmlld0lkZW50aXR5ID0gYXdhaXQgc3RhY2suYWRkVmlldyh7IG5hbWU6ICdnb29nbGUtdmlldycsIHVybDogJ2h0dHA6Ly9nb29nbGUuY29tLycgfSk7XG4gICAgICAgICAqIGNvbnNvbGUubG9nKCdJZGVudGl0eSBvZiB0aGUgZ29vZ2xlIHZpZXcganVzdCBhZGRlZCcsIHsgZ29vZ2xlVmlld0lkZW50aXR5IH0pO1xuICAgICAgICAgKiAvLyBwYXNzIGluIHsgaW5kZXg6IG51bWJlciB9IHRvIHNldCB0aGUgaW5kZXggaW4gdGhlIHN0YWNrLiBIZXJlIDEgbWVhbnMsIGVuZCBvZiB0aGUgc3RhY2sgKGRlZmF1bHRzIHRvIDApXG4gICAgICAgICAqIGNvbnN0IGFwcGxlVmlld0lkZW50aXR5ID0gYXdhaXQgc3RhY2suYWRkVmlldyh7IG5hbWU6ICdhcHBsZS12aWV3JywgdXJsOiAnaHR0cDovL2FwcGxlLmNvbS8nIH0sIHsgaW5kZXg6IDEgfSk7XG4gICAgICAgICAqIGNvbnNvbGUubG9nKCdJZGVudGl0eSBvZiB0aGUgYXBwbGUgdmlldyBqdXN0IGFkZGVkJywgeyBhcHBsZVZpZXdJZGVudGl0eSB9KTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqIEBleHBlcmltZW50YWxcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuYWRkVmlldyA9IGFzeW5jICh2aWV3LCBvcHRpb25zID0geyBpbmRleDogMCB9KSA9PiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGQodGhpcywgX1RhYlN0YWNrX2NsaWVudCwgXCJmXCIpLmFkZFZpZXdUb1N0YWNrKHRoaXMuZW50aXR5SWQsIHZpZXcsIG9wdGlvbnMpO1xuICAgICAgICAvKipcbiAgICAgICAgICogUmVtb3ZlcyBhIHZpZXcgZnJvbSB0aGlzIHtAbGluayBUYWJTdGFja30uXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZW1hcmtzIFRocm93cyBhbiBleGNlcHRpb24gaWYgdGhlIHZpZXcgaWRlbnRpdHkgZG9lcyBub3QgZXhpc3Qgb3Igd2FzIGFscmVhZHkgZGVzdHJveWVkLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdmlldyAtIElkZW50aXR5IG9mIHRoZSB2aWV3IHRvIHJlbW92ZS5cbiAgICAgICAgICogQHRocm93cyBJZiB0aGUgdmlldyBkb2VzIG5vdCBleGlzdCBvciBkb2VzIG5vdCBiZWxvbmcgdG8gdGhlIHN0YWNrLlxuICAgICAgICAgKiBAdGhyb3dzIElmIHRoZSB7QGxpbmsgVGFiU3RhY2t9IGhhcyBiZWVuIGRlc3Ryb3llZC5cbiAgICAgICAgICpcbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogaWYgKCFmaW4ubWUuaXNWaWV3KSB7XG4gICAgICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldy4nKTtcbiAgICAgICAgICogfVxuICAgICAgICAgKlxuICAgICAgICAgKiBjb25zdCBzdGFjayA9IGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50U3RhY2soKTtcbiAgICAgICAgICogY29uc3QgZ29vZ2xlVmlld0lkZW50aXR5ID0gYXdhaXQgc3RhY2suYWRkVmlldyh7IG5hbWU6ICdnb29nbGUtdmlldycsIHVybDogJ2h0dHA6Ly9nb29nbGUuY29tLycgfSk7XG4gICAgICAgICAqXG4gICAgICAgICAqIGF3YWl0IHN0YWNrLnJlbW92ZVZpZXcoZ29vZ2xlVmlld0lkZW50aXR5KTtcbiAgICAgICAgICpcbiAgICAgICAgICogdHJ5IHtcbiAgICAgICAgICogICAgIGF3YWl0IHN0YWNrLnJlbW92ZVZpZXcoZ29vZ2xlVmlld0lkZW50aXR5KTtcbiAgICAgICAgICogfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICogICAgIC8vIFRyaWVkIHRvIHJlbW92ZSBhIHZpZXcgKCdnb29nbGUtdmlldycpIHdoaWNoIGRvZXMgbm90IGJlbG9uZyB0byB0aGUgc3RhY2suXG4gICAgICAgICAqICAgICBjb25zb2xlLmxvZyhlcnJvcik7XG4gICAgICAgICAqIH1cbiAgICAgICAgICogYGBgXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnJlbW92ZVZpZXcgPSBhc3luYyAodmlldykgPT4ge1xuICAgICAgICAgICAgYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRkKHRoaXMsIF9UYWJTdGFja19jbGllbnQsIFwiZlwiKS5yZW1vdmVWaWV3RnJvbVN0YWNrKHRoaXMuZW50aXR5SWQsIHZpZXcpO1xuICAgICAgICB9O1xuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyB0aGUgYWN0aXZlIHZpZXcgb2YgdGhlIHtAbGluayBUYWJTdGFja30gd2l0aG91dCBmb2N1c2luZyBpdC5cbiAgICAgICAgICogQHBhcmFtIHZpZXcgLSBJZGVudGl0eSBvZiB0aGUgdmlldyB0byBhY3RpdmF0ZS5cbiAgICAgICAgICogQHJldHVybnMgUHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aXRoIHZvaWQgb25jZSB0aGUgdmlldyBoYXMgYmVlbiBhY3RpdmF0ZWQuXG4gICAgICAgICAqIEB0aHJvd3MgSWYgdGhlIHtAbGluayBUYWJTdGFja30gaGFzIGJlZW4gZGVzdHJveWVkLlxuICAgICAgICAgKiBAdGhyb3dzIElmIHRoZSB2aWV3IGRvZXMgbm90IGV4aXN0LlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBDaGFuZ2UgdGhlIGFjdGl2ZSB0YWIgb2YgYSBrbm93biBWaWV3J3MgVGFiU3RhY2s6XG4gICAgICAgICAqIGBgYGpzXG4gICAgICAgICAqIGNvbnN0IHRhcmdldFZpZXcgPSBmaW4uVmlldy53cmFwU3luYyh7IHV1aWQ6ICd1dWlkJywgbmFtZTogJ3ZpZXctbmFtZScgfSk7XG4gICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgdGFyZ2V0Vmlldy5nZXRDdXJyZW50U3RhY2soKTtcbiAgICAgICAgICogYXdhaXQgc3RhY2suc2V0QWN0aXZlVmlldyh0YXJnZXRWaWV3LmlkZW50aXR5KTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqXG4gICAgICAgICAqIFNldCB0aGUgY3VycmVudCBWaWV3IGFzIGFjdGl2ZSB3aXRoaW4gaXRzIFRhYlN0YWNrOlxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBjb25zdCBzdGFjayA9IGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50U3RhY2soKTtcbiAgICAgICAgICogYXdhaXQgc3RhY2suc2V0QWN0aXZlVmlldyhmaW4ubWUuaWRlbnRpdHkpO1xuICAgICAgICAgKiBgYGBcbiAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5zZXRBY3RpdmVWaWV3ID0gYXN5bmMgKHZpZXcpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkZCh0aGlzLCBfVGFiU3RhY2tfY2xpZW50LCBcImZcIikuc2V0U3RhY2tBY3RpdmVWaWV3KHRoaXMuZW50aXR5SWQsIHZpZXcpO1xuICAgICAgICB9O1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JGIodGhpcywgX1RhYlN0YWNrX2NsaWVudCwgY2xpZW50LCBcImZcIik7XG4gICAgfVxufVxubGF5b3V0RW50aXRpZXMuVGFiU3RhY2sgPSBUYWJTdGFjaztcbl9UYWJTdGFja19jbGllbnQgPSBuZXcgV2Vha01hcCgpO1xuLyoqXG4gKiBBIENvbHVtbk9yUm93IGlzIHVzZWQgdG8gbWFuYWdlIHRoZSBzdGF0ZSBvZiBDb2x1bW4gYW5kIFJvd3Mgd2l0aGluIGFuIE9wZW5GaW4gTGF5b3V0LlxuICovXG5jbGFzcyBDb2x1bW5PclJvdyBleHRlbmRzIExheW91dE5vZGUge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGNsaWVudCwgZW50aXR5SWQsIHR5cGUpIHtcbiAgICAgICAgc3VwZXIoY2xpZW50LCBlbnRpdHlJZCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAaWdub3JlXG4gICAgICAgICAqIEBpbnRlcm5hbFxuICAgICAgICAgKiBBcGlDbGllbnQgZm9yIHtAbGluayBMYXlvdXRFbnRpdGllc0NvbnRyb2xsZXJ9XG4gICAgICAgICAqL1xuICAgICAgICBfQ29sdW1uT3JSb3dfY2xpZW50LnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICAvKipcbiAgICAgICAgICogUmV0cmlldmVzIHRoZSBjb250ZW50IGFycmF5IG9mIHRoZSBDb2x1bW5PclJvd1xuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBpZiAoIWZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3LicpO1xuICAgICAgICAgKiB9XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IHN0YWNrID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRTdGFjaygpO1xuICAgICAgICAgKiAvLyBSZXRyaWV2ZXMgdGhlIHBhcmVudCBDb2x1bW5PclJvd1xuICAgICAgICAgKiBjb25zdCBjb2x1bW5PclJvdyA9IGF3YWl0IHN0YWNrLmdldFBhcmVudCgpO1xuICAgICAgICAgKlxuICAgICAgICAgKiAvLyByZXR1cm5zIFtUYWJTdGFja11cbiAgICAgICAgICogY29uc3QgY29udGVudEFycmF5ID0gYXdhaXQgY29sdW1uT3JSb3cuZ2V0Q29udGVudCgpO1xuICAgICAgICAgKiBjb25zb2xlLmxvZyhgVGhlIENvbHVtbk9yUm93IGhhcyAke2NvbnRlbnRBcnJheS5sZW5ndGh9IGl0ZW0ocylgKTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLmdldENvbnRlbnQgPSBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb250ZW50SXRlbUVudGl0aWVzID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRkKHRoaXMsIF9Db2x1bW5PclJvd19jbGllbnQsIFwiZlwiKS5nZXRDb250ZW50KHRoaXMuZW50aXR5SWQpO1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRlbnRJdGVtRW50aXRpZXMubWFwKChlbnRpdHkpID0+IExheW91dE5vZGUuZ2V0RW50aXR5KGVudGl0eSwgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRkKHRoaXMsIF9Db2x1bW5PclJvd19jbGllbnQsIFwiZlwiKSkpO1xuICAgICAgICB9O1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JGIodGhpcywgX0NvbHVtbk9yUm93X2NsaWVudCwgY2xpZW50LCBcImZcIik7XG4gICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgfVxufVxubGF5b3V0RW50aXRpZXMuQ29sdW1uT3JSb3cgPSBDb2x1bW5PclJvdztcbl9Db2x1bW5PclJvd19jbGllbnQgPSBuZXcgV2Vha01hcCgpO1xuXG52YXIgbGF5b3V0X2NvbnN0YW50cyA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkobGF5b3V0X2NvbnN0YW50cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5sYXlvdXRfY29uc3RhbnRzLkRFRkFVTFRfTEFZT1VUX0tFWSA9IGxheW91dF9jb25zdGFudHMuTEFZT1VUX0NPTlRST0xMRVJfSUQgPSB2b2lkIDA7XG5sYXlvdXRfY29uc3RhbnRzLkxBWU9VVF9DT05UUk9MTEVSX0lEID0gJ2xheW91dC1lbnRpdGllcyc7XG4vLyBUT0RPOiBldmVudHVhbGx5IGV4cG9ydCB0aGlzIHNvbWVob3dcbmxheW91dF9jb25zdGFudHMuREVGQVVMVF9MQVlPVVRfS0VZID0gJ19fZGVmYXVsdF9fJztcblxudmFyIG1haW4gPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KG1haW4sIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xubWFpbi5XZWJDb250ZW50cyA9IHZvaWQgMDtcbmNvbnN0IGJhc2VfMSRqID0gYmFzZTtcbmNsYXNzIFdlYkNvbnRlbnRzIGV4dGVuZHMgYmFzZV8xJGouRW1pdHRlckJhc2Uge1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBpZGVudGl0eSBUaGUgaWRlbnRpdHkgb2YgdGhlIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIFdlYkNvbnRlbnRzfS5cbiAgICAgKiBAcGFyYW0gZW50aXR5VHlwZSBUaGUgdHlwZSBvZiB0aGUge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgV2ViQ29udGVudHN9LlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHdpcmUsIGlkZW50aXR5LCBlbnRpdHlUeXBlKSB7XG4gICAgICAgIHN1cGVyKHdpcmUsIGVudGl0eVR5cGUsIGlkZW50aXR5LnV1aWQsIGlkZW50aXR5Lm5hbWUpO1xuICAgICAgICB0aGlzLmlkZW50aXR5ID0gaWRlbnRpdHk7XG4gICAgICAgIHRoaXMuZW50aXR5VHlwZSA9IGVudGl0eVR5cGU7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldHMgYSBiYXNlNjQgZW5jb2RlZCBpbWFnZSBvZiBhbGwgb3IgcGFydCBvZiB0aGUgV2ViQ29udGVudHMuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgT3B0aW9ucyBmb3IgdGhlIGNhcHR1cmVQYWdlIGNhbGwuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHZpZXcgPSBmaW4uVmlldy5nZXRDdXJyZW50U3luYygpO1xuICAgICAqXG4gICAgICogLy8gUE5HIGltYWdlIG9mIGEgZnVsbCB2aXNpYmxlIFZpZXdcbiAgICAgKiBjb25zb2xlLmxvZyhhd2FpdCB2aWV3LmNhcHR1cmVQYWdlKCkpO1xuICAgICAqXG4gICAgICogLy8gTG93LXF1YWxpdHkgSlBFRyBpbWFnZSBvZiBhIGRlZmluZWQgdmlzaWJsZSBhcmVhIG9mIHRoZSB2aWV3XG4gICAgICogY29uc3Qgb3B0aW9ucyA9IHtcbiAgICAgKiAgICAgYXJlYToge1xuICAgICAqICAgICAgICAgaGVpZ2h0OiAxMDAsXG4gICAgICogICAgICAgICB3aWR0aDogMTAwLFxuICAgICAqICAgICAgICAgeDogMTAsXG4gICAgICogICAgICAgICB5OiAxMCxcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgZm9ybWF0OiAnanBnJyxcbiAgICAgKiAgICAgcXVhbGl0eTogMjBcbiAgICAgKiB9XG4gICAgICogY29uc29sZS5sb2coYXdhaXQgdmlldy5jYXB0dXJlUGFnZShvcHRpb25zKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCB3bmQgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcbiAgICAgKlxuICAgICAqIC8vIFBORyBpbWFnZSBvZiBhIGZ1bGwgdmlzaWJsZSB3aW5kb3dcbiAgICAgKiBjb25zb2xlLmxvZyhhd2FpdCB3bmQuY2FwdHVyZVBhZ2UoKSk7XG4gICAgICpcbiAgICAgKiAvLyBMb3ctcXVhbGl0eSBKUEVHIGltYWdlIG9mIGEgZGVmaW5lZCB2aXNpYmxlIGFyZWEgb2YgdGhlIHdpbmRvd1xuICAgICAqIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICogICAgIGFyZWE6IHtcbiAgICAgKiAgICAgICAgIGhlaWdodDogMTAwLFxuICAgICAqICAgICAgICAgd2lkdGg6IDEwMCxcbiAgICAgKiAgICAgICAgIHg6IDEwLFxuICAgICAqICAgICAgICAgeTogMTAsXG4gICAgICogICAgIH0sXG4gICAgICogICAgIGZvcm1hdDogJ2pwZycsXG4gICAgICogICAgIHF1YWxpdHk6IDIwXG4gICAgICogfVxuICAgICAqIGNvbnNvbGUubG9nKGF3YWl0IHduZC5jYXB0dXJlUGFnZShvcHRpb25zKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIGBXZWJDb250ZW50c2AgcmVmZXJzIHRvIHNoYXJlZCBmdW5jdGlvbmFsaXR5IGJldHdlZW4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gICAgICogV2UgZG8gbm90IGV4cG9zZSBhbiBleHBsaWNpdCBzdXBlcmNsYXNzIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHksIGJ1dCBpdCBkb2VzIGhhdmUgaXRzIG93blxuICAgICAqIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIGV2ZW50IG5hbWVzcGFjZX0uXG4gICAgICovXG4gICAgY2FwdHVyZVBhZ2Uob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NhcHR1cmUtcGFnZScsIHsgb3B0aW9ucywgLi4udGhpcy5pZGVudGl0eSB9KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRXhlY3V0ZXMgSmF2YXNjcmlwdCBvbiB0aGUgV2ViQ29udGVudHMsIHJlc3RyaWN0ZWQgdG8gY29udGVudHMgeW91IG93biBvciBjb250ZW50cyBvd25lZCBieVxuICAgICAqIGFwcGxpY2F0aW9ucyB5b3UgaGF2ZSBjcmVhdGVkLlxuICAgICAqIEBwYXJhbSBjb2RlIEphdmFTY3JpcHQgY29kZSB0byBiZSBleGVjdXRlZCBvbiB0aGUgdmlldy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIGV4ZWN1dGVKYXZhU2NyaXB0KGNvZGUpIHtcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LndyYXAoe3V1aWQ6ICd1dWlkJywgbmFtZTogJ3ZpZXcgbmFtZSd9KTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHZpZXcuZXhlY3V0ZUphdmFTY3JpcHQoY29kZSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZXhlY3V0ZUphdmFTY3JpcHQoYGNvbnNvbGUubG9nKCdIZWxsbywgT3BlbmZpbicpYCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnSmF2YXNjcmlwdCBleGN1dGVkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFdpbmRvdzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIGV4ZWN1dGVKYXZhU2NyaXB0KGNvZGUpIHtcbiAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcbiAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG4gICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5leGVjdXRlSmF2YVNjcmlwdC5odG1sJyxcbiAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG4gICAgICogICAgIH0pO1xuICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uZXhlY3V0ZUphdmFTY3JpcHQoY29kZSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZXhlY3V0ZUphdmFTY3JpcHQoYGNvbnNvbGUubG9nKCdIZWxsbywgT3BlbmZpbicpYCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnSmF2YXNjcmlwdCBleGN1dGVkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIGBXZWJDb250ZW50c2AgcmVmZXJzIHRvIHNoYXJlZCBmdW5jdGlvbmFsaXR5IGJldHdlZW4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gICAgICogV2UgZG8gbm90IGV4cG9zZSBhbiBleHBsaWNpdCBzdXBlcmNsYXNzIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHksIGJ1dCBpdCBkb2VzIGhhdmUgaXRzIG93blxuICAgICAqIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIGV2ZW50IG5hbWVzcGFjZX0uXG4gICAgICovXG4gICAgZXhlY3V0ZUphdmFTY3JpcHQoY29kZSkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlXG4gICAgICAgICAgICAuc2VuZEFjdGlvbignZXhlY3V0ZS1qYXZhc2NyaXB0LWluLXdpbmRvdycsIHsgLi4udGhpcy5pZGVudGl0eSwgY29kZSB9KVxuICAgICAgICAgICAgLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB6b29tIGxldmVsIG9mIHRoZSBXZWJDb250ZW50cy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFpvb21MZXZlbCgpIHtcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHZpZXcuZ2V0Wm9vbUxldmVsKCk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZ2V0Wm9vbUxldmVsKCkudGhlbih6b29tTGV2ZWwgPT4gY29uc29sZS5sb2coem9vbUxldmVsKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luKCkge1xuICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcbiAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG4gICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmdldFpvb21MZXZlbC5odG1sJyxcbiAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG4gICAgICogICAgIH0pO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFpvb21MZXZlbCgpIHtcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgY3JlYXRlV2luKCk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uZ2V0Wm9vbUxldmVsKCk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZ2V0Wm9vbUxldmVsKCkudGhlbih6b29tTGV2ZWwgPT4gY29uc29sZS5sb2coem9vbUxldmVsKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBnZXRab29tTGV2ZWwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXpvb20tbGV2ZWwnLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgV2ViQ29udGVudHMuXG4gICAgICogQHBhcmFtIGxldmVsIFRoZSB6b29tIGxldmVsXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBzZXRab29tTGV2ZWwobnVtYmVyKSB7XG4gICAgICogICAgIGNvbnN0IHZpZXcgPSBhd2FpdCBmaW4uVmlldy5nZXRDdXJyZW50KCk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCB2aWV3LnNldFpvb21MZXZlbChudW1iZXIpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHNldFpvb21MZXZlbCg0KS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTZXR0aW5nIGEgIHpvb20gbGV2ZWwnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luKCkge1xuICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcbiAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG4gICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LnNldFpvb21MZXZlbC5odG1sJyxcbiAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG4gICAgICogICAgIH0pO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNldFpvb21MZXZlbChudW1iZXIpIHtcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgY3JlYXRlV2luKCk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uc2V0Wm9vbUxldmVsKG51bWJlcik7XG4gICAgICogfVxuICAgICAqXG4gICAgICogc2V0Wm9vbUxldmVsKDQpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1NldHRpbmcgYSAgem9vbSBsZXZlbCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIHNldFpvb21MZXZlbChsZXZlbCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NldC16b29tLWxldmVsJywgeyAuLi50aGlzLmlkZW50aXR5LCBsZXZlbCB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE5hdmlnYXRlcyB0aGUgV2ViQ29udGVudHMgdG8gYSBzcGVjaWZpZWQgVVJMLlxuICAgICAqXG4gICAgICogTm90ZTogVGhlIHVybCBtdXN0IGNvbnRhaW4gdGhlIHByb3RvY29sIHByZWZpeCBzdWNoIGFzIGh0dHA6Ly8gb3IgaHR0cHM6Ly8uXG4gICAgICogQHBhcmFtIHVybCAtIFRoZSBVUkwgdG8gbmF2aWdhdGUgdGhlIFdlYkNvbnRlbnRzIHRvLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlVmlldygpIHtcbiAgICAgKiAgICAgY29uc3QgbWUgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgcmV0dXJuIGZpbi5WaWV3LmNyZWF0ZSh7XG4gICAgICogICAgICAgICBuYW1lOiAndmlld05hbWUnLFxuICAgICAqICAgICAgICAgdGFyZ2V0OiBtZS5pZGVudGl0eSxcbiAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cbiAgICAgKiAgICAgfSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogY3JlYXRlVmlldygpXG4gICAgICogICAgIC50aGVuKHZpZXcgPT4gdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9leGFtcGxlLmNvbScpKVxuICAgICAqICAgICAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnbmF2aWdhdGlvbiBjb21wbGV0ZScpKVxuICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gbmF2aWdhdGUoKSB7XG4gICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLm5hdmlnYXRlKCdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93Lm5hdmlnYXRlLmh0bWwnKTtcbiAgICAgKiB9XG4gICAgICogbmF2aWdhdGUoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdOYXZpZ2F0ZSB0byB0dXRvcmlhbCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBuYXZpZ2F0ZSh1cmwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCduYXZpZ2F0ZS13aW5kb3cnLCB7IC4uLnRoaXMuaWRlbnRpdHksIHVybCB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE5hdmlnYXRlcyB0aGUgV2ViQ29udGVudHMgYmFjayBvbmUgcGFnZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIG5hdmlnYXRlQmFjaygpIHtcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LndyYXAoeyBuYW1lOiAndGVzdGFwcC12aWV3JywgdXVpZDogJ3Rlc3RhcHAnIH0pO1xuICAgICAqICAgICBhd2FpdCB2aWV3Lm5hdmlnYXRlKCdodHRwczovL3d3dy5nb29nbGUuY29tJyk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCB2aWV3Lm5hdmlnYXRlQmFjaygpO1xuICAgICAqIH1cbiAgICAgKiBuYXZpZ2F0ZUJhY2soKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdOYXZpZ2F0ZWQgYmFjaycpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBuYXZpZ2F0ZUJhY2soKSB7XG4gICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cud3JhcCh7IG5hbWU6ICd0ZXN0YXBwJywgdXVpZDogJ3Rlc3RhcHAnIH0pO1xuICAgICAqICAgICBhd2FpdCB3aW4ubmF2aWdhdGUoJ2h0dHBzOi8vd3d3Lmdvb2dsZS5jb20nKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5uYXZpZ2F0ZUJhY2soKTtcbiAgICAgKiB9XG4gICAgICogbmF2aWdhdGVCYWNrKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnTmF2aWdhdGVkIGJhY2snKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBuYXZpZ2F0ZUJhY2soKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignbmF2aWdhdGUtd2luZG93LWJhY2snLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBOYXZpZ2F0ZXMgdGhlIFdlYkNvbnRlbnRzIGZvcndhcmQgb25lIHBhZ2UuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBuYXZpZ2F0ZUZvcndhcmQoKSB7XG4gICAgICogICAgIGNvbnN0IHZpZXcgPSBhd2FpdCBmaW4uVmlldy5nZXRDdXJyZW50KCk7XG4gICAgICogICAgIGF3YWl0IHZpZXcubmF2aWdhdGUoJ2h0dHBzOi8vd3d3Lmdvb2dsZS5jb20nKTtcbiAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZUJhY2soKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHZpZXcubmF2aWdhdGVGb3J3YXJkKCk7XG4gICAgICogfVxuICAgICAqIG5hdmlnYXRlRm9yd2FyZCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ05hdmlnYXRlZCBmb3J3YXJkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFdpbmRvdzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIG5hdmlnYXRlRm9yd2FyZCgpIHtcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG4gICAgICogICAgIGF3YWl0IHdpbi5uYXZpZ2F0ZSgnaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbScpO1xuICAgICAqICAgICBhd2FpdCB3aW4ubmF2aWdhdGVCYWNrKCk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCB3aW4ubmF2aWdhdGVGb3J3YXJkKCk7XG4gICAgICogfVxuICAgICAqIG5hdmlnYXRlRm9yd2FyZCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ05hdmlnYXRlZCBmb3J3YXJkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIGBXZWJDb250ZW50c2AgcmVmZXJzIHRvIHNoYXJlZCBmdW5jdGlvbmFsaXR5IGJldHdlZW4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gICAgICogV2UgZG8gbm90IGV4cG9zZSBhbiBleHBsaWNpdCBzdXBlcmNsYXNzIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHksIGJ1dCBpdCBkb2VzIGhhdmUgaXRzIG93blxuICAgICAqIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIGV2ZW50IG5hbWVzcGFjZX0uXG4gICAgICovXG4gICAgYXN5bmMgbmF2aWdhdGVGb3J3YXJkKCkge1xuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignbmF2aWdhdGUtd2luZG93LWZvcndhcmQnLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN0b3BzIGFueSBjdXJyZW50IG5hdmlnYXRpb24gdGhlIFdlYkNvbnRlbnRzIGlzIHBlcmZvcm1pbmcuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBzdG9wTmF2aWdhdGlvbigpIHtcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LndyYXAoeyBuYW1lOiAndGVzdGFwcC12aWV3JywgdXVpZDogJ3Rlc3RhcHAnIH0pO1xuICAgICAqICAgICBhd2FpdCB2aWV3Lm5hdmlnYXRlKCdodHRwczovL3d3dy5nb29nbGUuY29tJyk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCB2aWV3LnN0b3BOYXZpZ2F0aW9uKCk7XG4gICAgICogfVxuICAgICAqIHN0b3BOYXZpZ2F0aW9uKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygneW91IHNoYWxsIG5vdCBuYXZpZ2F0ZScpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBzdG9wTmF2aWdhdGlvbigpIHtcbiAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy53cmFwKHsgbmFtZTogJ3Rlc3RhcHAnLCB1dWlkOiAndGVzdGFwcCcgfSk7XG4gICAgICogICAgIGF3YWl0IHdpbi5uYXZpZ2F0ZSgnaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbScpO1xuICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLnN0b3BOYXZpZ2F0aW9uKCk7XG4gICAgICogfVxuICAgICAqIHN0b3BOYXZpZ2F0aW9uKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygneW91IHNoYWxsIG5vdCBuYXZpZ2F0ZScpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIHN0b3BOYXZpZ2F0aW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3N0b3Atd2luZG93LW5hdmlnYXRpb24nLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWxvYWRzIHRoZSBXZWJDb250ZW50c1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gcmVsb2FkKCkge1xuICAgICAqIFx0Y29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHZpZXcucmVsb2FkKCk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogcmVsb2FkKCkudGhlbigoKSA9PiB7XG4gICAgICogXHRcdGNvbnNvbGUubG9nKCdSZWxvYWRlZCB2aWV3JylcbiAgICAgKiB9KS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiByZWxvYWRXaW5kb3coKSB7XG4gICAgICogXHRcdGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG4gICAgICogXHRcdFx0XHRuYW1lOiAnbXlBcHAnLFxuICAgICAqIFx0XHRcdFx0dXVpZDogJ2FwcC0xJyxcbiAgICAgKiBcdFx0XHRcdHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cucmVsb2FkLmh0bWwnLFxuICAgICAqIFx0XHRcdFx0YXV0b1Nob3c6IHRydWVcbiAgICAgKiBcdFx0fSk7XG4gICAgICogXHRcdGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5yZWxvYWQoKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiByZWxvYWRXaW5kb3coKS50aGVuKCgpID0+IHtcbiAgICAgKiBcdFx0Y29uc29sZS5sb2coJ1JlbG9hZGVkIHdpbmRvdycpXG4gICAgICogfSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICByZWxvYWQoaWdub3JlQ2FjaGUgPSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlXG4gICAgICAgICAgICAuc2VuZEFjdGlvbigncmVsb2FkLXdpbmRvdycsIHtcbiAgICAgICAgICAgIGlnbm9yZUNhY2hlLFxuICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUHJpbnRzIHRoZSBXZWJDb250ZW50cy5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBQcmludGVyIE9wdGlvbnNcbiAgICAgKlxuICAgICAqIE5vdGU6IFdoZW4gYHNpbGVudGAgaXMgc2V0IHRvIGB0cnVlYCwgdGhlIEFQSSB3aWxsIHBpY2sgdGhlIHN5c3RlbSdzIGRlZmF1bHQgcHJpbnRlciBpZiBkZXZpY2VOYW1lXG4gICAgICogaXMgZW1wdHkgYW5kIHRoZSBkZWZhdWx0IHNldHRpbmdzIGZvciBwcmludGluZy5cbiAgICAgKlxuICAgICAqIFVzZSB0aGUgQ1NTIHN0eWxlIGBwYWdlLWJyZWFrLWJlZm9yZTogYWx3YXlzO2AgdG8gZm9yY2UgcHJpbnQgdG8gYSBuZXcgcGFnZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCB2aWV3ID0gZmluLlZpZXcuZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKlxuICAgICAqIHZpZXcucHJpbnQoeyBzaWxlbnQ6IGZhbHNlLCBkZXZpY2VOYW1lOiAnc3lzdGVtLXByaW50ZXItbmFtZScgfSkudGhlbigoKSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdwcmludCBjYWxsIGhhcyBiZWVuIHNlbnQgdG8gdGhlIHN5c3RlbScpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBwcmludChvcHRpb25zID0ge30pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwcmludCcsIHsgLi4udGhpcy5pZGVudGl0eSwgb3B0aW9ucyB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEZpbmQgYW5kIGhpZ2hsaWdodCB0ZXh0IG9uIGEgcGFnZS5cbiAgICAgKiBAcGFyYW0gc2VhcmNoVGVybSBUZXJtIHRvIGZpbmQgaW4gcGFnZVxuICAgICAqIEBwYXJhbSBvcHRpb25zIFNlYXJjaCBvcHRpb25zXG4gICAgICpcbiAgICAgKiBOb3RlOiBCeSBkZWZhdWx0LCBlYWNoIHN1YnNlcXVlbnQgY2FsbCB3aWxsIGhpZ2hsaWdodCB0aGUgbmV4dCB0ZXh0IHRoYXQgbWF0Y2hlcyB0aGUgc2VhcmNoIHRlcm0uXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIGEgcHJvbWlzZSB3aXRoIHRoZSByZXN1bHRzIGZvciB0aGUgcmVxdWVzdC4gQnkgc3Vic2NyaWJpbmcgdG8gdGhlXG4gICAgICogZm91bmQtaW4tcGFnZSBldmVudCwgeW91IGNhbiBnZXQgdGhlIHJlc3VsdHMgb2YgdGhpcyBjYWxsIGFzIHdlbGwuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCB2aWV3ID0gZmluLlZpZXcuZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKlxuICAgICAqIC8vQnkgc3Vic2NyaWJpbmcgdG8gdGhlICdmb3VuZCBpbiBwYWdlJyBldmVudCB3ZSBjYW4gZ2V0IHRoZSByZXN1bHRzIG9mIGVhY2ggZmluZEluUGFnZSBjYWxsIG1hZGUuXG4gICAgICogdmlldy5hZGRMaXN0ZW5lcignZm91bmQtaW4tcGFnZScsIChldmVudCkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhldmVudCk7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiAvLyBUaGUgcHJvbWlzZSBhbHNvIHJldHVybnMgdGhlIHJlc3VsdHMgZm9yIHRoZSByZXF1ZXN0XG4gICAgICogdmlldy5maW5kSW5QYWdlKCdhJykudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKHJlc3VsdClcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFdpbmRvdzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHdpbiA9IGZpbi5XaW5kb3cuZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKlxuICAgICAqIC8vQnkgc3Vic2NyaWJpbmcgdG8gdGhlICdmb3VuZCBpbiBwYWdlJyBldmVudCB3ZSBjYW4gZ2V0IHRoZSByZXN1bHRzIG9mIGVhY2ggZmluZEluUGFnZSBjYWxsIG1hZGUuXG4gICAgICogd2luLmFkZExpc3RlbmVyKCdmb3VuZC1pbi1wYWdlJywgKGV2ZW50KSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKGV2ZW50KTtcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIC8vIFRoZSBwcm9taXNlIGFsc28gcmV0dXJucyB0aGUgcmVzdWx0cyBmb3IgdGhlIHJlcXVlc3RcbiAgICAgKiB3aW4uZmluZEluUGFnZSgnYScpLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhyZXN1bHQpXG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIGZpbmRJblBhZ2Uoc2VhcmNoVGVybSwgb3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlXG4gICAgICAgICAgICAuc2VuZEFjdGlvbignZmluZC1pbi1wYWdlJywgeyAuLi50aGlzLmlkZW50aXR5LCBzZWFyY2hUZXJtLCBvcHRpb25zIH0pXG4gICAgICAgICAgICAudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN0b3AgYSB7QGxpbmsgVmlldyNmaW5kSW5QYWdlIGZpbmRJblBhZ2V9IGNhbGwgYnkgc3BlY2lmeWluZyBhbnkgb2YgdGhlc2UgYWN0aW9uczpcbiAgICAgKlxuICAgICAqICogY2xlYXJTZWxlY3Rpb24gLSBDbGVhciB0aGUgc2VsZWN0aW9uLlxuICAgICAqICoga2VlcFNlbGVjdGlvbiAtIFRyYW5zbGF0ZSB0aGUgc2VsZWN0aW9uIGludG8gYSBub3JtYWwgc2VsZWN0aW9uLlxuICAgICAqICogYWN0aXZhdGVTZWxlY3Rpb24gLSBGb2N1cyBhbmQgY2xpY2sgdGhlIHNlbGVjdGlvbiBub2RlLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgdmlldyA9IGZpbi5WaWV3LmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICpcbiAgICAgKiB2aWV3LmFkZExpc3RlbmVyKCdmb3VuZC1pbi1wYWdlJywgKGV2ZW50KSA9PiB7XG4gICAgICogICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAqICAgICAgICAgdmlldy5zdG9wRmluZEluUGFnZSgnY2xlYXJTZWxlY3Rpb24nKTtcbiAgICAgKiAgICAgfSwgNTAwMCk7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiB2aWV3LmZpbmRJblBhZ2UoJ2EnKS50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhyZXN1bHRzKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFdpbmRvdzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHdpbiA9IGZpbi5XaW5kb3cuZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKlxuICAgICAqIHdpbi5hZGRMaXN0ZW5lcignZm91bmQtaW4tcGFnZScsIChldmVudCkgPT4ge1xuICAgICAqICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgKiAgICAgICAgIHdpbi5zdG9wRmluZEluUGFnZSgnY2xlYXJTZWxlY3Rpb24nKTtcbiAgICAgKiAgICAgfSwgNTAwMCk7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiB3aW4uZmluZEluUGFnZSgnYScpLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKHJlc3VsdHMpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBzdG9wRmluZEluUGFnZShhY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzdG9wLWZpbmQtaW4tcGFnZScsIHsgLi4udGhpcy5pZGVudGl0eSwgYWN0aW9uIH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBhcnJheSB3aXRoIGFsbCBzeXN0ZW0gcHJpbnRlcnNcbiAgICAgKiBAZGVwcmVjYXRlZCB1c2UgU3lzdGVtLmdldFByaW50ZXJzIGluc3RlYWRcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHZpZXcgPSBmaW4uVmlldy5nZXRDdXJyZW50U3luYygpO1xuICAgICAqXG4gICAgICogdmlldy5nZXRQcmludGVycygpXG4gICAgICogICAgIC50aGVuKChwcmludGVycykgPT4ge1xuICAgICAqICAgICAgICAgcHJpbnRlcnMuZm9yRWFjaCgocHJpbnRlcikgPT4ge1xuICAgICAqICAgICAgICAgICAgIGlmIChwcmludGVyLmlzRGVmYXVsdCkge1xuICAgICAqICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhwcmludGVyKTtcbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICB9KTtcbiAgICAgKiAgICAgfSlcbiAgICAgKiAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKGVycik7XG4gICAgICogICAgIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3Qgd2luID0gZmluLldpbmRvdy5nZXRDdXJyZW50U3luYygpO1xuICAgICAqXG4gICAgICogd2luLmdldFByaW50ZXJzKClcbiAgICAgKiAgICAgLnRoZW4oKHByaW50ZXJzKSA9PiB7XG4gICAgICogICAgICAgICBwcmludGVycy5mb3JFYWNoKChwcmludGVyKSA9PiB7XG4gICAgICogICAgICAgICAgICAgaWYgKHByaW50ZXIuaXNEZWZhdWx0KSB7XG4gICAgICogICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHByaW50ZXIpO1xuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgIH0pO1xuICAgICAqICAgICB9KVxuICAgICAqICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coZXJyKTtcbiAgICAgKiAgICAgfSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIGdldFByaW50ZXJzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1wcmludGVycycsIHsgLi4udGhpcy5pZGVudGl0eSB9KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2l2ZXMgZm9jdXMgdG8gdGhlIFdlYkNvbnRlbnRzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIGZvY3VzV2luZG93KCkge1xuICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcbiAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG4gICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmZvY3VzLmh0bWwnLFxuICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcbiAgICAgKiAgICAgfSk7XG4gICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5mb2N1cygpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGZvY3VzV2luZG93KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnV2luZG93IGZvY3VzZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBhc3luYyBmb2N1cyh7IGVtaXRTeW50aEZvY3VzZWQgfSA9IHsgZW1pdFN5bnRoRm9jdXNlZDogdHJ1ZSB9KSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmb2N1cy13aW5kb3cnLCB7IGVtaXRTeW50aEZvY3VzZWQsIC4uLnRoaXMuaWRlbnRpdHkgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNob3dzIHRoZSBDaHJvbWl1bSBEZXZlbG9wZXIgVG9vbHNcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNob3dEZXZlbG9wZXJUb29scygpIHtcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgcmV0dXJuIHZpZXcuc2hvd0RldmVsb3BlclRvb2xzKCk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogc2hvd0RldmVsb3BlcnRvb2xzKClcbiAgICAgKiAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU2hvd2luZyBkZXYgdG9vbHMnKSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUuZXJyb3IoZXJyKSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBXaW5kb3c6XG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBzaG93RGV2ZWxvcGVyVG9vbHMoKSB7XG4gICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuICAgICAqICAgICByZXR1cm4gd2luLnNob3dEZXZlbG9wZXJUb29scygpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIHNob3dEZXZlbG9wZXJ0b29scygpXG4gICAgICogLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1Nob3dpbmcgZGV2IHRvb2xzJykpXG4gICAgICogLmNhdGNoKGVyciA9PiBjb25zb2xlLmVycm9yKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBhc3luYyBzaG93RGV2ZWxvcGVyVG9vbHMoKSB7XG4gICAgICAgIC8vIE5vdGUgdGhpcyBoaXRzIHRoZSBzeXN0ZW0gYWN0aW9uIG1hcCBpbiBjb3JlIHN0YXRlIGZvciBsZWdhY3kgcmVhc29ucy5cbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Nob3ctZGV2ZWxvcGVyLXRvb2xzJywgdGhpcy5pZGVudGl0eSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgcHJvY2VzcyBpbmZvcm1hdGlvbiBhc3NvY2lhdGVkIHdpdGggYSBXZWJDb250ZW50cy5cbiAgICAgKlxuICAgICAqIE5vdGU6IFRoaXMgaW5jbHVkZXMgYW55IGlmcmFtZXMgYXNzb2NpYXRlZCB3aXRoIHRoZSBXZWJDb250ZW50c1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBWaWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogICAgIGNvbnN0IHZpZXcgPSBhd2FpdCBmaW4uVmlldy5nZXRDdXJyZW50KCk7XG4gICAgICogICAgIGNvbnN0IHByb2Nlc3NJbmZvID0gYXdhaXQgdmlldy5nZXRQcm9jZXNzSW5mbygpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuICAgICAqICAgICBjb25zdCBwcm9jZXNzSW5mbyA9IGF3YWl0IHdpbi5nZXRQcm9jZXNzSW5mbygpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBhc3luYyBnZXRQcm9jZXNzSW5mbygpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkOiB7IGRhdGEgfSB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1wcm9jZXNzLWluZm8nLCB0aGlzLmlkZW50aXR5KTtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBpbmZvcm1hdGlvbiBvbiBhbGwgU2hhcmVkIFdvcmtlcnMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmNyZWF0ZSh7XG4gICAgICogICAgICAgICBuYW1lOiAndmlld05hbWUnLFxuICAgICAqICAgICAgICAgdGFyZ2V0OiBmaW4ubWUuaWRlbnRpdHksXG4gICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHZpZXcubmF2aWdhdGUoJ2h0dHBzOi8vbWRuLmdpdGh1Yi5pby9kb20tZXhhbXBsZXMvd2ViLXdvcmtlcnMvc2ltcGxlLXNoYXJlZC13b3JrZXIvJyk7XG4gICAgICpcbiAgICAgKiAgICAgY29uc3Qgc2hhcmVkV29ya2VycyA9IGF3YWl0IHZpZXcuZ2V0U2hhcmVkV29ya2VycygpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogICAgIGNvbnN0IHdpbk9wdGlvbiA9IHtcbiAgICAgKiAgICAgICAgIG5hbWU6J2NoaWxkJyxcbiAgICAgKiAgICAgICAgIGRlZmF1bHRXaWR0aDogMzAwLFxuICAgICAqICAgICAgICAgZGVmYXVsdEhlaWdodDogMzAwLFxuICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9tZG4uZ2l0aHViLmlvL2RvbS1leGFtcGxlcy93ZWItd29ya2Vycy9zaW1wbGUtc2hhcmVkLXdvcmtlci8nLFxuICAgICAqICAgICAgICAgZnJhbWU6IHRydWUsXG4gICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuICAgICAqICAgICB9O1xuICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBmaW4uV2luZG93LmNyZWF0ZSh3aW5PcHRpb24pO1xuICAgICAqICAgICBjb25zdCBzaGFyZWRXb3JrZXJzID0gYXdhaXQgd2luLmdldFNoYXJlZFdvcmtlcnMoKTtcbiAgICAgKiBgYGBcbiAgICAgKiBAcmVtYXJrc1xuICAgICAqIGBXZWJDb250ZW50c2AgcmVmZXJzIHRvIHNoYXJlZCBmdW5jdGlvbmFsaXR5IGJldHdlZW4ge0BsaW5rIE9wZW5GaW4uV2luZG93fSBhbmQge0BsaW5rIE9wZW5GaW4uVmlld30uXG4gICAgICogV2UgZG8gbm90IGV4cG9zZSBhbiBleHBsaWNpdCBzdXBlcmNsYXNzIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHksIGJ1dCBpdCBkb2VzIGhhdmUgaXRzIG93blxuICAgICAqIHtAbGluayBPcGVuRmluLldlYkNvbnRlbnRzRXZlbnRzIGV2ZW50IG5hbWVzcGFjZX0uXG4gICAgICovXG4gICAgYXN5bmMgZ2V0U2hhcmVkV29ya2VycygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtc2hhcmVkLXdvcmtlcnMnLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogT3BlbnMgdGhlIGRldmVsb3BlciB0b29scyBmb3IgdGhlIHNoYXJlZCB3b3JrZXIgY29udGV4dC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogVmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcuY3JlYXRlKHtcbiAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZScsXG4gICAgICogICAgICAgICB0YXJnZXQ6IGZpbi5tZS5pZGVudGl0eSxcbiAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cbiAgICAgKiAgICAgfSk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9tZG4uZ2l0aHViLmlvL2RvbS1leGFtcGxlcy93ZWItd29ya2Vycy9zaW1wbGUtc2hhcmVkLXdvcmtlci8nKTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCB2aWV3Lmluc3BlY3RTaGFyZWRXb3JrZXIoKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEV4YW1wbGU6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgY29uc3Qgd2luT3B0aW9uID0ge1xuICAgICAqICAgICAgICAgbmFtZTonY2hpbGQnLFxuICAgICAqICAgICAgICAgZGVmYXVsdFdpZHRoOiAzMDAsXG4gICAgICogICAgICAgICBkZWZhdWx0SGVpZ2h0OiAzMDAsXG4gICAgICogICAgICAgICB1cmw6ICdodHRwczovL21kbi5naXRodWIuaW8vZG9tLWV4YW1wbGVzL3dlYi13b3JrZXJzL3NpbXBsZS1zaGFyZWQtd29ya2VyLycsXG4gICAgICogICAgICAgICBmcmFtZTogdHJ1ZSxcbiAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG4gICAgICogICAgIH07XG4gICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuY3JlYXRlKHdpbk9wdGlvbik7XG4gICAgICogICAgIGF3YWl0IHdpbi5pbnNwZWN0U2hhcmVkV29ya2VyKCk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIGFzeW5jIGluc3BlY3RTaGFyZWRXb3JrZXIoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnNwZWN0LXNoYXJlZC13b3JrZXInLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEluc3BlY3RzIHRoZSBzaGFyZWQgd29ya2VyIGJhc2VkIG9uIGl0cyBJRC5cbiAgICAgKiBAcGFyYW0gd29ya2VySWQgLSBUaGUgaWQgb2YgdGhlIHNoYXJlZCB3b3JrZXIuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmNyZWF0ZSh7XG4gICAgICogICAgICAgICBuYW1lOiAndmlld05hbWUnLFxuICAgICAqICAgICAgICAgdGFyZ2V0OiBmaW4ubWUuaWRlbnRpdHksXG4gICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHZpZXcubmF2aWdhdGUoJ2h0dHBzOi8vbWRuLmdpdGh1Yi5pby9kb20tZXhhbXBsZXMvd2ViLXdvcmtlcnMvc2ltcGxlLXNoYXJlZC13b3JrZXIvJyk7XG4gICAgICpcbiAgICAgKiAgICAgY29uc3Qgc2hhcmVkV29ya2VycyA9IGF3YWl0IHZpZXcuZ2V0U2hhcmVkV29ya2VycygpO1xuICAgICAqICAgICBhd2FpdCB2aWV3Lmluc3BlY3RTaGFyZWRXb3JrZXJCeUlkKHNoYXJlZFdvcmtlcnNbMF0uaWQpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogV2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogICAgIGNvbnN0IHdpbk9wdGlvbiA9IHtcbiAgICAgKiAgICAgICAgIG5hbWU6J2NoaWxkJyxcbiAgICAgKiAgICAgICAgIGRlZmF1bHRXaWR0aDogMzAwLFxuICAgICAqICAgICAgICAgZGVmYXVsdEhlaWdodDogMzAwLFxuICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9tZG4uZ2l0aHViLmlvL2RvbS1leGFtcGxlcy93ZWItd29ya2Vycy9zaW1wbGUtc2hhcmVkLXdvcmtlci8nLFxuICAgICAqICAgICAgICAgZnJhbWU6IHRydWUsXG4gICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuICAgICAqICAgICB9O1xuICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBmaW4uV2luZG93LmNyZWF0ZSh3aW5PcHRpb24pO1xuICAgICAqICAgICBjb25zdCBzaGFyZWRXb3JrZXJzID0gYXdhaXQgd2luLmdldFNoYXJlZFdvcmtlcnMoKTtcbiAgICAgKiAgICAgYXdhaXQgd2luLmluc3BlY3RTaGFyZWRXb3JrZXJCeUlkKHNoYXJlZFdvcmtlcnNbMF0uaWQpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBhc3luYyBpbnNwZWN0U2hhcmVkV29ya2VyQnlJZCh3b3JrZXJJZCkge1xuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignaW5zcGVjdC1zaGFyZWQtd29ya2VyLWJ5LWlkJywgeyAuLi50aGlzLmlkZW50aXR5LCB3b3JrZXJJZCB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogT3BlbnMgdGhlIGRldmVsb3BlciB0b29scyBmb3IgdGhlIHNlcnZpY2Ugd29ya2VyIGNvbnRleHQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFZpZXc6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmNyZWF0ZSh7XG4gICAgICogICAgICAgICBuYW1lOiAndmlld05hbWUnLFxuICAgICAqICAgICAgICAgdGFyZ2V0OiBmaW4ubWUuaWRlbnRpdHksXG4gICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG4gICAgICogICAgIH0pO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHZpZXcubmF2aWdhdGUoJ2h0dHA6Ly9nb29nbGVjaHJvbWUuZ2l0aHViLmlvL3NhbXBsZXMvc2VydmljZS13b3JrZXIvYmFzaWMvaW5kZXguaHRtbCcpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHZpZXcuaW5zcGVjdFNlcnZpY2VXb3JrZXIoKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFdpbmRvdzpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBjb25zdCB3aW5PcHRpb24gPSB7XG4gICAgICogICAgICAgICBuYW1lOidjaGlsZCcsXG4gICAgICogICAgICAgICBkZWZhdWx0V2lkdGg6IDMwMCxcbiAgICAgKiAgICAgICAgIGRlZmF1bHRIZWlnaHQ6IDMwMCxcbiAgICAgKiAgICAgICAgIHVybDogJ2h0dHA6Ly9nb29nbGVjaHJvbWUuZ2l0aHViLmlvL3NhbXBsZXMvc2VydmljZS13b3JrZXIvYmFzaWMvaW5kZXguaHRtbCcsXG4gICAgICogICAgICAgICBmcmFtZTogdHJ1ZSxcbiAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG4gICAgICogICAgIH07XG4gICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuY3JlYXRlKHdpbk9wdGlvbik7XG4gICAgICogICAgIGF3YWl0IHdpbi5pbnNwZWN0U2VydmljZVdvcmtlcigpO1xuICAgICAqIGBgYFxuICAgICAqIEByZW1hcmtzXG4gICAgICogYFdlYkNvbnRlbnRzYCByZWZlcnMgdG8gc2hhcmVkIGZ1bmN0aW9uYWxpdHkgYmV0d2VlbiB7QGxpbmsgT3BlbkZpbi5XaW5kb3d9IGFuZCB7QGxpbmsgT3BlbkZpbi5WaWV3fS5cbiAgICAgKiBXZSBkbyBub3QgZXhwb3NlIGFuIGV4cGxpY2l0IHN1cGVyY2xhc3MgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSwgYnV0IGl0IGRvZXMgaGF2ZSBpdHMgb3duXG4gICAgICoge0BsaW5rIE9wZW5GaW4uV2ViQ29udGVudHNFdmVudHMgZXZlbnQgbmFtZXNwYWNlfS5cbiAgICAgKi9cbiAgICBhc3luYyBpbnNwZWN0U2VydmljZVdvcmtlcigpIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2luc3BlY3Qtc2VydmljZS13b3JrZXInLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNob3dzIGEgcG9wdXAgd2luZG93LlxuICAgICAqXG4gICAgICogTm90ZTogSWYgdGhpcyBXZWJDb250ZW50cyBpcyBhIHZpZXcgYW5kIGl0cyBhdHRhY2hlZCB3aW5kb3cgaGFzIGEgcG9wdXAgb3BlbiwgdGhpcyB3aWxsIGNsb3NlIGl0LlxuICAgICAqXG4gICAgICogU2hvd3MgYSBwb3B1cCB3aW5kb3cuIEluY2x1ZGluZyBhIGBuYW1lYCBpbiBgb3B0aW9uc2Agd2lsbCBhdHRlbXB0IHRvIHNob3cgYW4gZXhpc3Rpbmcgd2luZG93IGFzIGEgcG9wdXAsIGlmXG4gICAgICogdGhhdCB3aW5kb3cgZG9lc24ndCBleGlzdCBvciBubyBgbmFtZWAgaXMgaW5jbHVkZWQgYSB3aW5kb3cgd2lsbCBiZSBjcmVhdGVkLiBJZiB0aGUgY2FsbGVyIHZpZXcgb3IgdGhlIGNhbGxlclxuICAgICAqIHZpZXcncyBwYXJlbnQgd2luZG93IGN1cnJlbnRseSBoYXMgYSBwb3B1cCB3aW5kb3cgb3BlbiwgY2FsbGluZyBgc2hvd1BvcHVwV2luZG93YCBhZ2FpbiB3aWxsIGRpc21pc3MgdGhlIGN1cnJlbnRseVxuICAgICAqIG9wZW4gcG9wdXAgd2luZG93IGJlZm9yZSBzaG93aW5nIHRoZSBuZXcgcG9wdXAgd2luZG93LiBBbHNvLCBpZiB0aGUgY2FsbGVyIHZpZXcgaXMgZGVzdHJveWVkIG9yIGRldGFjaGVkLCB0aGUgcG9wdXBcbiAgICAgKiB3aWxsIGJlIGRpc21pc3NlZC5cbiAgICAgKlxuICAgICAqIE5vdGU6IGluIHRoZSBjYXNlIHdoZXJlIHRoZSB3aW5kb3cgYmVpbmcgc2hvd24gYXMgYSBwb3B1cCBuZWVkcyB0byBiZSBjcmVhdGVkLCBpdCBpcyBhIGNoaWxkIG9mIHRoZSBjYWxsZXIgdmlldydzIHBhcmVudCB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogQ3JlYXRlIGFuZCBzaG93IGEgc2luZ2xlLXVzZSBwb3B1cCB3aW5kb3cgdGhhdCByZXR1cm5zIGEgc2luZ2xlIHJlc3VsdCB0byB0aGUgY2FsbGVyLiBgaW5pdGlhbE9wdGlvbnNgIGFsbG93c1xuICAgICAqIHVzIHRvIHBhc3Mgd2luZG93IG9wdGlvbnMgdG8gdGhlIHBvcHVwIHdpbmRvdyB0aGF0IHdpbGwgYmUgY3JlYXRlZC4gYHJlc3VsdERpc3BhdGNoQmVoYXZpb3I6ICdjbG9zZSdgIGVuc3VyZXNcbiAgICAgKiB0aGF0IG9uY2UgdGhlIHBvcHVwIHdpbmRvdyBjYWxscyBgZGlzcGF0Y2hQb3B1cFJlc3VsdGAgaXQgaXMgY2xvc2VkLiBgYmx1ckJlaGF2aW9yOiAnY2xvc2UnYCB3aWxsIHlpZWxkIGEgZGlzbWlzc2VkXG4gICAgICogcmVzdWx0IHNob3VsZCB0aGUgcG9wdXAgd2luZG93IGxvc2UgZm9jdXMuXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbi5tZS5zaG93UG9wdXBXaW5kb3coe1xuICAgICAqICAgICBpbml0aWFsT3B0aW9uczoge1xuICAgICAqICAgICAgICAgZnJhbWU6IGZhbHNlXG4gICAgICogICAgIH0sXG4gICAgICogICAgIHVybDogJzxteV9wb3B1cF91cmw+JyxcbiAgICAgKiAgICAgcmVzdWx0RGlzcGF0Y2hCZWhhdmlvcjogJ2Nsb3NlJyxcbiAgICAgKiAgICAgYmx1ckJlaGF2aW9yOiAnY2xvc2UnLFxuICAgICAqICAgICBmb2N1czogdHJ1ZSxcbiAgICAgKiAgICAgaGVpZ2h0OiAzMDAsXG4gICAgICogICAgIHdpZHRoOiAzMDAsXG4gICAgICogICAgIHg6IDAsXG4gICAgICogICAgIHk6IDBcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFNhbWUgYXMgYWJvdmUgYnV0IHVzaW5nIGFuIGV4aXN0aW5nIHdpbmRvdyBhcyBhIHBvcHVwIGJ5IHJlZmVyZW5jaW5nIGl0cyBgbmFtZWA6XG4gICAgICpcbiAgICAgKiBOb3RlOiBpZiBhIHdpbmRvdyB3aXRoIHRoZSBgbmFtZWAgcHJvdmlkZWQgZG9lc24ndCBleGlzdCwgaXQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCByZXN1bHQgPSBhd2FpdCBmaW4ubWUuc2hvd1BvcHVwV2luZG93KHtcbiAgICAgKiAgICAgaW5pdGlhbE9wdGlvbnM6IHtcbiAgICAgKiAgICAgICAgIGZyYW1lOiB0cnVlXG4gICAgICogICAgIH0sXG4gICAgICogICAgIG5hbWU6ICdteS1wb3B1cCcsIC8vIHNob3dzIHRoZSAnbXktcG9wdXAnIHdpbmRvdyBpZiBpdCBleGlzdHMsIG90aGVyd2lzZSBjcmVhdGVzIGl0XG4gICAgICogICAgIHVybDogJzxteV9wb3B1cF91cmw+JywgLy8gbmF2aWdhdGVzIHRvIHRoaXMgdXJsIGlmIGl0IGRvZXNuJ3QgbWF0Y2ggdGhlIGxvY2F0aW9uLmhyZWYgb2YgdGhlICdteS1wb3B1cCcgd2luZG93XG4gICAgICogICAgIHJlc3VsdERpc3BhdGNoQmVoYXZpb3I6ICdjbG9zZScsXG4gICAgICogICAgIGJsdXJCZWhhdmlvcjogJ2Nsb3NlJyxcbiAgICAgKiAgICAgZm9jdXM6IHRydWUsXG4gICAgICogICAgIGhpZGVPbkNsb3NlOiB0cnVlLCAvLyBwZXJzaXN0IHdpbmRvdyBvbiAnZGlzbWlzc2VkJyByZXN1bHQsIGFsdGVybmF0aXZlbHkgY2hhbmdlIG9uUmVzdWx0RGlzcGF0Y2ggYW5kIGJsdXJCZWhhdmlvciB0byAnaGlkZSdcbiAgICAgKiAgICAgaGVpZ2h0OiAzMDAsXG4gICAgICogICAgIHdpZHRoOiAzMDAsXG4gICAgICogICAgIHg6IDAsXG4gICAgICogICAgIHk6IDBcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIENyZWF0ZSBhbmQgc2hvdyBhIHBvcHVwIHdpbmRvdyB0aGF0IGlzIGFibGUgdG8gcmV0dXJuIG11bHRpcGxlIHJlc3VsdHMgdG8gdGhlIGNhbGxlciB2aWEgYW4gYG9uUG9wdXBSZXN1bHRgIGNhbGxiYWNrLiBFYWNoXG4gICAgICogdGltZSB0aGUgcG9wdXAgd2luZG93IGNhbGxzIGBkaXNwYXRjaFBvcHVwUmVzdWx0YCwgdGhlIGNhbGxiYWNrIHdpbGwgYmUgZXhlY3V0ZWQgb24gdGhlIHJlc3VsdC4gT25jZSB0aGUgcG9wdXAgd2luZG93IGlzXG4gICAgICogY2xvc2VkIG9yIGhpZGRlbiwgdGhlIGBzaG93UG9wdXBXaW5kb3dgIHByb21pc2Ugd2lsbCByZXNvbHZlIHdpdGggYSBgZGlzbWlzc2VkYCByZXN1bHQgdGhhdCB3aWxsIGluY2x1ZGUgdGhlIG1vc3QgcmVjZW50bHlcbiAgICAgKiBkaXNwYXRjaGVkIHJlc3VsdCBhcyBgbGFzdERpc3BhdGNoUmVzdWx0YDpcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcG9wdXBSZXN1bHRDYWxsYmFjayA9IChwYXlsb2FkKSA9PiB7XG4gICAgICogICAgICAgIGlmIChwYXlsb2FkLnJlc3VsdCA9PT0gJ2NsaWNrZWQnKSB7XG4gICAgICogICAgICAgICAgICBpZiAocGF5bG9hZC5kYXRhLnRvcGljID09PSAnY29sb3ItY2hhbmdlZCcpIHtcbiAgICAgKiAgICAgICAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgbGlrZVxuICAgICAqICAgICAgICAgICAgICAgIC8vIHNldENvbG9yKHBheWxvYWQuZGF0YS52YWx1ZSk7XG4gICAgICogICAgICAgICAgICB9XG4gICAgICogICAgICAgIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogYXdhaXQgZmluLm1lLnNob3dQb3B1cFdpbmRvdyh7XG4gICAgICogICAgIGluaXRpYWxPcHRpb25zOiB7XG4gICAgICogICAgICAgICBmcmFtZTogZmFsc2VcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgdXJsOiAnPG15X3BvcHVwX3VybD4nLFxuICAgICAqICAgICByZXN1bHREaXNwYXRjaEJlaGF2aW9yOiAnbm9uZScsXG4gICAgICogICAgIGJsdXJCZWhhdmlvcjogJ2Nsb3NlJyxcbiAgICAgKiAgICAgZm9jdXM6IHRydWUsXG4gICAgICogICAgIGhlaWdodDogMzAwLFxuICAgICAqICAgICB3aWR0aDogMzAwLFxuICAgICAqICAgICB4OiAwLFxuICAgICAqICAgICB5OiAwLFxuICAgICAqICAgICBvblBvcHVwUmVzdWx0OiBwb3B1cFJlc3VsdENhbGxiYWNrXG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBTYW1lIGFzIGFib3ZlIGJ1dCB1c2luZyBhbiBleGlzdGluZyB3aW5kb3cgYXMgYSBwb3B1cDpcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcG9wdXBSZXN1bHRDYWxsYmFjayA9IChwYXlsb2FkKSA9PiB7XG4gICAgICogICAgICAgIGlmIChwYXlsb2FkLnJlc3VsdCA9PT0gJ2NsaWNrZWQnKSB7XG4gICAgICogICAgICAgICAgICBpZiAocGF5bG9hZC5kYXRhLnRvcGljID09PSAnY29sb3ItY2hhbmdlZCcpIHtcbiAgICAgKiAgICAgICAgICAgICAgICAvLyBkbyBzb21ldGhpbmcgbGlrZVxuICAgICAqICAgICAgICAgICAgICAgIC8vIHNldENvbG9yKHBheWxvYWQuZGF0YS52YWx1ZSk7XG4gICAgICogICAgICAgICAgICB9XG4gICAgICogICAgICAgIH1cbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogYXdhaXQgZmluLm1lLnNob3dQb3B1cFdpbmRvdyh7XG4gICAgICogICAgIGluaXRpYWxPcHRpb25zOiB7XG4gICAgICogICAgICAgICBmcmFtZTogZmFsc2VcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgbmFtZTogJ215LXBvcHVwJywgLy8gc2hvd3MgdGhlICdteS1wb3B1cCcgd2luZG93IGlmIGl0IGV4aXN0cywgb3RoZXJ3aXNlIGNyZWF0ZXMgaXRcbiAgICAgKiAgICAgdXJsOiAnPG15X3BvcHVwX3VybD4nLCAvLyBuYXZpZ2F0ZXMgdG8gdGhpcyB1cmwgaWYgaXQgZG9lc24ndCBtYXRjaCB0aGUgbG9jYXRpb24uaHJlZiBvZiB0aGUgJ215LXBvcHVwJyB3aW5kb3dcbiAgICAgKiAgICAgcmVzdWx0RGlzcGF0Y2hCZWhhdmlvcjogJ25vbmUnLFxuICAgICAqICAgICBibHVyQmVoYXZpb3I6ICdoaWRlJyxcbiAgICAgKiAgICAgZm9jdXM6IHRydWUsXG4gICAgICogICAgIGhpZGVPbkNsb3NlOiB0cnVlLCAvLyB3ZSBjYW4ganVzdCB1c2UgdGhpcyBvciB3ZSBjYW4gY2hhbmdlIGJsdXJCZWhhdmlvciB0byAnaGlkZSdcbiAgICAgKiAgICAgaGVpZ2h0OiAzMDAsXG4gICAgICogICAgIHdpZHRoOiAzMDAsXG4gICAgICogICAgIHg6IDAsXG4gICAgICogICAgIHk6IDAsXG4gICAgICogICAgIG9uUG9wdXBSZXN1bHQ6IHBvcHVwUmVzdWx0Q2FsbGJhY2tcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIENyZWF0ZSBvciBzaG93IGEgcG9wdXAgd2luZG93IHRoYXQgZGlzYWJsZXMgdXNlciBtb3ZlbWVudCAocG9zaXRpb25pbmcgYW5kIHJlc2l6aW5nKSBpbiB0aGUgY2FsbGVyXG4gICAgICogdmlldydzIHBhcmVudCB3aW5kb3cgYnkgdXNpbmcgYGJsdXJCZWhhdmlvcjogJ21vZGFsJ2A6XG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbi5tZS5zaG93UG9wdXBXaW5kb3coe1xuICAgICAqICAgICBpbml0aWFsT3B0aW9uczoge1xuICAgICAqICAgICAgICAgZnJhbWU6IGZhbHNlXG4gICAgICogICAgIH0sXG4gICAgICogICAgIHVybDogJzxteV9wb3B1cF91cmw+JyxcbiAgICAgKiAgICAgcmVzdWx0RGlzcGF0Y2hCZWhhdmlvcjogJ2Nsb3NlJyxcbiAgICAgKiAgICAgYmx1ckJlaGF2aW9yOiAnbW9kYWwnLFxuICAgICAqICAgICBmb2N1czogdHJ1ZSxcbiAgICAgKiAgICAgaGVpZ2h0OiAzMDAsXG4gICAgICogICAgIHdpZHRoOiAzMDAsXG4gICAgICogICAgIHg6IDAsXG4gICAgICogICAgIHk6IDBcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIENyZWF0ZSBhIHBvcHVwIHdpbmRvdyBhcyBhIG1vZGFsOlxuICAgICAqXG4gICAgICogTm90ZTogVGhlIG9ubHkgd2F5IHRvIGVuc3VyZSB0cnVlIG1vZGFsIGJlaGF2aW9yIGlzIHRvIGNyZWF0ZSB0aGUgd2luZG93IGJlaW5nIHNob3duIGFzIGEgcG9wdXAgd2l0aCBhXG4gICAgICogYG1vZGFsUGFyZW50SWRlbnRpdHlgIHRoYXQgdXNlcyB0aGUgY2FsbGVyIHZpZXcncyBwYXJlbnQgd2luZG93IGlkZW50aXR5LlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCByZXN1bHQgPSBhd2FpdCBmaW4ubWUuc2hvd1BvcHVwV2luZG93KHtcbiAgICAgKiAgICAgaW5pdGlhbE9wdGlvbnM6IHtcbiAgICAgKiAgICAgICAgIGZyYW1lOiBmYWxzZSxcbiAgICAgKiAgICAgICAgIG1vZGFsUGFyZW50SWRlbnRpdHk6IGZpbi5tZS5pZGVudGl0eVxuICAgICAqICAgICB9LFxuICAgICAqICAgICB1cmw6ICc8bXlfcG9wdXBfdXJsPicsXG4gICAgICogICAgIHJlc3VsdERpc3BhdGNoQmVoYXZpb3I6ICdjbG9zZScsXG4gICAgICogICAgIGJsdXJCZWhhdmlvcjogJ21vZGFsJyxcbiAgICAgKiAgICAgZm9jdXM6IHRydWUsXG4gICAgICogICAgIGhlaWdodDogMzAwLFxuICAgICAqICAgICB3aWR0aDogMzAwLFxuICAgICAqICAgICB4OiAwLFxuICAgICAqICAgICB5OiAwXG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBQYXNzIGRhdGEgdG8gYSBwb3B1cCB3aW5kb3cgdGhhdCBpcyBhdmFpbGFibGUgd2hlbiB0aGUgcG9wdXAgaXMgc2hvd24uXG4gICAgICpcbiAgICAgKiBOb3RlOiB0aGlzIGlzIGp1c3Qgb25lIGV4YW1wbGUgZm9yIGEgdXNlIG9mIGBhZGRpdGlvbmFsT3B0aW9uc2AsIGl0IGNhbiBiZSB1c2VkIHRvIHVwZGF0ZSBhbnkgdXBkYXRhYmxlXG4gICAgICogd2luZG93IG9wdGlvbnMgd2hlbiBjcmVhdGluZyBvciBzaG93aW5nIGFuIGV4aXN0aW5nIHdpbmRvdyBhcyBhIHBvcHVwLlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCByZXN1bHQgPSBhd2FpdCBmaW4ubWUuc2hvd1BvcHVwV2luZG93KHtcbiAgICAgKiAgICAgYWRkaXRpb25hbE9wdGlvbnM6IHtcbiAgICAgKiAgICAgICAgIGN1c3RvbURhdGE6IHtcbiAgICAgKiAgICAgICAgICAgICBmb286ICdiYXInXG4gICAgICogICAgICAgICB9XG4gICAgICogICAgIH0sXG4gICAgICogICAgIHVybDogJzxteV9wb3B1cF91cmw+JyxcbiAgICAgKiAgICAgcmVzdWx0RGlzcGF0Y2hCZWhhdmlvcjogJ2Nsb3NlJyxcbiAgICAgKiAgICAgYmx1ckJlaGF2aW9yOiAnY2xvc2UnLFxuICAgICAqICAgICBmb2N1czogdHJ1ZSxcbiAgICAgKiAgICAgaGVpZ2h0OiAzMDAsXG4gICAgICogICAgIHdpZHRoOiAzMDAsXG4gICAgICogICAgIHg6IDAsXG4gICAgICogICAgIHk6IDBcbiAgICAgKiB9KTtcbiAgICAgKlxuICAgICAqIC8vIEFjY2VzcyBmcm9tIHRoZSBwb3B1cCB3aW5kb3cgY29udGV4dCBsaWtlIHNvOlxuICAgICAqIGNvbnN0IHsgY3VzdG9tRGF0YSB9ID0gYXdhaXQgZmluLm1lLmdldE9wdGlvbnMoKTtcbiAgICAgKiBjb25zdCB7IGZvbyB9ID0gY3VzdG9tRGF0YTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEV4ZWN1dGUgYSBjYWxsYmFjayBvbiB0aGUgcG9wdXAncyBPcGVuRmluIHdpbmRvdyB3aGVuIHRoZSBwb3B1cCBpcyBzaG93bjpcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcG9wdXBXaW5kb3dDYWxsYmFjayA9IGFzeW5jICh3aW4pID0+IHtcbiAgICAgKiAgICAgYXdhaXQgd2luLmZsYXNoKCk7XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbi5tZS5zaG93UG9wdXBXaW5kb3coe1xuICAgICAqICAgICB1cmw6ICc8bXlfcG9wdXBfdXJsPicsXG4gICAgICogICAgIHJlc3VsdERpc3BhdGNoQmVoYXZpb3I6ICdjbG9zZScsXG4gICAgICogICAgIGJsdXJCZWhhdmlvcjogJ2Nsb3NlJyxcbiAgICAgKiAgICAgZm9jdXM6IHRydWUsXG4gICAgICogICAgIGhlaWdodDogMzAwLFxuICAgICAqICAgICB3aWR0aDogMzAwLFxuICAgICAqICAgICB4OiAwLFxuICAgICAqICAgICB5OiAwLFxuICAgICAqICAgICBvblBvcHVwUmVhZHk6IHBvcHVwV2luZG93Q2FsbGJhY2s7XG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBgV2ViQ29udGVudHNgIHJlZmVycyB0byBzaGFyZWQgZnVuY3Rpb25hbGl0eSBiZXR3ZWVuIHtAbGluayBPcGVuRmluLldpbmRvd30gYW5kIHtAbGluayBPcGVuRmluLlZpZXd9LlxuICAgICAqIFdlIGRvIG5vdCBleHBvc2UgYW4gZXhwbGljaXQgc3VwZXJjbGFzcyBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5LCBidXQgaXQgZG9lcyBoYXZlIGl0cyBvd25cbiAgICAgKiB7QGxpbmsgT3BlbkZpbi5XZWJDb250ZW50c0V2ZW50cyBldmVudCBuYW1lc3BhY2V9LlxuICAgICAqL1xuICAgIGFzeW5jIHNob3dQb3B1cFdpbmRvdyhvcHRpb25zKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKGAke3RoaXMuZW50aXR5VHlwZX0tc2hvdy1wb3B1cC13aW5kb3dgLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChvcHRpb25zPy5vblBvcHVwUmVhZHkpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlYWR5TGlzdGVuZXIgPSBhc3luYyAoeyBwb3B1cE5hbWUgfSkgPT4ge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvcHVwV2luZG93ID0gdGhpcy5maW4uV2luZG93LndyYXBTeW5jKHsgdXVpZDogdGhpcy5maW4ubWUudXVpZCwgbmFtZTogcG9wdXBOYW1lIH0pO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBvcHRpb25zLm9uUG9wdXBSZWFkeShwb3B1cFdpbmRvdyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFNvbWV0aGluZyB3ZW50IHdyb25nIGR1cmluZyBvblBvcHVwUmVhZHkgZXhlY3V0aW9uOiAke2Vycm9yfWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvLyBUT0RPOiBmaXggdHlwaW5nIChpbnRlcm5hbClcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgIGF3YWl0IHRoaXMub25jZSgncG9wdXAtcmVhZHknLCByZWFkeUxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHRyeUNyZWF0ZVBheWxvYWQgfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCd0cnktY3JlYXRlLXBvcHVwLXdpbmRvdycsIHtcbiAgICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICAgICAgICAgIC8vIEludGVybmFsIHVzZSBvbmx5LlxuICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgICAgICBoYXNSZXN1bHRDYWxsYmFjazogISFvcHRpb25zPy5vblBvcHVwUmVzdWx0LFxuICAgICAgICAgICAgICAgIGhhc1JlYWR5Q2FsbGJhY2s6ICEhb3B0aW9ucz8ub25Qb3B1cFJlYWR5XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgeyBkYXRhOiB7IHdpbGxPcGVuLCBvcHRpb25zOiBwb3B1cE9wdGlvbnMgfSB9ID0gdHJ5Q3JlYXRlUGF5bG9hZDtcbiAgICAgICAgaWYgKHdpbGxPcGVuKSB7XG4gICAgICAgICAgICAvLyBTb2x2ZSB0aGUgaXNzdWUgd2hlcmUgSW50ZXJvcCBpbiBhIHBvcHVwIHdpbmRvdyB3aXRoIG5vbiBjcm9zcy1vcmlnaW4gdXJsIGlzIG5vdCB3b3JraW5nKGNvcmUtMTA3NikuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmZpbi5XaW5kb3cuY3JlYXRlKHBvcHVwT3B0aW9ucy5pbml0aWFsT3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgbm9ybWFsaXplUG9wdXBSZXN1bHQgPSAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgeyBuYW1lLCB1dWlkLCByZXN1bHQsIGRhdGEgfSA9IHBheWxvYWQ7XG4gICAgICAgICAgICBjb25zdCBwb3B1cFJlc3VsdCA9IHtcbiAgICAgICAgICAgICAgICBpZGVudGl0eToge1xuICAgICAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgICAgICB1dWlkXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByZXN1bHRcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoZGF0YSkge1xuICAgICAgICAgICAgICAgIHBvcHVwUmVzdWx0LmRhdGEgPSBkYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHBvcHVwUmVzdWx0O1xuICAgICAgICB9O1xuICAgICAgICBpZiAob3B0aW9ucz8ub25Qb3B1cFJlc3VsdCkge1xuICAgICAgICAgICAgY29uc3QgZGlzcGF0Y2hSZXN1bHRMaXN0ZW5lciA9IGFzeW5jIChwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICAgICAgYXdhaXQgb3B0aW9ucy5vblBvcHVwUmVzdWx0KG5vcm1hbGl6ZVBvcHVwUmVzdWx0KHBheWxvYWQpKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCB0ZWFyZG93bkxpc3RlbmVyID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IGZpeCB0eXBpbmcgKGludGVybmFsKVxuICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJlbW92ZUxpc3RlbmVyKCdwb3B1cC1yZXN1bHQnLCBkaXNwYXRjaFJlc3VsdExpc3RlbmVyKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICAvLyBUT0RPOiBmaXggdHlwaW5nIChpbnRlcm5hbClcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgIGF3YWl0IHRoaXMub24oJ3BvcHVwLXJlc3VsdCcsIGRpc3BhdGNoUmVzdWx0TGlzdGVuZXIpO1xuICAgICAgICAgICAgLy8gVE9ETzogZml4IHR5cGluZyAoaW50ZXJuYWwpXG4gICAgICAgICAgICAvLyBoaWxhcmlvdXNseSB0aGlzIGRvZXMgbm90IG5lZWQgYSB0cy1leHBlY3QtZXJyb3IgLSB0aGlzIGlzIGdhcCBpbiB0eXBlIHNvdW5kbmVzc1xuICAgICAgICAgICAgLy8gc2hvdWxkIGludmVzdGlnYXRlIC0gcHJvYmFibHkgZHVlIHRvIGB0ZWFyZG93bkxpc3RlbmVyYCB0YWtpbmcgYSB2b2lkIGFyZ3VtZW50XG4gICAgICAgICAgICAvLyB3aGljaCBtaWdodCBwbGF5IG5pY2VseSB3aXRoIHRoZSBgbmV2ZXJgIHR5cGU/ICBodWguLi5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMub25jZSgncG9wdXAtdGVhcmRvd24nLCB0ZWFyZG93bkxpc3RlbmVyKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IHBheWxvYWQgfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzaG93LXBvcHVwLXdpbmRvdycsIHtcbiAgICAgICAgICAgIG9wdGlvbnM6IHBvcHVwT3B0aW9ucyxcbiAgICAgICAgICAgIC4uLnRoaXMuaWRlbnRpdHlcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBwYXlsb2FkLmRhdGE7XG4gICAgfVxufVxubWFpbi5XZWJDb250ZW50cyA9IFdlYkNvbnRlbnRzO1xuXG52YXIgaGFzUmVxdWlyZWRJbnN0YW5jZSQyO1xuXG5mdW5jdGlvbiByZXF1aXJlSW5zdGFuY2UkMiAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEluc3RhbmNlJDIpIHJldHVybiBJbnN0YW5jZSQ1O1xuXHRoYXNSZXF1aXJlZEluc3RhbmNlJDIgPSAxO1xuXHR2YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG5cdCAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG5cdCAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcblx0ICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG5cdH07XG5cdHZhciBfVmlld19wcm92aWRlckNoYW5uZWxDbGllbnQ7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShJbnN0YW5jZSQ1LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0SW5zdGFuY2UkNS5WaWV3ID0gdm9pZCAwO1xuXHRjb25zdCB0cmFuc3BvcnRfZXJyb3JzXzEgPSB0cmFuc3BvcnRFcnJvcnM7XG5cdGNvbnN0IGxhenlfMSA9IGxhenk7XG5cdGNvbnN0IGxheW91dF9lbnRpdGllc18xID0gbGF5b3V0RW50aXRpZXM7XG5cdGNvbnN0IGxheW91dF9jb25zdGFudHNfMSA9IGxheW91dF9jb25zdGFudHM7XG5cdGNvbnN0IG1haW5fMSA9IG1haW47XG5cdGNvbnN0IHdpbmRvd18xID0gcmVxdWlyZVdpbmRvdygpO1xuXHQvKipcblx0ICogQSBWaWV3IGNhbiBiZSB1c2VkIHRvIGVtYmVkIGFkZGl0aW9uYWwgd2ViIGNvbnRlbnQgaW50byBhIFdpbmRvdy5cblx0ICogSXQgaXMgbGlrZSBhIGNoaWxkIHdpbmRvdywgZXhjZXB0IGl0IGlzIHBvc2l0aW9uZWQgcmVsYXRpdmUgdG8gaXRzIG93bmluZyB3aW5kb3cuXG5cdCAqIEl0IGhhcyB0aGUgYWJpbGl0eSB0byBsaXN0ZW4gZm9yIHtAbGluayBPcGVuRmluLlZpZXdFdmVudHMgVmlldy1zcGVjaWZpYyBldmVudHN9LlxuXHQgKlxuXHQgKiBCeSBkZWZhdWx0LCBhIFZpZXcgd2lsbCB0cnkgdG8gc2hhcmUgdGhlIHNhbWUgcmVuZGVyZXIgcHJvY2VzcyBhcyBvdGhlciBWaWV3cyBvd25lZCBieSBpdHMgcGFyZW50IEFwcGxpY2F0aW9uLlxuXHQgKiBUbyBjaGFuZ2UgdGhhdCBiZWhhdmlvciwgc2VlIHRoZSBwcm9jZXNzQWZmaW5pdHkge0BsaW5rIE9wZW5GaW4uVmlld09wdGlvbnMgdmlldyBvcHRpb259LlxuXHQgKlxuXHQgKiBBIFZpZXcncyBsaWZlY3ljbGUgaXMgdGllZCB0byBpdHMgb3duaW5nIHdpbmRvdyBhbmQgY2FuIGJlIHJlLWF0dGFjaGVkIHRvIGEgZGlmZmVyZW50IHdpbmRvdyBhdCBhbnkgcG9pbnQgZHVyaW5nIGl0cyBsaWZlY3ljbGUuXG5cdCAqL1xuXHRjbGFzcyBWaWV3IGV4dGVuZHMgbWFpbl8xLldlYkNvbnRlbnRzIHtcblx0ICAgIC8qKlxuXHQgICAgICogQGludGVybmFsXG5cdCAgICAgKi9cblx0ICAgIGNvbnN0cnVjdG9yKHdpcmUsIGlkZW50aXR5KSB7XG5cdCAgICAgICAgc3VwZXIod2lyZSwgaWRlbnRpdHksICd2aWV3Jyk7XG5cdCAgICAgICAgdGhpcy5pZGVudGl0eSA9IGlkZW50aXR5O1xuXHQgICAgICAgIF9WaWV3X3Byb3ZpZGVyQ2hhbm5lbENsaWVudC5zZXQodGhpcywgbmV3IGxhenlfMS5MYXp5KCgpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgcGxhdGZvcm0gPSB0aGlzLmZpbi5QbGF0Zm9ybS53cmFwU3luYyh0aGlzLmlkZW50aXR5KTtcblx0ICAgICAgICAgICAgcmV0dXJuIHBsYXRmb3JtLmdldENsaWVudCgpO1xuXHQgICAgICAgIH0pKTtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBBdHRhY2hlcyB0aGUgY3VycmVudCB2aWV3IHRvIHRoZSBnaXZlbiB3aW5kb3cgaWRlbnRpdHkuXG5cdCAgICAgICAgICogSWRlbnRpdHkgbXVzdCBiZSB0aGUgaWRlbnRpdHkgb2YgYSB3aW5kb3cgaW4gdGhlIHNhbWUgYXBwbGljYXRpb24uXG5cdCAgICAgICAgICogVGhpcyBkZXRhY2hlcyB0aGUgdmlldyBmcm9tIGl0cyBjdXJyZW50IHdpbmRvdywgYW5kIHNldHMgdGhlIHZpZXcgdG8gYmUgZGVzdHJveWVkIHdoZW4gaXRzIG5ldyB3aW5kb3cgY2xvc2VzLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKiBgYGBqc1xuXHQgICAgICAgICAqIGxldCB2aWV3O1xuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVZpZXcoKSB7XG5cdCAgICAgICAgICogICAgIGNvbnN0IG1lID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG5cdCAgICAgICAgICogICAgIHJldHVybiBmaW4uVmlldy5jcmVhdGUoe1xuXHQgICAgICAgICAqICAgICAgICAgbmFtZTogJ3ZpZXdOYW1lQXR0YWNoJyxcblx0ICAgICAgICAgKiAgICAgICAgIHRhcmdldDogbWUuaWRlbnRpdHksXG5cdCAgICAgICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG5cdCAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIGF0dGFjaFZpZXcoKSB7XG5cdCAgICAgICAgICogICAgIHZpZXcgPSBhd2FpdCBjcmVhdGVWaWV3KCk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IGNyZWF0ZWQuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9nb29nbGUuY29tJyk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IG5hdmlnYXRlZCB0byBnaXZlbiB1cmwuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgY29uc3Qgd2luT3B0aW9uID0ge1xuXHQgICAgICAgICAqICAgICAgICAgbmFtZTond2luT3B0aW9uTmFtZScsXG5cdCAgICAgICAgICogICAgICAgICBkZWZhdWx0V2lkdGg6IDMwMCxcblx0ICAgICAgICAgKiAgICAgICAgIGRlZmF1bHRIZWlnaHQ6IDMwMCxcblx0ICAgICAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuY3JlYXRlLmh0bWwnLFxuXHQgICAgICAgICAqICAgICAgICAgZnJhbWU6IHRydWUsXG5cdCAgICAgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICAgICAqICAgICB9O1xuXHQgICAgICAgICAqICAgICBjb25zdCBuZXdXaW5kb3cgPSBhd2FpdCBmaW4uV2luZG93LmNyZWF0ZSh3aW5PcHRpb24pO1xuXHQgICAgICAgICAqICAgICB2aWV3LmF0dGFjaChuZXdXaW5kb3cuaWRlbnRpdHkpO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGF0dGFjaFZpZXcoKVxuXHQgICAgICAgICAqICAgICAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnVmlldyBhdHRhY2hlZCB0byBuZXcgd2luZG93LicpKVxuXHQgICAgICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLmF0dGFjaCA9IGFzeW5jICh0YXJnZXQpID0+IHtcblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2F0dGFjaC12aWV3JywgeyB0YXJnZXQsIC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgfTtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBEZXN0cm95cyB0aGUgY3VycmVudCB2aWV3XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogY29uc3QgdmlldyA9IGZpbi5WaWV3LndyYXBTeW5jKHsgdXVpZDogJ3ZpZXdVdWlkJywgbmFtZTogJ3ZpZXdOYW1lJyB9KTtcblx0ICAgICAgICAgKiB2aWV3LmRlc3Ryb3koKTtcblx0ICAgICAgICAgKiBgYGBcblx0ICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy5kZXN0cm95ID0gYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZGVzdHJveS12aWV3JywgeyAuLi50aGlzLmlkZW50aXR5IH0pO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogU2hvd3MgdGhlIGN1cnJlbnQgdmlldyBpZiBpdCBpcyBjdXJyZW50bHkgaGlkZGVuLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKiBgYGBqc1xuXHQgICAgICAgICAqIGxldCB2aWV3O1xuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVZpZXcoKSB7XG5cdCAgICAgICAgICogICAgIGNvbnN0IG1lID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG5cdCAgICAgICAgICogICAgIHJldHVybiBmaW4uVmlldy5jcmVhdGUoe1xuXHQgICAgICAgICAqICAgICAgICAgbmFtZTogJ3ZpZXdOYW1lU2hvdycsXG5cdCAgICAgICAgICogICAgICAgICB0YXJnZXQ6IG1lLmlkZW50aXR5LFxuXHQgICAgICAgICAqICAgICAgICAgYm91bmRzOiB7dG9wOiAxMCwgbGVmdDogMTAsIHdpZHRoOiAyMDAsIGhlaWdodDogMjAwfVxuXHQgICAgICAgICAqICAgICB9KTtcblx0ICAgICAgICAgKiB9XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBhc3luYyBmdW5jdGlvbiBoaWRlQW5kU2hvd1ZpZXcoKSB7XG5cdCAgICAgICAgICogICAgIHZpZXcgPSBhd2FpdCBjcmVhdGVWaWV3KCk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IGNyZWF0ZWQuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9nb29nbGUuY29tJyk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IG5hdmlnYXRlZCB0byBnaXZlbiB1cmwgb3B0aW9uLicpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGF3YWl0IHZpZXcuaGlkZSgpO1xuXHQgICAgICAgICAqICAgICBjb25zb2xlLmxvZyhcIlZpZXcgaGlkZGVuLlwiKTtcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2aWV3LnNob3coKTtcblx0ICAgICAgICAgKiAgICAgY29uc29sZS5sb2coXCJWaWV3IHNob3duLlwiKTtcblx0ICAgICAgICAgKiB9XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBoaWRlQW5kU2hvd1ZpZXcoKVxuXHQgICAgICAgICAqICAgICAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnVmlldyBoaWRkZW4gYW5kIHNob3duLicpKVxuXHQgICAgICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLnNob3cgPSBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzaG93LXZpZXcnLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgfTtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBTZXRzIHRoZSBib3VuZHMgKHRvcCwgbGVmdCwgd2lkdGgsIGhlaWdodCkgb2YgdGhlIHZpZXcgcmVsYXRpdmUgdG8gaXRzIHdpbmRvdyBhbmQgc2hvd3MgaXQgaWYgaXQgaXMgaGlkZGVuLlxuXHQgICAgICAgICAqIFRoaXMgbWV0aG9kIGVuc3VyZXMgdGhlIHZpZXcgaXMgYm90aCBwb3NpdGlvbmVkIGFuZCBzaG93aW5nLiBJdCB3aWxsIHJlcG9zaXRpb24gYSB2aXNpYmxlIHZpZXcgYW5kIGJvdGggc2hvdyBhbmQgcmVwb3NpdGlvbiBhIGhpZGRlbiB2aWV3LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJlbWFya3MgVmlldyBwb3NpdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgYm91bmRzIG9mIHRoZSB3aW5kb3cuXG5cdCAgICAgICAgICogKHt0b3A6IDAsIGxlZnQ6IDB9IHJlcHJlc2VudHMgdGhlIHRvcCBsZWZ0IGNvcm5lciBvZiB0aGUgd2luZG93KVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKiBgYGBqc1xuXHQgICAgICAgICAqIGxldCB2aWV3O1xuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVZpZXcoKSB7XG5cdCAgICAgICAgICogICAgIGNvbnN0IG1lID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG5cdCAgICAgICAgICogICAgIHJldHVybiBmaW4uVmlldy5jcmVhdGUoe1xuXHQgICAgICAgICAqICAgICAgICAgbmFtZTogJ3ZpZXdOYW1lU2V0Qm91bmRzJyxcblx0ICAgICAgICAgKiAgICAgICAgIHRhcmdldDogbWUuaWRlbnRpdHksXG5cdCAgICAgICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG5cdCAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNob3dWaWV3QXQoKSB7XG5cdCAgICAgICAgICogICAgIHZpZXcgPSBhd2FpdCBjcmVhdGVWaWV3KCk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IGNyZWF0ZWQuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9nb29nbGUuY29tJyk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IG5hdmlnYXRlZCB0byBnaXZlbiB1cmwuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5zaG93QXQoe1xuXHQgICAgICAgICAqICAgICAgICAgdG9wOiAxMDAsXG5cdCAgICAgICAgICogICAgICAgICBsZWZ0OiAxMDAsXG5cdCAgICAgICAgICogICAgICAgICB3aWR0aDogMzAwLFxuXHQgICAgICAgICAqICAgICAgICAgaGVpZ2h0OiAzMDBcblx0ICAgICAgICAgKiAgICAgfSwge1xuXHQgICAgICAgICAqICAgICAgIGJyaW5nVG9Gcm9udCA6IHRydWVcblx0ICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogc2hvd1ZpZXdBdCgpXG5cdCAgICAgICAgICogICAgIC50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdWaWV3IHNldCB0byBuZXcgYm91bmRzIGFuZCBzaG93bi4nKSlcblx0ICAgICAgICAgKiAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAgICAgKiBgYGBcblx0ICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy5zaG93QXQgPSBhc3luYyAoYm91bmRzLCBvcHRpb25zID0ge30pID0+IHtcblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Nob3ctdmlldy1hdCcsIHsgYm91bmRzLCAuLi50aGlzLmlkZW50aXR5LCBvcHRpb25zIH0pO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQnJpbmdzIHRoZSBzcGVjaWZpZWQgdmlldyB0byB0aGUgZnJvbnQgb2YgaXRzIGN1cnJlbnQgd2luZG93LiBUaGlzIGVuc3VyZXMgdGhlIHZpZXcgd2lsbCBiZSB2aXNpYmxlIG9uIHRvcCBvZiBhbnkgb3RoZXIgdmlld3Ncblx0ICAgICAgICAgKiB3aGljaCBoYXZlIG92ZXJsYXBwaW5nIGJvdW5kcyB3aXRoIGl0LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogUGxlYXNlIG5vdGUsIHRoaXMgaXMgbm90IGEgcGVybWFuZW50IGFjdGlvbiAtIHdoZW4gYSBuZXcgdmlldyBpcyBjcmVhdGVkIG9yIGF0dGFjaGVkIHRvIHRoZSB3aW5kb3csIGl0IHdpbGwgZGlzcGxheSBvbiB0b3Agb2YgYWxsIG90aGVyIHZpZXdzXG5cdCAgICAgICAgICogaW4gdGhlIHdpbmRvdyB0aGF0IHNoYXJlIGJvdW5kcyB3aXRoIGl0LlxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHRoaXMuYnJpbmdUb0Zyb250ID0gYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignYnJpbmctdmlldy10by1mcm9udCcsIHsgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIEhpZGVzIHRoZSBjdXJyZW50IHZpZXcgaWYgaXQgaXMgY3VycmVudGx5IHZpc2libGUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogbGV0IHZpZXc7XG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlVmlldygpIHtcblx0ICAgICAgICAgKiAgICAgY29uc3QgbWUgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAgICAgKiAgICAgcmV0dXJuIGZpbi5WaWV3LmNyZWF0ZSh7XG5cdCAgICAgICAgICogICAgICAgICBuYW1lOiAndmlld05hbWVIaWRlJyxcblx0ICAgICAgICAgKiAgICAgICAgIHRhcmdldDogbWUuaWRlbnRpdHksXG5cdCAgICAgICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG5cdCAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIGhpZGVWaWV3KCkge1xuXHQgICAgICAgICAqICAgICB2aWV3ID0gYXdhaXQgY3JlYXRlVmlldygpO1xuXHQgICAgICAgICAqICAgICBjb25zb2xlLmxvZygnVmlldyBjcmVhdGVkLicpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGF3YWl0IHZpZXcubmF2aWdhdGUoJ2h0dHBzOi8vZ29vZ2xlLmNvbScpO1xuXHQgICAgICAgICAqICAgICBjb25zb2xlLmxvZygnVmlldyBuYXZpZ2F0ZWQgdG8gZ2l2ZW4gdXJsLicpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGF3YWl0IHZpZXcuaGlkZSgpO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGhpZGVWaWV3KClcblx0ICAgICAgICAgKiAgICAgLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1ZpZXcgaGlkZGVuLicpKVxuXHQgICAgICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLmhpZGUgPSBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdoaWRlLXZpZXcnLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgfTtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBTZXRzIHRoZSBib3VuZHMgKHRvcCwgbGVmdCwgd2lkdGgsIGhlaWdodCkgb2YgdGhlIHZpZXcgcmVsYXRpdmUgdG8gaXRzIHdpbmRvdy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZW1hcmtzIFZpZXcgcG9zaXRpb24gaXMgcmVsYXRpdmUgdG8gdGhlIGJvdW5kcyBvZiB0aGUgd2luZG93LlxuXHQgICAgICAgICAqICh7dG9wOiAwLCBsZWZ0OiAwfSByZXByZXNlbnRzIHRoZSB0b3AgbGVmdCBjb3JuZXIgb2YgdGhlIHdpbmRvdylcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICogYGBganNcblx0ICAgICAgICAgKiBsZXQgdmlldztcblx0ICAgICAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVWaWV3KCkge1xuXHQgICAgICAgICAqICAgICBjb25zdCBtZSA9IGF3YWl0IGZpbi5XaW5kb3cuZ2V0Q3VycmVudCgpO1xuXHQgICAgICAgICAqICAgICByZXR1cm4gZmluLlZpZXcuY3JlYXRlKHtcblx0ICAgICAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZVNldEJvdW5kcycsXG5cdCAgICAgICAgICogICAgICAgICB0YXJnZXQ6IG1lLmlkZW50aXR5LFxuXHQgICAgICAgICAqICAgICAgICAgYm91bmRzOiB7dG9wOiAxMCwgbGVmdDogMTAsIHdpZHRoOiAyMDAsIGhlaWdodDogMjAwfVxuXHQgICAgICAgICAqICAgICB9KTtcblx0ICAgICAgICAgKiB9XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBhc3luYyBmdW5jdGlvbiBzZXRWaWV3Qm91bmRzKCkge1xuXHQgICAgICAgICAqICAgICB2aWV3ID0gYXdhaXQgY3JlYXRlVmlldygpO1xuXHQgICAgICAgICAqICAgICBjb25zb2xlLmxvZygnVmlldyBjcmVhdGVkLicpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGF3YWl0IHZpZXcubmF2aWdhdGUoJ2h0dHBzOi8vZ29vZ2xlLmNvbScpO1xuXHQgICAgICAgICAqICAgICBjb25zb2xlLmxvZygnVmlldyBuYXZpZ2F0ZWQgdG8gZ2l2ZW4gdXJsLicpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGF3YWl0IHZpZXcuc2V0Qm91bmRzKHtcblx0ICAgICAgICAgKiAgICAgICAgIHRvcDogMTAwLFxuXHQgICAgICAgICAqICAgICAgICAgbGVmdDogMTAwLFxuXHQgICAgICAgICAqICAgICAgICAgd2lkdGg6IDMwMCxcblx0ICAgICAgICAgKiAgICAgICAgIGhlaWdodDogMzAwXG5cdCAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIHNldFZpZXdCb3VuZHMoKVxuXHQgICAgICAgICAqICAgICAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnVmlldyBzZXQgdG8gbmV3IGJvdW5kcy4nKSlcblx0ICAgICAgICAgKiAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAgICAgKiBgYGBcblx0ICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy5zZXRCb3VuZHMgPSBhc3luYyAoYm91bmRzKSA9PiB7XG5cdCAgICAgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzZXQtdmlldy1ib3VuZHMnLCB7IGJvdW5kcywgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIEdldHMgdGhlIGJvdW5kcyAodG9wLCBsZWZ0LCB3aWR0aCwgaGVpZ2h0KSBvZiB0aGUgdmlldyByZWxhdGl2ZSB0byBpdHMgd2luZG93LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJlbWFya3MgVmlldyBwb3NpdGlvbiBpcyByZWxhdGl2ZSB0byB0aGUgYm91bmRzIG9mIHRoZSB3aW5kb3cuXG5cdCAgICAgICAgICogKHt0b3A6IDAsIGxlZnQ6IDB9IHJlcHJlc2VudHMgdGhlIHRvcCBsZWZ0IGNvcm5lciBvZiB0aGUgd2luZG93KVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKiBgYGBqc1xuXHQgICAgICAgICAqIGNvbnN0IHZpZXcgPSBhd2FpdCBmaW4uVmlldy5jcmVhdGUoe1xuXHQgICAgICAgICAqICAgICBuYW1lOiAndmlld05hbWVTZXRCb3VuZHMnLFxuXHQgICAgICAgICAqICAgICB0YXJnZXQ6IGZpbi5tZS5pZGVudGl0eSxcblx0ICAgICAgICAgKiAgICAgYm91bmRzOiB7dG9wOiAxMCwgbGVmdDogMTAsIHdpZHRoOiAyMDAsIGhlaWdodDogMjAwfVxuXHQgICAgICAgICAqIH0pO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9nb29nbGUuY29tJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBhd2FpdCB2aWV3LnNldEJvdW5kcyh7XG5cdCAgICAgICAgICogICAgIHRvcDogMTAwLFxuXHQgICAgICAgICAqICAgICBsZWZ0OiAxMDAsXG5cdCAgICAgICAgICogICAgIHdpZHRoOiAzMDAsXG5cdCAgICAgICAgICogICAgIGhlaWdodDogMzAwXG5cdCAgICAgICAgICogfSk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBjb25zb2xlLmxvZyhhd2FpdCB2aWV3LmdldEJvdW5kcygpKTtcblx0ICAgICAgICAgKiBgYGBcblx0ICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy5nZXRCb3VuZHMgPSBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgIGNvbnN0IGFjayA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtdmlldy1ib3VuZHMnLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgICAgIHJldHVybiBhY2sucGF5bG9hZC5kYXRhO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogR2V0cyB0aGUgVmlldydzIGluZm8uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogbGV0IHZpZXc7XG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlVmlldygpIHtcblx0ICAgICAgICAgKiAgICAgY29uc3QgbWUgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAgICAgKiAgICAgcmV0dXJuIGZpbi5WaWV3LmNyZWF0ZSh7XG5cdCAgICAgICAgICogICAgICAgICBuYW1lOiAndmlld05hbWVHZXRJbmZvJyxcblx0ICAgICAgICAgKiAgICAgICAgIHRhcmdldDogbWUuaWRlbnRpdHksXG5cdCAgICAgICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG5cdCAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFZpZXdJbmZvKCkge1xuXHQgICAgICAgICAqICAgICB2aWV3ID0gYXdhaXQgY3JlYXRlVmlldygpO1xuXHQgICAgICAgICAqICAgICBjb25zb2xlLmxvZygnVmlldyBjcmVhdGVkLicpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGF3YWl0IHZpZXcubmF2aWdhdGUoJ2h0dHBzOi8vZ29vZ2xlLmNvbScpO1xuXHQgICAgICAgICAqICAgICBjb25zb2xlLmxvZygnVmlldyBuYXZpZ2F0ZWQgdG8gZ2l2ZW4gdXJsLicpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHJldHVybiB2aWV3LmdldEluZm8oKTtcblx0ICAgICAgICAgKiB9XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBnZXRWaWV3SW5mbygpXG5cdCAgICAgICAgICogICAgIC50aGVuKChpbmZvKSA9PiBjb25zb2xlLmxvZygnVmlldyBpbmZvIGZldGNoZWQuJywgaW5mbykpXG5cdCAgICAgICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgICAgICogYGBgXG5cdCAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHRoaXMuZ2V0SW5mbyA9IGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgYWNrID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC12aWV3LWluZm8nLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgICAgIHJldHVybiBhY2sucGF5bG9hZC5kYXRhO1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogUmV0cmlldmVzIHRoZSBsYXlvdXQgZm9yIHRoZSB3aW5kb3cgdGhlIHZpZXcgaXMgYXR0YWNoZWQgdG8uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogICAgIC8vZ2V0IHRoZSBjdXJyZW50IFZpZXdcblx0ICAgICAgICAgKiAgICAgY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmdldEN1cnJlbnQoKTtcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICAvL2dldCBhIHJlZmVyZW5jZSB0byB0aGUgTGF5b3V0IGZvciB0aGUgV2luZG93IHRoZSB2aWV3IGlzIHBhcnQgb2Zcblx0ICAgICAgICAgKiAgICAgY29uc3QgbGF5b3V0ID0gYXdhaXQgdmlldy5nZXRQYXJlbnRMYXlvdXQoKTtcblx0ICAgICAgICAgKiBgYGBcblx0ICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy5nZXRQYXJlbnRMYXlvdXQgPSBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd2aWV3LWdldC1wYXJlbnQtbGF5b3V0JywgeyAuLi50aGlzLmlkZW50aXR5IH0pLmNhdGNoKCgpID0+IHtcblx0ICAgICAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuXHQgICAgICAgICAgICB9KTtcblx0ICAgICAgICAgICAgY29uc3QgbGF5b3V0V2luZG93ID0gYXdhaXQgdGhpcy5nZXRDdXJyZW50V2luZG93KCk7XG5cdCAgICAgICAgICAgIGxldCBsYXlvdXRXaW5kb3dJZGVudGl0eSA9IGxheW91dFdpbmRvdy5pZGVudGl0eTtcblx0ICAgICAgICAgICAgLy8gVE9ETzogQ09SRS0xODU3IC0gd2hlbiB3ZSB0ZWFyb3V0IGFjdGl2ZSBsYXlvdXQgb3IgZHJhZyBhIHZpZXcgb3V0IG9mIGEgd2luZG93LCB0aGUgYWJvdmUgaWRlbnRpdHkgaW5jbHVkZXMgdGhlIHdob2xlIHdpbmRvdyBpbmZvLlxuXHQgICAgICAgICAgICBpZiAobGF5b3V0V2luZG93SWRlbnRpdHkuaWRlbnRpdHkpIHtcblx0ICAgICAgICAgICAgICAgIGxheW91dFdpbmRvd0lkZW50aXR5ID0gbGF5b3V0V2luZG93SWRlbnRpdHkuaWRlbnRpdHk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IHByb3ZpZGVyQ2hhbm5lbENsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1ZpZXdfcHJvdmlkZXJDaGFubmVsQ2xpZW50LCBcImZcIikuZ2V0VmFsdWUoKTtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IGxheW91dF9lbnRpdGllc18xLkxheW91dE5vZGUubmV3TGF5b3V0RW50aXRpZXNDbGllbnQocHJvdmlkZXJDaGFubmVsQ2xpZW50LCBsYXlvdXRfY29uc3RhbnRzXzEuTEFZT1VUX0NPTlRST0xMRVJfSUQsIGxheW91dFdpbmRvd0lkZW50aXR5KTtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IGxheW91dElkZW50aXR5ID0gYXdhaXQgY2xpZW50LmdldExheW91dElkZW50aXR5Rm9yVmlld09yVGhyb3codGhpcy5pZGVudGl0eSk7XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5maW4uUGxhdGZvcm0uTGF5b3V0LndyYXAobGF5b3V0SWRlbnRpdHkpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNhdGNoIChlKSB7XG5cdCAgICAgICAgICAgICAgICBjb25zdCBhbGxvd2VkRXJyb3JzID0gW1xuXHQgICAgICAgICAgICAgICAgICAgICdObyBhY3Rpb24gcmVnaXN0ZXJlZCBhdCB0YXJnZXQgZm9yJyxcblx0ICAgICAgICAgICAgICAgICAgICAnZ2V0TGF5b3V0SWRlbnRpdHlGb3JWaWV3T3JUaHJvdyBpcyBub3QgYSBmdW5jdGlvbidcblx0ICAgICAgICAgICAgICAgIF07XG5cdCAgICAgICAgICAgICAgICBpZiAoIWFsbG93ZWRFcnJvcnMuc29tZSgobSkgPT4gZS5tZXNzYWdlLmluY2x1ZGVzKG0pKSkge1xuXHQgICAgICAgICAgICAgICAgICAgIHRocm93IGU7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICAvLyBmYWxsYmFjayBsb2dpYyBmb3IgbWlzc2luZyBlbmRwb2ludFxuXHQgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluLlBsYXRmb3JtLkxheW91dC53cmFwKGxheW91dFdpbmRvd0lkZW50aXR5KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH07XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogR2V0cyB0aGUgVmlldydzIG9wdGlvbnMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogbGV0IHZpZXc7XG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlVmlldygpIHtcblx0ICAgICAgICAgKiAgICAgY29uc3QgbWUgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAgICAgKiAgICAgcmV0dXJuIGZpbi5WaWV3LmNyZWF0ZSh7XG5cdCAgICAgICAgICogICAgICAgICBuYW1lOiAndmlld05hbWVHZXRPcHRpb25zJyxcblx0ICAgICAgICAgKiAgICAgICAgIHRhcmdldDogbWUuaWRlbnRpdHksXG5cdCAgICAgICAgICogICAgICAgICBib3VuZHM6IHt0b3A6IDEwLCBsZWZ0OiAxMCwgd2lkdGg6IDIwMCwgaGVpZ2h0OiAyMDB9XG5cdCAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAqIH1cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFZpZXdPcHRpb25zKCkge1xuXHQgICAgICAgICAqICAgICB2aWV3ID0gYXdhaXQgY3JlYXRlVmlldygpO1xuXHQgICAgICAgICAqICAgICBjb25zb2xlLmxvZygnVmlldyBjcmVhdGVkLicpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGF3YWl0IHZpZXcubmF2aWdhdGUoJ2h0dHBzOi8vZ29vZ2xlLmNvbScpO1xuXHQgICAgICAgICAqICAgICBjb25zb2xlLmxvZygnVmlldyBuYXZpZ2F0ZWQgdG8gZ2l2ZW4gdXJsLicpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGNvbnN0IG1lID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG5cdCAgICAgICAgICogICAgIHZpZXcgPSBmaW4uVmlldy53cmFwU3luYyh7IHV1aWQ6IG1lLmlkZW50aXR5LnV1aWQsIG5hbWU6ICd2aWV3TmFtZUdldE9wdGlvbnMnIH0pO1xuXHQgICAgICAgICAqICAgICByZXR1cm4gdmlldy5nZXRPcHRpb25zKCk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogZ2V0Vmlld09wdGlvbnMoKVxuXHQgICAgICAgICAqICAgICAudGhlbigoaW5mbykgPT4gY29uc29sZS5sb2coJ1ZpZXcgb3B0aW9ucyBmZXRjaGVkLicsIGluZm8pKVxuXHQgICAgICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0aGlzLmdldE9wdGlvbnMgPSBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXZpZXctb3B0aW9ucycsIHsgLi4udGhpcy5pZGVudGl0eSB9KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFVwZGF0ZXMgdGhlIHZpZXcncyBvcHRpb25zLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKiBgYGBqc1xuXHQgICAgICAgICAqIGxldCB2aWV3O1xuXHQgICAgICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVZpZXcoKSB7XG5cdCAgICAgICAgICogICAgIGNvbnN0IG1lID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG5cdCAgICAgICAgICogICAgIHJldHVybiBmaW4uVmlldy5jcmVhdGUoe1xuXHQgICAgICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9nb29nbGUuY29tJyxcblx0ICAgICAgICAgKiAgICAgICAgIG5hbWU6ICd2aWV3TmFtZVVwZGF0ZU9wdGlvbnMnLFxuXHQgICAgICAgICAqICAgICAgICAgdGFyZ2V0OiBtZS5pZGVudGl0eSxcblx0ICAgICAgICAgKiAgICAgICAgIGJvdW5kczoge3RvcDogMTAsIGxlZnQ6IDEwLCB3aWR0aDogMjAwLCBoZWlnaHQ6IDIwMH1cblx0ICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICogfVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogYXN5bmMgZnVuY3Rpb24gdXBkYXRlVmlld09wdGlvbnMoKSB7XG5cdCAgICAgICAgICogICAgIHZpZXcgPSBhd2FpdCBjcmVhdGVWaWV3KCk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IGNyZWF0ZWQuJyk7XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgYXdhaXQgdmlldy5uYXZpZ2F0ZSgnaHR0cHM6Ly9nb29nbGUuY29tJyk7XG5cdCAgICAgICAgICogICAgIGNvbnNvbGUubG9nKCdWaWV3IG5hdmlnYXRlZCB0byBnaXZlbiB1cmwgb3B0aW9uLicpO1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGNvbnN0IG5ld09wdGlvbnMgPSB7IGF1dG9SZXNpemU6IHtcblx0ICAgICAgICAgKiAgICAgICAgIHdpZHRoOiB0cnVlLFxuXHQgICAgICAgICAqICAgICAgICAgaG9yaXpvbnRhbDogdHJ1ZVxuXHQgICAgICAgICAqICAgICB9fTtcblx0ICAgICAgICAgKiAgICAgcmV0dXJuIHZpZXcudXBkYXRlT3B0aW9ucyhuZXdPcHRpb25zKTtcblx0ICAgICAgICAgKiB9XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiB1cGRhdGVWaWV3T3B0aW9ucygpXG5cdCAgICAgICAgICogICAgIC50aGVuKHBheWxvYWQgPT4gY29uc29sZS5sb2coJ1ZpZXcgb3B0aW9ucyB1cGRhdGVkOiAnLCBwYXlsb2FkKSlcblx0ICAgICAgICAgKiAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAgICAgKiBgYGBcblx0ICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy51cGRhdGVPcHRpb25zID0gYXN5bmMgKG9wdGlvbnMpID0+IHtcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd1cGRhdGUtdmlldy1vcHRpb25zJywgeyBvcHRpb25zLCAuLi50aGlzLmlkZW50aXR5IH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFJldHJpZXZlcyB0aGUgd2luZG93IHRoZSB2aWV3IGlzIGN1cnJlbnRseSBhdHRhY2hlZCB0by5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICogYGBganNcblx0ICAgICAgICAgKiBjb25zdCB2aWV3ID0gZmluLlZpZXcud3JhcFN5bmMoeyB1dWlkOiAndmlld1V1aWQnLCBuYW1lOiAndmlld05hbWUnIH0pO1xuXHQgICAgICAgICAqIHZpZXcuZ2V0Q3VycmVudFdpbmRvdygpXG5cdCAgICAgICAgICogICAgIC50aGVuKHdpbiA9PiBjb25zb2xlLmxvZygnY3VycmVudCB3aW5kb3cnLCB3aW4pKVxuXHQgICAgICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpOylcblx0ICAgICAgICAgKiBgYGBcblx0ICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy5nZXRDdXJyZW50V2luZG93ID0gYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgZGF0YSB9IH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXZpZXctd2luZG93JywgeyAuLi50aGlzLmlkZW50aXR5IH0pO1xuXHQgICAgICAgICAgICByZXR1cm4gbmV3IHdpbmRvd18xLl9XaW5kb3codGhpcy53aXJlLCBkYXRhKTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFJldHJpZXZlcyB0aGUgY3VycmVudCB7QGxpbmsgT3BlbkZpbi5UYWJTdGFja30gb2YgdGhlIHZpZXcgaWYgaXQgYmVsb25ncyB0byBvbmUuXG5cdCAgICAgICAgICogQHJldHVybnMgdGhpcyB2aWV3IGJlbG9uZ3MgdG8uXG5cdCAgICAgICAgICogQHRocm93cyBpZiB0aGlzIHZpZXcgZG9lcyBub3QgYmVsb25nIHRvIGEgVGFiU3RhY2sgb3IgaWYgdGhlIHdpbmRvdyBoYXMgYmVlbiBkZXN0cm95ZWQuXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKiBgYGBqc1xuXHQgICAgICAgICAqIGlmICghZmluLm1lLmlzVmlldykge1xuXHQgICAgICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldy4nKTtcblx0ICAgICAgICAgKiB9XG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBjb25zdCBzdGFjayA9IGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50U3RhY2soKTtcblx0ICAgICAgICAgKiAvLyBBbHRlcm5hdGl2ZWx5LCB5b3UgY2FuIHdyYXAgYW55IHZpZXcgYW5kIGdldCB0aGUgc3RhY2sgZnJvbSB0aGVyZVxuXHQgICAgICAgICAqIC8vIGNvbnN0IHZpZXdGcm9tU29tZXdoZXJlID0gZmluLlZpZXcud3JhcFN5bmMoc29tZVZpZXcuaWRlbnRpdHkpO1xuXHQgICAgICAgICAqIC8vIGNvbnN0IHN0YWNrID0gYXdhaXQgdmlld0Zyb21Tb21ld2hlcmUuZ2V0Q3VycmVudFN0YWNrKCk7XG5cdCAgICAgICAgICogY29uc3Qgdmlld3MgPSBhd2FpdCBzdGFjay5nZXRWaWV3cygpO1xuXHQgICAgICAgICAqIGNvbnNvbGUubG9nKGBTdGFjayBjb250YWlucyAke3ZpZXdzLmxlbmd0aH0gdmlldyhzKWApO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHRoaXMuZ2V0Q3VycmVudFN0YWNrID0gYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigndmlldy1nZXQtY3VycmVudC1zdGFjaycpLmNhdGNoKCgpID0+IHtcblx0ICAgICAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuXHQgICAgICAgICAgICB9KTtcblx0ICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IGxheW91dFdpbmRvdyA9IGF3YWl0IHRoaXMuZ2V0Q3VycmVudFdpbmRvdygpO1xuXHQgICAgICAgICAgICAgICAgY29uc3QgcHJvdmlkZXJDaGFubmVsQ2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfVmlld19wcm92aWRlckNoYW5uZWxDbGllbnQsIFwiZlwiKS5nZXRWYWx1ZSgpO1xuXHQgICAgICAgICAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgbGF5b3V0X2VudGl0aWVzXzEuTGF5b3V0Tm9kZS5uZXdMYXlvdXRFbnRpdGllc0NsaWVudChwcm92aWRlckNoYW5uZWxDbGllbnQsIGxheW91dF9jb25zdGFudHNfMS5MQVlPVVRfQ09OVFJPTExFUl9JRCwgbGF5b3V0V2luZG93LmlkZW50aXR5KTtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IHN0YWNrRGVmaW5pdGlvbiA9IChhd2FpdCBjbGllbnQuZ2V0U3RhY2tCeVZpZXcodGhpcy5pZGVudGl0eSkpO1xuXHQgICAgICAgICAgICAgICAgcmV0dXJuIGxheW91dF9lbnRpdGllc18xLkxheW91dE5vZGUuZ2V0RW50aXR5KHN0YWNrRGVmaW5pdGlvbiwgY2xpZW50KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyB0cmFuc3BvcnRfZXJyb3JzXzEuUnVudGltZUVycm9yKHsgcmVhc29uOiAnVGhpcyB2aWV3IGRvZXMgbm90IGJlbG9uZyB0byBhIHN0YWNrLicsIGVycm9yIH0pO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfTtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBUcmlnZ2VycyB0aGUgYmVmb3JlLXVubG9hZCBoYW5kbGVyIGZvciB0aGUgVmlldywgaWYgb25lIGlzIHNldC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZW1hcmtzIFJldHVybnMgYHRydWVgIGlmIHRoZSBoYW5kbGVyIGlzIHRyeWluZyB0byBwcmV2ZW50IHRoZSBWaWV3IGZyb20gdW5sb2FkaW5nLCBhbmQgYGZhbHNlYCBpZiBpdCBpc24ndC5cblx0ICAgICAgICAgKiBPbmx5IGVuYWJsZWQgd2hlbiBzZXR0aW5nIGVuYWJsZUJlZm9yZVVubG9hZDogdHJ1ZSBpbiB5b3VyIFZpZXcgb3B0aW9ucy4gSWYgdGhpcyBvcHRpb24gaXMgbm90IGVuYWJsZWQgaXQgd2lsbFxuXHQgICAgICAgICAqIGFsd2F5cyByZXR1cm4gZmFsc2UuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBUaGlzIG1ldGhvZCBpcyB1c2VkIGludGVybmFsbHkgYnkgdGhlIFBsYXRmb3JtIFByb3ZpZGVyIHRvIGRldGVybWluZSB0aGUgc3RhdHVzIG9mIGVhY2ggYmVmb3JlIHVubG9hZCBoYW5kbGVyIGluIFZpZXdzIHdoZW4gY2xvc2luZyB0aGUgV2luZG93LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIGBgYGpzXG5cdCAgICAgICAgICogLy8gZnJvbSBpbnNpZGUgYSBWaWV3IGNvbnRleHRcblx0ICAgICAgICAgKiBjb25zdCB1bmxvYWRQcmV2ZW50ZWQgPSBhd2FpdCBmaW4ubWUudHJpZ2dlckJlZm9yZVVubG9hZCgpO1xuXHQgICAgICAgICAqIGBgYFxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHRoaXMudHJpZ2dlckJlZm9yZVVubG9hZCA9IGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCd0cmlnZ2VyLWJlZm9yZS11bmxvYWQnLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgICAgIHJldHVybiBtZXNzYWdlLnBheWxvYWQuZGF0YTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqICoqTk9URSoqOiBJbnRlcm5hbCB1c2Ugb25seS5cblx0ICAgICAgICAgKiBBdHRhY2hlcyB0aGlzIHZpZXcgdG8gYW4gSFRNTCBlbGVtZW50IGluIHRoZSBjdXJyZW50IGNvbnRleHQuIFRoZSB2aWV3IHdpbGwgcmVzaXplIHJlc3BvbnNpdmVseSB3aGVuIHRoZSBlbGVtZW50IGJvdW5kcyBjaGFuZ2UuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAqKktub3duIGlzc3VlKio6IFZpZXcuYmluZFRvRWxlbWVudCBkb2VzIG5vdCB0cmFjayBwb3NpdGlvbiBjaGFuZ2VzLCBpZiB0aGUgZWxlbWVudCBoYXMgZml4ZWQgcHggd2lkdGggYW5kIGhlaWdodCB2YWx1ZXMgaXQgaXMgcG9zc2libGUgZm9yIHRoZSB2aWV3IHRvIG5vdCB1cGRhdGUgcmVzcG9uc2l2ZWx5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogKipLbm93biBpc3N1ZSoqOiBXaGVuIFZpZXcuYmluZFRvRWxlbWVudCBpcyB1c2VkIG9uIGEgZWxlbWVudCB0aGF0IHRha2VzIHVwIHRoZSBlbnRpcmUgcGFnZSBpbiBhIHBsYXRmb3JtIHdpbmRvdywgdGhlIGJvdW5kIHZpZXcgd2lsbCBub3QgcmVzcG9uZCByZXNwb25zaXZlbHkgd2hlbiB0aGUgd2luZG93IGlzIHJlc2l6ZWQgdG8gYmUgc21hbGxlci5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSBlbGVtZW50IC0gSFRNTCBlbGVtZW50IHRvIGF0dGFjaCB0aGUgdmlldyB0by5cblx0ICAgICAgICAgKiBAcmV0dXJucyAtIENsZWFudXAgZnVuY3Rpb24gdGhhdCB3aWxsIGRpc2Nvbm5lY3QgdGhlIGVsZW1lbnQgcmVzaXplIG9ic2VydmVyLlxuXHQgICAgICAgICAqIEBpbnRlcm5hbFxuXHQgICAgICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAgICAgKiBAcmVtYXJrcyBWaWV3IHdpbGwgcmVzaXplIGFjY29yZGluZ2x5IHdoZW4gdGhlIGVsZW1lbnQgaXMgcmVzaXplZC4gSWYgdGhlIGVsZW1lbnQgaXMgcmVwb3NpdGlvbmVkIGluIHRoZSBET00gdGhlIHZpZXcgd2lsbCBub3QgYmUgcmVwb3NpdGlvbmVkLCB0byBoYW5kbGUgdGhpcyBjYXNlIGNhbGwgYGJpbmRUb0VsZW1lbnRgIGFnYWluIG9uY2UgdGhlIGVsZW1lbnQgY2hhbmdlcyBwb3NpdGlvbi5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICogYGBgaHRtbFxuXHQgICAgICAgICAqIDxkaXYgaWQ9XCJ2aWV3LWNvbnRhaW5lclwiPjwvZGl2PlxuXHQgICAgICAgICAqIDxzY3JpcHQ+XG5cdCAgICAgICAgICogICAgIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUFuZEF0dGFjaFZpZXcoKSB7XG5cdCAgICAgICAgICogICAgICAgICBjb25zdCB1cmwgPSAnaHR0cHM6Ly9leGFtcGxlLmNvbSc7XG5cdCAgICAgICAgICogICAgICAgICBjb25zdCBlbGVtZW50SWQgPSAndmlldy1jb250YWluZXInO1xuXHQgICAgICAgICAqICAgICAgICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsZW1lbnRJZCk7XG5cdCAgICAgICAgICogICAgICAgICBjb25zdCB2aWV3ID0gYXdhaXQgZmluLlZpZXcuY3JlYXRlKHtcblx0ICAgICAgICAgKiAgICAgICAgICAgICBuYW1lOiAnbXktdmlldycsXG5cdCAgICAgICAgICogICAgICAgICAgICAgdXJsLFxuXHQgICAgICAgICAqICAgICAgICAgICAgIHRhcmdldDogZmluLm1lLmlkZW50aXR5XG5cdCAgICAgICAgICogICAgICAgICB9KTtcblx0ICAgICAgICAgKiAgICAgICAgIGF3YWl0IHZpZXcubmF2aWdhdGUodXJsKTtcblx0ICAgICAgICAgKiAgICAgICAgIGF3YWl0IHZpZXcuYmluZFRvRWxlbWVudChlbGVtZW50KTtcblx0ICAgICAgICAgKiAgICAgfVxuXHQgICAgICAgICAqICAgICBjcmVhdGVBbmRBdHRhY2hWaWV3KCkuY2F0Y2goY29uc29sZS5lcnJvcik7XG5cdCAgICAgICAgICogPC9zY3JpcHQ+XG5cdCAgICAgICAgICogYGBgXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdGhpcy5iaW5kVG9FbGVtZW50ID0gYXN5bmMgKGVsZW1lbnQpID0+IHtcblx0ICAgICAgICAgICAgaWYgKCFlbGVtZW50KSB7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0VsZW1lbnQgbm90IGZvdW5kLicpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNvbnN0IG9uQ2hhbmdlID0gYXN5bmMgKGJvdW5kcykgPT4gdGhpcy5zZXRCb3VuZHMoYm91bmRzKTtcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5lbnZpcm9ubWVudC5vYnNlcnZlQm91bmRzKGVsZW1lbnQsIG9uQ2hhbmdlKTtcblx0ICAgICAgICB9O1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBGb2N1c2VzIHRoZSB2aWV3XG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCB2aWV3ID0gZmluLlZpZXcud3JhcFN5bmMoeyB1dWlkOiAndmlld1V1aWQnLCBuYW1lOiAndmlld05hbWUnIH0pO1xuXHQgICAgICogYXdhaXQgdmlldy5mb2N1cygpO1xuXHQgICAgICogLy8gZG8gdGhpbmdzIHdpdGggdGhlIGZvY3VzZWQgdmlld1xuXHQgICAgICogYGBgXG5cdCAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGZvY3VzKHsgZW1pdFN5bnRoRm9jdXNlZCB9ID0geyBlbWl0U3ludGhGb2N1c2VkOiB0cnVlIH0pIHtcblx0ICAgICAgICBjb25zdCB3aW4gPSBhd2FpdCB0aGlzLmdldEN1cnJlbnRXaW5kb3coKTtcblx0ICAgICAgICBhd2FpdCB3aW4uZm9jdXNlZFdlYlZpZXdXYXNDaGFuZ2VkKCk7XG5cdCAgICAgICAgYXdhaXQgc3VwZXIuZm9jdXMoeyBlbWl0U3ludGhGb2N1c2VkIH0pO1xuXHQgICAgfVxuXHR9XG5cdEluc3RhbmNlJDUuVmlldyA9IFZpZXc7XG5cdF9WaWV3X3Byb3ZpZGVyQ2hhbm5lbENsaWVudCA9IG5ldyBXZWFrTWFwKCk7XG5cdHJldHVybiBJbnN0YW5jZSQ1O1xufVxuXG52YXIgaGFzUmVxdWlyZWRWaWV3O1xuXG5mdW5jdGlvbiByZXF1aXJlVmlldyAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZFZpZXcpIHJldHVybiB2aWV3O1xuXHRoYXNSZXF1aXJlZFZpZXcgPSAxO1xuXHQoZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0XHR2YXIgX19jcmVhdGVCaW5kaW5nID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY3JlYXRlQmluZGluZykgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0XHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0XHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHRcdCAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xuXHRcdCAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XG5cdFx0ICAgIH1cblx0XHQgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcblx0XHR9KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHRcdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHRcdCAgICBvW2syXSA9IG1ba107XG5cdFx0fSkpO1xuXHRcdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdFx0ICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZXhwb3J0cywgcCkpIF9fY3JlYXRlQmluZGluZyhleHBvcnRzLCBtLCBwKTtcblx0XHR9O1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0XHQvKipcblx0XHQgKiBFbnRyeSBwb2ludHMgZm9yIHRoZSBPcGVuRmluIGBWaWV3YCBBUEkgKGBmaW4uVmlld2ApLlxuXHRcdCAqXG5cdFx0ICogKiB7QGxpbmsgVmlld01vZHVsZX0gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBWaWV3YCBBUEksIGFjY2Vzc2libGUgdGhyb3VnaCBgZmluLlZpZXdgLlxuXHRcdCAqICoge0BsaW5rIFZpZXd9IGRlc2NyaWJlcyBhbiBpbnN0YW5jZSBvZiBhbiBPcGVuRmluIFZpZXcsIGUuZy4gYXMgcmV0dXJuZWQgYnkgYGZpbi5WaWV3LmdldEN1cnJlbnRgLlxuXHRcdCAqXG5cdFx0ICogVGhlc2UgYXJlIHNlcGFyYXRlIGNvZGUgZW50aXRpZXMsIGFuZCBhcmUgZG9jdW1lbnRlZCBzZXBhcmF0ZWx5LiAgSW4gdGhlIFtwcmV2aW91cyB2ZXJzaW9uIG9mIHRoZSBBUEkgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvMzIuMTE0Ljc2LjEwL2luZGV4Lmh0bWwpLFxuXHRcdCAqIGJvdGggb2YgdGhlc2Ugd2VyZSBkb2N1bWVudGVkIG9uIHRoZSBzYW1lIHBhZ2UuXG5cdFx0ICpcblx0XHQgKiBAcGFja2FnZURvY3VtZW50YXRpb25cblx0XHQgKi9cblx0XHRfX2V4cG9ydFN0YXIocmVxdWlyZUZhY3RvcnkkMygpLCBleHBvcnRzKTtcblx0XHRfX2V4cG9ydFN0YXIocmVxdWlyZUluc3RhbmNlJDIoKSwgZXhwb3J0cyk7IFxuXHR9ICh2aWV3KSk7XG5cdHJldHVybiB2aWV3O1xufVxuXG52YXIgaGFzUmVxdWlyZWRJbnN0YW5jZSQxO1xuXG5mdW5jdGlvbiByZXF1aXJlSW5zdGFuY2UkMSAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEluc3RhbmNlJDEpIHJldHVybiBJbnN0YW5jZSQ2O1xuXHRoYXNSZXF1aXJlZEluc3RhbmNlJDEgPSAxO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoSW5zdGFuY2UkNiwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdEluc3RhbmNlJDYuQXBwbGljYXRpb24gPSB2b2lkIDA7XG5cdC8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9wcmVmZXItZGVmYXVsdC1leHBvcnQgKi9cblx0Y29uc3QgYmFzZV8xID0gYmFzZTtcblx0Y29uc3Qgd2luZG93XzEgPSByZXF1aXJlV2luZG93KCk7XG5cdGNvbnN0IHZpZXdfMSA9IHJlcXVpcmVWaWV3KCk7XG5cdC8qKlxuXHQgKiBBbiBvYmplY3QgcmVwcmVzZW50aW5nIGFuIGFwcGxpY2F0aW9uLiBBbGxvd3MgdGhlIGRldmVsb3BlciB0byBjcmVhdGUsXG5cdCAqIGV4ZWN1dGUsIHNob3cvY2xvc2UgYW4gYXBwbGljYXRpb24gYXMgd2VsbCBhcyBsaXN0ZW4gdG8ge0BsaW5rIE9wZW5GaW4uQXBwbGljYXRpb25FdmVudHMgYXBwbGljYXRpb24gZXZlbnRzfS5cblx0ICovXG5cdGNsYXNzIEFwcGxpY2F0aW9uIGV4dGVuZHMgYmFzZV8xLkVtaXR0ZXJCYXNlIHtcblx0ICAgIC8qKlxuXHQgICAgICogQGludGVybmFsXG5cdCAgICAgKi9cblx0ICAgIGNvbnN0cnVjdG9yKHdpcmUsIGlkZW50aXR5KSB7XG5cdCAgICAgICAgc3VwZXIod2lyZSwgJ2FwcGxpY2F0aW9uJywgaWRlbnRpdHkudXVpZCk7XG5cdCAgICAgICAgdGhpcy5pZGVudGl0eSA9IGlkZW50aXR5O1xuXHQgICAgICAgIHRoaXMud2luZG93ID0gbmV3IHdpbmRvd18xLl9XaW5kb3codGhpcy53aXJlLCB7XG5cdCAgICAgICAgICAgIHV1aWQ6IHRoaXMuaWRlbnRpdHkudXVpZCxcblx0ICAgICAgICAgICAgbmFtZTogdGhpcy5pZGVudGl0eS51dWlkXG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdCAgICB3aW5kb3dMaXN0RnJvbUlkZW50aXR5TGlzdChpZGVudGl0eUxpc3QpIHtcblx0ICAgICAgICBjb25zdCB3aW5kb3dMaXN0ID0gW107XG5cdCAgICAgICAgaWRlbnRpdHlMaXN0LmZvckVhY2goKGlkZW50aXR5KSA9PiB7XG5cdCAgICAgICAgICAgIHdpbmRvd0xpc3QucHVzaChuZXcgd2luZG93XzEuX1dpbmRvdyh0aGlzLndpcmUsIHtcblx0ICAgICAgICAgICAgICAgIHV1aWQ6IGlkZW50aXR5LnV1aWQsXG5cdCAgICAgICAgICAgICAgICBuYW1lOiBpZGVudGl0eS5uYW1lXG5cdCAgICAgICAgICAgIH0pKTtcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gd2luZG93TGlzdDtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogRGV0ZXJtaW5lcyBpZiB0aGUgYXBwbGljYXRpb24gaXMgY3VycmVudGx5IHJ1bm5pbmcuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gaXNBcHBSdW5uaW5nKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5pc1J1bm5pbmcoKTtcblx0ICAgICAqIH1cblx0ICAgICAqIGlzQXBwUnVubmluZygpLnRoZW4ocnVubmluZyA9PiBjb25zb2xlLmxvZyhgQ3VycmVudCBhcHAgaXMgcnVubmluZzogJHtydW5uaW5nfWApKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgaXNSdW5uaW5nKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignaXMtYXBwbGljYXRpb24tcnVubmluZycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBDbG9zZXMgdGhlIGFwcGxpY2F0aW9uIGFuZCBhbnkgY2hpbGQgd2luZG93cyBjcmVhdGVkIGJ5IHRoZSBhcHBsaWNhdGlvbi5cblx0ICAgICAqIENsZWFucyB0aGUgYXBwbGljYXRpb24gZnJvbSBzdGF0ZSBzbyBpdCBpcyBubyBsb25nZXIgZm91bmQgaW4gZ2V0QWxsQXBwbGljYXRpb25zLlxuXHQgICAgICogQHBhcmFtIGZvcmNlIENsb3NlIHdpbGwgYmUgcHJldmVudGVkIGZyb20gY2xvc2luZyB3aGVuIGZvcmNlIGlzIGZhbHNlIGFuZFxuXHQgICAgICogIOKAmGNsb3NlLXJlcXVlc3RlZOKAmSBoYXMgYmVlbiBzdWJzY3JpYmVkIHRvIGZvciBhcHBsaWNhdGlvbuKAmXMgbWFpbiB3aW5kb3cuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY2xvc2VBcHAoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYWxsQXBwczEgPSBhd2FpdCBmaW4uU3lzdGVtLmdldEFsbEFwcGxpY2F0aW9ucygpOyAvL1t7dXVpZDogJ2FwcDEnLCBpc1J1bm5pbmc6IHRydWV9LCB7dXVpZDogJ2FwcDInLCBpc1J1bm5pbmc6IHRydWV9XVxuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi53cmFwKHt1dWlkOiAnYXBwMid9KTtcblx0ICAgICAqICAgICBhd2FpdCBhcHAucXVpdCgpO1xuXHQgICAgICogICAgIGNvbnN0IGFsbEFwcHMyID0gYXdhaXQgZmluLlN5c3RlbS5nZXRBbGxBcHBsaWNhdGlvbnMoKTsgLy9be3V1aWQ6ICdhcHAxJywgaXNSdW5uaW5nOiB0cnVlfV1cblx0ICAgICAqXG5cdCAgICAgKiB9XG5cdCAgICAgKiBjbG9zZUFwcCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0FwcGxpY2F0aW9uIHF1aXQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHF1aXQoZm9yY2UgPSBmYWxzZSkge1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIGF3YWl0IHRoaXMuX2Nsb3NlKGZvcmNlKTtcblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2Rlc3Ryb3ktYXBwbGljYXRpb24nLCB7IGZvcmNlLCAuLi50aGlzLmlkZW50aXR5IH0pO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc3QgYWNjZXB0YWJsZUVycm9ycyA9IFsnUmVtb3RlIGNvbm5lY3Rpb24gaGFzIGNsb3NlZCcsICdDb3VsZCBub3QgbG9jYXRlIHRoZSByZXF1ZXN0ZWQgYXBwbGljYXRpb24nXTtcblx0ICAgICAgICAgICAgaWYgKCFhY2NlcHRhYmxlRXJyb3JzLnNvbWUoKG1zZykgPT4gZXJyb3IubWVzc2FnZS5pbmNsdWRlcyhtc2cpKSkge1xuXHQgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICBhc3luYyBfY2xvc2UoZm9yY2UgPSBmYWxzZSkge1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjbG9zZS1hcHBsaWNhdGlvbicsIHsgZm9yY2UsIC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBpZiAoIWVycm9yLm1lc3NhZ2UuaW5jbHVkZXMoJ1JlbW90ZSBjb25uZWN0aW9uIGhhcyBjbG9zZWQnKSkge1xuXHQgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEBkZXByZWNhdGVkIHVzZSBBcHBsaWNhdGlvbi5xdWl0IGluc3RlYWRcblx0ICAgICAqIENsb3NlcyB0aGUgYXBwbGljYXRpb24gYW5kIGFueSBjaGlsZCB3aW5kb3dzIGNyZWF0ZWQgYnkgdGhlIGFwcGxpY2F0aW9uLlxuXHQgICAgICogQHBhcmFtIGZvcmNlIC0gQ2xvc2Ugd2lsbCBiZSBwcmV2ZW50ZWQgZnJvbSBjbG9zaW5nIHdoZW4gZm9yY2UgaXMgZmFsc2UgYW5kIOKAmGNsb3NlLXJlcXVlc3RlZOKAmSBoYXMgYmVlbiBzdWJzY3JpYmVkIHRvIGZvciBhcHBsaWNhdGlvbuKAmXMgbWFpbiB3aW5kb3cuXG5cdCAgICAgKiBAcGFyYW0gY2FsbGJhY2sgLSBjYWxsZWQgaWYgdGhlIG1ldGhvZCBzdWNjZWVkcy5cblx0ICAgICAqIEBwYXJhbSBlcnJvckNhbGxiYWNrIC0gY2FsbGVkIGlmIHRoZSBtZXRob2QgZmFpbHMuIFRoZSByZWFzb24gZm9yIGZhaWx1cmUgaXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNsb3NlQXBwKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5jbG9zZSgpO1xuXHQgICAgICogfVxuXHQgICAgICogY2xvc2VBcHAoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdBcHBsaWNhdGlvbiBjbG9zZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGNsb3NlKGZvcmNlID0gZmFsc2UpIHtcblx0ICAgICAgICBjb25zb2xlLndhcm4oJ0RlcHJlY2F0aW9uIFdhcm5pbmc6IEFwcGxpY2F0aW9uLmNsb3NlIGlzIGRlcHJlY2F0ZWQgUGxlYXNlIHVzZSBBcHBsaWNhdGlvbi5xdWl0Jyk7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2FwcGxpY2F0aW9uLWNsb3NlJywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuX2Nsb3NlKGZvcmNlKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIGFuIGFycmF5IG9mIHdyYXBwZWQgZmluLldpbmRvd3MgZm9yIGVhY2ggb2YgdGhlIGFwcGxpY2F0aW9u4oCZcyBjaGlsZCB3aW5kb3dzLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldENoaWxkV2luZG93cygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0Q2hpbGRXaW5kb3dzKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0Q2hpbGRXaW5kb3dzKCkudGhlbihjaGlsZHJlbiA9PiBjb25zb2xlLmxvZyhjaGlsZHJlbikpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRDaGlsZFdpbmRvd3MoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtY2hpbGQtd2luZG93cycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiB7XG5cdCAgICAgICAgICAgIGNvbnN0IGlkZW50aXR5TGlzdCA9IFtdO1xuXHQgICAgICAgICAgICBwYXlsb2FkLmRhdGEuZm9yRWFjaCgod2luTmFtZSkgPT4ge1xuXHQgICAgICAgICAgICAgICAgaWRlbnRpdHlMaXN0LnB1c2goeyB1dWlkOiB0aGlzLmlkZW50aXR5LnV1aWQsIG5hbWU6IHdpbk5hbWUgfSk7XG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy53aW5kb3dMaXN0RnJvbUlkZW50aXR5TGlzdChpZGVudGl0eUxpc3QpO1xuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXRyaWV2ZXMgdGhlIEpTT04gbWFuaWZlc3QgdGhhdCB3YXMgdXNlZCB0byBjcmVhdGUgdGhlIGFwcGxpY2F0aW9uLiBJbnZva2VzIHRoZSBlcnJvciBjYWxsYmFja1xuXHQgICAgICogaWYgdGhlIGFwcGxpY2F0aW9uIHdhcyBub3QgY3JlYXRlZCBmcm9tIGEgbWFuaWZlc3QuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0TWFuaWZlc3QoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldE1hbmlmZXN0KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0TWFuaWZlc3QoKS50aGVuKG1hbmlmZXN0ID0+IGNvbnNvbGUubG9nKG1hbmlmZXN0KSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldE1hbmlmZXN0KCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWFwcGxpY2F0aW9uLW1hbmlmZXN0JywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyBVVUlEIG9mIHRoZSBhcHBsaWNhdGlvbiB0aGF0IGxhdW5jaGVzIHRoaXMgYXBwbGljYXRpb24uIEludm9rZXMgdGhlIGVycm9yIGNhbGxiYWNrXG5cdCAgICAgKiBpZiB0aGUgYXBwbGljYXRpb24gd2FzIGNyZWF0ZWQgZnJvbSBhIG1hbmlmZXN0LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFBhcmVudFV1aWQoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLUFwcGxpY2F0aW9uLmdldFBhcmVudFV1aWQuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRQYXJlbnRVdWlkKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0UGFyZW50VXVpZCgpLnRoZW4ocGFyZW50VXVpZCA9PiBjb25zb2xlLmxvZyhwYXJlbnRVdWlkKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldFBhcmVudFV1aWQoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtcGFyZW50LWFwcGxpY2F0aW9uJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyBjdXJyZW50IGFwcGxpY2F0aW9uJ3Mgc2hvcnRjdXQgY29uZmlndXJhdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRTaG9ydGN1dHMoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLndyYXAoeyB1dWlkOiAndGVzdGFwcCcgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRTaG9ydGN1dHMoKTtcblx0ICAgICAqIH1cblx0ICAgICAqIGdldFNob3J0Y3V0cygpLnRoZW4oY29uZmlnID0+IGNvbnNvbGUubG9nKGNvbmZpZykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRTaG9ydGN1dHMoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtc2hvcnRjdXRzJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyBjdXJyZW50IGFwcGxpY2F0aW9uJ3Mgdmlld3MuXG5cdCAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0Vmlld3MoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFZpZXdzKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKiBnZXRWaWV3cygpLnRoZW4odmlld3MgPT4gY29uc29sZS5sb2codmlld3MpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0Vmlld3MoKSB7XG5cdCAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignYXBwbGljYXRpb24tZ2V0LXZpZXdzJywgdGhpcy5pZGVudGl0eSk7XG5cdCAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YS5tYXAoKGlkKSA9PiBuZXcgdmlld18xLlZpZXcodGhpcy53aXJlLCBpZCkpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHpvb20gbGV2ZWwgb2YgdGhlIGFwcGxpY2F0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFpvb21MZXZlbCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0Wm9vbUxldmVsKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0Wm9vbUxldmVsKCkudGhlbih6b29tTGV2ZWwgPT4gY29uc29sZS5sb2coem9vbUxldmVsKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldFpvb21MZXZlbCgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1hcHBsaWNhdGlvbi16b29tLWxldmVsJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgYW4gaW5zdGFuY2Ugb2YgdGhlIG1haW4gV2luZG93IG9mIHRoZSBhcHBsaWNhdGlvblxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFdpbmRvdygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtQXBwbGljYXRpb24uZ2V0V2luZG93Lmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0V2luZG93KCkudGhlbih3aW4gPT4ge1xuXHQgICAgICogICAgIHdpbi5zaG93QXQoMCwgNDAwKTtcblx0ICAgICAqICAgICB3aW4uZmxhc2goKTtcblx0ICAgICAqIH0pLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRXaW5kb3coKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2FwcGxpY2F0aW9uLWdldC13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMud2luZG93KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogTWFudWFsbHkgcmVnaXN0ZXJzIGEgdXNlciB3aXRoIHRoZSBsaWNlbnNpbmcgc2VydmljZS4gVGhlIG9ubHkgZGF0YSBzZW50IGJ5IHRoaXMgY2FsbCBpcyB1c2VyTmFtZSBhbmQgYXBwTmFtZS5cblx0ICAgICAqIEBwYXJhbSB1c2VyTmFtZSAtIHVzZXJuYW1lIHRvIGJlIHBhc3NlZCB0byB0aGUgUlZNLlxuXHQgICAgICogQHBhcmFtIGFwcE5hbWUgLSBhcHAgbmFtZSB0byBiZSBwYXNzZWQgdG8gdGhlIFJWTS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiByZWdpc3RlclVzZXIoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLnJlZ2lzdGVyVXNlcigndXNlcicsICdteUFwcCcpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHJlZ2lzdGVyVXNlcigpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1N1Y2Nlc3NmdWxseSByZWdpc3RlcmVkIHRoZSB1c2VyJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICByZWdpc3RlclVzZXIodXNlck5hbWUsIGFwcE5hbWUpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3JlZ2lzdGVyLXVzZXInLCB7IHVzZXJOYW1lLCBhcHBOYW1lLCAuLi50aGlzLmlkZW50aXR5IH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVtb3ZlcyB0aGUgYXBwbGljYXRpb27igJlzIGljb24gZnJvbSB0aGUgdHJheS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiByZW1vdmVUcmF5SWNvbigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudCgpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAucmVtb3ZlVHJheUljb24oKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiByZW1vdmVUcmF5SWNvbigpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1JlbW92ZWQgdGhlIHRyYXkgaWNvbi4nKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHJlbW92ZVRyYXlJY29uKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigncmVtb3ZlLXRyYXktaWNvbicsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVzdGFydHMgdGhlIGFwcGxpY2F0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHJlc3RhcnRBcHAoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLnJlc3RhcnQoKTtcblx0ICAgICAqIH1cblx0ICAgICAqIHJlc3RhcnRBcHAoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdBcHBsaWNhdGlvbiByZXN0YXJ0ZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHJlc3RhcnQoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdyZXN0YXJ0LWFwcGxpY2F0aW9uJywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBERVBSRUNBVEVEIG1ldGhvZCB0byBydW4gdGhlIGFwcGxpY2F0aW9uLlxuXHQgICAgICogTmVlZGVkIHdoZW4gc3RhcnRpbmcgYXBwbGljYXRpb24gdmlhIHtAbGluayBBcHBsaWNhdGlvbi5jcmVhdGV9LCBidXQgTk9UIG5lZWRlZCB3aGVuIHN0YXJ0aW5nIHZpYSB7QGxpbmsgQXBwbGljYXRpb24uc3RhcnR9LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHJ1bigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uY3JlYXRlKHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLUFwcGxpY2F0aW9uLnJ1bi5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBhd2FpdCBhcHAucnVuKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKiBydW4oKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdBcHBsaWNhdGlvbiBpcyBydW5uaW5nJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqIEBpZ25vcmVcblx0ICAgICAqL1xuXHQgICAgcnVuKCkge1xuXHQgICAgICAgIGNvbnNvbGUud2FybignRGVwcmVjYXRpb24gV2FybmluZzogQXBwbGljYXRpb24ucnVuIGlzIGRlcHJlY2F0ZWQgUGxlYXNlIHVzZSBmaW4uQXBwbGljYXRpb24uc3RhcnQnKTtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignYXBwbGljYXRpb24tcnVuJywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuX3J1bigpO1xuXHQgICAgfVxuXHQgICAgX3J1bihvcHRzID0ge30pIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlXG5cdCAgICAgICAgICAgIC5zZW5kQWN0aW9uKCdydW4tYXBwbGljYXRpb24nLCB7XG5cdCAgICAgICAgICAgIG1hbmlmZXN0VXJsOiB0aGlzLl9tYW5pZmVzdFVybCxcblx0ICAgICAgICAgICAgb3B0cyxcblx0ICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuXHQgICAgICAgIH0pXG5cdCAgICAgICAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEluc3RydWN0cyB0aGUgUlZNIHRvIHNjaGVkdWxlIG9uZSByZXN0YXJ0IG9mIHRoZSBhcHBsaWNhdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBzY2hlZHVsZVJlc3RhcnQoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLnNjaGVkdWxlUmVzdGFydCgpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHNjaGVkdWxlUmVzdGFydCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0FwcGxpY2F0aW9uIGlzIHNjaGVkdWxlZCB0byByZXN0YXJ0JykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBzY2hlZHVsZVJlc3RhcnQoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdyZWxhdW5jaC1vbi1jbG9zZScsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2VuZHMgYSBtZXNzYWdlIHRvIHRoZSBSVk0gdG8gdXBsb2FkIHRoZSBhcHBsaWNhdGlvbidzIGxvZ3MuIE9uIHN1Y2Nlc3MsXG5cdCAgICAgKiBhbiBvYmplY3QgY29udGFpbmluZyBsb2dJZCBpcyByZXR1cm5lZC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBzZW5kTG9nKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5zZW5kQXBwbGljYXRpb25Mb2coKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBzZW5kTG9nKCkudGhlbihpbmZvID0+IGNvbnNvbGUubG9nKGluZm8ubG9nSWQpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgc2VuZEFwcGxpY2F0aW9uTG9nKCkge1xuXHQgICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NlbmQtYXBwbGljYXRpb24tbG9nJywgdGhpcy5pZGVudGl0eSk7XG5cdCAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2V0cyBvciByZW1vdmVzIGEgY3VzdG9tIEp1bXBMaXN0IGZvciB0aGUgYXBwbGljYXRpb24uIE9ubHkgYXBwbGljYWJsZSBpbiBXaW5kb3dzIE9TLlxuXHQgICAgICogSWYgY2F0ZWdvcmllcyBpcyBudWxsIHRoZSBwcmV2aW91c2x5IHNldCBjdXN0b20gSnVtcExpc3QgKGlmIGFueSkgd2lsbCBiZSByZXBsYWNlZCBieSB0aGUgc3RhbmRhcmQgSnVtcExpc3QgZm9yIHRoZSBhcHAgKG1hbmFnZWQgYnkgV2luZG93cykuXG5cdCAgICAgKlxuXHQgICAgICogTm90ZTogSWYgdGhlIFwibmFtZVwiIHByb3BlcnR5IGlzIG9taXR0ZWQgaXQgZGVmYXVsdHMgdG8gXCJ0YXNrc1wiLlxuXHQgICAgICogQHBhcmFtIGp1bXBMaXN0Q2F0ZWdvcmllcyBBbiBhcnJheSBvZiBKdW1wTGlzdCBDYXRlZ29yaWVzIHRvIHBvcHVsYXRlLiBJZiBudWxsLCByZW1vdmUgYW55IGV4aXN0aW5nIEp1bXBMaXN0IGNvbmZpZ3VyYXRpb24gYW5kIHNldCB0byBXaW5kb3dzIGRlZmF1bHQuXG5cdCAgICAgKlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIElmIGNhdGVnb3JpZXMgaXMgbnVsbCB0aGUgcHJldmlvdXNseSBzZXQgY3VzdG9tIEp1bXBMaXN0IChpZiBhbnkpIHdpbGwgYmUgcmVwbGFjZWQgYnkgdGhlIHN0YW5kYXJkIEp1bXBMaXN0IGZvciB0aGUgYXBwIChtYW5hZ2VkIGJ5IFdpbmRvd3MpLlxuXHQgICAgICpcblx0ICAgICAqIFRoZSBib3R0b21tb3N0IGl0ZW0gaW4gdGhlIGp1bXBsaXN0IHdpbGwgYWx3YXlzIGJlIGFuIGl0ZW0gcG9pbnRpbmcgdG8gdGhlIGN1cnJlbnQgYXBwLiBJdHMgbmFtZSBpcyB0YWtlbiBmcm9tIHRoZSBtYW5pZmVzdCdzXG5cdCAgICAgKiAqKmAgc2hvcnRjdXQubmFtZSBgKiogYW5kIHVzZXMgKipgIHNob3J0Y3V0LmNvbXBhbnkgYCoqIGFzIGEgZmFsbGJhY2suIENsaWNraW5nIHRoYXQgaXRlbSB3aWxsIGxhdW5jaCB0aGUgYXBwIGZyb20gaXRzIGN1cnJlbnQgbWFuaWZlc3QuXG5cdCAgICAgKlxuXHQgICAgICogTm90ZTogSWYgdGhlIFwibmFtZVwiIHByb3BlcnR5IGlzIG9taXR0ZWQgaXQgZGVmYXVsdHMgdG8gXCJ0YXNrc1wiLlxuXHQgICAgICpcblx0ICAgICAqIE5vdGU6IFdpbmRvdyBPUyBjYWNoZXMganVtcGxpc3RzIGljb25zLCB0aGVyZWZvcmUgYW4gaWNvbiBjaGFuZ2UgbWlnaHQgb25seSBiZSB2aXNpYmxlIGFmdGVyIHRoZSBjYWNoZSBpcyByZW1vdmVkIG9yIHRoZVxuXHQgICAgICogdXVpZCBvciBzaG9ydGN1dC5uYW1lIGlzIGNoYW5nZWQuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50U3luYygpO1xuXHQgICAgICogICAgIGNvbnN0IGFwcE5hbWUgPSAnTXkgQXBwJztcblx0ICAgICAqICAgICBjb25zdCBqdW1wTGlzdENvbmZpZyA9IFsgLy8gYXJyYXkgb2YgSnVtcExpc3QgY2F0ZWdvcmllc1xuXHQgICAgICogICAgICAgICB7XG5cdCAgICAgKiAgICAgICAgICAgICAvLyBoYXMgbm8gbmFtZSBhbmQgbm8gdHlwZSBzbyBgdHlwZWAgaXMgYXNzdW1lZCB0byBiZSBcInRhc2tzXCJcblx0ICAgICAqICAgICAgICAgICAgIGl0ZW1zOiBbIC8vIGFycmF5IG9mIEp1bXBMaXN0IGl0ZW1zXG5cdCAgICAgKiAgICAgICAgICAgICB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgdHlwZTogJ3Rhc2snLFxuXHQgICAgICogICAgICAgICAgICAgICAgIHRpdGxlOiBgTGF1bmNoICR7YXBwTmFtZX1gLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgUnVucyAke2FwcE5hbWV9IHdpdGggdGhlIGRlZmF1bHQgY29uZmlndXJhdGlvbmAsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgZGVlcExpbms6ICdmaW5zOi8vcGF0aC50by9hcHAvbWFuaWZlc3QuanNvbicsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgaWNvblBhdGg6ICdodHRwczovL3BhdGgudG8vYXBwL2ljb24uaWNvJyxcblx0ICAgICAqICAgICAgICAgICAgICAgICBpY29uSW5kZXg6IDBcblx0ICAgICAqICAgICAgICAgICAgIH0sXG5cdCAgICAgKiAgICAgICAgICAgICB7IHR5cGU6ICdzZXBhcmF0b3InIH0sXG5cdCAgICAgKiAgICAgICAgICAgICB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgdHlwZTogJ3Rhc2snLFxuXHQgICAgICogICAgICAgICAgICAgICAgIHRpdGxlOiBgUmVzdG9yZSAke2FwcE5hbWV9YCxcblx0ICAgICAqICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogJ1Jlc3RvcmUgdG8gbGFzdCBjb25maWd1cmF0aW9uJyxcblx0ICAgICAqICAgICAgICAgICAgICAgICBkZWVwTGluazogJ2ZpbnM6Ly9wYXRoLnRvL2FwcC9tYW5pZmVzdC5qc29uPyQkdXNlLWxhc3QtY29uZmlndXJhdGlvbj10cnVlJyxcblx0ICAgICAqICAgICAgICAgICAgICAgICBpY29uUGF0aDogJ2h0dHBzOi8vcGF0aC50by9hcHAvaWNvbi5pY28nLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGljb25JbmRleDogMFxuXHQgICAgICogICAgICAgICAgICAgfSxcblx0ICAgICAqICAgICAgICAgICAgIF1cblx0ICAgICAqICAgICAgICAgfSxcblx0ICAgICAqICAgICAgICAge1xuXHQgICAgICogICAgICAgICAgICAgbmFtZTogJ1Rvb2xzJyxcblx0ICAgICAqICAgICAgICAgICAgIGl0ZW1zOiBbIC8vIGFycmF5IG9mIEp1bXBMaXN0IGl0ZW1zXG5cdCAgICAgKiAgICAgICAgICAgICB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgdHlwZTogJ3Rhc2snLFxuXHQgICAgICogICAgICAgICAgICAgICAgIHRpdGxlOiAnVG9vbCBBJyxcblx0ICAgICAqICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogJ1J1bnMgVG9vbCBBJyxcblx0ICAgICAqICAgICAgICAgICAgICAgICBkZWVwTGluazogJ2ZpbnM6Ly9wYXRoLnRvL3Rvb2wtYS9tYW5pZmVzdC5qc29uJyxcblx0ICAgICAqICAgICAgICAgICAgICAgICBpY29uUGF0aDogJ2h0dHBzOi8vcGF0aC50by90b29sLWEvaWNvbi5pY28nLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGljb25JbmRleDogMFxuXHQgICAgICogICAgICAgICAgICAgfSxcblx0ICAgICAqICAgICAgICAgICAgIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICB0eXBlOiAndGFzaycsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgdGl0bGU6ICdUb29sIEInLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnUnVucyBUb29sIEInLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGRlZXBMaW5rOiAnZmluczovL3BhdGgudG8vdG9vbC1iL21hbmlmZXN0Lmpzb24nLFxuXHQgICAgICogICAgICAgICAgICAgICAgIGljb25QYXRoOiAnaHR0cHM6Ly9wYXRoLnRvL3Rvb2wtYi9pY29uLmljbycsXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgaWNvbkluZGV4OiAwXG5cdCAgICAgKiAgICAgICAgICAgICB9XVxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgXTtcblx0ICAgICAqXG5cdCAgICAgKiAgICAgYXBwLnNldEp1bXBMaXN0KGp1bXBMaXN0Q29uZmlnKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdKdW1wTGlzdCBhcHBsaWVkJykpLmNhdGNoKGUgPT4gY29uc29sZS5sb2coYEp1bXBMaXN0IGZhaWxlZCB0byBhcHBseTogJHtlLnRvU3RyaW5nKCl9YCkpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICogVG8gaGFuZGxlIGRlZXBsaW5rIGFyZ3M6XG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogICAgIGZ1bmN0aW9uIGhhbmRsZVVzZUxhc3RDb25maWd1cmF0aW9uKCkge1xuXHQgICAgICogICAgICAgICAvLyB0aGlzIGhhbmRsZXIgaXMgY2FsbGVkIHdoZW4gdGhlIGFwcCBpcyBiZWluZyBsYXVuY2hlZFxuXHQgICAgICogICAgICAgICBhcHAub24oJ3J1bi1yZXF1ZXN0ZWQnLCBldmVudCA9PiB7XG5cdCAgICAgKiAgICAgICAgICAgICBpZihldmVudC51c2VyQXBwQ29uZmlnQXJnc1sndXNlLWxhc3QtY29uZmlndXJhdGlvbiddKSB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgLy8geW91ciBsb2dpYyBoZXJlXG5cdCAgICAgKiAgICAgICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIH0pO1xuXHQgICAgICogICAgICAgICAvLyB0aGlzIGhhbmRsZXIgaXMgY2FsbGVkIHdoZW4gdGhlIGFwcCB3YXMgYWxyZWFkeSBydW5uaW5nIHdoZW4gdGhlIGxhdW5jaCB3YXMgcmVxdWVzdGVkXG5cdCAgICAgKiAgICAgICAgIGZpbi5kZXNrdG9wLm1haW4oZnVuY3Rpb24oYXJncykge1xuXHQgICAgICogICAgICAgICAgICAgaWYoYXJncyAmJiBhcmdzWyd1c2UtbGFzdC1jb25maWd1cmF0aW9uJ10pIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAvLyB5b3VyIGxvZ2ljIGhlcmVcblx0ICAgICAqICAgICAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgfSk7XG5cdCAgICAgKiAgICAgfVxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHNldEp1bXBMaXN0KGp1bXBMaXN0Q2F0ZWdvcmllcykge1xuXHQgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzZXQtanVtcC1saXN0JywgeyBjb25maWc6IGp1bXBMaXN0Q2F0ZWdvcmllcywgLi4udGhpcy5pZGVudGl0eSB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQWRkcyBhIGN1c3RvbWl6YWJsZSBpY29uIGluIHRoZSBzeXN0ZW0gdHJheS4gIFRvIGxpc3RlbiBmb3IgYSBjbGljayBvbiB0aGUgaWNvbiB1c2UgdGhlIGB0cmF5LWljb24tY2xpY2tlZGAgZXZlbnQuXG5cdCAgICAgKiBAcGFyYW0gaWNvbiBJbWFnZSBVUkwgb3IgYmFzZTY0IGVuY29kZWQgc3RyaW5nIHRvIGJlIHVzZWQgYXMgdGhlIGljb25cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCBpbWFnZVVybCA9IFwiaHR0cDovL2Nkbi5vcGVuZmluLmNvL2Fzc2V0cy90ZXN0aW5nL2ljb25zL2NpcmNsZWQtZGlnaXQtb25lLnBuZ1wiO1xuXHQgICAgICogY29uc3QgYmFzZTY0RW5jb2RlZEltYWdlID0gXCJpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQWdBQUFBSUFRTUFBQUQrd1N6SUFBQUFCbEJNVkVYXFxcblx0ICAgICAqIC8vLysvdjcralEzWTVBQUFBRGtsRVFWUUkxMlA0QUlYOEVBZ0FMZ0FEL2FOcGJ0RUFBQUFBU1VWT1JLNUNZSUlcIjtcblx0ICAgICAqIGNvbnN0IGRhdGFVUkwgPSBcImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQVVBQUFBRkNBWUFBQUNOYnlibEFBQUFIRWxFUVZRSTEyUDQvLzgvdzM4R0lBWERJQktFMERIXFxcblx0ICAgICAqIHhnbGpOQkFBTzlUWEwwWTRPSHdBQUFBQkpSVTVFcmtKZ2dnPT1cIjtcblx0ICAgICAqXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBzZXRUcmF5SWNvbihpY29uKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLnNldFRyYXlJY29uKGljb24pO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIC8vIHVzZSBpbWFnZSB1cmwgdG8gc2V0IHRyYXkgaWNvblxuXHQgICAgICogc2V0VHJheUljb24oaW1hZ2VVcmwpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1NldHRpbmcgdHJheSBpY29uJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqXG5cdCAgICAgKiAvLyB1c2UgYmFzZTY0IGVuY29kZWQgc3RyaW5nIHRvIHNldCB0cmF5IGljb25cblx0ICAgICAqIHNldFRyYXlJY29uKGJhc2U2NEVuY29kZWRJbWFnZSkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU2V0dGluZyB0cmF5IGljb24nKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICpcblx0ICAgICAqIC8vIHVzZSBhIGRhdGFVUkwgdG8gc2V0IHRyYXkgaWNvblxuXHQgICAgICogc2V0VHJheUljb24oZGF0YVVSTCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU2V0dGluZyB0cmF5IGljb24nKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHNldFRyYXlJY29uKGljb24pIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlXG5cdCAgICAgICAgICAgIC5zZW5kQWN0aW9uKCdzZXQtdHJheS1pY29uJywge1xuXHQgICAgICAgICAgICBlbmFibGVkSWNvbjogaWNvbixcblx0ICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuXHQgICAgICAgIH0pXG5cdCAgICAgICAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNldHMgbmV3IGFwcGxpY2F0aW9uJ3Mgc2hvcnRjdXQgY29uZmlndXJhdGlvbi4gV2luZG93cyBvbmx5LlxuXHQgICAgICogQHBhcmFtIGNvbmZpZyBOZXcgYXBwbGljYXRpb24ncyBzaG9ydGN1dCBjb25maWd1cmF0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIEFwcGxpY2F0aW9uIGhhcyB0byBiZSBsYXVuY2hlZCB3aXRoIGEgbWFuaWZlc3QgYW5kIGhhcyB0byBoYXZlIHNob3J0Y3V0IGNvbmZpZ3VyYXRpb24gKGljb24gdXJsLCBuYW1lLCBldGMuKSBpbiBpdHMgbWFuaWZlc3Rcblx0ICAgICAqIHRvIGJlIGFibGUgdG8gY2hhbmdlIHNob3J0Y3V0IHN0YXRlcy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBzZXRTaG9ydGN1dHMoY29uZmlnKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXBwLnNldFNob3J0Y3V0cyhjb25maWcpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHNldFNob3J0Y3V0cyh7XG5cdCAgICAgKiAgICAgZGVza3RvcDogdHJ1ZSxcblx0ICAgICAqICAgICBzdGFydE1lbnU6IGZhbHNlLFxuXHQgICAgICogICAgIHN5c3RlbVN0YXJ0dXA6IHRydWVcblx0ICAgICAqIH0pLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1Nob3J0Y3V0cyBhcmUgc2V0LicpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgc2V0U2hvcnRjdXRzKGNvbmZpZykge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignc2V0LXNob3J0Y3V0cycsIHsgZGF0YTogY29uZmlnLCAuLi50aGlzLmlkZW50aXR5IH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2V0cyB0aGUgcXVlcnkgc3RyaW5nIGluIGFsbCBzaG9ydGN1dHMgZm9yIHRoaXMgYXBwLiBSZXF1aXJlcyBSVk0gNS41Ky5cblx0ICAgICAqIEBwYXJhbSBxdWVyeVN0cmluZyBUaGUgbmV3IHF1ZXJ5IHN0cmluZyBmb3IgdGhpcyBhcHAncyBzaG9ydGN1dHMuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3QgbmV3UXVlcnlBcmdzID0gJ2FyZz10cnVlJmFyZzI9ZmFsc2UnO1xuXHQgICAgICogY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqIHRyeSB7XG5cdCAgICAgKiAgICAgYXdhaXQgYXBwLnNldFNob3J0Y3V0UXVlcnlQYXJhbXMobmV3UXVlcnlBcmdzKTtcblx0ICAgICAqIH0gY2F0Y2goZXJyKSB7XG5cdCAgICAgKiAgICAgY29uc29sZS5lcnJvcihlcnIpXG5cdCAgICAgKiB9XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgc2V0U2hvcnRjdXRRdWVyeVBhcmFtcyhxdWVyeVN0cmluZykge1xuXHQgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzZXQtc2hvcnRjdXQtcXVlcnktYXJncycsIHsgZGF0YTogcXVlcnlTdHJpbmcsIC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIGFwcGxpY2F0aW9uLiBUaGUgb3JpZ2luYWwgc2l6ZSBpcyAwIGFuZCBlYWNoIGluY3JlbWVudCBhYm92ZSBvciBiZWxvdyByZXByZXNlbnRzIHpvb21pbmcgMjAlXG5cdCAgICAgKiBsYXJnZXIgb3Igc21hbGxlciB0byBkZWZhdWx0IGxpbWl0cyBvZiAzMDAlIGFuZCA1MCUgb2Ygb3JpZ2luYWwgc2l6ZSwgcmVzcGVjdGl2ZWx5LlxuXHQgICAgICogQHBhcmFtIGxldmVsIFRoZSB6b29tIGxldmVsXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gc2V0Wm9vbUxldmVsKG51bWJlcikge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5zZXRab29tTGV2ZWwobnVtYmVyKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBzZXRab29tTGV2ZWwoNSkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU2V0dGluZyBhICB6b29tIGxldmVsJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBzZXRab29tTGV2ZWwobGV2ZWwpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NldC1hcHBsaWNhdGlvbi16b29tLWxldmVsJywgeyBsZXZlbCwgLi4udGhpcy5pZGVudGl0eSB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNldHMgYSB1c2VybmFtZSB0byBjb3JyZWxhdGUgd2l0aCBBcHAgTG9nIE1hbmFnZW1lbnQuXG5cdCAgICAgKiBAcGFyYW0gdXNlcm5hbWUgVXNlcm5hbWUgdG8gY29ycmVsYXRlIHdpdGggQXBwJ3MgTG9nLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNldEFwcExvZ1VzZXIoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLnNldEFwcExvZ1VzZXJuYW1lKCd1c2VybmFtZScpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHNldEFwcExvZ1VzZXIoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTdWNjZXNzJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqXG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgc2V0QXBwTG9nVXNlcm5hbWUodXNlcm5hbWUpIHtcblx0ICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc2V0LWFwcC1sb2ctdXNlcm5hbWUnLCB7IGRhdGE6IHVzZXJuYW1lLCAuLi50aGlzLmlkZW50aXR5IH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXRyaWV2ZXMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN5c3RlbSB0cmF5LiBJZiB0aGUgc3lzdGVtIHRyYXkgaXMgbm90IHNldCwgaXQgd2lsbCB0aHJvdyBhbiBlcnJvciBtZXNzYWdlLlxuXHQgICAgICogQHJlbWFya3MgVGhlIG9ubHkgaW5mb3JtYXRpb24gY3VycmVudGx5IHJldHVybmVkIGlzIHRoZSBwb3NpdGlvbiBhbmQgZGltZW5zaW9ucy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRUcmF5SWNvbkluZm8oKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLndyYXAoeyB1dWlkOiAndGVzdGFwcCcgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRUcmF5SWNvbkluZm8oKTtcblx0ICAgICAqIH1cblx0ICAgICAqIGdldFRyYXlJY29uSW5mbygpLnRoZW4oaW5mbyA9PiBjb25zb2xlLmxvZyhpbmZvKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldFRyYXlJY29uSW5mbygpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC10cmF5LWljb24taW5mbycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBDaGVja3MgaWYgdGhlIGFwcGxpY2F0aW9uIGhhcyBhbiBhc3NvY2lhdGVkIHRyYXkgaWNvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24ud3JhcCh7IHV1aWQ6ICd0ZXN0YXBwJyB9KTtcblx0ICAgICAqIGNvbnN0IGhhc1RyYXlJY29uID0gYXdhaXQgYXBwLmhhc1RyYXlJY29uKCk7XG5cdCAgICAgKiBjb25zb2xlLmxvZyhoYXNUcmF5SWNvbik7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgaGFzVHJheUljb24oKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdoYXMtdHJheS1pY29uJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIENsb3NlcyB0aGUgYXBwbGljYXRpb24gYnkgdGVybWluYXRpbmcgaXRzIHByb2Nlc3MuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gdGVybWluYXRlQXBwKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC50ZXJtaW5hdGUoKTtcblx0ICAgICAqIH1cblx0ICAgICAqIHRlcm1pbmF0ZUFwcCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0FwcGxpY2F0aW9uIHRlcm1pbmF0ZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHRlcm1pbmF0ZSgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Rlcm1pbmF0ZS1hcHBsaWNhdGlvbicsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogV2FpdHMgZm9yIGEgaGFuZ2luZyBhcHBsaWNhdGlvbi4gVGhpcyBtZXRob2QgY2FuIGJlIGNhbGxlZCBpbiByZXNwb25zZSB0byBhbiBhcHBsaWNhdGlvblxuXHQgICAgICogXCJub3QtcmVzcG9uZGluZ1wiIHRvIGFsbG93IHRoZSBhcHBsaWNhdGlvbiB0byBjb250aW51ZSBhbmQgdG8gZ2VuZXJhdGUgYW5vdGhlciBcIm5vdC1yZXNwb25kaW5nXCJcblx0ICAgICAqIG1lc3NhZ2UgYWZ0ZXIgYSBjZXJ0YWluIHBlcmlvZCBvZiB0aW1lLlxuXHQgICAgICpcblx0ICAgICAqIEBpZ25vcmVcblx0ICAgICAqL1xuXHQgICAgd2FpdCgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3dhaXQtZm9yLWh1bmctYXBwbGljYXRpb24nLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgYXBwbGljYXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgSWYgdGhlIGFwcGxpY2F0aW9uIHdhcyBub3QgbGF1bmNoZWQgZnJvbSBhIG1hbmlmZXN0LCB0aGUgY2FsbCB3aWxsIHJldHVybiB0aGUgY2xvc2VzdCBwYXJlbnQgYXBwbGljYXRpb24gYG1hbmlmZXN0YFxuXHQgICAgICogYW5kIGBtYW5pZmVzdFVybGAuICBgaW5pdGlhbE9wdGlvbnNgIHNob3dzIHRoZSBwYXJhbWV0ZXJzIHVzZWQgd2hlbiBsYXVuY2hlZCBwcm9ncmFtbWF0aWNhbGx5LCBvciB0aGUgYHN0YXJ0dXBfYXBwYCBvcHRpb25zXG5cdCAgICAgKiBpZiBsYXVuY2hlZCBmcm9tIG1hbmlmZXN0LiBUaGUgYHBhcmVudFV1aWRgIHdpbGwgYmUgdGhlIHV1aWQgb2YgdGhlIGltbWVkaWF0ZSBwYXJlbnQgKGlmIGFwcGxpY2FibGUpLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldEluZm8oKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldEluZm8oKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRJbmZvKCkudGhlbihpbmZvID0+IGNvbnNvbGUubG9nKGluZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0SW5mbygpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1pbmZvJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyBhbGwgcHJvY2VzcyBpbmZvcm1hdGlvbiBmb3IgZW50aXRpZXMgKHdpbmRvd3MgYW5kIHZpZXdzKSBhc3NvY2lhdGVkIHdpdGggYW4gYXBwbGljYXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICBjb25zdCBwcm9jZXNzSW5mbyA9IGF3YWl0IGFwcC5nZXRQcm9jZXNzSW5mbygpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKiBAZXhwZXJpbWVudGFsXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldFByb2Nlc3NJbmZvKCkge1xuXHQgICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhIH0gfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdhcHBsaWNhdGlvbi1nZXQtcHJvY2Vzcy1pbmZvJywgdGhpcy5pZGVudGl0eSk7XG5cdCAgICAgICAgcmV0dXJuIGRhdGE7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNldHMgZmlsZSBhdXRvIGRvd25sb2FkIGxvY2F0aW9uLiBJdCdzIG9ubHkgYWxsb3dlZCBpbiB0aGUgc2FtZSBhcHBsaWNhdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBOb3RlOiBUaGlzIG1ldGhvZCBpcyByZXN0cmljdGVkIGJ5IGRlZmF1bHQgYW5kIG11c3QgYmUgZW5hYmxlZCB2aWFcblx0ICAgICAqIDxhIGhyZWY9XCJodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9kb2NzL2FwaS1zZWN1cml0eVwiPkFQSSBzZWN1cml0eSBzZXR0aW5nczwvYT4uXG5cdCAgICAgKiBAcGFyYW0gZG93bmxvYWRMb2NhdGlvbiBmaWxlIGF1dG8gZG93bmxvYWQgbG9jYXRpb25cblx0ICAgICAqXG5cdCAgICAgKiBAdGhyb3dzIGlmIHNldHRpbmcgZmlsZSBhdXRvIGRvd25sb2FkIGxvY2F0aW9uIG9uIGRpZmZlcmVudCBhcHBsaWNhdGlvbnMuXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCBkb3dubG9hZExvY2F0aW9uID0gJ0M6XFxcXGRldlxcXFx0ZW1wJztcblx0ICAgICAqIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiB0cnkge1xuXHQgICAgICogICAgIGF3YWl0IGFwcC5zZXRGaWxlRG93bmxvYWRMb2NhdGlvbihkb3dubG9hZExvY2F0aW9uKTtcblx0ICAgICAqICAgICBjb25zb2xlLmxvZygnRmlsZSBkb3dubG9hZCBsb2NhdGlvbiBpcyBzZXQnKTtcblx0ICAgICAqIH0gY2F0Y2goZXJyKSB7XG5cdCAgICAgKiAgICAgY29uc29sZS5lcnJvcihlcnIpXG5cdCAgICAgKiB9XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgc2V0RmlsZURvd25sb2FkTG9jYXRpb24oZG93bmxvYWRMb2NhdGlvbikge1xuXHQgICAgICAgIGNvbnN0IHsgbmFtZSB9ID0gdGhpcy53aXJlLm1lO1xuXHQgICAgICAgIGNvbnN0IGVudGl0eUlkZW50aXR5ID0geyB1dWlkOiB0aGlzLmlkZW50aXR5LnV1aWQsIG5hbWUgfTtcblx0ICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc2V0LWZpbGUtZG93bmxvYWQtbG9jYXRpb24nLCB7IC4uLmVudGl0eUlkZW50aXR5LCBkb3dubG9hZExvY2F0aW9uIH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBHZXRzIGZpbGUgYXV0byBkb3dubG9hZCBsb2NhdGlvbi4gSXQncyBvbmx5IGFsbG93ZWQgaW4gdGhlIHNhbWUgYXBwbGljYXRpb24uIElmIGZpbGUgYXV0byBkb3dubG9hZCBsb2NhdGlvbiBpcyBub3Qgc2V0LCBpdCB3aWxsIHJldHVybiB0aGUgZGVmYXVsdCBsb2NhdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBOb3RlOiBUaGlzIG1ldGhvZCBpcyByZXN0cmljdGVkIGJ5IGRlZmF1bHQgYW5kIG11c3QgYmUgZW5hYmxlZCB2aWFcblx0ICAgICAqIDxhIGhyZWY9XCJodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9kb2NzL2FwaS1zZWN1cml0eVwiPkFQSSBzZWN1cml0eSBzZXR0aW5nczwvYT4uXG5cdCAgICAgKlxuXHQgICAgICogQHRocm93cyBpZiBnZXR0aW5nIGZpbGUgYXV0byBkb3dubG9hZCBsb2NhdGlvbiBvbiBkaWZmZXJlbnQgYXBwbGljYXRpb25zLlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqIGNvbnN0IGZpbGVEb3dubG9hZERpciA9ICBhd2FpdCBhcHAuZ2V0RmlsZURvd25sb2FkTG9jYXRpb24oKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRGaWxlRG93bmxvYWRMb2NhdGlvbigpIHtcblx0ICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgZGF0YSB9IH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWZpbGUtZG93bmxvYWQtbG9jYXRpb24nLCB0aGlzLmlkZW50aXR5KTtcblx0ICAgICAgICByZXR1cm4gZGF0YTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2hvd3MgYSBtZW51IG9uIHRoZSB0cmF5IGljb24uIFVzZSB3aXRoIHRyYXktaWNvbi1jbGlja2VkIGV2ZW50LlxuXHQgICAgICogQHBhcmFtIG9wdGlvbnNcblx0ICAgICAqIEB0eXBlUGFyYW0gRGF0YSBVc2VyLWRlZmluZWQgc2hhcGUgZm9yIGRhdGEgcmV0dXJuZWQgdXBvbiBtZW51IGl0ZW0gY2xpY2suIFNob3VsZCBiZSBhXG5cdCAgICAgKiBbdW5pb25dKGh0dHBzOi8vd3d3LnR5cGVzY3JpcHRsYW5nLm9yZy9kb2NzL2hhbmRib29rLzIvZXZlcnlkYXktdHlwZXMuaHRtbCN1bmlvbi10eXBlcylcblx0ICAgICAqIG9mIGFsbCBwb3NzaWJsZSBkYXRhIHNoYXBlcyBmb3IgdGhlIGVudGlyZSBtZW51LCBhbmQgdGhlIGNsaWNrIGhhbmRsZXIgc2hvdWxkIHByb2Nlc3Ncblx0ICAgICAqIHRoZXNlIHdpdGggYSBcInJlZHVjZXJcIiBwYXR0ZXJuLlxuXHQgICAgICogQHRocm93cyBpZiB0aGUgYXBwbGljYXRpb24gaGFzIG5vIHRyYXkgaWNvbiBzZXRcblx0ICAgICAqIEB0aHJvd3MgaWYgdGhlIHN5c3RlbSB0cmF5IGlzIGN1cnJlbnRseSBoaWRkZW5cblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IGljb25VcmwgPSAnaHR0cDovL2Nkbi5vcGVuZmluLmNvL2Fzc2V0cy90ZXN0aW5nL2ljb25zL2NpcmNsZWQtZGlnaXQtb25lLnBuZyc7XG5cdCAgICAgKiBjb25zdCBhcHAgPSBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudFN5bmMoKTtcblx0ICAgICAqXG5cdCAgICAgKiBhd2FpdCBhcHAuc2V0VHJheUljb24oaWNvblVybCk7XG5cdCAgICAgKlxuXHQgICAgICogY29uc3QgdGVtcGxhdGUgPSBbXG5cdCAgICAgKiAge1xuXHQgICAgICogICAgbGFiZWw6ICdNZW51IEl0ZW0gMScsXG5cdCAgICAgKiAgICBkYXRhOiAnaGVsbG8gZnJvbSBpdGVtIDEnXG5cdCAgICAgKiAgfSxcblx0ICAgICAqICB7IHR5cGU6ICdzZXBhcmF0b3InIH0sXG5cdCAgICAgKiAge1xuXHQgICAgICogICAgbGFiZWw6ICdNZW51IEl0ZW0gMicsXG5cdCAgICAgKiAgICB0eXBlOiAnY2hlY2tib3gnLFxuXHQgICAgICogICAgY2hlY2tlZDogdHJ1ZSxcblx0ICAgICAqICAgIGRhdGE6ICdUaGUgdXNlciBjbGlja2VkIHRoZSBjaGVja2JveCdcblx0ICAgICAqICB9LFxuXHQgICAgICogIHtcblx0ICAgICAqICAgIGxhYmVsOiAnc2VlIG1vcmUnLFxuXHQgICAgICogICAgZW5hYmxlZDogZmFsc2UsXG5cdCAgICAgKiAgICBzdWJtZW51OiBbXG5cdCAgICAgKiAgICAgIHsgbGFiZWw6ICdzdWJtZW51IDEnLCBkYXRhOiAnaGVsbG8gZnJvbSBzdWJtZW51JyB9XG5cdCAgICAgKiAgICBdXG5cdCAgICAgKiAgfVxuXHQgICAgICogXTtcblx0ICAgICAqXG5cdCAgICAgKiBhcHAuYWRkTGlzdGVuZXIoJ3RyYXktaWNvbi1jbGlja2VkJywgKGV2ZW50KSA9PiB7XG5cdCAgICAgKiAgIC8vIHJpZ2h0LWNsaWNrXG5cdCAgICAgKiAgIGlmIChldmVudC5idXR0b24gPT09IDIpIHtcblx0ICAgICAqICAgICBhcHAuc2hvd1RyYXlJY29uUG9wdXBNZW51KHsgdGVtcGxhdGUgfSkudGhlbihyID0+IHtcblx0ICAgICAqICAgICAgIGlmIChyLnJlc3VsdCA9PT0gJ2Nsb3NlZCcpIHtcblx0ICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ25vdGhpbmcgaGFwcGVuZWQnKTtcblx0ICAgICAqICAgICAgIH0gZWxzZSB7XG5cdCAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKHIuZGF0YSk7XG5cdCAgICAgKiAgICAgICB9XG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgIH1cblx0ICAgICAqIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHNob3dUcmF5SWNvblBvcHVwTWVudShvcHRpb25zKSB7XG5cdCAgICAgICAgY29uc3QgeyBuYW1lIH0gPSB0aGlzLndpcmUubWU7XG5cdCAgICAgICAgY29uc3QgZW50aXR5SWRlbnRpdHkgPSB7IHV1aWQ6IHRoaXMuaWRlbnRpdHkudXVpZCwgbmFtZSB9O1xuXHQgICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Nob3ctdHJheS1pY29uLXBvcHVwLW1lbnUnLCB7IC4uLmVudGl0eUlkZW50aXR5LCBvcHRpb25zIH0pO1xuXHQgICAgICAgIHJldHVybiBwYXlsb2FkLmRhdGE7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIENsb3NlcyB0aGUgdHJheSBpY29uIG1lbnUuXG5cdCAgICAgKlxuXHQgICAgICogQHRocm93cyBpZiB0aGUgYXBwbGljYXRpb24gaGFzIG5vIHRyYXkgaWNvbiBzZXRcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IGFwcCA9IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50U3luYygpO1xuXHQgICAgICpcblx0ICAgICAqIGF3YWl0IGFwcC5jbG9zZVRyYXlJY29uUG9wdXBNZW51KCk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgY2xvc2VUcmF5SWNvblBvcHVwTWVudSgpIHtcblx0ICAgICAgICBjb25zdCB7IG5hbWUgfSA9IHRoaXMud2lyZS5tZTtcblx0ICAgICAgICBjb25zdCBlbnRpdHlJZGVudGl0eSA9IHsgdXVpZDogdGhpcy5pZGVudGl0eS51dWlkLCBuYW1lIH07XG5cdCAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2Nsb3NlLXRyYXktaWNvbi1wb3B1cC1tZW51JywgeyAuLi5lbnRpdHlJZGVudGl0eSB9KTtcblx0ICAgIH1cblx0fVxuXHRJbnN0YW5jZSQ2LkFwcGxpY2F0aW9uID0gQXBwbGljYXRpb247XG5cdHJldHVybiBJbnN0YW5jZSQ2O1xufVxuXG52YXIgaGFzUmVxdWlyZWRGYWN0b3J5JDI7XG5cbmZ1bmN0aW9uIHJlcXVpcmVGYWN0b3J5JDIgKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRGYWN0b3J5JDIpIHJldHVybiBGYWN0b3J5JDc7XG5cdGhhc1JlcXVpcmVkRmFjdG9yeSQyID0gMTtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KEZhY3RvcnkkNywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdEZhY3RvcnkkNy5BcHBsaWNhdGlvbk1vZHVsZSA9IHZvaWQgMDtcblx0Y29uc3QgYmFzZV8xID0gYmFzZTtcblx0Y29uc3QgdmFsaWRhdGVfMSA9IHZhbGlkYXRlO1xuXHRjb25zdCBJbnN0YW5jZV8xID0gcmVxdWlyZUluc3RhbmNlJDEoKTtcblx0LyoqXG5cdCAqIFN0YXRpYyBuYW1lc3BhY2UgZm9yIE9wZW5GaW4gQVBJIG1ldGhvZHMgdGhhdCBpbnRlcmFjdCB3aXRoIHRoZSB7QGxpbmsgQXBwbGljYXRpb259IGNsYXNzLCBhdmFpbGFibGUgdW5kZXIgYGZpbi5BcHBsaWNhdGlvbmAuXG5cdCAqL1xuXHRjbGFzcyBBcHBsaWNhdGlvbk1vZHVsZSBleHRlbmRzIGJhc2VfMS5CYXNlIHtcblx0ICAgIC8qKlxuXHQgICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhbiBBUEkgaGFuZGxlIGZvciB0aGUgZ2l2ZW4gQXBwbGljYXRpb24gaWRlbnRpdHkuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgV3JhcHBpbmcgYW4gQXBwbGljYXRpb24gaWRlbnRpdHkgdGhhdCBkb2VzIG5vdCB5ZXQgZXhpc3Qgd2lsbCAqbm90KiB0aHJvdyBhbiBlcnJvciwgYW5kIGluc3RlYWRcblx0ICAgICAqIHJldHVybnMgYSBzdHViIG9iamVjdCB0aGF0IGNhbm5vdCB5ZXQgcGVyZm9ybSByZW5kZXJpbmcgdGFza3MuIFRoaXMgY2FuIGJlIHVzZWZ1bCBmb3IgcGx1bWJpbmcgZXZlbnRpbmdcblx0ICAgICAqIGZvciBhbiBBcHBsaWNhdGlvbiB0aHJvdWdob3V0IGl0cyBlbnRpcmUgbGlmZWN5Y2xlLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5BcHBsaWNhdGlvbi53cmFwKHsgdXVpZDogJ3Rlc3RhcHAnIH0pXG5cdCAgICAgKiAudGhlbihhcHAgPT4gYXBwLmlzUnVubmluZygpKVxuXHQgICAgICogLnRoZW4ocnVubmluZyA9PiBjb25zb2xlLmxvZygnQXBwbGljYXRpb24gaXMgcnVubmluZzogJyArIHJ1bm5pbmcpKVxuXHQgICAgICogLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgd3JhcChpZGVudGl0eSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd3cmFwLWFwcGxpY2F0aW9uJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgZXJyb3JNc2cgPSAoMCwgdmFsaWRhdGVfMS52YWxpZGF0ZUlkZW50aXR5KShpZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKGVycm9yTXNnKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvck1zZyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMS5BcHBsaWNhdGlvbih0aGlzLndpcmUsIGlkZW50aXR5KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGFuIEFQSSBoYW5kbGUgZm9yIHRoZSBnaXZlbiBBcHBsaWNhdGlvbiBpZGVudGl0eS5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBXcmFwcGluZyBhbiBBcHBsaWNhdGlvbiBpZGVudGl0eSB0aGF0IGRvZXMgbm90IHlldCBleGlzdCB3aWxsICpub3QqIHRocm93IGFuIGVycm9yLCBhbmQgaW5zdGVhZFxuXHQgICAgICogcmV0dXJucyBhIHN0dWIgb2JqZWN0IHRoYXQgY2Fubm90IHlldCBwZXJmb3JtIHJlbmRlcmluZyB0YXNrcy4gVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBwbHVtYmluZyBldmVudGluZ1xuXHQgICAgICogZm9yIGFuIEFwbGljYXRpb24gdGhyb3VnaG91dCBpdHMgZW50aXJlIGxpZmVjeWNsZS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCBhcHAgPSBmaW4uQXBwbGljYXRpb24ud3JhcFN5bmMoeyB1dWlkOiAndGVzdGFwcCcgfSk7XG5cdCAgICAgKiBhd2FpdCBhcHAuY2xvc2UoKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqL1xuXHQgICAgd3JhcFN5bmMoaWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignd3JhcC1hcHBsaWNhdGlvbi1zeW5jJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgZXJyb3JNc2cgPSAoMCwgdmFsaWRhdGVfMS52YWxpZGF0ZUlkZW50aXR5KShpZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKGVycm9yTXNnKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvck1zZyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMS5BcHBsaWNhdGlvbih0aGlzLndpcmUsIGlkZW50aXR5KTtcblx0ICAgIH1cblx0ICAgIGFzeW5jIF9jcmVhdGUoYXBwT3B0aW9ucykge1xuXHQgICAgICAgIC8vIHNldCBkZWZhdWx0czpcblx0ICAgICAgICBpZiAoYXBwT3B0aW9ucy53YWl0Rm9yUGFnZUxvYWQgPT09IHVuZGVmaW5lZCkge1xuXHQgICAgICAgICAgICBhcHBPcHRpb25zLndhaXRGb3JQYWdlTG9hZCA9IGZhbHNlO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBpZiAoYXBwT3B0aW9ucy5hdXRvU2hvdyA9PT0gdW5kZWZpbmVkICYmIGFwcE9wdGlvbnMuaXNQbGF0Zm9ybUNvbnRyb2xsZXIgPT09IHVuZGVmaW5lZCkge1xuXHQgICAgICAgICAgICBhcHBPcHRpb25zLmF1dG9TaG93ID0gdHJ1ZTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NyZWF0ZS1hcHBsaWNhdGlvbicsIGFwcE9wdGlvbnMpO1xuXHQgICAgICAgIHJldHVybiB0aGlzLndyYXAoeyB1dWlkOiBhcHBPcHRpb25zLnV1aWQgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIERFUFJFQ0FURUQgbWV0aG9kIHRvIGNyZWF0ZSBhIG5ldyBBcHBsaWNhdGlvbi4gVXNlIHtAbGluayBBcHBsaWNhdGlvbi5BcHBsaWNhdGlvbk1vZHVsZS5zdGFydCBBcHBsaWNhdGlvbi5zdGFydH0gaW5zdGVhZC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVBcHAoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmNyZWF0ZSh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMycsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1BcHBsaWNhdGlvbi5jcmVhdGUuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgYXdhaXQgYXBwLnJ1bigpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGNyZWF0ZUFwcCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0FwcGxpY2F0aW9uIGlzIGNyZWF0ZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICogQGlnbm9yZVxuXHQgICAgICovXG5cdCAgICBjcmVhdGUoYXBwT3B0aW9ucykge1xuXHQgICAgICAgIGNvbnNvbGUud2FybignRGVwcmVjYXRpb24gV2FybmluZzogZmluLkFwcGxpY2F0aW9uLmNyZWF0ZSBpcyBkZXByZWNhdGVkLiBQbGVhc2UgdXNlIGZpbi5BcHBsaWNhdGlvbi5zdGFydCcpO1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdhcHBsaWNhdGlvbi1jcmVhdGUnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gdGhpcy5fY3JlYXRlKGFwcE9wdGlvbnMpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBDcmVhdGVzIGFuZCBzdGFydHMgYSBuZXcgQXBwbGljYXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gc3RhcnQoKSB7XG5cdCAgICAgKiAgICAgcmV0dXJuIGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1BcHBsaWNhdGlvbi5zdGFydC5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqIH1cblx0ICAgICAqIHN0YXJ0KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQXBwbGljYXRpb24gaXMgcnVubmluZycpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHN0YXJ0KGFwcE9wdGlvbnMpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignc3RhcnQtYXBwbGljYXRpb24nKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBhcHAgPSBhd2FpdCB0aGlzLl9jcmVhdGUoYXBwT3B0aW9ucyk7XG5cdCAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3J1bi1hcHBsaWNhdGlvbicsIHsgdXVpZDogYXBwT3B0aW9ucy51dWlkIH0pO1xuXHQgICAgICAgIHJldHVybiBhcHA7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEFzeW5jaHJvbm91c2x5IHN0YXJ0cyBhIGJhdGNoIG9mIGFwcGxpY2F0aW9ucyBnaXZlbiBhbiBhcnJheSBvZiBhcHBsaWNhdGlvbiBpZGVudGlmaWVycyBhbmQgbWFuaWZlc3RVcmxzLlxuXHQgICAgICogUmV0dXJucyBvbmNlIHRoZSBSVk0gaXMgZmluaXNoZWQgYXR0ZW1wdGluZyB0byBsYXVuY2ggdGhlIGFwcGxpY2F0aW9ucy5cblx0ICAgICAqIEBwYXJhbSBvcHRzIC0gUGFyYW1ldGVycyB0aGF0IHRoZSBSVk0gd2lsbCB1c2UuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICpcblx0ICAgICAqIGNvbnN0IGFwcGxpY2F0aW9uSW5mb0FycmF5ID0gW1xuXHQgICAgICogICAgIHtcblx0ICAgICAqICAgICAgICAgXCJ1dWlkXCI6ICdBcHAtMScsXG5cdCAgICAgKiAgICAgICAgIFwibWFuaWZlc3RVcmxcIjogJ2h0dHA6Ly9sb2NhbGhvc3Q6NTU1NS9hcHAxLmpzb24nLFxuXHQgICAgICogICAgIH0sXG5cdCAgICAgKiAgICAge1xuXHQgICAgICogICAgICAgICBcInV1aWRcIjogJ0FwcC0yJyxcblx0ICAgICAqICAgICAgICAgXCJtYW5pZmVzdFVybFwiOiAnaHR0cDovL2xvY2FsaG9zdDo1NTU1L2FwcDIuanNvbicsXG5cdCAgICAgKiAgICAgfSxcblx0ICAgICAqICAgICB7XG5cdCAgICAgKiAgICAgICAgIFwidXVpZFwiOiAnQXBwLTMnLFxuXHQgICAgICogICAgICAgICBcIm1hbmlmZXN0VXJsXCI6ICdodHRwOi8vbG9jYWxob3N0OjU1NTUvYXBwMy5qc29uJyxcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiBdXG5cdCAgICAgKlxuXHQgICAgICogZmluLkFwcGxpY2F0aW9uLnN0YXJ0TWFueU1hbmlmZXN0cyhhcHBsaWNhdGlvbkluZm9BcnJheSlcblx0ICAgICAqICAgICAudGhlbigoKSA9PiB7XG5cdCAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCdSVk0gaGFzIGZpbmlzaGVkIGxhdW5jaGluZyB0aGUgYXBwbGljYXRpb24gbGlzdC4nKTtcblx0ICAgICAqICAgICB9KVxuXHQgICAgICogICAgIC5jYXRjaCgoZXJyKSA9PiB7XG5cdCAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKGVycik7XG5cdCAgICAgKiAgICAgfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgc3RhcnRNYW55TWFuaWZlc3RzKGFwcGxpY2F0aW9ucywgb3B0cykge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigncnVuLWFwcGxpY2F0aW9ucycsIHsgYXBwbGljYXRpb25zLCBvcHRzIH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhbiBBcHBsaWNhdGlvbiBvYmplY3QgdGhhdCByZXByZXNlbnRzIHRoZSBjdXJyZW50IGFwcGxpY2F0aW9uXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gaXNDdXJyZW50QXBwUnVubmluZyAoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXBwLmlzUnVubmluZygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGlzQ3VycmVudEFwcFJ1bm5pbmcoKS50aGVuKHJ1bm5pbmcgPT4ge1xuXHQgICAgICogICAgIGNvbnNvbGUubG9nKGBDdXJyZW50IGFwcCBpcyBydW5uaW5nOiAke3J1bm5pbmd9YCk7XG5cdCAgICAgKiB9KS5jYXRjaChlcnIgPT4ge1xuXHQgICAgICogICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcblx0ICAgICAqIH0pO1xuXHQgICAgICpcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRDdXJyZW50KCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtY3VycmVudC1hcHBsaWNhdGlvbicpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiB0aGlzLndyYXAoeyB1dWlkOiB0aGlzLndpcmUubWUudXVpZCB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGFuIEFwcGxpY2F0aW9uIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIGN1cnJlbnQgYXBwbGljYXRpb25cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBpc0N1cnJlbnRBcHBSdW5uaW5nICgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudFN5bmMoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXBwLmlzUnVubmluZygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGlzQ3VycmVudEFwcFJ1bm5pbmcoKS50aGVuKHJ1bm5pbmcgPT4ge1xuXHQgICAgICogICAgIGNvbnNvbGUubG9nKGBDdXJyZW50IGFwcCBpcyBydW5uaW5nOiAke3J1bm5pbmd9YCk7XG5cdCAgICAgKiB9KS5jYXRjaChlcnIgPT4ge1xuXHQgICAgICogICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcblx0ICAgICAqIH0pO1xuXHQgICAgICpcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRDdXJyZW50U3luYygpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWN1cnJlbnQtYXBwbGljYXRpb24tc3luYycpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiB0aGlzLndyYXBTeW5jKHsgdXVpZDogdGhpcy53aXJlLm1lLnV1aWQgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyBhcHBsaWNhdGlvbidzIG1hbmlmZXN0IGFuZCByZXR1cm5zIGEgcnVubmluZyBpbnN0YW5jZSBvZiB0aGUgYXBwbGljYXRpb24uXG5cdCAgICAgKiBAcGFyYW0gbWFuaWZlc3RVcmwgLSBUaGUgVVJMIG9mIGFwcCdzIG1hbmlmZXN0LlxuXHQgICAgICogQHBhcmFtIG9wdHMgLSBQYXJhbWV0ZXJzIHRoYXQgdGhlIFJWTSB3aWxsIHVzZS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBmaW4uQXBwbGljYXRpb24uc3RhcnRGcm9tTWFuaWZlc3QoJ2h0dHA6Ly9sb2NhbGhvc3Q6NTU1NS9hcHAuanNvbicpLnRoZW4oYXBwID0+IGNvbnNvbGUubG9nKCdBcHAgaXMgcnVubmluZycpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKlxuXHQgICAgICogLy8gRm9yIGEgbG9jYWwgbWFuaWZlc3QgZmlsZTpcblx0ICAgICAqIGZpbi5BcHBsaWNhdGlvbi5zdGFydEZyb21NYW5pZmVzdCgnZmlsZTovLy9DOi9zb21lZm9sZGVyL2FwcC5qc29uJykudGhlbihhcHAgPT4gY29uc29sZS5sb2coJ0FwcCBpcyBydW5uaW5nJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBzdGFydEZyb21NYW5pZmVzdChtYW5pZmVzdFVybCwgb3B0cykge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdhcHBsaWNhdGlvbi1zdGFydC1mcm9tLW1hbmlmZXN0JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgYXBwID0gYXdhaXQgdGhpcy5fY3JlYXRlRnJvbU1hbmlmZXN0KG1hbmlmZXN0VXJsKTtcblx0ICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHVzaW5nIHByaXZhdGUgbWV0aG9kIHdpdGhvdXQgd2FybmluZy5cblx0ICAgICAgICBhd2FpdCBhcHAuX3J1bihvcHRzKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlcnNjb3JlLWRhbmdsZVxuXHQgICAgICAgIHJldHVybiBhcHA7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgQXBwbGljYXRpb24uQXBwbGljYXRpb25Nb2R1bGUuc3RhcnRGcm9tTWFuaWZlc3QgQXBwbGljYXRpb24uc3RhcnRGcm9tTWFuaWZlc3R9IGluc3RlYWQuXG5cdCAgICAgKiBSZXRyaWV2ZXMgYXBwbGljYXRpb24ncyBtYW5pZmVzdCBhbmQgcmV0dXJucyBhIHdyYXBwZWQgYXBwbGljYXRpb24uXG5cdCAgICAgKiBAcGFyYW0gbWFuaWZlc3RVcmwgLSBUaGUgVVJMIG9mIGFwcCdzIG1hbmlmZXN0LlxuXHQgICAgICogQHBhcmFtIGNhbGxiYWNrIC0gY2FsbGVkIGlmIHRoZSBtZXRob2Qgc3VjY2VlZHMuXG5cdCAgICAgKiBAcGFyYW0gZXJyb3JDYWxsYmFjayAtIGNhbGxlZCBpZiB0aGUgbWV0aG9kIGZhaWxzLiBUaGUgcmVhc29uIGZvciBmYWlsdXJlIGlzIHBhc3NlZCBhcyBhbiBhcmd1bWVudC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBmaW4uQXBwbGljYXRpb24uY3JlYXRlRnJvbU1hbmlmZXN0KCdodHRwOi8vbG9jYWxob3N0OjU1NTUvYXBwLmpzb24nKS50aGVuKGFwcCA9PiBjb25zb2xlLmxvZyhhcHApKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqIEBpZ25vcmVcblx0ICAgICAqL1xuXHQgICAgY3JlYXRlRnJvbU1hbmlmZXN0KG1hbmlmZXN0VXJsKSB7XG5cdCAgICAgICAgY29uc29sZS53YXJuKCdEZXByZWNhdGlvbiBXYXJuaW5nOiBmaW4uQXBwbGljYXRpb24uY3JlYXRlRnJvbU1hbmlmZXN0IGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgZmluLkFwcGxpY2F0aW9uLnN0YXJ0RnJvbU1hbmlmZXN0Jyk7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2FwcGxpY2F0aW9uLWNyZWF0ZS1mcm9tLW1hbmlmZXN0JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuX2NyZWF0ZUZyb21NYW5pZmVzdChtYW5pZmVzdFVybCk7XG5cdCAgICB9XG5cdCAgICBfY3JlYXRlRnJvbU1hbmlmZXN0KG1hbmlmZXN0VXJsKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZVxuXHQgICAgICAgICAgICAuc2VuZEFjdGlvbignZ2V0LWFwcGxpY2F0aW9uLW1hbmlmZXN0JywgeyBtYW5pZmVzdFVybCB9KVxuXHQgICAgICAgICAgICAudGhlbigoeyBwYXlsb2FkIH0pID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgdXVpZCA9IHBheWxvYWQuZGF0YS5wbGF0Zm9ybSA/IHBheWxvYWQuZGF0YS5wbGF0Zm9ybS51dWlkIDogcGF5bG9hZC5kYXRhLnN0YXJ0dXBfYXBwLnV1aWQ7XG5cdCAgICAgICAgICAgIHJldHVybiB0aGlzLndyYXAoeyB1dWlkIH0pO1xuXHQgICAgICAgIH0pXG5cdCAgICAgICAgICAgIC50aGVuKChhcHApID0+IHtcblx0ICAgICAgICAgICAgYXBwLl9tYW5pZmVzdFVybCA9IG1hbmlmZXN0VXJsOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVyc2NvcmUtZGFuZ2xlXG5cdCAgICAgICAgICAgIHJldHVybiBhcHA7XG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdH1cblx0RmFjdG9yeSQ3LkFwcGxpY2F0aW9uTW9kdWxlID0gQXBwbGljYXRpb25Nb2R1bGU7XG5cdHJldHVybiBGYWN0b3J5JDc7XG59XG5cbnZhciBoYXNSZXF1aXJlZEFwcGxpY2F0aW9uO1xuXG5mdW5jdGlvbiByZXF1aXJlQXBwbGljYXRpb24gKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRBcHBsaWNhdGlvbikgcmV0dXJuIGFwcGxpY2F0aW9uO1xuXHRoYXNSZXF1aXJlZEFwcGxpY2F0aW9uID0gMTtcblx0KGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdFx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdFx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdFx0ICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcblx0XHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0XHQgICAgICBkZXNjID0geyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbVtrXTsgfSB9O1xuXHRcdCAgICB9XG5cdFx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdFx0fSkgOiAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0XHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0XHQgICAgb1trMl0gPSBtW2tdO1xuXHRcdH0pKTtcblx0XHR2YXIgX19leHBvcnRTdGFyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fZXhwb3J0U3RhcikgfHwgZnVuY3Rpb24obSwgZXhwb3J0cykge1xuXHRcdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdFx0fTtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdFx0LyoqXG5cdFx0ICogRW50cnkgcG9pbnRzIGZvciB0aGUgT3BlbkZpbiBgQXBwbGljYXRpb25gIEFQSSAoYGZpbi5BcHBsaWNhdGlvbmApLlxuXHRcdCAqXG5cdFx0ICogKiB7QGxpbmsgQXBwbGljYXRpb25Nb2R1bGV9IGNvbnRhaW5zIHN0YXRpYyBtZW1iZXJzIG9mIHRoZSBgQXBwbGljYXRpb25gIEFQSSwgYWNjZXNzaWJsZSB0aHJvdWdoIGBmaW4uQXBwbGljYXRpb25gLlxuXHRcdCAqICoge0BsaW5rIEFwcGxpY2F0aW9ufSBkZXNjcmliZXMgYW4gaW5zdGFuY2Ugb2YgYW4gT3BlbkZpbiBBcHBsaWNhdGlvbiwgZS5nLiBhcyByZXR1cm5lZCBieSBgZmluLkFwcGxpY2F0aW9uLmdldEN1cnJlbnRgLlxuXHRcdCAqXG5cdFx0ICogVGhlc2UgYXJlIHNlcGFyYXRlIGNvZGUgZW50aXRpZXMsIGFuZCBhcmUgZG9jdW1lbnRlZCBzZXBhcmF0ZWx5LiAgSW4gdGhlIFtwcmV2aW91cyB2ZXJzaW9uIG9mIHRoZSBBUEkgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvMzIuMTE0Ljc2LjEwL2luZGV4Lmh0bWwpLFxuXHRcdCAqIGJvdGggb2YgdGhlc2Ugd2VyZSBkb2N1bWVudGVkIG9uIHRoZSBzYW1lIHBhZ2UuXG5cdFx0ICpcblx0XHQgKiBAcGFja2FnZURvY3VtZW50YXRpb25cblx0XHQgKi9cblx0XHRfX2V4cG9ydFN0YXIocmVxdWlyZUZhY3RvcnkkMigpLCBleHBvcnRzKTtcblx0XHRfX2V4cG9ydFN0YXIocmVxdWlyZUluc3RhbmNlJDEoKSwgZXhwb3J0cyk7IFxuXHR9IChhcHBsaWNhdGlvbikpO1xuXHRyZXR1cm4gYXBwbGljYXRpb247XG59XG5cbnZhciBwcm9taXNpZnlTdWJzY3JpcHRpb24kMSA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkocHJvbWlzaWZ5U3Vic2NyaXB0aW9uJDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xucHJvbWlzaWZ5U3Vic2NyaXB0aW9uJDEucHJvbWlzaWZ5U3Vic2NyaXB0aW9uID0gdm9pZCAwO1xuY29uc3QgcHJvbWlzaWZ5U3Vic2NyaXB0aW9uID0gYXN5bmMgKGVtaXR0ZXIsIGV2ZW50TmFtZSwgcHJlZGljYXRlID0gKCkgPT4gdHJ1ZSwgdGltZW91dCkgPT4ge1xuICAgIGxldCByZXNvbHZlO1xuICAgIGxldCByZWplY3Q7XG4gICAgbGV0IHRpbWVyO1xuICAgIGNvbnN0IHZhbHVlUHJvbWlzZSA9IG5ldyBQcm9taXNlKCh5LCBuKSA9PiB7XG4gICAgICAgIHJlc29sdmUgPSB5O1xuICAgICAgICByZWplY3QgPSBuO1xuICAgIH0pO1xuICAgIGNvbnN0IGxpc3RlbmVyID0gKGUpID0+IHtcbiAgICAgICAgaWYgKHByZWRpY2F0ZShlKSkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgICAgIHJlc29sdmUoZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGF3YWl0IGVtaXR0ZXIub24oZXZlbnROYW1lLCBsaXN0ZW5lcik7XG4gICAgaWYgKHRpbWVvdXQpIHtcbiAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHJlamVjdChuZXcgRXJyb3IoJ2V2ZW50IHRpbWVkIG91dCcpKSwgdGltZW91dCk7XG4gICAgfVxuICAgIHZhbHVlUHJvbWlzZS5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgZW1pdHRlci5yZW1vdmVMaXN0ZW5lcihldmVudE5hbWUsIGxpc3RlbmVyKS5jYXRjaCgoKSA9PiBudWxsKTtcbiAgICB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgICBnZXRWYWx1ZTogKCkgPT4gdmFsdWVQcm9taXNlXG4gICAgfTtcbn07XG5wcm9taXNpZnlTdWJzY3JpcHRpb24kMS5wcm9taXNpZnlTdWJzY3JpcHRpb24gPSBwcm9taXNpZnlTdWJzY3JpcHRpb247XG5cbnZhciBoYXNSZXF1aXJlZEluc3RhbmNlO1xuXG5mdW5jdGlvbiByZXF1aXJlSW5zdGFuY2UgKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRJbnN0YW5jZSkgcmV0dXJuIEluc3RhbmNlJDc7XG5cdGhhc1JlcXVpcmVkSW5zdGFuY2UgPSAxO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoSW5zdGFuY2UkNywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdEluc3RhbmNlJDcuX1dpbmRvdyA9IHZvaWQgMDtcblx0LyogZXNsaW50LWRpc2FibGUgaW1wb3J0L3ByZWZlci1kZWZhdWx0LWV4cG9ydCAqL1xuXHQvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi9cblx0LyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXHQvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uICovXG5cdGNvbnN0IGFwcGxpY2F0aW9uXzEgPSByZXF1aXJlQXBwbGljYXRpb24oKTtcblx0Y29uc3QgbWFpbl8xID0gbWFpbjtcblx0Y29uc3Qgdmlld18xID0gcmVxdWlyZVZpZXcoKTtcblx0Y29uc3Qgd2FybmluZ3NfMSA9IHdhcm5pbmdzO1xuXHRjb25zdCBwcm9taXNpZnlTdWJzY3JpcHRpb25fMSA9IHByb21pc2lmeVN1YnNjcmlwdGlvbiQxO1xuXHQvKipcblx0ICogQSBiYXNpYyB3aW5kb3cgdGhhdCB3cmFwcyBhIG5hdGl2ZSBIVE1MIHdpbmRvdy4gUHJvdmlkZXMgbW9yZSBmaW5lLWdyYWluZWRcblx0ICogY29udHJvbCBvdmVyIHRoZSB3aW5kb3cgc3RhdGUgc3VjaCBhcyB0aGUgYWJpbGl0eSB0byBtaW5pbWl6ZSwgbWF4aW1pemUsIHJlc3RvcmUsIGV0Yy5cblx0ICogQnkgZGVmYXVsdCBhIHdpbmRvdyBkb2VzIG5vdCBzaG93IHVwb24gaW5zdGFudGlhdGlvbjsgaW5zdGVhZCB0aGUgd2luZG93J3Mgc2hvdygpIG1ldGhvZFxuXHQgKiBtdXN0IGJlIGludm9rZWQgbWFudWFsbHkuIFRoZSBuZXcgd2luZG93IGFwcGVhcnMgaW4gdGhlIHNhbWUgcHJvY2VzcyBhcyB0aGUgcGFyZW50IHdpbmRvdy5cblx0ICogSXQgaGFzIHRoZSBhYmlsaXR5IHRvIGxpc3RlbiBmb3Ige0BsaW5rIE9wZW5GaW4uV2luZG93RXZlbnRzIHdpbmRvdyBzcGVjaWZpYyBldmVudHN9LlxuXHQgKi9cblx0Ly8gVGhlIHdpbmRvdy5XaW5kb3cgbmFtZSBpcyB0YWtlblxuXHRjbGFzcyBfV2luZG93IGV4dGVuZHMgbWFpbl8xLldlYkNvbnRlbnRzIHtcblx0ICAgIC8qKlxuXHQgICAgICogQGludGVybmFsXG5cdCAgICAgKi9cblx0ICAgIGNvbnN0cnVjdG9yKHdpcmUsIGlkZW50aXR5KSB7XG5cdCAgICAgICAgc3VwZXIod2lyZSwgaWRlbnRpdHksICd3aW5kb3cnKTtcblx0ICAgIH1cblx0ICAgIGFzeW5jIGNyZWF0ZVdpbmRvdyhvcHRpb25zKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3dpbmRvdy1jcmVhdGUtd2luZG93JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgQ09OU1RSVUNUT1JfQ0JfVE9QSUMgPSAnZmlyZS1jb25zdHJ1Y3Rvci1jYWxsYmFjayc7XG5cdCAgICAgICAgY29uc3QgcmVzcG9uc2VTdWJzY3JpcHRpb24gPSBhd2FpdCAoMCwgcHJvbWlzaWZ5U3Vic2NyaXB0aW9uXzEucHJvbWlzaWZ5U3Vic2NyaXB0aW9uKSh0aGlzLCBDT05TVFJVQ1RPUl9DQl9UT1BJQyk7XG5cdCAgICAgICAgLy8gc2V0IGRlZmF1bHRzOlxuXHQgICAgICAgIGlmIChvcHRpb25zLndhaXRGb3JQYWdlTG9hZCA9PT0gdW5kZWZpbmVkKSB7XG5cdCAgICAgICAgICAgIG9wdGlvbnMud2FpdEZvclBhZ2VMb2FkID0gZmFsc2U7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmIChvcHRpb25zLmF1dG9TaG93ID09PSB1bmRlZmluZWQpIHtcblx0ICAgICAgICAgICAgb3B0aW9ucy5hdXRvU2hvdyA9IHRydWU7XG5cdCAgICAgICAgfVxuXHQgICAgICAgICgwLCB3YXJuaW5nc18xLmhhbmRsZURlcHJlY2F0ZWRXYXJuaW5ncykob3B0aW9ucyk7XG5cdCAgICAgICAgY29uc3Qgd2luZG93Q3JlYXRpb24gPSB0aGlzLndpcmUuZW52aXJvbm1lbnQuY3JlYXRlQ2hpbGRDb250ZW50KHsgZW50aXR5VHlwZTogJ3dpbmRvdycsIG9wdGlvbnMgfSk7XG5cdCAgICAgICAgY29uc3QgW3Jlc3BvbnNlXSA9IGF3YWl0IFByb21pc2UuYWxsKFtyZXNwb25zZVN1YnNjcmlwdGlvbi5nZXRWYWx1ZSgpLCB3aW5kb3dDcmVhdGlvbl0pO1xuXHQgICAgICAgIGxldCBjYlBheWxvYWQ7XG5cdCAgICAgICAgY29uc3QgeyBzdWNjZXNzIH0gPSByZXNwb25zZTtcblx0ICAgICAgICBjb25zdCByZXNwb25zZURhdGEgPSByZXNwb25zZS5kYXRhO1xuXHQgICAgICAgIGNvbnN0IHsgbWVzc2FnZSB9ID0gcmVzcG9uc2VEYXRhO1xuXHQgICAgICAgIGlmIChzdWNjZXNzKSB7XG5cdCAgICAgICAgICAgIGNiUGF5bG9hZCA9IHtcblx0ICAgICAgICAgICAgICAgIGh0dHBSZXNwb25zZUNvZGU6IHJlc3BvbnNlRGF0YS5odHRwUmVzcG9uc2VDb2RlLFxuXHQgICAgICAgICAgICAgICAgYXBpSW5qZWN0ZWQ6IHJlc3BvbnNlRGF0YS5hcGlJbmplY3RlZFxuXHQgICAgICAgICAgICB9O1xuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgY2JQYXlsb2FkID0ge1xuXHQgICAgICAgICAgICAgICAgbWVzc2FnZTogcmVzcG9uc2VEYXRhLm1lc3NhZ2UsXG5cdCAgICAgICAgICAgICAgICBuZXR3b3JrRXJyb3JDb2RlOiByZXNwb25zZURhdGEubmV0d29ya0Vycm9yQ29kZSxcblx0ICAgICAgICAgICAgICAgIHN0YWNrOiByZXNwb25zZURhdGEuc3RhY2tcblx0ICAgICAgICAgICAgfTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3QgcGFnZVJlc29sdmUgPSB7XG5cdCAgICAgICAgICAgIG1lc3NhZ2UsXG5cdCAgICAgICAgICAgIGNiUGF5bG9hZCxcblx0ICAgICAgICAgICAgc3VjY2Vzc1xuXHQgICAgICAgIH07XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgLy8gdGhpcyBpcyB0byBlbmZvcmNlIGEgNS4wIGNvbnRyYWN0IHRoYXQgdGhlIGNoaWxkJ3MgbWFpbiBmdW5jdGlvblxuXHQgICAgICAgICAgICAvLyB3aWxsIG5vdCBmaXJlIGJlZm9yZSB0aGUgcGFyZW50J3Mgc3VjY2VzcyBjYWxsYmFjayBvbiBjcmVhdGlvbi5cblx0ICAgICAgICAgICAgLy8gaWYgdGhlIGNoaWxkIHdpbmRvdyBpcyBub3QgYWNjZXNzaWJsZSAoQ09SUykgdGhpcyBjb250cmFjdCBkb2VzXG5cdCAgICAgICAgICAgIC8vIG5vdCBob2xkLlxuXHQgICAgICAgICAgICBjb25zdCB3ZWJXaW5kb3cgPSB0aGlzLmdldFdlYldpbmRvdygpO1xuXHQgICAgICAgICAgICB3ZWJXaW5kb3cuZmluLl9faW50ZXJuYWxfLm9wZW5lclN1Y2Nlc3NDQkNhbGxlZCgpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZSkge1xuXHQgICAgICAgICAgICAvLyBjb21tb24gZm9yIG1haW4gd2luZG93cywgd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IuIGhlcmUganVzdCB0byBoYXZlIGEgZGVidWcgdGFyZ2V0LlxuXHQgICAgICAgICAgICAvLyBjb25zb2xlLmVycm9yKGUpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBpZiAocGFnZVJlc29sdmUuc3VjY2Vzcykge1xuXHQgICAgICAgICAgICByZXR1cm4gdGhpcztcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHBhZ2VSZXNvbHZlKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIGFuIGFycmF5IG9mIGZyYW1lIGluZm8gb2JqZWN0cyByZXByZXNlbnRpbmcgdGhlIG1haW4gZnJhbWUgYW5kIGFueVxuXHQgICAgICogaWZyYW1lcyB0aGF0IGFyZSBjdXJyZW50bHkgb24gdGhlIHBhZ2UuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRBbGxGcmFtZXMoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5nZXRBbGxGcmFtZXMuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uZ2V0QWxsRnJhbWVzKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0QWxsRnJhbWVzKCkudGhlbihmcmFtZXNJbmZvID0+IGNvbnNvbGUubG9nKGZyYW1lc0luZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0QWxsRnJhbWVzKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWFsbC1mcmFtZXMnLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0cyB0aGUgY3VycmVudCBib3VuZHMgKHRvcCwgYm90dG9tLCByaWdodCwgbGVmdCwgd2lkdGgsIGhlaWdodCkgb2YgdGhlIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldEJvdW5kcygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTMnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmdldEJvdW5kcy5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5nZXRCb3VuZHMoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRCb3VuZHMoKS50aGVuKGJvdW5kcyA9PiBjb25zb2xlLmxvZyhib3VuZHMpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0Qm91bmRzKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmVcblx0ICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ2dldC13aW5kb3ctYm91bmRzJywgdGhpcy5pZGVudGl0eSlcblx0ICAgICAgICAgICAgLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBDZW50ZXJzIHRoZSB3aW5kb3cgb24gaXRzIGN1cnJlbnQgc2NyZWVuLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIERvZXMgbm90IGhhdmUgYW4gZWZmZWN0IG9uIG1pbmltaXplZCBvciBtYXhpbWl6ZWQgd2luZG93cy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNlbnRlcldpbmRvdygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmNlbnRlci5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5jZW50ZXIoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBjZW50ZXJXaW5kb3coKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdXaW5kb3cgY2VudGVyZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICovXG5cdCAgICBjZW50ZXIoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjZW50ZXItd2luZG93JywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZW1vdmVzIGZvY3VzIGZyb20gdGhlIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGJsdXJXaW5kb3coKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5ibHVyLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmJsdXIoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBibHVyV2luZG93KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQmx1cmVkIFdpbmRvdycpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYmx1cigpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2JsdXItd2luZG93JywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBCcmluZ3MgdGhlIHdpbmRvdyB0byB0aGUgZnJvbnQgb2YgdGhlIHdpbmRvdyBzdGFjay5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIEJyaW5nV2luZG93VG9Gcm9udCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmJyaW5nVG9Gcm9udC5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5icmluZ1RvRnJvbnQoKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBCcmluZ1dpbmRvd1RvRnJvbnQoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdXaW5kb3cgaXMgaW4gdGhlIGZyb250JykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBicmluZ1RvRnJvbnQoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdicmluZy13aW5kb3ctdG8tZnJvbnQnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFBlcmZvcm1zIHRoZSBzcGVjaWZpZWQgd2luZG93IHRyYW5zaXRpb25zLlxuXHQgICAgICogQHBhcmFtIHRyYW5zaXRpb25zIC0gRGVzY3JpYmVzIHRoZSBhbmltYXRpb25zIHRvIHBlcmZvcm0uIFNlZSB0aGUgdHV0b3JpYWwuXG5cdCAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbnMgZm9yIHRoZSBhbmltYXRpb24uIFNlZSB0aGUgdHV0b3JpYWwuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYFxuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gYW5pbWF0ZVdpbmRvdygpIHtcblx0ICAgICAqICAgICBjb25zdCB0cmFuc2l0aW9ucyA9IHtcblx0ICAgICAqICAgICAgICAgb3BhY2l0eToge1xuXHQgICAgICogICAgICAgICAgICAgb3BhY2l0eTogMC43LFxuXHQgICAgICogICAgICAgICAgICAgZHVyYXRpb246IDUwMFxuXHQgICAgICogICAgICAgICB9LFxuXHQgICAgICogICAgICAgICBwb3NpdGlvbjoge1xuXHQgICAgICogICAgICAgICAgICAgdG9wOiAxMDAsXG5cdCAgICAgKiAgICAgICAgICAgICBsZWZ0OiAxMDAsXG5cdCAgICAgKiAgICAgICAgICAgICBkdXJhdGlvbjogNTAwLFxuXHQgICAgICogICAgICAgICAgICAgcmVsYXRpdmU6IHRydWVcblx0ICAgICAqICAgICAgICAgfVxuXHQgICAgICogICAgIH07XG5cdCAgICAgKiAgICAgY29uc3Qgb3B0aW9ucyA9IHtcblx0ICAgICAqICAgICAgICAgaW50ZXJydXB0OiB0cnVlLFxuXHQgICAgICogICAgICAgICB0d2VlbjogJ2Vhc2UtaW4nXG5cdCAgICAgKiAgICAgfTtcblx0ICAgICAqXG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIHdpbi5hbmltYXRlKHRyYW5zaXRpb25zLCBvcHRpb25zKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBhbmltYXRlV2luZG93KClcblx0ICAgICAqICAgICAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQW5pbWF0aW9uIGRvbmUnKSlcblx0ICAgICAqICAgICAuY2F0Y2goZXJyID0+IGNvbnNvbGUuZXJyb3IoZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYW5pbWF0ZSh0cmFuc2l0aW9ucywgb3B0aW9ucykge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmVcblx0ICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ2FuaW1hdGUtd2luZG93Jywge1xuXHQgICAgICAgICAgICB0cmFuc2l0aW9ucyxcblx0ICAgICAgICAgICAgb3B0aW9ucyxcblx0ICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuXHQgICAgICAgIH0pXG5cdCAgICAgICAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEhpZGVzIHRoZSB3aW5kb3cuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBoaWRlV2luZG93KCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuaGlkZS5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5oaWRlKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogaGlkZVdpbmRvdygpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1dpbmRvdyBpcyBoaWRkZW4nKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGhpZGUoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdoaWRlLXdpbmRvdycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogY2xvc2VzIHRoZSB3aW5kb3cgYXBwbGljYXRpb25cblx0ICAgICAqIEBwYXJhbSBmb3JjZSBDbG9zZSB3aWxsIGJlIHByZXZlbnRlZCBmcm9tIGNsb3Npbmcgd2hlbiBmb3JjZSBpcyBmYWxzZSBhbmRcblx0ICAgICAqICDigJhjbG9zZS1yZXF1ZXN0ZWTigJkgaGFzIGJlZW4gc3Vic2NyaWJlZCB0byBmb3IgYXBwbGljYXRpb27igJlzIG1haW4gd2luZG93LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY2xvc2VXaW5kb3coKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0zJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5jbG9zZS5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5jbG9zZSgpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGNsb3NlV2luZG93KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnV2luZG93IGNsb3NlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgY2xvc2UoZm9yY2UgPSBmYWxzZSkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignY2xvc2Utd2luZG93JywgeyBmb3JjZSwgLi4udGhpcy5pZGVudGl0eSB9KS50aGVuKCgpID0+IHtcblx0ICAgICAgICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIG51bGwpO1xuXHQgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgZm9jdXNlZFdlYlZpZXdXYXNDaGFuZ2VkKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZm9jdXNlZC13ZWJ2aWV3LWNoYW5nZWQnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgdGhlIG5hdGl2ZSBPUyBsZXZlbCBJZC5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBJbiBXaW5kb3dzLCBpdCB3aWxsIHJldHVybiB0aGUgV2luZG93cyBbaGFuZGxlXShodHRwczovL2RvY3MubWljcm9zb2Z0LmNvbS9lbi11cy93aW5kb3dzL2Rlc2t0b3AvV2luUHJvZy93aW5kb3dzLWRhdGEtdHlwZXMjSFdORCkuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRXaW5kb3dOYXRpdmVJZCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTMnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmdldE5hdGl2ZUlkLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmdldE5hdGl2ZUlkKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0V2luZG93TmF0aXZlSWQoKS50aGVuKG5hdGl2ZUlkID0+IGNvbnNvbGUubG9nKG5hdGl2ZUlkKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldE5hdGl2ZUlkKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXdpbmRvdy1uYXRpdmUtaWQnLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIHdpbmRvdydzIGF0dGFjaGVkIHZpZXdzLlxuXHQgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3Qgd2luID0gZmluLldpbmRvdy5nZXRDdXJyZW50U3luYygpO1xuXHQgICAgICpcblx0ICAgICAqIHdpbi5nZXRDdXJyZW50Vmlld3MoKVxuXHQgICAgICogICAudGhlbih2aWV3cyA9PiBjb25zb2xlLmxvZyh2aWV3cykpXG5cdCAgICAgKiAgIC5jYXRjaChjb25zb2xlLmVycm9yKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRDdXJyZW50Vmlld3MoKSB7XG5cdCAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignd2luZG93LWdldC12aWV3cycsIHRoaXMuaWRlbnRpdHkpO1xuXHQgICAgICAgIHJldHVybiBwYXlsb2FkLmRhdGEubWFwKChpZCkgPT4gbmV3IHZpZXdfMS5WaWV3KHRoaXMud2lyZSwgaWQpKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayBXaW5kb3cuX1dpbmRvdy5kaXNhYmxlVXNlck1vdmVtZW50fSBpbnN0ZWFkLlxuXHQgICAgICovXG5cdCAgICBkaXNhYmxlRnJhbWUoKSB7XG5cdCAgICAgICAgY29uc29sZS53YXJuKCdGdW5jdGlvbiBpcyBkZXByZWNhdGVkOyB1c2UgZGlzYWJsZVVzZXJNb3ZlbWVudCBpbnN0ZWFkLicpO1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZGlzYWJsZS13aW5kb3ctZnJhbWUnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFByZXZlbnRzIGEgdXNlciBmcm9tIGNoYW5naW5nIGEgd2luZG93J3Mgc2l6ZS9wb3NpdGlvbiB3aGVuIHVzaW5nIHRoZSB3aW5kb3cncyBmcmFtZS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGRpc2FibGVVc2VyTW92ZW1lbnQoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0zJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5kaXNhYmxlRnJhbWUuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uZGlzYWJsZVVzZXJNb3ZlbWVudCgpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGRpc2FibGVVc2VyTW92ZW1lbnQoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdXaW5kb3cgaXMgZGlzYWJsZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGRpc2FibGVVc2VyTW92ZW1lbnQoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdkaXNhYmxlLXdpbmRvdy1mcmFtZScsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayBXaW5kb3cuX1dpbmRvdy5lbmFibGVVc2VyTW92ZW1lbnR9IGluc3RlYWQuXG5cdCAgICAgKi9cblx0ICAgIGVuYWJsZUZyYW1lKCkge1xuXHQgICAgICAgIGNvbnNvbGUud2FybignRnVuY3Rpb24gaXMgZGVwcmVjYXRlZDsgdXNlIGVuYWJsZVVzZXJNb3ZlbWVudCBpbnN0ZWFkLicpO1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZW5hYmxlLXdpbmRvdy1mcmFtZScsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmUtZW5hYmxlcyB1c2VyIGNoYW5nZXMgdG8gYSB3aW5kb3cncyBzaXplL3Bvc2l0aW9uIHdoZW4gdXNpbmcgdGhlIHdpbmRvdydzIGZyYW1lLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZW5hYmxlVXNlck1vdmVtZW50KCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMycsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZW5hYmxlRnJhbWUuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uZW5hYmxlVXNlck1vdmVtZW50KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZW5hYmxlVXNlck1vdmVtZW50KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnV2luZG93IGlzIGVuYWJsZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGVuYWJsZVVzZXJNb3ZlbWVudCgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2VuYWJsZS13aW5kb3ctZnJhbWUnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEZsYXNoZXMgdGhlIHdpbmRvd+KAmXMgZnJhbWUgYW5kIHRhc2tiYXIgaWNvbiB1bnRpbCBzdG9wRmxhc2hpbmcgaXMgY2FsbGVkIG9yIHVudGlsIGEgZm9jdXMgZXZlbnQgaXMgZmlyZWQuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgT24gbWFjT1MgZmxhc2ggb25seSB3b3JrcyBvbiBpbmFjdGl2ZSB3aW5kb3dzLlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiB3aW5kb3dGbGFzaCgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmZsYXNoLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmZsYXNoKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogd2luZG93Rmxhc2goKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdXaW5kb3cgZmxhc2hpbmcnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGZsYXNoKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZmxhc2gtd2luZG93JywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTdG9wcyB0aGUgdGFza2JhciBpY29uIGZyb20gZmxhc2hpbmcuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBzdG9wV2luZG93Rmxhc2hpbmcoKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5zdG9wRmxhc2hpbmcuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uc3RvcEZsYXNoaW5nKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogc3RvcFdpbmRvd0ZsYXNoaW5nKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQXBwbGljYXRpb24gd2luZG93IGZsYXNoaW5nJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBzdG9wRmxhc2hpbmcoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzdG9wLWZsYXNoLXdpbmRvdycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0cyBhbiBpbmZvcm1hdGlvbiBvYmplY3QgZm9yIHRoZSB3aW5kb3cuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRJbmZvKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZ2V0SW5mby5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5nZXRJbmZvKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0SW5mbygpLnRoZW4oaW5mbyA9PiBjb25zb2xlLmxvZyhpbmZvKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldEluZm8oKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtd2luZG93LWluZm8nLCB0aGlzLmlkZW50aXR5KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIHRoZSB3aW5kb3cncyBMYXlvdXRcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqICAgICAvL2dldCB0aGUgY3VycmVudCB3aW5kb3dcblx0ICAgICAqICAgICBjb25zdCB3aW5kb3cgPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAqXG5cdCAgICAgKiAgICAgLy9nZXQgdGhlIGxheW91dCBmb3IgdGhlIHdpbmRvd1xuXHQgICAgICogICAgIGNvbnN0IGxheW91dCA9IGF3YWl0IHdpbmRvdy5nZXRMYXlvdXQoKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRMYXlvdXQobGF5b3V0SWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignd2luZG93LWdldC1sYXlvdXQnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2Vcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBvcHRzID0gYXdhaXQgdGhpcy5nZXRPcHRpb25zKCk7XG5cdCAgICAgICAgaWYgKCFvcHRzLmxheW91dCAmJiAhb3B0cy5sYXlvdXRTbmFwc2hvdCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dpbmRvdyBkb2VzIG5vdCBoYXZlIGEgTGF5b3V0Jyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiB0aGlzLmZpbi5QbGF0Zm9ybS5MYXlvdXQud3JhcChsYXlvdXRJZGVudGl0eSA/PyB0aGlzLmlkZW50aXR5KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0cyB0aGUgY3VycmVudCBzZXR0aW5ncyBvZiB0aGUgd2luZG93LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0V2luZG93T3B0aW9ucygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmdldE9wdGlvbnMuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uZ2V0T3B0aW9ucygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGdldFdpbmRvd09wdGlvbnMoKS50aGVuKG9wdHMgPT4gY29uc29sZS5sb2cob3B0cykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRPcHRpb25zKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXdpbmRvdy1vcHRpb25zJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEdldHMgdGhlIHBhcmVudCBhcHBsaWNhdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFBhcmVudEFwcGxpY2F0aW9uKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuZ2V0UGFyZW50QXBwbGljYXRpb24uaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uZ2V0UGFyZW50QXBwbGljYXRpb24oKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRQYXJlbnRBcHBsaWNhdGlvbigpLnRoZW4ocGFyZW50QXBwbGljYXRpb24gPT4gY29uc29sZS5sb2cocGFyZW50QXBwbGljYXRpb24pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0UGFyZW50QXBwbGljYXRpb24oKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3dpbmRvdy1nZXQtcGFyZW50LWFwcGxpY2F0aW9uJywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXcgYXBwbGljYXRpb25fMS5BcHBsaWNhdGlvbih0aGlzLndpcmUsIHRoaXMuaWRlbnRpdHkpKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0cyB0aGUgcGFyZW50IHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFBhcmVudFdpbmRvdygpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmdldFBhcmVudFdpbmRvdy5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5nZXRQYXJlbnRXaW5kb3coKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBnZXRQYXJlbnRXaW5kb3coKS50aGVuKHBhcmVudFdpbmRvdyA9PiBjb25zb2xlLmxvZyhwYXJlbnRXaW5kb3cpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0UGFyZW50V2luZG93KCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd3aW5kb3ctZ2V0LXBhcmVudC13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBhcHBsaWNhdGlvbl8xLkFwcGxpY2F0aW9uKHRoaXMud2lyZSwgdGhpcy5pZGVudGl0eSkpLnRoZW4oKGFwcCkgPT4gYXBwLmdldFdpbmRvdygpKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogKioqREVQUkVDQVRFRCAtIHBsZWFzZSB1c2UgV2luZG93LmNhcHR1cmVQYWdlLioqKlxuXHQgICAgICogR2V0cyBhIGJhc2U2NCBlbmNvZGVkIFBORyBpbWFnZSBvZiB0aGUgd2luZG93IG9yIGp1c3QgcGFydCBhIG9mIGl0LlxuXHQgICAgICogQHBhcmFtIGFyZWEgVGhlIGFyZWEgb2YgdGhlIHdpbmRvdyB0byBiZSBjYXB0dXJlZC5cblx0ICAgICAqIE9taXR0aW5nIGl0IHdpbGwgY2FwdHVyZSB0aGUgd2hvbGUgdmlzaWJsZSB3aW5kb3cuXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIFdpbmRvdy5jYXB0dXJlUGFnZVxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRTbmFwc2hvdChhcmVhKSB7XG5cdCAgICAgICAgY29uc3QgcmVxID0geyBhcmVhLCAuLi50aGlzLmlkZW50aXR5IH07XG5cdCAgICAgICAgY29uc29sZS53YXJuKCdXaW5kb3cuZ2V0U25hcHNob3QgaGFzIGJlZW4gZGVwcmVjYXRlZCwgcGxlYXNlIHVzZSBXaW5kb3cuY2FwdHVyZVBhZ2UnKTtcblx0ICAgICAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXdpbmRvdy1zbmFwc2hvdCcsIHJlcSk7XG5cdCAgICAgICAgcmV0dXJuIHJlcy5wYXlsb2FkLmRhdGE7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEdldHMgdGhlIGN1cnJlbnQgc3RhdGUgKFwibWluaW1pemVkXCIsIFwibWF4aW1pemVkXCIsIG9yIFwibm9ybWFsXCIpIG9mIHRoZSB3aW5kb3cuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRXaW5kb3dTdGF0ZSgpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LmdldFN0YXRlLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmdldFN0YXRlKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0V2luZG93U3RhdGUoKS50aGVuKHdpblN0YXRlID0+IGNvbnNvbGUubG9nKHdpblN0YXRlKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldFN0YXRlKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXdpbmRvdy1zdGF0ZScsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBQcmV2aW91c2x5IGNhbGxlZCBnZXROYXRpdmVXaW5kb3cuXG5cdCAgICAgKiBSZXR1cm5zIHRoZSBbV2luZG93IE9iamVjdF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvdylcblx0ICAgICAqIHRoYXQgcmVwcmVzZW50cyB0aGUgd2ViIGNvbnRleHQgb2YgdGhlIHRhcmdldCB3aW5kb3cuIFRoaXMgaXMgdGhlIHNhbWUgb2JqZWN0IHRoYXRcblx0ICAgICAqIHlvdSB3b3VsZCBnZXQgZnJvbSBjYWxsaW5nIFt3aW5kb3cub3BlbigpXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93L29wZW4pIGluIGEgc3RhbmRhcmQgd2ViIGNvbnRleHQuXG5cdCAgICAgKiBUaGUgdGFyZ2V0IHdpbmRvdyBuZWVkcyB0byBiZSBpbiB0aGUgc2FtZSBhcHBsaWNhdGlvbiBhcyB0aGUgcmVxdWVzdGluZyB3aW5kb3dcblx0ICAgICAqIGFzIHdlbGwgYXMgY29tcGx5IHdpdGggW3NhbWUtb3JpZ2luXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9TZWN1cml0eS9TYW1lLW9yaWdpbl9wb2xpY3kpIHBvbGljeSByZXF1aXJlbWVudHMuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIEluamVjdGluZyBjb250ZW50IGludG8gYW4gZW1wdHkgd2luZG93OlxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiAoYXN5bmMgKCk9PiB7XG5cdCAgICAgKiAgICAgdHJ5IHtcblx0ICAgICAqICAgICAgICAgY29uc3Qgd2luTmFtZSA9IGBjaGlsZC13aW5kb3ctJHtEYXRlLm5vdygpfWA7XG5cdCAgICAgKiAgICAgICAgIGNvbnN0IHdpbiA9IGF3YWl0IGZpbi5XaW5kb3cuY3JlYXRlKHtcblx0ICAgICAqICAgICAgICAgICAgIG5hbWU6IHdpbk5hbWUsXG5cdCAgICAgKiAgICAgICAgICAgICB1cmw6ICdhYm91dDpibGFuaydcblx0ICAgICAqICAgICAgICAgfSk7XG5cdCAgICAgKiAgICAgICAgIHdpbi5nZXRXZWJXaW5kb3coKS5kb2N1bWVudC53cml0ZSgnPGgxPkhlbGxvIFdvcmxkPC9oMT4nKTtcblx0ICAgICAqICAgICB9IGNhdGNoIChlcnIpIHtcblx0ICAgICAqICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuXHQgICAgICogICAgIH1cblx0ICAgICAqIH0pKCk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqXG5cdCAgICAgKiBDbG9uaW5nIERPTSBlbGVtZW50cyBmcm9tIHRoZSBwYXJlbnQgd2luZG93IChpbiB0aGlzIGV4YW1wbGUgd2UgY2xvbmUgYW4gYGgzYCBlbGVtZW50IGZyb20gdGhlIHBhcmVudCB3aW5kb3cpOlxuXHQgICAgICogYGBganNcblx0ICAgICAqIChhc3luYyAoKT0+IHtcblx0ICAgICAqICAgICB0cnkge1xuXHQgICAgICogICAgICAgICBjb25zdCBjdXJyZW50V2luZG93ID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgICAgIGNvbnN0IHBhcmVudFdpbmRvdyA9IGF3YWl0IGN1cnJlbnRXaW5kb3cuZ2V0UGFyZW50V2luZG93KCk7XG5cdCAgICAgKiAgICAgICAgIGNvbnN0IGNsb25lZEgzID0gcGFyZW50V2luZG93LmdldFdlYldpbmRvdygpLmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2gzJykuY2xvbmVOb2RlKHRydWUpO1xuXHQgICAgICogICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZChjbG9uZWRIMyk7XG5cdCAgICAgKlxuXHQgICAgICogICAgIH0gY2F0Y2ggKGVycikge1xuXHQgICAgICogICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG5cdCAgICAgKiAgICAgfVxuXHQgICAgICogfSkoKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqIFJlbmRlcmluZyBvbiBhIGNoaWxkIHdpbmRvdyB2aWEgYSBsaWJyYXJ5IChpbiB0aGlzIGV4YW1wbGUgd2UgYXJlIHVzaW5nIHRoZSBbbGl0LWh0bWxdKGh0dHBzOi8vbGl0LWh0bWwucG9seW1lci1wcm9qZWN0Lm9yZy8pXG5cdCAgICAgKiB0ZW1wbGF0ZSBsaWJyYXJ5IHRvIHJlbmRlciBjb250ZW50IG9uIGEgYmxhbmsgY2hpbGQgd2luZG93LiBZb3UgYXJlIG5vdCBnb2luZyB0byBiZSBhYmxlIHRvIGNvcHkgcGFzdGUgdGhpcyBleGFtcGxlIHdpdGhvdXRcblx0ICAgICAqIGNvbmZpZ3VyaW5nIHRoZSBwcm9qZWN0IGNvcnJlY3RseSBidXQgdGhpcyB3b3VsZCBkZW1vbnN0cmF0ZSBzb21lIHRlbXBsYXRpbmcgb3B0aW9ucyBhdmFpbGFibGUpOlxuXHQgICAgICogYGBganNcblx0ICAgICAqIChhc3luYyAoKT0+IHtcblx0ICAgICAqICAgICB0cnkge1xuXHQgICAgICogICAgICAgICBjb25zdCB3aW4gPSBhd2FpdCBmaW4uV2luZG93LmNyZWF0ZSh7XG5cdCAgICAgKiAgICAgICAgICAgICBuYW1lOiBgY2hpbGQtd2luZG93LSR7RGF0ZS5ub3coKX1gLFxuXHQgICAgICogICAgICAgICAgICAgdXJsOiAnYWJvdXQ6YmxhbmsnXG5cdCAgICAgKiAgICAgICAgIH0pO1xuXHQgICAgICogICAgICAgICBjb25zdCB0ZW1wbGF0ZSA9IGh0bWxgXG5cdCAgICAgKiAgICAgICAgICAgICA8ZGl2PlxuXHQgICAgICogICAgICAgICAgICAgICAgIDxzcGFuPkNsaWNrIGhlcmU6IDwvc3Bhbj5cblx0ICAgICAqICAgICAgICAgICAgICAgICA8YnV0dG9uIEBjbGljaz0keygpPT4gY29uc29sZS5sb2coJ0hlbGxvIFdvcmxkIScpfT5sb2cgdG8gdGhlIGNvbnNvbGU8L2J1dHRvbj5cblx0ICAgICAqICAgICAgICAgICAgIDwvZGl2PmA7XG5cdCAgICAgKiAgICAgICAgIHJlbmRlcih0ZW1wbGF0ZSwgd2luLmdldFdlYldpbmRvdygpLmRvY3VtZW50LmJvZHkpO1xuXHQgICAgICpcblx0ICAgICAqICAgICB9IGNhdGNoIChlcnIpIHtcblx0ICAgICAqICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuXHQgICAgICogICAgIH1cblx0ICAgICAqIH0pKCk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgZ2V0V2ViV2luZG93KCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd3aW5kb3ctZ2V0LXdlYi13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLmVudmlyb25tZW50LmdldFdlYldpbmRvdyh0aGlzLmlkZW50aXR5KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogRGV0ZXJtaW5lcyBpZiB0aGUgd2luZG93IGlzIGEgbWFpbiB3aW5kb3cuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCB3bmQgPSBmaW4uV2luZG93LmdldEN1cnJlbnRTeW5jKCk7XG5cdCAgICAgKiBjb25zdCBpc01haW5XbmQgPSB3bmQuaXNNYWluV2luZG93KCk7XG5cdCAgICAgKiBjb25zb2xlLmxvZygnSXMgdGhpcyBhIG1haW4gd2luZG93PyAnICsgaXNNYWluV25kKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBpc01haW5XaW5kb3coKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3dpbmRvdy1pcy1tYWluLXdpbmRvdycsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiB0aGlzLm1lLnV1aWQgPT09IHRoaXMubWUubmFtZTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogRGV0ZXJtaW5lcyBpZiB0aGUgd2luZG93IGlzIGN1cnJlbnRseSBzaG93aW5nLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gaXNXaW5kb3dTaG93aW5nKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuaXNTaG93aW5nLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLmlzU2hvd2luZygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGlzV2luZG93U2hvd2luZygpLnRoZW4oYm9vbCA9PiBjb25zb2xlLmxvZyhib29sKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGlzU2hvd2luZygpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2lzLXdpbmRvdy1zaG93aW5nJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIE1heGltaXplcyB0aGUgd2luZG93XG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBtYXhXaW5kb3coKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5tYXhpbWl6ZS5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5tYXhpbWl6ZSgpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIG1heFdpbmRvdygpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ01heGltaXplZCB3aW5kb3cnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIG1heGltaXplKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignbWF4aW1pemUtd2luZG93JywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBNaW5pbWl6ZXMgdGhlIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIG1pbldpbmRvdygpIHtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBmaW4uV2luZG93LmdldEN1cnJlbnQoKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLm1pbmltaXplKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogbWluV2luZG93KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnTWluaW1pemVkIHdpbmRvdycpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgbWluaW1pemUoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdtaW5pbWl6ZS13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIE1vdmVzIHRoZSB3aW5kb3cgYnkgYSBzcGVjaWZpZWQgYW1vdW50LlxuXHQgICAgICogQHBhcmFtIGRlbHRhTGVmdCBUaGUgY2hhbmdlIGluIHRoZSBsZWZ0IHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcblx0ICAgICAqIEBwYXJhbSBkZWx0YVRvcCBUaGUgY2hhbmdlIGluIHRoZSB0b3AgcG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cubW92ZUJ5Lmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gbW92ZUJ5KGxlZnQsIHRvcCkge1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGNyZWF0ZVdpbigpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4ubW92ZUJ5KGxlZnQsIHRvcCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogbW92ZUJ5KDU4MCwgMzAwKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdNb3ZlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgbW92ZUJ5KGRlbHRhTGVmdCwgZGVsdGFUb3AsIHBvc2l0aW9uaW5nT3B0aW9ucykge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmVcblx0ICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ21vdmUtd2luZG93LWJ5Jywge1xuXHQgICAgICAgICAgICBkZWx0YUxlZnQsXG5cdCAgICAgICAgICAgIGRlbHRhVG9wLFxuXHQgICAgICAgICAgICBwb3NpdGlvbmluZ09wdGlvbnMsXG5cdCAgICAgICAgICAgIC4uLnRoaXMuaWRlbnRpdHlcblx0ICAgICAgICB9KVxuXHQgICAgICAgICAgICAudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBNb3ZlcyB0aGUgd2luZG93IHRvIGEgc3BlY2lmaWVkIGxvY2F0aW9uLlxuXHQgICAgICogQHBhcmFtIGxlZnQgVGhlIGxlZnQgcG9zaXRpb24gb2YgdGhlIHdpbmRvd1xuXHQgICAgICogQHBhcmFtIHRvcCBUaGUgdG9wIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93Lm1vdmVUby5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIG1vdmVUbyhsZWZ0LCB0b3ApIHtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBjcmVhdGVXaW4oKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLm1vdmVUbyhsZWZ0LCB0b3ApXG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogbW92ZVRvKDU4MCwgMzAwKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdNb3ZlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSlcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBtb3ZlVG8obGVmdCwgdG9wLCBwb3NpdGlvbmluZ09wdGlvbnMpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlXG5cdCAgICAgICAgICAgIC5zZW5kQWN0aW9uKCdtb3ZlLXdpbmRvdycsIHtcblx0ICAgICAgICAgICAgbGVmdCxcblx0ICAgICAgICAgICAgdG9wLFxuXHQgICAgICAgICAgICBwb3NpdGlvbmluZ09wdGlvbnMsXG5cdCAgICAgICAgICAgIC4uLnRoaXMuaWRlbnRpdHlcblx0ICAgICAgICB9KVxuXHQgICAgICAgICAgICAudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXNpemVzIHRoZSB3aW5kb3cgYnkgYSBzcGVjaWZpZWQgYW1vdW50LlxuXHQgICAgICogQHBhcmFtIGRlbHRhV2lkdGggVGhlIGNoYW5nZSBpbiB0aGUgd2lkdGggb2YgdGhlIHdpbmRvd1xuXHQgICAgICogQHBhcmFtIGRlbHRhSGVpZ2h0IFRoZSBjaGFuZ2UgaW4gdGhlIGhlaWdodCBvZiB0aGUgd2luZG93XG5cdCAgICAgKiBAcGFyYW0gYW5jaG9yIFNwZWNpZmllcyBhIGNvcm5lciB0byByZW1haW4gZml4ZWQgZHVyaW5nIHRoZSByZXNpemUuXG5cdCAgICAgKiBDYW4gdGFrZSB0aGUgdmFsdWVzOiBcInRvcC1sZWZ0XCIsIFwidG9wLXJpZ2h0XCIsIFwiYm90dG9tLWxlZnRcIiwgb3IgXCJib3R0b20tcmlnaHRcIi5cblx0ICAgICAqIElmIHVuZGVmaW5lZCwgdGhlIGRlZmF1bHQgaXMgXCJ0b3AtbGVmdFwiXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVXaW4oKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5yZXNpemVCeS5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHJlc2l6ZUJ5KGxlZnQsIHRvcCwgYW5jaG9yKSB7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgY3JlYXRlV2luKCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5yZXNpemVCeShsZWZ0LCB0b3AsIGFuY2hvcilcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiByZXNpemVCeSg1ODAsIDMwMCwgJ3RvcC1yaWdodCcpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1Jlc2l6ZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHJlc2l6ZUJ5KGRlbHRhV2lkdGgsIGRlbHRhSGVpZ2h0LCBhbmNob3IsIHBvc2l0aW9uaW5nT3B0aW9ucykge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmVcblx0ICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ3Jlc2l6ZS13aW5kb3ctYnknLCB7XG5cdCAgICAgICAgICAgIGRlbHRhV2lkdGg6IE1hdGguZmxvb3IoZGVsdGFXaWR0aCksXG5cdCAgICAgICAgICAgIGRlbHRhSGVpZ2h0OiBNYXRoLmZsb29yKGRlbHRhSGVpZ2h0KSxcblx0ICAgICAgICAgICAgYW5jaG9yLFxuXHQgICAgICAgICAgICBwb3NpdGlvbmluZ09wdGlvbnMsXG5cdCAgICAgICAgICAgIC4uLnRoaXMuaWRlbnRpdHlcblx0ICAgICAgICB9KVxuXHQgICAgICAgICAgICAudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXNpemVzIHRoZSB3aW5kb3cgdG8gdGhlIHNwZWNpZmllZCBkaW1lbnNpb25zLlxuXHQgICAgICogQHBhcmFtIHdpZHRoIFRoZSBjaGFuZ2UgaW4gdGhlIHdpZHRoIG9mIHRoZSB3aW5kb3dcblx0ICAgICAqIEBwYXJhbSBoZWlnaHQgVGhlIGNoYW5nZSBpbiB0aGUgaGVpZ2h0IG9mIHRoZSB3aW5kb3dcblx0ICAgICAqIEBwYXJhbSBhbmNob3IgU3BlY2lmaWVzIGEgY29ybmVyIHRvIHJlbWFpbiBmaXhlZCBkdXJpbmcgdGhlIHJlc2l6ZS5cblx0ICAgICAqIENhbiB0YWtlIHRoZSB2YWx1ZXM6IFwidG9wLWxlZnRcIiwgXCJ0b3AtcmlnaHRcIiwgXCJib3R0b20tbGVmdFwiLCBvciBcImJvdHRvbS1yaWdodFwiLlxuXHQgICAgICogSWYgdW5kZWZpbmVkLCB0aGUgZGVmYXVsdCBpcyBcInRvcC1sZWZ0XCJcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LnJlc2l6ZVRvLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gcmVzaXplVG8obGVmdCwgdG9wLCBhbmNob3IpIHtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBjcmVhdGVXaW4oKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLnJlc2l6ZVRvKGxlZnQsIHRvcCwgYW5jaG9yKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiByZXNpemVUbyg1ODAsIDMwMCwgJ3RvcC1sZWZ0JykudGhlbigoKSA9PiBjb25zb2xlLmxvZygnUmVzaXplZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgcmVzaXplVG8od2lkdGgsIGhlaWdodCwgYW5jaG9yLCBwb3NpdGlvbmluZ09wdGlvbnMpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlXG5cdCAgICAgICAgICAgIC5zZW5kQWN0aW9uKCdyZXNpemUtd2luZG93Jywge1xuXHQgICAgICAgICAgICB3aWR0aDogTWF0aC5mbG9vcih3aWR0aCksXG5cdCAgICAgICAgICAgIGhlaWdodDogTWF0aC5mbG9vcihoZWlnaHQpLFxuXHQgICAgICAgICAgICBhbmNob3IsXG5cdCAgICAgICAgICAgIHBvc2l0aW9uaW5nT3B0aW9ucyxcblx0ICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuXHQgICAgICAgIH0pXG5cdCAgICAgICAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlc3RvcmVzIHRoZSB3aW5kb3cgdG8gaXRzIG5vcm1hbCBzdGF0ZSAoaS5lLiwgdW5taW5pbWl6ZWQsIHVubWF4aW1pemVkKS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LnJlc3RvcmUuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiByZXN0b3JlKCkge1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGNyZWF0ZVdpbigpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4ucmVzdG9yZSgpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHJlc3RvcmUoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdSZXN0b3JlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgcmVzdG9yZSgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Jlc3RvcmUtd2luZG93JywgdGhpcy5pZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBXaWxsIGJyaW5nIHRoZSB3aW5kb3cgdG8gdGhlIGZyb250IG9mIHRoZSBlbnRpcmUgc3RhY2sgYW5kIGdpdmUgaXQgZm9jdXMuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVXaW4oKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5zZXRBc0ZvcmVncm91bmQuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiB0cnVlXG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGFwcC5nZXRXaW5kb3coKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBzZXRBc0ZvcmVncm91bmQoKSB7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgY3JlYXRlV2luKCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IHdpbi5zZXRBc0ZvcmVncm91bmQoKVxuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHNldEFzRm9yZWdyb3VuZCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0luIHRoZSBmb3JlZ3JvdW5kJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBzZXRBc0ZvcmVncm91bmQoKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzZXQtZm9yZWdyb3VuZC13aW5kb3cnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNldHMgdGhlIHdpbmRvdydzIHNpemUgYW5kIHBvc2l0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2luKCkge1xuXHQgICAgICogICAgIGNvbnN0IGFwcCA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5zdGFydCh7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6ICdteUFwcCcsXG5cdCAgICAgKiAgICAgICAgIHV1aWQ6ICdhcHAtMScsXG5cdCAgICAgKiAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0L3N0YWJsZS90dXRvcmlhbC1XaW5kb3cuc2V0Qm91bmRzLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gc2V0Qm91bmRzKGJvdW5kcykge1xuXHQgICAgICogICAgIGNvbnN0IHdpbiA9IGF3YWl0IGNyZWF0ZVdpbigpO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCB3aW4uc2V0Qm91bmRzKGJvdW5kcyk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogc2V0Qm91bmRzKHtcblx0ICAgICAqICAgICBoZWlnaHQ6IDEwMCxcblx0ICAgICAqICAgICB3aWR0aDogMjAwLFxuXHQgICAgICogICAgIHRvcDogNDAwLFxuXHQgICAgICogICAgIGxlZnQ6IDQwMFxuXHQgICAgICogfSkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnQm91bmRzIHNldCB0byB3aW5kb3cnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHNldEJvdW5kcyhib3VuZHMsIHBvc2l0aW9uaW5nT3B0aW9ucykge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmVcblx0ICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ3NldC13aW5kb3ctYm91bmRzJywgeyAuLi5ib3VuZHMsIC4uLnRoaXMuaWRlbnRpdHksIHBvc2l0aW9uaW5nT3B0aW9ucyB9KVxuXHQgICAgICAgICAgICAudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTaG93cyB0aGUgd2luZG93IGlmIGl0IGlzIGhpZGRlbi5cblx0ICAgICAqIEBwYXJhbSBmb3JjZSBTaG93IHdpbGwgYmUgcHJldmVudGVkIGZyb20gc2hvd2luZyB3aGVuIGZvcmNlIGlzIGZhbHNlIGFuZFxuXHQgICAgICogIOKAmHNob3ctcmVxdWVzdGVk4oCZIGhhcyBiZWVuIHN1YnNjcmliZWQgdG8gZm9yIGFwcGxpY2F0aW9u4oCZcyBtYWluIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LnNob3cuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGF1dG9TaG93OiBmYWxzZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogYXN5bmMgZnVuY3Rpb24gc2hvdygpIHtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBjcmVhdGVXaW4oKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLnNob3coKVxuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIHNob3coKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTaG93aW5nJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBzaG93KGZvcmNlID0gZmFsc2UpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Nob3ctd2luZG93JywgeyBmb3JjZSwgLi4udGhpcy5pZGVudGl0eSB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNob3dzIHRoZSB3aW5kb3cgaWYgaXQgaXMgaGlkZGVuIGF0IHRoZSBzcGVjaWZpZWQgbG9jYXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGxlZnQgVGhlIGxlZnQgcG9zaXRpb24gb2YgdGhlIHdpbmRvdyBpbiBwaXhlbHNcblx0ICAgICAqIEBwYXJhbSB0b3AgVGhlIHRvcCBwb3NpdGlvbiBvZiB0aGUgd2luZG93IGluIHBpeGVsc1xuXHQgICAgICogQHBhcmFtIGZvcmNlIFNob3cgd2lsbCBiZSBwcmV2ZW50ZWQgZnJvbSBjbG9zaW5nIHdoZW4gZm9yY2UgaXMgZmFsc2UgYW5kXG5cdCAgICAgKiDigJhzaG93LXJlcXVlc3RlZOKAmSBoYXMgYmVlbiBzdWJzY3JpYmVkIHRvIGZvciBhcHBsaWNhdGlvbuKAmXMgbWFpbiB3aW5kb3dcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LnNob3dBdC5odG1sJyxcblx0ICAgICAqICAgICAgICAgYXV0b1Nob3c6IHRydWVcblx0ICAgICAqICAgICB9KTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgYXBwLmdldFdpbmRvdygpO1xuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHNob3dBdChsZWZ0LCB0b3ApIHtcblx0ICAgICAqICAgICBjb25zdCB3aW4gPSBhd2FpdCBjcmVhdGVXaW4oKTtcblx0ICAgICAqICAgICByZXR1cm4gYXdhaXQgd2luLnNob3dBdChsZWZ0LCB0b3ApXG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogc2hvd0F0KDU4MCwgMzAwKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdTaG93aW5nIGF0JykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBzaG93QXQobGVmdCwgdG9wLCBmb3JjZSA9IGZhbHNlKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZVxuXHQgICAgICAgICAgICAuc2VuZEFjdGlvbignc2hvdy1hdC13aW5kb3cnLCB7XG5cdCAgICAgICAgICAgIGZvcmNlLFxuXHQgICAgICAgICAgICBsZWZ0OiBNYXRoLmZsb29yKGxlZnQpLFxuXHQgICAgICAgICAgICB0b3A6IE1hdGguZmxvb3IodG9wKSxcblx0ICAgICAgICAgICAgLi4udGhpcy5pZGVudGl0eVxuXHQgICAgICAgIH0pXG5cdCAgICAgICAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNob3dzIHRoZSBDaHJvbWl1bSBEZXZlbG9wZXIgVG9vbHNcblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgV2luZG93LnNob3dEZXZlbG9wZXJUb29sc1xuXHQgICAgICovXG5cdCAgICAvKipcblx0ICAgICAqIFVwZGF0ZXMgdGhlIHdpbmRvdyB1c2luZyB0aGUgcGFzc2VkIG9wdGlvbnMuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgVmFsdWVzIHRoYXQgYXJlIG9iamVjdHMgYXJlIGRlZXAtbWVyZ2VkLCBvdmVyd3JpdGluZyBvbmx5IHRoZSB2YWx1ZXMgdGhhdCBhcmUgcHJvdmlkZWQuXG5cdCAgICAgKiBAcGFyYW0gb3B0aW9ucyBDaGFuZ2VzIGEgd2luZG93J3Mgb3B0aW9ucyB0aGF0IHdlcmUgZGVmaW5lZCB1cG9uIGNyZWF0aW9uLiBTZWUgdHV0b3JpYWxcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZU9wdGlvbnMoKSB7XG5cdCAgICAgKiAgICAgY29uc3Qgd2luID0gYXdhaXQgZmluLldpbmRvdy5nZXRDdXJyZW50KCk7XG5cdCAgICAgKiAgICAgcmV0dXJuIHdpbi51cGRhdGVPcHRpb25zKHttYXhXaWR0aDogMTAwfSk7XG5cdCAgICAgKiB9XG5cdCAgICAgKiB1cGRhdGVPcHRpb25zKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnb3B0aW9ucyBpcyB1cGRhdGVkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmVycm9yKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIHVwZGF0ZU9wdGlvbnMob3B0aW9ucykge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigndXBkYXRlLXdpbmRvdy1vcHRpb25zJywgeyBvcHRpb25zLCAuLi50aGlzLmlkZW50aXR5IH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUHJvdmlkZXMgY3JlZGVudGlhbHMgdG8gYXV0aGVudGljYXRpb24gcmVxdWVzdHNcblx0ICAgICAqIEBwYXJhbSB1c2VyTmFtZSB1c2VyTmFtZSB0byBwcm92aWRlIHRvIHRoZSBhdXRoZW50aWNhdGlvbiBjaGFsbGVuZ2Vcblx0ICAgICAqIEBwYXJhbSBwYXNzd29yZCBwYXNzd29yZCB0byBwcm92aWRlIHRvIHRoZSBhdXRoZW50aWNhdGlvbiBjaGFsbGVuZ2Vcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5BcHBsaWNhdGlvbi53cmFwKHt1dWlkOiAnT3BlbmZpblBPQyd9KS50aGVuKGFwcCA9PiB7XG5cdCAgICAgKiAgICAgYXBwLm9uKCd3aW5kb3ctYXV0aC1yZXF1ZXN0ZWQnLCBldnQgPT4ge1xuXHQgICAgICogICAgICAgICBsZXQgd2luID0gZmluLldpbmRvdy53cmFwKHsgdXVpZDogZXZ0LnV1aWQsIG5hbWU6IGV2dC5uYW1lfSk7XG5cdCAgICAgKiAgICAgICAgIHdpbi5hdXRoZW50aWNhdGUoJ3VzZXJOYW1lJywgJ1BAYXNzdzByZCcpLnRoZW4oKCk9PiBjb25zb2xlLmxvZygnYXV0aGVudGljYXRlZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKiAgICAgfSk7XG5cdCAgICAgKiB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhdXRoZW50aWNhdGUodXNlck5hbWUsIHBhc3N3b3JkKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud2lyZVxuXHQgICAgICAgICAgICAuc2VuZEFjdGlvbignd2luZG93LWF1dGhlbnRpY2F0ZScsIHsgdXNlck5hbWUsIHBhc3N3b3JkLCAuLi50aGlzLmlkZW50aXR5IH0pXG5cdCAgICAgICAgICAgIC50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFNob3dzIGEgbWVudSBvbiB0aGUgd2luZG93LlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgdXNlciBoYXMgZWl0aGVyIHNlbGVjdGVkIGFuIGl0ZW0gb3IgY2xvc2VkIHRoZSBtZW51LiAoVGhpcyBtYXkgdGFrZSBsb25nZXIgdGhhbiBvdGhlciBhcGlzKS5cblx0ICAgICAqIFJlc29sdmVzIHRvIGFuIG9iamVjdCB3aXRoIGB7cmVzdWx0OiAnY2xpY2tlZCcsIGRhdGEgfWAgd2hlcmUgZGF0YSBpcyB0aGUgZGF0YSBmaWVsZCBvbiB0aGUgbWVudSBpdGVtIGNsaWNrZWQsIG9yIGB7cmVzdWx0ICdjbG9zZWQnfWAgd2hlbiB0aGUgdXNlciBkb2Vzbid0IHNlbGVjdCBhbnl0aGluZy5cblx0ICAgICAqIENhbGxpbmcgdGhpcyBtZXRob2Qgd2lsbCBjbG9zZSBwcmV2aW91c2x5IG9wZW5lZCBtZW51cy5cblx0ICAgICAqIEBleHBlcmltZW50YWxcblx0ICAgICAqIEBwYXJhbSBvcHRpb25zXG5cdCAgICAgKiBAdHlwZVBhcmFtIERhdGEgVXNlci1kZWZpbmVkIHNoYXBlIGZvciBkYXRhIHJldHVybmVkIHVwb24gbWVudSBpdGVtIGNsaWNrLiAgU2hvdWxkIGJlIGFcblx0ICAgICAqIFt1bmlvbl0oaHR0cHM6Ly93d3cudHlwZXNjcmlwdGxhbmcub3JnL2RvY3MvaGFuZGJvb2svMi9ldmVyeWRheS10eXBlcy5odG1sI3VuaW9uLXR5cGVzKVxuXHQgICAgICogb2YgYWxsIHBvc3NpYmxlIGRhdGEgc2hhcGVzIGZvciB0aGUgZW50aXJlIG1lbnUsIGFuZCB0aGUgY2xpY2sgaGFuZGxlciBzaG91bGQgcHJvY2Vzc1xuXHQgICAgICogdGhlc2Ugd2l0aCBhIFwicmVkdWNlclwiIHBhdHRlcm4uXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogVGhpcyBjb3VsZCBiZSB1c2VkIHRvIHNob3cgYSBkcm9wIGRvd24gbWVudSBvdmVyIHZpZXdzIGluIGEgcGxhdGZvcm0gd2luZG93OlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IHRlbXBsYXRlID0gW1xuXHQgICAgICogICAgIHtcblx0ICAgICAqICAgICAgICAgbGFiZWw6ICdNZW51IEl0ZW0gMScsXG5cdCAgICAgKiAgICAgICAgIGRhdGE6ICdoZWxsbyBmcm9tIGl0ZW0gMSdcblx0ICAgICAqICAgICB9LFxuXHQgICAgICogICAgIHsgdHlwZTogJ3NlcGFyYXRvcicgfSxcblx0ICAgICAqICAgICB7XG5cdCAgICAgKiAgICAgICAgIGxhYmVsOiAnTWVudSBJdGVtIDInLFxuXHQgICAgICogICAgICAgICB0eXBlOiAnY2hlY2tib3gnLFxuXHQgICAgICogICAgICAgICBjaGVja2VkOiB0cnVlLFxuXHQgICAgICogICAgICAgICBkYXRhOiAnVGhlIHVzZXIgY2xpY2tlZCB0aGUgY2hlY2tib3gnXG5cdCAgICAgKiAgICAgfSxcblx0ICAgICAqICAgICB7XG5cdCAgICAgKiAgICAgICAgIGxhYmVsOiAnc2VlIG1vcmUnLFxuXHQgICAgICogICAgICAgICBlbmFibGVkOiBmYWxzZSxcblx0ICAgICAqICAgICAgICAgc3VibWVudTogW1xuXHQgICAgICogICAgICAgICAgICAgeyBsYWJlbDogJ3N1Ym1lbnUgMScsIGRhdGE6ICdoZWxsbyBmcm9tIHN1Ym1lbnUnIH1cblx0ICAgICAqICAgICAgICAgXVxuXHQgICAgICogICAgIH1cblx0ICAgICAqIF1cblx0ICAgICAqIGZpbi5tZS5zaG93UG9wdXBNZW51KHsgdGVtcGxhdGUgfSkudGhlbihyID0+IHtcblx0ICAgICAqICAgICBpZiAoci5yZXN1bHQgPT09ICdjbG9zZWQnKSB7XG5cdCAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCdub3RoaW5nIGhhcHBlbmVkJyk7XG5cdCAgICAgKiAgICAgfSBlbHNlIHtcblx0ICAgICAqICAgICAgICAgY29uc29sZS5sb2coci5kYXRhKVxuXHQgICAgICogICAgIH1cblx0ICAgICAqIH0pXG5cdCAgICAgKiBgYGBcblx0ICAgICAqXG5cdCAgICAgKiBPdmVycmlkaW5nIHRoZSBidWlsdCBpbiBjb250ZXh0IG1lbnUgKG5vdGU6IHRoYXQgdGhpcyBjYW4gYmUgZG9uZSBwZXIgZWxlbWVudCBvciBkb2N1bWVudCB3aWRlKTpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIGUgPT4ge1xuXHQgICAgICogICAgIGUucHJldmVudERlZmF1bHQoKTtcblx0ICAgICAqICAgICBjb25zdCB0ZW1wbGF0ZSA9IFtcblx0ICAgICAqICAgICAgICAge1xuXHQgICAgICogICAgICAgICAgICAgbGFiZWw6ICdNZW51IEl0ZW0gMScsXG5cdCAgICAgKiAgICAgICAgICAgICBkYXRhOiAnaGVsbG8gZnJvbSBpdGVtIDEnXG5cdCAgICAgKiAgICAgICAgIH0sXG5cdCAgICAgKiAgICAgICAgIHsgdHlwZTogJ3NlcGFyYXRvcicgfSxcblx0ICAgICAqICAgICAgICAge1xuXHQgICAgICogICAgICAgICAgICAgbGFiZWw6ICdNZW51IEl0ZW0gMicsXG5cdCAgICAgKiAgICAgICAgICAgICB0eXBlOiAnY2hlY2tib3gnLFxuXHQgICAgICogICAgICAgICAgICAgY2hlY2tlZDogdHJ1ZSxcblx0ICAgICAqICAgICAgICAgICAgIGRhdGE6ICdUaGUgdXNlciBjbGlja2VkIHRoZSBjaGVja2JveCdcblx0ICAgICAqICAgICAgICAgfSxcblx0ICAgICAqICAgICAgICAge1xuXHQgICAgICogICAgICAgICAgICAgbGFiZWw6ICdzZWUgbW9yZScsXG5cdCAgICAgKiAgICAgICAgICAgICBlbmFibGVkOiBmYWxzZSxcblx0ICAgICAqICAgICAgICAgICAgIHN1Ym1lbnU6IFtcblx0ICAgICAqICAgICAgICAgICAgICAgICB7IGxhYmVsOiAnc3VibWVudSAxJywgZGF0YTogJ2hlbGxvIGZyb20gc3VibWVudScgfVxuXHQgICAgICogICAgICAgICAgICAgXVxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgXVxuXHQgICAgICogICAgIGZpbi5tZS5zaG93UG9wdXBNZW51KHsgdGVtcGxhdGUsIHg6IGUueCwgeTogZS55IH0pLnRoZW4ociA9PiB7XG5cdCAgICAgKiAgICAgICAgIGlmIChyLnJlc3VsdCA9PT0gJ2Nsb3NlZCcpIHtcblx0ICAgICAqICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdub3RoaW5nIGhhcHBlbmVkJyk7XG5cdCAgICAgKiAgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgKiAgICAgICAgICAgICBjb25zb2xlLmxvZyhyLmRhdGEpXG5cdCAgICAgKiAgICAgICAgIH1cblx0ICAgICAqICAgICB9KVxuXHQgICAgICogfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBzaG93UG9wdXBNZW51KG9wdGlvbnMpIHtcblx0ICAgICAgICBjb25zdCB7IHBheWxvYWQgfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzaG93LXBvcHVwLW1lbnUnLCB7IG9wdGlvbnMsIC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQ2xvc2VzIHRoZSB3aW5kb3cncyBwb3B1cCBtZW51LCBpZiBvbmUgZXhpc3RzLlxuXHQgICAgICogQGV4cGVyaW1lbnRhbFxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIE9ubHkgb25lIHBvcHVwIG1lbnUgd2lsbCBldmVyIGJlIHNob3dpbmcgYXQgYSB0aW1lLiBDYWxsaW5nIGBzaG93UG9wdXBNZW51YCB3aWxsIGF1dG9tYXRpY2FsbHkgY2xvc2Vcblx0ICAgICAqIGFueSBleGlzdGluZyBwb3B1cCBtZW51LlxuXHQgICAgICpcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogVGhpcyBjb3VsZCBiZSB1c2VkIHRvIGNsb3NlIGEgcG9wdXAgbWVudSBpZiB0aGUgdXNlcidzIG1vdXNlIGxlYXZlcyBhbiBlbGVtZW50IGZvciBleGFtcGxlLlxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhd2FpdCBmaW4ubWUuY2xvc2VQb3B1cE1lbnUoKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBjbG9zZVBvcHVwTWVudSgpIHtcblx0ICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2Nsb3NlLXBvcHVwLW1lbnUnLCB7IC4uLnRoaXMuaWRlbnRpdHkgfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBEaXNwYXRjaCBhIHJlc3VsdCB0byB0aGUgY2FsbGVyIG9mIGBzaG93UG9wdXBXaW5kb3dgLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIElmIHRoaXMgd2luZG93IGlzbid0IGN1cnJlbnRseSBiZWluZyBzaG93biBhcyBhIHBvcHVwLCB0aGlzIGNhbGwgd2lsbCBzaWxlbnRseSBmYWlsLlxuXHQgICAgICogQHBhcmFtIGRhdGEgU2VyaWFsaXphYmxlIGRhdGEgdG8gc2VuZCB0byB0aGUgY2FsbGVyIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGF3YWl0IGZpbi5tZS5kaXNwYXRjaFBvcHVwUmVzdWx0KHtcblx0ICAgICAqICAgICBmb286ICdiYXInXG5cdCAgICAgKiB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBkaXNwYXRjaFBvcHVwUmVzdWx0KGRhdGEpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignd2luZG93LWRpc3BhdGNoLXBvcHVwLXJlc3VsdCcsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdkaXNwYXRjaC1wb3B1cC1yZXN1bHQnLCB7IGRhdGEsIC4uLnRoaXMuaWRlbnRpdHkgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFByaW50cyB0aGUgY29udGVudHMgb2YgdGhlIHdpbmRvdy5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gb3B0aW9ucyBDb25maWd1cmF0aW9uIGZvciB0aGUgcHJpbnQgdGFzay5cblx0ICAgICAqIEByZW1hcmtzIFdoZW4gYHNpbGVudGAgaXMgc2V0IHRvIGB0cnVlYCwgdGhlIEFQSSB3aWxsIHBpY2sgdGhlIHN5c3RlbSdzIGRlZmF1bHQgcHJpbnRlciBpZiBkZXZpY2VOYW1lIGlzIGVtcHR5XG5cdCAgICAgKiBhbmQgdGhlIGRlZmF1bHQgc2V0dGluZ3MgZm9yIHByaW50aW5nLlxuXHQgICAgICpcblx0ICAgICAqIFVzZSB0aGUgQ1NTIHN0eWxlIGBwYWdlLWJyZWFrLWJlZm9yZTogYWx3YXlzO2AgdG8gZm9yY2UgcHJpbnQgdG8gYSBuZXcgcGFnZS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IHdpbiA9IGZpbi5XaW5kb3cuZ2V0Q3VycmVudFN5bmMoKTtcblx0ICAgICAqXG5cdCAgICAgKiB3aW4ucHJpbnQoeyBzaWxlbnQ6IGZhbHNlLCBkZXZpY2VOYW1lOiAnc3lzdGVtLXByaW50ZXItbmFtZScgfSkudGhlbigoKSA9PiB7XG5cdCAgICAgKiAgICAgY29uc29sZS5sb2coJ3ByaW50IGNhbGwgaGFzIGJlZW4gc2VudCB0byB0aGUgc3lzdGVtJyk7XG5cdCAgICAgKiB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqIElmIGEgd2luZG93IGhhcyBlbWJlZGRlZCB2aWV3cywgdGhvc2Ugdmlld3Mgd2lsbCBub3QgcHJpbnQgYnkgZGVmYXVsdC4gIFRvIHByaW50IGEgd2luZG93J3MgY29udGVudHMgaW5jbHVkaW5nIGVtYmVkZGVkIHZpZXdzLFxuXHQgICAgICogdXNlIHRoZSBgY29udGVudGAgb3B0aW9uOlxuXHQgICAgICpcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCB3aW4gPSBmaW4uV2luZG93LmdldEN1cnJlbnRTeW5jKCk7XG5cdCAgICAgKlxuXHQgICAgICogLy8gUHJpbnQgZW1iZWRkZWQgdmlld3Ncblx0ICAgICAqIHdpbi5wcmludCh7IGNvbnRlbnQ6ICd2aWV3cycgfSk7XG5cdCAgICAgKlxuXHQgICAgICogLy8gUHJpbnQgc2NyZWVuc2hvdCBvZiBjdXJyZW50IHdpbmRvd1xuXHQgICAgICogd2luLnByaW50KHsgY29udGVudDogJ3NjcmVlbnNob3QnIH0pXG5cdCAgICAgKiBgYGBcblx0ICAgICAqXG5cdCAgICAgKiBXaGVuIGBjb250ZW50YCBpcyBzZXQgdG8gYHZpZXdzYCwgdGhlIGVtYmVkZGVkIHZpZXdzIGluIHRoZSBwbGF0Zm9ybSB3aW5kb3cgd2lsbCBiZSBjb25jYXRlbmF0ZWQgYW5kIHByaW50ZWQgYXNcblx0ICAgICAqIGluZGl2aWR1YWwgcGFnZXMuICBJZiBgaW5jbHVkZVNlbGZgIGlzIHNldCB0byBgdHJ1ZWAsIHRoZSBwbGF0Zm9ybSB3aW5kb3cgaXRzZWxmIHdpbGwgYmUgcHJpbnRlZCBhcyB0aGUgZmlyc3Rcblx0ICAgICAqIHBhZ2UgLSBiZSBhd2FyZSB0aGF0IHRoaXMgcGFnZSB3aWxsICpub3QqIGluY2x1ZGUgdGhlIGVtYmVkZGVkIHZpZXdzIC0gaXQgd2lsbCBvbmx5IGluY2x1ZGUgdGhlIGNvbnRlbnRzIG9mXG5cdCAgICAgKiB0aGUgcGxhdGZvcm0gd2luZG93IGl0c2VsZiAoZS5nLiB0YWIgc3RhY2tzKSwgd2l0aCBibGFuayBzcGFjZXMgd2hlcmUgdGhlIHZpZXcgY29udGVudHMgd291bGQgYmUgZW1iZWRkZWQuXG5cdCAgICAgKlxuXHQgICAgICogRHVlIHRvIGEga25vd24gaXNzdWUsIHZpZXcgY29udGVudHMgdGhhdCBhcmUgbm90IHZpc2libGUgYXQgdGhlIHRpbWUgYHByaW50YCBpcyBjYWxsZWQgd2lsbCBub3QgYXBwZWFyIHdoZW5cblx0ICAgICAqIHByaW50aW5nIGBjb250ZW50czogdmlld3NgLiAgVGhpcyBpbmNsdWRlcyB2aWV3cyB0aGF0IGFyZSBvYnNjdXJlZCBiZWhpbmQgb3RoZXIgYWN0aXZlIFVJIGVsZW1lbnRzLlxuXHQgICAgICpcblx0ICAgICAqIFRvIHByaW50IHRoZSB2aWV3cyBlbWJlZGRlZCBpbiB0aGVpciBwYWdlIGNvbnRleHQsIHNldCBgY29udGVudGAgdG8gYHNjcmVlbnNob3RgLlxuXHQgICAgICovXG5cdCAgICBhc3luYyBwcmludChvcHRpb25zID0geyBjb250ZW50OiAnc2VsZicgfSkge1xuXHQgICAgICAgIHN3aXRjaCAob3B0aW9ucy5jb250ZW50KSB7XG5cdCAgICAgICAgICAgIGNhc2UgdW5kZWZpbmVkOlxuXHQgICAgICAgICAgICBjYXNlICdzZWxmJzpcblx0ICAgICAgICAgICAgICAgIHJldHVybiBzdXBlci5wcmludChvcHRpb25zKTtcblx0ICAgICAgICAgICAgY2FzZSAnc2NyZWVuc2hvdCc6XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3ByaW50LXNjcmVlbnNob3QnLCB0aGlzLmlkZW50aXR5KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG5cdCAgICAgICAgICAgIGNhc2UgJ3ZpZXdzJzpcblx0ICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbigncHJpbnQtdmlld3MnLCB7IC4uLnRoaXMuaWRlbnRpdHksIG9wdGlvbnMgfSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuXHQgICAgICAgICAgICBkZWZhdWx0OlxuXHQgICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdH1cblx0SW5zdGFuY2UkNy5fV2luZG93ID0gX1dpbmRvdztcblx0cmV0dXJuIEluc3RhbmNlJDc7XG59XG5cbnZhciBoYXNSZXF1aXJlZEZhY3RvcnkkMTtcblxuZnVuY3Rpb24gcmVxdWlyZUZhY3RvcnkkMSAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZEZhY3RvcnkkMSkgcmV0dXJuIEZhY3RvcnkkODtcblx0aGFzUmVxdWlyZWRGYWN0b3J5JDEgPSAxO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoRmFjdG9yeSQ4LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0RmFjdG9yeSQ4Ll9XaW5kb3dNb2R1bGUgPSB2b2lkIDA7XG5cdGNvbnN0IGJhc2VfMSA9IGJhc2U7XG5cdGNvbnN0IHZhbGlkYXRlXzEgPSB2YWxpZGF0ZTtcblx0Y29uc3QgSW5zdGFuY2VfMSA9IHJlcXVpcmVJbnN0YW5jZSgpO1xuXHQvKipcblx0ICogU3RhdGljIG5hbWVzcGFjZSBmb3IgT3BlbkZpbiBBUEkgbWV0aG9kcyB0aGF0IGludGVyYWN0IHdpdGggdGhlIHtAbGluayBfV2luZG93fSBjbGFzcywgYXZhaWxhYmxlIHVuZGVyIGBmaW4uV2luZG93YC5cblx0ICovXG5cdGNsYXNzIF9XaW5kb3dNb2R1bGUgZXh0ZW5kcyBiYXNlXzEuQmFzZSB7XG5cdCAgICAvKipcblx0ICAgICAqIEFzeW5jaHJvbm91c2x5IHJldHVybnMgYW4gQVBJIGhhbmRsZSBmb3IgdGhlIGdpdmVuIFdpbmRvdyBpZGVudGl0eS5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBXcmFwcGluZyBhIFdpbmRvdyBpZGVudGl0eSB0aGF0IGRvZXMgbm90IHlldCBleGlzdCB3aWxsICpub3QqIHRocm93IGFuIGVycm9yLCBhbmQgaW5zdGVhZFxuXHQgICAgICogcmV0dXJucyBhIHN0dWIgb2JqZWN0IHRoYXQgY2Fubm90IHlldCBwZXJmb3JtIHJlbmRlcmluZyB0YXNrcy4gVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBwbHVtYmluZyBldmVudGluZ1xuXHQgICAgICogZm9yIGEgV2luZG93IHRocm91Z2hvdXQgaXRzIGVudGlyZSBsaWZlY3ljbGUuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVXaW4oKSB7XG5cdCAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0KHtcblx0ICAgICAqICAgICAgICAgbmFtZTogJ215QXBwJyxcblx0ICAgICAqICAgICAgICAgdXVpZDogJ2FwcC0xJyxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy53cmFwLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKiBjcmVhdGVXaW4oKS50aGVuKCgpID0+IGZpbi5XaW5kb3cud3JhcCh7IHV1aWQ6ICdhcHAtMScsIG5hbWU6ICdteUFwcCcgfSkpXG5cdCAgICAgKiAudGhlbih3aW4gPT4gY29uc29sZS5sb2coJ3dyYXBwZWQgd2luZG93JykpXG5cdCAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHdyYXAoaWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignd2luZG93LXdyYXAnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBlcnJvck1zZyA9ICgwLCB2YWxpZGF0ZV8xLnZhbGlkYXRlSWRlbnRpdHkpKGlkZW50aXR5KTtcblx0ICAgICAgICBpZiAoZXJyb3JNc2cpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTXNnKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIG5ldyBJbnN0YW5jZV8xLl9XaW5kb3codGhpcy53aXJlLCBpZGVudGl0eSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFN5bmNocm9ub3VzbHkgcmV0dXJucyBhbiBBUEkgaGFuZGxlIGZvciB0aGUgZ2l2ZW4gV2luZG93IGlkZW50aXR5LlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFdyYXBwaW5nIGEgV2luZG93IGlkZW50aXR5IHRoYXQgZG9lcyBub3QgeWV0IGV4aXN0IHdpbGwgKm5vdCogdGhyb3cgYW4gZXJyb3IsIGFuZCBpbnN0ZWFkXG5cdCAgICAgKiByZXR1cm5zIGEgc3R1YiBvYmplY3QgdGhhdCBjYW5ub3QgeWV0IHBlcmZvcm0gcmVuZGVyaW5nIHRhc2tzLiBUaGlzIGNhbiBiZSB1c2VmdWwgZm9yIHBsdW1iaW5nIGV2ZW50aW5nXG5cdCAgICAgKiBmb3IgYSBXaW5kb3cgdGhyb3VnaG91dCBpdHMgZW50aXJlIGxpZmVjeWNsZS5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbigpIHtcblx0ICAgICAqICAgICBjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnQoe1xuXHQgICAgICogICAgICAgICBuYW1lOiAnbXlBcHAnLFxuXHQgICAgICogICAgICAgICB1dWlkOiAnYXBwLTEnLFxuXHQgICAgICogICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9zdGFibGUvdHV0b3JpYWwtV2luZG93LndyYXBTeW5jLmh0bWwnLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogICAgIHJldHVybiBhd2FpdCBhcHAuZ2V0V2luZG93KCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKiBhd2FpdCBjcmVhdGVXaW4oKTtcblx0ICAgICAqIGxldCB3aW4gPSBmaW4uV2luZG93LndyYXBTeW5jKHsgdXVpZDogJ2FwcC0xJywgbmFtZTogJ215QXBwJyB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICB3cmFwU3luYyhpZGVudGl0eSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd3aW5kb3ctd3JhcC1zeW5jJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgZXJyb3JNc2cgPSAoMCwgdmFsaWRhdGVfMS52YWxpZGF0ZUlkZW50aXR5KShpZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKGVycm9yTXNnKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvck1zZyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMS5fV2luZG93KHRoaXMud2lyZSwgaWRlbnRpdHkpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBDcmVhdGVzIGEgbmV3IFdpbmRvdy5cblx0ICAgICAqIEBwYXJhbSBvcHRpb25zIC0gV2luZG93IGNyZWF0aW9uIG9wdGlvbnNcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVdpbmRvdygpIHtcblx0ICAgICAqICAgICBjb25zdCB3aW5PcHRpb24gPSB7XG5cdCAgICAgKiAgICAgICAgIG5hbWU6J2NoaWxkJyxcblx0ICAgICAqICAgICAgICAgZGVmYXVsdFdpZHRoOiAzMDAsXG5cdCAgICAgKiAgICAgICAgIGRlZmF1bHRIZWlnaHQ6IDMwMCxcblx0ICAgICAqICAgICAgICAgdXJsOiAnaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVdpbmRvdy5jcmVhdGUuaHRtbCcsXG5cdCAgICAgKiAgICAgICAgIGZyYW1lOiB0cnVlLFxuXHQgICAgICogICAgICAgICBhdXRvU2hvdzogdHJ1ZVxuXHQgICAgICogICAgIH07XG5cdCAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGZpbi5XaW5kb3cuY3JlYXRlKHdpbk9wdGlvbik7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogY3JlYXRlV2luZG93KCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnV2luZG93IGlzIGNyZWF0ZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGNyZWF0ZShvcHRpb25zKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NyZWF0ZS13aW5kb3cnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCB3aW4gPSBuZXcgSW5zdGFuY2VfMS5fV2luZG93KHRoaXMud2lyZSwgeyB1dWlkOiB0aGlzLm1lLnV1aWQsIG5hbWU6IG9wdGlvbnMubmFtZSB9KTtcblx0ICAgICAgICByZXR1cm4gd2luLmNyZWF0ZVdpbmRvdyhvcHRpb25zKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhIFdpbmRvdyBvYmplY3QgdGhhdCByZXByZXNlbnRzIHRoZSBjdXJyZW50IHdpbmRvd1xuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLldpbmRvdy5nZXRDdXJyZW50KClcblx0ICAgICAqIC50aGVuKHduZCA9PiBjb25zb2xlLmxvZygnY3VycmVudCB3aW5kb3cnKSlcblx0ICAgICAqIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG5cdCAgICAgKlxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGdldEN1cnJlbnQoKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1jdXJyZW50LXdpbmRvdycpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGlmICghdGhpcy53aXJlLm1lLmlzV2luZG93KSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IGFyZSBub3QgaW4gYSBXaW5kb3cgY29udGV4dCcpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IHRoaXMud2lyZS5tZTtcblx0ICAgICAgICByZXR1cm4gdGhpcy53cmFwKHsgdXVpZCwgbmFtZSB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGEgV2luZG93IG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIGN1cnJlbnQgd2luZG93XG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBjb25zdCB3bmQgPSBmaW4uV2luZG93LmdldEN1cnJlbnRTeW5jKCk7XG5cdCAgICAgKiBjb25zdCBpbmZvID0gYXdhaXQgd25kLmdldEluZm8oKTtcblx0ICAgICAqIGNvbnNvbGUubG9nKGluZm8pO1xuXHQgICAgICpcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBnZXRDdXJyZW50U3luYygpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWN1cnJlbnQtd2luZG93LXN5bmMnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBpZiAoIXRoaXMud2lyZS5tZS5pc1dpbmRvdykge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBhcmUgbm90IGluIGEgV2luZG93IGNvbnRleHQnKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSB0aGlzLndpcmUubWU7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMud3JhcFN5bmMoeyB1dWlkLCBuYW1lIH0pO1xuXHQgICAgfVxuXHR9XG5cdEZhY3RvcnkkOC5fV2luZG93TW9kdWxlID0gX1dpbmRvd01vZHVsZTtcblx0cmV0dXJuIEZhY3RvcnkkODtcbn1cblxudmFyIGhhc1JlcXVpcmVkV2luZG93O1xuXG5mdW5jdGlvbiByZXF1aXJlV2luZG93ICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkV2luZG93KSByZXR1cm4gd2luZG93JDE7XG5cdGhhc1JlcXVpcmVkV2luZG93ID0gMTtcblx0KGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdFx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdFx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdFx0ICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcblx0XHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0XHQgICAgICBkZXNjID0geyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbVtrXTsgfSB9O1xuXHRcdCAgICB9XG5cdFx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdFx0fSkgOiAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcblx0XHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0XHQgICAgb1trMl0gPSBtW2tdO1xuXHRcdH0pKTtcblx0XHR2YXIgX19leHBvcnRTdGFyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fZXhwb3J0U3RhcikgfHwgZnVuY3Rpb24obSwgZXhwb3J0cykge1xuXHRcdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdFx0fTtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdFx0LyoqXG5cdFx0ICogRW50cnkgcG9pbnRzIGZvciB0aGUgT3BlbkZpbiBgV2luZG93YCBBUEkgKGBmaW4uV2luZG93YCkuXG5cdFx0ICpcblx0XHQgKiAqIHtAbGluayBfV2luZG93TW9kdWxlfSBjb250YWlucyBzdGF0aWMgbWVtYmVycyBvZiB0aGUgYFdpbmRvd2AgQVBJLCBhY2Nlc3NpYmxlIHRocm91Z2ggYGZpbi5XaW5kb3dgLlxuXHRcdCAqICoge0BsaW5rIF9XaW5kb3d9IGRlc2NyaWJlcyBhbiBpbnN0YW5jZSBvZiBhbiBPcGVuRmluIFdpbmRvdywgZS5nLiBhcyByZXR1cm5lZCBieSBgZmluLldpbmRvdy5nZXRDdXJyZW50YC5cblx0XHQgKlxuXHRcdCAqIFRoZXNlIGFyZSBzZXBhcmF0ZSBjb2RlIGVudGl0aWVzLCBhbmQgYXJlIGRvY3VtZW50ZWQgc2VwYXJhdGVseS4gIEluIHRoZSBbcHJldmlvdXMgdmVyc2lvbiBvZiB0aGUgQVBJIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vY2RuLm9wZW5maW4uY28vZG9jcy9qYXZhc2NyaXB0LzMyLjExNC43Ni4xMC9pbmRleC5odG1sKSxcblx0XHQgKiBib3RoIG9mIHRoZXNlIHdlcmUgZG9jdW1lbnRlZCBvbiB0aGUgc2FtZSBwYWdlLlxuXHRcdCAqXG5cdFx0ICogVW5kZXJzY29yZSBwcmVmaXhpbmcgb2YgT3BlbkZpbiB0eXBlcyB0aGF0IGFsaWFzIERPTSBlbnRpdGllcyB3aWxsIGJlIGZpeGVkIGluIGEgZnV0dXJlIHZlcnNpb24uXG5cdFx0ICpcblx0XHQgKiBAcGFja2FnZURvY3VtZW50YXRpb25cblx0XHQgKi9cblx0XHRfX2V4cG9ydFN0YXIocmVxdWlyZUZhY3RvcnkkMSgpLCBleHBvcnRzKTtcblx0XHRfX2V4cG9ydFN0YXIocmVxdWlyZUluc3RhbmNlKCksIGV4cG9ydHMpOyBcblx0fSAod2luZG93JDEpKTtcblx0cmV0dXJuIHdpbmRvdyQxO1xufVxuXG4vKipcbiAqIEVudHJ5IHBvaW50IGZvciB0aGUgT3BlbkZpbiBgU3lzdGVtYCBBUEkgKGBmaW4uU3lzdGVtYCkuXG4gKlxuICogKiB7QGxpbmsgU3lzdGVtfSBjb250YWlucyBzdGF0aWMgbWVtYmVycyBvZiB0aGUgYFN5c3RlbWAgQVBJIChhdmFpbGFibGUgdW5kZXIgYGZpbi5TeXN0ZW1gKVxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoc3lzdGVtLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnN5c3RlbS5TeXN0ZW0gPSB2b2lkIDA7XG5jb25zdCBiYXNlXzEkaSA9IGJhc2U7XG5jb25zdCB0cmFuc3BvcnRfZXJyb3JzXzEkMSA9IHRyYW5zcG9ydEVycm9ycztcbmNvbnN0IHdpbmRvd18xID0gcmVxdWlyZVdpbmRvdygpO1xuY29uc3QgZXZlbnRzXzEkNiA9IHJlcXVpcmUkJDA7XG4vKipcbiAqIEFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGNvcmUgb2YgT3BlbkZpbiBSdW50aW1lLiBBbGxvd3MgdGhlIGRldmVsb3BlclxuICogdG8gcGVyZm9ybSBzeXN0ZW0tbGV2ZWwgYWN0aW9ucywgc3VjaCBhcyBhY2Nlc3NpbmcgbG9ncywgdmlld2luZyBwcm9jZXNzZXMsXG4gKiBjbGVhcmluZyB0aGUgY2FjaGUgYW5kIGV4aXRpbmcgdGhlIHJ1bnRpbWUgYXMgd2VsbCBhcyBsaXN0ZW4gdG8ge0BsaW5rIE9wZW5GaW4uU3lzdGVtRXZlbnRzIHN5c3RlbSBldmVudHN9LlxuICpcbiAqL1xuY2xhc3MgU3lzdGVtIGV4dGVuZHMgYmFzZV8xJGkuRW1pdHRlckJhc2Uge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHdpcmUpIHtcbiAgICAgICAgc3VwZXIod2lyZSwgJ3N5c3RlbScpO1xuICAgIH1cbiAgICBzZW5kRXh0ZXJuYWxQcm9jZXNzUmVxdWVzdChhY3Rpb24sIG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGV4aXRFdmVudEtleSA9ICdleHRlcm5hbC1wcm9jZXNzLWV4aXRlZCc7XG4gICAgICAgICAgICBsZXQgcHJvY2Vzc1V1aWQ7XG4gICAgICAgICAgICBsZXQgZXhpdFBheWxvYWQ7XG4gICAgICAgICAgICBsZXQgZXh0ZXJuYWxQcm9jZXNzRXhpdEhhbmRsZXI7XG4gICAgICAgICAgICBsZXQgb2ZXaW5kb3c7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMubGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICBleHRlcm5hbFByb2Nlc3NFeGl0SGFuZGxlciA9IChwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBwYXlsb2FkIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICBleGl0UGF5bG9hZCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcGljOiAnZXhpdGVkJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHV1aWQ6IGRhdGEucHJvY2Vzc1V1aWQgfHwgJycsXG4gICAgICAgICAgICAgICAgICAgICAgICBleGl0Q29kZTogZGF0YS5leGl0Q29kZSB8fCAwXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9jZXNzVXVpZCA9PT0gcGF5bG9hZC5wcm9jZXNzVXVpZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5saXN0ZW5lcihleGl0UGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvZldpbmRvdy5yZW1vdmVMaXN0ZW5lcihleGl0RXZlbnRLZXksIGV4dGVybmFsUHJvY2Vzc0V4aXRIYW5kbGVyKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgLy8gd2luZG93IGNvbnN0cnVjdG9yIGV4cGVjdHMgdGhlIG5hbWUgaXMgbm90IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIGlmICghdGhpcy53aXJlLm1lLm5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy53aXJlLm1lLm5hbWUgPSB0aGlzLndpcmUubWUudXVpZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb2ZXaW5kb3cgPSBuZXcgd2luZG93XzEuX1dpbmRvdyh0aGlzLndpcmUsIHRoaXMud2lyZS5tZSk7XG4gICAgICAgICAgICAgICAgb2ZXaW5kb3cub24oZXhpdEV2ZW50S2V5LCBleHRlcm5hbFByb2Nlc3NFeGl0SGFuZGxlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndpcmVcbiAgICAgICAgICAgICAgICAuc2VuZEFjdGlvbihhY3Rpb24sIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiB7XG4gICAgICAgICAgICAgICAgcHJvY2Vzc1V1aWQgPSBwYXlsb2FkLmRhdGEudXVpZDtcbiAgICAgICAgICAgICAgICByZXNvbHZlKHBheWxvYWQuZGF0YSk7XG4gICAgICAgICAgICAgICAgaWYgKGV4aXRQYXlsb2FkICYmIHByb2Nlc3NVdWlkID09PSBleGl0UGF5bG9hZC51dWlkKSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMubGlzdGVuZXIoZXhpdFBheWxvYWQpO1xuICAgICAgICAgICAgICAgICAgICBvZldpbmRvdy5yZW1vdmVMaXN0ZW5lcihleGl0RXZlbnRLZXksIGV4dGVybmFsUHJvY2Vzc0V4aXRIYW5kbGVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKG9mV2luZG93KSB7XG4gICAgICAgICAgICAgICAgICAgIG9mV2luZG93LnJlbW92ZUxpc3RlbmVyKGV4aXRFdmVudEtleSwgZXh0ZXJuYWxQcm9jZXNzRXhpdEhhbmRsZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgdmVyc2lvbiBvZiB0aGUgcnVudGltZS4gVGhlIHZlcnNpb24gY29udGFpbnMgdGhlIG1ham9yLCBtaW5vcixcbiAgICAgKiBidWlsZCBhbmQgcmV2aXNpb24gbnVtYmVycy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldFZlcnNpb24oKS50aGVuKHYgPT4gY29uc29sZS5sb2codikpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRWZXJzaW9uKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC12ZXJzaW9uJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENsZWFycyBjYWNoZWQgZGF0YSBjb250YWluaW5nIGFwcGxpY2F0aW9uIHJlc291cmNlXG4gICAgICogZmlsZXMgKGltYWdlcywgSFRNTCwgSmF2YVNjcmlwdCBmaWxlcyksIGNvb2tpZXMsIGFuZCBpdGVtcyBzdG9yZWQgaW4gdGhlXG4gICAgICogTG9jYWwgU3RvcmFnZS5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIFNlZSBiZWxvdyBmb3IgZGV0YWlscy5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIEZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHRoZSBhY2NlcHRlZCBvcHRpb25zLCBzZWUgdGhlIGZvbGxvd2luZyBwYWdlczpcbiAgICAgKiAqIGNhY2hlOiBicm93c2luZyBkYXRhIGNhY2hlIGZvciBodG1sIGZpbGVzIGFuZCBpbWFnZXMgKFtjYWNoaW5nXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVFRQL0NhY2hpbmcpKVxuICAgICAqICogY29va2llczogYnJvd3NlciBbY29va2llc10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRUUC9Db29raWVzKVxuICAgICAqICogbG9jYWxTdG9yYWdlOiBicm93c2VyIGRhdGEgdGhhdCBjYW4gYmUgdXNlZCBhY3Jvc3Mgc2Vzc2lvbnMgKFtsb2NhbCBzdG9yYWdlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93L2xvY2FsU3RvcmFnZSkpXG4gICAgICogKiBhcHBjYWNoZTogaHRtbDUgW2FwcGxpY2F0aW9uIGNhY2hlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML1VzaW5nX3RoZV9hcHBsaWNhdGlvbl9jYWNoZSlcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgY2xlYXJDYWNoZU9wdGlvbnMgPSB7XG4gICAgICogICAgIGFwcGNhY2hlOiB0cnVlLFxuICAgICAqICAgICBjYWNoZTogdHJ1ZSxcbiAgICAgKiAgICAgY29va2llczogdHJ1ZSxcbiAgICAgKiAgICAgbG9jYWxTdG9yYWdlOiB0cnVlXG4gICAgICogfTtcbiAgICAgKiBmaW4uU3lzdGVtLmNsZWFyQ2FjaGUoY2xlYXJDYWNoZU9wdGlvbnMpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0NhY2hlIGNsZWFyZWQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICovXG4gICAgY2xlYXJDYWNoZShvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignY2xlYXItY2FjaGUnLCBvcHRpb25zKS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENsZWFycyBhbGwgY2FjaGVkIGRhdGEgd2hlbiBPcGVuRmluIFJ1bnRpbWUgZXhpdHMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5kZWxldGVDYWNoZU9uRXhpdCgpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0RlbGV0ZWQgQ2FjaGUnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGRlbGV0ZUNhY2hlT25FeGl0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2RlbGV0ZS1jYWNoZS1yZXF1ZXN0JykudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBFeGl0cyB0aGUgUnVudGltZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmV4aXQoKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdleGl0JykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBleGl0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2V4aXQtZGVza3RvcCcpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyBhIEpTT04gbWFuaWZlc3QgdXNpbmcgdGhlIGJyb3dzZXIgcHJvY2VzcyBhbmQgcmV0dXJucyBhIEphdmFzY3JpcHQgb2JqZWN0LlxuICAgICAqIEBwYXJhbSBtYW5pZmVzdFVybCBUaGUgVVJMIG9mIHRoZSBtYW5pZmVzdCB0byBmZXRjaC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBtYW5pZmVzdCA9IGF3YWl0IGZpbi5TeXN0ZW0uZmV0Y2hNYW5pZmVzdCgnaHR0cHM6Ly93d3cucGF0aC10by1tYW5pZmVzdC5jb20nKTtcbiAgICAgKiBjb25zb2xlLmxvZyhtYW5pZmVzdCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZmV0Y2hNYW5pZmVzdChtYW5pZmVzdFVybCkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgZGF0YSB9IH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZmV0Y2gtbWFuaWZlc3QnLCB7IG1hbmlmZXN0VXJsIH0pO1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogV3JpdGVzIGFueSB1bndyaXR0ZW4gY29va2llcyBkYXRhIHRvIGRpc2suXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5mbHVzaENvb2tpZVN0b3JlKClcbiAgICAgKiAgICAgLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ3N1Y2Nlc3MnKSlcbiAgICAgKiAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmVycm9yKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGZsdXNoQ29va2llU3RvcmUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZmx1c2gtY29va2llLXN0b3JlJykudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYW4gYXJyYXkgb2YgZGF0YSAobmFtZSwgaWRzLCBib3VuZHMpIGZvciBhbGwgYXBwbGljYXRpb24gd2luZG93cy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldEFsbFdpbmRvd3MoKS50aGVuKHdpbnMgPT4gY29uc29sZS5sb2cod2lucykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRBbGxXaW5kb3dzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1hbGwtd2luZG93cycpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYW4gYXJyYXkgb2YgZGF0YSBmb3IgYWxsIGFwcGxpY2F0aW9ucy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldEFsbEFwcGxpY2F0aW9ucygpLnRoZW4oYXBwcyA9PiBjb25zb2xlLmxvZyhhcHBzKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldEFsbEFwcGxpY2F0aW9ucygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtYWxsLWFwcGxpY2F0aW9ucycpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIGNvbW1hbmQgbGluZSBhcmd1bWVudCBzdHJpbmcgdGhhdCBzdGFydGVkIE9wZW5GaW4gUnVudGltZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldENvbW1hbmRMaW5lQXJndW1lbnRzKCkudGhlbihhcmdzID0+IGNvbnNvbGUubG9nKGFyZ3MpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0Q29tbWFuZExpbmVBcmd1bWVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWNvbW1hbmQtbGluZS1hcmd1bWVudHMnKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBjcmFzaCByZXBvcnRlci5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldENyYXNoUmVwb3J0ZXJTdGF0ZSgpLnRoZW4oc3RhdGUgPT4gY29uc29sZS5sb2coc3RhdGUpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZ2V0Q3Jhc2hSZXBvcnRlclN0YXRlKCkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgZGF0YTogeyBkaWFnbm9zdGljTW9kZSwgaXNSdW5uaW5nIH0gfSB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1jcmFzaC1yZXBvcnRlci1zdGF0ZScpO1xuICAgICAgICBjb25zb2xlLndhcm4oJ2RpYWdub3N0aWNNb2RlIHByb3BlcnR5IGlzIGRlcHJlY2F0ZWQuIEl0IHdpbGwgYmUgcmVtb3ZlZCBpbiBhIGZ1dHVyZSB2ZXJzaW9uJyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAvLyBkaWFnbm9zdGljTW9kZSB3aWxsIGJlIHJlbW92ZWQgaW4gYSBmdXR1cmUgdmVyc2lvblxuICAgICAgICAgICAgZGlhZ25vc3RpY01vZGUsXG4gICAgICAgICAgICBkaWFnbm9zdGljc01vZGU6IGRpYWdub3N0aWNNb2RlLFxuICAgICAgICAgICAgaXNSdW5uaW5nXG4gICAgICAgIH07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN0YXJ0IHRoZSBjcmFzaCByZXBvcnRlciBpZiBub3QgYWxyZWFkeSBydW5uaW5nLlxuICAgICAqIEBwYXJhbSBvcHRpb25zIC0gY29uZmlndXJlIGNyYXNoIHJlcG9ydGVyXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBZb3UgY2FuIG9wdGlvbmFsbHkgc3BlY2lmeSBgZGlhZ25vc3RpY3NNb2RlYCB0byBoYXZlIHRoZSBsb2dzIHNlbnQgdG9cbiAgICAgKiBPcGVuRmluIG9uIHJ1bnRpbWUgY2xvc2UuIChOT1RFOiBgZGlhZ25vc3RpY3NNb2RlYCB3aWxsIHR1cm4gb24gdmVyYm9zZSBsb2dnaW5nIGFuZCBkaXNhYmxlIHRoZSBzYW5kYm94XG4gICAgICogZm9yIG5ld2x5IGxhdW5jaGVkIHJlbmRlcmVyIHByb2Nlc3Nlcy4gU2VlIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL29mLWRvY3MvZG9jcy9kZWJ1Z2dpbmcjZGlhZ25vc3RpY3MtbW9kZSBmb3JcbiAgICAgKiBtb3JlIGRldGFpbHMuKVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uc3RhcnRDcmFzaFJlcG9ydGVyKHtkaWFnbm9zdGljc01vZGU6IHRydWV9KS50aGVuKHJlcG9ydGVyID0+IGNvbnNvbGUubG9nKHJlcG9ydGVyKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHN0YXJ0Q3Jhc2hSZXBvcnRlcihvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IG9wdHMgPSBvcHRpb25zO1xuICAgICAgICBjb25zdCBuZXdPcHRzID0geyAuLi5vcHRzLCBkaWFnbm9zdGljTW9kZTogb3B0cy5kaWFnbm9zdGljc01vZGUgfHwgb3B0cy5kaWFnbm9zdGljTW9kZSB9O1xuICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgZGF0YTogeyBkaWFnbm9zdGljTW9kZSwgaXNSdW5uaW5nIH0gfSB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3N0YXJ0LWNyYXNoLXJlcG9ydGVyJywgbmV3T3B0cyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAvLyBkaWFnbm9zdGljTW9kZSB3aWxsIGJlIHJlbW92ZWQgaW4gYSBmdXR1cmUgdmVyc2lvblxuICAgICAgICAgICAgZGlhZ25vc3RpY01vZGUsXG4gICAgICAgICAgICBkaWFnbm9zdGljc01vZGU6IGRpYWdub3N0aWNNb2RlLFxuICAgICAgICAgICAgaXNSdW5uaW5nXG4gICAgICAgIH07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBoZXggZW5jb2RlZCBoYXNoIG9mIHRoZSBtYWNoaW5lIGlkIGFuZCB0aGUgY3VycmVudGx5IGxvZ2dlZCBpbiB1c2VyIG5hbWUuXG4gICAgICogVGhpcyBpcyB0aGUgcmVjb21tZW5kZWQgd2F5IHRvIHVuaXF1ZWx5IGlkZW50aWZ5IGEgdXNlciAvIG1hY2hpbmUgY29tYmluYXRpb24uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBGb3IgV2luZG93cyBzeXN0ZW1zIHRoaXMgaXMgYSBzaGEyNTYgaGFzaCBvZiB0aGUgbWFjaGluZSBJRCBzZXQgaW4gdGhlIHJlZ2lzdHJ5IGtleTpcbiAgICAgKiBgSEtFWV9MT0NBTF9NQUNISU5FXFxTT0ZUV0FSRVxcTWljcm9zb2Z0XFxDcnlwdG9ncmFwaHlcXE1hY2hpbmVHdWlkYCBhbmQgYFVTRVJOQU1FYC5cbiAgICAgKlxuICAgICAqIEZvciBPU1ggc3lzdGVtcywgYSBuYXRpdmUtbGV2ZWwgY2FsbCBpcyB1c2VkIHRvIGdldCB0aGUgbWFjaGluZSBJRC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldFVuaXF1ZVVzZXJJZCgpLnRoZW4oaWQgPT4gY29uc29sZS5sb2coaWQpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0VW5pcXVlVXNlcklkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC11bmlxdWUtdXNlci1pZCcpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgYSBmcmFtZSBpbmZvIG9iamVjdCBmb3IgdGhlIHV1aWQgYW5kIG5hbWUgcGFzc2VkIGluXG4gICAgICogQHBhcmFtIHV1aWQgLSBUaGUgVVVJRCBvZiB0aGUgdGFyZ2V0LlxuICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhcmdldC5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIFRoZSBwb3NzaWJsZSB0eXBlcyBhcmUgJ3dpbmRvdycsICdpZnJhbWUnLCAnZXh0ZXJuYWwgY29ubmVjdGlvbicgb3IgJ3Vua25vd24nLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBlbnRpdHlVdWlkID0gJ09wZW5maW5QT0MnO1xuICAgICAqIGNvbnN0IGVudGl0eU5hbWUgPSAnNDBjNzRiNWQtZWQ5OC00MGY3LTg1M2YtZTNkM2MyNjk5MTc1JztcbiAgICAgKiBmaW4uU3lzdGVtLmdldEVudGl0eUluZm8oZW50aXR5VXVpZCwgZW50aXR5TmFtZSkudGhlbihpbmZvID0+IGNvbnNvbGUubG9nKGluZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICpcbiAgICAgKiAvLyBleGFtcGxlIGluZm8gc2hhcGVcbiAgICAgKiB7XG4gICAgICogICAgIFwidXVpZFwiOiBcIk9wZW5maW5QT0NcIixcbiAgICAgKiAgICAgXCJuYW1lXCI6IFwiNDBjNzRiNWQtZWQ5OC00MGY3LTg1M2YtZTNkM2MyNjk5MTc1XCIsXG4gICAgICogICAgIFwicGFyZW50XCI6IHtcbiAgICAgKiAgICAgICAgIFwidXVpZFwiOiBcIk9wZW5maW5QT0NcIixcbiAgICAgKiAgICAgICAgIFwibmFtZVwiOiBcIk9wZW5maW5QT0NcIlxuICAgICAqICAgICB9LFxuICAgICAqICAgICBcImVudGl0eVR5cGVcIjogXCJpZnJhbWVcIlxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRFbnRpdHlJbmZvKHV1aWQsIG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtZW50aXR5LWluZm8nLCB7IHV1aWQsIG5hbWUgfSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIHZhbHVlIG9mIGEgZ2l2ZW4gZW52aXJvbm1lbnQgdmFyaWFibGUgb24gdGhlIGNvbXB1dGVyIG9uIHdoaWNoIHRoZSBydW50aW1lIGlzIGluc3RhbGxlZFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0RW52aXJvbm1lbnRWYXJpYWJsZSgnSE9NRScpLnRoZW4oZW52ID0+IGNvbnNvbGUubG9nKGVudikpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRFbnZpcm9ubWVudFZhcmlhYmxlKGVudk5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZVxuICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ2dldC1lbnZpcm9ubWVudC12YXJpYWJsZScsIHtcbiAgICAgICAgICAgIGVudmlyb25tZW50VmFyaWFibGVzOiBlbnZOYW1lXG4gICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEdldCBjdXJyZW50bHkgZm9jdXNlZCBXaW5kb3cuXG4gICAgICogSWYgYSBWaWV3IGN1cnJlbnRseSBoYXMgZm9jdXMsIHJldHVybnMgdGhlIGlkZW50aXR5IG9mIFZpZXcncyBwYXJlbnQgV2luZG93LlxuICAgICAqIFVzZSB7QGxpbmsgV2luZG93Ll9XaW5kb3cjZ2V0Rm9jdXNlZENvbnRlbnQgV2luZG93LmdldEZvY3VzZWRDb250ZW50fSB0byBkaXJlY3RseSBhY2Nlc3MgY3VycmVudGx5IGZvY3VzZWQgV2luZG93IG9yIFZpZXcuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRGb2N1c2VkV2luZG93KCkudGhlbih3aW5JbmZvID0+IGNvbnNvbGUubG9nKHdpbkluZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0Rm9jdXNlZFdpbmRvdygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtZm9jdXNlZC13aW5kb3cnKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGN1cnJlbnRseSBmb2N1c2VkIGNvbnRlbnQuIFJldHVybnMgaWRlbnRpdHkgb2YgZW50aXR5IHdpdGggYGVudGl0eVR5cGVgLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0Rm9jdXNlZENvbnRlbnQoKS50aGVuKGNvbnRlbnRJZGVudGl0eSA9PiBjb25zb2xlLmxvZyhjb250ZW50SWRlbnRpdHkpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0Rm9jdXNlZENvbnRlbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWZvY3VzZWQtY29udGVudCcpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGluZm9ybWF0aW9uIGFib3V0IHRoZSBnaXZlbiBhcHAncyBjZXJ0aWZpY2F0aW9uIHN0YXR1c1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IG1hbmlmZXN0VXJsID0gXCJodHRwOi8vbG9jYWxob3N0OjEyMzQvYXBwLmpzb25cIlxuICAgICAqIHRyeSB7XG4gICAgICogICAgIGNvbnN0IGNlcnRpZmljYXRpb25JbmZvID0gYXdhaXQgZmluLlN5c3RlbS5pc0FwcENlcnRpZmllZChtYW5pZmVzdFVybCk7XG4gICAgICogfSBjYXRjaChlcnIpIHtcbiAgICAgKiAgICAgY29uc29sZS5lcnJvcihlcnIpXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGlzQXBwQ2VydGlmaWVkKG1hbmlmZXN0VXJsKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhOiB7IGNlcnRpZmllZEluZm8gfSB9IH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignaXMtYXBwLWNlcnRpZmllZCcsIHsgbWFuaWZlc3RVcmwgfSk7XG4gICAgICAgIHJldHVybiBjZXJ0aWZpZWRJbmZvO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIGFycmF5IG9mIGFsbCB0aGUgaW5zdGFsbGVkIHJ1bnRpbWUgdmVyc2lvbnMgaW4gYW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0SW5zdGFsbGVkUnVudGltZXMoKS50aGVuKHJ1bnRpbWVzID0+IGNvbnNvbGUubG9nKHJ1bnRpbWVzKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIC8vIGluY29tcGF0aWJsZSB3aXRoIHN0YW5kYWxvbmUgbm9kZSBwcm9jZXNzLlxuICAgIGdldEluc3RhbGxlZFJ1bnRpbWVzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1pbnN0YWxsZWQtcnVudGltZXMnKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhLnJ1bnRpbWVzKTtcbiAgICB9XG4gICAgLy8gaW5jb21wYXRpYmxlIHdpdGggc3RhbmRhbG9uZSBub2RlIHByb2Nlc3MuXG4gICAgYXN5bmMgZ2V0SW5zdGFsbGVkQXBwcygpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkOiB7IGRhdGE6IHsgaW5zdGFsbGVkQXBwcyB9IH0gfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtaW5zdGFsbGVkLWFwcHMnKTtcbiAgICAgICAgcmV0dXJuIGluc3RhbGxlZEFwcHM7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgY29udGVudHMgb2YgdGhlIGxvZyB3aXRoIHRoZSBzcGVjaWZpZWQgZmlsZW5hbWUuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgQSBvYmplY3QgdGhhdCBpZCBkZWZpbmVkIGJ5IHRoZSBHZXRMb2dSZXF1ZXN0VHlwZSBpbnRlcmZhY2VcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBnZXRMb2coKSB7XG4gICAgICogICAgIGNvbnN0IGxvZ3MgPSBhd2FpdCBmaW4uU3lzdGVtLmdldExvZ0xpc3QoKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGZpbi5TeXN0ZW0uZ2V0TG9nKGxvZ3NbMF0pO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGdldExvZygpLnRoZW4obG9nID0+IGNvbnNvbGUubG9nKGxvZykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRMb2cob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3ZpZXctbG9nJywgb3B0aW9ucykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSB1bmlxdWUgaWRlbnRpZmllciAoVVVJRCkgcHJvdmlkZWQgYnkgdGhlIG1hY2hpbmUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRNYWNoaW5lSWQoKS50aGVuKGlkID0+IGNvbnNvbGUubG9nKGlkKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldE1hY2hpbmVJZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtbWFjaGluZS1pZCcpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBtaW5pbXVtIChpbmNsdXNpdmUpIGxvZ2dpbmcgbGV2ZWwgdGhhdCBpcyBjdXJyZW50bHkgYmVpbmcgd3JpdHRlbiB0byB0aGUgbG9nLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0TWluTG9nTGV2ZWwoKS50aGVuKGxldmVsID0+IGNvbnNvbGUubG9nKGxldmVsKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldE1pbkxvZ0xldmVsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1taW4tbG9nLWxldmVsJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhbiBhcnJheSBjb250YWluaW5nIGluZm9ybWF0aW9uIGZvciBlYWNoIGxvZyBmaWxlLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0TG9nTGlzdCgpLnRoZW4obG9nTGlzdCA9PiBjb25zb2xlLmxvZyhsb2dMaXN0KSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldExvZ0xpc3QoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignbGlzdC1sb2dzJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhbiBvYmplY3QgdGhhdCBjb250YWlucyBkYXRhIGFib3V0IHRoZSBtb25pdG9yIHNldHVwIG9mIHRoZVxuICAgICAqIGNvbXB1dGVyIHRoYXQgdGhlIHJ1bnRpbWUgaXMgcnVubmluZyBvbi5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldE1vbml0b3JJbmZvKCkudGhlbihtb25pdG9ySW5mbyA9PiBjb25zb2xlLmxvZyhtb25pdG9ySW5mbykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRNb25pdG9ySW5mbygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtbW9uaXRvci1pbmZvJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIG1vdXNlIGluIHZpcnR1YWwgc2NyZWVuIGNvb3JkaW5hdGVzIChsZWZ0LCB0b3ApLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0TW91c2VQb3NpdGlvbigpLnRoZW4obW91c2VQb3NpdGlvbiA9PiBjb25zb2xlLmxvZyhtb3VzZVBvc2l0aW9uKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldE1vdXNlUG9zaXRpb24oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LW1vdXNlLXBvc2l0aW9uJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhbiBhcnJheSBvZiBhbGwgb2YgdGhlIHJ1bnRpbWUgcHJvY2Vzc2VzIHRoYXQgYXJlIGN1cnJlbnRseVxuICAgICAqIHJ1bm5pbmcuIEVhY2ggZWxlbWVudCBpbiB0aGUgYXJyYXkgaXMgYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIHV1aWRcbiAgICAgKiBhbmQgdGhlIG5hbWUgb2YgdGhlIGFwcGxpY2F0aW9uIHRvIHdoaWNoIHRoZSBwcm9jZXNzIGJlbG9uZ3MuXG4gICAgICogQGRlcHJlY2F0ZWQgUGxlYXNlIHVzZSBvdXIgbmV3IHNldCBvZiBwcm9jZXNzIEFQSXM6XG4gICAgICoge0BsaW5rIFdpbmRvdy5fV2luZG93I2dldFByb2Nlc3NJbmZvIFdpbmRvdy5nZXRQcm9jZXNzSW5mb31cbiAgICAgKiB7QGxpbmsgVmlldy5WaWV3I2dldFByb2Nlc3NJbmZvIFZpZXcuZ2V0UHJvY2Vzc0luZm99XG4gICAgICoge0BsaW5rIEFwcGxpY2F0aW9uLkFwcGxpY2F0aW9uI2dldFByb2Nlc3NJbmZvIEFwcGxpY2F0aW9uLmdldFByb2Nlc3NJbmZvfVxuICAgICAqIHtAbGluayBTeXN0ZW0jZ2V0QWxsUHJvY2Vzc0luZm8gU3lzdGVtLmdldEFsbFByb2Nlc3NJbmZvfVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0UHJvY2Vzc0xpc3QoKS50aGVuKFByb2Nlc3NMaXN0ID0+IGNvbnNvbGUubG9nKFByb2Nlc3NMaXN0KSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldFByb2Nlc3NMaXN0KCkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICBjb25zb2xlLndhcm4oJ1N5c3RlbS5nZXRQcm9jZXNzTGlzdCBoYXMgYmVlbiBkZXByZWNhdGVkLiBQbGVhc2UgY29uc2lkZXIgdXNpbmcgb3VyIG5ldyBwcm9jZXNzIEFQSXM6IFdpbmRvdy5nZXRQcm9jZXNzSW5mbywgVmlldy5nZXRQcm9jZXNzSW5mbywgQXBwbGljYXRpb24uZ2V0UHJvY2Vzc0luZm8sIFN5c3RlbS5nZXRBbGxQcm9jZXNzSW5mbycpO1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3Byb2Nlc3Mtc25hcHNob3QnKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGFsbCBwcm9jZXNzIGluZm9ybWF0aW9uLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgVGhpcyBpbmNsdWRlcyB0aGUgYnJvd3NlciBwcm9jZXNzIGFuZCBldmVyeSBwcm9jZXNzIGFzc29jaWF0ZWQgdG8gYWxsIGVudGl0aWVzICh3aW5kb3dzIGFuZCB2aWV3cykuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgYWxsUHJvY2Vzc0luZm8gPSBhd2FpdCBmaW4uU3lzdGVtLmdldEFsbFByb2Nlc3NJbmZvKCk7XG4gICAgICogYGBgXG4gICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAqL1xuICAgIGFzeW5jIGdldEFsbFByb2Nlc3NJbmZvKCkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgZGF0YSB9IH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWFsbC1wcm9jZXNzLWluZm8nLCB0aGlzLmlkZW50aXR5KTtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyB0aGUgUHJveHkgc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5nZXRQcm94eVNldHRpbmdzKCkudGhlbihQcm94eVNldHRpbmcgPT4gY29uc29sZS5sb2coUHJveHlTZXR0aW5nKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqXG4gICAgICogLy9UaGlzIHJlc3BvbnNlIGhhcyB0aGUgZm9sbG93aW5nIHNoYXBlOlxuICAgICAqIHtcbiAgICAgKiAgICAgY29uZmlnOiB7XG4gICAgICogICAgICAgICBwcm94eUFkZHJlc3M6IFwicHJveHlBZGRyZXNzXCIsIC8vdGhlIGNvbmZpZ3VyZWQgUHJveHkgQWRkcmVzc1xuICAgICAqICAgICAgICAgcHJveHlQb3J0OiAwLCAvL3RoZSBjb25maWd1cmVkIFByb3h5IHBvcnRcbiAgICAgKiAgICAgICAgIHR5cGU6IFwic3lzdGVtXCIgLy9Qcm94eSBUeXBlXG4gICAgICogICAgIH0sXG4gICAgICogICAgIHN5c3RlbToge1xuICAgICAqICAgICAgICAgYXV0b0NvbmZpZ1VybDogXCJcIixcbiAgICAgKiAgICAgICAgIGJ5cGFzczogXCJcIixcbiAgICAgKiAgICAgICAgIGVuYWJsZWQ6IGZhbHNlLFxuICAgICAqICAgICAgICAgcHJveHk6IFwiXCJcbiAgICAgKiAgICAgfVxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRQcm94eVNldHRpbmdzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1wcm94eS1zZXR0aW5ncycpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGluZm9ybWF0aW9uIGFib3V0IHRoZSBydW5uaW5nIFJ1bnRpbWUgaW4gYW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0UnVudGltZUluZm8oKS50aGVuKFJ1bnRpbWVJbmZvID0+IGNvbnNvbGUubG9nKFJ1bnRpbWVJbmZvKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldFJ1bnRpbWVJbmZvKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1ydW50aW1lLWluZm8nKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcnVubmluZyBSVk0gaW4gYW4gb2JqZWN0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0UnZtSW5mbygpLnRoZW4oUnZtSW5mbyA9PiBjb25zb2xlLmxvZyhSdm1JbmZvKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIC8vIGluY29tcGF0aWJsZSB3aXRoIHN0YW5kYWxvbmUgbm9kZSBwcm9jZXNzLlxuICAgIGdldFJ2bUluZm8oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXJ2bS1pbmZvJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBnZW5lcmFsIHN5c3RlbSBpbmZvcm1hdGlvbi4gSWYgeW91IG5lZWQgbW9yZSBkZXRhaWxlZCBpbmZvcm1hdGlvbiBhYm91dCB0aGVcbiAgICAgKiBPUyBhbmQgdGhlIGN1cnJlbnRseSBsb2dnZWQgaW4gdXNlciwgdXNlIGBmaW4uU3lzdGVtLmdldE9TSW5mbygpYCBpbnN0ZWFkLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0SG9zdFNwZWNzKCkudGhlbihzcGVjcyA9PiBjb25zb2xlLmxvZyhzcGVjcykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRIb3N0U3BlY3MoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWhvc3Qtc3BlY3MnKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBPUyBhbmQgdGhlIGN1cnJlbnRseSBsb2dnZWQgaW4gdXNlci5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldE9TSW5mbygpLnRoZW4oc3BlY3MgPT4gY29uc29sZS5sb2coc3BlY3MpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0T1NJbmZvKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1vcy1pbmZvJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJ1bnMgYW4gZXhlY3V0YWJsZSBvciBiYXRjaCBmaWxlLiBBIHBhdGggdG8gdGhlIGZpbGUgbXVzdCBiZSBpbmNsdWRlZCBpbiBvcHRpb25zLlxuICAgICAqIDxicj4gQSB1dWlkIG1heSBiZSBvcHRpb25hbGx5IHByb3ZpZGVkLiBJZiBub3QgcHJvdmlkZWQsIE9wZW5GaW4gd2lsbCBjcmVhdGUgYSB1dWlkIGZvciB0aGUgbmV3IHByb2Nlc3MuXG4gICAgICogPGJyPiBOb3RlOiBUaGlzIG1ldGhvZCBpcyByZXN0cmljdGVkIGJ5IGRlZmF1bHQgYW5kIG11c3QgYmUgZW5hYmxlZCB2aWFcbiAgICAgKiA8YSBocmVmPVwiaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5maW4uY28vZG9jcy9hcGktc2VjdXJpdHlcIj5BUEkgc2VjdXJpdHkgc2V0dGluZ3M8L2E+LiBBbHNvLCB0aGlzIGFwaSBoYXMgYW4gZW5oYW5jZWQgcGVybWlzc2lvbiBzZXQgdG8gbWFrZSBpdCBsZXNzIGRhbmdlcm91cy4gU28gYXBwbGljYXRpb24gb3duZXJzIGNhbiBvbmx5IGFsbG93IHRvIGxhdW5jaCB0aGUgYXNzZXRzIG93bmVkIGJ5IHRoZSBhcHBsaWNhdGlvbiwgdGhlIGVuYWJsZWQgZG93bmxvYWRlZCBmaWxlcyBvciB0aGUgcmVzdHJpY3RlZCBleGVjdXRhYmxlcy5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBBIG9iamVjdCB0aGF0IGlzIGRlZmluZWQgaW4gdGhlIEV4dGVybmFsUHJvY2Vzc1JlcXVlc3RUeXBlIGludGVyZmFjZVxuICAgICAqXG4gICAgICogQHJlbWFya3MgSWYgYW4gdW51c2VkIFVVSUQgaXMgcHJvdmlkZWQgaW4gb3B0aW9ucywgaXQgd2lsbCBiZSB1c2VkLiBJZiBubyBVVUlEIGlzIHByb3ZpZGVkLCBPcGVuRmluIHdpbGwgYXNzaWduIG9uZS5cbiAgICAgKiBUaGlzIGFwaSBoYXMgYW4gZW5oYW5jZWQgcGVybWlzc2lvbiBzZXQgdG8gbWFrZSBpdCBsZXNzIGRhbmdlcm91cy4gU28gYXBwbGljYXRpb24gb3duZXJzIGNhbiBvbmx5IGFsbG93IHRvIGxhdW5jaCB0aGVcbiAgICAgKiBhc3NldHMgb3duZWQgYnkgdGhlIGFwcGxpY2F0aW9uLCB0aGUgZW5hYmxlZCBkb3dubG9hZGVkIGZpbGVzIG9yIHRoZSByZXN0cmljdGVkIGV4ZWN1dGFibGVzLlxuICAgICAqXG4gICAgICogKipOb3RlOioqIFNpbmNlIF9hcHBBc3NldHNfIHJlbGllcyBvbiB0aGUgUlZNLCB3aGljaCBpcyBtaXNzaW5nIG9uIE1BQ19PUywgJ2FsaWFzJyBpcyBub3QgYXZhaWxhYmxlLiBJbnN0ZWFkIHByb3ZpZGVcbiAgICAgKiB0aGUgZnVsbCBwYXRoIGUuZy4gXy9BcHBsaWNhdGlvbnMvQ2FsY3VsYXRvci5hcHAvQ29udGVudHMvTWFjT1MvQ2FsY3VsYXRvcl8uXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIEJhc2ljIEV4YW1wbGU6XG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmxhdW5jaEV4dGVybmFsUHJvY2Vzcyh7XG4gICAgICogICAgIHBhdGg6ICdub3RlcGFkJyxcbiAgICAgKiAgICAgYXJndW1lbnRzOiAnJyxcbiAgICAgKiAgICAgbGlzdGVuZXI6IGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCd0aGUgZXhpdCBjb2RlJywgcmVzdWx0LmV4aXRDb2RlKTtcbiAgICAgKiAgICAgfVxuICAgICAqIH0pLnRoZW4ocHJvY2Vzc0lkZW50aXR5ID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2cocHJvY2Vzc0lkZW50aXR5KTtcbiAgICAgKiB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKGVycm9yKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFByb21pc2UgcmVzb2x1dGlvbjpcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogLy9UaGlzIHJlc3BvbnNlIGhhcyB0aGUgZm9sbG93aW5nIHNoYXBlOlxuICAgICAqIHtcbiAgICAgKiAgICAgdXVpZDogXCJGQjNFNkUzNi0wOTc2LTRDMkItOUEwOS1GQjJFNTREMkYxQkJcIiAvLyBUaGUgbWFwcGVkIFVVSUQgd2hpY2ggaWRlbnRpZmllcyB0aGUgbGF1bmNoZWQgcHJvY2Vzc1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIExpc3RlbmVyIGNhbGxiYWNrOlxuICAgICAqIGBgYGpzXG4gICAgICogLy9UaGlzIHJlc3BvbnNlIGhhcyB0aGUgZm9sbG93aW5nIHNoYXBlOlxuICAgICAqIHtcbiAgICAgKiAgICAgdG9waWM6IFwiZXhpdGVkXCIsIC8vIE9yIFwicmVsZWFzZWRcIiBvbiBhIGNhbGwgdG8gcmVsZWFzZUV4dGVybmFsUHJvY2Vzc1xuICAgICAqICAgICB1dWlkOiBcIkZCM0U2RTM2LTA5NzYtNEMyQi05QTA5LUZCMkU1NEQyRjFCQlwiLCAvLyBUaGUgbWFwcGVkIFVVSUQgd2hpY2ggaWRlbnRpZmllcyB0aGUgbGF1bmNoZWQgcHJvY2Vzc1xuICAgICAqICAgICBleGl0Q29kZTogMCAvLyBQcm9jZXNzIGV4aXQgY29kZVxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEJ5IHNwZWNpZnlpbmcgYSBsaWZldGltZSwgYW4gZXh0ZXJuYWwgcHJvY2VzcyBjYW4gbGl2ZSBhcyBsb25nIHRoZSB3aW5kb3cvYXBwbGljYXRpb24gdGhhdCBsYXVuY2hlZCBpdCBvclxuICAgICAqIHBlcnNpc3QgYWZ0ZXIgdGhlIGFwcGxpY2F0aW9uIGV4aXRzLiBUaGUgZGVmYXVsdCB2YWx1ZSBpcyBudWxsLCB3aGljaCBpcyBlcXVpdmFsZW50IHRvICdwZXJzaXN0JywgbWVhbmluZ1xuICAgICAqIHRoZSBwcm9jZXNzIGxpdmVzIG9uIGFmdGVyIHRoZSBhcHBsaWNhdGlvbiBleGl0czpcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5sYXVuY2hFeHRlcm5hbFByb2Nlc3Moe1xuICAgICAqICAgICBwYXRoOiAnbm90ZXBhZCcsXG4gICAgICogICAgIGFyZ3VtZW50czogJycsXG4gICAgICogICAgIGxpc3RlbmVyOiAocmVzdWx0KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZygndGhlIGV4aXQgY29kZScsIHJlc3VsdC5leGl0Q29kZSk7XG4gICAgICogICAgIH0sXG4gICAgICogICAgIGxpZmV0aW1lOiAnd2luZG93J1xuICAgICAqIH0pLnRoZW4ocHJvY2Vzc0lkZW50aXR5ID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2cocHJvY2Vzc0lkZW50aXR5KTtcbiAgICAgKiB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKGVycm9yKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIE5vdGU6IEEgcHJvY2VzcyB0aGF0IGV4aXRzIHdoZW4gdGhlIHdpbmRvdy9hcHBsaWNhdGlvbiBleGl0cyBjYW5ub3QgYmUgcmVsZWFzZWQgdmlhIGZpbi5kZXNrdG9wLlN5c3RlbS5yZWxlYXNlRXh0ZXJuYWxQcm9jZXNzLlxuICAgICAqXG4gICAgICogQnkgc3BlY2lmeWluZyBhIGN3ZCwgaXQgd2lsbCBzZXQgY3VycmVudCB3b3JraW5nIGRpcmVjdG9yeSB3aGVuIGxhdW5jaGluZyBhbiBleHRlcm5hbCBwcm9jZXNzOlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmxhdW5jaEV4dGVybmFsUHJvY2Vzcyh7XG4gICAgICogICAgIHBhdGg6ICdjbWQuZXhlJyxcbiAgICAgKiAgICAgY3dkOiAnYzpcXFxcdGVtcCcsXG4gICAgICogICAgIGFyZ3VtZW50czogJycsXG4gICAgICogICAgIGxpc3RlbmVyOiAocmVzdWx0KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZygndGhlIGV4aXQgY29kZScsIHJlc3VsdC5leGl0Q29kZSk7XG4gICAgICogICAgIH1cbiAgICAgKiB9KS50aGVuKHByb2Nlc3NJZGVudGl0eSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKHByb2Nlc3NJZGVudGl0eSk7XG4gICAgICogfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhlcnJvcik7XG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBFeGFtcGxlIHVzaW5nIGFuIGFsaWFzIGZyb20gYXBwLmpzb24gYXBwQXNzZXRzIHByb3BlcnR5OlxuICAgICAqXG4gICAgICogYGBganNvblxuICAgICAqIFwiYXBwQXNzZXRzXCI6IFtcbiAgICAgKiAgICAge1xuICAgICAqICAgICAgICAgXCJzcmNcIjogXCJleGUuemlwXCIsXG4gICAgICogICAgICAgICBcImFsaWFzXCI6IFwibXlBcHBcIixcbiAgICAgKiAgICAgICAgIFwidmVyc2lvblwiOiBcIjQuMTIuOFwiLFxuICAgICAqICAgICAgICAgXCJ0YXJnZXRcIjogXCJteUFwcC5leGVcIixcbiAgICAgKiAgICAgICAgIFwiYXJnc1wiOiBcImEgYiBjIGRcIlxuICAgICAqICAgICB9LFxuICAgICAqIF1cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogLy8gIFdoZW4gY2FsbGVkLCBpZiBubyBhcmd1bWVudHMgYXJlIHBhc3NlZCB0aGVuIHRoZSBhcmd1bWVudHMgKGlmIGFueSlcbiAgICAgKiAvLyAgYXJlIHRha2VuIGZyb20gdGhlICdhcHAuanNvbicgZmlsZSwgZnJvbSB0aGUgICdhcmdzJyBwYXJhbWV0ZXJcbiAgICAgKiAvLyAgb2YgdGhlICdhcHBBc3NldHMnIE9iamVjdCB3aXRoIHRoZSByZWxldmFudCAnYWxpYXMnLlxuICAgICAqIGZpbi5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKHtcbiAgICAgKiAgICAgLy9BZGRpdGlvbmFsbHkgbm90ZSB0aGF0IHRoZSBleGVjdXRhYmxlIGZvdW5kIGluIHRoZSB6aXAgZmlsZSBzcGVjaWZpZWQgaW4gYXBwQXNzZXRzXG4gICAgICogICAgIC8vd2lsbCBkZWZhdWx0IHRvIHRoZSBvbmUgbWVudGlvbmVkIGJ5IGFwcEFzc2V0cy50YXJnZXRcbiAgICAgKiAgICAgLy9JZiB0aGUgdGhlIHBhdGggYmVsb3cgcmVmZXJzIHRvIGEgc3BlY2lmaWMgcGF0aCBpdCB3aWxsIG92ZXJyaWRlIHRoaXMgZGVmYXVsdFxuICAgICAqICAgICBhbGlhczogJ215QXBwJyxcbiAgICAgKiAgICAgbGlzdGVuZXI6IChyZXN1bHQpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCd0aGUgZXhpdCBjb2RlJywgcmVzdWx0LmV4aXRDb2RlKTtcbiAgICAgKiAgICAgfVxuICAgICAqIH0pLnRoZW4ocHJvY2Vzc0lkZW50aXR5ID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2cocHJvY2Vzc0lkZW50aXR5KTtcbiAgICAgKiB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKGVycm9yKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEV4YW1wbGUgdXNpbmcgYW4gYWxpYXMgYnV0IG92ZXJyaWRpbmcgdGhlIGFyZ3VtZW50czpcbiAgICAgKlxuICAgICAqIGBgYGpzb25cbiAgICAgKiBcImFwcEFzc2V0c1wiOiBbXG4gICAgICogICAgIHtcbiAgICAgKiAgICAgICAgIFwic3JjXCI6IFwiZXhlLnppcFwiLFxuICAgICAqICAgICAgICAgXCJhbGlhc1wiOiBcIm15QXBwXCIsXG4gICAgICogICAgICAgICBcInZlcnNpb25cIjogXCI0LjEyLjhcIixcbiAgICAgKiAgICAgICAgIFwidGFyZ2V0XCI6IFwibXlBcHAuZXhlXCIsXG4gICAgICogICAgICAgICBcImFyZ3NcIjogXCJhIGIgYyBkXCJcbiAgICAgKiAgICAgfSxcbiAgICAgKiBdXG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIC8vICBJZiAnYXJndW1lbnRzJyBpcyBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIgaXQgdGFrZXMgcHJlY2VkZW5jZVxuICAgICAqIC8vICBvdmVyIGFueSAnYXJncycgc2V0IGluIHRoZSAnYXBwLmpzb24nLlxuICAgICAqIGZpbi5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKHtcbiAgICAgKiAgICAgYWxpYXM6ICdteUFwcCcsXG4gICAgICogICAgIGFyZ3VtZW50czogJ2UgZiBnJyxcbiAgICAgKiAgICAgbGlzdGVuZXI6IChyZXN1bHQpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCd0aGUgZXhpdCBjb2RlJywgcmVzdWx0LmV4aXRDb2RlKTtcbiAgICAgKiAgICAgfVxuICAgICAqIH0pLnRoZW4ocHJvY2Vzc0lkZW50aXR5ID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2cocHJvY2Vzc0lkZW50aXR5KTtcbiAgICAgKiB9KS5jYXRjaChlcnJvciA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKGVycm9yKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEl0IGlzIG5vdyBwb3NzaWJsZSB0byBvcHRpb25hbGx5IHBlcmZvcm0gYW55IGNvbWJpbmF0aW9uIG9mIHRoZSBmb2xsb3dpbmcgY2VydGlmaWNhdGUgY2hlY2tzXG4gICAgICogYWdhaW5zdCBhbiBhYnNvbHV0ZSB0YXJnZXQgdmlhIGBmaW4uZGVza3RvcC5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKClgOlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBcImNlcnRpZmljYXRlXCI6IHtcbiAgICAgKiAgICAgXCJzZXJpYWxcIjogXCIzYyBhNSAuLi5cIiwgICAgICAgICAgICAgICAgICAgICAgICAvLyBBIGhleCBzdHJpbmcgd2l0aCBvciB3aXRob3V0IHNwYWNlc1xuICAgICAqICAgICBcInN1YmplY3RcIjogXCJPPU9wZW5GaW4gSU5DLiwgTD1OZXcgWW9yaywgLi4uXCIsIC8vIEFuIGludGVybmFsbHkgdG9rZW5pemVkIGFuZCBjb21tYSBkZWxpbWl0ZWQgc3RyaW5nIGFsbG93aW5nIHBhcnRpYWwgb3IgZnVsbCBjaGVja3Mgb2YgdGhlIHN1YmplY3QgZmllbGRzXG4gICAgICogICAgIFwicHVibGlja2V5XCI6IFwiM2MgYTUgLi4uXCIsICAgICAgICAgICAgICAgICAgICAgLy8gQSBoZXggc3RyaW5nIHdpdGggb3Igd2l0aG91dCBzcGFjZXNcbiAgICAgKiAgICAgXCJ0aHVtYnByaW50XCI6IFwiM2MgYTUgLi4uXCIsICAgICAgICAgICAgICAgICAgICAvLyBBIGhleCBzdHJpbmcgd2l0aCBvciB3aXRob3V0IHNwYWNlc1xuICAgICAqICAgICBcInRydXN0ZWRcIjogdHJ1ZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBIGJvb2xlYW4gaW5kaWNhdGluZyB0aGF0IHRoZSBjZXJ0aWZpY2F0ZSBpcyB0cnVzdGVkIGFuZCBub3QgcmV2b2tlZFxuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFByb3ZpZGluZyB0aGlzIGluZm9ybWF0aW9uIGFzIHBhcnQgb2YgdGhlIGRlZmF1bHQgY29uZmlndXJhdGlvbnMgZm9yIGFzc2V0cyBpbiBhbiBhcHBsaWNhdGlvbidzIG1hbmlmZXN0XG4gICAgICogd2lsbCBiZSBhZGRlZCBpbiBhIGZ1dHVyZSBSVk0gdXBkYXRlOlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmxhdW5jaEV4dGVybmFsUHJvY2Vzcyh7XG4gICAgICogICAgIHBhdGg6ICdDOlxcXFxVc2Vyc1xcXFxFeGFtcGxlVXNlclxcXFxBcHBEYXRhXFxcXExvY2FsXFxcXE9wZW5GaW5cXFxcT3BlbkZpblJWTS5leGUnLFxuICAgICAqICAgICBhcmd1bWVudHM6ICctLXZlcnNpb24nLFxuICAgICAqICAgICBjZXJ0aWZpY2F0ZToge1xuICAgICAqICAgICAgICAgdHJ1c3RlZDogdHJ1ZSxcbiAgICAgKiAgICAgICAgIHN1YmplY3Q6ICdPPU9wZW5GaW4gSU5DLiwgTD1OZXcgWW9yaywgUz1OWSwgQz1VUycsXG4gICAgICogICAgICAgICB0aHVtYnByaW50OiAn4oCOM2MgYTUgMjggMTkgODMgMDUgZmUgNjkgODggZTYgOGYgNGIgM2EgYWYgYzUgYzUgMWIgMDcgODAgNWInXG4gICAgICogICAgIH0sXG4gICAgICogICAgIGxpc3RlbmVyOiAocmVzdWx0KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZygndGhlIGV4aXQgY29kZScsIHJlc3VsdC5leGl0Q29kZSk7XG4gICAgICogICAgIH1cbiAgICAgKiB9KS50aGVuKHByb2Nlc3NJZGVudGl0eSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKHByb2Nlc3NJZGVudGl0eSk7XG4gICAgICogfSkuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhlcnJvcik7XG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBJdCBpcyBwb3NzaWJsZSB0byBsYXVuY2ggZmlsZXMgdGhhdCBoYXZlIGJlZW4gZG93bmxvYWRlZCBieSB0aGUgdXNlciBieSBsaXN0ZW5pbmcgdG8gdGhlIHdpbmRvd1xuICAgICAqIGBmaWxlLWRvd25sb2FkLWNvbXBsZXRlZGAgZXZlbnQgYW5kIHVzaW5nIHRoZSBgZmlsZVV1aWRgIHByb3ZpZGVkIGJ5IHRoZSBldmVudDpcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3Qgd2luID0gZmluLldpbmRvdy5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIHdpbi5hZGRMaXN0ZW5lcignZmlsZS1kb3dubG9hZC1jb21wbGV0ZWQnLCAoZXZ0KSA9PiB7XG4gICAgICogICAgIGlmIChldnQuc3RhdGUgPT09ICdjb21wbGV0ZWQnKSB7XG4gICAgICogICAgICAgICBmaW4uU3lzdGVtLmxhdW5jaEV4dGVybmFsUHJvY2Vzcyh7XG4gICAgICogICAgICAgICAgICAgZmlsZVV1aWQ6IGV2dC5maWxlVXVpZCxcbiAgICAgKiAgICAgICAgICAgICBhcmd1bWVudHM6ICcnLFxuICAgICAqICAgICAgICAgICAgIGxpc3RlbmVyOiAocmVzdWx0KSA9PiB7XG4gICAgICogICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCd0aGUgZXhpdCBjb2RlJywgcmVzdWx0LmV4aXRDb2RlKTtcbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICB9KS50aGVuKHByb2Nlc3NJZGVudGl0eSA9PiB7XG4gICAgICogICAgICAgICAgICAgY29uc29sZS5sb2cocHJvY2Vzc0lkZW50aXR5KTtcbiAgICAgKiAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgKiAgICAgICAgICAgICBjb25zb2xlLmxvZyhlcnJvcik7XG4gICAgICogICAgICAgICB9KTtcbiAgICAgKiAgICAgfVxuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogTGF1bmNoaW5nIGFzc2V0cyBzcGVjaWZpZWQgaW4gdGhlIGFwcCBtYW5pZmVzdDpcbiAgICAgKlxuICAgICAqIFNhbXBsZSBhcHBBc3NldHMgc2VjdGlvbiBpbiBhcHAuanNvblxuICAgICAqIGBgYGpzXG4gICAgICogICAgIFwiYXBwQXNzZXRzXCI6IFtcbiAgICAgKiAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICBcInNyY1wiOiBcImh0dHA6Ly9maWxlc2FtcGxlcy5jb20vZXhlLnppcFwiLFxuICAgICAqICAgICAgICAgICAgIFwiYWxpYXNcIjogXCJteUFwcFwiLFxuICAgICAqICAgICAgICAgICAgIFwidmVyc2lvblwiOiBcIjQuMTIuOFwiLFxuICAgICAqICAgICAgICAgICAgIFwidGFyZ2V0XCI6IFwibXlBcHAuZXhlXCIsXG4gICAgICogICAgICAgICAgICAgXCJhcmdzXCI6IFwiYSBiIGMgZFwiXG4gICAgICogICAgICAgICB9LFxuICAgICAqICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgIFwic3JjXCI6IFwiaHR0cDovL2V4YW1wbGVzLmNvbS9leGUuemlwXCIsXG4gICAgICogICAgICAgICAgICAgXCJhbGlhc1wiOiBcIm15QXBwMlwiLFxuICAgICAqICAgICAgICAgICAgIFwidmVyc2lvblwiOiBcIjUuMTIuOFwiLFxuICAgICAqICAgICAgICAgICAgIFwidGFyZ2V0XCI6IFwibXlBcHAyLmV4ZVwiLFxuICAgICAqICAgICAgICAgICAgIFwiYXJnc1wiOiBcImEgYiBjXCJcbiAgICAgKiAgICAgICAgIH1cbiAgICAgKiAgICAgXVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogVGhpcyBwZXJtaXNzaW9uIGFsbG93cyBmb3IgbGF1bmNoaW5nIG9mIGFsbCBhc3NldHMgc3BlY2lmaWVkIGluIHRoZSBhYm92ZSBhcHBBc3NldHMgc2VjdGlvbi4gKFwibXlBcHBcIiBhbmQgXCJteUFwcDJcIik6XG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBcInBlcm1pc3Npb25zXCI6IHtcbiAgICAgKiAgICAgICAgXCJTeXN0ZW1cIjoge1xuICAgICAqICAgICAgICAgICAgXCJsYXVuY2hFeHRlcm5hbFByb2Nlc3NcIjoge1xuICAgICAqICAgICAgICAgICAgICAgICBcImVuYWJsZWRcIjogdHJ1ZSxcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJhc3NldHNcIjoge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgXCJlbmFibGVkXCI6IHRydWVcbiAgICAgKiAgICAgICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgfVxuICAgICAqICAgICB9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBUaGlzIHBlcm1pc3Npb24gYWxsb3dzIGZvciBsYXVuY2hpbmcgb2YgX29ubHlfIHRoZSBcIm15QXBwXCIgYXNzZXQgaW4gdGhlIGFib3ZlIGFwcEFzc2V0cyBzZWN0aW9uLCBhcyBkZWZpbmVkIGluIGBzcmNSdWxlc2A6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgXCJwZXJtaXNzaW9uc1wiOiB7XG4gICAgICogICAgICAgIFwiU3lzdGVtXCI6IHtcbiAgICAgKiAgICAgICAgICAgIFwibGF1bmNoRXh0ZXJuYWxQcm9jZXNzXCI6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJlbmFibGVkXCI6IHRydWUsXG4gICAgICogICAgICAgICAgICAgICAgIFwiYXNzZXRzXCI6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIFwiZW5hYmxlZFwiOiB0cnVlXG4gICAgICogICAgICAgICAgICAgICAgICAgICBcInNyY1J1bGVzXCI6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwibWF0Y2hcIjogW1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIqOi8vZmlsZXNhbXBsZXMuY29tLypcIlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImJlaGF2aW9yXCI6IFwiYWxsb3dcIlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIm1hdGNoXCI6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPGFsbF91cmxzPlwiXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYmVoYXZpb3JcIjogXCJibG9ja1wiXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAqICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgfVxuICAgICAqICAgICAgICB9XG4gICAgICogICAgIH1cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIExhdW5jaGluZyBkb3dubG9hZGVkIGZpbGVzOlxuICAgICAqIGBgYGpzXG4gICAgICogICAgIFwicGVybWlzc2lvbnNcIjoge1xuICAgICAqICAgICAgICBcIlN5c3RlbVwiOiB7XG4gICAgICogICAgICAgICAgICBcImxhdW5jaEV4dGVybmFsUHJvY2Vzc1wiOiB7XG4gICAgICogICAgICAgICAgICAgICAgIFwiZW5hYmxlZFwiOiB0cnVlLFxuICAgICAqICAgICAgICAgICAgICAgICBcImRvd25sb2Fkc1wiOiB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICBcImVuYWJsZWRcIjogdHJ1ZVxuICAgICAqICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgfVxuICAgICAqICAgICAgICB9XG4gICAgICogICAgIH1cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFRoaXMgcGVybWlzc2lvbiBhbGxvd3MgdG8gbGF1bmNoIGFsbCB0aGUgZXhlY3V0YWJsZXM6XG4gICAgICogYGBganNcbiAgICAgKiAgICAgXCJwZXJtaXNzaW9uc1wiOiB7XG4gICAgICogICAgICAgIFwiU3lzdGVtXCI6IHtcbiAgICAgKiAgICAgICAgICAgIFwibGF1bmNoRXh0ZXJuYWxQcm9jZXNzXCI6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJlbmFibGVkXCI6IHRydWUsXG4gICAgICogICAgICAgICAgICAgICAgIFwiZXhlY3V0YWJsZXNcIjoge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgXCJlbmFibGVkXCI6IHRydWVcbiAgICAgKiAgICAgICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgfVxuICAgICAqICAgICB9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKlxuICAgICAqIFRoaXMgcGVybWlzc2lvbiBvbmx5IGFsbG93cyBsYXVuY2hpbmcgb2YgZXhlY3V0YWJsZXMgd2hvc2UgZmlsZSBwYXRocyBtYXRjaCB0aGUgY29ycmVzcG9uZGluZyBgcGF0aFJ1bGVzYDpcbiAgICAgKiBgYGBqc1xuICAgICAqICAgICBcInBlcm1pc3Npb25zXCI6IHtcbiAgICAgKiAgICAgICAgXCJTeXN0ZW1cIjoge1xuICAgICAqICAgICAgICAgICAgXCJsYXVuY2hFeHRlcm5hbFByb2Nlc3NcIjoge1xuICAgICAqICAgICAgICAgICAgICAgICBcImVuYWJsZWRcIjogdHJ1ZSxcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJleGVjdXRhYmxlc1wiOiB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICBcImVuYWJsZWRcIjogdHJ1ZVxuICAgICAqICAgICAgICAgICAgICAgICAgICAgXCJwYXRoUnVsZXNcIjogW1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJtYXRjaFwiOiBbXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIi9XaW5kb3dzL1N5c3RlbTMyLyouZXhlXCJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJiZWhhdmlvclwiOiBcImFsbG93XCJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJtYXRjaFwiOiBbXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIiouZXhlXCJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJiZWhhdmlvclwiOiBcImJsb2NrXCJcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICBdXG4gICAgICogICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgIH1cbiAgICAgKiAgICAgfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGxhdW5jaEV4dGVybmFsUHJvY2VzcyhvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbmRFeHRlcm5hbFByb2Nlc3NSZXF1ZXN0KCdsYXVuY2gtZXh0ZXJuYWwtcHJvY2VzcycsIG9wdGlvbnMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBNb25pdG9ycyBhIHJ1bm5pbmcgcHJvY2Vzcy4gQSBwaWQgZm9yIHRoZSBwcm9jZXNzIG11c3QgYmUgaW5jbHVkZWQgaW4gb3B0aW9ucy5cbiAgICAgKiA8YnI+IEEgdXVpZCBtYXkgYmUgb3B0aW9uYWxseSBwcm92aWRlZC4gSWYgbm90IHByb3ZpZGVkLCBPcGVuRmluIHdpbGwgY3JlYXRlIGEgdXVpZCBmb3IgdGhlIG5ldyBwcm9jZXNzLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgSWYgYW4gdW51c2VkIHV1aWQgaXMgcHJvdmlkZWQgaW4gb3B0aW9ucywgaXQgd2lsbCBiZSB1c2VkLiBJZiBubyB1dWlkIGlzIHByb3ZpZGVkLCBPcGVmaW5GaW4gd2lsbCBhc3NpZ24gYSB1dWlkLlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLm1vbml0b3JFeHRlcm5hbFByb2Nlc3Moe1xuICAgICAqICAgICBwaWQ6IDEwMjA4LFxuICAgICAqICAgICB1dWlkOiAnbXktZXh0ZXJuYWwtcHJvY2VzcycsIC8vIG9wdGlvbmFsXG4gICAgICogICAgIGxpc3RlbmVyOiBmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZygndGhlIGV4aXQgY29kZScsIHJlc3VsdC5leGl0Q29kZSk7XG4gICAgICogICAgIH1cbiAgICAgKiB9KS50aGVuKHByb2Nlc3NJZGVudGl0eSA9PiBjb25zb2xlLmxvZyhwcm9jZXNzSWRlbnRpdHkpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgbW9uaXRvckV4dGVybmFsUHJvY2VzcyhvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbmRFeHRlcm5hbFByb2Nlc3NSZXF1ZXN0KCdtb25pdG9yLWV4dGVybmFsLXByb2Nlc3MnLCBvcHRpb25zKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogV3JpdGVzIHRoZSBwYXNzZWQgbWVzc2FnZSBpbnRvIGJvdGggdGhlIGxvZyBmaWxlIGFuZCB0aGUgY29uc29sZS5cbiAgICAgKiBAcGFyYW0gbGV2ZWwgVGhlIGxvZyBsZXZlbCBmb3IgdGhlIGVudHJ5LiBDYW4gYmUgZWl0aGVyIFwiaW5mb1wiLCBcIndhcm5pbmdcIiBvciBcImVycm9yXCJcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSBUaGUgbG9nIG1lc3NhZ2UgdGV4dFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ubG9nKFwiaW5mb1wiLCBcIkFuIGV4YW1wbGUgbG9nIG1lc3NhZ2VcIikudGhlbigoKSA9PiBjb25zb2xlLmxvZygnTG9nIGluZm8gbWVzc2FnZScpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgbG9nKGxldmVsLCBtZXNzYWdlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignd3JpdGUtdG8tbG9nJywgeyBsZXZlbCwgbWVzc2FnZSB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE9wZW5zIHRoZSBwYXNzZWQgVVJMIGluIHRoZSBkZWZhdWx0IHdlYiBicm93c2VyLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgSXQgb25seSBzdXBwb3J0cyBodHRwKHMpIGFuZCBmaW4ocykgcHJvdG9jb2xzIGJ5IGRlZmF1bHQuXG4gICAgICogSW4gb3JkZXIgdG8gdXNlIG90aGVyIGN1c3RvbSBwcm90b2NvbHMsIHRoZXkgaGF2ZSB0byBiZSBlbmFibGVkIHZpYVxuICAgICAqIFtBUEkgc2VjdXJpdHkgc2V0dGluZ3NdKGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvYXBpLXNlY3VyaXR5KS5cbiAgICAgKiBGaWxlIHByb3RvY29sIGFuZCBmaWxlIHBhdGggYXJlIG5vdCBzdXBwb3J0ZWQuXG4gICAgICogQHBhcmFtIHVybCBUaGUgVVJMIHRvIG9wZW5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLm9wZW5VcmxXaXRoQnJvd3NlcignaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvc3RhYmxlL3R1dG9yaWFsLVN5c3RlbS5vcGVuVXJsV2l0aEJyb3dzZXIuaHRtbCcpXG4gICAgICogLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ09wZW5lZCBVUkwnKSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogRXhhbXBsZSBvZiBwZXJtaXNzaW9uIGRlZmluaXRpb24gdG8gZW5hYmxlIG5vbi1kZWZhdWx0IHByb3RvY29sczpcbiAgICAgKlxuICAgICAqIE5vdGU6IHBlcm1pc3Npb24gZGVmaW5pdGlvbiBzaG91bGQgYmUgc3BlY2lmaWVkIGluIGFuIGFwcCBtYW5pZmVzdCBmaWxlIGlmIHRoZXJlIGlzIG5vIERPUyBzZXR0aW5ncy5cbiAgICAgKiBPdGhlcndpc2UgaXQgaGFzIHRvIGJlIHNwZWNpZmllZCBpbiBib3RoIERPUyBhbmQgYXBwIG1hbmlmZXN0IGZpbGVzLlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAgICAgXCJwZXJtaXNzaW9uc1wiOiB7XG4gICAgICogICAgICAgIFwiU3lzdGVtXCI6IHtcbiAgICAgKiAgICAgICAgICAgIFwib3BlblVybFdpdGhCcm93c2VyXCI6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJlbmFibGVkXCI6IHRydWUsXG4gICAgICogICAgICAgICAgICAgICAgIFwicHJvdG9jb2xzXCI6IFsgXCJtc3RlYW1zXCIsIFwic2xhY2tcIl1cbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgIH1cbiAgICAgKiAgICAgfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIG9wZW5VcmxXaXRoQnJvd3Nlcih1cmwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdvcGVuLXVybC13aXRoLWJyb3dzZXInLCB7IHVybCB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgcmVnaXN0cnkgZW50cnkgdW5kZXIgdGhlIEhLQ1Ugcm9vdCBXaW5kb3dzIHJlZ2lzdHJ5IGtleSBpZiB0aGUgZ2l2ZW4gY3VzdG9tIHByb3RvY29sIG5hbWUgZG9lc24ndCBleGlzdCBvclxuICAgICAqIG92ZXJ3cml0ZXMgdGhlIGV4aXN0aW5nIHJlZ2lzdHJ5IGVudHJ5IGlmIHRoZSBnaXZlbiBjdXN0b20gcHJvdG9jb2wgbmFtZSBhbHJlYWR5IGV4aXN0cy5cbiAgICAgKlxuICAgICAqIE5vdGU6IFRoaXMgbWV0aG9kIGlzIHJlc3RyaWN0ZWQgYnkgZGVmYXVsdCBhbmQgbXVzdCBiZSBlbmFibGVkIHZpYVxuICAgICAqIHtAbGluayBodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9kb2NzL2FwaS1zZWN1cml0eSBBUEkgc2VjdXJpdHkgc2V0dGluZ3N9LiBJdCByZXF1aXJlcyBSVk0gMTIgb3IgaGlnaGVyIHZlcnNpb24uXG4gICAgICpcbiAgICAgKlxuICAgICAqIEByZW1hcmtzIFRoZXNlIHByb3RvY29scyBhcmUgcmVzZXJ2ZWQgYW5kIGNhbm5vdCBiZSByZWdpc3RlcmVkOlxuICAgICAqIC0gZmluXG4gICAgICogLSBmaW5zXG4gICAgICogLSBvcGVuZmluXG4gICAgICogLSBVUkkgU2NoZW1lcyByZWdpc3RlcmVkIHdpdGgge0BsaW5rIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xpc3Rfb2ZfVVJJX3NjaGVtZXMjT2ZmaWNpYWxfSUFOQS1yZWdpc3RlcmVkX3NjaGVtZXMgSUFOQX1cbiAgICAgKlxuICAgICAqIEB0aHJvd3MgaWYgYSBnaXZlbiBjdXN0b20gcHJvdG9jb2wgZmFpbGVkIHRvIGJlIHJlZ2lzdGVyZWQuXG4gICAgICogQHRocm93cyBpZiBhIG1hbmlmZXN0IFVSTCBjb250YWlucyB0aGUgJyUxJyBzdHJpbmcuXG4gICAgICogQHRocm93cyBpZiBhIG1hbmlmZXN0IFVSTCBjb250YWlucyBhIHF1ZXJ5IHN0cmluZyBwYXJhbWV0ZXIgd2hpY2ggbmFtZSBlcXVhbHMgdG8gdGhlIFByb3RvY29sIExhdW5jaCBSZXF1ZXN0IFBhcmFtZXRlciBOYW1lLlxuICAgICAqIEB0aHJvd3MgaWYgdGhlIGZ1bGwgbGVuZ3RoIG9mIHRoZSBjb21tYW5kIHN0cmluZyB0aGF0IGlzIHRvIGJlIHdyaXR0ZW4gdG8gdGhlIHJlZ2lzdHJ5IGV4Y2VlZHMgMjA0OCBieXRlcy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLnJlZ2lzdGVyQ3VzdG9tUHJvdG9jb2woe3Byb3RvY29sTmFtZToncHJvdG9jb2wxJ30pLnRoZW4oY29uc29sZS5sb2cpLmNhdGNoKGNvbnNvbGUuZXJyb3IpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHJlZ2lzdGVyQ3VzdG9tUHJvdG9jb2wob3B0aW9ucykge1xuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ011c3QgcHJvdmlkZSBhbiBvYmplY3Qgd2l0aCBhIGBwcm90b2NvbE5hbWVgIHByb3BlcnR5IGhhdmluZyBhIHN0cmluZyB2YWx1ZS4nKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbigncmVnaXN0ZXItY3VzdG9tLXByb3RvY29sJywgb3B0aW9ucyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIHJlZ2lzdHJ5IGVudHJ5IGZvciBhIGdpdmVuIGN1c3RvbSBwcm90b2NvbC5cbiAgICAgKlxuICAgICAqIE5vdGU6IFRoaXMgbWV0aG9kIGlzIHJlc3RyaWN0ZWQgYnkgZGVmYXVsdCBhbmQgbXVzdCBiZSBlbmFibGVkIHZpYVxuICAgICAqIHtAbGluayBodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9kb2NzL2FwaS1zZWN1cml0eSBBUEkgc2VjdXJpdHkgc2V0dGluZ3N9LiBJdCByZXF1aXJlcyBSVk0gMTIgb3IgaGlnaGVyIHZlcnNpb24uXG4gICAgICpcbiAgICAgKlxuICAgICAqIEByZW1hcmtzIFRoZXNlIHByb3RvY29scyBhcmUgcmVzZXJ2ZWQgYW5kIGNhbm5vdCBiZSB1bnJlZ2lzdGVyZWQ6XG4gICAgICogLSBmaW5cbiAgICAgKiAtIGZpbnNcbiAgICAgKiAtIG9wZW5maW5cbiAgICAgKiAtIFVSSSBTY2hlbWVzIHJlZ2lzdGVyZWQgd2l0aCB7QGxpbmsgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGlzdF9vZl9VUklfc2NoZW1lcyNPZmZpY2lhbF9JQU5BLXJlZ2lzdGVyZWRfc2NoZW1lcyBJQU5BfVxuICAgICAqXG4gICAgICogQHRocm93cyBpZiBhIHByb3RvY29sIGVudHJ5IGZhaWxlZCB0byBiZSByZW1vdmVkIGluIHJlZ2lzdHJ5LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGF3YWl0IGZpbi5TeXN0ZW0udW5yZWdpc3RlckN1c3RvbVByb3RvY29sKCdwcm90b2NvbDEnKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyB1bnJlZ2lzdGVyQ3VzdG9tUHJvdG9jb2wocHJvdG9jb2xOYW1lKSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCd1bnJlZ2lzdGVyLWN1c3RvbS1wcm90b2NvbCcsIHsgcHJvdG9jb2xOYW1lIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZXMgdGhlIHJlZ2lzdHJhdGlvbiBzdGF0ZSBmb3IgYSBnaXZlbiBjdXN0b20gcHJvdG9jb2wuXG4gICAgICpcbiAgICAgKiBOb3RlOiBUaGlzIG1ldGhvZCBpcyByZXN0cmljdGVkIGJ5IGRlZmF1bHQgYW5kIG11c3QgYmUgZW5hYmxlZCB2aWFcbiAgICAgKiB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXJzLm9wZW5maW4uY28vZG9jcy9hcGktc2VjdXJpdHkgQVBJIHNlY3VyaXR5IHNldHRpbmdzfS4gSXQgcmVxdWlyZXMgUlZNIDEyIG9yIGhpZ2hlciB2ZXJzaW9uLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgVGhlc2UgcHJvdG9jb2xzIGFyZSByZXNlcnZlZCBhbmQgY2Fubm90IGdldCBzdGF0ZXMgZm9yIHRoZW06XG4gICAgICogLSBmaW5cbiAgICAgKiAtIGZpbnNcbiAgICAgKiAtIG9wZW5maW5cbiAgICAgKiAtIFVSSSBTY2hlbWVzIHJlZ2lzdGVyZWQgd2l0aCB7QGxpbmsgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGlzdF9vZl9VUklfc2NoZW1lcyNPZmZpY2lhbF9JQU5BLXJlZ2lzdGVyZWRfc2NoZW1lcyBJQU5BfVxuICAgICAqXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcHJvdG9jb2xTdGF0ZSA9IGF3YWl0IGZpbi5TeXN0ZW0uZ2V0Q3VzdG9tUHJvdG9jb2xTdGF0ZSgncHJvdG9jb2wxJyk7XG4gICAgICovXG4gICAgYXN5bmMgZ2V0Q3VzdG9tUHJvdG9jb2xTdGF0ZShwcm90b2NvbE5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtY3VzdG9tLXByb3RvY29sLXN0YXRlJywgeyBwcm90b2NvbE5hbWUgfSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIHByb2Nlc3MgZW50cnkgZm9yIHRoZSBwYXNzZWQgVVVJRCBvYnRhaW5lZCBmcm9tIGEgcHJpb3IgY2FsbFxuICAgICAqIG9mIGZpbi5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKCkuXG4gICAgICogQHBhcmFtIHV1aWQgVGhlIFVVSUQgZm9yIGEgcHJvY2VzcyBvYnRhaW5lZCBmcm9tIGEgcHJpb3IgY2FsbCB0byBmaW4uZGVza3RvcC5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKClcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmxhdW5jaEV4dGVybmFsUHJvY2Vzcyh7XG4gICAgICogICAgIHBhdGg6IFwibm90ZXBhZFwiLFxuICAgICAqICAgICBsaXN0ZW5lcjogZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coXCJUaGUgZXhpdCBjb2RlXCIsIHJlc3VsdC5leGl0Q29kZSk7XG4gICAgICogICAgIH1cbiAgICAgKiB9KVxuICAgICAqIC50aGVuKGlkZW50aXR5ID0+IGZpbi5TeXN0ZW0ucmVsZWFzZUV4dGVybmFsUHJvY2VzcyhpZGVudGl0eS51dWlkKSlcbiAgICAgKiAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnUHJvY2VzcyBoYXMgYmVlbiB1bm1hcHBlZCEnKSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHJlbGVhc2VFeHRlcm5hbFByb2Nlc3ModXVpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3JlbGVhc2UtZXh0ZXJuYWwtcHJvY2VzcycsIHsgdXVpZCB9KS50aGVuKCgpID0+IHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNob3dzIHRoZSBDaHJvbWl1bSBEZXZlbG9wZXIgVG9vbHMgZm9yIHRoZSBzcGVjaWZpZWQgd2luZG93XG4gICAgICogQHBhcmFtIGlkZW50aXR5IFRoaXMgaXMgYSBvYmplY3QgdGhhdCBpcyBkZWZpbmVkIGJ5IHRoZSBJZGVudGl0eSBpbnRlcmZhY2VcbiAgICAgKlxuICAgICAqIEB0dXRvcmlhbCBTeXN0ZW0uc2hvd0RldmVsb3BlclRvb2xzXG4gICAgICovXG4gICAgc2hvd0RldmVsb3BlclRvb2xzKGlkZW50aXR5KSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignc2hvdy1kZXZlbG9wZXItdG9vbHMnLCBpZGVudGl0eSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBdHRlbXB0IHRvIGNsb3NlIGFuIGV4dGVybmFsIHByb2Nlc3MuIFRoZSBwcm9jZXNzIHdpbGwgYmUgdGVybWluYXRlZCBpZiBpdFxuICAgICAqIGhhcyBub3QgY2xvc2VkIGFmdGVyIHRoZSBlbGFwc2VkIHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzLlxuICAgICAqXG4gICAgICogTm90ZTogVGhpcyBtZXRob2QgaXMgcmVzdHJpY3RlZCBieSBkZWZhdWx0IGFuZCBtdXN0IGJlIGVuYWJsZWQgdmlhXG4gICAgICogPGEgaHJlZj1cImh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvYXBpLXNlY3VyaXR5XCI+QVBJIHNlY3VyaXR5IHNldHRpbmdzPC9hPi5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBBIG9iamVjdCBkZWZpbmVkIGluIHRoZSBUZXJtaW5hdGVFeHRlcm5hbFJlcXVlc3RUeXBlIGludGVyZmFjZVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ubGF1bmNoRXh0ZXJuYWxQcm9jZXNzKHtcbiAgICAgKiAgICAgcGF0aDogXCJub3RlcGFkXCIsXG4gICAgICogICAgIGxpc3RlbmVyOiBmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhcIlRoZSBleGl0IGNvZGVcIiwgcmVzdWx0LmV4aXRDb2RlKTtcbiAgICAgKiAgICAgfVxuICAgICAqIH0pXG4gICAgICogLnRoZW4oaWRlbnRpdHkgPT4gZmluLlN5c3RlbS50ZXJtaW5hdGVFeHRlcm5hbFByb2Nlc3Moe3V1aWQ6IGlkZW50aXR5LnV1aWQsIHRpbWVvdXQ6MjAwMCwga2lsbFRyZWU6IGZhbHNlfSkpXG4gICAgICogLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1Rlcm1pbmF0ZSB0aGUgcHJvY2VzcycpKVxuICAgICAqIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgdGVybWluYXRlRXh0ZXJuYWxQcm9jZXNzKG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCd0ZXJtaW5hdGUtZXh0ZXJuYWwtcHJvY2VzcycsIG9wdGlvbnMpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBPcGVuRmluIFJ1bnRpbWUgUHJveHkgc2V0dGluZ3MuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgQSBjb25maWcgb2JqZWN0IGRlZmluZWQgaW4gdGhlIFByb3h5Q29uZmlnIGludGVyZmFjZVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0udXBkYXRlUHJveHlTZXR0aW5ncyh7cHJveHlBZGRyZXNzOicxMjcuMC4wLjEnLCBwcm94eVBvcnQ6ODA4MCwgdHlwZTonaHR0cCd9KVxuICAgICAqIC50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdVcGRhdGUgcHJveHkgc3VjY2Vzc2Z1bGx5JykpXG4gICAgICogLmNhdGNoKGVyciA9PiBjb25zb2xlLmVycm9yKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHVwZGF0ZVByb3h5U2V0dGluZ3Mob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3VwZGF0ZS1wcm94eScsIG9wdGlvbnMpLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIHRoZSBnaXZlbiBhcHBsaWNhdGlvbiBhc3NldC5cbiAgICAgKlxuICAgICAqIE5vdGU6IFRoaXMgbWV0aG9kIGlzIHJlc3RyaWN0ZWQgYnkgZGVmYXVsdCBhbmQgbXVzdCBiZSBlbmFibGVkIHZpYVxuICAgICAqIDxhIGhyZWY9XCJodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9kb2NzL2FwaS1zZWN1cml0eVwiPkFQSSBzZWN1cml0eSBzZXR0aW5nczwvYT4uXG4gICAgICogQHBhcmFtIGFwcEFzc2V0IEFwcCBhc3NldCBvYmplY3RcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBkb3dubG9hZEFzc2V0KCkge1xuICAgICAqICAgICBjb25zdCBhcHBBc3NldCA9IHtcbiAgICAgKiAgICAgICAgIHNyYzogYCR7IGxvY2F0aW9uLm9yaWdpbiB9L2Fzc2V0cy56aXBgLFxuICAgICAqICAgICAgICAgYWxpYXM6ICdkaXJBcHAnLFxuICAgICAqICAgICAgICAgdmVyc2lvbjogJzEuMjMuMjQnLFxuICAgICAqICAgICAgICAgdGFyZ2V0OiAnYXNzZXRzL3J1bi5iYXQnXG4gICAgICogICAgIH07XG4gICAgICpcbiAgICAgKiAgICAgcmV0dXJuIGZpbi5TeXN0ZW0uZG93bmxvYWRBc3NldChhcHBBc3NldCwgKHByb2dyZXNzID0+IHtcbiAgICAgKiAgICAgLy9QcmludCBwcm9ncmVzcyBhcyB3ZSBkb3dubG9hZCB0aGUgYXNzZXQuXG4gICAgICogICAgICAgICBjb25zdCBkb3dubG9hZGVkUGVyY2VudCA9IE1hdGguZmxvb3IoKHByb2dyZXNzLmRvd25sb2FkZWRCeXRlcyAvIHByb2dyZXNzLnRvdGFsQnl0ZXMpICogMTAwKTtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKGBEb3dubG9hZGVkICR7ZG93bmxvYWRlZFBlcmNlbnR9JWApO1xuICAgICAqICAgICB9KSk7XG4gICAgICogfVxuICAgICAqXG4gICAgICogZG93bmxvYWRBc3NldCgpXG4gICAgICogLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1N1Y2Nlc3MnKSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUuZXJyb3IoZXJyKSk7XG4gICAgICpcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICAvLyBpbmNvbXBhdGlibGUgd2l0aCBzdGFuZGFsb25lIG5vZGUgcHJvY2Vzcy5cbiAgICBhc3luYyBkb3dubG9hZEFzc2V0KGFwcEFzc2V0LCBwcm9ncmVzc0xpc3RlbmVyKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvZXhwbGljaXQtZnVuY3Rpb24tcmV0dXJuLXR5cGUsIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICAgICAgICBjb25zdCBub29wID0gKCkgPT4geyB9O1xuICAgICAgICBsZXQgcmVzb2x2ZSA9IG5vb3A7XG4gICAgICAgIGxldCByZWplY3QgPSBub29wO1xuICAgICAgICBjb25zdCBkb3dubG9hZENvbXBsZXRlUHJvbWlzZSA9IG5ldyBQcm9taXNlKCh5LCBuKSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlID0geTtcbiAgICAgICAgICAgIHJlamVjdCA9IG47XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBub2RlLmpzIGVudmlyb25tZW50IG5vdCBzdXBwb3J0ZWRcbiAgICAgICAgaWYgKHRoaXMud2lyZS5lbnZpcm9ubWVudC50eXBlICE9PSAnb3BlbmZpbicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyB0cmFuc3BvcnRfZXJyb3JzXzEkMS5Ob3RTdXBwb3J0ZWRFcnJvcignZG93bmxvYWRBc3NldCBvbmx5IHN1cHBvcnRlZCBpbiBhbiBPcGVuRmluIFJlbmRlciBwcm9jZXNzJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2FsbFNpdGUgPSB0cmFuc3BvcnRfZXJyb3JzXzEkMS5SdW50aW1lRXJyb3IuZ2V0Q2FsbFNpdGUoKTtcbiAgICAgICAgY29uc3QgZG93bmxvYWRJZCA9IHRoaXMud2lyZS5lbnZpcm9ubWVudC5nZXROZXh0TWVzc2FnZUlkKCkudG9TdHJpbmcoKTtcbiAgICAgICAgY29uc3QgZGxQcm9ncmVzc0tleSA9IGBhc3NldC1kb3dubG9hZC1wcm9ncmVzcy0ke2Rvd25sb2FkSWR9YDtcbiAgICAgICAgY29uc3QgZGxFcnJvcktleSA9IGBhc3NldC1kb3dubG9hZC1lcnJvci0ke2Rvd25sb2FkSWR9YDtcbiAgICAgICAgY29uc3QgZGxDb21wbGV0ZUtleSA9IGBhc3NldC1kb3dubG9hZC1jb21wbGV0ZS0ke2Rvd25sb2FkSWR9YDtcbiAgICAgICAgY29uc3QgZGxQcm9ncmVzcyA9IChwcm9ncmVzcykgPT4ge1xuICAgICAgICAgICAgY29uc3QgcCA9IHtcbiAgICAgICAgICAgICAgICBkb3dubG9hZGVkQnl0ZXM6IHByb2dyZXNzLmRvd25sb2FkZWRCeXRlcyxcbiAgICAgICAgICAgICAgICB0b3RhbEJ5dGVzOiBwcm9ncmVzcy50b3RhbEJ5dGVzXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcHJvZ3Jlc3NMaXN0ZW5lcihwKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgY2xlYW5MaXN0ZW5lcnMgPSAoKSA9PiB7XG4gICAgICAgICAgICAvLyBUT0RPOiBmaXggaW50ZXJuYWwgdHlwZXNcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZGxQcm9ncmVzc0tleSwgZGxQcm9ncmVzcyk7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGRsRXJyb3IgPSAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgY2xlYW5MaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgIGNvbnN0IHsgcmVhc29uLCBlcnI6IGVycm9yIH0gPSBwYXlsb2FkO1xuICAgICAgICAgICAgcmVqZWN0KG5ldyB0cmFuc3BvcnRfZXJyb3JzXzEkMS5SdW50aW1lRXJyb3IoeyByZWFzb24sIGVycm9yIH0sIGNhbGxTaXRlKSk7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGRsQ29tcGxldGUgPSAoKSA9PiB7XG4gICAgICAgICAgICBjbGVhbkxpc3RlbmVycygpO1xuICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9O1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAvLyBUT0RPOiBmaXggaW50ZXJuYWwgdHlwZXNcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgIHRoaXMub24oZGxQcm9ncmVzc0tleSwgZGxQcm9ncmVzcyksXG4gICAgICAgICAgICAvLyBUT0RPOiBmaXggaW50ZXJuYWwgdHlwZXNcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgIHRoaXMub25jZShkbEVycm9yS2V5LCBkbEVycm9yKSxcbiAgICAgICAgICAgIC8vIFRPRE86IGZpeCBpbnRlcm5hbCB0eXBlc1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgdGhpcy5vbmNlKGRsQ29tcGxldGVLZXksIGRsQ29tcGxldGUpXG4gICAgICAgIF0pO1xuICAgICAgICBjb25zdCBkb3dubG9hZE9wdGlvbnMgPSBPYmplY3QuYXNzaWduKGFwcEFzc2V0LCB7IGRvd25sb2FkSWQgfSk7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdkb3dubG9hZC1hc3NldCcsIGRvd25sb2FkT3B0aW9ucykuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgY2xlYW5MaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBkb3dubG9hZENvbXBsZXRlUHJvbWlzZTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRG93bmxvYWRzIGEgdmVyc2lvbiBvZiB0aGUgcnVudGltZS5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIERvd25sb2FkIG9wdGlvbnMuXG4gICAgICogQHBhcmFtIHByb2dyZXNzTGlzdGVuZXIgLSBjYWxsZWQgYXMgdGhlIHJ1bnRpbWUgaXMgZG93bmxvYWRlZCB3aXRoIHByb2dyZXNzIGluZm9ybWF0aW9uLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgT25seSBzdXBwb3J0ZWQgaW4gYW4gT3BlbkZpbiBSZW5kZXIgcHJvY2Vzcy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiB2YXIgZG93bmxvYWRPcHRpb25zID0ge1xuICAgICAqICAgICAvL1NwZWNpZmljIHZlcnNpb24gbnVtYmVyIHJlcXVpcmVkLCBpZiBnaXZlbiBhIHJlbGVhc2UgY2hhbm5lbCB0aGUgY2FsbCB3aWxsIHByb2R1Y2UgYW4gZXJyb3IuXG4gICAgICogICAgIHZlcnNpb246ICc5LjYxLjMwLjEnXG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIGZ1bmN0aW9uIG9uUHJvZ3Jlc3MocHJvZ3Jlc3MpIHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coYCR7TWF0aC5mbG9vcigocHJvZ3Jlc3MuZG93bmxvYWRlZEJ5dGVzIC8gcHJvZ3Jlc3MudG90YWxCeXRlcykgKiAxMDApfSVgKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBmaW4uU3lzdGVtLmRvd25sb2FkUnVudGltZShkb3dubG9hZE9wdGlvbnMsIG9uUHJvZ3Jlc3MpLnRoZW4oKCkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnRG93bmxvYWQgY29tcGxldGUnKTtcbiAgICAgKiB9KS5jYXRjaChlcnIgPT4gICAge1xuICAgICAqICAgICBjb25zb2xlLmxvZyhgRG93bmxvYWQgRmFpbGVkLCB3ZSBjb3VsZCByZXRyeTogJHtlcnIubWVzc2FnZX1gKTtcbiAgICAgKiAgICAgY29uc29sZS5sb2coZXJyKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBkb3dubG9hZFJ1bnRpbWUob3B0aW9ucywgcHJvZ3Jlc3NMaXN0ZW5lcikge1xuICAgICAgICBjb25zdCBjYWxsc2l0ZXMgPSB0cmFuc3BvcnRfZXJyb3JzXzEkMS5SdW50aW1lRXJyb3IuZ2V0Q2FsbFNpdGUoKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIC8vIG5vZGUuanMgZW52aXJvbm1lbnQgbm90IHN1cHBvcnRlZFxuICAgICAgICAgICAgaWYgKHRoaXMud2lyZS5lbnZpcm9ubWVudC50eXBlICE9PSAnb3BlbmZpbicpIHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IHRyYW5zcG9ydF9lcnJvcnNfMSQxLk5vdFN1cHBvcnRlZEVycm9yKCdkb3dubG9hZFJ1bnRpbWUgb25seSBzdXBwb3J0ZWQgaW4gYW4gT3BlbkZpbiBSZW5kZXIgcHJvY2VzcycpKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBkb3dubG9hZElkID0gdGhpcy53aXJlLmVudmlyb25tZW50LmdldE5leHRNZXNzYWdlSWQoKS50b1N0cmluZygpO1xuICAgICAgICAgICAgY29uc3QgZGxQcm9ncmVzc0tleSA9IGBydW50aW1lLWRvd25sb2FkLXByb2dyZXNzLSR7ZG93bmxvYWRJZH1gO1xuICAgICAgICAgICAgY29uc3QgZGxFcnJvcktleSA9IGBydW50aW1lLWRvd25sb2FkLWVycm9yLSR7ZG93bmxvYWRJZH1gO1xuICAgICAgICAgICAgY29uc3QgZGxDb21wbGV0ZUtleSA9IGBydW50aW1lLWRvd25sb2FkLWNvbXBsZXRlLSR7ZG93bmxvYWRJZH1gO1xuICAgICAgICAgICAgY29uc3QgZGxQcm9ncmVzcyA9IChwcm9ncmVzcykgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHAgPSB7XG4gICAgICAgICAgICAgICAgICAgIGRvd25sb2FkZWRCeXRlczogcHJvZ3Jlc3MuZG93bmxvYWRlZEJ5dGVzLFxuICAgICAgICAgICAgICAgICAgICB0b3RhbEJ5dGVzOiBwcm9ncmVzcy50b3RhbEJ5dGVzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBwcm9ncmVzc0xpc3RlbmVyKHApO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IGNsZWFuTGlzdGVuZXJzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IGZpeCBpbnRlcm5hbCB0eXBlc1xuICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGRsUHJvZ3Jlc3NLZXksIGRsUHJvZ3Jlc3MpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IGRsRXJyb3IgPSAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgICAgIGNsZWFuTGlzdGVuZXJzKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgeyByZWFzb24sIGVycjogZXJyb3IgfSA9IHBheWxvYWQ7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyB0cmFuc3BvcnRfZXJyb3JzXzEkMS5SdW50aW1lRXJyb3IoeyByZWFzb24sIGVycm9yIH0sIGNhbGxzaXRlcykpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IGRsQ29tcGxldGUgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY2xlYW5MaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLy8gVE9ETzogZml4IGludGVybmFsIHR5cGVzXG4gICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgICAgICB0aGlzLm9uKGRsUHJvZ3Jlc3NLZXksIGRsUHJvZ3Jlc3MpO1xuICAgICAgICAgICAgLy8gVE9ETzogZml4IGludGVybmFsIHR5cGVzXG4gICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgICAgICB0aGlzLm9uY2UoZGxFcnJvcktleSwgZGxFcnJvcik7XG4gICAgICAgICAgICAvLyBUT0RPOiBmaXggaW50ZXJuYWwgdHlwZXNcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgICAgIHRoaXMub25jZShkbENvbXBsZXRlS2V5LCBkbENvbXBsZXRlKTtcbiAgICAgICAgICAgIGNvbnN0IGRvd25sb2FkT3B0aW9ucyA9IE9iamVjdC5hc3NpZ24ob3B0aW9ucywgeyBkb3dubG9hZElkIH0pO1xuICAgICAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2Rvd25sb2FkLXJ1bnRpbWUnLCBkb3dubG9hZE9wdGlvbnMpLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBjbGVhbkxpc3RlbmVycygpO1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBEb3dubG9hZCBwcmVsb2FkIHNjcmlwdHMgZnJvbSBnaXZlbiBVUkxzXG4gICAgICogQHBhcmFtIHNjcmlwdHMgLSBVUkxzIG9mIHByZWxvYWQgc2NyaXB0cy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBzY3JpcHRzID0gW1xuICAgICAqICAgICB7IHVybDogJ2h0dHA6Ly8uLi4vcHJlbG9hZC5qcycgfSxcbiAgICAgKiAgICAgeyB1cmw6ICdodHRwOi8vLi4uL3ByZWxvYWQyLmpzJyB9XG4gICAgICogXTtcbiAgICAgKlxuICAgICAqIGZpbi5TeXN0ZW0uZG93bmxvYWRQcmVsb2FkU2NyaXB0cyhzY3JpcHRzKS50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAqICAgICByZXN1bHRzLmZvckVhY2goKHt1cmwsIHN1Y2Nlc3MsIGVycm9yfSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coYFVSTDogJHt1cmx9YCk7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhgU3VjY2VzczogJHtzdWNjZXNzfWApO1xuICAgICAqICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICogICAgICAgICAgICAgY29uc29sZS5sb2coYEVycm9yOiAke2Vycm9yfWApO1xuICAgICAqICAgICAgICAgfVxuICAgICAqICAgICB9KTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBkb3dubG9hZFByZWxvYWRTY3JpcHRzKHNjcmlwdHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdkb3dubG9hZC1wcmVsb2FkLXNjcmlwdHMnLCB7IHNjcmlwdHMgfSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhbiBhcnJheSBvZiBkYXRhIChuYW1lLCBpZHMsIGJvdW5kcykgZm9yIGFsbCBhcHBsaWNhdGlvbiB3aW5kb3dzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0QWxsRXh0ZXJuYWxBcHBsaWNhdGlvbnMoKVxuICAgICAqIC50aGVuKGV4dGVybmFsQXBwcyA9PiBjb25zb2xlLmxvZygnVG90YWwgZXh0ZXJuYWwgYXBwczogJyArIGV4dGVybmFsQXBwcy5sZW5ndGgpKVxuICAgICAqIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0QWxsRXh0ZXJuYWxBcHBsaWNhdGlvbnMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWFsbC1leHRlcm5hbC1hcHBsaWNhdGlvbnMnKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGFwcCBhc3NldCBpbmZvcm1hdGlvbi5cbiAgICAgKiBAcGFyYW0gb3B0aW9uc1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0QXBwQXNzZXRJbmZvKHthbGlhczoncHJvY2V4cCd9KS50aGVuKGFzc2V0SW5mbyA9PiBjb25zb2xlLmxvZyhhc3NldEluZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0QXBwQXNzZXRJbmZvKG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtYXBwLWFzc2V0LWluZm8nLCBvcHRpb25zKS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogR2V0IGFkZGl0aW9uYWwgaW5mbyBvZiBjb29raWVzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0uZ2V0Q29va2llcyh7bmFtZTogJ215Q29va2llJ30pLnRoZW4oY29va2llcyA9PiBjb25zb2xlLmxvZyhjb29raWVzKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldENvb2tpZXMob3B0aW9ucykge1xuICAgICAgICBjb25zdCB1cmwgPSB0aGlzLndpcmUuZW52aXJvbm1lbnQuZ2V0VXJsKCk7XG4gICAgICAgIGNvbnN0IG5ld09wdGlvbnMgPSBPYmplY3QuYXNzaWduKG9wdGlvbnMsIHsgdXJsIH0pO1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1jb29raWVzJywgbmV3T3B0aW9ucykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgbWluaW11bSBsb2cgbGV2ZWwgYWJvdmUgd2hpY2ggbG9ncyB3aWxsIGJlIHdyaXR0ZW4gdG8gdGhlIE9wZW5GaW4gbG9nXG4gICAgICogQHBhcmFtIFRoZSBtaW5pbXVtIGxldmVsIChpbmNsdXNpdmUpIGFib3ZlIHdoaWNoIGFsbCBjYWxscyB0byBsb2cgd2lsbCBiZSB3cml0dGVuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5zZXRNaW5Mb2dMZXZlbChcInZlcmJvc2VcIikudGhlbigoKSA9PiBjb25zb2xlLmxvZyhcImxvZyBsZXZlbCBpcyBzZXQgdG8gdmVyYm9zZVwiKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHNldE1pbkxvZ0xldmVsKGxldmVsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignc2V0LW1pbi1sb2ctbGV2ZWwnLCB7IGxldmVsIH0pLnRoZW4oKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBVVUlEIG9mIHRoZSBjb21wdXRlciBvbiB3aGljaCB0aGUgcnVudGltZSBpcyBpbnN0YWxsZWRcbiAgICAgKiBAcGFyYW0gdXVpZCBUaGUgdXVpZCBvZiB0aGUgcnVubmluZyBhcHBsaWNhdGlvblxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ucmVzb2x2ZVV1aWQoJ09wZW5maW5QT0MnKS50aGVuKGVudGl0eSA9PiBjb25zb2xlLmxvZyhlbnRpdHkpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgcmVzb2x2ZVV1aWQodXVpZCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlXG4gICAgICAgICAgICAuc2VuZEFjdGlvbigncmVzb2x2ZS11dWlkJywge1xuICAgICAgICAgICAgZW50aXR5S2V5OiB1dWlkXG4gICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBhbiBhcnJheSBvZiBkYXRhIGZvciBhbGwgZXh0ZXJuYWwgYXBwbGljYXRpb25zXG4gICAgICogQHBhcmFtIHJlcXVlc3RpbmdJZGVudGl0eSBUaGlzIG9iamVjdCBpcyBkZXNjcmliZWQgaW4gdGhlIElkZW50aXR5IHR5cGVkZWZcbiAgICAgKiBAcGFyYW0gZGF0YSBBbnkgZGF0YSB0eXBlIHRvIHBhc3MgdG8gdGhlIG1ldGhvZFxuICAgICAqXG4gICAgICogQGlnbm9yZVxuICAgICAqL1xuICAgIGV4ZWN1dGVPblJlbW90ZShyZXF1ZXN0aW5nSWRlbnRpdHksIGRhdGEpIHtcbiAgICAgICAgZGF0YS5yZXF1ZXN0aW5nSWRlbnRpdHkgPSByZXF1ZXN0aW5nSWRlbnRpdHk7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuZmVycnlBY3Rpb24oZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlYWRzIHRoZSBzcGVjaWZlZCB2YWx1ZSBmcm9tIHRoZSByZWdpc3RyeS5cbiAgICAgKiBAcmVtYXJrcyBUaGlzIG1ldGhvZCBpcyByZXN0cmljdGVkIGJ5IGRlZmF1bHQgYW5kIG11c3QgYmUgZW5hYmxlZCB2aWFcbiAgICAgKiBbQVBJIHNlY3VyaXR5IHNldHRpbmdzXShodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9kb2NzL2FwaS1zZWN1cml0eSkuXG4gICAgICogQHBhcmFtIHJvb3RLZXkgLSBUaGUgcmVnaXN0cnkgcm9vdCBrZXkuXG4gICAgICogQHBhcmFtIHN1YmtleSAtIFRoZSByZWdpc3RyeSBrZXkuXG4gICAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHJlZ2lzdHJ5IHZhbHVlIG5hbWUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5yZWFkUmVnaXN0cnlWYWx1ZShcIkhLRVlfTE9DQUxfTUFDSElORVwiLCBcIkhBUkRXQVJFXFxcXERFU0NSSVBUSU9OXFxcXFN5c3RlbVwiLCBcIkJvb3RBcmNoaXRlY3R1cmVcIikudGhlbih2YWwgPT4gY29uc29sZS5sb2codmFsKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogU2VlIHtAbGluayBodHRwczovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L3dpbmRvd3MvZGVza3RvcC9tczY4MTM4Mih2PXZzLjg1KS5hc3B4IGhlcmV9IGZvciBXaW5kb3cncyBlcnJvciBjb2RlIGRlZmluaXRpb25zLlxuICAgICAqXG4gICAgICogRXhhbXBsZSBwYXlsb2FkcyBvZiBkaWZmZXJlbnQgcmVnaXN0cnkgdHlwZXM6XG4gICAgICpcbiAgICAgKiBTZWUgbGlzdCBvZiB0eXBlcyB7QGxpbmsgaHR0cHM6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS93aW5kb3dzL2Rlc2t0b3AvbXM3MjQ4ODQodj12cy44NSkuYXNweCBoZXJlfS5cbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogLy8gUkVHX0RXT1JEXG4gICAgICoge1xuICAgICAqICAgICBkYXRhOiAxLFxuICAgICAqICAgICByb290S2V5OiBcIkhLRVlfTE9DQUxfTUFDSElORVwiLFxuICAgICAqICAgICBzdWJrZXk6IFwiRm9vXFxCYXJcIixcbiAgICAgKiAgICAgdHlwZTogXCJSRUdfRFdPUkRcIixcbiAgICAgKiAgICAgdmFsdWU6IFwiQmF6XCJcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiAvLyBSRUdfUVdPUkRcbiAgICAgKiB7XG4gICAgICogICAgIGRhdGE6IDEzMTA4MTQ2NjcxMzM0MTEyLFxuICAgICAqICAgICByb290S2V5OiBcIkhLRVlfTE9DQUxfTUFDSElORVwiLFxuICAgICAqICAgICBzdWJrZXk6IFwiRm9vXFxCYXJcIixcbiAgICAgKiAgICAgdHlwZTogXCJSRUdfUVdPUkRcIixcbiAgICAgKiAgICAgdmFsdWU6IFwiQmF6XCJcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiAvLyBSRUdfU1pcbiAgICAgKiB7XG4gICAgICogICAgIGRhdGE6IFwiRm9vQmFyQmF6XCIsXG4gICAgICogICAgIHJvb3RLZXk6IFwiSEtFWV9MT0NBTF9NQUNISU5FXCIsXG4gICAgICogICAgIHN1YmtleTogXCJGb29cXEJhclwiLFxuICAgICAqICAgICB0eXBlOiBcIlJFR19TWlwiLFxuICAgICAqICAgICB2YWx1ZTogXCJCYXpcIlxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIC8vIFJFR19FWFBBTkRfU1pcbiAgICAgKiB7XG4gICAgICogICAgIGRhdGE6IFwiQzpcXFVzZXJcXEpvaG5Eb2VcXEFwcERhdGFcXExvY2FsXCIsXG4gICAgICogICAgIHJvb3RLZXk6IFwiSEtFWV9DVVJSRU5UX1VTRVJcIixcbiAgICAgKiAgICAgc3Via2V5OiBcIkZvb1xcQmFyXCIsXG4gICAgICogICAgIHR5cGU6IFwiUkVHX0VYUEFORF9TWlwiLFxuICAgICAqICAgICB2YWx1ZTogXCJCYXpcIlxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIC8vIFJFR19NVUxUSV9TWlxuICAgICAqIHtcbiAgICAgKiAgICAgZGF0YTogW1xuICAgICAqICAgICAgICAgXCJGb29cIixcbiAgICAgKiAgICAgICAgIFwiQmFyXCIsXG4gICAgICogICAgICAgICBcIkJhelwiXG4gICAgICogICAgIF0sXG4gICAgICogICAgIHJvb3RLZXk6IFwiSEtFWV9DVVJSRU5UX1VTRVJcIixcbiAgICAgKiAgICAgc3Via2V5OiBcIkZvb1xcQmFyXCIsXG4gICAgICogICAgIHR5cGU6IFwiUkVHX01VTFRJX1NaXCIsXG4gICAgICogICAgIHZhbHVlOiBcIkJhelwiXG4gICAgICogfVxuICAgICAqXG4gICAgICogLy8gUkVHX0JJTkFSWVxuICAgICAqIHtcbiAgICAgKiAgICAgZGF0YToge1xuICAgICAqICAgICAgICAgZGF0YTogW1xuICAgICAqICAgICAgICAgICAgIDI1NSxcbiAgICAgKiAgICAgICAgICAgICAyNTUsXG4gICAgICogICAgICAgICAgICAgMCxcbiAgICAgKiAgICAgICAgICAgICA0MyxcbiAgICAgKiAgICAgICAgICAgICA1NSxcbiAgICAgKiAgICAgICAgICAgICAwLFxuICAgICAqICAgICAgICAgICAgIDAsXG4gICAgICogICAgICAgICAgICAgMjU1LFxuICAgICAqICAgICAgICAgICAgIDI1NVxuICAgICAqICAgICAgICAgXSxcbiAgICAgKiAgICAgICAgIHR5cGU6IFwiQnVmZmVyXCJcbiAgICAgKiAgICAgfSxcbiAgICAgKiAgICAgcm9vdEtleTogXCJIS0VZX0NVUlJFTlRfVVNFUlwiLFxuICAgICAqICAgICBzdWJrZXk6IFwiRm9vXFxCYXJcIixcbiAgICAgKiAgICAgdHlwZTogXCJSRUdfQklOQVJZXCIsXG4gICAgICogICAgIHZhbHVlOiBcIkJhelwiXG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHJlYWRSZWdpc3RyeVZhbHVlKHJvb3RLZXksIHN1YmtleSwgdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZVxuICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ3JlYWQtcmVnaXN0cnktdmFsdWUnLCB7XG4gICAgICAgICAgICByb290S2V5LFxuICAgICAgICAgICAgc3Via2V5LFxuICAgICAgICAgICAgdmFsdWVcbiAgICAgICAgfSlcbiAgICAgICAgICAgIC50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVGhpcyBmdW5jdGlvbiBjYWxsIHdpbGwgcmVnaXN0ZXIgYSB1bmlxdWUgaWQgYW5kIHByb2R1Y2UgYSB0b2tlbi5cbiAgICAgKiBUaGUgdG9rZW4gY2FuIGJlIHVzZWQgdG8gYnJva2VyIGFuIGV4dGVybmFsIGNvbm5lY3Rpb24uXG4gICAgICogQHBhcmFtIHV1aWQgLSBBIFVVSUQgZm9yIHRoZSByZW1vdGUgY29ubmVjdGlvbi5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLnJlZ2lzdGVyRXh0ZXJuYWxDb25uZWN0aW9uKFwicmVtb3RlLWNvbm5lY3Rpb24tdXVpZFwiKS50aGVuKGNvbm4gPT4gY29uc29sZS5sb2coY29ubikpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKlxuICAgICAqXG4gICAgICogLy8gb2JqZWN0IGNvbWVzIGJhY2sgd2l0aFxuICAgICAqIC8vICAgICB0b2tlbjogXCIwNDg5RUFDNS02NDA0LTRGMEQtOTkzQi05MkJCOEVBQjQ0NURcIiwgLy8gdGhpcyB3aWxsIGJlIHVuaXF1ZSBlYWNoIHRpbWVcbiAgICAgKiAvLyAgICAgdXVpZDogXCJyZW1vdGUtY29ubmVjdGlvbi11dWlkXCJcbiAgICAgKlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHJlZ2lzdGVyRXh0ZXJuYWxDb25uZWN0aW9uKHV1aWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdyZWdpc3Rlci1leHRlcm5hbC1jb25uZWN0aW9uJywgeyB1dWlkIH0pLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBqc29uIGJsb2IgZm91bmQgaW4gdGhlIFtkZXNrdG9wIG93bmVyIHNldHRpbmdzXShodHRwczovL29wZW5maW4uY28vZG9jdW1lbnRhdGlvbi9kZXNrdG9wLW93bmVyLXNldHRpbmdzLylcbiAgICAgKiBmb3IgdGhlIHNwZWNpZmllZCBzZXJ2aWNlLlxuICAgICAqIEBwYXJhbSBzZXJ2aWNlSWRlbnRpZmllciBBbiBvYmplY3QgY29udGFpbmluZyBhIG5hbWUga2V5IHRoYXQgaWRlbnRpZmllcyB0aGUgc2VydmljZS5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIE1vcmUgaW5mb3JtYXRpb24gYWJvdXQgZGVza3RvcCBzZXJ2aWNlcyBjYW4gYmUgZm91bmQgW2hlcmVdKGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvZGVza3RvcC1zZXJ2aWNlcykuXG4gICAgICogVGhpcyBjYWxsIHdpbGwgcmVqZWN0IGlmIHRoZSBkZXNrdG9wIG93bmVyIHNldHRpbmdzIGZpbGUgaXMgbm90IHByZXNlbnQsIG5vdCBjb3JyZWN0bHkgZm9ybWF0dGVkLCBvciBpZiB0aGUgc2VydmljZSByZXF1ZXN0ZWQgaXMgbm90IGNvbmZpZ3VyZWQgb3IgY29uZmlndXJlZCBpbmNvcnJlY3RseS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiAvLyBIZXJlIHdlIGFyZSB1c2luZyB0aGUgW2xheW91dHNdKGh0dHBzOi8vZ2l0aHViLmNvbS9IYWRvdWtlbklPL2xheW91dHMtc2VydmljZSkgc2VydmljZS5cbiAgICAgKiBmaW4uU3lzdGVtLmdldFNlcnZpY2VDb25maWd1cmF0aW9uKHtuYW1lOidsYXlvdXRzJ30pLnRoZW4oY29uc29sZS5sb2cpLmNhdGNoKGNvbnNvbGUuZXJyb3IpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGdldFNlcnZpY2VDb25maWd1cmF0aW9uKHNlcnZpY2VJZGVudGlmaWVyKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2VydmljZUlkZW50aWZpZXIubmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTXVzdCBwcm92aWRlIGFuIG9iamVjdCB3aXRoIGEgYG5hbWVgIHByb3BlcnR5IGhhdmluZyBhIHN0cmluZyB2YWx1ZScpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgbmFtZSB9ID0gc2VydmljZUlkZW50aWZpZXI7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXNlcnZpY2UtY29uZmlndXJhdGlvbicsIHsgbmFtZSB9KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgYXN5bmMgZ2V0U3lzdGVtQXBwQ29uZmlnKG5hbWUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBuYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNdXN0IHByb3ZpZGUgYSBzdHJpbmcgdmFsdWUgZm9yIG5hbWUgb2Ygc3lzdGVtIGFwcCcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LXN5c3RlbS1hcHAtY29uZmlndXJhdGlvbicsIHsgbmFtZSB9KS50aGVuKCh7IHBheWxvYWQgfSkgPT4gcGF5bG9hZC5kYXRhKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJzIGEgc3lzdGVtIHNodXRkb3duIGhhbmRsZXIgc28gdXNlciBjYW4gZG8gc29tZSBjbGVhbnVwIGJlZm9yZSBzeXN0ZW0gaXMgc2h1dHRpbmcgZG93bi5cbiAgICAgKiBAcmVtYXJrcyBPbmNlIHN5c3RlbSBzaHV0ZG93biBzdGFydHMsIHlvdSBhcmUgdW5hYmxlIHRvIGNhbmNlbCBpdC5cbiAgICAgKiBAcGFyYW0gaGFuZGxlciBzeXN0ZW0gc2h1dGRvd24gaGFuZGxlclxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ucmVnaXN0ZXJTaHV0ZG93bkhhbmRsZXIoKHNodXRkb3duRXZlbnQpID0+IHtcbiAgICAgKiAgICAgICAgIC8vIHNhdmUgc3RhdGUgb3IgY2xlYW51cFxuICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ2RvIHNvbWUgY2xlYW51cCBiZWZvcmUgc2h1dGRvd24nKTtcbiAgICAgKiAgICAgICAgIC8vIE5vdGlmeSBhcHAgaXMgcmVhZHkgZm9yIHRlcm1pbmF0aW9uLlxuICAgICAqICAgICAgICAgc2h1dGRvd25FdmVudC5wcm9jZWVkKCk7XG4gICAgICogfSlcbiAgICAgKiAudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU2h1dGRvd24gaGFuZGxlciByZWdpc3RlcmVkIScpKVxuICAgICAqIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAqL1xuICAgIGFzeW5jIHJlZ2lzdGVyU2h1dGRvd25IYW5kbGVyKGhhbmRsZXIpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3N5c3RlbS1yZWdpc3Rlci1zaHV0ZG93bi1oYW5kbGVyJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgU3lzdGVtU2h1dGRvd25FdmVudE5hbWUgPSAnc3lzdGVtLXNodXRkb3duJztcbiAgICAgICAgY29uc3QgU3lzdGVtU2h1dGRvd25IYW5kbGVkRXZlbnROYW1lID0gJ3N5c3RlbS1zaHV0ZG93bi1oYW5kbGVkJztcbiAgICAgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSB0aGlzLndpcmUubWU7XG4gICAgICAgIGNvbnN0IHNodXRkb3duSGFuZGxlciA9IChwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwcm9jZWVkID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIG5vdGlmeSBjb3JlIHRoYXQgdGhlIGFwcCBpcyByZWFkeSBmb3Igc2h1dGRvd25cbiAgICAgICAgICAgICAgICB0aGlzLndpcmUuZW52aXJvbm1lbnQucmFpc2VFdmVudChgYXBwbGljYXRpb24vJHtTeXN0ZW1TaHV0ZG93bkhhbmRsZWRFdmVudE5hbWV9YCwge1xuICAgICAgICAgICAgICAgICAgICB1dWlkLFxuICAgICAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgICAgICB0b3BpYzogJ2FwcGxpY2F0aW9uJ1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGhhbmRsZXIoeyBwcm9jZWVkIH0pO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLm9uKFN5c3RlbVNodXRkb3duRXZlbnROYW1lLCBzaHV0ZG93bkhhbmRsZXIpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTaWduYWxzIHRoZSBSVk0gdG8gcGVyZm9ybSBhIGhlYWx0aCBjaGVjayBhbmQgcmV0dXJucyB0aGUgcmVzdWx0cyBhcyBqc29uLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgUmVxdWlyZXMgUlZNIDUuNStcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiB0cnkge1xuICAgICAqICAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgZmluLlN5c3RlbS5ydW5Sdm1IZWFsdGhDaGVjaygpO1xuICAgICAqICAgICBjb25zb2xlLmxvZyhyZXN1bHRzKTtcbiAgICAgKiB9IGNhdGNoKGUpIHtcbiAgICAgKiAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHJ1blJ2bUhlYWx0aENoZWNrKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3J1bi1ydm0taGVhbHRoLWNoZWNrJykudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIExhdW5jaCBhcHBsaWNhdGlvbiB1c2luZyBhIG1hbmlmZXN0IFVSTC9wYXRoLiBJdCBkaWZmZXJzIGZyb20gQXBwbGljYXRpb24uc3RhcnRGcm9tTWFuaWZlc3QgaW4gdGhhdCB0aGlzIEFQSSBjYW4gYWNjZXB0IGEgbWFuaWZlc3QgdXNpbmcgdGhlIGZpbiBwcm90b2NvbC5cbiAgICAgKiBAcGFyYW0gbWFuaWZlc3RVcmwgLSBUaGUgbWFuaWZlc3QncyBVUkwgb3IgcGF0aC5cbiAgICAgKiBAcGFyYW0gb3B0cyAtIFBhcmFtZXRlcnMgdGhhdCB0aGUgUlZNIHdpbGwgdXNlLlxuICAgICAqXG4gICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAqIEByZW1hcmtzIFN1cHBvcnRzIHByb3RvY29scyBodHRwL3MgYW5kIGZpbi9zLCBhbmQgYWxzbyBhIGxvY2FsIHBhdGguXG4gICAgICpcbiAgICAgKiBOb3RlOiBUaGlzIEFQSSBpcyBXaW5kb3dzIG9ubHkuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogVGhpcyBBUEkgY2FuIGhhbmRsZSBtb3N0IG1hbmlmZXN0IHR5cGVzLiBTb21lIGV4YW1wbGVzIGJlbG93LlxuICAgICAqXG4gICAgICogVHJhZGl0aW9uYWw6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBtYW5pZmVzdCA9IGF3YWl0IGZpbi5TeXN0ZW0ubGF1bmNoTWFuaWZlc3QoXG4gICAgICogICAnaHR0cHM6Ly9kZW1vYXBwZGlyZWN0b3J5Lm9wZW5mLmluL2Rlc2t0b3AvY29uZmlnL2FwcHMvT3BlbkZpbi9IZWxsb09wZW5GaW4vYXBwLmpzb24nKTtcbiAgICAgKiBjb25zb2xlLmxvZyhtYW5pZmVzdCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBQbGF0Zm9ybTpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgZmluLlN5c3RlbS5sYXVuY2hNYW5pZmVzdCgnaHR0cHM6Ly9vcGVuZmluLmdpdGh1Yi5pby9wbGF0Zm9ybS1hcGktcHJvamVjdC1zZWVkL3B1YmxpYy5qc29uJyk7XG4gICAgICogY29uc29sZS5sb2cobWFuaWZlc3QpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogTGF1bmNoaW5nIHRyYWRpdGlvbmFsIG1hbmlmZXN0IGludG8gYSBwbGF0Zm9ybTpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IG1hbmlmZXN0ID0gYXdhaXQgZmluLlN5c3RlbS5sYXVuY2hNYW5pZmVzdChcbiAgICAgKiAgICdodHRwczovL29wZW5maW4uZ2l0aHViLmlvL3BsYXRmb3JtLWFwaS1wcm9qZWN0LXNlZWQvcHVibGljLmpzb24/XFxcbiAgICAgKiAgICQkYXBwTWFuaWZlc3RVcmw9aHR0cHM6Ly9kZW1vYXBwZGlyZWN0b3J5Lm9wZW5mLmluL2Rlc2t0b3AvY29uZmlnL1xcXG4gICAgICogICBhcHBzL09wZW5GaW4vSGVsbG9PcGVuRmluL2FwcC5qc29uJyk7XG4gICAgICogY29uc29sZS5sb2cobWFuaWZlc3QpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogTGF1bmNoaW5nIHdpdGggUlZNIG9wdGlvbnM6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBtYW5pZmVzdCA9IGF3YWl0IGZpbi5TeXN0ZW0ubGF1bmNoTWFuaWZlc3QoJ2h0dHBzOi8vb3BlbmZpbi5naXRodWIuaW8vcGxhdGZvcm0tYXBpLXByb2plY3Qtc2VlZC9wdWJsaWMuanNvbicsXG4gICAgICogICAgIHsgbm9VaTogdHJ1ZSwgdXNlckFwcENvbmZpZ0FyZ3M6IHsgYWJjOiAnMTIzJywgeHl6OiAnNzg5JyB9IH0pO1xuICAgICAqIGNvbnNvbGUubG9nKG1hbmlmZXN0KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIExvY2FsIFBhdGg6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBtYW5pZmVzdCA9ICBhd2FpdCBmaW4uU3lzdGVtLmxhdW5jaE1hbmlmZXN0KCdmaWxlOi8vYzpcXFxccGF0aFxcXFx0b1xcXFxtYW5pZmVzdFxcXFxmaWxlLmpzb24nKTtcbiAgICAgKiBjb25zb2xlLmxvZyhtYW5pZmVzdCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBMYXVuY2hpbmcgd2l0aCBSVk0gJ3N1YnNjcmliZScgb3B0aW9uOlxuICAgICAqXG4gICAgICogVGhpcyBvcHRpb24gYWxsb3dzIHVzZXJzIHRvIHN1YnNjcmliZSB0byBhcHAgdmVyc2lvbiByZXNvbHZlciBldmVudHMgd2hlblxuICAgICAqIGNhbGxpbmcgbGF1bmNoTWFuaWZlc3Qgd2l0aCBmYWxsYmFja01hbmlmZXN0cyBzcGVjaWZpZWQuXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5TeXN0ZW0ubGF1bmNoTWFuaWZlc3QoJ2ZpbnM6Ly9zeXN0ZW0tYXBwcy9ub3RpZmljYXRpb25zL2FwcC5qc29uJywgeyBzdWJzY3JpYmU6IChsYXVuY2gpID0+IHtcbiAgICAgKiBcdFx0bGF1bmNoLm9uKCdhcHAtdmVyc2lvbi1wcm9ncmVzcycsIChwcm9ncmVzcykgPT4ge1xuICAgICAqIFx0XHRcdGNvbnNvbGUubG9nKFwiVHJ5aW5nIG1hbmlmZXN0IFwiICsgcHJvZ3Jlc3MubWFuaWZlc3QpXG4gICAgICogXHRcdH0pO1xuICAgICAqXG4gICAgICogXHRcdGxhdW5jaC5vbigncnVudGltZS1zdGF0dXMnLCAoc3RhdHVzKSA9PiB7XG4gICAgICogXHRcdFx0Y29uc29sZS5sb2coXCJSdW50aW1lIHN0YXR1czogXCIgKyBKU09OLnN0cmluZ2lmeShzdGF0dXMpKTtcbiAgICAgKiBcdFx0fSk7XG4gICAgICpcbiAgICAgKiBcdFx0Ly8gUlZNIGhhcyBzdWNjZXNzZnVsbHkgZm91bmQgdGhlIHRhcmdldCBydW50aW1lIHZlcnNpb25cbiAgICAgKiBcdFx0bGF1bmNoLm9uKCdhcHAtdmVyc2lvbi1jb21wbGV0ZScsIChjb21wbGV0ZSkgPT4ge1xuICAgICAqIFx0XHRcdGNvbnNvbGUubG9nKFwiUGFyZW50IGFwcCBcIiArIGNvbXBsZXRlLnNyY01hbmlmZXN0ICsgXCIgcmVzb2x2ZWQgdG8gXCIgKyBjb21wbGV0ZS5tYW5pZmVzdCk7XG4gICAgICogXHRcdFx0bGF1bmNoLnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgICAqIFx0XHR9KTtcbiAgICAgKlxuICAgICAqIFx0XHQvLyBSVk0gZmFpbGVkIHRvIGZpbmQgYW4gYXZhaWxhYmxlIHJ1bnRpbWUgdmVyc2lvblxuICAgICAqIFx0XHRsYXVuY2gub24oJ2FwcC12ZXJzaW9uLWVycm9yJywgKGVycm9yKSA9PiB7XG4gICAgICogXHRcdFx0Y29uc29sZS5sb2coXCJGYWlsZWQgdG8gcmVzb2x2ZSBcIiArIGVycm9yLnNyY01hbmlmZXN0ICsgXCIgZnJvbSB0aGUgZmFsbGJhY2tNYW5pZmVzdHNcIik7XG4gICAgICogXHRcdFx0bGF1bmNoLnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgICAqIFx0XHR9KTtcbiAgICAgKiBcdH1cbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBsYXVuY2hNYW5pZmVzdChtYW5pZmVzdFVybCwgb3B0cyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IHsgc3Vic2NyaWJlLCAuLi5fc2VuZE9wdHMgfSA9IG9wdHM7XG4gICAgICAgIGNvbnN0IHNlbmRPcHRzID0gX3NlbmRPcHRzO1xuICAgICAgICBpZiAoc3Vic2NyaWJlKSB7XG4gICAgICAgICAgICBjb25zdCBsYXVuY2hFbWl0dGVyID0gbmV3IGV2ZW50c18xJDYuRXZlbnRFbWl0dGVyKCk7XG4gICAgICAgICAgICBzdWJzY3JpYmUobGF1bmNoRW1pdHRlcik7XG4gICAgICAgICAgICBjb25zdCBBcHBWZXJzaW9uUHJvZ3Jlc3NFdmVudE5hbWUgPSAnYXBwLXZlcnNpb24tcHJvZ3Jlc3MnO1xuICAgICAgICAgICAgY29uc3QgUnVudGltZVN0YXR1c0V2ZW50TmFtZSA9ICdydW50aW1lLXN0YXR1cyc7XG4gICAgICAgICAgICBjb25zdCBBcHBWZXJzaW9uQ29tcGxldGVFdmVudE5hbWUgPSAnYXBwLXZlcnNpb24tY29tcGxldGUnO1xuICAgICAgICAgICAgY29uc3QgQXBwVmVyc2lvbkVycm9yRXZlbnROYW1lID0gJ2FwcC12ZXJzaW9uLWVycm9yJztcbiAgICAgICAgICAgIC8vIGFkZCBpZCB0byBhdm9pZCBtdWx0aXBsZSBhcGkgY2FsbHMgZ2V0dGluZyBkdXBsaWNhdGVkIGV2ZW50c1xuICAgICAgICAgICAgY29uc3QgaWQgPSB0aGlzLndpcmUuZW52aXJvbm1lbnQuZ2V0TmV4dE1lc3NhZ2VJZCgpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBzZW5kT3B0cy5hcHBWZXJzaW9uSWQgPSBpZDtcbiAgICAgICAgICAgIGNvbnN0IHN1cHBvcnRlZEV2ZW50cyA9IFtcbiAgICAgICAgICAgICAgICBBcHBWZXJzaW9uQ29tcGxldGVFdmVudE5hbWUsXG4gICAgICAgICAgICAgICAgQXBwVmVyc2lvblByb2dyZXNzRXZlbnROYW1lLFxuICAgICAgICAgICAgICAgIFJ1bnRpbWVTdGF0dXNFdmVudE5hbWUsXG4gICAgICAgICAgICAgICAgQXBwVmVyc2lvbkVycm9yRXZlbnROYW1lXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgY29uc3QgY2xlYW5FdmVudFBheWxvYWQgPSAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIFdlIG5lZWQgdG8gZG8gdHlwZSBjYXN0aW5ncyBiZWxvdyB0byBtYWtlIHN1cmUgdGhlIHJldHVybiB0eXBlIGlzIGNvcnJlY3QuXG4gICAgICAgICAgICAgICAgY29uc3QgeyBhcHBWZXJzaW9uSWQsIHRvcGljLCB0eXBlOiB0eXBlV2l0aElkLCAuLi5yZXN0IH0gPSBwYXlsb2FkO1xuICAgICAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBzdXBwb3J0ZWRFdmVudHMuZmluZCgoeCkgPT4gdHlwZVdpdGhJZC5pbmNsdWRlcyh4KSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgLi4ucmVzdCxcbiAgICAgICAgICAgICAgICAgICAgdHlwZVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgYXBwVmVyc2lvbkxpc3RlbmVyID0gKHBheWxvYWQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBjbGVhblBheWxvYWQgPSBjbGVhbkV2ZW50UGF5bG9hZChwYXlsb2FkKTtcbiAgICAgICAgICAgICAgICBsYXVuY2hFbWl0dGVyLmVtaXQoY2xlYW5QYXlsb2FkLnR5cGUsIGNsZWFuUGF5bG9hZCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgcmVtb3ZlQWxsTGlzdGVuZXJzID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoYCR7QXBwVmVyc2lvblByb2dyZXNzRXZlbnROYW1lfS4ke2lkfWAsIGFwcFZlcnNpb25MaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihgJHtSdW50aW1lU3RhdHVzRXZlbnROYW1lfS4ke2lkfWAsIGFwcFZlcnNpb25MaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihgJHtBcHBWZXJzaW9uQ29tcGxldGVFdmVudE5hbWV9LiR7aWR9YCwgYXBwVmVyc2lvbkxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKGAke0FwcFZlcnNpb25FcnJvckV2ZW50TmFtZX0uJHtpZH1gLCBhcHBWZXJzaW9uTGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoYCR7QXBwVmVyc2lvbkNvbXBsZXRlRXZlbnROYW1lfS4ke2lkfWAsIHJlbW92ZUFsbExpc3RlbmVycyk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcihgJHtBcHBWZXJzaW9uRXJyb3JFdmVudE5hbWV9LiR7aWR9YCwgcmVtb3ZlQWxsTGlzdGVuZXJzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgdGhpcy5vbihgJHtBcHBWZXJzaW9uUHJvZ3Jlc3NFdmVudE5hbWV9LiR7aWR9YCwgYXBwVmVyc2lvbkxpc3RlbmVyKSxcbiAgICAgICAgICAgICAgICB0aGlzLm9uKGAke1J1bnRpbWVTdGF0dXNFdmVudE5hbWV9LiR7aWR9YCwgYXBwVmVyc2lvbkxpc3RlbmVyKSxcbiAgICAgICAgICAgICAgICB0aGlzLm9uY2UoYCR7QXBwVmVyc2lvbkNvbXBsZXRlRXZlbnROYW1lfS4ke2lkfWAsIGFwcFZlcnNpb25MaXN0ZW5lciksXG4gICAgICAgICAgICAgICAgdGhpcy5vbmNlKGAke0FwcFZlcnNpb25FcnJvckV2ZW50TmFtZX0uJHtpZH1gLCBhcHBWZXJzaW9uTGlzdGVuZXIpLFxuICAgICAgICAgICAgICAgIHRoaXMub25jZShgJHtBcHBWZXJzaW9uQ29tcGxldGVFdmVudE5hbWV9LiR7aWR9YCwgcmVtb3ZlQWxsTGlzdGVuZXJzKSxcbiAgICAgICAgICAgICAgICB0aGlzLm9uY2UoYCR7QXBwVmVyc2lvbkVycm9yRXZlbnROYW1lfS4ke2lkfWAsIHJlbW92ZUFsbExpc3RlbmVycylcbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2xhdW5jaC1tYW5pZmVzdCcsIHtcbiAgICAgICAgICAgIG1hbmlmZXN0VXJsLFxuICAgICAgICAgICAgb3B0czogc2VuZE9wdHNcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXNwb25zZS5wYXlsb2FkLmRhdGEubWFuaWZlc3Q7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFF1ZXJ5IHBlcm1pc3Npb24gb2YgYSBzZWN1cmVkIGFwaSBpbiBjdXJyZW50IGNvbnRleHQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYXBpTmFtZSAtIFRoZSBmdWxsIG5hbWUgb2YgYSBzZWN1cmVkIEFQSS5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIElmIGEgZnVuY3Rpb24gaGFzIGEgc3RydWN0dXJlZCBwZXJtaXNzaW9uIHZhbHVlLCB0aGUgdmFsdWUgb2YgYGdyYW50ZWRgIHdpbGwgcmVmbGVjdCB0aGUgYGVuYWJsZWRgIGtleVxuICAgICAqIG9mIHRoZSBjYWxsJ3MgcGVybWlzc2lvbnMgbGl0ZXJhbC4gIEluIHRoaXMgY2FzZSwgKnBlcm1pc3Npb24gbWF5IHN0aWxsIGJlIGRlbmllZCB0byBhIGNhbGwqIHBlbmRpbmcgYXJndW1lbnRzIG9yIG90aGVyXG4gICAgICogcnVudGltZSBzdGF0ZS4gIFRoaXMgaXMgaW5kaWNhdGVkIHdpdGggYHN0YXRlOiB1bmF2YWlsYWJsZWAuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLlN5c3RlbS5xdWVyeVBlcm1pc3Npb25Gb3JDdXJyZW50Q29udGV4dCgnU3lzdGVtLmxhdW5jaEV4dGVybmFsUHJvY2VzcycpLnRoZW4ocmVzdWx0ID0+IGNvbnNvbGUubG9nKHJlc3VsdCkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKlxuICAgICAqIC8vVGhpcyByZXNwb25zZSBoYXMgdGhlIGZvbGxvd2luZyBzaGFwZTpcbiAgICAgKiB7XG4gICAgICogICAgcGVybWlzc2lvbjogJ1N5c3RlbS5sYXVuY2hFeHRlcm5hbFByb2Nlc3MnLCAvLyBhcGkgZnVsbCBuYW1lXG4gICAgICogICAgc3RhdGU6ICdncmFudGVkJywgLy8gc3RhdGUgb2YgcGVybWlzc2lvblxuICAgICAqICAgIGdyYW50ZWQ6IHRydWVcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgcXVlcnlQZXJtaXNzaW9uRm9yQ3VycmVudENvbnRleHQoYXBpTmFtZSkge1xuICAgICAgICBjb25zdCBpZGVudGl0eSA9IHsgdXVpZDogdGhpcy53aXJlLm1lLnV1aWQsIG5hbWU6IHRoaXMud2lyZS5tZS5uYW1lIH07XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3F1ZXJ5LXBlcm1pc3Npb24tZm9yLWN1cnJlbnQtY29udGV4dCcsIHtcbiAgICAgICAgICAgIGFwaU5hbWUsXG4gICAgICAgICAgICBpZGVudGl0eVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnBheWxvYWQuZGF0YTtcbiAgICB9XG4gICAgLy8gTm90IGRvY3VtZW50aW5nLCBpbnRlcm5hbCB1c2Ugb25seS5cbiAgICBhc3luYyBlbmFibGVOYXRpdmVXaW5kb3dJbnRlZ3JhdGlvblByb3ZpZGVyKHBlcm1pc3Npb25zKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2VuYWJsZS1uYXRpdmUtd2luZG93LWludGVncmF0aW9uLXByb3ZpZGVyJywgeyBwZXJtaXNzaW9ucyB9KTtcbiAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogKEludGVybmFsKSBSZWdpc3RlciB0aGUgdXNhZ2Ugb2YgYSBjb21wb25lbnQgd2l0aCBhIHBsYXRmb3JtXG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBPYmplY3Qgd2l0aCBkYXRhIGFuZCB0eXBlXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gcmVnaXN0ZXJVc2FnZSgpIHtcbiAgICAgKiAgICAgY29uc3QgYXBwID0gYXdhaXQgZmluLlN5c3RlbS5nZXRDdXJyZW50KCk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCBmaW4uU3lzdGVtLnJlZ2lzdGVyVXNhZ2Uoe1xuICAgICAqICAgICAgICAgdHlwZTogJ3dvcmtzcGFjZS1saWNlbnNpbmcnLFxuICAgICAqICAgICAgICAgLy8gZXhhbXBsZSB2YWx1ZXMgZm9yIHRoZSBmb2xsb3dpbmcgZGF0YSBvYmplY3RcbiAgICAgKiAgICAgICAgIGRhdGE6IHtcbiAgICAgKiAgICAgICAgICAgICBhcGlWZXJzaW9uOiAnMS4wJyxcbiAgICAgKiAgICAgICAgICAgICBjb21wb25lbnROYW1lOiAnaG9tZScsXG4gICAgICogICAgICAgICAgICAgY29tcG9uZW50VmVyc2lvbjogJzEuMCcsXG4gICAgICogICAgICAgICAgICAgYWxsb3dlZDogdHJ1ZSxcbiAgICAgKiAgICAgICAgICAgICByZWplY3Rpb25Db2RlOiAnJ1xuICAgICAqICAgICAgICAgfVxuICAgICAqICAgICB9KTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiByZWdpc3RlclVzYWdlKCkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU3VjY2Vzc2Z1bGx5IHJlZ2lzdGVyZWQgY29tcG9uZW50IGFwcGxpY2F0aW9uJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyByZWdpc3RlclVzYWdlKHsgZGF0YSwgdHlwZSB9KSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdyZWdpc3Rlci11c2FnZScsIHsgZGF0YSwgdHlwZSB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBhcnJheSB3aXRoIGFsbCBwcmludGVycyBvZiB0aGUgY2FsbGVyIGFuZCBub3QgYWxsIHRoZSBwcmludGVycyBvbiB0aGUgZGVza3RvcC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uU3lzdGVtLmdldFByaW50ZXJzKClcbiAgICAgKiAgICAgLnRoZW4oKHByaW50ZXJzKSA9PiB7XG4gICAgICogICAgICAgICBwcmludGVycy5mb3JFYWNoKChwcmludGVyKSA9PiB7XG4gICAgICogICAgICAgICAgICAgaWYgKHByaW50ZXIuaXNEZWZhdWx0KSB7XG4gICAgICogICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHByaW50ZXIpO1xuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgIH0pO1xuICAgICAqICAgICB9KVxuICAgICAqICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coZXJyKTtcbiAgICAgKiAgICAgfSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZ2V0UHJpbnRlcnMoKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3N5c3RlbS1nZXQtcHJpbnRlcnMnKTtcbiAgICAgICAgcmV0dXJuIHBheWxvYWQuZGF0YTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogVXBkYXRlcyBQcm9jZXNzIExvZ2dpbmcgdmFsdWVzOiBwZXJpb2RpYyBpbnRlcnZhbCBhbmQgb3V0bGllciBkZXRlY3Rpb24gZW50cmllcyBhbmQgaW50ZXJ2YWwuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgUHJvY2VzcyBMb2dnaW5nIHVwZGF0YWJsZSBvcHRpb25zLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgV2hlbiBlbmFibGluZyB2ZXJib3NlIG1vZGUsIGFkZGl0aW9uYWwgcHJvY2VzcyBpbmZvcm1hdGlvbiBpcyBsb2dnZWQgdG8gdGhlIGRlYnVnLmxvZzpcbiAgICAgKlxuICAgICAqIDEuIFBlcmlvZGljYWxseSBwcm9jZXNzIHVzYWdlIChtZW1vcnksIGNwdSwgZXRjKSB3aWxsIGJlIGxvZ2dlZCBmb3IgZWFjaCBQSUQgYWxvbmcgd2l0aCB0aGUgd2luZG93cywgdmlld3MgYW5kXG4gICAgICogaWZyYW1lcyB0aGF0IGJlbG9uZyB0byB0aGVtLiBUaGUgZGVmYXVsdCBpcyBldmVyeSAzMCBzZWNvbmRzLiBVcGRhdGFibGUgYnkgcGFzc2luZyB0aGUgaW50ZXJ2YWwgb3B0aW9uLlxuICAgICAqIDIuIFdoZW4gV2luZG93cyBhbmQgVmlld3MgYXJlIGNyZWF0ZWQgb3IgbmF2aWdhdGVkIHRoZSBQSUQgdGhleSBiZWxvbmcgdG8gYW5kIHRoZWlyIG9wdGlvbnMgd2lsbCBiZSBsb2dnZWQuXG4gICAgICogMy4gV2hlbiBXaW5kb3dzIGFuZCBWaWV3cyBhcmUgZGVzdHJveWVkIHRoZWlyIGxhc3Qga25vd24gcHJvY2VzcyB1c2FnZSB3aWxsIGJlIGxvZ2dlZC5cbiAgICAgKiA0LiBXaGVuZXZlciBhbiBvdXRsaWVyIG1lbW9yeSB1c2FnZSBpcyBkZXRlY3RlZCBpdCB3aWxsIGJlIGxvZ2dlZC4gQnkgZGVmYXVsdCwgb24gYW4gaW50ZXJ2YWwgb2YgNSBzZWNvbmRzIHdlIHdpbGxcbiAgICAgKiBjb2xsZWN0IHByb2Nlc3MgdXNhZ2UgZm9yIGFsbCBQSURzIGFuZCB3aGVuIDE0NCBzdWNoIGVudHJpZXMgYXJlIGNvbGxlY3RlZCwgd2Ugd2lsbCBzdGFydCBhbmFseXppbmcgdGhlIGRhdGEgZm9yIGFueVxuICAgICAqIHBvc3NpYmxlIG91dGxpZXJzIGluIHRoZSBmb2xsb3dpbmcgZW50cmllcy4gVGhlIGludGVydmFsIGFuZCBtYXhpbXVtIG51bWJlciBvZiBlbnRyaWVzIHN0b3JlZCBpbiB0aGUgcnVubmluZyBidWZmZXJcbiAgICAgKiBjYW4gYmUgdXBkYXRhYmxlIGJ5IHBhc3NpbmcgdGhlIG91dGxpZXJEZXRlY3Rpb24uaW50ZXJ2YWwgYW5kIG91dGxpZXJEZXRlY3Rpb24uZW50cmllcyBvcHRpb25zLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogYXdhaXQgZmluLlN5c3RlbS51cGRhdGVQcm9jZXNzTG9nZ2luZ09wdGlvbnMoe1xuICAgICAqICAgICBpbnRlcnZhbDogMTAsXG4gICAgICogICAgIG91dGxpZXJEZXRlY3Rpb246IHtcbiAgICAgKiAgICAgICAgIGludGVydmFsOiAxNSxcbiAgICAgKiAgICAgICAgIGVudHJpZXM6IDIwMFxuICAgICAqICAgICB9XG4gICAgICogfSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgdXBkYXRlUHJvY2Vzc0xvZ2dpbmdPcHRpb25zKG9wdGlvbnMpIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3N5c3RlbS11cGRhdGUtcHJvY2Vzcy1sb2dnaW5nLW9wdGlvbnMnLCB7IG9wdGlvbnMgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgZG9tYWluIHNldHRpbmdzIGZvciB0aGUgY3VycmVudCBhcHBsaWNhdGlvbi5cbiAgICAgKiBJbml0aWFsIHNldHRpbmdzIGFyZSBjb25maWd1cmVkIHdpdGggdGhlIGRlZmF1bHREb21haW5TZXR0aW5ncyBhcHBsaWNhdGlvbiBvcHRpb24gdmlhIG1hbmlmZXN0LlxuICAgICAqIERvbWFpbiBzZXR0aW5ncyBjYW4gYmUgb3ZlcndyaXR0ZW4gZHVyaW5nIHJ1bnRpbWUgd2l0aCBTeXN0ZW0uc2V0RG9tYWluU2V0dGluZ3MuXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IGRvbWFpblNldHRpbmdzID0gYXdhaXQgZmluLlN5c3RlbS5nZXREb21haW5TZXR0aW5ncygpO1xuICAgICAqIC8vIHtcbiAgICAgKiAvLyAgICAgXCJydWxlc1wiOiBbXG4gICAgICogLy8gICAgICAgICB7XG4gICAgICogLy8gICAgICAgICAgICAgXCJtYXRjaFwiOiBbXG4gICAgICogLy8gICAgICAgICAgICAgICAgIFwiaHR0cHM6Ly9vcGVuZmluLmNvXCJcbiAgICAgKiAvLyAgICAgICAgICAgICBdLFxuICAgICAqIC8vICAgICAgICAgICAgIFwib3B0aW9uc1wiOiB7XG4gICAgICogLy8gICAgICAgICAgICAgICAgIFwiZG93bmxvYWRTZXR0aW5nc1wiOiB7XG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICBcInJ1bGVzXCI6IFtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwibWF0Y2hcIjogW1xuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI8YWxsX3VybHM+XCJcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJiZWhhdmlvclwiOiBcInByb21wdFwiXG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAqIC8vICAgICAgICAgICAgICAgICB9XG4gICAgICogLy8gICAgICAgICAgICAgfVxuICAgICAqIC8vICAgICAgICAgfVxuICAgICAqIC8vICAgICBdXG4gICAgICogLy8gfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGdldERvbWFpblNldHRpbmdzKCkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgZGF0YSB9IH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWRvbWFpbi1zZXR0aW5ncycsIHRoaXMuaWRlbnRpdHkpO1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgZG9tYWluIHNldHRpbmdzIGZvciB0aGUgY3VycmVudCBhcHBsaWNhdGlvbi5cbiAgICAgKiBAcGFyYW0gZG9tYWluU2V0dGluZ3MgLSBkb21haW4gc2V0dGluZ3Mgb2JqZWN0XG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IGRvbWFpblNldHRpbmdzID0gYXdhaXQgZmluLlN5c3RlbS5nZXREb21haW5TZXR0aW5ncygpO1xuICAgICAqIC8vIHtcbiAgICAgKiAvLyAgICAgXCJydWxlc1wiOiBbXG4gICAgICogLy8gICAgICAgICB7XG4gICAgICogLy8gICAgICAgICAgICAgXCJtYXRjaFwiOiBbXG4gICAgICogLy8gICAgICAgICAgICAgICAgIFwiaHR0cHM6Ly9vcGVuZmluLmNvXCJcbiAgICAgKiAvLyAgICAgICAgICAgICBdLFxuICAgICAqIC8vICAgICAgICAgICAgIFwib3B0aW9uc1wiOiB7XG4gICAgICogLy8gICAgICAgICAgICAgICAgIFwiZG93bmxvYWRTZXR0aW5nc1wiOiB7XG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICBcInJ1bGVzXCI6IFtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwibWF0Y2hcIjogW1xuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCI8YWxsX3VybHM+XCJcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJiZWhhdmlvclwiOiBcInByb21wdFwiXG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAqIC8vICAgICAgICAgICAgICAgICB9XG4gICAgICogLy8gICAgICAgICAgICAgfVxuICAgICAqIC8vICAgICAgICAgfVxuICAgICAqIC8vICAgICBdXG4gICAgICogLy8gfVxuICAgICAqXG4gICAgICogLy8gVmFsaWQgcnVsZSBiZWhhdmlvcnMgYXJlICdwcm9tcHQnIGFuZCAnbm8tcHJvbXB0J1xuICAgICAqIGRvbWFpblNldHRpbmdzLnJ1bGVzWzBdLm9wdGlvbnMuZG93bmxvYWRTZXR0aW5ncy5ydWxlc1swXS5iZWhhdmlvciA9ICduby1wcm9tcHQnO1xuICAgICAqXG4gICAgICogYXdhaXQgZmluLlN5c3RlbS5zZXREb21haW5TZXR0aW5ncyhkb21haW5TZXR0aW5ncyk7XG4gICAgICpcbiAgICAgKiBjb25zdCBuZXdEb21haW5TZXR0aW5ncyA9IGF3YWl0IGZpbi5TeXN0ZW0uZ2V0RG9tYWluU2V0dGluZ3MoKTtcbiAgICAgKiAvLyB7XG4gICAgICogLy8gICAgIFwicnVsZXNcIjogW1xuICAgICAqIC8vICAgICAgICAge1xuICAgICAqIC8vICAgICAgICAgICAgIFwibWF0Y2hcIjogW1xuICAgICAqIC8vICAgICAgICAgICAgICAgICBcImh0dHBzOi8vb3BlbmZpbi5jb1wiXG4gICAgICogLy8gICAgICAgICAgICAgXSxcbiAgICAgKiAvLyAgICAgICAgICAgICBcIm9wdGlvbnNcIjoge1xuICAgICAqIC8vICAgICAgICAgICAgICAgICBcImRvd25sb2FkU2V0dGluZ3NcIjoge1xuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgXCJydWxlc1wiOiBbXG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIm1hdGNoXCI6IFtcbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiPGFsbF91cmxzPlwiXG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICogLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYmVoYXZpb3JcIjogXCJuby1wcm9tcHRcIlxuICAgICAqIC8vICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgICAgIF1cbiAgICAgKiAvLyAgICAgICAgICAgICAgICAgfVxuICAgICAqIC8vICAgICAgICAgICAgIH1cbiAgICAgKiAvLyAgICAgICAgIH1cbiAgICAgKiAvLyAgICAgXVxuICAgICAqIC8vIH1cbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBzZXREb21haW5TZXR0aW5ncyhkb21haW5TZXR0aW5ncykge1xuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc2V0LWRvbWFpbi1zZXR0aW5ncycsIHsgZG9tYWluU2V0dGluZ3MsIC4uLnRoaXMuaWRlbnRpdHkgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEF0dGVtcHRzIHRvIGluc3RhbGwgYW5kIGVuYWJsZSBleHRlbnNpb25zIGZvciB0aGUgc2VjdXJpdHkgcmVhbG0uICBVc2VycyBtYXkgd2FudCB0byBjYWxsIHRoaXMgZnVuY3Rpb24gaW4gcmVzcG9uc2VcbiAgICAgKiB0byBhbiBgZXh0ZW5zaW9ucy1pbnN0YWxsLWZhaWxlZGAgZXZlbnQuICBPbmx5IGV4dGVuc2lvbnMgYWxsb3dlZCBieSBldmVyeSBhcHBsaWNhdGlvbiBvbiB0aGUgY3VycmVudCBzZWN1cml0eSByZWFsbVxuICAgICAqIHdpbGwgYmUgaW5zdGFsbGVkL2VuYWJsZWQuXG4gICAgICovXG4gICAgYXN5bmMgcmVmcmVzaEV4dGVuc2lvbnMoKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3JlZnJlc2gtZXh0ZW5zaW9ucycpO1xuICAgICAgICByZXR1cm4gcGF5bG9hZC5kYXRhO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBjdXJyZW50bHktaW5zdGFsbGVkXG4gICAgICovXG4gICAgYXN5bmMgZ2V0SW5zdGFsbGVkRXh0ZW5zaW9ucygpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWluc3RhbGxlZC1leHRlbnNpb25zJyk7XG4gICAgICAgIHJldHVybiBwYXlsb2FkLmRhdGE7XG4gICAgfVxufVxuc3lzdGVtLlN5c3RlbSA9IFN5c3RlbTtcblxudmFyIGludGVyYXBwYnVzID0ge307XG5cbnZhciByZWZDb3VudGVyID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShyZWZDb3VudGVyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnJlZkNvdW50ZXIuUmVmQ291bnRlciA9IHZvaWQgMDtcbmNsYXNzIFJlZkNvdW50ZXIge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnRvcGljUmVmTWFwID0gbmV3IE1hcCgpO1xuICAgIH1cbiAgICAvLyByZXR1cm5zIHRoZSByZWYgY291bnQgYWZ0ZXIgaW5jcmVtZW50aW5nXG4gICAgaW5jUmVmQ291bnQoa2V5KSB7XG4gICAgICAgIGNvbnN0IHJlZkNvdW50ID0gdGhpcy50b3BpY1JlZk1hcC5nZXQoa2V5KTtcbiAgICAgICAgbGV0IHJldHVybkNvdW50O1xuICAgICAgICBpZiAoIXJlZkNvdW50KSB7XG4gICAgICAgICAgICB0aGlzLnRvcGljUmVmTWFwLnNldChrZXksIDEpO1xuICAgICAgICAgICAgcmV0dXJuQ291bnQgPSAxO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbmV3UmVmQ291bnQgPSByZWZDb3VudCArIDE7XG4gICAgICAgICAgICByZXR1cm5Db3VudCA9IG5ld1JlZkNvdW50O1xuICAgICAgICAgICAgdGhpcy50b3BpY1JlZk1hcC5zZXQoa2V5LCBuZXdSZWZDb3VudCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJldHVybkNvdW50O1xuICAgIH1cbiAgICAvLyByZXR1cm5zIHRoZSByZWYgY291bnQgYWZ0ZXIgZGVjcmVtZW50aW5nLCBvciAtMSBpZiB0aGUga2V5IGFscmVhZHkgaGFkIG5vIHJlZmVyZW5jZXNcbiAgICBkZWNSZWZDb3VudChrZXkpIHtcbiAgICAgICAgY29uc3QgcmVmQ291bnQgPSB0aGlzLnRvcGljUmVmTWFwLmdldChrZXkpO1xuICAgICAgICBsZXQgcmV0dXJuQ291bnQ7XG4gICAgICAgIGlmIChyZWZDb3VudCkge1xuICAgICAgICAgICAgY29uc3QgbmV3UmVmQ291bnQgPSByZWZDb3VudCAtIDE7XG4gICAgICAgICAgICB0aGlzLnRvcGljUmVmTWFwLnNldChrZXksIG5ld1JlZkNvdW50KTtcbiAgICAgICAgICAgIHJldHVybkNvdW50ID0gbmV3UmVmQ291bnQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm5Db3VudCA9IC0xO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXR1cm5Db3VudDtcbiAgICB9XG4gICAgLy8gRXhlY3V0ZSBmaXJzdEFjdGlvbiBpZiBpdCBpcyB0aGUgZmlyc3Qgc3VjaCByZWYsIGVsc2UgZXhlY3V0ZSBub25GaXJzdEFjdGlvbi5cbiAgICAvLyBJbiBlaXRoZXIgY2FzZSB0aGUgcmV0dXJuIHZhbHVlIGlzIHRoYXQgb2YgdGhlIGFjdGlvbiBleGVjdXRlZFxuICAgIGFjdE9uRmlyc3Qoa2V5LCBmaXJzdEFjdGlvbiwgbm9uRmlyc3RBY3Rpb24pIHtcbiAgICAgICAgY29uc3QgbnVtUmVmcyA9IHRoaXMuaW5jUmVmQ291bnQoa2V5KTtcbiAgICAgICAgY29uc3QgaXNGaXJzdFJlZiA9IG51bVJlZnMgPT09IDE7XG4gICAgICAgIHJldHVybiBpc0ZpcnN0UmVmID8gZmlyc3RBY3Rpb24oKSA6IG5vbkZpcnN0QWN0aW9uKCk7XG4gICAgfVxuICAgIC8vIEV4ZWN1dGUgbGFzdEFjdGlvbiBpZiBpdCBpcyB0aGUgZmlyc3Qgc3VjaCByZWYsIGVsc2UgZXhlY3V0ZSBub25MYXN0QWN0aW9uLlxuICAgIC8vIEluIGVpdGhlciBjYXNlIHRoZSByZXR1cm4gdmFsdWUgaXMgdGhhdCBvZiB0aGUgYWN0aW9uIGV4ZWN1dGVkXG4gICAgYWN0T25MYXN0KGtleSwgbGFzdEFjdGlvbiwgbm9uTGFzdEFjdGlvbikge1xuICAgICAgICBjb25zdCBudW1SZWZzID0gdGhpcy5kZWNSZWZDb3VudChrZXkpO1xuICAgICAgICBjb25zdCBpc0xhc3RSZWYgPSBudW1SZWZzID09PSAwO1xuICAgICAgICByZXR1cm4gaXNMYXN0UmVmID8gbGFzdEFjdGlvbigpIDogbm9uTGFzdEFjdGlvbigpO1xuICAgIH1cbn1cbnJlZkNvdW50ZXIuUmVmQ291bnRlciA9IFJlZkNvdW50ZXI7XG5cbnZhciBjaGFubmVsJDEgPSB7fTtcblxudmFyIGNsaWVudCA9IHt9O1xuXG52YXIgY2hhbm5lbCA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoY2hhbm5lbCwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jaGFubmVsLkNoYW5uZWxCYXNlID0gY2hhbm5lbC5Qcm90ZWN0ZWRJdGVtcyA9IHZvaWQgMDtcbmNvbnN0IHJlc3VsdE9yUGF5bG9hZCA9IChmdW5jKSA9PiBhc3luYyAodG9waWMsIHBheWxvYWQsIHNlbmRlcklkZW50aXR5KSA9PiB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgZnVuYyh0b3BpYywgcGF5bG9hZCwgc2VuZGVySWRlbnRpdHkpO1xuICAgIHJldHVybiByZXMgPT09IHVuZGVmaW5lZCA/IHBheWxvYWQgOiByZXM7XG59O1xuY2xhc3MgUHJvdGVjdGVkSXRlbXMge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11c2VsZXNzLWNvbnN0cnVjdG9yXG4gICAgY29uc3RydWN0b3IocHJvdmlkZXJJZGVudGl0eSwgY2xvc2UpIHtcbiAgICAgICAgdGhpcy5wcm92aWRlcklkZW50aXR5ID0gcHJvdmlkZXJJZGVudGl0eTtcbiAgICAgICAgdGhpcy5jbG9zZSA9IGNsb3NlO1xuICAgIH1cbn1cbmNoYW5uZWwuUHJvdGVjdGVkSXRlbXMgPSBQcm90ZWN0ZWRJdGVtcztcbmNsYXNzIENoYW5uZWxCYXNlIHtcbiAgICBzdGF0aWMgZGVmYXVsdEFjdGlvbih0b3BpYykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGFjdGlvbiByZWdpc3RlcmVkIGF0IHRhcmdldCBmb3IgJHt0b3BpY31gKTtcbiAgICB9XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucyA9IG5ldyBNYXAoKTtcbiAgICB9XG4gICAgYXN5bmMgcHJvY2Vzc0FjdGlvbih0b3BpYywgcGF5bG9hZCwgc2VuZGVySWRlbnRpdHkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IG1haW5BY3Rpb24gPSB0aGlzLnN1YnNjcmlwdGlvbnMuaGFzKHRvcGljKVxuICAgICAgICAgICAgICAgID8gdGhpcy5zdWJzY3JpcHRpb25zLmdldCh0b3BpYylcbiAgICAgICAgICAgICAgICA6IChjdXJyZW50UGF5bG9hZCwgaWQpID0+ICh0aGlzLmRlZmF1bHRBY3Rpb24gPz8gQ2hhbm5lbEJhc2UuZGVmYXVsdEFjdGlvbikodG9waWMsIGN1cnJlbnRQYXlsb2FkLCBpZCk7XG4gICAgICAgICAgICBjb25zdCBwcmVBY3Rpb25Qcm9jZXNzZWQgPSB0aGlzLnByZUFjdGlvbiA/IGF3YWl0IHRoaXMucHJlQWN0aW9uKHRvcGljLCBwYXlsb2FkLCBzZW5kZXJJZGVudGl0eSkgOiBwYXlsb2FkO1xuICAgICAgICAgICAgY29uc3QgYWN0aW9uUHJvY2Vzc2VkID0gYXdhaXQgbWFpbkFjdGlvbihwcmVBY3Rpb25Qcm9jZXNzZWQsIHNlbmRlcklkZW50aXR5KTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnBvc3RBY3Rpb24gPyBhd2FpdCB0aGlzLnBvc3RBY3Rpb24odG9waWMsIGFjdGlvblByb2Nlc3NlZCwgc2VuZGVySWRlbnRpdHkpIDogYWN0aW9uUHJvY2Vzc2VkO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5lcnJvck1pZGRsZXdhcmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lcnJvck1pZGRsZXdhcmUodG9waWMsIGUsIHNlbmRlcklkZW50aXR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgbWlkZGxld2FyZSB0aGF0IGZpcmVzIGJlZm9yZSB0aGUgYWN0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZ1bmNcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBDaGFubmVsIFByb3ZpZGVyOlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBwcm92aWRlciA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY3JlYXRlKCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIHByb3ZpZGVyLnJlZ2lzdGVyKCdwcm92aWRlci1hY3Rpb24nLCAocGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKHBheWxvYWQsIGlkZW50aXR5KTtcbiAgICAgKiAgICAgICAgIHJldHVybiB7XG4gICAgICogICAgICAgICAgICAgZWNobzogcGF5bG9hZFxuICAgICAqICAgICAgICAgfTtcbiAgICAgKiAgICAgfSk7XG4gICAgICpcbiAgICAgKiAgICAgcHJvdmlkZXIuYmVmb3JlQWN0aW9uKChhY3Rpb24sIHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICAvL1RoZSBwYXlsb2FkIGNhbiBiZSBhbHRlcmVkIGhlcmUgYmVmb3JlIGhhbmRsaW5nIHRoZSBhY3Rpb24uXG4gICAgICogICAgICAgICBwYXlsb2FkLnJlY2VpdmVkID0gRGF0ZS5ub3coKTtcbiAgICAgKiAgICAgICAgIHJldHVybiBwYXlsb2FkO1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBDaGFubmVsIENsaWVudDpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGNsaWVudC5yZWdpc3RlcignY2xpZW50LWFjdGlvbicsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2cocGF5bG9hZCwgaWRlbnRpdHkpO1xuICAgICAqICAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgICBlY2hvOiBwYXlsb2FkXG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqICAgICBjbGllbnQuYmVmb3JlQWN0aW9uKChhY3Rpb24sIHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICAvL1RoZSBwYXlsb2FkIGNhbiBiZSBhbHRlcmVkIGhlcmUgYmVmb3JlIGhhbmRsaW5nIHRoZSBhY3Rpb24uXG4gICAgICogICAgICAgICBwYXlsb2FkLnJlY2VpdmVkID0gRGF0ZS5ub3coKTtcbiAgICAgKiAgICAgICAgIHJldHVybiBwYXlsb2FkO1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqICAgICBjb25zdCBwcm92aWRlclJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdwcm92aWRlci1hY3Rpb24nLCB7IG1lc3NhZ2U6ICdIZWxsbyBGcm9tIHRoZSBjbGllbnQnIH0pO1xuICAgICAqICAgICBjb25zb2xlLmxvZyhwcm92aWRlclJlc3BvbnNlKTtcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGJlZm9yZUFjdGlvbihmdW5jKSB7XG4gICAgICAgIGlmICh0aGlzLnByZUFjdGlvbikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBbHJlYWR5IHJlZ2lzdGVyZWQgYmVmb3JlQWN0aW9uIG1pZGRsZXdhcmUnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnByZUFjdGlvbiA9IHJlc3VsdE9yUGF5bG9hZChmdW5jKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYW4gZXJyb3IgaGFuZGxlci4gVGhpcyBpcyBjYWxsZWQgYmVmb3JlIHJlc3BvbmRpbmcgb24gYW55IGVycm9yLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZ1bmNcbiAgICAgKlxuICAgICAqIENoYW5uZWwgUHJvdmlkZXI6XG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgcHJvdmlkZXIucmVnaXN0ZXIoJ3Byb3ZpZGVyLWFjdGlvbicsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2cocGF5bG9hZCk7XG4gICAgICogICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FjdGlvbiBlcnJvcicpO1xuICAgICAqICAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgICBlY2hvOiBwYXlsb2FkXG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqICAgICBwcm92aWRlci5vbkVycm9yKChhY3Rpb24sIGVycm9yLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ3VuY2F1Z2h0IEV4Y2VwdGlvbiBpbiBhY3Rpb246JywgYWN0aW9uKTtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBDaGFubmVsIENsaWVudDpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGNsaWVudC5yZWdpc3RlcignY2xpZW50LWFjdGlvbicsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2cocGF5bG9hZCk7XG4gICAgICogICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FjdGlvbiBlcnJvcicpO1xuICAgICAqICAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgICBlY2hvOiBwYXlsb2FkXG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqICAgICBjbGllbnQub25FcnJvcigoYWN0aW9uLCBlcnJvciwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCd1bmNhdWdodCBFeGNlcHRpb24gaW4gYWN0aW9uOicsIGFjdGlvbik7XG4gICAgICogICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgKiAgICAgfSk7XG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBvbkVycm9yKGZ1bmMpIHtcbiAgICAgICAgaWYgKHRoaXMuZXJyb3JNaWRkbGV3YXJlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FscmVhZHkgcmVnaXN0ZXJlZCBlcnJvciBtaWRkbGV3YXJlJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lcnJvck1pZGRsZXdhcmUgPSBmdW5jO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBtaWRkbGV3YXJlIHRoYXQgZmlyZXMgYWZ0ZXIgdGhlIGFjdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBmdW5jXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBJZiB0aGUgYWN0aW9uIGRvZXMgbm90IHJldHVybiB0aGUgcGF5bG9hZCwgdGhlbiB0aGUgYWZ0ZXJBY3Rpb24gd2lsbCBub3QgaGF2ZSBhY2Nlc3MgdG8gdGhlIHBheWxvYWQgb2JqZWN0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIENoYW5uZWwgUHJvdmlkZXI6XG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgcHJvdmlkZXIucmVnaXN0ZXIoJ3Byb3ZpZGVyLWFjdGlvbicsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgICBlY2hvOiBwYXlsb2FkXG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCBwcm92aWRlci5hZnRlckFjdGlvbigoYWN0aW9uLCBwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgLy90aGUgcGF5bG9hZCBjYW4gYmUgYWx0ZXJlZCBoZXJlIGFmdGVyIGhhbmRsaW5nIHRoZSBhY3Rpb24gYnV0IGJlZm9yZSBzZW5kaW5nIGFuIGFja25vd2xlZGdlbWVudC5cbiAgICAgKiAgICAgICAgIHBheWxvYWQuc2VudCA9IGRhdGUubm93KCk7XG4gICAgICogICAgICAgICByZXR1cm4gcGF5bG9hZDtcbiAgICAgKiAgICAgfSk7XG4gICAgICpcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQ2hhbm5lbCBDbGllbnQ6XG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY29ubmVjdCgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCBjbGllbnQucmVnaXN0ZXIoJ2NsaWVudC1hY3Rpb24nLCAocGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgIHJldHVybiB7XG4gICAgICogICAgICAgICAgICAgZWNobzogcGF5bG9hZFxuICAgICAqICAgICAgICAgfTtcbiAgICAgKiAgICAgfSk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgY2xpZW50LmFmdGVyQWN0aW9uKChhY3Rpb24sIHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICAvL3RoZSBwYXlsb2FkIGNhbiBiZSBhbHRlcmVkIGhlcmUgYWZ0ZXIgaGFuZGxpbmcgdGhlIGFjdGlvbiBidXQgYmVmb3JlIHNlbmRpbmcgYW4gYWNrbm93bGVkZ2VtZW50LlxuICAgICAqICAgICAgICAgcGF5bG9hZC5zZW50ID0gZGF0ZS5ub3coKTtcbiAgICAgKiAgICAgICAgIHJldHVybiBwYXlsb2FkO1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYWZ0ZXJBY3Rpb24oZnVuYykge1xuICAgICAgICBpZiAodGhpcy5wb3N0QWN0aW9uKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FscmVhZHkgcmVnaXN0ZXJlZCBhZnRlckFjdGlvbiBtaWRkbGV3YXJlJyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5wb3N0QWN0aW9uID0gcmVzdWx0T3JQYXlsb2FkKGZ1bmMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYW4gYWN0aW9uIGJ5IGFjdGlvbiBuYW1lLlxuICAgICAqXG4gICAgICogQHBhcmFtIGFjdGlvblxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBwcm92aWRlciA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY3JlYXRlKCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHByb3ZpZGVyLnJlZ2lzdGVyKCdwcm92aWRlci1hY3Rpb24nLCAocGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKHBheWxvYWQpO1xuICAgICAqICAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgICBlY2hvOiBwYXlsb2FkXG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCBwcm92aWRlci5yZW1vdmUoJ3Byb3ZpZGVyLWFjdGlvbicpO1xuICAgICAqXG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICByZW1vdmUoYWN0aW9uKSB7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5kZWxldGUoYWN0aW9uKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJzIGEgZGVmYXVsdCBhY3Rpb24uIFRoaXMgaXMgdXNlZCBhbnkgdGltZSBhbiBhY3Rpb24gdGhhdCBoYXMgbm90IGJlZW4gcmVnaXN0ZXJlZCBpcyBpbnZva2VkLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIENoYW5uZWwgUHJvdmlkZXI6XG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgcHJvdmlkZXIuc2V0RGVmYXVsdEFjdGlvbigoYWN0aW9uLCBwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coYENsaWVudCB3aXRoIGlkZW50aXR5ICR7SlNPTi5zdHJpbmdpZnkoaWRlbnRpdHkpfSBoYXMgYXR0ZW1wdGVkIHRvIGRpc3BhdGNoIHVucmVnaXN0ZXJlZCBhY3Rpb246ICR7YWN0aW9ufS5gKTtcbiAgICAgKlxuICAgICAqICAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgICBlY2hvOiBwYXlsb2FkXG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBDaGFubmVsIENsaWVudDpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IGNsaWVudC5zZXREZWZhdWx0QWN0aW9uKChhY3Rpb24sIHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgICBjb25zb2xlLmxvZyhgUHJvdmlkZXIgd2l0aCBpZGVudGl0eSAke0pTT04uc3RyaW5naWZ5KGlkZW50aXR5KX0gaGFzIGF0dGVtcHRlZCB0byBkaXNwYXRjaCB1bnJlZ2lzdGVyZWQgYWN0aW9uOiAke2FjdGlvbn0uYCk7XG4gICAgICpcbiAgICAgKiAgICAgICAgIHJldHVybiB7XG4gICAgICogICAgICAgICAgICAgZWNobzogcGF5bG9hZFxuICAgICAqICAgICAgICAgfTtcbiAgICAgKiAgICAgfSk7XG4gICAgICpcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqIEBwYXJhbSBmdW5jXG4gICAgICovXG4gICAgc2V0RGVmYXVsdEFjdGlvbihmdW5jKSB7XG4gICAgICAgIGlmICh0aGlzLmRlZmF1bHRBY3Rpb24pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZGVmYXVsdCBhY3Rpb24gY2FuIG9ubHkgYmUgc2V0IG9uY2UnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZGVmYXVsdEFjdGlvbiA9IGZ1bmM7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYW4gYWN0aW9uIHRvIGJlIGNhbGxlZCBieSBkaXNwYXRjaGluZyBmcm9tIGFueSBjaGFubmVsQ2xpZW50IG9yIGNoYW5uZWxQcm92aWRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0b3BpY1xuICAgICAqIEBwYXJhbSBsaXN0ZW5lclxuICAgICAqXG4gICAgICogQHJlbWFya3MgVGhlIHJldHVybiB2YWx1ZSB3aWxsIGJlIHNlbnQgYmFjayBhcyBhbiBhY2tub3dsZWRnZW1lbnQgdG8gdGhlIG9yaWdpbmFsIGNhbGxlci4gWW91IGNhbiB0aHJvdyBhblxuICAgICAqIGVycm9yIHRvIHNlbmQgYSBuZWdhdGl2ZS1hY2tub3dsZWRnZW1lbnQgYW5kIHRoZSBlcnJvciB3aWxsIHJlamVjdCB0aGUgcHJvbWlzZSByZXR1cm5lZCB0byB0aGUgc2VuZGVyIGJ5IHRoZVxuICAgICAqIGRpc3BhdGNoIGNhbGwuICBPbmNlIGEgbGlzdGVuZXIgaXMgcmVnaXN0ZXJlZCBmb3IgYSBwYXJ0aWN1bGFyIGFjdGlvbiwgaXQgc3RheXMgaW4gcGxhY2UgcmVjZWl2aW5nIGFuZCByZXNwb25kaW5nXG4gICAgICogdG8gaW5jb21pbmcgbWVzc2FnZXMgdW50aWwgaXQgaXMgcmVtb3ZlZC4gIFRoaXMgbWVzc2FnaW5nIG1lY2hhbmlzbSB3b3JrcyBleGFjdGx5IHRoZSBzYW1lIHdoZW4gbWVzc2FnZXMgYXJlXG4gICAgICogZGlzcGF0Y2hlZCBmcm9tIHRoZSBwcm92aWRlciB0byBhIGNsaWVudC4gIEhvd2V2ZXIsIHRoZSBwcm92aWRlciBoYXMgYW4gYWRkaXRpb25hbCBwdWJsaXNoIG1ldGhvZCB0aGF0IHNlbmRzIG1lc3NhZ2VzXG4gICAgICogdG8gYWxsIGNvbm5lY3RlZCBjbGllbnRzLlxuICAgICAqXG4gICAgICogQmVjYXVzZSBtdWx0aXBsZSBjbGllbnRzIGNhbiBzaGFyZSB0aGUgc2FtZSBgbmFtZWAgYW5kIGB1dWlkYCwgaW4gb3JkZXIgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiBpbmRpdmlkdWFsIGNsaWVudHMsXG4gICAgICogdGhlIGBpZGVudGl0eWAgYXJndW1lbnQgaW4gYSBwcm92aWRlcidzIHJlZ2lzdGVyZWQgYWN0aW9uIGNhbGxiYWNrIGNvbnRhaW5zIGFuIGBlbmRwb2ludElkYCBwcm9wZXJ0eS4gV2hlbiBkaXNwYXRjaGluZ1xuICAgICAqIGZyb20gYSBwcm92aWRlciB0byBhIGNsaWVudCwgdGhlIGBlbmRwb2ludElkYCBwcm9wZXJ0eSBtdXN0IGJlIHByb3ZpZGVkIGluIG9yZGVyIHRvIHNlbmQgYW4gYWN0aW9uIHRvIGEgc3BlY2lmaWMgY2xpZW50LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIENoYW5uZWwgUHJvdmlkZXI6XG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgcHJvdmlkZXIucmVnaXN0ZXIoJ3Byb3ZpZGVyLWFjdGlvbicsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICBjb25zb2xlLmxvZygnQWN0aW9uIGRpc3BhdGNoZWQgYnkgY2xpZW50OiAnLCBpZGVudGl0eSk7XG4gICAgICogICAgICAgIGNvbnNvbGUubG9nKCdQYXlsb2FkIHNlbnQgaW4gZGlzcGF0Y2g6ICcsIHBheWxvYWQpO1xuICAgICAqXG4gICAgICogICAgICAgIHJldHVybiB7IGVjaG86IHBheWxvYWQgfTtcbiAgICAgKiAgICB9KTtcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQ2hhbm5lbCBDbGllbnQ6XG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY29ubmVjdCgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgICBhd2FpdCBjbGllbnQucmVnaXN0ZXIoJ2NsaWVudC1hY3Rpb24nLCAocGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgY29uc29sZS5sb2coJ0FjdGlvbiBkaXNwYXRjaGVkIGJ5IGNsaWVudDogJywgaWRlbnRpdHkpO1xuICAgICAqICAgICAgICBjb25zb2xlLmxvZygnUGF5bG9hZCBzZW50IGluIGRpc3BhdGNoOiAnLCBwYXlsb2FkKTtcbiAgICAgKlxuICAgICAqICAgICAgICByZXR1cm4geyBlY2hvOiBwYXlsb2FkIH07XG4gICAgICogICAgfSk7XG4gICAgICogfSkoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICByZWdpc3Rlcih0b3BpYywgbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKHRoaXMuc3Vic2NyaXB0aW9ucy5oYXModG9waWMpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFN1YnNjcmlwdGlvbiBhbHJlYWR5IHJlZ2lzdGVyZWQgZm9yIGFjdGlvbjogJHt0b3BpY30uIFVuc3Vic2NyaWJlIGJlZm9yZSBhZGRpbmcgbmV3IHN1YnNjcmlwdGlvbmApO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnNldCh0b3BpYywgbGlzdGVuZXIpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG59XG5jaGFubmVsLkNoYW5uZWxCYXNlID0gQ2hhbm5lbEJhc2U7XG5cbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGMgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JGEgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XG59O1xudmFyIF9DaGFubmVsQ2xpZW50X3Byb3RlY3RlZE9iaiwgX0NoYW5uZWxDbGllbnRfc3RyYXRlZ3ksIF9DaGFubmVsQ2xpZW50X2Nsb3NlO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGNsaWVudCwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jbGllbnQuQ2hhbm5lbENsaWVudCA9IHZvaWQgMDtcbmNvbnN0IGNoYW5uZWxfMSQxID0gY2hhbm5lbDtcbmNvbnN0IGNoYW5uZWxDbGllbnRzQnlFbmRwb2ludElkID0gbmV3IE1hcCgpO1xuLyoqXG4gKiBJbnN0YW5jZSBjcmVhdGVkIHRvIGVuYWJsZSB1c2Ugb2YgYSBjaGFubmVsIGFzIGEgY2xpZW50LiAgQWxsb3dzIGZvciBjb21tdW5pY2F0aW9uIHdpdGggdGhlXG4gKiB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyIENoYW5uZWxQcm92aWRlcn0gYnkgaW52b2tpbmcgYW4gYWN0aW9uIG9uIHRoZVxuICogcHJvdmlkZXIgdmlhIHtAbGluayBDaGFubmVsQ2xpZW50I2Rpc3BhdGNoIGRpc3BhdGNofSBhbmQgdG8gbGlzdGVuIGZvciBjb21tdW5pY2F0aW9uXG4gKiBmcm9tIHRoZSBwcm92aWRlciBieSByZWdpc3RlcmluZyBhbiBhY3Rpb24gdmlhIHtAbGluayBDaGFubmVsQ2xpZW50I3JlZ2lzdGVyIHJlZ2lzdGVyfS5cbiAqXG4gKiAjIyMgU3luY2hyb25vdXMgTWV0aG9kczpcbiAqICAqIHtAbGluayBDaGFubmVsQ2xpZW50I29uRGlzY29ubmVjdGlvbiBvbkRpc2Nvbm5lY3Rpb24obGlzdGVuZXIpfVxuICogICoge0BsaW5rIENoYW5uZWxDbGllbnQjcmVnaXN0ZXIgcmVnaXN0ZXIoYWN0aW9uLCBsaXN0ZW5lcil9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbENsaWVudCNyZW1vdmUgcmVtb3ZlKGFjdGlvbil9XG4gKlxuICogIyMjIEFzeW5jaHJvbm91cyBNZXRob2RzOlxuICogICoge0BsaW5rIENoYW5uZWxDbGllbnQjZGlzY29ubmVjdCBkaXNjb25uZWN0KCl9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbENsaWVudCNkaXNwYXRjaCBkaXNwYXRjaChhY3Rpb24sIHBheWxvYWQpfVxuICpcbiAqICMjIyBNaWRkbGV3YXJlOlxuICogTWlkZGxld2FyZSBmdW5jdGlvbnMgcmVjZWl2ZSB0aGUgZm9sbG93aW5nIGFyZ3VtZW50czogKGFjdGlvbiwgcGF5bG9hZCwgc2VuZGVySWQpLlxuICogVGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgbWlkZGxld2FyZSBmdW5jdGlvbiB3aWxsIGJlIHBhc3NlZCBvbiBhcyB0aGUgcGF5bG9hZCBmcm9tIGJlZm9yZUFjdGlvbiwgdG8gdGhlIGFjdGlvbiBsaXN0ZW5lciwgdG8gYWZ0ZXJBY3Rpb25cbiAqIHVubGVzcyBpdCBpcyB1bmRlZmluZWQsIGluIHdoaWNoIGNhc2UgdGhlIG9yaWdpbmFsIHBheWxvYWQgaXMgdXNlZC4gIE1pZGRsZXdhcmUgY2FuIGJlIHVzZWQgZm9yIHNpZGUgZWZmZWN0cy5cbiAqICAqIHtAbGluayBDaGFubmVsQ2xpZW50I3NldERlZmF1bHRBY3Rpb24gc2V0RGVmYXVsdEFjdGlvbihtaWRkbGV3YXJlKX1cbiAqICAqIHtAbGluayBDaGFubmVsQ2xpZW50I29uRXJyb3Igb25FcnJvcihtaWRkbGV3YXJlKX1cbiAqICAqIHtAbGluayBDaGFubmVsQ2xpZW50I2JlZm9yZUFjdGlvbiBiZWZvcmVBY3Rpb24obWlkZGxld2FyZSl9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbENsaWVudCNhZnRlckFjdGlvbiBhZnRlckFjdGlvbihtaWRkbGV3YXJlKX1cbiAqL1xuY2xhc3MgQ2hhbm5lbENsaWVudCBleHRlbmRzIGNoYW5uZWxfMSQxLkNoYW5uZWxCYXNlIHtcbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBzdGF0aWMgY2xvc2VDaGFubmVsQnlFbmRwb2ludElkKGlkKSB7XG4gICAgICAgIGNvbnN0IGNoYW5uZWwgPSBjaGFubmVsQ2xpZW50c0J5RW5kcG9pbnRJZC5nZXQoaWQpO1xuICAgICAgICBpZiAoY2hhbm5lbCkge1xuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRjKGNoYW5uZWwsIF9DaGFubmVsQ2xpZW50X2Nsb3NlLCBcImZcIikuY2FsbChjaGFubmVsKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKiBjbG9zZXMgdGhlIGNvcnJlc3BvbmRpbmcgY2hhbm5lbCBhbmQgaW52b2tlcyB0aGUgZGlzY29ubmVjdCBsaXN0ZW5lciBpZiBhbiBldmVudCBwYXlsb2FkIGlzIHBhc3NlZC5cbiAgICAgKi9cbiAgICBzdGF0aWMgaGFuZGxlUHJvdmlkZXJEaXNjb25uZWN0KGV2ZW50UGF5bG9hZCkge1xuICAgICAgICBmb3IgKGNvbnN0IGNoYW5uZWxDbGllbnQgb2YgY2hhbm5lbENsaWVudHNCeUVuZHBvaW50SWQudmFsdWVzKCkpIHtcbiAgICAgICAgICAgIGlmIChjaGFubmVsQ2xpZW50LnByb3ZpZGVySWRlbnRpdHkuY2hhbm5lbElkID09PSBldmVudFBheWxvYWQuY2hhbm5lbElkKSB7XG4gICAgICAgICAgICAgICAgY2hhbm5lbENsaWVudC5kaXNjb25uZWN0TGlzdGVuZXIoZXZlbnRQYXlsb2FkKTtcbiAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGMoY2hhbm5lbENsaWVudCwgX0NoYW5uZWxDbGllbnRfY2xvc2UsIFwiZlwiKS5jYWxsKGNoYW5uZWxDbGllbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHJvdXRpbmdJbmZvLCBjbG9zZSwgc3RyYXRlZ3kpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgX0NoYW5uZWxDbGllbnRfcHJvdGVjdGVkT2JqLnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICBfQ2hhbm5lbENsaWVudF9zdHJhdGVneS5zZXQodGhpcywgdm9pZCAwKTtcbiAgICAgICAgLy8gbmVlZHMgdG8gYmUgYm91bmQ7XG4gICAgICAgIHRoaXMucHJvY2Vzc0FjdGlvbiA9IChhY3Rpb24sIHBheWxvYWQsIHNlbmRlcklkZW50aXR5KSA9PiBzdXBlci5wcm9jZXNzQWN0aW9uKGFjdGlvbiwgcGF5bG9hZCwgc2VuZGVySWRlbnRpdHkpO1xuICAgICAgICBfQ2hhbm5lbENsaWVudF9jbG9zZS5zZXQodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgY2hhbm5lbENsaWVudHNCeUVuZHBvaW50SWQuZGVsZXRlKHRoaXMuZW5kcG9pbnRJZCk7XG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGModGhpcywgX0NoYW5uZWxDbGllbnRfc3RyYXRlZ3ksIFwiZlwiKS5jbG9zZSgpO1xuICAgICAgICB9KTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCRhKHRoaXMsIF9DaGFubmVsQ2xpZW50X3Byb3RlY3RlZE9iaiwgbmV3IGNoYW5uZWxfMSQxLlByb3RlY3RlZEl0ZW1zKHJvdXRpbmdJbmZvLCBjbG9zZSksIFwiZlwiKTtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0TGlzdGVuZXIgPSAoKSA9PiB1bmRlZmluZWQ7XG4gICAgICAgIHRoaXMuZW5kcG9pbnRJZCA9IHJvdXRpbmdJbmZvLmVuZHBvaW50SWQ7XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkYSh0aGlzLCBfQ2hhbm5lbENsaWVudF9zdHJhdGVneSwgc3RyYXRlZ3ksIFwiZlwiKTtcbiAgICAgICAgY2hhbm5lbENsaWVudHNCeUVuZHBvaW50SWQuc2V0KHRoaXMuZW5kcG9pbnRJZCwgdGhpcyk7XG4gICAgICAgIHN0cmF0ZWd5LnJlY2VpdmUodGhpcy5wcm9jZXNzQWN0aW9uKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogYSByZWFkLW9ubHkgcHJvdmlkZXIgaWRlbnRpdHlcbiAgICAgKi9cbiAgICBnZXQgcHJvdmlkZXJJZGVudGl0eSgpIHtcbiAgICAgICAgY29uc3QgcHJvdGVjdGVkT2JqID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCRjKHRoaXMsIF9DaGFubmVsQ2xpZW50X3Byb3RlY3RlZE9iaiwgXCJmXCIpO1xuICAgICAgICByZXR1cm4gcHJvdGVjdGVkT2JqLnByb3ZpZGVySWRlbnRpdHk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERpc3BhdGNoIHRoZSBnaXZlbiBhY3Rpb24gdG8gdGhlIGNoYW5uZWwgcHJvdmlkZXIuIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgcmVzcG9uc2UgZnJvbVxuICAgICAqIHRoZSBwcm92aWRlciBmb3IgdGhhdCBhY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYWN0aW9uXG4gICAgICogQHBhcmFtIHBheWxvYWRcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IGNsaWVudC5yZWdpc3RlcignY2xpZW50LWFjdGlvbicsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2cocGF5bG9hZCwgaWRlbnRpdHkpO1xuICAgICAqICAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgICBlY2hvOiBwYXlsb2FkXG4gICAgICogICAgICAgICB9O1xuICAgICAqICAgICB9KTtcbiAgICAgKlxuICAgICAqICAgICBjb25zdCBwcm92aWRlclJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdwcm92aWRlci1hY3Rpb24nLCB7IG1lc3NhZ2U6ICdIZWxsbyBGcm9tIHRoZSBjbGllbnQnfSk7XG4gICAgICogICAgIGNvbnNvbGUubG9nKHByb3ZpZGVyUmVzcG9uc2UpO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZGlzcGF0Y2goYWN0aW9uLCBwYXlsb2FkKSB7XG4gICAgICAgIGlmIChfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGModGhpcywgX0NoYW5uZWxDbGllbnRfc3RyYXRlZ3ksIFwiZlwiKS5pc0VuZHBvaW50Q29ubmVjdGVkKHRoaXMucHJvdmlkZXJJZGVudGl0eS5jaGFubmVsSWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gX19jbGFzc1ByaXZhdGVGaWVsZEdldCRjKHRoaXMsIF9DaGFubmVsQ2xpZW50X3N0cmF0ZWd5LCBcImZcIikuc2VuZCh0aGlzLnByb3ZpZGVySWRlbnRpdHkuY2hhbm5lbElkLCBhY3Rpb24sIHBheWxvYWQpO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGNsaWVudCB5b3UgYXJlIHRyeWluZyB0byBkaXNwYXRjaCBmcm9tIGlzIGRpc2Nvbm5lY3RlZCBmcm9tIHRoZSB0YXJnZXQgcHJvdmlkZXIuJyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIGEgbGlzdGVuZXIgdGhhdCBpcyBjYWxsZWQgb24gcHJvdmlkZXIgZGlzY29ubmVjdGlvbi4gSXQgaXMgcGFzc2VkIHRoZSBkaXNjb25uZWN0aW9uIGV2ZW50IG9mIHRoZVxuICAgICAqIGRpc2Nvbm5lY3RpbmcgcHJvdmlkZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbGlzdGVuZXJcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IGNsaWVudC5vbkRpc2Nvbm5lY3Rpb24oZXZ0ID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKCdQcm92aWRlciBkaXNjb25uZWN0ZWQnLCBgdXVpZDogJHtldnQudXVpZH0sIG5hbWU6ICR7ZXZ0Lm5hbWV9YCk7XG4gICAgICogICAgIH0pO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgb25EaXNjb25uZWN0aW9uKGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMuZGlzY29ubmVjdExpc3RlbmVyID0gKHBheWxvYWQpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXIocGF5bG9hZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3aGlsZSBjYWxsaW5nIHRoZSBvbkRpc2Nvbm5lY3Rpb24gY2FsbGJhY2s6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc2Nvbm5lY3RMaXN0ZW5lciA9ICgpID0+IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogRGlzY29ubmVjdHMgdGhlIGNsaWVudCBmcm9tIHRoZSBjaGFubmVsLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3QoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgY2xpZW50LmRpc2Nvbm5lY3QoKTtcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGRpc2Nvbm5lY3QoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuc2VuZERpc2Nvbm5lY3RBY3Rpb24oKTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRjKHRoaXMsIF9DaGFubmVsQ2xpZW50X2Nsb3NlLCBcImZcIikuY2FsbCh0aGlzKTtcbiAgICB9XG4gICAgYXN5bmMgc2VuZERpc2Nvbm5lY3RBY3Rpb24oKSB7XG4gICAgICAgIGNvbnN0IHByb3RlY3RlZE9iaiA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYyh0aGlzLCBfQ2hhbm5lbENsaWVudF9wcm90ZWN0ZWRPYmosIFwiZlwiKTtcbiAgICAgICAgYXdhaXQgcHJvdGVjdGVkT2JqLmNsb3NlKCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqIFdyaXRpbmcgdGhpcyBhcyBhIHN0YXRpYyB0byBrZWVwIGNvZGUgdG9nZXRoZXIsIGJ1dCBpbiBlbnZpcm9ubWVudHMgd2l0aCBhIHdpcmUsIHRoaXMgd2lsbCBiZSBESSdkIGludG8gdGhlIHByb3RlY3RlZE9iamVjdCBjbGFzcyBhcyBjbG9zZS5cbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgd2lyZUNsb3NlKHdpcmUsIHByb3ZpZGVySWRlbnRpdHksIGVuZHBvaW50SWQpIHtcbiAgICAgICAgY29uc3QgeyBjaGFubmVsTmFtZSwgdXVpZCwgbmFtZSB9ID0gcHJvdmlkZXJJZGVudGl0eTtcbiAgICAgICAgYXdhaXQgd2lyZS5zZW5kQWN0aW9uKCdkaXNjb25uZWN0LWZyb20tY2hhbm5lbCcsIHtcbiAgICAgICAgICAgIGNoYW5uZWxOYW1lLFxuICAgICAgICAgICAgdXVpZCxcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBlbmRwb2ludElkXG4gICAgICAgIH0pO1xuICAgIH1cbn1cbmNsaWVudC5DaGFubmVsQ2xpZW50ID0gQ2hhbm5lbENsaWVudDtcbl9DaGFubmVsQ2xpZW50X3Byb3RlY3RlZE9iaiA9IG5ldyBXZWFrTWFwKCksIF9DaGFubmVsQ2xpZW50X3N0cmF0ZWd5ID0gbmV3IFdlYWtNYXAoKSwgX0NoYW5uZWxDbGllbnRfY2xvc2UgPSBuZXcgV2Vha01hcCgpO1xuXG52YXIgY29ubmVjdGlvbk1hbmFnZXIgPSB7fTtcblxudmFyIGV4aGF1c3RpdmUgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4aGF1c3RpdmUsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZXhoYXVzdGl2ZS5leGhhdXN0aXZlQ2hlY2sgPSB2b2lkIDA7XG5mdW5jdGlvbiBleGhhdXN0aXZlQ2hlY2sodmFsdWUsIGFsbG93ZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIHZhbHVlOiAke3ZhbHVlfSR7YWxsb3dlZCA/IGBcXG4gU3VwcG9ydGVkIHZhbHVlcyBhcmU6ICR7YWxsb3dlZC5qb2luKCcnKX1gIDogJyd9YCk7XG59XG5leGhhdXN0aXZlLmV4aGF1c3RpdmVDaGVjayA9IGV4aGF1c3RpdmVDaGVjaztcblxudmFyIHN0cmF0ZWd5JDMgPSB7fTtcblxudmFyIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkOSA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcbn07XG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRiID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcbn07XG52YXIgX0NsYXNzaWNTdHJhdGVneV93aXJlLCBfQ2xhc3NpY1N0cmF0ZWd5X2VuZHBvaW50SWRlbnRpdHlNYXAsIF9DbGFzc2ljU3RyYXRlZ3lfcGVuZGluZ01lc3NhZ2VzQnlFbmRwb2ludElkO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KHN0cmF0ZWd5JDMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuc3RyYXRlZ3kkMy5DbGFzc2ljSW5mbyA9IHN0cmF0ZWd5JDMuQ2xhc3NpY1N0cmF0ZWd5ID0gdm9pZCAwO1xuLypcblRoaXMgaXMgdXNlZCB0byBhYnN0cmFjdCBvdXQgaXBjIG1lc3NhZ2luZyBmcm9tIHRoZSBjaGFubmVscyBpbXBsZW1lbnRhdGlvbi4gSXQgaXMgb25seSBjb25jZXJuZWQgd2l0aCBzZW5kaW5nIG1lc3NhZ2VzIGFuZCByZWdpc3RyYXRpb24gd2l0aCB0aGUgTWVzc2FnZVJlY2VpdmVyXG4qL1xuY2xhc3MgQ2xhc3NpY1N0cmF0ZWd5IHtcbiAgICBjb25zdHJ1Y3Rvcih3aXJlLCBtZXNzYWdlUmVjZWl2ZXIsIGVuZHBvaW50SWQsIC8vIFByb3ZpZGVyIGVuZHBvaW50SWQgaXMgY2hhbm5lbElkXG4gICAgcHJvdmlkZXJJZGVudGl0eSkge1xuICAgICAgICB0aGlzLm1lc3NhZ2VSZWNlaXZlciA9IG1lc3NhZ2VSZWNlaXZlcjtcbiAgICAgICAgdGhpcy5lbmRwb2ludElkID0gZW5kcG9pbnRJZDtcbiAgICAgICAgdGhpcy5wcm92aWRlcklkZW50aXR5ID0gcHJvdmlkZXJJZGVudGl0eTtcbiAgICAgICAgX0NsYXNzaWNTdHJhdGVneV93aXJlLnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICAvLyBTdG9yZSBmdWxsIGVuZHBvaW50SWRlbnRpdHkgYnkgZW5kcG9pbnRJZCBvZiBhbGwga25vd24gZW5kcG9pbnRzIGZvciB0aGlzIHN0cmF0ZWd5IGluc3RhbmNlLlxuICAgICAgICAvLyAoY2xpZW50cyB3aWxsIG9ubHkgaGF2ZSAxOiB0aGUgcHJvdmlkZXIsIHRoZSBwcm92aWRlciB3aWxsIGhhdmUgYWxsIGNsaWVudHMpXG4gICAgICAgIF9DbGFzc2ljU3RyYXRlZ3lfZW5kcG9pbnRJZGVudGl0eU1hcC5zZXQodGhpcywgbmV3IE1hcCgpKTtcbiAgICAgICAgLy8gU3RvcmUgYSBzZXQgb2YgY2FuY2VsbGFibGUgcHJvbWlzZXMgdG8gYmUgYWJsZSB0byByZWplY3QgdGhlbSB3aGVuIGNsaWVudFxuICAgICAgICAvLyBjb25uZWN0aW9uIHByb2JsZW1zIG9jY3VyXG4gICAgICAgIF9DbGFzc2ljU3RyYXRlZ3lfcGVuZGluZ01lc3NhZ2VzQnlFbmRwb2ludElkLnNldCh0aGlzLCBuZXcgTWFwKTtcbiAgICAgICAgdGhpcy5zZW5kID0gYXN5bmMgKGVuZHBvaW50SWQsIGFjdGlvbiwgcGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdG8gPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGIodGhpcywgX0NsYXNzaWNTdHJhdGVneV9lbmRwb2ludElkZW50aXR5TWFwLCBcImZcIikuZ2V0KGVuZHBvaW50SWQpO1xuICAgICAgICAgICAgaWYgKCF0bykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGxvY2F0ZSByb3V0aW5nIGluZm8gZm9yIGVuZHBvaW50ICR7ZW5kcG9pbnRJZH1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGFzIGNhc3RpbmcgdG8gYW55IGJlY2F1c2UgdHlwZXNjcmlwdCBjb21wbGFpbnMuIFRoZSBmb2xsb3dpbmcgaXMgb25seSByZWxldmFudCBpZiB0aGlzIGlzIGEgbG9jYWxseSBzZXQgZW5kcG9pbnRJZCBvbiBhIENsaWVudElkZW50aXR5LlxuICAgICAgICAgICAgLy8gV2UgZGVsZXRlIHRoZXNlIHByb3BlcnRpZXMgdG8gbm90IGNoYW5nZSBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbiAgICAgICAgICAgIGNvbnN0IGNsZWFuSWQgPSB7IC4uLnRvIH07XG4gICAgICAgICAgICBpZiAoY2xlYW5JZC5pc0xvY2FsRW5kcG9pbnRJZCkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBjbGVhbklkLmVuZHBvaW50SWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWxldGUgY2xlYW5JZC5pc0xvY2FsRW5kcG9pbnRJZDtcbiAgICAgICAgICAgIC8vIGdyYWIgdGhlIHByb21pc2UgYmVmb3JlIGF3YWl0aW5nIGl0IHRvIHNhdmUgaW4gb3VyIHBlbmRpbmcgbWVzc2FnZXMgbWFwXG4gICAgICAgICAgICBjb25zdCBwID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCRiKHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfd2lyZSwgXCJmXCIpXG4gICAgICAgICAgICAgICAgLnNlbmRBY3Rpb24oJ3NlbmQtY2hhbm5lbC1tZXNzYWdlJywge1xuICAgICAgICAgICAgICAgIC4uLmNsZWFuSWQsXG4gICAgICAgICAgICAgICAgcHJvdmlkZXJJZGVudGl0eTogdGhpcy5wcm92aWRlcklkZW50aXR5LFxuICAgICAgICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICAgICAgICBwYXlsb2FkXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYih0aGlzLCBfQ2xhc3NpY1N0cmF0ZWd5X3BlbmRpbmdNZXNzYWdlc0J5RW5kcG9pbnRJZCwgXCJmXCIpLmdldChlbmRwb2ludElkKT8uYWRkKHApO1xuICAgICAgICAgICAgY29uc3QgcmF3ID0gYXdhaXQgcC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IubWVzc2FnZSk7XG4gICAgICAgICAgICB9KS5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBjbGVhbiB1cCB0aGUgcGVuZGluZyBwcm9taXNlXG4gICAgICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRiKHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfcGVuZGluZ01lc3NhZ2VzQnlFbmRwb2ludElkLCBcImZcIikuZ2V0KGVuZHBvaW50SWQpPy5kZWxldGUocCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiByYXcucGF5bG9hZC5kYXRhLnJlc3VsdDtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jbG9zZSA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMubWVzc2FnZVJlY2VpdmVyLnJlbW92ZUVuZHBvaW50KHRoaXMucHJvdmlkZXJJZGVudGl0eS5jaGFubmVsSWQsIHRoaXMuZW5kcG9pbnRJZCk7XG4gICAgICAgICAgICBbLi4uX19jbGFzc1ByaXZhdGVGaWVsZEdldCRiKHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfZW5kcG9pbnRJZGVudGl0eU1hcCwgXCJmXCIpLmtleXMoKV0uZm9yRWFjaCgoaWQpID0+IHRoaXMuY2xvc2VFbmRwb2ludChpZCkpO1xuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ5KHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfZW5kcG9pbnRJZGVudGl0eU1hcCwgbmV3IE1hcCgpLCBcImZcIik7XG4gICAgICAgIH07XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkOSh0aGlzLCBfQ2xhc3NpY1N0cmF0ZWd5X3dpcmUsIHdpcmUsIFwiZlwiKTtcbiAgICB9XG4gICAgb25FbmRwb2ludERpc2Nvbm5lY3QoZW5kcG9pbnRJZCwgbGlzdGVuZXIpIHtcbiAgICAgICAgLy8gTmV2ZXIgZmlyZXMgZm9yICdjbGFzc2ljJy5cbiAgICB9XG4gICAgcmVjZWl2ZShsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLm1lc3NhZ2VSZWNlaXZlci5hZGRFbmRwb2ludChsaXN0ZW5lciwgdGhpcy5wcm92aWRlcklkZW50aXR5LmNoYW5uZWxJZCwgdGhpcy5lbmRwb2ludElkKTtcbiAgICB9XG4gICAgYXN5bmMgY2xvc2VFbmRwb2ludChlbmRwb2ludElkKSB7XG4gICAgICAgIGNvbnN0IGlkID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCRiKHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfZW5kcG9pbnRJZGVudGl0eU1hcCwgXCJmXCIpLmdldChlbmRwb2ludElkKTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRiKHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfZW5kcG9pbnRJZGVudGl0eU1hcCwgXCJmXCIpLmRlbGV0ZShlbmRwb2ludElkKTtcbiAgICAgICAgY29uc3QgcGVuZGluZ1NldCA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYih0aGlzLCBfQ2xhc3NpY1N0cmF0ZWd5X3BlbmRpbmdNZXNzYWdlc0J5RW5kcG9pbnRJZCwgXCJmXCIpLmdldChlbmRwb2ludElkKTtcbiAgICAgICAgcGVuZGluZ1NldD8uZm9yRWFjaCgocCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZXJyb3JNc2cgPSBgQ2hhbm5lbCBjb25uZWN0aW9uIHdpdGggaWRlbnRpdHkgdXVpZDogJHtpZD8udXVpZH0gLyBuYW1lOiAke2lkPy5uYW1lfSAvIGVuZHBvaW50SWQ6ICR7ZW5kcG9pbnRJZH0gbm8gbG9uZ2VyIGNvbm5lY3RlZC5gO1xuICAgICAgICAgICAgcC5jYW5jZWwobmV3IEVycm9yKGVycm9yTXNnKSk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpc0VuZHBvaW50Q29ubmVjdGVkKGVuZHBvaW50SWQpIHtcbiAgICAgICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYih0aGlzLCBfQ2xhc3NpY1N0cmF0ZWd5X2VuZHBvaW50SWRlbnRpdHlNYXAsIFwiZlwiKS5oYXMoZW5kcG9pbnRJZCk7XG4gICAgfVxuICAgIGFkZEVuZHBvaW50KGVuZHBvaW50SWQsIHBheWxvYWQpIHtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRiKHRoaXMsIF9DbGFzc2ljU3RyYXRlZ3lfZW5kcG9pbnRJZGVudGl0eU1hcCwgXCJmXCIpLnNldChlbmRwb2ludElkLCBwYXlsb2FkLmVuZHBvaW50SWRlbnRpdHkpO1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGIodGhpcywgX0NsYXNzaWNTdHJhdGVneV9wZW5kaW5nTWVzc2FnZXNCeUVuZHBvaW50SWQsIFwiZlwiKS5zZXQoZW5kcG9pbnRJZCwgbmV3IFNldCgpKTtcbiAgICB9XG4gICAgaXNWYWxpZEVuZHBvaW50UGF5bG9hZChwYXlsb2FkKSB7XG4gICAgICAgIHJldHVybiAodHlwZW9mIHBheWxvYWQ/LmVuZHBvaW50SWRlbnRpdHk/LmVuZHBvaW50SWQgPT09ICdzdHJpbmcnIHx8XG4gICAgICAgICAgICB0eXBlb2YgcGF5bG9hZD8uZW5kcG9pbnRJZGVudGl0eT8uY2hhbm5lbElkID09PSAnc3RyaW5nJyk7XG4gICAgfVxufVxuc3RyYXRlZ3kkMy5DbGFzc2ljU3RyYXRlZ3kgPSBDbGFzc2ljU3RyYXRlZ3k7XG5fQ2xhc3NpY1N0cmF0ZWd5X3dpcmUgPSBuZXcgV2Vha01hcCgpLCBfQ2xhc3NpY1N0cmF0ZWd5X2VuZHBvaW50SWRlbnRpdHlNYXAgPSBuZXcgV2Vha01hcCgpLCBfQ2xhc3NpY1N0cmF0ZWd5X3BlbmRpbmdNZXNzYWdlc0J5RW5kcG9pbnRJZCA9IG5ldyBXZWFrTWFwKCk7XG4vLyBBcmJpdHJhcmlseSBzdGFydGluZyBhdCA1IHRvIGxlYXZlIHRoZSBkb29yIG9wZW4gdG8gYmFja2ZpbGxpbmcgcHJlIGVuZHBvaW50SWQgZXRjLlxuc3RyYXRlZ3kkMy5DbGFzc2ljSW5mbyA9IHsgdmVyc2lvbjogNSwgbWluaW11bVZlcnNpb246IDAsIHR5cGU6ICdjbGFzc2ljJyB9O1xuXG52YXIgc3RyYXRlZ3kkMiA9IHt9O1xuXG52YXIgZW5kcG9pbnQgPSB7fTtcblxudmFyIGVycm9ycyA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXJyb3JzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmVycm9ycy5lcnJvclRvUE9KTyA9IHZvaWQgMDtcbmZ1bmN0aW9uIGVycm9yVG9QT0pPKGVycm9yKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3RhY2s6IGVycm9yLnN0YWNrLFxuICAgICAgICBuYW1lOiBlcnJvci5uYW1lLFxuICAgICAgICBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLFxuICAgICAgICAvLyBzdXBwb3J0IHRoZSBjYXNlIHdoZXJlIHN0YWNrIGlzIGVtcHR5IG9yIG1pc3NpbmdcbiAgICAgICAgdG9TdHJpbmc6ICgpID0+IGVycm9yLnN0YWNrIHx8IGVycm9yLnRvU3RyaW5nKClcbiAgICB9O1xufVxuZXJyb3JzLmVycm9yVG9QT0pPID0gZXJyb3JUb1BPSk87XG5cbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGEgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDggPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgc2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XG59O1xudmFyIF9SVENFbmRwb2ludF9wcm9jZXNzQWN0aW9uLCBfUlRDRW5kcG9pbnRfZGlzY29ubmVjdExpc3RlbmVyO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGVuZHBvaW50LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmVuZHBvaW50LlJUQ0VuZHBvaW50ID0gdm9pZCAwO1xuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG5jb25zdCBlcnJvcnNfMSQxID0gZXJyb3JzO1xuLypcblRoaXMgaGFuZGxlcyBzZW5kaW5nIFJUQyBtZXNzYWdlcyBiZXR3ZWVuIFJUQyBjb25uZWN0aW9ucyBvdmVyIHRoZSByZXF1ZXN0IGFuZCByZXNwb25zZSBkYXRhIGNoYW5uZWxzLlxuKi9cbmNsYXNzIFJUQ0VuZHBvaW50IHtcbiAgICBzdGF0aWMgaXNWYWxpZEVuZHBvaW50UGF5bG9hZChwYXlsb2FkKSB7XG4gICAgICAgIGNvbnN0IGlzT2JqZWN0ID0gKHgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgLy8gVE9ETyBpbiBmYWN0b3J5IFBSOlxuICAgICAgICAvLyBwYXlsb2FkLnR5cGUgPT09ICdydGMnICYmXG4gICAgICAgIGlzT2JqZWN0KHBheWxvYWQpICYmXG4gICAgICAgICAgICBpc09iamVjdChwYXlsb2FkLmVuZHBvaW50SWRlbnRpdHkpICYmXG4gICAgICAgICAgICBpc09iamVjdChwYXlsb2FkLnJ0YykgJiZcbiAgICAgICAgICAgIHR5cGVvZiBwYXlsb2FkLmVuZHBvaW50SWRlbnRpdHkuZW5kcG9pbnRJZCA9PT0gJ3N0cmluZycpO1xuICAgIH1cbiAgICBjb25zdHJ1Y3Rvcih7IHJ0YywgZW5kcG9pbnRJZGVudGl0eSB9KSB7XG4gICAgICAgIHRoaXMucmVzcG9uc2VNYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgIF9SVENFbmRwb2ludF9wcm9jZXNzQWN0aW9uLnNldCh0aGlzLCBudWxsKTtcbiAgICAgICAgX1JUQ0VuZHBvaW50X2Rpc2Nvbm5lY3RMaXN0ZW5lci5zZXQodGhpcywgdm9pZCAwKTtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uU3RhdGVDaGFuZ2VIYW5kbGVyID0gKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5ydGMucnRjQ2xpZW50LmNvbm5lY3Rpb25TdGF0ZSAhPT0gJ2Nvbm5lY3RlZCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJ0Yy5ydGNDbGllbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgdGhpcy5jb25uZWN0aW9uU3RhdGVDaGFuZ2VIYW5kbGVyKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgaWYgKF9fY2xhc3NQcml2YXRlRmllbGRHZXQkYSh0aGlzLCBfUlRDRW5kcG9pbnRfZGlzY29ubmVjdExpc3RlbmVyLCBcImZcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCRhKHRoaXMsIF9SVENFbmRwb2ludF9kaXNjb25uZWN0TGlzdGVuZXIsIFwiZlwiKS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5zZW5kID0gYXN5bmMgKGFjdGlvbiwgcGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZUlkID0gYG1lc3NhZ2UtJHtNYXRoLnJhbmRvbSgpfWA7XG4gICAgICAgICAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzcG9uc2VNYXAuc2V0KG1lc3NhZ2VJZCwgeyByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMucnRjLmNoYW5uZWxzLnJlcXVlc3Quc2VuZChKU09OLnN0cmluZ2lmeSh7IGFjdGlvbiwgcGF5bG9hZCwgbWVzc2FnZUlkIH0pKTtcbiAgICAgICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNsb3NlID0gKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZXNwb25zZU1hcC5mb3JFYWNoKChyZXNwb25zZSkgPT4gcmVzcG9uc2UucmVqZWN0KCdDb25uZWN0aW9uIGhhcyBjbG9zZWQuJykpO1xuICAgICAgICAgICAgdGhpcy5yZXNwb25zZU1hcCA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgIHRoaXMucnRjLmNoYW5uZWxzLnJlcXVlc3QuY2xvc2UoKTtcbiAgICAgICAgICAgIHRoaXMucnRjLmNoYW5uZWxzLnJlc3BvbnNlLmNsb3NlKCk7XG4gICAgICAgICAgICB0aGlzLnJ0Yy5ydGNDbGllbnQuY2xvc2UoKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ydGMgPSBydGM7XG4gICAgICAgIHRoaXMuZW5kcG9pbnRJZGVudGl0eSA9IGVuZHBvaW50SWRlbnRpdHk7XG4gICAgICAgIHRoaXMucnRjLmNoYW5uZWxzLnJlc3BvbnNlLmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCAoZSkgPT4ge1xuICAgICAgICAgICAgbGV0IHsgZGF0YSB9ID0gZTtcbiAgICAgICAgICAgIGlmIChlLmRhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoZS5kYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHsgbWVzc2FnZUlkLCBwYXlsb2FkLCBzdWNjZXNzLCBlcnJvciB9ID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgICAgIGNvbnN0IHsgcmVzb2x2ZSwgcmVqZWN0IH0gPSB0aGlzLnJlc3BvbnNlTWFwLmdldChtZXNzYWdlSWQpID8/IHt9O1xuICAgICAgICAgICAgaWYgKHJlc29sdmUgJiYgcmVqZWN0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZU1hcC5kZWxldGUobWVzc2FnZUlkKTtcbiAgICAgICAgICAgICAgICBpZiAoc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHBheWxvYWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnQ291bGQgbm90IGZpbmQgaWQgaW4gcmVzcG9uc2VNYXAuJyk7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnJ0Yy5jaGFubmVscy5yZXF1ZXN0LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBhc3luYyAoZSkgPT4ge1xuICAgICAgICAgICAgbGV0IHsgZGF0YSB9ID0gZTtcbiAgICAgICAgICAgIGlmIChlLmRhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgICAgICAgICAgICAgIGRhdGEgPSBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoZS5kYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHsgbWVzc2FnZUlkLCBhY3Rpb24sIHBheWxvYWQgfSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgICAgICBpZiAoX19jbGFzc1ByaXZhdGVGaWVsZEdldCRhKHRoaXMsIF9SVENFbmRwb2ludF9wcm9jZXNzQWN0aW9uLCBcImZcIikpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGEodGhpcywgX1JUQ0VuZHBvaW50X3Byb2Nlc3NBY3Rpb24sIFwiZlwiKS5jYWxsKHRoaXMsIGFjdGlvbiwgcGF5bG9hZCwgZW5kcG9pbnRJZGVudGl0eSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucnRjLmNoYW5uZWxzLnJlc3BvbnNlLnNlbmQoSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGF5bG9hZDogcmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogdHJ1ZVxuICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBSVENEYXRhQ2hhbm5lbCBpcyBvcGVuIGJlZm9yZSBzZW5kaW5nLCBlcnJvciBnZXRzIHN3YWxsb3dlZCBoZXJlIGluIHRoZSBjYXNlIHdoZXJlXG4gICAgICAgICAgICAgICAgICAgIC8vIGNsaWVudCBkaXNwYXRjaGVkIHRoZW4gY2xvc2VkIG9yIGRpc2Nvbm5lY3RlZCBiZWZvcmUgdGhlIGRpc3BhdGNoIHJlc29sdmVzLlxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5ydGMuY2hhbm5lbHMucmVzcG9uc2UucmVhZHlTdGF0ZSA9PT0gJ29wZW4nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJ0Yy5jaGFubmVscy5yZXNwb25zZS5zZW5kKEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3I6ICgwLCBlcnJvcnNfMSQxLmVycm9yVG9QT0pPKShlcnJvciksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBSVENEYXRhQ2hhbm5lbCBpcyBvcGVuIGZvciBzYW1lIHJlYXNvbiBhcyBjYXRjaCBibG9jayBhYm92ZS5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHRoaXMucnRjLmNoYW5uZWxzLnJlc3BvbnNlLnJlYWR5U3RhdGUgPT09ICdvcGVuJykge1xuICAgICAgICAgICAgICAgIHRoaXMucnRjLmNoYW5uZWxzLnJlc3BvbnNlLnNlbmQoSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlSWQsXG4gICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBlcnJvcjogJ0Nvbm5lY3Rpb24gbm90IHJlYWR5LidcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnJ0Yy5ydGNDbGllbnQuYWRkRXZlbnRMaXN0ZW5lcignY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgdGhpcy5jb25uZWN0aW9uU3RhdGVDaGFuZ2VIYW5kbGVyKTtcbiAgICAgICAgLy8gRGlzY29ubmVjdCBpZiBkYXRhIGNoYW5uZWxzIGNsb3NlIHVuZXhwZWN0ZWRseSwgZS5nLiBjYW4gaGFwcGVuIGR1ZSB0byBtZXNzYWdlIHNpemUgPiB+MjU1a0IgKFJUQ1BlZXJDb25uZWN0aW9uLnNjdHAubWF4TWVzc2FnZVNpemVMaW1pdDogMjYyMTQ0KVxuICAgICAgICBPYmplY3QudmFsdWVzKHRoaXMucnRjLmNoYW5uZWxzKS5mb3JFYWNoKChkYXRhY2hhbm5lbCkgPT4ge1xuICAgICAgICAgICAgZGF0YWNoYW5uZWwub25jbG9zZSA9IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgWy4uLnRoaXMucmVzcG9uc2VNYXAudmFsdWVzKCldLmZvckVhY2goKHByb21pc2UpID0+IHByb21pc2UucmVqZWN0KG5ldyBFcnJvcignUlRDRGF0YUNoYW5uZWwgY2xvc2VkIHVuZXhwZWN0ZWRseSwgdGhpcyBpcyBtb3N0IGNvbW1vbmx5IGNhdXNlZCBieSBtZXNzYWdlIHNpemUuIE5vdGU6IFJUQyBDaGFubmVscyBoYXZlIGEgbWVzc2FnZSBzaXplIGxpbWl0IG9mIH4yNTVrQi4nKSkpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICBpZiAoX19jbGFzc1ByaXZhdGVGaWVsZEdldCRhKHRoaXMsIF9SVENFbmRwb2ludF9kaXNjb25uZWN0TGlzdGVuZXIsIFwiZlwiKSkge1xuICAgICAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGEodGhpcywgX1JUQ0VuZHBvaW50X2Rpc2Nvbm5lY3RMaXN0ZW5lciwgXCJmXCIpLmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIG9uRGlzY29ubmVjdChsaXN0ZW5lcikge1xuICAgICAgICBpZiAoIV9fY2xhc3NQcml2YXRlRmllbGRHZXQkYSh0aGlzLCBfUlRDRW5kcG9pbnRfZGlzY29ubmVjdExpc3RlbmVyLCBcImZcIikpIHtcbiAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkOCh0aGlzLCBfUlRDRW5kcG9pbnRfZGlzY29ubmVjdExpc3RlbmVyLCBsaXN0ZW5lciwgXCJmXCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdSVENFbmRwb2ludCBkaXNjb25uZWN0TGlzdGVuZXIgY2Fubm90IGJlIHNldCB0d2ljZS4nKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZWNlaXZlKGxpc3RlbmVyKSB7XG4gICAgICAgIGlmIChfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JGEodGhpcywgX1JUQ0VuZHBvaW50X3Byb2Nlc3NBY3Rpb24sIFwiZlwiKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgaGF2ZSBhbHJlYWR5IHNldCBhIGxpc3RlbmVyIGZvciB0aGlzIFJUQyBFbmRwb2ludC4nKTtcbiAgICAgICAgfVxuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDgodGhpcywgX1JUQ0VuZHBvaW50X3Byb2Nlc3NBY3Rpb24sIGxpc3RlbmVyLCBcImZcIik7XG4gICAgfVxuICAgIGdldCBjb25uZWN0ZWQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnJ0Yy5ydGNDbGllbnQuY29ubmVjdGlvblN0YXRlID09PSAnY29ubmVjdGVkJztcbiAgICB9XG59XG5lbmRwb2ludC5SVENFbmRwb2ludCA9IFJUQ0VuZHBvaW50O1xuX1JUQ0VuZHBvaW50X3Byb2Nlc3NBY3Rpb24gPSBuZXcgV2Vha01hcCgpLCBfUlRDRW5kcG9pbnRfZGlzY29ubmVjdExpc3RlbmVyID0gbmV3IFdlYWtNYXAoKTtcblxudmFyIHN0cmF0ZWd5JDEgPSB7fTtcblxudmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkNyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcbn07XG52YXIgX0VuZHBvaW50U3RyYXRlZ3lfcHJvY2Vzc0FjdGlvbiwgX0VuZHBvaW50U3RyYXRlZ3lfZW5kcG9pbnRNYXAsIF9FbmRwb2ludFN0cmF0ZWd5X2Nvbm5lY3RlZDtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShzdHJhdGVneSQxLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnN0cmF0ZWd5JDEuRW5kcG9pbnRTdHJhdGVneSA9IHZvaWQgMDtcbmNsYXNzIEVuZHBvaW50U3RyYXRlZ3kge1xuICAgIC8vIE5lZWQgdG8gcGFzcyBpbiB2YWxpZGF0ZSBlbmRwb2ludCBzZXBhcmF0ZWx5IGZyb20gY29uc3RydWN0b3IgYmVjYXVzZSB0cyBpbnRlcmZhY2VzIGRvbid0IGRvIHdlbGwgd2l0aCBzdGF0aWMgbWV0aG9kc1xuICAgIGNvbnN0cnVjdG9yKEVuZHBvaW50VHlwZSwgdmFsaWRhdGVFbmRwb2ludCwgU3RyYXRlZ3lOYW1lKSB7XG4gICAgICAgIHRoaXMuRW5kcG9pbnRUeXBlID0gRW5kcG9pbnRUeXBlO1xuICAgICAgICB0aGlzLlN0cmF0ZWd5TmFtZSA9IFN0cmF0ZWd5TmFtZTtcbiAgICAgICAgX0VuZHBvaW50U3RyYXRlZ3lfcHJvY2Vzc0FjdGlvbi5zZXQodGhpcywgbnVsbCk7XG4gICAgICAgIF9FbmRwb2ludFN0cmF0ZWd5X2VuZHBvaW50TWFwLnNldCh0aGlzLCBuZXcgTWFwKCkpO1xuICAgICAgICBfRW5kcG9pbnRTdHJhdGVneV9jb25uZWN0ZWQuc2V0KHRoaXMsIHRydWUpO1xuICAgICAgICB0aGlzLnNlbmQgPSBhc3luYyAoZW5kcG9pbnRJZCwgYWN0aW9uLCBwYXlsb2FkKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRFbmRwb2ludEJ5SWQoZW5kcG9pbnRJZCkuc2VuZChhY3Rpb24sIHBheWxvYWQpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNsb3NlID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9jb25uZWN0ZWQsIFwiZlwiKSkge1xuICAgICAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9lbmRwb2ludE1hcCwgXCJmXCIpLmZvckVhY2goKGVuZHBvaW50KSA9PiBlbmRwb2ludC5jbG9zZSgpKTtcbiAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDcodGhpcywgX0VuZHBvaW50U3RyYXRlZ3lfZW5kcG9pbnRNYXAsIG5ldyBNYXAoKSwgXCJmXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ3KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X2Nvbm5lY3RlZCwgZmFsc2UsIFwiZlwiKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5pc1ZhbGlkRW5kcG9pbnRQYXlsb2FkID0gdmFsaWRhdGVFbmRwb2ludDtcbiAgICB9XG4gICAgb25FbmRwb2ludERpc2Nvbm5lY3QoZW5kcG9pbnRJZCwgbGlzdGVuZXIpIHtcbiAgICAgICAgdGhpcy5nZXRFbmRwb2ludEJ5SWQoZW5kcG9pbnRJZCkub25EaXNjb25uZWN0KGxpc3RlbmVyKTtcbiAgICB9XG4gICAgcmVjZWl2ZShsaXN0ZW5lcikge1xuICAgICAgICBpZiAoX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X3Byb2Nlc3NBY3Rpb24sIFwiZlwiKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBZb3UgaGF2ZSBhbHJlYWR5IHNldCBhIGxpc3RlbmVyIGZvciB0aGlzICR7dGhpcy5TdHJhdGVneU5hbWV9IFN0cmF0ZWd5YCk7XG4gICAgICAgIH1cbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ3KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X3Byb2Nlc3NBY3Rpb24sIGxpc3RlbmVyLCBcImZcIik7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9lbmRwb2ludE1hcCwgXCJmXCIpLmZvckVhY2goKGVuZHBvaW50KSA9PiBlbmRwb2ludC5yZWNlaXZlKF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9wcm9jZXNzQWN0aW9uLCBcImZcIikpKTtcbiAgICB9XG4gICAgZ2V0RW5kcG9pbnRCeUlkKGVuZHBvaW50SWQpIHtcbiAgICAgICAgY29uc3QgZW5kcG9pbnQgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDkodGhpcywgX0VuZHBvaW50U3RyYXRlZ3lfZW5kcG9pbnRNYXAsIFwiZlwiKS5nZXQoZW5kcG9pbnRJZCk7XG4gICAgICAgIGlmICghZW5kcG9pbnQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2xpZW50IHdpdGggZW5kcG9pbnQgaWQgJHtlbmRwb2ludElkfSBpcyBub3QgY29ubmVjdGVkYCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVuZHBvaW50O1xuICAgIH1cbiAgICBnZXQgY29ubmVjdGVkKCkge1xuICAgICAgICByZXR1cm4gX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ5KHRoaXMsIF9FbmRwb2ludFN0cmF0ZWd5X2Nvbm5lY3RlZCwgXCJmXCIpO1xuICAgIH1cbiAgICBpc0VuZHBvaW50Q29ubmVjdGVkKGVuZHBvaW50SWQpIHtcbiAgICAgICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9lbmRwb2ludE1hcCwgXCJmXCIpLmhhcyhlbmRwb2ludElkKTtcbiAgICB9XG4gICAgYWRkRW5kcG9pbnQoZW5kcG9pbnRJZCwgcGF5bG9hZCkge1xuICAgICAgICBpZiAoIV9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9jb25uZWN0ZWQsIFwiZlwiKSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBBZGRpbmcgZW5kcG9pbnQgdG8gZGlzY29ubmVjdGVkICR7dGhpcy5TdHJhdGVneU5hbWV9IFN0cmF0ZWd5YCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2xpZW50U3RyYXQgPSBuZXcgdGhpcy5FbmRwb2ludFR5cGUocGF5bG9hZCk7XG4gICAgICAgIGlmIChfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDkodGhpcywgX0VuZHBvaW50U3RyYXRlZ3lfcHJvY2Vzc0FjdGlvbiwgXCJmXCIpKSB7XG4gICAgICAgICAgICBjbGllbnRTdHJhdC5yZWNlaXZlKF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9wcm9jZXNzQWN0aW9uLCBcImZcIikpO1xuICAgICAgICB9XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOSh0aGlzLCBfRW5kcG9pbnRTdHJhdGVneV9lbmRwb2ludE1hcCwgXCJmXCIpLnNldChlbmRwb2ludElkLCBjbGllbnRTdHJhdCk7XG4gICAgfVxuICAgIGFzeW5jIGNsb3NlRW5kcG9pbnQoZW5kcG9pbnRJZCkge1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDkodGhpcywgX0VuZHBvaW50U3RyYXRlZ3lfZW5kcG9pbnRNYXAsIFwiZlwiKS5kZWxldGUoZW5kcG9pbnRJZCk7XG4gICAgfVxufVxuc3RyYXRlZ3kkMS5FbmRwb2ludFN0cmF0ZWd5ID0gRW5kcG9pbnRTdHJhdGVneTtcbl9FbmRwb2ludFN0cmF0ZWd5X3Byb2Nlc3NBY3Rpb24gPSBuZXcgV2Vha01hcCgpLCBfRW5kcG9pbnRTdHJhdGVneV9lbmRwb2ludE1hcCA9IG5ldyBXZWFrTWFwKCksIF9FbmRwb2ludFN0cmF0ZWd5X2Nvbm5lY3RlZCA9IG5ldyBXZWFrTWFwKCk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShzdHJhdGVneSQyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnN0cmF0ZWd5JDIuUlRDSW5mbyA9IHN0cmF0ZWd5JDIuUlRDU3RyYXRlZ3kgPSB2b2lkIDA7XG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi9cbi8qIGVzbGludC1kaXNhYmxlIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXMgKi9cbmNvbnN0IGVuZHBvaW50XzEgPSBlbmRwb2ludDtcbmNvbnN0IHN0cmF0ZWd5XzEkMSA9IHN0cmF0ZWd5JDE7XG4vKlxuVGhpcyBpcyB1c2VkIHRvIGFic3RyYWN0IG91dCBydGMgbWVzc2FnaW5nIGZyb20gdGhlIGNoYW5uZWxzIGltcGxlbWVudGF0aW9uIHVzaW5nIFJUQ0VuZHBvaW50cy5cbiovXG5jbGFzcyBSVENTdHJhdGVneSBleHRlbmRzIHN0cmF0ZWd5XzEkMS5FbmRwb2ludFN0cmF0ZWd5IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoZW5kcG9pbnRfMS5SVENFbmRwb2ludCwgZW5kcG9pbnRfMS5SVENFbmRwb2ludC5pc1ZhbGlkRW5kcG9pbnRQYXlsb2FkLCAnUlRDJyk7XG4gICAgfVxufVxuc3RyYXRlZ3kkMi5SVENTdHJhdGVneSA9IFJUQ1N0cmF0ZWd5O1xuc3RyYXRlZ3kkMi5SVENJbmZvID0geyB2ZXJzaW9uOiAyLCBtaW5pbXVtVmVyc2lvbjogMCwgdHlwZTogJ3J0YycgfTtcblxudmFyIGljZU1hbmFnZXIgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGljZU1hbmFnZXIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuaWNlTWFuYWdlci5SVENJQ0VNYW5hZ2VyID0gdm9pZCAwO1xuY29uc3QgYmFzZV8xJGggPSBiYXNlO1xuLypcblNpbmdsZXRvbiB0aGF0IGZhY2lsaXRhdGVzIE9mZmVyIGFuZCBBbnN3ZXIgZXhjaGFuZ2UgcmVxdWlyZWQgZm9yIGVzdGFibGlzaGluZyBSVEMgY29ubmVjdGlvbnMuXG4qL1xuY2xhc3MgUlRDSUNFTWFuYWdlciBleHRlbmRzIGJhc2VfMSRoLkVtaXR0ZXJCYXNlIHtcbiAgICBjb25zdHJ1Y3Rvcih3aXJlKSB7XG4gICAgICAgIHN1cGVyKHdpcmUsICdjaGFubmVsJyk7XG4gICAgICAgIHRoaXMuZW5zdXJlQ2hhbm5lbE9wZW5lZCA9IChjaGFubmVsKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChjaGFubmVsLnJlYWR5U3RhdGUgPT09ICdvcGVuJykge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGNoYW5uZWwucmVhZHlTdGF0ZSA9PT0gJ2Nvbm5lY3RpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hhbm5lbC5yZW1vdmVFdmVudExpc3RlbmVyKCdvcGVuJywgbGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBjaGFubmVsLmFkZEV2ZW50TGlzdGVuZXIoJ29wZW4nLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdUaGlzIENoYW5uZWwgaGFzIGFscmVhZHkgY2xvc2VkJykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBzdGF0aWMgY3JlYXRlRGF0YUNoYW5uZWxQcm9taXNlKGxhYmVsLCBydGNDbGllbnQpIHtcbiAgICAgICAgbGV0IHJlc29sdmVyO1xuICAgICAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmVyID0gcmVzb2x2ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGxpc3RlbmVyID0gKGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG9wZW5MaXN0ZW5lciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBlLmNoYW5uZWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignb3BlbicsIG9wZW5MaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZXIoZS5jaGFubmVsKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoZS5jaGFubmVsLmxhYmVsID09PSBsYWJlbCkge1xuICAgICAgICAgICAgICAgIGUuY2hhbm5lbC5hZGRFdmVudExpc3RlbmVyKCdvcGVuJywgb3Blbkxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICBydGNDbGllbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZGF0YWNoYW5uZWwnLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHJ0Y0NsaWVudC5hZGRFdmVudExpc3RlbmVyKCdkYXRhY2hhbm5lbCcsIGxpc3RlbmVyKTtcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuICAgIGFzeW5jIGxpc3RlbkZvclByb3ZpZGVySWNlKHJ0Y0Nvbm5lY3Rpb25JZCwgbGlzdGVuZXIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5vbih0aGlzLmNyZWF0ZVByb3ZpZGVyRXZlbnROYW1lKHJ0Y0Nvbm5lY3Rpb25JZCksIGxpc3RlbmVyLCB7IHRpbWVzdGFtcDogRGF0ZS5ub3coKSB9KTtcbiAgICB9XG4gICAgYXN5bmMgcmFpc2VQcm92aWRlckljZShydGNDb25uZWN0aW9uSWQsIHBheWxvYWQpIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLmVudmlyb25tZW50LnJhaXNlRXZlbnQodGhpcy5jcmVhdGVSb3V0ZVN0cmluZyh0aGlzLmNyZWF0ZVByb3ZpZGVyRXZlbnROYW1lKHJ0Y0Nvbm5lY3Rpb25JZCkpLCBwYXlsb2FkKTtcbiAgICB9XG4gICAgYXN5bmMgbGlzdGVuRm9yQ2xpZW50SWNlKHJ0Y0Nvbm5lY3Rpb25JZCwgbGlzdGVuZXIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5vbih0aGlzLmNyZWF0ZUNsaWVudEV2ZW50TmFtZShydGNDb25uZWN0aW9uSWQpLCBsaXN0ZW5lciwgeyB0aW1lc3RhbXA6IERhdGUubm93KCkgfSk7XG4gICAgfVxuICAgIGFzeW5jIHJhaXNlQ2xpZW50SWNlKHJ0Y0Nvbm5lY3Rpb25JZCwgcGF5bG9hZCkge1xuICAgICAgICBhd2FpdCB0aGlzLndpcmUuZW52aXJvbm1lbnQucmFpc2VFdmVudCh0aGlzLmNyZWF0ZVJvdXRlU3RyaW5nKHRoaXMuY3JlYXRlQ2xpZW50RXZlbnROYW1lKHJ0Y0Nvbm5lY3Rpb25JZCkpLCBwYXlsb2FkKTtcbiAgICB9XG4gICAgY2xlYW51cEljZUxpc3RlbmVycyhydGNDb25uZWN0aW9uSWQpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnModGhpcy5jcmVhdGVDbGllbnRFdmVudE5hbWUocnRjQ29ubmVjdGlvbklkKSk7XG4gICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKHRoaXMuY3JlYXRlUHJvdmlkZXJFdmVudE5hbWUocnRjQ29ubmVjdGlvbklkKSk7XG4gICAgfVxuICAgIGNyZWF0ZUNsaWVudEV2ZW50TmFtZShydGNDb25uZWN0aW9uSWQpIHtcbiAgICAgICAgcmV0dXJuIGBpY2UtY2xpZW50LSR7cnRjQ29ubmVjdGlvbklkfWA7XG4gICAgfVxuICAgIGNyZWF0ZVByb3ZpZGVyRXZlbnROYW1lKHJ0Y0Nvbm5lY3Rpb25JZCkge1xuICAgICAgICByZXR1cm4gYGljZS1wcm92aWRlci0ke3J0Y0Nvbm5lY3Rpb25JZH1gO1xuICAgIH1cbiAgICBjcmVhdGVSb3V0ZVN0cmluZyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBgY2hhbm5lbC8ke25hbWV9YDtcbiAgICB9XG4gICAgY3JlYXRlUnRjUGVlcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5lbnZpcm9ubWVudC5nZXRSdGNQZWVyKCk7XG4gICAgfVxuICAgIGFzeW5jIHN0YXJ0Q2xpZW50T2ZmZXIoKSB7XG4gICAgICAgIC8vIFRPRE8gcmVwbGFjZSB3aXRoIHJlYWwgZ3VpZC5cbiAgICAgICAgY29uc3QgcnRjQ29ubmVjdGlvbklkID0gTWF0aC5yYW5kb20oKS50b1N0cmluZygpO1xuICAgICAgICBjb25zdCBydGNDbGllbnQgPSB0aGlzLmNyZWF0ZVJ0Y1BlZXIoKTtcbiAgICAgICAgcnRjQ2xpZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2ljZWNhbmRpZGF0ZScsIGFzeW5jIChlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZS5jYW5kaWRhdGUpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJhaXNlQ2xpZW50SWNlKHJ0Y0Nvbm5lY3Rpb25JZCwgeyBjYW5kaWRhdGU6IGUuY2FuZGlkYXRlPy50b0pTT04oKSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGF3YWl0IHRoaXMubGlzdGVuRm9yUHJvdmlkZXJJY2UocnRjQ29ubmVjdGlvbklkLCBhc3luYyAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgcnRjQ2xpZW50LmFkZEljZUNhbmRpZGF0ZShwYXlsb2FkLmNhbmRpZGF0ZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjaGFubmVscyA9IHtcbiAgICAgICAgICAgIHJlcXVlc3Q6IHJ0Y0NsaWVudC5jcmVhdGVEYXRhQ2hhbm5lbCgncmVxdWVzdCcpLFxuICAgICAgICAgICAgcmVzcG9uc2U6IHJ0Y0NsaWVudC5jcmVhdGVEYXRhQ2hhbm5lbCgncmVzcG9uc2UnKVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBvZmZlciA9IGF3YWl0IHJ0Y0NsaWVudC5jcmVhdGVPZmZlcigpO1xuICAgICAgICBhd2FpdCBydGNDbGllbnQuc2V0TG9jYWxEZXNjcmlwdGlvbihvZmZlcik7XG4gICAgICAgIGNvbnN0IGNoYW5uZWxzT3BlbmVkID0gUHJvbWlzZS5hbGwoW2NoYW5uZWxzLnJlcXVlc3QsIGNoYW5uZWxzLnJlc3BvbnNlXS5tYXAodGhpcy5lbnN1cmVDaGFubmVsT3BlbmVkKSkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgICByZXR1cm4geyBydGNDbGllbnQsIGNoYW5uZWxzLCBvZmZlciwgcnRjQ29ubmVjdGlvbklkLCBjaGFubmVsc09wZW5lZCB9O1xuICAgIH1cbiAgICBhc3luYyBmaW5pc2hDbGllbnRPZmZlcihydGNDbGllbnQsIGFuc3dlciwgcHJvdmlkZXJSZWFkeSkge1xuICAgICAgICBhd2FpdCBydGNDbGllbnQuc2V0UmVtb3RlRGVzY3JpcHRpb24oYW5zd2VyKTtcbiAgICAgICAgYXdhaXQgcHJvdmlkZXJSZWFkeTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGFzeW5jIGNyZWF0ZVByb3ZpZGVyQW5zd2VyKHJ0Y0Nvbm5lY3Rpb25JZCwgb2ZmZXIpIHtcbiAgICAgICAgY29uc3QgcnRjQ2xpZW50ID0gdGhpcy5jcmVhdGVSdGNQZWVyKCk7XG4gICAgICAgIGNvbnN0IHJlcXVlc3RDaGFubmVsUHJvbWlzZSA9IFJUQ0lDRU1hbmFnZXIuY3JlYXRlRGF0YUNoYW5uZWxQcm9taXNlKCdyZXF1ZXN0JywgcnRjQ2xpZW50KTtcbiAgICAgICAgY29uc3QgcmVzcG9uc2VDaGFubmVsUHJvbWlzZSA9IFJUQ0lDRU1hbmFnZXIuY3JlYXRlRGF0YUNoYW5uZWxQcm9taXNlKCdyZXNwb25zZScsIHJ0Y0NsaWVudCk7XG4gICAgICAgIHJ0Y0NsaWVudC5hZGRFdmVudExpc3RlbmVyKCdpY2VjYW5kaWRhdGUnLCBhc3luYyAoZSkgPT4ge1xuICAgICAgICAgICAgaWYgKGUuY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5yYWlzZVByb3ZpZGVySWNlKHJ0Y0Nvbm5lY3Rpb25JZCwgeyBjYW5kaWRhdGU6IGUuY2FuZGlkYXRlPy50b0pTT04oKSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGF3YWl0IHRoaXMubGlzdGVuRm9yQ2xpZW50SWNlKHJ0Y0Nvbm5lY3Rpb25JZCwgYXN5bmMgKHBheWxvYWQpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IHJ0Y0NsaWVudC5hZGRJY2VDYW5kaWRhdGUocGF5bG9hZC5jYW5kaWRhdGUpO1xuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgcnRjQ2xpZW50LnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKTtcbiAgICAgICAgY29uc3QgYW5zd2VyID0gYXdhaXQgcnRjQ2xpZW50LmNyZWF0ZUFuc3dlcigpO1xuICAgICAgICBhd2FpdCBydGNDbGllbnQuc2V0TG9jYWxEZXNjcmlwdGlvbihhbnN3ZXIpO1xuICAgICAgICBjb25zdCBjaGFubmVscyA9IFByb21pc2UuYWxsKFtyZXF1ZXN0Q2hhbm5lbFByb21pc2UsIHJlc3BvbnNlQ2hhbm5lbFByb21pc2VdKS50aGVuKChbcmVxdWVzdCwgcmVzcG9uc2VdKSA9PiB7XG4gICAgICAgICAgICAvLyBDbGVhbiB1cCBpY2UgZXZlbnRzLlxuICAgICAgICAgICAgdGhpcy5jbGVhbnVwSWNlTGlzdGVuZXJzKHJ0Y0Nvbm5lY3Rpb25JZCk7XG4gICAgICAgICAgICByZXR1cm4geyByZXF1ZXN0LCByZXNwb25zZSB9O1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJ0Y0NsaWVudCxcbiAgICAgICAgICAgIGFuc3dlcixcbiAgICAgICAgICAgIGNoYW5uZWxzXG4gICAgICAgIH07XG4gICAgfVxufVxuaWNlTWFuYWdlci5SVENJQ0VNYW5hZ2VyID0gUlRDSUNFTWFuYWdlcjtcblxudmFyIHByb3ZpZGVyID0ge307XG5cbnZhciBydW50aW1lVmVyc2lvbmluZyA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkocnVudGltZVZlcnNpb25pbmcsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xucnVudGltZVZlcnNpb25pbmcucnVudGltZVV1aWRNZWV0c01pbmltdW1SdW50aW1lVmVyc2lvbiA9IHJ1bnRpbWVWZXJzaW9uaW5nLnBhcnNlUnVudGltZVV1aWQgPSBydW50aW1lVmVyc2lvbmluZy5tZWV0c01pbmltdW1SdW50aW1lVmVyc2lvbiA9IHZvaWQgMDtcbmZ1bmN0aW9uIHZOdW0oeCkge1xuICAgIHJldHVybiBbLi4ueC5zcGxpdCgnLicpLnJldmVyc2UoKS5lbnRyaWVzKCldLnJlZHVjZSgocCwgW2ksIHZdKSA9PiBwICsgK3YgKiAxMDAwMCAqKiBpLCAwKTtcbn1cbi8qXG4gIENvbXBhcmVzIHJ1bnRpbWUgdmVyc2lvbnMgdG8gc2VlIGlmIHRoZSBjdXJyZW50IHJ1bnRpbWUgbWVldHMgeW91ciBkZXNpcmVkIG1pbmltdW0uXG4qL1xuZnVuY3Rpb24gbWVldHNNaW5pbXVtUnVudGltZVZlcnNpb24oY3VycmVudFZlcnNpb24sIG1pblZlcnNpb24pIHtcbiAgICBjb25zdCBjdXJyZW50VmVyc2lvblBhcnNlZCA9IHZOdW0oY3VycmVudFZlcnNpb24pO1xuICAgIGNvbnN0IG1pblZlcnNpb25QYXJzZWQgPSB2TnVtKG1pblZlcnNpb24pO1xuICAgIHJldHVybiBjdXJyZW50VmVyc2lvblBhcnNlZCA+PSBtaW5WZXJzaW9uUGFyc2VkO1xufVxucnVudGltZVZlcnNpb25pbmcubWVldHNNaW5pbXVtUnVudGltZVZlcnNpb24gPSBtZWV0c01pbmltdW1SdW50aW1lVmVyc2lvbjtcbi8vIFN0cmlwcyB0aGUgcG9ydCBpbmZvIGZyb20gdGhlIHJ1bnRpbWVVdWlkLCBsZWF2aW5nIGp1c3QgdGhlIHJ1bnRpbWUgdmVyc2lvbi5cbmZ1bmN0aW9uIHBhcnNlUnVudGltZVV1aWQocnVudGltZVV1aWQpIHtcbiAgICByZXR1cm4gcnVudGltZVV1aWQuc3BsaXQoJy8nKVswXTtcbn1cbnJ1bnRpbWVWZXJzaW9uaW5nLnBhcnNlUnVudGltZVV1aWQgPSBwYXJzZVJ1bnRpbWVVdWlkO1xuZnVuY3Rpb24gcnVudGltZVV1aWRNZWV0c01pbmltdW1SdW50aW1lVmVyc2lvbihydW50aW1lVXVpZCwgbWluVmVyc2lvbikge1xuICAgIGNvbnN0IHJ1bnRpbWVWZXJzaW9uID0gcGFyc2VSdW50aW1lVXVpZChydW50aW1lVXVpZCk7XG4gICAgcmV0dXJuIG1lZXRzTWluaW11bVJ1bnRpbWVWZXJzaW9uKHJ1bnRpbWVWZXJzaW9uLCBtaW5WZXJzaW9uKTtcbn1cbnJ1bnRpbWVWZXJzaW9uaW5nLnJ1bnRpbWVVdWlkTWVldHNNaW5pbXVtUnVudGltZVZlcnNpb24gPSBydW50aW1lVXVpZE1lZXRzTWluaW11bVJ1bnRpbWVWZXJzaW9uO1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ4ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcbn07XG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ2ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufTtcbnZhciBfQ2hhbm5lbFByb3ZpZGVyX2Nvbm5lY3Rpb25zLCBfQ2hhbm5lbFByb3ZpZGVyX3Byb3RlY3RlZE9iaiwgX0NoYW5uZWxQcm92aWRlcl9zdHJhdGVneSwgX0NoYW5uZWxQcm92aWRlcl9yZW1vdmVFbmRwb2ludCwgX0NoYW5uZWxQcm92aWRlcl9jbG9zZTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm92aWRlciwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5wcm92aWRlci5DaGFubmVsUHJvdmlkZXIgPSB2b2lkIDA7XG5jb25zdCBjaGFubmVsXzEgPSBjaGFubmVsO1xuY29uc3QgcnVudGltZVZlcnNpb25pbmdfMSA9IHJ1bnRpbWVWZXJzaW9uaW5nO1xuLyoqXG4gKiBJbnN0YW5jZSBjcmVhdGVkIHRvIGVuYWJsZSB1c2Ugb2YgYSBjaGFubmVsIGFzIGEgcHJvdmlkZXIuIEFsbG93cyBmb3IgY29tbXVuaWNhdGlvbiB3aXRoIHRoZSB7QGxpbmsgQ2hhbm5lbENsaWVudCBDaGFubmVsQ2xpZW50c30gYnkgaW52b2tpbmcgYW4gYWN0aW9uIG9uXG4gKiBhIHNpbmdsZSBjbGllbnQgdmlhIHtAbGluayBDaGFubmVsUHJvdmlkZXIjZGlzcGF0Y2ggZGlzcGF0Y2h9IG9yIGFsbCBjbGllbnRzIHZpYSB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI3B1Ymxpc2ggcHVibGlzaH1cbiAqIGFuZCB0byBsaXN0ZW4gZm9yIGNvbW11bmljYXRpb24gZnJvbSBjbGllbnRzIGJ5IHJlZ2lzdGVyaW5nIGFuIGFjdGlvbiB2aWEge0BsaW5rIENoYW5uZWxQcm92aWRlciNyZWdpc3RlciByZWdpc3Rlcn0uXG4gKlxuICogIyMjIFN5bmNocm9ub3VzIE1ldGhvZHM6XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI29uQ29ubmVjdGlvbiBvbkNvbm5lY3Rpb24obGlzdGVuZXIpfVxuICogICoge0BsaW5rIENoYW5uZWxQcm92aWRlciNvbkRpc2Nvbm5lY3Rpb24gb25EaXNjb25uZWN0aW9uKGxpc3RlbmVyKX1cbiAqICAqIHtAbGluayBDaGFubmVsUHJvdmlkZXIjcHVibGlzaCBwdWJsaXNoKGFjdGlvbiwgcGF5bG9hZCl9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI3JlZ2lzdGVyIHJlZ2lzdGVyKGFjdGlvbiwgbGlzdGVuZXIpfVxuICogICoge0BsaW5rIENoYW5uZWxQcm92aWRlciNyZW1vdmUgcmVtb3ZlKGFjdGlvbil9XG4gKlxuICogIyMjIEFzeW5jaHJvbm91cyBNZXRob2RzOlxuICogICoge0BsaW5rIENoYW5uZWxQcm92aWRlciNkZXN0cm95IGRlc3Ryb3koKX1cbiAqICAqIHtAbGluayBDaGFubmVsUHJvdmlkZXIjZGlzcGF0Y2ggZGlzcGF0Y2godG8sIGFjdGlvbiwgcGF5bG9hZCl9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI2dldEFsbENsaWVudEluZm8gZ2V0QWxsQ2xpZW50SW5mbygpfVxuICpcbiAqICMjIyBNaWRkbGV3YXJlOlxuICogTWlkZGxld2FyZSBmdW5jdGlvbnMgcmVjZWl2ZSB0aGUgZm9sbG93aW5nIGFyZ3VtZW50czogKGFjdGlvbiwgcGF5bG9hZCwgc2VuZGVySWQpLlxuICogVGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgbWlkZGxld2FyZSBmdW5jdGlvbiB3aWxsIGJlIHBhc3NlZCBvbiBhcyB0aGUgcGF5bG9hZCBmcm9tIGJlZm9yZUFjdGlvbiwgdG8gdGhlIGFjdGlvbiBsaXN0ZW5lciwgdG8gYWZ0ZXJBY3Rpb25cbiAqIHVubGVzcyBpdCBpcyB1bmRlZmluZWQsIGluIHdoaWNoIGNhc2UgdGhlIG1vc3QgcmVjZW50bHkgZGVmaW5lZCBwYXlsb2FkIGlzIHVzZWQuICBNaWRkbGV3YXJlIGNhbiBiZSB1c2VkIGZvciBzaWRlIGVmZmVjdHMuXG4gKiAgKiB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyI3NldERlZmF1bHRBY3Rpb24gc2V0RGVmYXVsdEFjdGlvbihtaWRkbGV3YXJlKX1cbiAqICAqIHtAbGluayBDaGFubmVsUHJvdmlkZXIjb25FcnJvciBvbkVycm9yKG1pZGRsZXdhcmUpfVxuICogICoge0BsaW5rIENoYW5uZWxQcm92aWRlciNiZWZvcmVBY3Rpb24gYmVmb3JlQWN0aW9uKG1pZGRsZXdhcmUpfVxuICogICoge0BsaW5rIENoYW5uZWxQcm92aWRlciNhZnRlckFjdGlvbiBhZnRlckFjdGlvbihtaWRkbGV3YXJlKX1cbiAqL1xuY2xhc3MgQ2hhbm5lbFByb3ZpZGVyIGV4dGVuZHMgY2hhbm5lbF8xLkNoYW5uZWxCYXNlIHtcbiAgICAvKipcbiAgICAgKiBhIHJlYWQtb25seSBhcnJheSBjb250YWluaW5nIGFsbCB0aGUgaWRlbnRpdGllcyBvZiBjb25uZWN0aW5nIGNsaWVudHMuXG4gICAgICovXG4gICAgZ2V0IGNvbm5lY3Rpb25zKCkge1xuICAgICAgICByZXR1cm4gWy4uLl9fY2xhc3NQcml2YXRlRmllbGRHZXQkOCh0aGlzLCBfQ2hhbm5lbFByb3ZpZGVyX2Nvbm5lY3Rpb25zLCBcImZcIildO1xuICAgIH1cbiAgICBzdGF0aWMgaGFuZGxlQ2xpZW50RGlzY29ubmVjdGlvbihjaGFubmVsLCBwYXlsb2FkKSB7XG4gICAgICAgIGNvbnN0IHJlbW92ZUJ5SWQgPSBjaGFubmVsLmNvbm5lY3Rpb25zLmZpbmQoKGlkZW50aXR5KSA9PiBpZGVudGl0eS5lbmRwb2ludElkID09PSBwYXlsb2FkLmVuZHBvaW50SWQpO1xuICAgICAgICBpZiAocmVtb3ZlQnlJZCkge1xuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ4KGNoYW5uZWwsIF9DaGFubmVsUHJvdmlkZXJfcmVtb3ZlRW5kcG9pbnQsIFwiZlwiKS5jYWxsKGNoYW5uZWwsIHJlbW92ZUJ5SWQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgbXVsdGlwbGVSZW1vdmVzID0gY2hhbm5lbC5jb25uZWN0aW9ucy5maWx0ZXIoKGlkZW50aXR5KSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlkZW50aXR5LnV1aWQgPT09IHBheWxvYWQudXVpZCAmJiBpZGVudGl0eS5uYW1lID09PSBwYXlsb2FkLm5hbWU7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIG11bHRpcGxlUmVtb3Zlcy5mb3JFYWNoKF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOChjaGFubmVsLCBfQ2hhbm5lbFByb3ZpZGVyX3JlbW92ZUVuZHBvaW50LCBcImZcIikpO1xuICAgICAgICB9XG4gICAgICAgIGNoYW5uZWwuZGlzY29ubmVjdExpc3RlbmVyKHBheWxvYWQpO1xuICAgIH1cbiAgICBzdGF0aWMgc2V0UHJvdmlkZXJSZW1vdmFsKHByb3ZpZGVyLCByZW1vdmUpIHtcbiAgICAgICAgQ2hhbm5lbFByb3ZpZGVyLnJlbW92YWxNYXAuc2V0KHByb3ZpZGVyLCByZW1vdmUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcm92aWRlcklkZW50aXR5LCBjbG9zZSwgc3RyYXRlZ3kpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgX0NoYW5uZWxQcm92aWRlcl9jb25uZWN0aW9ucy5zZXQodGhpcywgdm9pZCAwKTtcbiAgICAgICAgX0NoYW5uZWxQcm92aWRlcl9wcm90ZWN0ZWRPYmouc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIF9DaGFubmVsUHJvdmlkZXJfc3RyYXRlZ3kuc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIF9DaGFubmVsUHJvdmlkZXJfcmVtb3ZlRW5kcG9pbnQuc2V0KHRoaXMsIChpZGVudGl0eSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVtYWluaW5nQ29ubmVjdGlvbnMgPSB0aGlzLmNvbm5lY3Rpb25zLmZpbHRlcigoY2xpZW50SWRlbnRpdHkpID0+IGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQgIT09IGlkZW50aXR5LmVuZHBvaW50SWQpO1xuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ4KHRoaXMsIF9DaGFubmVsUHJvdmlkZXJfc3RyYXRlZ3ksIFwiZlwiKS5jbG9zZUVuZHBvaW50KGlkZW50aXR5LmVuZHBvaW50SWQpO1xuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ2KHRoaXMsIF9DaGFubmVsUHJvdmlkZXJfY29ubmVjdGlvbnMsIHJlbWFpbmluZ0Nvbm5lY3Rpb25zLCBcImZcIik7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBNdXN0IGJlIGJvdW5kLlxuICAgICAgICB0aGlzLnByb2Nlc3NBY3Rpb24gPSBhc3luYyAoYWN0aW9uLCBwYXlsb2FkLCBzZW5kZXJJZGVudGl0eSkgPT4ge1xuICAgICAgICAgICAgaWYgKENoYW5uZWxQcm92aWRlci5jbGllbnRJc011bHRpUnVudGltZShzZW5kZXJJZGVudGl0eSkgJiZcbiAgICAgICAgICAgICAgICAhKDAsIHJ1bnRpbWVWZXJzaW9uaW5nXzEucnVudGltZVV1aWRNZWV0c01pbmltdW1SdW50aW1lVmVyc2lvbikoc2VuZGVySWRlbnRpdHkucnVudGltZVV1aWQsICcxOC44Ny41Ni4wJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZU11bHRpUnVudGltZUxlZ2FjeUNsaWVudChzZW5kZXJJZGVudGl0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNoZWNrRm9yQ2xpZW50Q29ubmVjdGlvbihzZW5kZXJJZGVudGl0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3VwZXIucHJvY2Vzc0FjdGlvbihhY3Rpb24sIHBheWxvYWQsIHNlbmRlcklkZW50aXR5KTtcbiAgICAgICAgfTtcbiAgICAgICAgX0NoYW5uZWxQcm92aWRlcl9jbG9zZS5zZXQodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ4KHRoaXMsIF9DaGFubmVsUHJvdmlkZXJfc3RyYXRlZ3ksIFwiZlwiKS5jbG9zZSgpO1xuICAgICAgICAgICAgY29uc3QgcmVtb3ZlID0gQ2hhbm5lbFByb3ZpZGVyLnJlbW92YWxNYXAuZ2V0KHRoaXMpO1xuICAgICAgICAgICAgaWYgKHJlbW92ZSkge1xuICAgICAgICAgICAgICAgIHJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ2KHRoaXMsIF9DaGFubmVsUHJvdmlkZXJfcHJvdGVjdGVkT2JqLCBuZXcgY2hhbm5lbF8xLlByb3RlY3RlZEl0ZW1zKHByb3ZpZGVySWRlbnRpdHksIGNsb3NlKSwgXCJmXCIpO1xuICAgICAgICB0aGlzLmNvbm5lY3RMaXN0ZW5lciA9ICgpID0+IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0TGlzdGVuZXIgPSAoKSA9PiB1bmRlZmluZWQ7XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkNih0aGlzLCBfQ2hhbm5lbFByb3ZpZGVyX2Nvbm5lY3Rpb25zLCBbXSwgXCJmXCIpO1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDYodGhpcywgX0NoYW5uZWxQcm92aWRlcl9zdHJhdGVneSwgc3RyYXRlZ3ksIFwiZlwiKTtcbiAgICAgICAgc3RyYXRlZ3kucmVjZWl2ZSh0aGlzLnByb2Nlc3NBY3Rpb24pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBEaXNwYXRjaCBhbiBhY3Rpb24gdG8gYSBzcGVjaWZpZWQgY2xpZW50LiBSZXR1cm5zIGEgcHJvbWlzZSBmb3IgdGhlIHJlc3VsdCBvZiBleGVjdXRpbmcgdGhhdCBhY3Rpb24gb24gdGhlIGNsaWVudCBzaWRlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHRvIC0gSWRlbnRpdHkgb2YgdGhlIHRhcmdldCBjbGllbnQuXG4gICAgICogQHBhcmFtIGFjdGlvbiAtIE5hbWUgb2YgdGhlIGFjdGlvbiB0byBiZSBpbnZva2VkIGJ5IHRoZSBjbGllbnQuXG4gICAgICogQHBhcmFtIHBheWxvYWQgLSBQYXlsb2FkIHRvIGJlIHNlbnQgYWxvbmcgd2l0aCB0aGUgYWN0aW9uLlxuICAgICAqXG4gICAgICogQHJlbWFya3NcbiAgICAgKlxuICAgICAqIEJlY2F1c2UgbXVsdGlwbGUgY2xpZW50cyBjYW4gc2hhcmUgdGhlIHNhbWUgYG5hbWVgIGFuZCBgdXVpZGAsIHdoZW4gZGlzcGF0Y2hpbmcgZnJvbSBhIHByb3ZpZGVyIHRvIGEgY2xpZW50LFxuICAgICAqIHRoZSBgaWRlbnRpdHlgIHlvdSBwcm92aWRlIG11c3QgaW5jbHVkZSB0aGUgY2xpZW50J3MgdW5pcXVlIGBlbmRwb2ludElkYCBwcm9wZXJ0eS4gVGhpcyBgZW5kcG9pbnRJZGAgaXNcbiAgICAgKiBwYXNzZWQgdG8gdGhlIHByb3ZpZGVyIGluIGJvdGggdGhlIGBQcm92aWRlci5vbkNvbm5lY3Rpb25gIGNhbGxiYWNrIGFuZCBpbiBhbnkgcmVnaXN0ZXJlZCBhY3Rpb24gY2FsbGJhY2tzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBwcm92aWRlciA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY3JlYXRlKCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHByb3ZpZGVyLnJlZ2lzdGVyKCdwcm92aWRlci1hY3Rpb24nLCBhc3luYyAocGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKHBheWxvYWQsIGlkZW50aXR5KTtcbiAgICAgKiAgICAgICAgIHJldHVybiBhd2FpdCBwcm92aWRlci5kaXNwYXRjaChpZGVudGl0eSwgJ2NsaWVudC1hY3Rpb24nLCAnSGVsbG8sIFdvcmxkIScpO1xuICAgICAqICAgICB9KTtcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGRpc3BhdGNoKHRvLCBhY3Rpb24sIHBheWxvYWQpIHtcbiAgICAgICAgY29uc3QgZW5kcG9pbnRJZCA9IHRvLmVuZHBvaW50SWQgPz8gdGhpcy5nZXRFbmRwb2ludElkRm9yT3BlbkZpbklkKHRvLCBhY3Rpb24pO1xuICAgICAgICBpZiAoZW5kcG9pbnRJZCAmJiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDgodGhpcywgX0NoYW5uZWxQcm92aWRlcl9zdHJhdGVneSwgXCJmXCIpLmlzRW5kcG9pbnRDb25uZWN0ZWQoZW5kcG9pbnRJZCkpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDgodGhpcywgX0NoYW5uZWxQcm92aWRlcl9zdHJhdGVneSwgXCJmXCIpLnNlbmQoZW5kcG9pbnRJZCwgYWN0aW9uLCBwYXlsb2FkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKGBDbGllbnQgY29ubmVjdGlvbiB3aXRoIGlkZW50aXR5IHV1aWQ6ICR7dG8udXVpZH0gLyBuYW1lOiAke3RvLm5hbWV9IC8gZW5kcG9pbnRJZDogJHtlbmRwb2ludElkfSBubyBsb25nZXIgY29ubmVjdGVkLmApKTtcbiAgICB9XG4gICAgYXN5bmMgcHJvY2Vzc0Nvbm5lY3Rpb24oc2VuZGVySWQsIHBheWxvYWQpIHtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ4KHRoaXMsIF9DaGFubmVsUHJvdmlkZXJfY29ubmVjdGlvbnMsIFwiZlwiKS5wdXNoKHNlbmRlcklkKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdExpc3RlbmVyKHNlbmRlcklkLCBwYXlsb2FkKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUHVibGlzaCBhbiBhY3Rpb24gYW5kIHBheWxvYWQgdG8gZXZlcnkgY29ubmVjdGVkIGNsaWVudC5cbiAgICAgKiBTeW5jaHJvbm91c2x5IHJldHVybnMgYW4gYXJyYXkgb2YgcHJvbWlzZXMgZm9yIGVhY2ggYWN0aW9uIChzZWUgZGlzcGF0Y2gpLlxuICAgICAqXG4gICAgICogQHBhcmFtIGFjdGlvblxuICAgICAqIEBwYXJhbSBwYXlsb2FkXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBwcm92aWRlciA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY3JlYXRlKCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHByb3ZpZGVyLnJlZ2lzdGVyKCdwcm92aWRlci1hY3Rpb24nLCBhc3luYyAocGF5bG9hZCwgaWRlbnRpdHkpID0+IHtcbiAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKHBheWxvYWQsIGlkZW50aXR5KTtcbiAgICAgKiAgICAgICAgIHJldHVybiBhd2FpdCBQcm9taXNlLmFsbChwcm92aWRlci5wdWJsaXNoKCdjbGllbnQtYWN0aW9uJywgeyBtZXNzYWdlOiAnQnJvYWRjYXN0IGZyb20gcHJvdmlkZXInfSkpO1xuICAgICAqICAgICB9KTtcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHB1Ymxpc2goYWN0aW9uLCBwYXlsb2FkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb25zLm1hcCgodG8pID0+IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOCh0aGlzLCBfQ2hhbm5lbFByb3ZpZGVyX3N0cmF0ZWd5LCBcImZcIikuc2VuZCh0by5lbmRwb2ludElkLCBhY3Rpb24sIHBheWxvYWQpKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYSBsaXN0ZW5lciB0aGF0IGlzIGNhbGxlZCBvbiBldmVyeSBuZXcgY2xpZW50IGNvbm5lY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBJdCBpcyBwYXNzZWQgdGhlIGlkZW50aXR5IG9mIHRoZSBjb25uZWN0aW5nIGNsaWVudCBhbmQgYSBwYXlsb2FkIGlmIGl0IHdhcyBwcm92aWRlZCB0byBDaGFubmVsLmNvbm5lY3QuXG4gICAgICogSWYgeW91IHdpc2ggdG8gcmVqZWN0IHRoZSBjb25uZWN0aW9uLCB0aHJvdyBhbiBlcnJvci4gQmUgc3VyZSB0byBzeW5jaHJvbm91c2x5IHByb3ZpZGUgYW4gb25Db25uZWN0aW9uIHVwb24gcmVjZWlwdCBvZlxuICAgICAqIHRoZSBjaGFubmVsUHJvdmlkZXIgdG8gZW5zdXJlIGFsbCBwb3RlbnRpYWwgY2xpZW50IGNvbm5lY3Rpb25zIGFyZSBjYXVnaHQgYnkgdGhlIGxpc3RlbmVyLlxuICAgICAqXG4gICAgICogQmVjYXVzZSBtdWx0aXBsZSBjbGllbnRzIGNhbiBleGlzdCBhdCB0aGUgc2FtZSBgbmFtZWAgYW5kIGB1dWlkYCwgaW4gb3JkZXIgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiBpbmRpdmlkdWFsIGNsaWVudHMsXG4gICAgICogdGhlIGBpZGVudGl0eWAgYXJndW1lbnQgaW4gYSBwcm92aWRlcidzIGBvbkNvbm5lY3Rpb25gIGNhbGxiYWNrIGNvbnRhaW5zIGFuIGBlbmRwb2ludElkYCBwcm9wZXJ0eS4gV2hlbiBkaXNwYXRjaGluZyBmcm9tIGFcbiAgICAgKiBwcm92aWRlciB0byBhIGNsaWVudCwgdGhlIGBlbmRwb2ludElkYCBwcm9wZXJ0eSBtdXN0IGJlIHByb3ZpZGVkIGluIG9yZGVyIHRvIHNlbmQgYW4gYWN0aW9uIHRvIGEgc3BlY2lmaWMgY2xpZW50LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZSgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgICBwcm92aWRlci5vbkNvbm5lY3Rpb24oaWRlbnRpdHkgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ0NsaWVudCBjb25uZWN0ZWQnLCBpZGVudGl0eSk7XG4gICAgICogICAgIH0pO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBSZWplY3QgY29ubmVjdGlvbjpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZSgnY2hhbm5lbE5hbWUnKTtcbiAgICAgKlxuICAgICAqICAgICBwcm92aWRlci5vbkNvbm5lY3Rpb24oaWRlbnRpdHkgPT4ge1xuICAgICAqICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb25uZWN0aW9uIFJlamVjdGVkJyk7XG4gICAgICogICAgIH0pO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICogQHBhcmFtIGxpc3RlbmVyXG4gICAgICovXG4gICAgb25Db25uZWN0aW9uKGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMuY29ubmVjdExpc3RlbmVyID0gbGlzdGVuZXI7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIGEgbGlzdGVuZXIgdGhhdCBpcyBjYWxsZWQgb24gY2xpZW50IGRpc2Nvbm5lY3Rpb24uIEl0IGlzIHBhc3NlZCB0aGUgZGlzY29ubmVjdGlvbiBldmVudCBvZiB0aGUgZGlzY29ubmVjdGluZ1xuICAgICAqIGNsaWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBsaXN0ZW5lclxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogKGFzeW5jICgpPT4ge1xuICAgICAqICAgICBjb25zdCBwcm92aWRlciA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY3JlYXRlKCdjaGFubmVsTmFtZScpO1xuICAgICAqXG4gICAgICogICAgIGF3YWl0IHByb3ZpZGVyLm9uRGlzY29ubmVjdGlvbihldnQgPT4ge1xuICAgICAqICAgICAgICAgY29uc29sZS5sb2coJ0NsaWVudCBkaXNjb25uZWN0ZWQnLCBgdXVpZDogJHtldnQudXVpZH0sIG5hbWU6ICR7ZXZ0Lm5hbWV9YCk7XG4gICAgICogICAgIH0pO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgb25EaXNjb25uZWN0aW9uKGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMuZGlzY29ubmVjdExpc3RlbmVyID0gbGlzdGVuZXI7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIERlc3Ryb3kgdGhlIGNoYW5uZWwsIHJhaXNlcyBgZGlzY29ubmVjdGVkYCBldmVudHMgb24gYWxsIGNvbm5lY3RlZCBjaGFubmVsIGNsaWVudHMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAoYXN5bmMgKCk9PiB7XG4gICAgICogICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICAgYXdhaXQgcHJvdmlkZXIuZGVzdHJveSgpO1xuICAgICAqIH0pKCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZGVzdHJveSgpIHtcbiAgICAgICAgY29uc3QgcHJvdGVjdGVkT2JqID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ4KHRoaXMsIF9DaGFubmVsUHJvdmlkZXJfcHJvdGVjdGVkT2JqLCBcImZcIik7XG4gICAgICAgIHByb3RlY3RlZE9iai5wcm92aWRlcklkZW50aXR5O1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDYodGhpcywgX0NoYW5uZWxQcm92aWRlcl9jb25uZWN0aW9ucywgW10sIFwiZlwiKTtcbiAgICAgICAgYXdhaXQgcHJvdGVjdGVkT2JqLmNsb3NlKCk7XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkOCh0aGlzLCBfQ2hhbm5lbFByb3ZpZGVyX2Nsb3NlLCBcImZcIikuY2FsbCh0aGlzKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhbiBhcnJheSB3aXRoIGluZm8gb24gZXZlcnkgQ2xpZW50IGNvbm5lY3RlZCB0byB0aGUgUHJvdmlkZXJcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ29wZW5maW4nKTtcbiAgICAgKiBjb25zdCBjbGllbnQgPSBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3QoJ29wZW5maW4nKTtcbiAgICAgKiBjb25zdCBjbGllbnRJbmZvID0gYXdhaXQgcHJvdmlkZXIuZ2V0QWxsQ2xpZW50SW5mbygpO1xuICAgICAqXG4gICAgICogY29uc29sZS5sb2coY2xpZW50SW5mbyk7XG4gICAgICpcbiAgICAgKiAvLyBbXG4gICAgICogLy8gICAge1xuICAgICAqIC8vICAgICAgICBcInV1aWRcIjogXCJvcGVuZmluXCIsXG4gICAgICogLy8gICAgICAgIFwibmFtZVwiOiBcIm9wZW5maW4tdmlld1wiLFxuICAgICAqIC8vICAgICAgICBcImVuZHBvaW50SWRcIjogXCI2ZDRjN2NhOC00YTc0LTQ2MzQtODdmOC03NjA1NTgyMjk2MTNcIixcbiAgICAgKiAvLyAgICAgICAgXCJlbnRpdHlUeXBlXCI6IFwidmlld1wiLFxuICAgICAqIC8vICAgICAgICBcInVybFwiOiBcImh0dHBzOi8vb3BlbmZpbi5jb1wiXG4gICAgICogLy8gICAgfSxcbiAgICAgKiAvLyAgICB7XG4gICAgICogLy8gICAgICAgIFwidXVpZFwiOiBcIm9wZW5maW4yXCIsXG4gICAgICogLy8gICAgICAgIFwibmFtZVwiOiBcIm9wZW5maW4tdmlldzJcIixcbiAgICAgKiAvLyAgICAgICAgXCJlbmRwb2ludElkXCI6IFwiNHo1ZDhhYjktMmI4MS0zNjkxLTkxZXgtMTQyMTc5MzgyNTExXCIsXG4gICAgICogLy8gICAgICAgIFwiZW50aXR5VHlwZVwiOiBcInZpZXdcIixcbiAgICAgKiAvLyAgICAgICAgXCJ1cmxcIjogXCJodHRwczovL2V4YW1wbGUuY29tXCJcbiAgICAgKiAvLyAgICB9XG4gICAgICogLy9dXG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QWxsQ2xpZW50SW5mbygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvbnMubWFwKChjbGllbnRJbmZvKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUsIGVuZHBvaW50SWQsIGVudGl0eVR5cGUsIGNvbm5lY3Rpb25VcmwgfSA9IGNsaWVudEluZm87XG4gICAgICAgICAgICByZXR1cm4geyB1dWlkLCBuYW1lLCBlbmRwb2ludElkLCBlbnRpdHlUeXBlLCBjb25uZWN0aW9uVXJsIH07XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBjaGVja0ZvckNsaWVudENvbm5lY3Rpb24oY2xpZW50SWRlbnRpdHkpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzQ2xpZW50Q29ubmVjdGVkKGNsaWVudElkZW50aXR5KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGlzIGFjdGlvbiB3YXMgc2VudCBmcm9tIGEgY2xpZW50IHRoYXQgaXMgbm90IGNvbm5lY3RlZCB0byB0aGUgcHJvdmlkZXIuXG4gICAgICAgICAgICAgICAgICAgIENsaWVudCBJZGVudGl0eToge3V1aWQ6ICR7Y2xpZW50SWRlbnRpdHkudXVpZH0sIG5hbWU6ICR7Y2xpZW50SWRlbnRpdHkubmFtZX0sIGVuZHBvaW50SWQ6ICR7Y2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZH19YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaXNDbGllbnRDb25uZWN0ZWQoY2xpZW50SWRlbnRpdHkpIHtcbiAgICAgICAgaWYgKENoYW5uZWxQcm92aWRlci5jbGllbnRJZGVudGl0eUluY2x1ZGVzRW5kcG9pbnRJZChjbGllbnRJZGVudGl0eSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb25zLnNvbWUoKGlkZW50aXR5KSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAvLyBNaWdodCBiZSByZWR1bmRhbnQgdG8gY2hlY2sgZm9yIHV1aWQgYW5kIG5hbWUgaGVyZSBhZnRlciB3ZSBnZXQgYW4gZW5kcG9pbnRJZCBtYXRjaCwgYnV0IGp1c3QgaW4gY2FzZVxuICAgICAgICAgICAgICAgIGlkZW50aXR5LmVuZHBvaW50SWQgPT09IGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQgJiZcbiAgICAgICAgICAgICAgICAgICAgaWRlbnRpdHkudXVpZCA9PT0gY2xpZW50SWRlbnRpdHkudXVpZCAmJlxuICAgICAgICAgICAgICAgICAgICBpZGVudGl0eS5uYW1lID09PSBjbGllbnRJZGVudGl0eS5uYW1lKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmlzTGVnYWN5Q2xpZW50Q29ubmVjdGVkKGNsaWVudElkZW50aXR5KTtcbiAgICB9XG4gICAgaXNMZWdhY3lDbGllbnRDb25uZWN0ZWQoY2xpZW50SWRlbnRpdHkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvbnMuc29tZSgoaWRlbnRpdHkpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBpZGVudGl0eS51dWlkID09PSBjbGllbnRJZGVudGl0eS51dWlkICYmIGlkZW50aXR5Lm5hbWUgPT09IGNsaWVudElkZW50aXR5Lm5hbWU7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBoYW5kbGVNdWx0aVJ1bnRpbWVMZWdhY3lDbGllbnQoc2VuZGVySWRlbnRpdHkpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzTGVnYWN5Q2xpZW50Q29ubmVjdGVkKHNlbmRlcklkZW50aXR5KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGlzIGFjdGlvbiB3YXMgc2VudCBmcm9tIGEgY2xpZW50IHRoYXQgaXMgbm90IGNvbm5lY3RlZCB0byB0aGUgcHJvdmlkZXIuIENsaWVudCBJZGVudGl0eTpcbiAgICAgICAgICAgICAgICAgICAge3V1aWQ6ICR7c2VuZGVySWRlbnRpdHkudXVpZH0sIG5hbWU6ICR7c2VuZGVySWRlbnRpdHkubmFtZX0sIGVuZHBvaW50SWQ6ICR7c2VuZGVySWRlbnRpdHkuZW5kcG9pbnRJZH19YCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZ2V0RW5kcG9pbnRJZEZvck9wZW5GaW5JZChjbGllbnRJZGVudGl0eSwgYWN0aW9uKSB7XG4gICAgICAgIGNvbnN0IG1hdGNoaW5nQ29ubmVjdGlvbnMgPSB0aGlzLmNvbm5lY3Rpb25zLmZpbHRlcigoYykgPT4gYy5uYW1lID09PSBjbGllbnRJZGVudGl0eS5uYW1lICYmIGMudXVpZCA9PT0gY2xpZW50SWRlbnRpdHkudXVpZCk7XG4gICAgICAgIGlmIChtYXRjaGluZ0Nvbm5lY3Rpb25zLmxlbmd0aCA+PSAyKSB7XG4gICAgICAgICAgICBjb25zdCBwcm90ZWN0ZWRPYmogPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDgodGhpcywgX0NoYW5uZWxQcm92aWRlcl9wcm90ZWN0ZWRPYmosIFwiZlwiKTtcbiAgICAgICAgICAgIGNvbnN0IHsgdXVpZCwgbmFtZSB9ID0gY2xpZW50SWRlbnRpdHk7XG4gICAgICAgICAgICBjb25zdCBwcm92aWRlclV1aWQgPSBwcm90ZWN0ZWRPYmo/LnByb3ZpZGVySWRlbnRpdHkudXVpZDtcbiAgICAgICAgICAgIGNvbnN0IHByb3ZpZGVyTmFtZSA9IHByb3RlY3RlZE9iaj8ucHJvdmlkZXJJZGVudGl0eS5uYW1lO1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgV0FSTklORzogRGlzcGF0Y2ggY2FsbCBtYXkgaGF2ZSB1bmludGVuZGVkIHJlc3VsdHMuIFRoZSBcInRvXCIgYXJndW1lbnQgb2YgeW91ciBkaXNwYXRjaCBjYWxsIGlzIG1pc3NpbmcgdGhlXG4gICAgICAgICAgICAgICAgXCJlbmRwb2ludElkXCIgcGFyYW1ldGVyLiBUaGUgaWRlbnRpdHkgeW91IGFyZSBkaXNwYXRjaGluZyB0byAoe3V1aWQ6ICR7dXVpZH0sIG5hbWU6ICR7bmFtZX19KVxuICAgICAgICAgICAgICAgIGhhcyBtdWx0aXBsZSBjaGFubmVsQ2xpZW50cyBmb3IgdGhpcyBjaGFubmVsLiBZb3VyIGRpc3BhdGNoZWQgYWN0aW9uOiAoJHthY3Rpb259KSBmcm9tIHRoZSBwcm92aWRlcjpcbiAgICAgICAgICAgICAgICAoe3V1aWQ6ICR7cHJvdmlkZXJVdWlkfSwgbmFtZTogJHtwcm92aWRlck5hbWV9fSkgd2lsbCBvbmx5IGJlIHByb2Nlc3NlZCBieSB0aGUgbW9zdCByZWNlbnRseS1jcmVhdGVkIGNsaWVudC5gKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBQb3AgdG8gcmV0dXJuIHRoZSBtb3N0IHJlY2VudGx5IGNyZWF0ZWQgZW5kcG9pbnRJZC5cbiAgICAgICAgcmV0dXJuIG1hdGNoaW5nQ29ubmVjdGlvbnMucG9wKCk/LmVuZHBvaW50SWQ7XG4gICAgfVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG4gICAgc3RhdGljIGNsaWVudElkZW50aXR5SW5jbHVkZXNFbmRwb2ludElkKHN1YnNjcmlwdGlvbklkZW50aXR5KSB7XG4gICAgICAgIHJldHVybiBzdWJzY3JpcHRpb25JZGVudGl0eS5lbmRwb2ludElkICE9PSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG4gICAgc3RhdGljIGNsaWVudElzTXVsdGlSdW50aW1lKHN1YnNjcmlwdGlvbklkZW50aXR5KSB7XG4gICAgICAgIHJldHVybiBzdWJzY3JpcHRpb25JZGVudGl0eS5ydW50aW1lVXVpZCAhPT0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBzdGF0aWMgYXN5bmMgd2lyZUNsb3NlKHdpcmUsIGNoYW5uZWxOYW1lKSB7XG4gICAgICAgIGF3YWl0IHdpcmUuc2VuZEFjdGlvbignZGVzdHJveS1jaGFubmVsJywgeyBjaGFubmVsTmFtZSB9KTtcbiAgICB9XG59XG5wcm92aWRlci5DaGFubmVsUHJvdmlkZXIgPSBDaGFubmVsUHJvdmlkZXI7XG5fQ2hhbm5lbFByb3ZpZGVyX2Nvbm5lY3Rpb25zID0gbmV3IFdlYWtNYXAoKSwgX0NoYW5uZWxQcm92aWRlcl9wcm90ZWN0ZWRPYmogPSBuZXcgV2Vha01hcCgpLCBfQ2hhbm5lbFByb3ZpZGVyX3N0cmF0ZWd5ID0gbmV3IFdlYWtNYXAoKSwgX0NoYW5uZWxQcm92aWRlcl9yZW1vdmVFbmRwb2ludCA9IG5ldyBXZWFrTWFwKCksIF9DaGFubmVsUHJvdmlkZXJfY2xvc2UgPSBuZXcgV2Vha01hcCgpO1xuLy8gVGhlIGZvbGxvd2luZyBsaW5lIHNob3VsZCBiZSBjaGFuZ2VkIGZvbGxvd2luZyBhIHR5cGVzY3JpcHQgdXBkYXRlLlxuLy8gc3RhdGljICNyZW1vdmFsTWFwID0gbmV3IFdlYWtNYXA8Q2hhbm5lbFByb3ZpZGVyLCBGdW5jdGlvbj4oKTtcbkNoYW5uZWxQcm92aWRlci5yZW1vdmFsTWFwID0gbmV3IFdlYWtNYXAoKTtcblxudmFyIG1lc3NhZ2VSZWNlaXZlciA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkobWVzc2FnZVJlY2VpdmVyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbm1lc3NhZ2VSZWNlaXZlci5NZXNzYWdlUmVjZWl2ZXIgPSB2b2lkIDA7XG5jb25zdCBjbGllbnRfMSQxID0gY2xpZW50O1xuY29uc3QgYmFzZV8xJGcgPSBiYXNlO1xuLypcblRoaXMgaXMgYSBzaW5nbGV0b24gKHBlciBmaW4gb2JqZWN0KSB0YXNrZWQgd2l0aCByb3V0aW5nIG1lc3NhZ2VzIGNvbWluZyBvZmYgdGhlIGlwYyB0byB0aGUgY29ycmVjdCBlbmRwb2ludC5cbkl0IG5lZWRzIHRvIGJlIGEgc2luZ2xldG9uIGJlY2F1c2UgdGhlcmUgY2FuIG9ubHkgYmUgb25lIHBlciB3aXJlLiBJdCB0cmFja3MgYm90aCBjbGllbnRzIGFuZCBwcm92aWRlcnMnIHByb2Nlc3NBY3Rpb24gcGFzc2VkIGluIHZpYSB0aGUgc3RyYXRlZ3kuXG5JZiBmdW5jdGlvbmFsaXR5IGlzIG5vdCBhYm91dCByZWNlaXZpbmcgbWVzc2FnZXMsIGl0IGRvZXMgbm90IGJlbG9uZyBoZXJlLlxuKi9cbmNsYXNzIE1lc3NhZ2VSZWNlaXZlciBleHRlbmRzIGJhc2VfMSRnLkJhc2Uge1xuICAgIGNvbnN0cnVjdG9yKHdpcmUpIHtcbiAgICAgICAgc3VwZXIod2lyZSk7XG4gICAgICAgIHRoaXMub25tZXNzYWdlID0gKG1zZykgPT4ge1xuICAgICAgICAgICAgaWYgKG1zZy5hY3Rpb24gPT09ICdwcm9jZXNzLWNoYW5uZWwtbWVzc2FnZScpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NDaGFubmVsTWVzc2FnZShtc2cpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmVuZHBvaW50TWFwID0gbmV3IE1hcCgpO1xuICAgICAgICB0aGlzLmxhdGVzdEVuZHBvaW50SWRCeUNoYW5uZWxJZCA9IG5ldyBNYXAoKTtcbiAgICAgICAgd2lyZS5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKHRoaXMub25tZXNzYWdlLmJpbmQodGhpcykpO1xuICAgIH1cbiAgICBhc3luYyBwcm9jZXNzQ2hhbm5lbE1lc3NhZ2UobXNnKSB7XG4gICAgICAgIGNvbnN0IHsgc2VuZGVySWRlbnRpdHksIHByb3ZpZGVySWRlbnRpdHksIGFjdGlvbiwgYWNrVG9TZW5kZXIsIHBheWxvYWQsIGludGVuZGVkVGFyZ2V0SWRlbnRpdHkgfSA9IG1zZy5wYXlsb2FkO1xuICAgICAgICBjb25zdCBrZXkgPSBpbnRlbmRlZFRhcmdldElkZW50aXR5LmNoYW5uZWxJZCA/PyAvLyBUaGUgcmVjaXBpZW50IGlzIGEgcHJvdmlkZXJcbiAgICAgICAgICAgIGludGVuZGVkVGFyZ2V0SWRlbnRpdHkuZW5kcG9pbnRJZCA/PyAvLyBUaGUgcmVjaXBpZW50IGlzIGEgY2xpZW50XG4gICAgICAgICAgICB0aGlzLmxhdGVzdEVuZHBvaW50SWRCeUNoYW5uZWxJZC5nZXQocHJvdmlkZXJJZGVudGl0eS5jaGFubmVsSWQpOyAvLyBObyBlbmRwb2ludElkIHdhcyBwYXNzZWQsIG1ha2UgYmVzdCBhdHRlbXB0XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSB0aGlzLmVuZHBvaW50TWFwLmdldChrZXkpO1xuICAgICAgICBpZiAoIWhhbmRsZXIpIHtcbiAgICAgICAgICAgIGFja1RvU2VuZGVyLnBheWxvYWQuc3VjY2VzcyA9IGZhbHNlO1xuICAgICAgICAgICAgYWNrVG9TZW5kZXIucGF5bG9hZC5yZWFzb24gPSBgQ2xpZW50IGNvbm5lY3Rpb24gd2l0aCBpZGVudGl0eSB1dWlkOiAke3RoaXMud2lyZS5tZS51dWlkfSAvIG5hbWU6ICR7dGhpcy53aXJlLm1lLm5hbWV9IC8gZW5kcG9pbnRJZDogJHtrZXl9IG5vIGxvbmdlciBjb25uZWN0ZWQuYDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZFJhdyhhY2tUb1NlbmRlcik7XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGhhbmRsZXIoYWN0aW9uLCBwYXlsb2FkLCBzZW5kZXJJZGVudGl0eSk7XG4gICAgICAgICAgICBhY2tUb1NlbmRlci5wYXlsb2FkLnBheWxvYWQgPSBhY2tUb1NlbmRlci5wYXlsb2FkLnBheWxvYWQgfHwge307XG4gICAgICAgICAgICBhY2tUb1NlbmRlci5wYXlsb2FkLnBheWxvYWQucmVzdWx0ID0gcmVzO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kUmF3KGFja1RvU2VuZGVyKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgYWNrVG9TZW5kZXIucGF5bG9hZC5zdWNjZXNzID0gZmFsc2U7XG4gICAgICAgICAgICBhY2tUb1NlbmRlci5wYXlsb2FkLnJlYXNvbiA9IGUubWVzc2FnZTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZFJhdyhhY2tUb1NlbmRlcik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgYWRkRW5kcG9pbnQoaGFuZGxlciwgY2hhbm5lbElkLCBlbmRwb2ludElkKSB7XG4gICAgICAgIHRoaXMuZW5kcG9pbnRNYXAuc2V0KGVuZHBvaW50SWQsIGhhbmRsZXIpO1xuICAgICAgICAvLyBQcm92aWRlcnMgaGF2ZSB0aGUgc2FtZSBlbmRwb2ludElkIGFuZCBjaGFubmVsSWQuXG4gICAgICAgIC8vIFRoaXMgaXMgb25seSB1c2VkIHdoZW4gY2xpZW50cyBhcmUgcmVjZWl2aW5nIG1lc3NhZ2VzIGZyb20gcHJvdmlkZXJzLCBzbyB3ZSBzaG91bGRuJ3Qgc2F2ZSBwcm92aWRlciBlbmRwb2ludElkIGhlcmUuXG4gICAgICAgIGlmIChjaGFubmVsSWQgIT09IGVuZHBvaW50SWQpIHtcbiAgICAgICAgICAgIHRoaXMubGF0ZXN0RW5kcG9pbnRJZEJ5Q2hhbm5lbElkLnNldChjaGFubmVsSWQsIGVuZHBvaW50SWQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJlbW92ZUVuZHBvaW50KGNoYW5uZWxJZCwgZW5kcG9pbnRJZCkge1xuICAgICAgICB0aGlzLmVuZHBvaW50TWFwLmRlbGV0ZShlbmRwb2ludElkKTtcbiAgICAgICAgaWYgKHRoaXMubGF0ZXN0RW5kcG9pbnRJZEJ5Q2hhbm5lbElkLmdldChjaGFubmVsSWQpID09PSBlbmRwb2ludElkKSB7XG4gICAgICAgICAgICB0aGlzLmxhdGVzdEVuZHBvaW50SWRCeUNoYW5uZWxJZC5kZWxldGUoY2hhbm5lbElkKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjaGVja0ZvclByZXZpb3VzQ2xpZW50Q29ubmVjdGlvbihjaGFubmVsSWQpIHtcbiAgICAgICAgY29uc3QgZW5kcG9pbnRJZEZyb21QcmV2aW91c0Nvbm5lY3Rpb24gPSB0aGlzLmxhdGVzdEVuZHBvaW50SWRCeUNoYW5uZWxJZC5nZXQoY2hhbm5lbElkKTtcbiAgICAgICAgaWYgKGVuZHBvaW50SWRGcm9tUHJldmlvdXNDb25uZWN0aW9uKSB7XG4gICAgICAgICAgICAvLyBOb3QgY29udmluY2VkIGJ5IHRoaXMgd2F5IG9mIGRvaW5nIHRoaW5ncywgYnV0IHB1c2hpbmcgdXAgZm9yIG5vdy5cbiAgICAgICAgICAgIGNsaWVudF8xJDEuQ2hhbm5lbENsaWVudC5jbG9zZUNoYW5uZWxCeUVuZHBvaW50SWQoZW5kcG9pbnRJZEZyb21QcmV2aW91c0Nvbm5lY3Rpb24pO1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGNvbnNvbGUud2FybignWW91IGhhdmUgY3JlYXRlZCBhIHNlY29uZCBjb25uZWN0aW9uIHRvIGFuIG9sZGVyIHByb3ZpZGVyLiBGaXJzdCBjb25uZWN0aW9uIGhhcyBiZWVuIHJlbW92ZWQgZnJvbSB0aGUgY2xpZW50TWFwJyk7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICAgICAgY29uc29sZS53YXJuKCdJZiB0aGUgcHJvdmlkZXIgY2FsbHMgcHVibGlzaCgpLCB5b3UgbWF5IHJlY2VpdmUgbXVsdGlwbGUgbWVzc2FnZXMuJyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5tZXNzYWdlUmVjZWl2ZXIuTWVzc2FnZVJlY2VpdmVyID0gTWVzc2FnZVJlY2VpdmVyO1xuXG52YXIgcHJvdG9jb2xNYW5hZ2VyID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShwcm90b2NvbE1hbmFnZXIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xucHJvdG9jb2xNYW5hZ2VyLlByb3RvY29sTWFuYWdlciA9IHZvaWQgMDtcbi8qXG5UaGlzIHNob3VsZCBiZSBhZ25vc3RpYyBvZiBhbnkgYWN0dWFsIG9wZW5maW4gY29kZSB0byBiZSB1bml0IHRlc3RhYmxlLlxuRGVwZW5kZW5jaWVzIG9uIHRoZSBhY3R1YWwgc3JhdGVnaWVzIHNob3VsZCBiZSBoYW5kbGVkIGluIENvbm5lY3Rpb25NYW5hZ2VyXG4qL1xuY2xhc3MgUHJvdG9jb2xNYW5hZ2VyIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlbGVzcy1jb25zdHJ1Y3RvclxuICAgIGNvbnN0cnVjdG9yKFByb3RvY29sc0luUHJlZmVyZW5jZU9yZGVyKSB7XG4gICAgICAgIHRoaXMuUHJvdG9jb2xzSW5QcmVmZXJlbmNlT3JkZXIgPSBQcm90b2NvbHNJblByZWZlcmVuY2VPcmRlcjtcbiAgICAgICAgdGhpcy5EZWZhdWx0Q2xpZW50UHJvdG9jb2xzID0gWydjbGFzc2ljJ107XG4gICAgICAgIHRoaXMuRGVmYXVsdFByb3ZpZGVyUHJvdG9jb2xzID0gWydjbGFzc2ljJ107XG4gICAgICAgIHRoaXMuZ2V0Q2xpZW50UHJvdG9jb2xzID0gKHByb3RvY29scykgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3VwcG9ydGVkID0gcHJvdG9jb2xzXG4gICAgICAgICAgICAgICAgPyB0aGlzLlByb3RvY29sc0luUHJlZmVyZW5jZU9yZGVyLmZpbHRlcigoeCkgPT4gcHJvdG9jb2xzLmluY2x1ZGVzKHgpKVxuICAgICAgICAgICAgICAgIDogdGhpcy5EZWZhdWx0Q2xpZW50UHJvdG9jb2xzO1xuICAgICAgICAgICAgaWYgKCFzdXBwb3J0ZWQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyB2YWxpZCBwcm90b2NvbHMgd2VyZSBwYXNzZWQgaW4uIEFjY2VwdGVkIHZhbHVlcyBhcmU6ICR7dGhpcy5Qcm90b2NvbHNJblByZWZlcmVuY2VPcmRlci5qb2luKCcsICcpfS5gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzdXBwb3J0ZWQ7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZ2V0UHJvdmlkZXJQcm90b2NvbHMgPSAocHJvdG9jb2xzKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdXBwb3J0ZWQgPSBwcm90b2NvbHNcbiAgICAgICAgICAgICAgICA/IHRoaXMuUHJvdG9jb2xzSW5QcmVmZXJlbmNlT3JkZXIuZmlsdGVyKCh4KSA9PiBwcm90b2NvbHMuaW5jbHVkZXMoeCkpXG4gICAgICAgICAgICAgICAgOiB0aGlzLkRlZmF1bHRQcm92aWRlclByb3RvY29scztcbiAgICAgICAgICAgIGlmICghc3VwcG9ydGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gdmFsaWQgcHJvdG9jb2xzIHdlcmUgcGFzc2VkIGluLiBBY2NlcHRlZCB2YWx1ZXMgYXJlOiAke3RoaXMuUHJvdG9jb2xzSW5QcmVmZXJlbmNlT3JkZXIuam9pbignLCAnKX0uYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc3VwcG9ydGVkO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmdldENvbXBhdGlibGVQcm90b2NvbHMgPSAocHJvdmlkZXJQcm90b2NvbHMsIGNsaWVudE9mZmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdXBwb3J0ZWQgPSBjbGllbnRPZmZlci5zdXBwb3J0ZWRQcm90b2NvbHMuZmlsdGVyKChjbGllbnRQcm90b2NvbCkgPT4gcHJvdmlkZXJQcm90b2NvbHMuc29tZSgocHJvdmlkZXJQcm90b2NvbCkgPT4gcHJvdmlkZXJQcm90b2NvbC50eXBlID09PSBjbGllbnRQcm90b2NvbC50eXBlICYmXG4gICAgICAgICAgICAgICAgY2xpZW50UHJvdG9jb2wudmVyc2lvbiA+PSBwcm92aWRlclByb3RvY29sLm1pbmltdW1WZXJzaW9uICYmXG4gICAgICAgICAgICAgICAgcHJvdmlkZXJQcm90b2NvbC52ZXJzaW9uID49IChjbGllbnRQcm90b2NvbC5taW5pbXVtVmVyc2lvbiA/PyAwKSkpO1xuICAgICAgICAgICAgcmV0dXJuIHN1cHBvcnRlZC5zbGljZSgwLCBjbGllbnRPZmZlci5tYXhQcm90b2NvbHMpO1xuICAgICAgICB9O1xuICAgIH1cbn1cbnByb3RvY29sTWFuYWdlci5Qcm90b2NvbE1hbmFnZXIgPSBQcm90b2NvbE1hbmFnZXI7XG5cbnZhciBzdHJhdGVneSA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoc3RyYXRlZ3ksIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY2xhc3MgQ29tYmluZWRTdHJhdGVneSB7XG4gICAgLy8gTWFraW5nIHRoaXMgYSBzdGF0aWMgbWV0aG9kIGJlY2F1c2UgdGhlIGNvbnN0cnVjdG9yIGNhbid0IGJlIHR5cGVkLlxuICAgIC8vIE90aGVyd2lzZSBpdCB3aWxsIGVycm9yIHdoZW4gY2FsbGluZyBhZGRFbmRwb2ludCBidXQgSSdkIHJhdGhlciB0aGUgd2hvbGUgaW5zdGFuY2UgYmUgdHlwZWQgYXMgbmV2ZXIuXG4gICAgc3RhdGljIGNvbWJpbmUoYSwgYikge1xuICAgICAgICByZXR1cm4gbmV3IENvbWJpbmVkU3RyYXRlZ3koYSwgYik7XG4gICAgfVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11c2VsZXNzLWNvbnN0cnVjdG9yXG4gICAgY29uc3RydWN0b3IocHJpbWFyeSwgc2Vjb25kYXJ5KSB7XG4gICAgICAgIHRoaXMucHJpbWFyeSA9IHByaW1hcnk7XG4gICAgICAgIHRoaXMuc2Vjb25kYXJ5ID0gc2Vjb25kYXJ5O1xuICAgIH1cbiAgICBvbkVuZHBvaW50RGlzY29ubmVjdChlbmRwb2ludElkLCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLnByaW1hcnkub25FbmRwb2ludERpc2Nvbm5lY3QoZW5kcG9pbnRJZCwgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnNlY29uZGFyeS5pc0VuZHBvaW50Q29ubmVjdGVkKGVuZHBvaW50SWQpKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuc2Vjb25kYXJ5Lm9uRW5kcG9pbnREaXNjb25uZWN0KGVuZHBvaW50SWQsICgpID0+IHtcbiAgICAgICAgICAgIGlmICghdGhpcy5wcmltYXJ5LmlzRW5kcG9pbnRDb25uZWN0ZWQoZW5kcG9pbnRJZCkpIHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5lcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgaXNWYWxpZEVuZHBvaW50UGF5bG9hZChwYXlsb2FkKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnByaW1hcnkuaXNWYWxpZEVuZHBvaW50UGF5bG9hZChwYXlsb2FkKSB8fCB0aGlzLnNlY29uZGFyeS5pc1ZhbGlkRW5kcG9pbnRQYXlsb2FkKHBheWxvYWQpO1xuICAgIH1cbiAgICBhc3luYyBjbG9zZUVuZHBvaW50KGVuZHBvaW50SWQpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5wcmltYXJ5LmNsb3NlRW5kcG9pbnQoZW5kcG9pbnRJZCk7XG4gICAgICAgIGF3YWl0IHRoaXMuc2Vjb25kYXJ5LmNsb3NlRW5kcG9pbnQoZW5kcG9pbnRJZCk7XG4gICAgfVxuICAgIGlzRW5kcG9pbnRDb25uZWN0ZWQoZW5kcG9pbnQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJpbWFyeS5pc0VuZHBvaW50Q29ubmVjdGVkKGVuZHBvaW50KSB8fCB0aGlzLnNlY29uZGFyeS5pc0VuZHBvaW50Q29ubmVjdGVkKGVuZHBvaW50KTtcbiAgICB9XG4gICAgYXN5bmMgYWRkRW5kcG9pbnQoZW5kcG9pbnQsIHBheWxvYWQpIHtcbiAgICAgICAgaWYgKHRoaXMucHJpbWFyeS5pc1ZhbGlkRW5kcG9pbnRQYXlsb2FkKHBheWxvYWQpKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnByaW1hcnkuYWRkRW5kcG9pbnQoZW5kcG9pbnQsIHBheWxvYWQpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNlY29uZGFyeS5pc1ZhbGlkRW5kcG9pbnRQYXlsb2FkKHBheWxvYWQpKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNlY29uZGFyeS5hZGRFbmRwb2ludChlbmRwb2ludCwgcGF5bG9hZCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmVjZWl2ZShsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLnByaW1hcnkucmVjZWl2ZShsaXN0ZW5lcik7XG4gICAgICAgIHRoaXMuc2Vjb25kYXJ5LnJlY2VpdmUobGlzdGVuZXIpO1xuICAgIH1cbiAgICBzZW5kKGVuZHBvaW50SWQsIGFjdGlvbiwgcGF5bG9hZCkge1xuICAgICAgICBpZiAodGhpcy5wcmltYXJ5LmlzRW5kcG9pbnRDb25uZWN0ZWQoZW5kcG9pbnRJZCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByaW1hcnkuc2VuZChlbmRwb2ludElkLCBhY3Rpb24sIHBheWxvYWQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnNlY29uZGFyeS5zZW5kKGVuZHBvaW50SWQsIGFjdGlvbiwgcGF5bG9hZCk7XG4gICAgfVxuICAgIGFzeW5jIGNsb3NlKCkge1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChbdGhpcy5wcmltYXJ5LmNsb3NlKCksIHRoaXMuc2Vjb25kYXJ5LmNsb3NlKCldKTtcbiAgICB9XG59XG5zdHJhdGVneS5kZWZhdWx0ID0gQ29tYmluZWRTdHJhdGVneTtcblxudmFyIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkNSA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcbn07XG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ3ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcbn07XG52YXIgX19pbXBvcnREZWZhdWx0JDEgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19pbXBvcnREZWZhdWx0KSB8fCBmdW5jdGlvbiAobW9kKSB7XG4gICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBcImRlZmF1bHRcIjogbW9kIH07XG59O1xudmFyIF9Db25uZWN0aW9uTWFuYWdlcl9tZXNzYWdlUmVjZWl2ZXIsIF9Db25uZWN0aW9uTWFuYWdlcl9ydGNDb25uZWN0aW9uTWFuYWdlcjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb25uZWN0aW9uTWFuYWdlciwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25uZWN0aW9uTWFuYWdlci5Db25uZWN0aW9uTWFuYWdlciA9IHZvaWQgMDtcbmNvbnN0IGV4aGF1c3RpdmVfMSA9IGV4aGF1c3RpdmU7XG5jb25zdCBiYXNlXzEkZiA9IGJhc2U7XG5jb25zdCBzdHJhdGVneV8xID0gc3RyYXRlZ3kkMztcbmNvbnN0IHN0cmF0ZWd5XzIgPSBzdHJhdGVneSQyO1xuY29uc3QgaWNlX21hbmFnZXJfMSA9IGljZU1hbmFnZXI7XG5jb25zdCBwcm92aWRlcl8xJDEgPSBwcm92aWRlcjtcbmNvbnN0IG1lc3NhZ2VfcmVjZWl2ZXJfMSA9IG1lc3NhZ2VSZWNlaXZlcjtcbmNvbnN0IHByb3RvY29sX21hbmFnZXJfMSA9IHByb3RvY29sTWFuYWdlcjtcbmNvbnN0IHN0cmF0ZWd5XzMgPSBfX2ltcG9ydERlZmF1bHQkMShzdHJhdGVneSk7XG5jbGFzcyBDb25uZWN0aW9uTWFuYWdlciBleHRlbmRzIGJhc2VfMSRmLkJhc2Uge1xuICAgIHN0YXRpYyBnZXRQcm90b2NvbE9wdGlvbnNGcm9tU3RyaW5ncyhwcm90b2NvbHMpIHtcbiAgICAgICAgcmV0dXJuIHByb3RvY29scy5tYXAoKHByb3RvY29sKSA9PiB7XG4gICAgICAgICAgICBzd2l0Y2ggKHByb3RvY29sKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAncnRjJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmF0ZWd5XzIuUlRDSW5mbztcbiAgICAgICAgICAgICAgICBjYXNlICdjbGFzc2ljJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmF0ZWd5XzEuQ2xhc3NpY0luZm87XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgwLCBleGhhdXN0aXZlXzEuZXhoYXVzdGl2ZUNoZWNrKShwcm90b2NvbCwgWydydGMnLCAnY2xhc3NpYyddKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnN0cnVjdG9yKHdpcmUpIHtcbiAgICAgICAgc3VwZXIod2lyZSk7XG4gICAgICAgIF9Db25uZWN0aW9uTWFuYWdlcl9tZXNzYWdlUmVjZWl2ZXIuc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIF9Db25uZWN0aW9uTWFuYWdlcl9ydGNDb25uZWN0aW9uTWFuYWdlci5zZXQodGhpcywgdm9pZCAwKTtcbiAgICAgICAgdGhpcy5yZW1vdmVDaGFubmVsRnJvbVByb3ZpZGVyTWFwID0gKGNoYW5uZWxJZCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5wcm92aWRlck1hcC5kZWxldGUoY2hhbm5lbElkKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5vbm1lc3NhZ2UgPSAobXNnKSA9PiB7XG4gICAgICAgICAgICBpZiAobXNnLmFjdGlvbiA9PT0gJ3Byb2Nlc3MtY2hhbm5lbC1jb25uZWN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc0NoYW5uZWxDb25uZWN0aW9uKG1zZyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMucHJvdmlkZXJNYXAgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMucHJvdG9jb2xNYW5hZ2VyID0gbmV3IHByb3RvY29sX21hbmFnZXJfMS5Qcm90b2NvbE1hbmFnZXIodGhpcy53aXJlLmVudmlyb25tZW50LnR5cGUgPT09ICdub2RlJyA/IFsnY2xhc3NpYyddIDogWydydGMnLCAnY2xhc3NpYyddKTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ1KHRoaXMsIF9Db25uZWN0aW9uTWFuYWdlcl9tZXNzYWdlUmVjZWl2ZXIsIG5ldyBtZXNzYWdlX3JlY2VpdmVyXzEuTWVzc2FnZVJlY2VpdmVyKHdpcmUpLCBcImZcIik7XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkNSh0aGlzLCBfQ29ubmVjdGlvbk1hbmFnZXJfcnRjQ29ubmVjdGlvbk1hbmFnZXIsIG5ldyBpY2VfbWFuYWdlcl8xLlJUQ0lDRU1hbmFnZXIod2lyZSksIFwiZlwiKTtcbiAgICAgICAgd2lyZS5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKHRoaXMub25tZXNzYWdlLmJpbmQodGhpcykpO1xuICAgIH1cbiAgICBjcmVhdGVQcm92aWRlcihvcHRpb25zLCBwcm92aWRlcklkZW50aXR5KSB7XG4gICAgICAgIGNvbnN0IG9wdHMgPSBPYmplY3QuYXNzaWduKHRoaXMud2lyZS5lbnZpcm9ubWVudC5nZXREZWZhdWx0Q2hhbm5lbE9wdGlvbnMoKS5jcmVhdGUsIG9wdGlvbnMgfHwge30pO1xuICAgICAgICBjb25zdCBwcm90b2NvbHMgPSB0aGlzLnByb3RvY29sTWFuYWdlci5nZXRQcm92aWRlclByb3RvY29scyhvcHRzPy5wcm90b2NvbHMpO1xuICAgICAgICBjb25zdCBjcmVhdGVTaW5nbGVTdHJhdGVneSA9IChzdHJhdFR5cGUpID0+IHtcbiAgICAgICAgICAgIHN3aXRjaCAoc3RyYXRUeXBlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAncnRjJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBzdHJhdGVneV8yLlJUQ1N0cmF0ZWd5KCk7XG4gICAgICAgICAgICAgICAgY2FzZSAnY2xhc3NpYyc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgc3RyYXRlZ3lfMS5DbGFzc2ljU3RyYXRlZ3kodGhpcy53aXJlLCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDcodGhpcywgX0Nvbm5lY3Rpb25NYW5hZ2VyX21lc3NhZ2VSZWNlaXZlciwgXCJmXCIpLCBcbiAgICAgICAgICAgICAgICAgICAgLy8gUHJvdmlkZXJzIGRvIG5vdCBoYXZlIGFuIGVuZHBvaW50SWQsIHVzZSBjaGFubmVsSWQgYXMgZW5kcG9pbnRJZCBpbiB0aGUgc3RyYXRlZ3kuXG4gICAgICAgICAgICAgICAgICAgIHByb3ZpZGVySWRlbnRpdHkuY2hhbm5lbElkLCBwcm92aWRlcklkZW50aXR5KTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIGV4aGF1c3RpdmVfMS5leGhhdXN0aXZlQ2hlY2spKHN0cmF0VHlwZSwgWydydGMnLCAnY2xhc3NpYyddKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgc3RyYXRlZ2llcyA9IHByb3RvY29scy5tYXAoY3JlYXRlU2luZ2xlU3RyYXRlZ3kpO1xuICAgICAgICBsZXQgc3RyYXRlZ3k7XG4gICAgICAgIGlmIChzdHJhdGVnaWVzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICAgY29uc3QgW2EsIGJdID0gc3RyYXRlZ2llcztcbiAgICAgICAgICAgIHN0cmF0ZWd5ID0gc3RyYXRlZ3lfMy5kZWZhdWx0LmNvbWJpbmUoYSwgYik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoc3RyYXRlZ2llcy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIFtzdHJhdGVneV0gPSBzdHJhdGVnaWVzO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gU2hvdWxkIGJlIGltcG9zc2libGUuXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ZhaWxlZCB0byBjb21iaW5lIHN0cmF0ZWdpZXMnKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGFubmVsID0gbmV3IHByb3ZpZGVyXzEkMS5DaGFubmVsUHJvdmlkZXIocHJvdmlkZXJJZGVudGl0eSwgKCkgPT4gcHJvdmlkZXJfMSQxLkNoYW5uZWxQcm92aWRlci53aXJlQ2xvc2UodGhpcy53aXJlLCBwcm92aWRlcklkZW50aXR5LmNoYW5uZWxOYW1lKSwgc3RyYXRlZ3kpO1xuICAgICAgICBjb25zdCBrZXkgPSBwcm92aWRlcklkZW50aXR5LmNoYW5uZWxJZDtcbiAgICAgICAgdGhpcy5wcm92aWRlck1hcC5zZXQoa2V5LCB7XG4gICAgICAgICAgICBwcm92aWRlcjogY2hhbm5lbCxcbiAgICAgICAgICAgIHN0cmF0ZWd5LFxuICAgICAgICAgICAgc3VwcG9ydGVkUHJvdG9jb2xzOiBDb25uZWN0aW9uTWFuYWdlci5nZXRQcm90b2NvbE9wdGlvbnNGcm9tU3RyaW5ncyhwcm90b2NvbHMpXG4gICAgICAgIH0pO1xuICAgICAgICBwcm92aWRlcl8xJDEuQ2hhbm5lbFByb3ZpZGVyLnNldFByb3ZpZGVyUmVtb3ZhbChjaGFubmVsLCB0aGlzLnJlbW92ZUNoYW5uZWxGcm9tUHJvdmlkZXJNYXAuYmluZCh0aGlzKSk7XG4gICAgICAgIHJldHVybiBjaGFubmVsO1xuICAgIH1cbiAgICBhc3luYyBjcmVhdGVDbGllbnRPZmZlcihvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHByb3RvY29scyA9IHRoaXMucHJvdG9jb2xNYW5hZ2VyLmdldENsaWVudFByb3RvY29scyhvcHRpb25zPy5wcm90b2NvbHMpO1xuICAgICAgICBsZXQgcnRjUGFja2V0O1xuICAgICAgICBjb25zdCBzdXBwb3J0ZWRQcm90b2NvbHMgPSBhd2FpdCBQcm9taXNlLmFsbChwcm90b2NvbHMubWFwKGFzeW5jICh0eXBlKSA9PiB7XG4gICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdydGMnOiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgcnRjQ2xpZW50LCBjaGFubmVscywgb2ZmZXIsIHJ0Y0Nvbm5lY3Rpb25JZCwgY2hhbm5lbHNPcGVuZWQgfSA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNyh0aGlzLCBfQ29ubmVjdGlvbk1hbmFnZXJfcnRjQ29ubmVjdGlvbk1hbmFnZXIsIFwiZlwiKS5zdGFydENsaWVudE9mZmVyKCk7XG4gICAgICAgICAgICAgICAgICAgIHJ0Y1BhY2tldCA9IHsgcnRjQ2xpZW50LCBjaGFubmVscywgY2hhbm5lbHNPcGVuZWQgfTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdydGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdmVyc2lvbjogc3RyYXRlZ3lfMi5SVENJbmZvLnZlcnNpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXlsb2FkOiB7IG9mZmVyLCBydGNDb25uZWN0aW9uSWQgfVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdjbGFzc2ljJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ2NsYXNzaWMnLCB2ZXJzaW9uOiBzdHJhdGVneV8xLkNsYXNzaWNJbmZvLnZlcnNpb24gfTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIGV4aGF1c3RpdmVfMS5leGhhdXN0aXZlQ2hlY2spKHR5cGUsIFsncnRjJywgJ2NsYXNzaWMnXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG9mZmVyOiB7XG4gICAgICAgICAgICAgICAgc3VwcG9ydGVkUHJvdG9jb2xzLFxuICAgICAgICAgICAgICAgIG1heFByb3RvY29sczogMlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJ0YzogcnRjUGFja2V0XG4gICAgICAgIH07XG4gICAgfVxuICAgIGFzeW5jIGNyZWF0ZUNsaWVudFN0cmF0ZWd5KHJ0Y1BhY2tldCwgcm91dGluZ0luZm8pIHtcbiAgICAgICAgaWYgKCFyb3V0aW5nSW5mby5lbmRwb2ludElkKSB7XG4gICAgICAgICAgICByb3V0aW5nSW5mby5lbmRwb2ludElkID0gdGhpcy53aXJlLmVudmlyb25tZW50LmdldE5leHRNZXNzYWdlSWQoKTtcbiAgICAgICAgICAgIC8vIEZvciBOZXcgQ2xpZW50cyBjb25uZWN0aW5nIHRvIE9sZCBQcm92aWRlcnMuIFRvIHByZXZlbnQgbXVsdGktZGlzcGF0Y2hpbmcgYW5kIHB1Ymxpc2hpbmcsIHdlIGRlbGV0ZSBwcmV2aW91c2x5LWNvbm5lY3RlZFxuICAgICAgICAgICAgLy8gY2xpZW50cyB0aGF0IGFyZSBpbiB0aGUgc2FtZSBjb250ZXh0IGFzIHRoZSBuZXdseS1jb25uZWN0ZWQgY2xpZW50LlxuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ3KHRoaXMsIF9Db25uZWN0aW9uTWFuYWdlcl9tZXNzYWdlUmVjZWl2ZXIsIFwiZlwiKS5jaGVja0ZvclByZXZpb3VzQ2xpZW50Q29ubmVjdGlvbihyb3V0aW5nSW5mby5jaGFubmVsSWQpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGFuc3dlciA9IHJvdXRpbmdJbmZvLmFuc3dlciA/PyB7XG4gICAgICAgICAgICBzdXBwb3J0ZWRQcm90b2NvbHM6IFt7IHR5cGU6ICdjbGFzc2ljJywgdmVyc2lvbjogMSB9XVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBjcmVhdGVTdHJhdGVneUZyb21BbnN3ZXIgPSBhc3luYyAocHJvdG9jb2wpID0+IHtcbiAgICAgICAgICAgIGlmIChwcm90b2NvbC50eXBlID09PSAncnRjJyAmJiBydGNQYWNrZXQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDcodGhpcywgX0Nvbm5lY3Rpb25NYW5hZ2VyX3J0Y0Nvbm5lY3Rpb25NYW5hZ2VyLCBcImZcIikuZmluaXNoQ2xpZW50T2ZmZXIocnRjUGFja2V0LnJ0Y0NsaWVudCwgcHJvdG9jb2wucGF5bG9hZC5hbnN3ZXIsIHJ0Y1BhY2tldC5jaGFubmVsc09wZW5lZCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBzdHJhdGVneV8yLlJUQ1N0cmF0ZWd5KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocHJvdG9jb2wudHlwZSA9PT0gJ2NsYXNzaWMnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBzdHJhdGVneV8xLkNsYXNzaWNTdHJhdGVneSh0aGlzLndpcmUsIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNyh0aGlzLCBfQ29ubmVjdGlvbk1hbmFnZXJfbWVzc2FnZVJlY2VpdmVyLCBcImZcIiksIHJvdXRpbmdJbmZvLmVuZHBvaW50SWQsIHJvdXRpbmdJbmZvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBhbGxQcm90b2NvbHMgPSAoYXdhaXQgUHJvbWlzZS5hbGwoYW5zd2VyLnN1cHBvcnRlZFByb3RvY29scy5tYXAoY3JlYXRlU3RyYXRlZ3lGcm9tQW5zd2VyKSkpLmZpbHRlcigoeCkgPT4geCAhPT0gbnVsbCk7XG4gICAgICAgIC8vIENsZWFuIHVwIGxvZ2ljIGlmIHByb3ZpZGVyIGRpZG4ndCBzdXBwb3J0IHJ0Yy5cbiAgICAgICAgaWYgKHJ0Y1BhY2tldCAmJiAhYWxsUHJvdG9jb2xzLnNvbWUoKHgpID0+IHggaW5zdGFuY2VvZiBzdHJhdGVneV8yLlJUQ1N0cmF0ZWd5KSkge1xuICAgICAgICAgICAgaWYgKHJ0Y1BhY2tldCkge1xuICAgICAgICAgICAgICAgIHJ0Y1BhY2tldC5ydGNDbGllbnQuY2xvc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsZXQgc3RyYXRlZ3k7XG4gICAgICAgIGlmIChhbGxQcm90b2NvbHMubGVuZ3RoID49IDIpIHtcbiAgICAgICAgICAgIHN0cmF0ZWd5ID0gc3RyYXRlZ3lfMy5kZWZhdWx0LmNvbWJpbmUoYWxsUHJvdG9jb2xzWzBdLCBhbGxQcm90b2NvbHNbMV0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGFsbFByb3RvY29scy5sZW5ndGgpIHtcbiAgICAgICAgICAgIFtzdHJhdGVneV0gPSBhbGxQcm90b2NvbHM7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBTaG91bGQgYmUgaW1wb3NzaWJsZS5cbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gY29tcGF0aWJsZSBwcm90b2NvbHMnKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBhcyBjYXN0aW5nIHJ0Y1BhY2tldCBiZWNhdXNlIHdlIHdvbid0IGhhdmUgYW4gcnRjU3RyYXRlZ3kgaWYgcnRjUGFja2V0IGlzIHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgZW5kcG9pbnRQYXlsb2FkID0geyBlbmRwb2ludElkZW50aXR5OiByb3V0aW5nSW5mbywgcnRjOiBydGNQYWNrZXQgfTtcbiAgICAgICAgc3RyYXRlZ3kuYWRkRW5kcG9pbnQocm91dGluZ0luZm8uY2hhbm5lbElkLCBlbmRwb2ludFBheWxvYWQpO1xuICAgICAgICByZXR1cm4gc3RyYXRlZ3k7XG4gICAgfVxuICAgIGFzeW5jIHByb2Nlc3NDaGFubmVsQ29ubmVjdGlvbihtc2cpIHtcbiAgICAgICAgY29uc3QgeyBjbGllbnRJZGVudGl0eSwgcHJvdmlkZXJJZGVudGl0eSwgYWNrVG9TZW5kZXIsIHBheWxvYWQsIG9mZmVyOiBjbGllbnRPZmZlciB9ID0gbXNnLnBheWxvYWQ7XG4gICAgICAgIGlmICghY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCkge1xuICAgICAgICAgICAgLy8gU2hvdWxkIGJlIHBvbHlmaWxsZWQgYnkgY29yZSBidXQgbm90IGluIGNhc2VzIG9mIG5vZGUgY29ubmVjdGluZyB0byBhbiBvbGQgcnVudGltZS5cbiAgICAgICAgICAgIGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQgPSB0aGlzLndpcmUuZW52aXJvbm1lbnQuZ2V0TmV4dE1lc3NhZ2VJZCgpO1xuICAgICAgICAgICAgY2xpZW50SWRlbnRpdHkuaXNMb2NhbEVuZHBvaW50SWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2xpZW50SWRlbnRpdHkuaXNMb2NhbEVuZHBvaW50SWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBrZXkgPSBwcm92aWRlcklkZW50aXR5LmNoYW5uZWxJZDtcbiAgICAgICAgY29uc3QgYnVzID0gdGhpcy5wcm92aWRlck1hcC5nZXQoa2V5KTtcbiAgICAgICAgaWYgKCFidXMpIHtcbiAgICAgICAgICAgIGFja1RvU2VuZGVyLnBheWxvYWQuc3VjY2VzcyA9IGZhbHNlO1xuICAgICAgICAgICAgYWNrVG9TZW5kZXIucGF5bG9hZC5yZWFzb24gPSBgQ2hhbm5lbCBcIiR7cHJvdmlkZXJJZGVudGl0eS5jaGFubmVsTmFtZX1cIiBoYXMgYmVlbiBkZXN0cm95ZWQuYDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZFJhdyhhY2tUb1NlbmRlcik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyBwcm92aWRlciwgc3RyYXRlZ3ksIHN1cHBvcnRlZFByb3RvY29scyB9ID0gYnVzO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKCEocHJvdmlkZXIgaW5zdGFuY2VvZiBwcm92aWRlcl8xJDEuQ2hhbm5lbFByb3ZpZGVyKSkge1xuICAgICAgICAgICAgICAgIHRocm93IEVycm9yKCdDYW5ub3QgY29ubmVjdCB0byBhIGNoYW5uZWwgY2xpZW50Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBvZmZlciA9IGNsaWVudE9mZmVyID8/IHtcbiAgICAgICAgICAgICAgICBzdXBwb3J0ZWRQcm90b2NvbHM6IFt7IHR5cGU6ICdjbGFzc2ljJywgdmVyc2lvbjogMSB9XSxcbiAgICAgICAgICAgICAgICBtYXhQcm90b2NvbHM6IDFcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBvdmVybGFwcGluZ1Byb3RvY29scyA9IHRoaXMucHJvdG9jb2xNYW5hZ2VyLmdldENvbXBhdGlibGVQcm90b2NvbHMoc3VwcG9ydGVkUHJvdG9jb2xzLCBvZmZlcik7XG4gICAgICAgICAgICBpZiAoIW92ZXJsYXBwaW5nUHJvdG9jb2xzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhpcyBwcm92aWRlciBkb2VzIG5vdCBzdXBwb3J0IGFueSBvZiB0aGUgb2ZmZXJlZCBwcm90b2NvbHMuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBwcm92aWRlci5wcm9jZXNzQ29ubmVjdGlvbihjbGllbnRJZGVudGl0eSwgcGF5bG9hZCk7XG4gICAgICAgICAgICBhY2tUb1NlbmRlci5wYXlsb2FkLnBheWxvYWQgPSBhY2tUb1NlbmRlci5wYXlsb2FkLnBheWxvYWQgfHwge307XG4gICAgICAgICAgICAvLyBMb29wIHRocm91Z2ggYWxsIHN1cHBvcnRlZCBwcm90b2NvbHMgYW5kIGFjY3VtdWxhdGUgdGhlbSBpbnRvIHRoZSBhbnN3ZXJcbiAgICAgICAgICAgIC8vIGFkZEVuZHBvaW50IGlzIHRyaWNreSBidXQgd2UgbmVlZCB0byB3YWl0IGZvciBjaGFubmVsIHJlc29sdXRpb24gYmVmb3JlIGFkZGluZyB0aGUgZW5kcG9pbnQuXG4gICAgICAgICAgICBsZXQgY2xpZW50QW5zd2VyID0ge1xuICAgICAgICAgICAgICAgIHN1cHBvcnRlZFByb3RvY29sczogW10sXG4gICAgICAgICAgICAgICAgZW5kcG9pbnRQYXlsb2FkUHJvbWlzZTogUHJvbWlzZS5yZXNvbHZlKHsgZW5kcG9pbnRJZGVudGl0eTogY2xpZW50SWRlbnRpdHkgfSlcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjbGllbnRBbnN3ZXIgPSBhd2FpdCBvdmVybGFwcGluZ1Byb3RvY29scy5yZWR1Y2UoYXN5bmMgKGFjY3VtUCwgcHJvdG9jb2xUb1VzZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFuc3dlciA9IGF3YWl0IGFjY3VtUDtcbiAgICAgICAgICAgICAgICBpZiAocHJvdG9jb2xUb1VzZS50eXBlID09PSAncnRjJykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB7IGFuc3dlcjogcnRjQW5zd2VyLCBydGNDbGllbnQsIGNoYW5uZWxzIH0gPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDcodGhpcywgX0Nvbm5lY3Rpb25NYW5hZ2VyX3J0Y0Nvbm5lY3Rpb25NYW5hZ2VyLCBcImZcIikuY3JlYXRlUHJvdmlkZXJBbnN3ZXIocHJvdG9jb2xUb1VzZS5wYXlsb2FkLnJ0Y0Nvbm5lY3Rpb25JZCwgcHJvdG9jb2xUb1VzZS5wYXlsb2FkLm9mZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgYW5zd2VyLnN1cHBvcnRlZFByb3RvY29scy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdydGMnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdmVyc2lvbjogc3RyYXRlZ3lfMi5SVENJbmZvLnZlcnNpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5zd2VyOiBydGNBbnN3ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGFuc3dlci5lbmRwb2ludFBheWxvYWRQcm9taXNlID0gYW5zd2VyLmVuZHBvaW50UGF5bG9hZFByb21pc2UudGhlbigoZW5kcG9pbnRQYXlsb2FkKSA9PiBjaGFubmVscy50aGVuKChyZXNvbHZlZENoYW5uZWxzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmVuZHBvaW50UGF5bG9hZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydGM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcnRjQ2xpZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFubmVsczogcmVzb2x2ZWRDaGFubmVsc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFuc3dlci5zdXBwb3J0ZWRQcm90b2NvbHMucHVzaCh7IHR5cGU6ICdjbGFzc2ljJywgdmVyc2lvbjogc3RyYXRlZ3lfMS5DbGFzc2ljSW5mby52ZXJzaW9uIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gYW5zd2VyO1xuICAgICAgICAgICAgfSwgUHJvbWlzZS5yZXNvbHZlKGNsaWVudEFuc3dlcikpO1xuICAgICAgICAgICAgLy8gTmVlZCB0byBhcyBjYXN0IGhlcmUuXG4gICAgICAgICAgICBjbGllbnRBbnN3ZXIuZW5kcG9pbnRQYXlsb2FkUHJvbWlzZS50aGVuKChlbmRwb2ludFBheWxvYWQpID0+IHN0cmF0ZWd5LmFkZEVuZHBvaW50KGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQsIGVuZHBvaW50UGF5bG9hZCkpO1xuICAgICAgICAgICAgYWNrVG9TZW5kZXIucGF5bG9hZC5wYXlsb2FkLnJlc3VsdCA9IHJlcztcbiAgICAgICAgICAgIGFja1RvU2VuZGVyLnBheWxvYWQucGF5bG9hZC5hbnN3ZXIgPSBjbGllbnRBbnN3ZXI7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRSYXcoYWNrVG9TZW5kZXIpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICBhY2tUb1NlbmRlci5wYXlsb2FkLnN1Y2Nlc3MgPSBmYWxzZTtcbiAgICAgICAgICAgIGFja1RvU2VuZGVyLnBheWxvYWQucmVhc29uID0gZS5tZXNzYWdlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kUmF3KGFja1RvU2VuZGVyKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbmNvbm5lY3Rpb25NYW5hZ2VyLkNvbm5lY3Rpb25NYW5hZ2VyID0gQ29ubmVjdGlvbk1hbmFnZXI7XG5fQ29ubmVjdGlvbk1hbmFnZXJfbWVzc2FnZVJlY2VpdmVyID0gbmV3IFdlYWtNYXAoKSwgX0Nvbm5lY3Rpb25NYW5hZ2VyX3J0Y0Nvbm5lY3Rpb25NYW5hZ2VyID0gbmV3IFdlYWtNYXAoKTtcblxuLyoqXG4gKiBFbnRyeSBwb2ludHMgZm9yIHRoZSBgQ2hhbm5lbGAgc3Vic2V0IG9mIHRoZSBgSW50ZXJBcHBsaWNhdGlvbkJ1c2AgQVBJIChgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbGApLlxuICpcbiAqICoge0BsaW5rIENoYW5uZWx9IGNvbnRhaW5zIHN0YXRpYyBtZW1iZXJzIG9mIHRoZSBgQ2hhbm5lbGAgQVBJLCBhY2Nlc3NpYmxlIHRocm91Z2ggYGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWxgLlxuICogKiB7QGxpbmsgT3BlbkZpbi5DaGFubmVsQ2xpZW50fSBkZXNjcmliZXMgYSBjbGllbnQgb2YgYSBjaGFubmVsLCBlLmcuIGFzIHJldHVybmVkIGJ5IGBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNvbm5lY3RgLlxuICogKiB7QGxpbmsgT3BlbkZpbi5DaGFubmVsUHJvdmlkZXJ9IGRlc2NyaWJlcyBhIHByb3ZpZGVyIG9mIGEgY2hhbm5lbCwgZS5nLiBhcyByZXR1cm5lZCBieSBgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGVgLlxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQ0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDYgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xufTtcbnZhciBfQ2hhbm5lbF9jb25uZWN0aW9uTWFuYWdlciwgX0NoYW5uZWxfaW50ZXJuYWxFbWl0dGVyLCBfQ2hhbm5lbF9yZWFkeVRvQ29ubmVjdDtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShjaGFubmVsJDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY2hhbm5lbCQxLkNoYW5uZWwgPSB2b2lkIDA7XG4vKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5jb25zdCBldmVudHNfMSQ1ID0gcmVxdWlyZSQkMDtcbmNvbnN0IGxhenlfMSQxID0gbGF6eTtcbmNvbnN0IGJhc2VfMSRlID0gYmFzZTtcbmNvbnN0IGNsaWVudF8xID0gY2xpZW50O1xuY29uc3QgY29ubmVjdGlvbl9tYW5hZ2VyXzEgPSBjb25uZWN0aW9uTWFuYWdlcjtcbmNvbnN0IHByb3ZpZGVyXzEgPSBwcm92aWRlcjtcbmZ1bmN0aW9uIHJldHJ5RGVsYXkoY291bnQpIHtcbiAgICBjb25zdCBpbnRlcnZhbCA9IDUwMDsgLy8gYmFzZSBkZWxheVxuICAgIGNvbnN0IHN0ZXBzID0gMTA7IC8vIEhvdyBtYW55IHJldHJpZXMgdG8gZG8gYmVmb3JlIGluY3JlbWVudGluZyB0aGUgZGVsYXlcbiAgICBjb25zdCBiYXNlID0gMjsgLy8gSG93IG11Y2ggdG8gbXVsdGlwbHkgdGhlIHByZXZpb3VzIGRlbGF5IGJ5XG4gICAgY29uc3QgbWF4ID0gMzAwMDA7IC8vIG1heCBkZWxheVxuICAgIGNvbnN0IHN0ZXAgPSBNYXRoLmZsb29yKGNvdW50IC8gc3RlcHMpO1xuICAgIGNvbnN0IGRlbGF5ID0gTWF0aC5taW4obWF4LCBpbnRlcnZhbCAqIGJhc2UgKiogc3RlcCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZShmYWxzZSk7XG4gICAgICAgIH0sIGRlbGF5KTtcbiAgICB9KTtcbn1cbi8qKlxuICogVGhlIENoYW5uZWwgQVBJIGFsbG93cyBhbiBPcGVuRmluIGFwcGxpY2F0aW9uIHRvIGNyZWF0ZSBhIGNoYW5uZWwgYXMgYSB7QGxpbmsgQ2hhbm5lbFByb3ZpZGVyIENoYW5uZWxQcm92aWRlcn0sXG4gKiBvciBjb25uZWN0IHRvIGEgY2hhbm5lbCBhcyBhIHtAbGluayBDaGFubmVsQ2xpZW50IENoYW5uZWxDbGllbnR9LlxuICogQHJlbWFya3MgVGhlIFwiaGFuZHNoYWtlXCIgYmV0d2VlbiB0aGUgY29tbXVuaWNhdGlvbiBwYXJ0bmVycyBpc1xuICogc2ltcGxpZmllZCB3aGVuIHVzaW5nIGEgY2hhbm5lbC4gIEEgcmVxdWVzdCB0byBjb25uZWN0IHRvIGEgY2hhbm5lbCBhcyBhIGNsaWVudCB3aWxsIHJldHVybiBhIHByb21pc2UgdGhhdCByZXNvbHZlcyBpZi93aGVuIHRoZSBjaGFubmVsIGhhcyBiZWVuIGNyZWF0ZWQuIEJvdGggdGhlXG4gKiBwcm92aWRlciBhbmQgY2xpZW50IGNhbiBkaXNwYXRjaCBhY3Rpb25zIHRoYXQgaGF2ZSBiZWVuIHJlZ2lzdGVyZWQgb24gdGhlaXIgb3Bwb3NpdGVzLCBhbmQgZGlzcGF0Y2ggcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIGEgcGF5bG9hZCBmcm9tIHRoZSBvdGhlclxuICogY29tbXVuaWNhdGlvbiBwYXJ0aWNpcGFudC4gVGhlcmUgY2FuIGJlIG9ubHkgb25lIHByb3ZpZGVyIHBlciBjaGFubmVsLCBidXQgbWFueSBjbGllbnRzLiAgVmVyc2lvbiBgOS42MS4zNS4qYCBvciBsYXRlciBpcyByZXF1aXJlZCBmb3IgYm90aCBjb21tdW5pY2F0aW9uIHBhcnRuZXJzLlxuICpcbiAqIEFzeW5jaHJvbm91cyBNZXRob2RzOlxuICogICoge0BsaW5rIENoYW5uZWwuY3JlYXRlIGNyZWF0ZShjaGFubmVsTmFtZSwgb3B0aW9ucyl9XG4gKiAgKiB7QGxpbmsgQ2hhbm5lbC5jb25uZWN0IGNvbm5lY3QoY2hhbm5lbE5hbWUsIG9wdGlvbnMpfVxuICogICoge0BsaW5rIENoYW5uZWwub25DaGFubmVsQ29ubmVjdCBvbkNoYW5uZWxDb25uZWN0KGxpc3RlbmVyKX1cbiAqICAqIHtAbGluayBDaGFubmVsLm9uQ2hhbm5lbERpc2Nvbm5lY3Qgb25DaGFubmVsRGlzY29ubmVjdChsaXN0ZW5lcil9XG4gKi9cbmNsYXNzIENoYW5uZWwgZXh0ZW5kcyBiYXNlXzEkZS5FbWl0dGVyQmFzZSB7XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iod2lyZSkge1xuICAgICAgICBzdXBlcih3aXJlLCAnY2hhbm5lbCcpO1xuICAgICAgICBfQ2hhbm5lbF9jb25uZWN0aW9uTWFuYWdlci5zZXQodGhpcywgdm9pZCAwKTtcbiAgICAgICAgX0NoYW5uZWxfaW50ZXJuYWxFbWl0dGVyLnNldCh0aGlzLCBuZXcgZXZlbnRzXzEkNS5FdmVudEVtaXR0ZXIoKSk7XG4gICAgICAgIC8vIE9wZW5GaW4gQVBJIGhhcyBub3QgYmVlbiBpbmplY3RlZCBhdCBjb25zdHJ1Y3Rpb24gdGltZSwgKm11c3QqIHdhaXQgZm9yIEFQSSB0byBiZSByZWFkeS5cbiAgICAgICAgX0NoYW5uZWxfcmVhZHlUb0Nvbm5lY3Quc2V0KHRoaXMsIG5ldyBsYXp5XzEkMS5Bc3luY1JldHJ5YWJsZUxhenkoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgICAgIHRoaXMub24oJ2Rpc2Nvbm5lY3RlZCcsIChldmVudFBheWxvYWQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY2xpZW50XzEuQ2hhbm5lbENsaWVudC5oYW5kbGVQcm92aWRlckRpc2Nvbm5lY3QoZXZlbnRQYXlsb2FkKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICB0aGlzLm9uKCdjb25uZWN0ZWQnLCAoLi4uYXJncykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDYodGhpcywgX0NoYW5uZWxfaW50ZXJuYWxFbWl0dGVyLCBcImZcIikuZW1pdCgnY29ubmVjdGVkJywgLi4uYXJncyk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIF0pLmNhdGNoKCgpID0+IG5ldyBFcnJvcignZXJyb3Igc2V0dGluZyB1cCBjaGFubmVsIGNvbm5lY3Rpb24gbGlzdGVuZXJzJykpO1xuICAgICAgICB9KSk7XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkNCh0aGlzLCBfQ2hhbm5lbF9jb25uZWN0aW9uTWFuYWdlciwgbmV3IGNvbm5lY3Rpb25fbWFuYWdlcl8xLkNvbm5lY3Rpb25NYW5hZ2VyKHdpcmUpLCBcImZcIik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgYXN5bmMgZ2V0QWxsQ2hhbm5lbHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLndpcmUuc2VuZEFjdGlvbignZ2V0LWFsbC1jaGFubmVscycpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBMaXN0ZW5zIGZvciBjaGFubmVsIGNvbm5lY3Rpb25zLlxuICAgICAqXG4gICAgICogQHBhcmFtIGxpc3RlbmVyIC0gY2FsbGJhY2sgdG8gZXhlY3V0ZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IGxpc3RlbmVyID0gKGNoYW5uZWxQYXlsb2FkKSA9PiBjb25zb2xlLmxvZyhjaGFubmVsUGF5bG9hZCk7IC8vIHNlZSByZXR1cm4gdmFsdWUgYmVsb3dcbiAgICAgKlxuICAgICAqIGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwub25DaGFubmVsQ29ubmVjdChsaXN0ZW5lcik7XG4gICAgICpcbiAgICAgKiAvLyBleGFtcGxlIHNoYXBlXG4gICAgICoge1xuICAgICAqICAgICBcInRvcGljXCI6IFwiY2hhbm5lbFwiLFxuICAgICAqICAgICBcInR5cGVcIjogXCJjb25uZWN0ZWRcIixcbiAgICAgKiAgICAgXCJ1dWlkXCI6IFwiT3BlbmZpblBPQ1wiLFxuICAgICAqICAgICBcIm5hbWVcIjogXCJPcGVuZmluUE9DXCIsXG4gICAgICogICAgIFwiY2hhbm5lbE5hbWVcIjogXCJjb3VudGVyXCIsXG4gICAgICogICAgIFwiY2hhbm5lbElkXCI6IFwiT3BlbmZpblBPQy9PcGVuZmluUE9DL2NvdW50ZXJcIlxuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIG9uQ2hhbm5lbENvbm5lY3QobGlzdGVuZXIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5vbignY29ubmVjdGVkJywgbGlzdGVuZXIpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBMaXN0ZW4gZm9yIGNoYW5uZWwgZGlzY29ubmVjdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbGlzdGVuZXIgLSBjYWxsYmFjayB0byBleGVjdXRlLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgbGlzdGVuZXIgPSAoY2hhbm5lbFBheWxvYWQpID0+IGNvbnNvbGUubG9nKGNoYW5uZWxQYXlsb2FkKTsgLy8gc2VlIHJldHVybiB2YWx1ZSBiZWxvd1xuICAgICAqXG4gICAgICogZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5vbkNoYW5uZWxEaXNjb25uZWN0KGxpc3RlbmVyKTtcbiAgICAgKlxuICAgICAqIC8vIGV4YW1wbGUgc2hhcGVcbiAgICAgKiB7XG4gICAgICogICAgIFwidG9waWNcIjogXCJjaGFubmVsXCIsXG4gICAgICogICAgIFwidHlwZVwiOiBcImRpc2Nvbm5lY3RlZFwiLFxuICAgICAqICAgICBcInV1aWRcIjogXCJPcGVuZmluUE9DXCIsXG4gICAgICogICAgIFwibmFtZVwiOiBcIk9wZW5maW5QT0NcIixcbiAgICAgKiAgICAgXCJjaGFubmVsTmFtZVwiOiBcImNvdW50ZXJcIixcbiAgICAgKiAgICAgXCJjaGFubmVsSWRcIjogXCJPcGVuZmluUE9DL09wZW5maW5QT0MvY291bnRlclwiXG4gICAgICogfVxuICAgICAqXG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgb25DaGFubmVsRGlzY29ubmVjdChsaXN0ZW5lcikge1xuICAgICAgICBhd2FpdCB0aGlzLm9uKCdkaXNjb25uZWN0ZWQnLCBsaXN0ZW5lcik7XG4gICAgfVxuICAgIGFzeW5jIHNhZmVDb25uZWN0KGNoYW5uZWxOYW1lLCBzaG91bGRXYWl0LCBjb25uZWN0UGF5bG9hZCkge1xuICAgICAgICBjb25zdCByZXRyeUluZm8gPSB7IGNvdW50OiAwIH07XG4gICAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWF3YWl0LWluLWxvb3AsIG5vLWNvbnN0YW50LWNvbmRpdGlvbiAqL1xuICAgICAgICBkbyB7XG4gICAgICAgICAgICAvLyBzZXR1cCBhIGxpc3RlbmVyIGFuZCBhIGNvbm5lY3RlZCBwcm9taXNlIHRvIGF3YWl0IGluIGNhc2Ugd2UgY29ubmVjdCBiZWZvcmUgdGhlIGNoYW5uZWwgaXMgcmVhZHlcbiAgICAgICAgICAgIGxldCBjb25uZWN0ZWRMaXN0ZW5lciA9ICgpID0+IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3RlZFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbm5lY3RlZExpc3RlbmVyID0gKHBheWxvYWQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoYW5uZWxOYW1lID09PSBwYXlsb2FkLmNoYW5uZWxOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDYodGhpcywgX0NoYW5uZWxfaW50ZXJuYWxFbWl0dGVyLCBcImZcIikub24oJ2Nvbm5lY3RlZCcsIGNvbm5lY3RlZExpc3RlbmVyKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAocmV0cnlJbmZvLmNvdW50ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBXYWl0IGJlZm9yZSByZXRyeWluZ1xuICAgICAgICAgICAgICAgICAgICAvLyBEZWxheSByZXR1cm5zIGZhbHNlIGNvbm5lY3RlZFByb21pc2UgcmV0dXJucyB0cnVlIHNvIHdlIGNhbiBrbm93IGlmIGEgcmV0cnkgaXMgZHVlIHRvIGNvbm5lY3RlZCBldmVudFxuICAgICAgICAgICAgICAgICAgICByZXRyeUluZm8uZ290Q29ubmVjdGVkRXZlbnQgPSBhd2FpdCBQcm9taXNlLnJhY2UoW3JldHJ5RGVsYXkocmV0cnlJbmZvLmNvdW50KSwgY29ubmVjdGVkUHJvbWlzZV0pO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignY29ubmVjdC10by1jaGFubmVsJywgeyAuLi5jb25uZWN0UGF5bG9hZCwgcmV0cnlJbmZvIH0pO1xuICAgICAgICAgICAgICAgICAgICAvLyBsb2cgb25seSBpZiB0aGVyZSB3YXMgYSByZXRyeVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgU3VjY2Vzc2Z1bGx5IGNvbm5lY3RlZCB0byBjaGFubmVsTmFtZTogJHtjaGFubmVsTmFtZX1gKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5wYXlsb2FkLmRhdGE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFNlbmQgcmV0cnlJbmZvIHRvIHRoZSBjb3JlIGZvciBkZWJ1ZyBsb2cgaW5jbHVzaW9uXG4gICAgICAgICAgICAgICAgY29uc3Qgc2VudE1lc3NhZ2VQcm9taXNlID0gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2Nvbm5lY3QtdG8tY2hhbm5lbCcsIGNvbm5lY3RQYXlsb2FkKTtcbiAgICAgICAgICAgICAgICAvLyBTYXZlIG1lc3NhZ2VJZCBmcm9tIHRoZSBmaXJzdCBjb25uZWN0aW9uIGF0dGVtcHRcbiAgICAgICAgICAgICAgICByZXRyeUluZm8ub3JpZ2luYWxNZXNzYWdlSWQgPSBzZW50TWVzc2FnZVByb21pc2UubWVzc2FnZUlkO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNlbnRNZXNzYWdlUHJvbWlzZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0LnBheWxvYWQuZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGlmICghZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnaW50ZXJuYWwtbmFjaycpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdCBhbiBpbnRlcm5hbCBuYWNrLCBicmVhayB0aGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHNob3VsZFdhaXQgJiYgcmV0cnlJbmZvLmNvdW50ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHN0YXJ0IHdhaXRpbmcgb24gdGhlIG5leHQgaXRlcmF0aW9uLCB3YXJuIHRoZSB1c2VyXG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgTm8gY2hhbm5lbCBmb3VuZCBmb3IgY2hhbm5lbE5hbWU6ICR7Y2hhbm5lbE5hbWV9LiBXYWl0aW5nIGZvciBjb25uZWN0aW9uLi4uYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICAgICAgcmV0cnlJbmZvLmNvdW50ICs9IDE7XG4gICAgICAgICAgICAgICAgLy8gaW4gY2FzZSBvZiBvdGhlciBlcnJvcnMsIHJlbW92ZSBvdXIgbGlzdGVuZXJcbiAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDYodGhpcywgX0NoYW5uZWxfaW50ZXJuYWxFbWl0dGVyLCBcImZcIikucmVtb3ZlTGlzdGVuZXIoJ2Nvbm5lY3RlZCcsIGNvbm5lY3RlZExpc3RlbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSB3aGlsZSAoc2hvdWxkV2FpdCk7IC8vIElmIHdlJ3JlIHdhaXRpbmcgd2UgcmV0cnkgdGhlIGFib3ZlIGxvb3BcbiAgICAgICAgLy8gU2hvdWxkIHdhaXQgd2FzIGZhbHNlLCBubyBjaGFubmVsIHdhcyBmb3VuZC5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBjaGFubmVsIGZvdW5kIGZvciBjaGFubmVsTmFtZTogJHtjaGFubmVsTmFtZX0uYCk7XG4gICAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tYXdhaXQtaW4tbG9vcCwgbm8tY29uc3RhbnQtY29uZGl0aW9uICovXG4gICAgfVxuICAgIC8qKlxuICAgICAqIENvbm5lY3QgdG8gYSBjaGFubmVsLiBJZiB5b3Ugd2lzaCB0byBzZW5kIGEgcGF5bG9hZCB0byB0aGUgcHJvdmlkZXIsIGFkZCBhIHBheWxvYWQgcHJvcGVydHkgdG8gdGhlIG9wdGlvbnMgYXJndW1lbnQuXG4gICAgICogRVhQRVJJTUVOVEFMOiBwYXNzIHsgcHJvdG9jb2xzOiBbJ3J0YyddIH0gYXMgb3B0aW9ucyB0byBvcHQtaW4gdG8gSGlnaCBUaHJvdWdocHV0IENoYW5uZWxzLlxuICAgICAqXG4gICAgICogQHBhcmFtIGNoYW5uZWxOYW1lIC0gTmFtZSBvZiB0aGUgdGFyZ2V0IGNoYW5uZWwuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBDb25uZWN0aW9uIG9wdGlvbnMuXG4gICAgICogQHJldHVybnMgUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIGFuIGluc3RhbmNlIG9mIHtAbGluayBDaGFubmVsQ2xpZW50IENoYW5uZWxDbGllbnR9LlxuICAgICAqXG4gICAgICogQHJlbWFya3MgVGhlIGNvbm5lY3Rpb24gcmVxdWVzdCB3aWxsIGJlIHJvdXRlZCB0byB0aGUgY2hhbm5lbFByb3ZpZGVyIGlmL3doZW4gdGhlIGNoYW5uZWwgaXMgY3JlYXRlZC4gIElmIHRoZSBjb25uZWN0XG4gICAgICogcmVxdWVzdCBpcyBzZW50IHByaW9yIHRvIGNyZWF0aW9uLCB0aGUgcHJvbWlzZSB3aWxsIG5vdCByZXNvbHZlIG9yIHJlamVjdCB1bnRpbCB0aGUgY2hhbm5lbCBpcyBjcmVhdGVkIGJ5IGEgY2hhbm5lbFByb3ZpZGVyXG4gICAgICogKHdoZXRoZXIgb3Igbm90IHRvIHdhaXQgZm9yIGNyZWF0aW9uIGlzIGNvbmZpZ3VyYWJsZSBpbiB0aGUgY29ubmVjdE9wdGlvbnMpLlxuICAgICAqXG4gICAgICogVGhlIGNvbm5lY3QgY2FsbCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHdpbGwgcmVzb2x2ZSB3aXRoIGEgY2hhbm5lbENsaWVudCBidXMgaWYgYWNjZXB0ZWQgYnkgdGhlIGNoYW5uZWxQcm92aWRlciwgb3IgcmVqZWN0IGlmXG4gICAgICogdGhlIGNoYW5uZWxQcm92aWRlciB0aHJvd3MgYW4gZXJyb3IgdG8gcmVqZWN0IHRoZSBjb25uZWN0aW9uLiBUaGlzIGJ1cyBjYW4gY29tbXVuaWNhdGUgd2l0aCB0aGUgUHJvdmlkZXIsIGJ1dCBub3QgdG8gb3RoZXJcbiAgICAgKiBjbGllbnRzIG9uIHRoZSBjaGFubmVsLiBVc2luZyB0aGUgYnVzLCB0aGUgY2hhbm5lbENsaWVudCBjYW4gcmVnaXN0ZXIgYWN0aW9ucyBhbmQgbWlkZGxld2FyZS4gQ2hhbm5lbCBsaWZlY3ljbGUgY2FuIGFsc28gYmVcbiAgICAgKiBoYW5kbGVkIHdpdGggYW4gb25EaXNjb25uZWN0aW9uIGxpc3RlbmVyLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gbWFrZUNsaWVudChjaGFubmVsTmFtZSkge1xuICAgICAqICAgIC8vIEEgcGF5bG9hZCBjYW4gYmUgc2VudCBhbG9uZyB3aXRoIGNoYW5uZWwgY29ubmVjdGlvbiByZXF1ZXN0cyB0byBoZWxwIHdpdGggYXV0aGVudGljYXRpb25cbiAgICAgKiAgICBjb25zdCBjb25uZWN0UGF5bG9hZCA9IHsgcGF5bG9hZDogJ3Rva2VuJyB9O1xuICAgICAqXG4gICAgICogICAgLy8gSWYgdGhlIGNoYW5uZWwgaGFzIGJlZW4gY3JlYXRlZCB0aGlzIHJlcXVlc3Qgd2lsbCBiZSBzZW50IHRvIHRoZSBwcm92aWRlci4gIElmIG5vdCwgdGhlXG4gICAgICogICAgLy8gcHJvbWlzZSB3aWxsIG5vdCBiZSByZXNvbHZlZCBvciByZWplY3RlZCB1bnRpbCB0aGUgY2hhbm5lbCBoYXMgYmVlbiBjcmVhdGVkLlxuICAgICAqICAgIGNvbnN0IGNsaWVudEJ1cyA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY29ubmVjdChjaGFubmVsTmFtZSwgY29ubmVjdFBheWxvYWQpO1xuICAgICAqXG4gICAgICogICAgY2xpZW50QnVzLm9uRGlzY29ubmVjdGlvbihjaGFubmVsSW5mbyA9PiB7XG4gICAgICogICAgICAgIC8vIGhhbmRsZSB0aGUgY2hhbm5lbCBsaWZlY3ljbGUgaGVyZSAtIHdlIGNhbiBjb25uZWN0IGFnYWluIHdoaWNoIHdpbGwgcmV0dXJuIGEgcHJvbWlzZVxuICAgICAqICAgICAgICAvLyB0aGF0IHdpbGwgcmVzb2x2ZSBpZi93aGVuIHRoZSBjaGFubmVsIGlzIHJlLWNyZWF0ZWQuXG4gICAgICogICAgICAgIG1ha2VDbGllbnQoY2hhbm5lbEluZm8uY2hhbm5lbE5hbWUpO1xuICAgICAqICAgIH0pXG4gICAgICpcbiAgICAgKiAgICBjbGllbnRCdXMucmVnaXN0ZXIoJ3RvcGljJywgKHBheWxvYWQsIGlkZW50aXR5KSA9PiB7XG4gICAgICogICAgICAgIC8vIHJlZ2lzdGVyIGEgY2FsbGJhY2sgZm9yIGEgdG9waWMgdG8gd2hpY2ggdGhlIGNoYW5uZWwgcHJvdmlkZXIgY2FuIGRpc3BhdGNoIGFuIGFjdGlvblxuICAgICAqICAgICAgICBjb25zb2xlLmxvZygnQWN0aW9uIGRpc3BhdGNoZWQgYnkgcHJvdmlkZXI6ICcsIEpTT04uc3RyaW5naWZ5KGlkZW50aXR5KSk7XG4gICAgICogICAgICAgIGNvbnNvbGUubG9nKCdQYXlsb2FkIHNlbnQgaW4gZGlzcGF0Y2g6ICcsIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgKiAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgIGVjaG86IHBheWxvYWRcbiAgICAgKiAgICAgICAgfTtcbiAgICAgKiAgICB9KTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBtYWtlQ2xpZW50KCdjaGFubmVsTmFtZScpXG4gICAgICogLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ0Nvbm5lY3RlZCcpKVxuICAgICAqIC5jYXRjaChjb25zb2xlLmVycm9yKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBjb25uZWN0KGNoYW5uZWxOYW1lLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgLy8gTWFrZSBzdXJlIHdlIGRvbid0IGNvbm5lY3QgYmVmb3JlIGxpc3RlbmVycyBhcmUgc2V0IHVwXG4gICAgICAgIC8vIFRoaXMgYWxzbyBlcnJvcnMgaWYgd2UncmUgbm90IGluIE9wZW5GaW4sIGVuc3VyaW5nIHdlIGRvbid0IHJ1biB1bm5lY2Vzc2FyeSBjb2RlXG4gICAgICAgIGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNih0aGlzLCBfQ2hhbm5lbF9yZWFkeVRvQ29ubmVjdCwgXCJmXCIpLmdldFZhbHVlKCk7XG4gICAgICAgIGlmICghY2hhbm5lbE5hbWUgfHwgdHlwZW9mIGNoYW5uZWxOYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQbGVhc2UgcHJvdmlkZSBhIGNoYW5uZWxOYW1lIHN0cmluZyB0byBjb25uZWN0IHRvIGEgY2hhbm5lbC4nKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBvcHRzID0geyB3YWl0OiB0cnVlLCAuLi50aGlzLndpcmUuZW52aXJvbm1lbnQuZ2V0RGVmYXVsdENoYW5uZWxPcHRpb25zKCkuY29ubmVjdCwgLi4ub3B0aW9ucyB9O1xuICAgICAgICBjb25zdCB7IG9mZmVyLCBydGM6IHJ0Y1BhY2tldCB9ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ2KHRoaXMsIF9DaGFubmVsX2Nvbm5lY3Rpb25NYW5hZ2VyLCBcImZcIikuY3JlYXRlQ2xpZW50T2ZmZXIob3B0cyk7XG4gICAgICAgIGxldCBjb25uZWN0aW9uVXJsO1xuICAgICAgICBpZiAodGhpcy5maW4ubWUuaXNGcmFtZSB8fCB0aGlzLmZpbi5tZS5pc1ZpZXcgfHwgdGhpcy5maW4ubWUuaXNXaW5kb3cpIHtcbiAgICAgICAgICAgIGNvbm5lY3Rpb25VcmwgPSAoYXdhaXQgdGhpcy5maW4ubWUuZ2V0SW5mbygpKS51cmw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY29ubmVjdFBheWxvYWQgPSB7XG4gICAgICAgICAgICBjaGFubmVsTmFtZSxcbiAgICAgICAgICAgIC4uLm9wdHMsXG4gICAgICAgICAgICBvZmZlcixcbiAgICAgICAgICAgIGNvbm5lY3Rpb25VcmxcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3Qgcm91dGluZ0luZm8gPSBhd2FpdCB0aGlzLnNhZmVDb25uZWN0KGNoYW5uZWxOYW1lLCBvcHRzLndhaXQsIGNvbm5lY3RQYXlsb2FkKTtcbiAgICAgICAgY29uc3Qgc3RyYXRlZ3kgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDYodGhpcywgX0NoYW5uZWxfY29ubmVjdGlvbk1hbmFnZXIsIFwiZlwiKS5jcmVhdGVDbGllbnRTdHJhdGVneShydGNQYWNrZXQsIHJvdXRpbmdJbmZvKTtcbiAgICAgICAgY29uc3QgY2hhbm5lbCA9IG5ldyBjbGllbnRfMS5DaGFubmVsQ2xpZW50KHJvdXRpbmdJbmZvLCAoKSA9PiBjbGllbnRfMS5DaGFubmVsQ2xpZW50LndpcmVDbG9zZSh0aGlzLndpcmUsIHJvdXRpbmdJbmZvLCByb3V0aW5nSW5mby5lbmRwb2ludElkKSwgc3RyYXRlZ3kpO1xuICAgICAgICAvLyBJdCBpcyB0aGUgY2xpZW50J3MgcmVzcG9uc2liaWxpdHkgdG8gaGFuZGxlIGVuZHBvaW50IGRpc2Nvbm5lY3Rpb24gdG8gdGhlIHByb3ZpZGVyLlxuICAgICAgICAvLyBJZiB0aGUgZW5kcG9pbnQgZGllcywgdGhlIGNsaWVudCB3aWxsIGZvcmNlIGEgZGlzY29ubmVjdGlvbiB0aHJvdWdoIHRoZSBjb3JlLlxuICAgICAgICAvLyBUaGUgcHJvdmlkZXIgZG9lcyBub3QgY2FyZSBhYm91dCBlbmRwb2ludCBkaXNjb25uZWN0aW9uLlxuICAgICAgICBzdHJhdGVneS5vbkVuZHBvaW50RGlzY29ubmVjdChyb3V0aW5nSW5mby5jaGFubmVsSWQsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgY2hhbm5lbC5zZW5kRGlzY29ubmVjdEFjdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBTb21ldGhpbmcgd2VudCB3cm9uZyBkdXJpbmcgZGlzY29ubmVjdCBmb3IgY2xpZW50IHdpdGggdXVpZDogJHtyb3V0aW5nSW5mby51dWlkfSAvIG5hbWU6ICR7cm91dGluZ0luZm8ubmFtZX0gLyBlbmRwb2ludElkOiAke3JvdXRpbmdJbmZvLmVuZHBvaW50SWR9LmApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICAgICAgY2xpZW50XzEuQ2hhbm5lbENsaWVudC5oYW5kbGVQcm92aWRlckRpc2Nvbm5lY3Qocm91dGluZ0luZm8pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNoYW5uZWw7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIG5ldyBjaGFubmVsLlxuICAgICAqIFlvdSBtdXN0IHByb3ZpZGUgYSB1bmlxdWUgY2hhbm5lbE5hbWUuIElmIGEgY2hhbm5lbE5hbWUgaXMgbm90IHByb3ZpZGVkLCBvciBpdCBpcyBub3QgdW5pcXVlLCB0aGUgY3JlYXRpb24gd2lsbCBmYWlsLlxuICAgICAqIEVYUEVSSU1FTlRBTDogcGFzcyB7IHByb3RvY29sczogWydydGMnXSB9IGFzIG9wdGlvbnMgdG8gb3B0LWluIHRvIEhpZ2ggVGhyb3VnaHB1dCBDaGFubmVscy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBjaGFubmVsTmFtZSAtIE5hbWUgb2YgdGhlIGNoYW5uZWwgdG8gYmUgY3JlYXRlZC5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIENyZWF0aW9uIG9wdGlvbnMuXG4gICAgICogQHJldHVybnMgUmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIGFuIGluc3RhbmNlIG9mIHtAbGluayBDaGFubmVsUHJvdmlkZXIgQ2hhbm5lbFByb3ZpZGVyfS5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIElmIHN1Y2Nlc3NmdWwsIHRoZSBjcmVhdGUgbWV0aG9kIHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gaW5zdGFuY2Ugb2YgdGhlIGNoYW5uZWxQcm92aWRlciBidXMuIFRoZSBjYWxsZXJcbiAgICAgKiB0aGVuIGJlY29tZXMgdGhlIOKAnGNoYW5uZWwgcHJvdmlkZXLigJ0gYW5kIGNhbiB1c2UgdGhlIGNoYW5uZWxQcm92aWRlciBidXMgdG8gcmVnaXN0ZXIgYWN0aW9ucyBhbmQgbWlkZGxld2FyZS5cbiAgICAgKlxuICAgICAqIFRoZSBjYWxsZXIgY2FuIGFsc28gc2V0IGFuIG9uQ29ubmVjdGlvbiBhbmQvb3Igb25EaXNjb25uZWN0aW9uIGxpc3RlbmVyIHRoYXQgd2lsbCBleGVjdXRlIG9uIGFueSBuZXcgY2hhbm5lbFxuICAgICAqIGNvbm5lY3Rpb24vZGlzY29ubmVjdGlvbiBhdHRlbXB0IGZyb20gYSBjaGFubmVsIGNsaWVudC4gVG8gcmVqZWN0IGEgY29ubmVjdGlvbiwgc2ltcGx5IHRocm93IGFuIGVycm9yIGluIHRoZVxuICAgICAqIG9uQ29ubmVjdGlvbiBsaXN0ZW5lci4gIFRoZSBkZWZhdWx0IGJlaGF2aW9yIGlzIHRvIGFjY2VwdCBhbGwgbmV3IGNvbm5lY3Rpb25zLlxuICAgICAqXG4gICAgICogQSBtYXAgb2YgY2xpZW50IGNvbm5lY3Rpb25zIGlzIHVwZGF0ZWQgYXV0b21hdGljYWxseSBvbiBjbGllbnQgY29ubmVjdGlvbiBhbmQgZGlzY29ubmVjdGlvbiBhbmQgc2F2ZWQgaW4gdGhlXG4gICAgICogW3JlYWQtb25seV0gYGNvbm5lY3Rpb25zYCBwcm9wZXJ0eSBvbiB0aGUgY2hhbm5lbFByb3ZpZGVyIGJ1cy4gIFRoZSBjaGFubmVsIHdpbGwgZXhpc3QgdW50aWwgdGhlIHByb3ZpZGVyXG4gICAgICogZGVzdHJveXMgaXQgb3IgZGlzY29ubmVjdHMgYnkgY2xvc2luZyBvciBkZXN0cm95aW5nIHRoZSBjb250ZXh0IChuYXZpZ2F0aW5nIG9yIHJlbG9hZGluZykuIFRvIHNldHVwIGEgY2hhbm5lbFxuICAgICAqIGFzIGEgY2hhbm5lbFByb3ZpZGVyLCBjYWxsIGBDaGFubmVsLmNyZWF0ZWAgd2l0aCBhIHVuaXF1ZSBjaGFubmVsIG5hbWUuIEEgbWFwIG9mIGNsaWVudCBjb25uZWN0aW9ucyBpcyB1cGRhdGVkXG4gICAgICogYXV0b21hdGljYWxseSBvbiBjbGllbnQgY29ubmVjdGlvbiBhbmQgZGlzY29ubmVjdGlvbi5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIChhc3luYyAoKT0+IHtcbiAgICAgKiAgICAvLyBlbnRpdHkgY3JlYXRlcyBhIGNoYW5uZWwgYW5kIGJlY29tZXMgdGhlIGNoYW5uZWxQcm92aWRlclxuICAgICAqICAgIGNvbnN0IHByb3ZpZGVyQnVzID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoJ2NoYW5uZWxOYW1lJyk7XG4gICAgICpcbiAgICAgKiAgICBwcm92aWRlckJ1cy5vbkNvbm5lY3Rpb24oKGlkZW50aXR5LCBwYXlsb2FkKSA9PiB7XG4gICAgICogICAgICAgIC8vIGNhbiByZWplY3QgYSBjb25uZWN0aW9uIGhlcmUgYnkgdGhyb3dpbmcgYW4gZXJyb3JcbiAgICAgKiAgICAgICAgY29uc29sZS5sb2coJ0NsaWVudCBjb25uZWN0aW9uIHJlcXVlc3QgaWRlbnRpdHk6ICcsIEpTT04uc3RyaW5naWZ5KGlkZW50aXR5KSk7XG4gICAgICogICAgICAgIGNvbnNvbGUubG9nKCdDbGllbnQgY29ubmVjdGlvbiByZXF1ZXN0IHBheWxvYWQ6ICcsIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgKiAgICB9KTtcbiAgICAgKlxuICAgICAqICAgIHByb3ZpZGVyQnVzLnJlZ2lzdGVyKCd0b3BpYycsIChwYXlsb2FkLCBpZGVudGl0eSkgPT4ge1xuICAgICAqICAgICAgICAvLyByZWdpc3RlciBhIGNhbGxiYWNrIGZvciBhICd0b3BpYycgdG8gd2hpY2ggY2xpZW50cyBjYW4gZGlzcGF0Y2ggYW4gYWN0aW9uXG4gICAgICogICAgICAgIGNvbnNvbGUubG9nKCdBY3Rpb24gZGlzcGF0Y2hlZCBieSBjbGllbnQ6ICcsIEpTT04uc3RyaW5naWZ5KGlkZW50aXR5KSk7XG4gICAgICogICAgICAgIGNvbnNvbGUubG9nKCdQYXlsb2FkIHNlbnQgaW4gZGlzcGF0Y2g6ICcsIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgKiAgICAgICAgcmV0dXJuIHtcbiAgICAgKiAgICAgICAgICAgIGVjaG86IHBheWxvYWRcbiAgICAgKiAgICAgICAgfTtcbiAgICAgKiAgICB9KTtcbiAgICAgKiB9KSgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGNyZWF0ZShjaGFubmVsTmFtZSwgb3B0aW9ucykge1xuICAgICAgICBpZiAoIWNoYW5uZWxOYW1lKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BsZWFzZSBwcm92aWRlIGEgY2hhbm5lbE5hbWUgdG8gY3JlYXRlIGEgY2hhbm5lbCcpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhOiBwcm92aWRlcklkZW50aXR5IH0gfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjcmVhdGUtY2hhbm5lbCcsIHsgY2hhbm5lbE5hbWUgfSk7XG4gICAgICAgIGNvbnN0IGNoYW5uZWwgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDYodGhpcywgX0NoYW5uZWxfY29ubmVjdGlvbk1hbmFnZXIsIFwiZlwiKS5jcmVhdGVQcm92aWRlcihvcHRpb25zLCBwcm92aWRlcklkZW50aXR5KTtcbiAgICAgICAgLy8gVE9ETzogZml4IHR5cGluZyAoaW50ZXJuYWwpXG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgdGhpcy5vbignY2xpZW50LWRpc2Nvbm5lY3RlZCcsIChldmVudFBheWxvYWQpID0+IHtcbiAgICAgICAgICAgIGlmIChldmVudFBheWxvYWQuY2hhbm5lbE5hbWUgPT09IGNoYW5uZWxOYW1lKSB7XG4gICAgICAgICAgICAgICAgcHJvdmlkZXJfMS5DaGFubmVsUHJvdmlkZXIuaGFuZGxlQ2xpZW50RGlzY29ubmVjdGlvbihjaGFubmVsLCBldmVudFBheWxvYWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNoYW5uZWw7XG4gICAgfVxufVxuY2hhbm5lbCQxLkNoYW5uZWwgPSBDaGFubmVsO1xuX0NoYW5uZWxfY29ubmVjdGlvbk1hbmFnZXIgPSBuZXcgV2Vha01hcCgpLCBfQ2hhbm5lbF9pbnRlcm5hbEVtaXR0ZXIgPSBuZXcgV2Vha01hcCgpLCBfQ2hhbm5lbF9yZWFkeVRvQ29ubmVjdCA9IG5ldyBXZWFrTWFwKCk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShpbnRlcmFwcGJ1cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5pbnRlcmFwcGJ1cy5JbnRlckFwcFBheWxvYWQgPSBpbnRlcmFwcGJ1cy5JbnRlckFwcGxpY2F0aW9uQnVzID0gdm9pZCAwO1xuLyoqXG4gKiBFbnRyeSBwb2ludCBmb3IgdGhlIE9wZW5GaW4gYEludGVyQXBwbGljYXRpb25CdXNgIEFQSSAoYGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzYCkuXG4gKlxuICogKiB7QGxpbmsgSW50ZXJBcHBsaWNhdGlvbkJ1c30gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBJbnRlckFwcGxpY2F0aW9uQnVzYCBBUEksIGFjY2Vzc2libGUgdGhyb3VnaCBgZmluLkludGVyQXBwbGljYXRpb25CdXNgLlxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5jb25zdCBldmVudHNfMSQ0ID0gcmVxdWlyZSQkMDtcbmNvbnN0IGJhc2VfMSRkID0gYmFzZTtcbmNvbnN0IHJlZl9jb3VudGVyXzEgPSByZWZDb3VudGVyO1xuY29uc3QgaW5kZXhfMSQyID0gY2hhbm5lbCQxO1xuY29uc3QgdmFsaWRhdGVfMSQzID0gdmFsaWRhdGU7XG4vKipcbiAqIEEgbWVzc2FnaW5nIGJ1cyB0aGF0IGFsbG93cyBmb3IgcHViL3N1YiBtZXNzYWdpbmcgYmV0d2VlbiBkaWZmZXJlbnQgYXBwbGljYXRpb25zLlxuICpcbiAqL1xuY2xhc3MgSW50ZXJBcHBsaWNhdGlvbkJ1cyBleHRlbmRzIGJhc2VfMSRkLkJhc2Uge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHdpcmUpIHtcbiAgICAgICAgc3VwZXIod2lyZSk7XG4gICAgICAgIHRoaXMuZXZlbnRzID0ge1xuICAgICAgICAgICAgc3Vic2NyaWJlckFkZGVkOiAnc3Vic2NyaWJlci1hZGRlZCcsXG4gICAgICAgICAgICBzdWJzY3JpYmVyUmVtb3ZlZDogJ3N1YnNjcmliZXItcmVtb3ZlZCdcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5yZWZDb3VudGVyID0gbmV3IHJlZl9jb3VudGVyXzEuUmVmQ291bnRlcigpO1xuICAgICAgICB0aGlzLkNoYW5uZWwgPSBuZXcgaW5kZXhfMSQyLkNoYW5uZWwod2lyZSk7XG4gICAgICAgIHRoaXMuZW1pdHRlciA9IG5ldyBldmVudHNfMSQ0LkV2ZW50RW1pdHRlcigpO1xuICAgICAgICB3aXJlLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIodGhpcy5vbm1lc3NhZ2UuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMub24gPSB0aGlzLmVtaXR0ZXIub24uYmluZCh0aGlzLmVtaXR0ZXIpO1xuICAgICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyA9IHRoaXMuZW1pdHRlci5yZW1vdmVBbGxMaXN0ZW5lcnMuYmluZCh0aGlzLmVtaXR0ZXIpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBQdWJsaXNoZXMgYSBtZXNzYWdlIHRvIGFsbCBhcHBsaWNhdGlvbnMgcnVubmluZyBvbiBPcGVuRmluIFJ1bnRpbWUgdGhhdFxuICAgICAqIGFyZSBzdWJzY3JpYmVkIHRvIHRoZSBzcGVjaWZpZWQgdG9waWMuXG4gICAgICogQHBhcmFtIHRvcGljIFRoZSB0b3BpYyBvbiB3aGljaCB0aGUgbWVzc2FnZSBpcyBzZW50XG4gICAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gYmUgcHVibGlzaGVkLiBDYW4gYmUgZWl0aGVyIGEgcHJpbWl0aXZlXG4gICAgICogZGF0YSB0eXBlIChzdHJpbmcsIG51bWJlciwgb3IgYm9vbGVhbikgb3IgY29tcG9zaXRlIGRhdGEgdHlwZSAob2JqZWN0LCBhcnJheSlcbiAgICAgKiB0aGF0IGlzIGNvbXBvc2VkIG9mIG90aGVyIHByaW1pdGl2ZSBvciBjb21wb3NpdGUgZGF0YSB0eXBlc1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLnB1Ymxpc2goJ3RvcGljJywgJ2hlbGxvJykudGhlbigoKSA9PiBjb25zb2xlLmxvZygnUHVibGlzaGVkJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBwdWJsaXNoKHRvcGljLCBtZXNzYWdlKSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwdWJsaXNoLW1lc3NhZ2UnLCB7XG4gICAgICAgICAgICB0b3BpYyxcbiAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICBzb3VyY2VXaW5kb3dOYW1lOiB0aGlzLm1lLm5hbWVcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFNlbmRzIGEgbWVzc2FnZSB0byBhIHNwZWNpZmljIGFwcGxpY2F0aW9uIG9uIGEgc3BlY2lmaWMgdG9waWMuXG4gICAgICogQHBhcmFtIGRlc3RpbmF0aW9uIFRoZSBpZGVudGl0eSBvZiB0aGUgYXBwbGljYXRpb24gdG8gd2hpY2ggdGhlIG1lc3NhZ2UgaXMgc2VudFxuICAgICAqIEBwYXJhbSB0b3BpYyBUaGUgdG9waWMgb24gd2hpY2ggdGhlIG1lc3NhZ2UgaXMgc2VudFxuICAgICAqIEBwYXJhbSBtZXNzYWdlIFRoZSBtZXNzYWdlIHRvIGJlIHNlbnQuIENhbiBiZSBlaXRoZXIgYSBwcmltaXRpdmUgZGF0YVxuICAgICAqIHR5cGUgKHN0cmluZywgbnVtYmVyLCBvciBib29sZWFuKSBvciBjb21wb3NpdGUgZGF0YSB0eXBlIChvYmplY3QsIGFycmF5KSB0aGF0XG4gICAgICogaXMgY29tcG9zZWQgb2Ygb3RoZXIgcHJpbWl0aXZlIG9yIGNvbXBvc2l0ZSBkYXRhIHR5cGVzXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkludGVyQXBwbGljYXRpb25CdXMuc2VuZChmaW4ubWUsICd0b3BpYycsICdIZWxsbyB0aGVyZSEnKS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdNZXNzYWdlIHNlbnQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHNlbmQoZGVzdGluYXRpb24sIHRvcGljLCBtZXNzYWdlKSB7XG4gICAgICAgIGNvbnN0IGVycm9yTXNnID0gKDAsIHZhbGlkYXRlXzEkMy52YWxpZGF0ZUlkZW50aXR5KShkZXN0aW5hdGlvbik7XG4gICAgICAgIGlmIChlcnJvck1zZykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTXNnKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignc2VuZC1tZXNzYWdlJywge1xuICAgICAgICAgICAgZGVzdGluYXRpb25VdWlkOiBkZXN0aW5hdGlvbi51dWlkLFxuICAgICAgICAgICAgZGVzdGluYXRpb25XaW5kb3dOYW1lOiBkZXN0aW5hdGlvbi5uYW1lLFxuICAgICAgICAgICAgdG9waWMsXG4gICAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgICAgc291cmNlV2luZG93TmFtZTogdGhpcy5tZS5uYW1lXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTdWJzY3JpYmVzIHRvIG1lc3NhZ2VzIGZyb20gdGhlIHNwZWNpZmllZCBhcHBsaWNhdGlvbiBvbiB0aGUgc3BlY2lmaWVkIHRvcGljLlxuICAgICAqIEBwYXJhbSBzb3VyY2UgVGhpcyBvYmplY3QgaXMgZGVzY3JpYmVkIGluIHRoZSBJZGVudGl0eSBpbiB0aGUgdHlwZWRlZlxuICAgICAqIEBwYXJhbSB0b3BpYyBUaGUgdG9waWMgb24gd2hpY2ggdGhlIG1lc3NhZ2UgaXMgc2VudFxuICAgICAqIEBwYXJhbSBsaXN0ZW5lciBBIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW4gYSBtZXNzYWdlIGhhc1xuICAgICAqIGJlZW4gcmVjZWl2ZWQuIEl0IGlzIHBhc3NlZCB0aGUgbWVzc2FnZSwgdXVpZCBhbmQgbmFtZSBvZiB0aGUgc2VuZGluZyBhcHBsaWNhdGlvbi5cbiAgICAgKiBUaGUgbWVzc2FnZSBjYW4gYmUgZWl0aGVyIGEgcHJpbWl0aXZlIGRhdGEgdHlwZSAoc3RyaW5nLCBudW1iZXIsIG9yIGJvb2xlYW4pIG9yXG4gICAgICogY29tcG9zaXRlIGRhdGEgdHlwZSAob2JqZWN0LCBhcnJheSkgdGhhdCBpcyBjb21wb3NlZCBvZiBvdGhlciBwcmltaXRpdmUgb3IgY29tcG9zaXRlXG4gICAgICogZGF0YSB0eXBlc1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIC8vIHN1YnNjcmliZSB0byBhIHNwZWNpZmllZCBhcHBsaWNhdGlvblxuICAgICAqIGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLnN1YnNjcmliZShmaW4ubWUsICd0b3BpYycsIHN1Yl9tc2cgPT4gY29uc29sZS5sb2coc3ViX21zZykpLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ1N1YnNjcmliZWQgdG8gdGhlIHNwZWNpZmllZCBhcHBsaWNhdGlvbicpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICpcbiAgICAgKiAvLyBzdWJzY3JpYmUgdG8gd2lsZGNhcmRcbiAgICAgKiBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5zdWJzY3JpYmUoeyB1dWlkOiAnKicgfSwgJ3RvcGljJywgc3ViX21zZyA9PiBjb25zb2xlLmxvZyhzdWJfbXNnKSkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnU3Vic2NyaWJlZCB0byAqJykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBzdWJzY3JpYmUoc291cmNlLCB0b3BpYywgbGlzdGVuZXIpIHtcbiAgICAgICAgY29uc3Qgc3ViS2V5ID0gdGhpcy5jcmVhdGVTdWJzY3JpcHRpb25LZXkoc291cmNlLnV1aWQsIHNvdXJjZS5uYW1lIHx8ICcqJywgdG9waWMpO1xuICAgICAgICBjb25zdCBzZW5kU3Vic2NyaXB0aW9uID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3N1YnNjcmliZScsIHtcbiAgICAgICAgICAgICAgICBzb3VyY2VVdWlkOiBzb3VyY2UudXVpZCxcbiAgICAgICAgICAgICAgICBzb3VyY2VXaW5kb3dOYW1lOiBzb3VyY2UubmFtZSB8fCAnKicsXG4gICAgICAgICAgICAgICAgdG9waWMsXG4gICAgICAgICAgICAgICAgZGVzdGluYXRpb25XaW5kb3dOYW1lOiB0aGlzLm1lLm5hbWVcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBhbHJlYWR5U3Vic2NyaWJlZCA9ICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5lbWl0dGVyLm9uKHN1YktleSwgbGlzdGVuZXIpO1xuICAgICAgICByZXR1cm4gdGhpcy5yZWZDb3VudGVyLmFjdE9uRmlyc3Qoc3ViS2V5LCBzZW5kU3Vic2NyaXB0aW9uLCBhbHJlYWR5U3Vic2NyaWJlZCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFVuc3Vic2NyaWJlcyB0byBtZXNzYWdlcyBmcm9tIHRoZSBzcGVjaWZpZWQgYXBwbGljYXRpb24gb24gdGhlIHNwZWNpZmllZCB0b3BpYy5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIElmIHlvdSBhcmUgbGlzdGVuaW5nIHRvIGFsbCBhcHBzIG9uIGEgdG9waWMsIChpLmUgeW91IHBhc3NlZCBgeyB1dWlkOicqJyB9YCB0byB0aGUgc3Vic2NyaWJlIGZ1bmN0aW9uKVxuICAgICAqIHRoZW4geW91IG5lZWQgdG8gcGFzcyBgeyB1dWlkOicqJyB9YCB0byB1bnN1YnNjcmliZSBhcyB3ZWxsLiBJZiB5b3UgYXJlIGxpc3RlbmluZyB0byBhIHNwZWNpZmljIGFwcGxpY2F0aW9uLFxuICAgICAqIChpLmUgeW91IHBhc3NlZCBgeyB1dWlkOidzb21lX2FwcCcgfWAgdG8gdGhlIHN1YnNjcmliZSBmdW5jdGlvbikgdGhlbiB5b3UgbmVlZCB0byBwcm92aWRlIHRoZSBzYW1lIGlkZW50aWZpZXIgdG9cbiAgICAgKiB1bnN1YnNjcmliZSwgdW5zdWJzY3JpYmluZyB0byBgKmAgb24gdGhhdCBzYW1lIHRvcGljIHdpbGwgbm90IHVuaG9vayB5b3VyIGluaXRpYWwgbGlzdGVuZXIgb3RoZXJ3aXNlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHNvdXJjZSBUaGlzIG9iamVjdCBpcyBkZXNjcmliZWQgaW4gdGhlIElkZW50aXR5IGluIHRoZSB0eXBlZGVmXG4gICAgICogQHBhcmFtIHRvcGljIFRoZSB0b3BpYyBvbiB3aGljaCB0aGUgbWVzc2FnZSBpcyBzZW50XG4gICAgICogQHBhcmFtIGxpc3RlbmVyIEEgY2FsbGJhY2sgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggc3Vic2NyaWJlKClcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBsaXN0ZW5lciA9IGNvbnNvbGUubG9nO1xuICAgICAqXG4gICAgICogLy8gSWYgYW55IGFwcGxpY2F0aW9uIHB1Ymxpc2hlcyBhIG1lc3NhZ2Ugb24gdG9waWMgYGZvb2AsIG91ciBsaXN0ZW5lciB3aWxsIGJlIGNhbGxlZC5cbiAgICAgKiBhd2FpdCBmaW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5zdWJzY3JpYmUoeyB1dWlkOicqJyB9LCAnZm9vJywgbGlzdGVuZXIpXG4gICAgICpcbiAgICAgKiAvLyBXaGVuIHlvdSB3YW50IHRvIHVuc3Vic2NyaWJlLCB5b3UgbmVlZCB0byBzcGVjaWZ5IHRoZSB1dWlkIG9mIHRoZSBhcHAgeW91J2QgbGlrZSB0b1xuICAgICAqIC8vIHVuc3Vic2NyaWJlIGZyb20gKG9yIGAqYCkgYW5kIHByb3ZpZGUgdGhlIHNhbWUgZnVuY3Rpb24geW91IGdhdmUgdGhlIHN1YnNjcmliZSBmdW5jdGlvblxuICAgICAqIGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLnVuc3Vic2NyaWJlKHsgdXVpZDonKicgfSwgJ2ZvbycsIGxpc3RlbmVyKVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHVuc3Vic2NyaWJlKHNvdXJjZSwgdG9waWMsIGxpc3RlbmVyKSB7XG4gICAgICAgIGNvbnN0IHNvdXJjZVdpbmRvd05hbWUgPSBzb3VyY2UubmFtZSB8fCAnKic7XG4gICAgICAgIGNvbnN0IHN1YktleSA9IHRoaXMuY3JlYXRlU3Vic2NyaXB0aW9uS2V5KHNvdXJjZS51dWlkLCBzb3VyY2VXaW5kb3dOYW1lLCB0b3BpYyk7XG4gICAgICAgIGNvbnN0IHNlbmRVbnN1YnNjcmlwdGlvbiA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCd1bnN1YnNjcmliZScsIHtcbiAgICAgICAgICAgICAgICBzb3VyY2VVdWlkOiBzb3VyY2UudXVpZCxcbiAgICAgICAgICAgICAgICBzb3VyY2VXaW5kb3dOYW1lLFxuICAgICAgICAgICAgICAgIHRvcGljLFxuICAgICAgICAgICAgICAgIGRlc3RpbmF0aW9uV2luZG93TmFtZTogdGhpcy5tZS5uYW1lXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZG9udFNlbmRVbnN1YnNjcmlwdGlvbiA9ICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocikgPT4gcikudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIoc3ViS2V5LCBsaXN0ZW5lcik7XG4gICAgICAgIHJldHVybiB0aGlzLnJlZkNvdW50ZXIuYWN0T25MYXN0KHN1YktleSwgc2VuZFVuc3Vic2NyaXB0aW9uLCBkb250U2VuZFVuc3Vic2NyaXB0aW9uKTtcbiAgICB9XG4gICAgcHJvY2Vzc01lc3NhZ2UobWVzc2FnZSkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQ6IHsgbWVzc2FnZTogcGF5bG9hZE1lc3NhZ2UsIHNvdXJjZVdpbmRvd05hbWUsIHNvdXJjZVV1aWQsIHRvcGljIH0gfSA9IG1lc3NhZ2U7XG4gICAgICAgIGNvbnN0IGtleXMgPSBbXG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVN1YnNjcmlwdGlvbktleShzb3VyY2VVdWlkLCBzb3VyY2VXaW5kb3dOYW1lLCB0b3BpYyksXG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVN1YnNjcmlwdGlvbktleShzb3VyY2VVdWlkLCAnKicsIHRvcGljKSxcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlU3Vic2NyaXB0aW9uS2V5KCcqJywgJyonLCB0b3BpYylcbiAgICAgICAgXTtcbiAgICAgICAgY29uc3QgaWRPZlNlbmRlciA9IHsgdXVpZDogc291cmNlVXVpZCwgbmFtZTogc291cmNlV2luZG93TmFtZSB9O1xuICAgICAgICBrZXlzLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lbWl0dGVyLmVtaXQoa2V5LCBwYXlsb2FkTWVzc2FnZSwgaWRPZlNlbmRlcik7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBlbWl0U3Vic2NyaXZlckV2ZW50KHR5cGUsIG1lc3NhZ2UpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkOiB7IHRhcmdldE5hbWU6IG5hbWUsIHV1aWQsIHRvcGljIH0gfSA9IG1lc3NhZ2U7XG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSB7IG5hbWUsIHV1aWQsIHRvcGljIH07XG4gICAgICAgIHRoaXMuZW1pdHRlci5lbWl0KHR5cGUsIHBheWxvYWQpO1xuICAgIH1cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuICAgIGNyZWF0ZVN1YnNjcmlwdGlvbktleSh1dWlkLCBuYW1lLCB0b3BpYykge1xuICAgICAgICBjb25zdCBuID0gbmFtZSB8fCAnKic7XG4gICAgICAgIGlmICghKHV1aWQgJiYgbiAmJiB0b3BpYykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTWlzc2luZyB1dWlkLCBuYW1lLCBvciB0b3BpYyBzdHJpbmcnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY3JlYXRlS2V5KHV1aWQsIG4sIHRvcGljKTtcbiAgICB9XG4gICAgb25tZXNzYWdlKG1lc3NhZ2UpIHtcbiAgICAgICAgY29uc3QgeyBhY3Rpb24gfSA9IG1lc3NhZ2U7XG4gICAgICAgIHN3aXRjaCAoYWN0aW9uKSB7XG4gICAgICAgICAgICBjYXNlICdwcm9jZXNzLW1lc3NhZ2UnOlxuICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc01lc3NhZ2UobWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHRoaXMuZXZlbnRzLnN1YnNjcmliZXJBZGRlZDpcbiAgICAgICAgICAgICAgICB0aGlzLmVtaXRTdWJzY3JpdmVyRXZlbnQodGhpcy5ldmVudHMuc3Vic2NyaWJlckFkZGVkLCBtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgdGhpcy5ldmVudHMuc3Vic2NyaWJlclJlbW92ZWQ6XG4gICAgICAgICAgICAgICAgdGhpcy5lbWl0U3Vic2NyaXZlckV2ZW50KHRoaXMuZXZlbnRzLnN1YnNjcmliZXJSZW1vdmVkLCBtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59XG5pbnRlcmFwcGJ1cy5JbnRlckFwcGxpY2F0aW9uQnVzID0gSW50ZXJBcHBsaWNhdGlvbkJ1cztcbi8qKlxuICogQGludGVybmFsXG4gKi9cbmNsYXNzIEludGVyQXBwUGF5bG9hZCB7XG59XG5pbnRlcmFwcGJ1cy5JbnRlckFwcFBheWxvYWQgPSBJbnRlckFwcFBheWxvYWQ7XG5mdW5jdGlvbiBjcmVhdGVLZXkoLi4udG9IYXNoKSB7XG4gICAgcmV0dXJuIHRvSGFzaFxuICAgICAgICAubWFwKChpdGVtKSA9PiB7XG4gICAgICAgIHJldHVybiBCdWZmZXIuZnJvbShgJHtpdGVtfWApLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICB9KVxuICAgICAgICAuam9pbignLycpO1xufVxuXG52YXIgY2xpcGJvYXJkID0ge307XG5cbi8qKlxuICogRW50cnkgcG9pbnQgZm9yIHRoZSBPcGVuRmluIGBDbGlwYm9hcmRgIEFQSSAoYGZpbi5DbGlwYm9hcmRgKS5cbiAqXG4gKiAqIHtAbGluayBDbGlwYm9hcmR9IGNvbnRhaW5zIHN0YXRpYyBtZW1iZXJzIG9mIHRoZSBgQ2xpcGJvYXJkYCBBUEksIGFjY2Vzc2libGUgdGhyb3VnaCBgZmluLkNsaXBib2FyZGAuXG4gKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShjbGlwYm9hcmQsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY2xpcGJvYXJkLkNsaXBib2FyZCA9IHZvaWQgMDtcbmNvbnN0IGJhc2VfMSRjID0gYmFzZTtcbi8qKlxuICogVGhlIENsaXBib2FyZCBBUEkgYWxsb3dzIHJlYWRpbmcgYW5kIHdyaXRpbmcgdG8gdGhlIGNsaXBib2FyZCBpbiBtdWx0aXBsZSBmb3JtYXRzLlxuICpcbiAqL1xuY2xhc3MgQ2xpcGJvYXJkIGV4dGVuZHMgYmFzZV8xJGMuQmFzZSB7XG4gICAgLyoqXG4gICAgICogV3JpdGVzIGRhdGEgaW50byB0aGUgY2xpcGJvYXJkIGFzIHBsYWluIHRleHRcbiAgICAgKiBAcGFyYW0gd3JpdGVPYmogVGhlIG9iamVjdCBmb3Igd3JpdGluZyBkYXRhIGludG8gdGhlIGNsaXBib2FyZFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5DbGlwYm9hcmQud3JpdGVUZXh0KHtcbiAgICAgKiAgICAgZGF0YTogJ2hlbGxvLCB3b3JsZCdcbiAgICAgKiB9KS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdUZXh0IE9uIGNsaXBib2FyZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgd3JpdGVUZXh0KHdyaXRlT2JqKSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjbGlwYm9hcmQtd3JpdGUtdGV4dCcsIHdyaXRlT2JqKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVhZCB0aGUgY29udGVudCBvZiB0aGUgY2xpcGJvYXJkIGFzIHBsYWluIHRleHRcbiAgICAgKiBAcGFyYW0gdHlwZSBDbGlwYm9hcmQgVHlwZSBkZWZhdWx0cyB0byAnY2xpcGJvYXJkJywgdXNlICdzZWxlY3Rpb24nIGZvciBsaW51eFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5DbGlwYm9hcmQucmVhZFRleHQoKS50aGVuKHRleHQgPT4gY29uc29sZS5sb2codGV4dCkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyByZWFkVGV4dCh0eXBlKSB7XG4gICAgICAgIC8vIE5PVEU6IFdoZW4gd2Ugc3RhcnQgc3VwcG9ydGluZyBsaW51eCwgd2UgY291bGQgZGV0ZWN0IHRoZSBPUyBhbmQgY2hvb3NlICdzZWxlY3Rpb24nIGF1dG9tYXRpY2FsbHkgZm9yIHRoZSB1c2VyXG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NsaXBib2FyZC1yZWFkLXRleHQnLCB7IHR5cGUgfSk7XG4gICAgICAgIHJldHVybiBwYXlsb2FkLmRhdGE7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBkYXRhIGludG8gdGhlIGNsaXBib2FyZCBhcyBhbiBJbWFnZVxuICAgICAqIEBwYXJhbSB3cml0ZVJlcXVlc3QgVGhlIG9iamVjdCB0byB3cml0ZSBhbiBpbWFnZSB0byB0aGUgY2xpcGJvYXJkXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogZmluLkNsaXBib2FyZC53cml0ZUltYWdlKHtcbiAgICAgKiAgIC8vIHJhdyBiYXNlNjQgc3RyaW5nLCBvciBkYXRhVVJMIG9mIGVpdGhlciBkYXRhOmltYWdlL3BuZyBvciBkYXRhOmltYWdlL2pwZWcgdHlwZVxuICAgICAqICAgaW1hZ2U6ICcuLi4nXG4gICAgICogfSkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnSW1hZ2Ugd3JpdHRlbiB0byBjbGlwYm9hcmQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHdyaXRlSW1hZ2Uod3JpdGVSZXF1ZXN0KSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjbGlwYm9hcmQtd3JpdGUtaW1hZ2UnLCB3cml0ZVJlcXVlc3QpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWFkIHRoZSBjb250ZW50IG9mIHRoZSBjbGlwYm9hcmQgYXMgYSBiYXNlNjQgc3RyaW5nIG9yIGEgZGF0YVVSTCBiYXNlZCBvbiB0aGUgaW5wdXQgcGFyYW1ldGVyICdmb3JtYXQnLCBkZWZhdWx0cyB0byAnZGF0YVVSTCdcbiAgICAgKiBAcGFyYW0gcmVhZFJlcXVlc3QgQ2xpcGJvYXJkIFJlYWQgSW1hZ2UgcmVxdWVzdCB3aXRoIGZvcm1hdHRpbmcgb3B0aW9uc1xuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIC8vIHNlZSBUUyB0eXBlOiBPcGVuRmluLkltYWdlRm9ybWF0T3B0aW9uc1xuICAgICAqXG4gICAgICogY29uc3QgcG5nT3JEYXRhVVJMT3JCbXBPcHRpb25zID0ge1xuICAgICAqICAgICBmb3JtYXQ6ICdwbmcnLCAvLyBjYW4gYmU6ICdwbmcnIHwgJ2RhdGFVUkwnIHwgJ2JtcCdcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogY29uc3QganBnT3B0aW9ucyA9IHtcbiAgICAgKiAgICAgZm9ybWF0OiAnanBnJyxcbiAgICAgKiAgICAgcXVhbGl0eTogODAgLy8gb3B0aW9uYWwsIGlmIG9taXR0ZWQgZGVmYXVsdHMgdG8gMTAwXG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIGZpbi5DbGlwYm9hcmQucmVhZEltYWdlKHBuZ09yRGF0YVVSTE9yQm1wT3B0aW9ucylcbiAgICAgKiAgICAgLnRoZW4oaW1hZ2UgPT4gY29uc29sZS5sb2coJ0ltYWdlIHJlYWQgZnJvbSBjbGlwYm9hcmQgYXMgUE5HLCBEYXRhVVJMIG9yIEJNUCcsIGltYWdlKSlcbiAgICAgKiAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKlxuICAgICAqIGZpbi5DbGlwYm9hcmQucmVhZEltYWdlKGpwZ09wdGlvbnMpXG4gICAgICogICAgIC50aGVuKGltYWdlID0+IGNvbnNvbGUubG9nKCdJbWFnZSByZWFkIGZyb20gY2xpcGJvYXJkIGFzIEpQRycsIGltYWdlKSlcbiAgICAgKiAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKlxuICAgICAqIC8vIGRlZmF1bHRzIHRvIHtmb3JtYXQ6ICdkYXRhVVJMJ31cbiAgICAgKiBmaW4uQ2xpcGJvYXJkLnJlYWRJbWFnZSgpXG4gICAgICogICAgIC50aGVuKGltYWdlID0+IGNvbnNvbGUubG9nKCdJbWFnZSByZWFkIGZyb20gY2xpcGJvYXJkIGFzIERhdGFVUkwnLCBpbWFnZSkpXG4gICAgICogICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICpcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyByZWFkSW1hZ2UocmVhZFJlcXVlc3QgPSB7IGZvcm1hdDogJ2RhdGFVUkwnIH0pIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignY2xpcGJvYXJkLXJlYWQtaW1hZ2UnLCByZWFkUmVxdWVzdCk7XG4gICAgICAgIHJldHVybiBwYXlsb2FkLmRhdGE7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBkYXRhIGludG8gdGhlIGNsaXBib2FyZCBhcyBIdG1sXG4gICAgICogQHBhcmFtIHdyaXRlT2JqIFRoZSBvYmplY3QgZm9yIHdyaXRpbmcgZGF0YSBpbnRvIHRoZSBjbGlwYm9hcmRcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uQ2xpcGJvYXJkLndyaXRlSHRtbCh7XG4gICAgICogICAgICAgICBkYXRhOiAnPGgxPkhlbGxvLCBXb3JsZCE8L2gxPidcbiAgICAgKiB9KS50aGVuKCgpID0+IGNvbnNvbGUubG9nKCdIVE1MIE9uIGNsaXBib2FyZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgd3JpdGVIdG1sKHdyaXRlT2JqKSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjbGlwYm9hcmQtd3JpdGUtaHRtbCcsIHdyaXRlT2JqKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmVhZCB0aGUgY29udGVudCBvZiB0aGUgY2xpcGJvYXJkIGFzIEh0bWxcbiAgICAgKiBAcGFyYW0gdHlwZSBDbGlwYm9hcmQgVHlwZSBkZWZhdWx0cyB0byAnY2xpcGJvYXJkJywgdXNlICdzZWxlY3Rpb24nIGZvciBsaW51eFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5DbGlwYm9hcmQucmVhZEh0bWwoKS50aGVuKGh0bWwgPT4gY29uc29sZS5sb2coaHRtbCkpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyByZWFkSHRtbCh0eXBlKSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NsaXBib2FyZC1yZWFkLWh0bWwnLCB7IHR5cGUgfSk7XG4gICAgICAgIHJldHVybiBwYXlsb2FkLmRhdGE7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFdyaXRlcyBkYXRhIGludG8gdGhlIGNsaXBib2FyZCBhcyBSdGZcbiAgICAgKiBAcGFyYW0gd3JpdGVPYmogVGhlIG9iamVjdCBmb3Igd3JpdGluZyBkYXRhIGludG8gdGhlIGNsaXBib2FyZFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5DbGlwYm9hcmQud3JpdGVSdGYoe1xuICAgICAqICAgICAgICAgZGF0YTogJ3NvbWUgdGV4dCBnb2VzIGhlcmUnXG4gICAgICogfSkudGhlbigoKSA9PiBjb25zb2xlLmxvZygnUlRGIE9uIGNsaXBib2FyZCcpKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgd3JpdGVSdGYod3JpdGVPYmopIHtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2NsaXBib2FyZC13cml0ZS1ydGYnLCB3cml0ZU9iaik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlYWQgdGhlIGNvbnRlbnQgb2YgdGhlIGNsaXBib2FyZCBhcyBSdGZcbiAgICAgKiBAcGFyYW0gdHlwZSBDbGlwYm9hcmQgVHlwZSBkZWZhdWx0cyB0byAnY2xpcGJvYXJkJywgdXNlICdzZWxlY3Rpb24nIGZvciBsaW51eFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3Qgd3JpdGVPYmogPSB7XG4gICAgICogICAgIGRhdGE6ICdzb21lIHRleHQgZ29lcyBoZXJlJ1xuICAgICAqIH07XG4gICAgICogYXN5bmMgZnVuY3Rpb24gcmVhZFJ0ZigpIHtcbiAgICAgKiAgICAgYXdhaXQgZmluLkNsaXBib2FyZC53cml0ZVJ0Zih3cml0ZU9iaik7XG4gICAgICogICAgIHJldHVybiBhd2FpdCBmaW4uQ2xpcGJvYXJkLnJlYWRSdGYoKTtcbiAgICAgKiB9XG4gICAgICogcmVhZFJ0ZigpLnRoZW4ocnRmID0+IGNvbnNvbGUubG9nKHJ0ZikpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyByZWFkUnRmKHR5cGUpIHtcbiAgICAgICAgY29uc3QgeyBwYXlsb2FkIH0gPSBhd2FpdCB0aGlzLndpcmUuc2VuZEFjdGlvbignY2xpcGJvYXJkLXJlYWQtcnRmJywgeyB0eXBlIH0pO1xuICAgICAgICByZXR1cm4gcGF5bG9hZC5kYXRhO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBXcml0ZXMgZGF0YSBpbnRvIHRoZSBjbGlwYm9hcmRcbiAgICAgKiBAcGFyYW0gd3JpdGVPYmogVGhlIG9iamVjdCBmb3Igd3JpdGluZyBkYXRhIGludG8gdGhlIGNsaXBib2FyZFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5DbGlwYm9hcmQud3JpdGUoe1xuICAgICAqICAgZGF0YToge1xuICAgICAqICAgICB0ZXh0OiAnYScsXG4gICAgICogICAgIGh0bWw6ICdiJyxcbiAgICAgKiAgICAgcnRmOiAnYycsXG4gICAgICogICAgIC8vIENhbiBiZSBlaXRoZXIgYSBiYXNlNjQgc3RyaW5nLCBvciBhIERhdGFVUkwgc3RyaW5nLiBJZiB1c2luZyBEYXRhVVJMLCB0aGVcbiAgICAgKiAgICAgLy8gc3VwcG9ydGVkIGZvcm1hdHMgYXJlIGBkYXRhOmltYWdlL3BuZ1s7YmFzZTY0XSxgIGFuZCBgZGF0YTppbWFnZS9qcGVnWztiYXNlNjRdLGAuXG4gICAgICogICAgIC8vIFVzaW5nIG90aGVyIGltYWdlLzxmb3JtYXQ+IERhdGFVUkxzIHdpbGwgdGhyb3cgYW4gRXJyb3IuXG4gICAgICogICAgIGltYWdlOiAnLi4uJ1xuICAgICAqICAgfVxuICAgICAqIH0pLnRoZW4oKCkgPT4gY29uc29sZS5sb2coJ3dyaXRlIGRhdGEgaW50byBjbGlwYm9hcmQnKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHdyaXRlKHdyaXRlT2JqKSB7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjbGlwYm9hcmQtd3JpdGUnLCB3cml0ZU9iaik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJlYWRzIGF2YWlsYWJsZSBmb3JtYXRzIGZvciB0aGUgY2xpcGJvYXJkIHR5cGVcbiAgICAgKiBAcGFyYW0gdHlwZSBDbGlwYm9hcmQgVHlwZSBkZWZhdWx0cyB0byAnY2xpcGJvYXJkJywgdXNlICdzZWxlY3Rpb24nIGZvciBsaW51eFxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5DbGlwYm9hcmQuZ2V0QXZhaWxhYmxlRm9ybWF0cygpLnRoZW4oZm9ybWF0cyA9PiBjb25zb2xlLmxvZyhmb3JtYXRzKSkuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGdldEF2YWlsYWJsZUZvcm1hdHModHlwZSkge1xuICAgICAgICBjb25zdCB7IHBheWxvYWQgfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdjbGlwYm9hcmQtcmVhZC1mb3JtYXRzJywgeyB0eXBlIH0pO1xuICAgICAgICByZXR1cm4gcGF5bG9hZC5kYXRhO1xuICAgIH1cbn1cbmNsaXBib2FyZC5DbGlwYm9hcmQgPSBDbGlwYm9hcmQ7XG5cbnZhciBleHRlcm5hbEFwcGxpY2F0aW9uID0ge307XG5cbnZhciBGYWN0b3J5JDUgPSB7fTtcblxudmFyIEluc3RhbmNlJDQgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KEluc3RhbmNlJDQsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuSW5zdGFuY2UkNC5FeHRlcm5hbEFwcGxpY2F0aW9uID0gdm9pZCAwO1xuLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L3ByZWZlci1kZWZhdWx0LWV4cG9ydCAqL1xuY29uc3QgYmFzZV8xJGIgPSBiYXNlO1xuLyoqXG4gKiBBbiBFeHRlcm5hbEFwcGxpY2F0aW9uIG9iamVjdCByZXByZXNlbnRpbmcgbmF0aXZlIGxhbmd1YWdlIGFkYXB0ZXIgY29ubmVjdGlvbnMgdG8gdGhlIHJ1bnRpbWUuIEFsbG93c1xuICogdGhlIGRldmVsb3BlciB0byBsaXN0ZW4gdG8ge0BsaW5rIE9wZW5GaW4uRXh0ZXJuYWxBcHBsaWNhdGlvbkV2ZW50cyBleHRlcm5hbCBhcHBsaWNhdGlvbiBldmVudHN9LlxuICogRGlzY292ZXJ5IG9mIGNvbm5lY3Rpb25zIGlzIHByb3ZpZGVkIGJ5IHtAbGluayBTeXN0ZW0uU3lzdGVtLmdldEFsbEV4dGVybmFsQXBwbGljYXRpb25zIGdldEFsbEV4dGVybmFsQXBwbGljYXRpb25zfS48L2E+XG4gKlxuICogUHJvY2Vzc2VzIHRoYXQgY2FuIGJlIHdyYXBwZWQgYXMgYEV4dGVybmFsQXBwbGljYXRpb25gcyBpbmNsdWRlIHRoZSBmb2xsb3dpbmc6XG4gKiAtIFByb2Nlc3NlcyB3aGljaCBoYXZlIGNvbm5lY3RlZCB0byBhbiBPcGVuRmluIHJ1bnRpbWUgdmlhIGFuIGFkYXB0ZXJcbiAqIC0gUHJvY2Vzc2VzIHN0YXJ0ZWQgdmlhIGBTeXN0ZW0ubGF1bmNoRXh0ZXJuYWxBcHBsaWNhdGlvbmBcbiAqIC0gUHJvY2Vzc2VzIG1vbml0b3JlZCB2aWEgYFN5c3RlbS5tb25pdG9yRXh0ZXJuYWxQcm9jZXNzYFxuICovXG5jbGFzcyBFeHRlcm5hbEFwcGxpY2F0aW9uIGV4dGVuZHMgYmFzZV8xJGIuRW1pdHRlckJhc2Uge1xuICAgIC8qKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHdpcmUsIGlkZW50aXR5KSB7XG4gICAgICAgIHN1cGVyKHdpcmUsICdleHRlcm5hbC1hcHBsaWNhdGlvbicsIGlkZW50aXR5LnV1aWQpO1xuICAgICAgICB0aGlzLmlkZW50aXR5ID0gaWRlbnRpdHk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlcyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZXh0ZXJuYWwgYXBwbGljYXRpb24uXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0SW5mbygpIHtcbiAgICAgKiAgICAgY29uc3QgZXh0QXBwID0gYXdhaXQgZmluLkV4dGVybmFsQXBwbGljYXRpb24ud3JhcCgnamF2YUFwcC11dWlkJyk7XG4gICAgICogICAgIHJldHVybiBhd2FpdCBleHRBcHAuZ2V0SW5mbygpO1xuICAgICAqIH1cbiAgICAgKiBnZXRJbmZvKCkudGhlbihpbmZvID0+IGNvbnNvbGUubG9nKGluZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0SW5mbygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnZXQtZXh0ZXJuYWwtYXBwbGljYXRpb24taW5mbycsIHRoaXMuaWRlbnRpdHkpLnRoZW4oKHsgcGF5bG9hZCB9KSA9PiBwYXlsb2FkLmRhdGEpO1xuICAgIH1cbn1cbkluc3RhbmNlJDQuRXh0ZXJuYWxBcHBsaWNhdGlvbiA9IEV4dGVybmFsQXBwbGljYXRpb247XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShGYWN0b3J5JDUsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuRmFjdG9yeSQ1LkV4dGVybmFsQXBwbGljYXRpb25Nb2R1bGUgPSB2b2lkIDA7XG5jb25zdCBiYXNlXzEkYSA9IGJhc2U7XG5jb25zdCBJbnN0YW5jZV8xJDQgPSBJbnN0YW5jZSQ0O1xuLyoqXG4gKiBTdGF0aWMgbmFtZXNwYWNlIGZvciBPcGVuRmluIEFQSSBtZXRob2RzIHRoYXQgaW50ZXJhY3Qgd2l0aCB0aGUge0BsaW5rIEV4dGVybmFsQXBwbGljYXRpb259IGNsYXNzLCBhdmFpbGFibGUgdW5kZXIgYGZpbi5FeHRlcm5hbEFwcGxpY2F0aW9uYC5cbiAqL1xuY2xhc3MgRXh0ZXJuYWxBcHBsaWNhdGlvbk1vZHVsZSBleHRlbmRzIGJhc2VfMSRhLkJhc2Uge1xuICAgIC8qKlxuICAgICAqIEFzeW5jaHJvbm91c2x5IHJldHVybnMgYW4gRXh0ZXJuYWwgQXBwbGljYXRpb24gb2JqZWN0IHRoYXQgcmVwcmVzZW50cyBhbiBleHRlcm5hbCBhcHBsaWNhdGlvbi5cbiAgICAgKiA8YnI+SXQgaXMgcG9zc2libGUgdG8gd3JhcCBhIHByb2Nlc3MgdGhhdCBkb2VzIG5vdCB5ZXQgZXhpc3QsIChmb3IgZXhhbXBsZSwgdG8gbGlzdGVuIGZvciBzdGFydHVwLXJlbGF0ZWQgZXZlbnRzKVxuICAgICAqIHByb3ZpZGVkIGl0cyB1dWlkIGlzIGFscmVhZHkga25vd24uXG4gICAgICogQHBhcmFtIHV1aWQgVGhlIFVVSUQgb2YgdGhlIGV4dGVybmFsIGFwcGxpY2F0aW9uIHRvIGJlIHdyYXBwZWRcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uRXh0ZXJuYWxBcHBsaWNhdGlvbi53cmFwKCdqYXZhQXBwLXV1aWQnKTtcbiAgICAgKiAudGhlbihleHRBcHAgPT4gY29uc29sZS5sb2coJ3dyYXBwZWQgZXh0ZXJuYWwgYXBwbGljYXRpb24nKSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IGNvbnNvbGUubG9nKGVycikpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHdyYXAodXVpZCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZXh0ZXJuYWwtYXBwbGljYXRpb24td3JhcCcpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IEluc3RhbmNlXzEkNC5FeHRlcm5hbEFwcGxpY2F0aW9uKHRoaXMud2lyZSwgeyB1dWlkIH0pKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGFuIEV4dGVybmFsIEFwcGxpY2F0aW9uIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgYW4gZXh0ZXJuYWwgYXBwbGljYXRpb24uXG4gICAgICogPGJyPkl0IGlzIHBvc3NpYmxlIHRvIHdyYXAgYSBwcm9jZXNzIHRoYXQgZG9lcyBub3QgeWV0IGV4aXN0LCAoZm9yIGV4YW1wbGUsIHRvIGxpc3RlbiBmb3Igc3RhcnR1cC1yZWxhdGVkIGV2ZW50cylcbiAgICAgKiBwcm92aWRlZCBpdHMgdXVpZCBpcyBhbHJlYWR5IGtub3duLlxuICAgICAqIEBwYXJhbSB1dWlkIFRoZSBVVUlEIG9mIHRoZSBleHRlcm5hbCBhcHBsaWNhdGlvbiB0byBiZSB3cmFwcGVkXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgZXh0QXBwID0gZmluLkV4dGVybmFsQXBwbGljYXRpb24ud3JhcFN5bmMoJ2phdmFBcHAtdXVpZCcpO1xuICAgICAqIGNvbnN0IGluZm8gPSBhd2FpdCBleHRBcHAuZ2V0SW5mbygpO1xuICAgICAqIGNvbnNvbGUubG9nKGluZm8pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHdyYXBTeW5jKHV1aWQpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2V4dGVybmFsLWFwcGxpY2F0aW9uLXdyYXAtc3luYycpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMSQ0LkV4dGVybmFsQXBwbGljYXRpb24odGhpcy53aXJlLCB7IHV1aWQgfSk7XG4gICAgfVxufVxuRmFjdG9yeSQ1LkV4dGVybmFsQXBwbGljYXRpb25Nb2R1bGUgPSBFeHRlcm5hbEFwcGxpY2F0aW9uTW9kdWxlO1xuXG4oZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0ICAgIH1cblx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgb1trMl0gPSBtW2tdO1xuXHR9KSk7XG5cdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0LyoqXG5cdCAqIEVudHJ5IHBvaW50cyBmb3IgdGhlIE9wZW5GaW4gYEV4dGVybmFsQXBwbGljYXRpb25gIEFQSSAoYGZpbi5FeHRlcm5hbEFwcGxpY2F0aW9uYCkuXG5cdCAqXG5cdCAqICoge0BsaW5rIEV4dGVybmFsQXBwbGljYXRpb25Nb2R1bGV9IGNvbnRhaW5zIHN0YXRpYyBtZW1iZXJzIG9mIHRoZSBgRXh0ZXJuYWxBcHBsaWNhdGlvbmAgdHlwZSwgYWNjZXNzaWJsZSB0aHJvdWdoIGBmaW4uRXh0ZXJuYWxBcHBsaWNhdGlvbmAuXG5cdCAqICoge0BsaW5rIEV4dGVybmFsQXBwbGljYXRpb259IGRlc2NyaWJlcyBhbiBpbnN0YW5jZSBvZiBhbiBPcGVuRmluIEV4dGVybmFsQXBwbGljYXRpb24sIGUuZy4gYXMgcmV0dXJuZWQgYnkgYGZpbi5FeHRlcm5hbEFwcGxpY2F0aW9uLmdldEN1cnJlbnRgLlxuXHQgKlxuXHQgKiBUaGVzZSBhcmUgc2VwYXJhdGUgY29kZSBlbnRpdGllcywgYW5kIGFyZSBkb2N1bWVudGVkIHNlcGFyYXRlbHkuICBJbiB0aGUgW3ByZXZpb3VzIHZlcnNpb24gb2YgdGhlIEFQSSBkb2N1bWVudGF0aW9uXShodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC8zMi4xMTQuNzYuMTAvaW5kZXguaHRtbCksXG5cdCAqIGJvdGggb2YgdGhlc2Ugd2VyZSBkb2N1bWVudGVkIG9uIHRoZSBzYW1lIHBhZ2UuXG5cdCAqXG5cdCAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuXHQgKi9cblx0X19leHBvcnRTdGFyKEZhY3RvcnkkNSwgZXhwb3J0cyk7XG5cdF9fZXhwb3J0U3RhcihJbnN0YW5jZSQ0LCBleHBvcnRzKTsgXG59IChleHRlcm5hbEFwcGxpY2F0aW9uKSk7XG5cbnZhciBmcmFtZSA9IHt9O1xuXG52YXIgRmFjdG9yeSQ0ID0ge307XG5cbnZhciBJbnN0YW5jZSQzID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShJbnN0YW5jZSQzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbkluc3RhbmNlJDMuX0ZyYW1lID0gdm9pZCAwO1xuLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L3ByZWZlci1kZWZhdWx0LWV4cG9ydCAqL1xuY29uc3QgYmFzZV8xJDkgPSBiYXNlO1xuLyoqXG4gKiBBbiBpZnJhbWUgcmVwcmVzZW50cyBhbiBlbWJlZGRlZCBIVE1MIHBhZ2Ugd2l0aGluIGEgcGFyZW50IEhUTUwgcGFnZS4gQmVjYXVzZSB0aGlzIGVtYmVkZGVkIHBhZ2VcbiAqIGhhcyBpdHMgb3duIERPTSBhbmQgZ2xvYmFsIEpTIGNvbnRleHQgKHdoaWNoIG1heSBvciBtYXkgbm90IGJlIGxpbmtlZCB0byB0aGF0IG9mIHRoZSBwYXJlbnQgZGVwZW5kaW5nXG4gKiBvbiBpZiBpdCBpcyBjb25zaWRlcmVkIG91dCBvZiB0aGUgcm9vdCBkb21haW4gb3Igbm90KSwgaXQgcmVwcmVzZW50cyBhIHVuaXF1ZSBlbmRwb2ludCBhcyBhbiBPcGVuRmluXG4gKiBjb25uZWN0aW9uLiBJZnJhbWVzIG1heSBiZSBnZW5lcmF0ZWQgZHluYW1pY2FsbHksIG9yIGJlIHByZXNlbnQgb24gaW5pdGlhbCBwYWdlIGxvYWQgYW5kIGVhY2ggbm9uLUNPUlNcbiAqIGlmcmFtZSBoYXMgdGhlIE9wZW5GaW4gQVBJIGluamVjdGVkIGJ5IGRlZmF1bHQuIEl0IGlzIHBvc3NpYmxlIHRvIG9wdCBpbnRvIGNyb3NzLW9yaWdpbiBpZnJhbWVzIGhhdmluZ1xuICogdGhlIEFQSSBieSBzZXR0aW5nIGFwaS5pZnJhbWUuY3Jvc3NPcmlnaW5JbmplY3Rpb24gdG8gdHJ1ZSBpbiBhIHdpbmRvdydzIG9wdGlvbnMuIFRvIGJsb2NrIGFsbCBpZnJhbWVzXG4gKiBmcm9tIGdldHRpbmcgdGhlIEFQSSBpbmplY3RlZCB5b3UgY2FuIHNldCBhcGkuZnJhbWUuc2FtZU9yaWdpbkluamVjdGlvblxuICogdG8gZmFsc2UgPGEgaHJlZj1cIldpbmRvdy5odG1sI35vcHRpb25zXCIgdGFyZ2V0PVwiX2JsYW5rXCI+KHtAbGluayBPcGVuRmluLldpbmRvd0NyZWF0aW9uT3B0aW9ucyBzZWUgV2luZG93IE9wdGlvbnN9KTwvYT4uXG4gKlxuICogVG8gYmUgYWJsZSB0byBkaXJlY3RseSBhZGRyZXNzIHRoaXMgY29udGV4dCBmb3IgZXZlbnRpbmcgYW5kIG1lc3NhZ2luZyBwdXJwb3NlcywgaXQgbmVlZHMgYVxuICogdW5pcXVlIHV1aWQgbmFtZSBwYWlyaW5nLiBGb3IgT3BlbkZpbiBhcHBsaWNhdGlvbnMgYW5kIHdpbmRvd3MgdGhpcyBpcyBwcm92aWRlZCB2aWEgYSBjb25maWd1cmF0aW9uXG4gKiBvYmplY3QgaW4gdGhlIGZvcm0gb2YgYSBtYW5pZmVzdCBVUkwgb3Igb3B0aW9ucyBvYmplY3QsIGJ1dCB0aGVyZSBpcyBubyBjb25maWd1cmF0aW9uIG9iamVjdCBmb3IgaWZyYW1lcy5cbiAqIEp1c3QgYXMgYSBjYWxsIHRvIHdpbmRvdy5vcGVuIG91dHNpZGUgb2Ygb3VyIFdpbmRvdyBBUEkgcmV0dXJucyBhIG5ldyB3aW5kb3cgd2l0aCBhIHJhbmRvbSBHVUlEIGFzc2lnbmVkXG4gKiBmb3IgdGhlIG5hbWUsIGVhY2ggaWZyYW1lIHRoYXQgaGFzIHRoZSBBUEkgaW5qZWN0ZWQgd2lsbCBiZSBhc3NpZ25lZCBhIEdVSUQgYXMgaXRzIG5hbWUsIHRoZSBVVUlEIHdpbGwgYmVcbiAqIHRoZSBzYW1lIGFzIHRoZSBwYXJlbnQgd2luZG93J3MuXG4gKlxuICogVGhlIGZpbi5GcmFtZSBuYW1lc3BhY2UgcmVwcmVzZW50cyBhIHdheSB0byBpbnRlcmFjdCB3aXRoIGBpZnJhbWVzYCBhbmQgZmFjaWxpdGF0ZXMgdGhlIGRpc2NvdmVyeSBvZiBjdXJyZW50IGNvbnRleHRcbiAqIChpZnJhbWUgb3IgbWFpbiB3aW5kb3cpIGFzIHdlbGwgYXMgdGhlIGFiaWxpdHkgdG8gbGlzdGVuIGZvciB7QGxpbmsgT3BlbkZpbi5GcmFtZUV2ZW50cyBmcmFtZS1zcGVjaWZpYyBldmVudHN9LlxuICovXG5jbGFzcyBfRnJhbWUgZXh0ZW5kcyBiYXNlXzEkOS5FbWl0dGVyQmFzZSB7XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iod2lyZSwgaWRlbnRpdHkpIHtcbiAgICAgICAgc3VwZXIod2lyZSwgJ2ZyYW1lJywgaWRlbnRpdHkudXVpZCwgaWRlbnRpdHkubmFtZSk7XG4gICAgICAgIHRoaXMuaWRlbnRpdHkgPSBpZGVudGl0eTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIGZyYW1lIGluZm8gb2JqZWN0IGZvciB0aGUgcmVwcmVzZW50ZWQgZnJhbWUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogYXN5bmMgZnVuY3Rpb24gZ2V0SW5mbygpIHtcbiAgICAgKiAgICAgY29uc3QgZnJtID0gYXdhaXQgZmluLkZyYW1lLmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGZybS5nZXRJbmZvKCk7XG4gICAgICogfVxuICAgICAqIGdldEluZm8oKS50aGVuKGluZm8gPT4gY29uc29sZS5sb2coaW5mbykpLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRJbmZvKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1mcmFtZS1pbmZvJywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBmcmFtZSBpbmZvIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIHdpbmRvdyB0aGF0IHRoZSByZWZlcmVuY2VkIGlmcmFtZSBpc1xuICAgICAqIGN1cnJlbnRseSBlbWJlZGRlZCBpbi5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIElmIHRoZSBmcmFtZSBpcyBlbWJlZGRlZCBpbiBhIHZpZXcsIHRoaXMgd2lsbCByZXR1cm4gYW4gaW52YWxpZCBzdHViIHdpdGggZW1wdHkgZmllbGRzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGFzeW5jIGZ1bmN0aW9uIGdldFBhcmVudFdpbmRvdygpIHtcbiAgICAgKiAgICAgY29uc3QgZnJtID0gYXdhaXQgZmluLkZyYW1lLmdldEN1cnJlbnQoKTtcbiAgICAgKiAgICAgcmV0dXJuIGF3YWl0IGZybS5nZXRQYXJlbnRXaW5kb3coKTtcbiAgICAgKiB9XG4gICAgICogZ2V0UGFyZW50V2luZG93KCkudGhlbih3aW5JbmZvID0+IGNvbnNvbGUubG9nKHdpbkluZm8pKS5jYXRjaChlcnIgPT4gY29uc29sZS5sb2coZXJyKSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0UGFyZW50V2luZG93KCkge1xuICAgICAgICByZXR1cm4gdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dldC1wYXJlbnQtd2luZG93JywgdGhpcy5pZGVudGl0eSkudGhlbigoeyBwYXlsb2FkIH0pID0+IHBheWxvYWQuZGF0YSk7XG4gICAgfVxufVxuSW5zdGFuY2UkMy5fRnJhbWUgPSBfRnJhbWU7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShGYWN0b3J5JDQsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuRmFjdG9yeSQ0Ll9GcmFtZU1vZHVsZSA9IHZvaWQgMDtcbmNvbnN0IGJhc2VfMSQ4ID0gYmFzZTtcbmNvbnN0IHZhbGlkYXRlXzEkMiA9IHZhbGlkYXRlO1xuY29uc3QgSW5zdGFuY2VfMSQzID0gSW5zdGFuY2UkMztcbi8qKlxuICogU3RhdGljIG5hbWVzcGFjZSBmb3IgT3BlbkZpbiBBUEkgbWV0aG9kcyB0aGF0IGludGVyYWN0IHdpdGggdGhlIHtAbGluayBfRnJhbWV9IGNsYXNzLCBhdmFpbGFibGUgdW5kZXIgYGZpbi5GcmFtZWAuXG4gKi9cbmNsYXNzIF9GcmFtZU1vZHVsZSBleHRlbmRzIGJhc2VfMSQ4LkJhc2Uge1xuICAgIC8qKlxuICAgICAqIEFzeW5jaHJvbm91c2x5IHJldHVybnMgYW4gQVBJIGhhbmRsZSBmb3IgdGhlIGdpdmVuIEZyYW1lIGlkZW50aXR5LlxuICAgICAqXG4gICAgICogQHJlbWFya3MgV3JhcHBpbmcgYSBGcmFtZSBpZGVudGl0eSB0aGF0IGRvZXMgbm90IHlldCBleGlzdCB3aWxsICpub3QqIHRocm93IGFuIGVycm9yLCBhbmQgaW5zdGVhZFxuICAgICAqIHJldHVybnMgYSBzdHViIG9iamVjdCB0aGF0IGNhbm5vdCB5ZXQgcGVyZm9ybSByZW5kZXJpbmcgdGFza3MuIFRoaXMgY2FuIGJlIHVzZWZ1bCBmb3IgcGx1bWJpbmcgZXZlbnRpbmdcbiAgICAgKiBmb3IgYSBGcmFtZSB0aHJvdWdob3V0IGl0cyBlbnRpcmUgbGlmZWN5Y2xlLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5GcmFtZS53cmFwKHsgdXVpZDogJ3Rlc3RGcmFtZScsIG5hbWU6ICd0ZXN0RnJhbWUnIH0pXG4gICAgICogLnRoZW4oZnJtID0+IGNvbnNvbGUubG9nKCd3cmFwcGVkIGZyYW1lJykpXG4gICAgICogLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyB3cmFwKGlkZW50aXR5KSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmcmFtZS13cmFwJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgZXJyb3JNc2cgPSAoMCwgdmFsaWRhdGVfMSQyLnZhbGlkYXRlSWRlbnRpdHkpKGlkZW50aXR5KTtcbiAgICAgICAgaWYgKGVycm9yTXNnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNc2cpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMSQzLl9GcmFtZSh0aGlzLndpcmUsIGlkZW50aXR5KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogU3luY2hyb25vdXNseSByZXR1cm5zIGFuIEFQSSBoYW5kbGUgZm9yIHRoZSBnaXZlbiBGcmFtZSBpZGVudGl0eS5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIFdyYXBwaW5nIGEgRnJhbWUgaWRlbnRpdHkgdGhhdCBkb2VzIG5vdCB5ZXQgZXhpc3Qgd2lsbCAqbm90KiB0aHJvdyBhbiBlcnJvciwgYW5kIGluc3RlYWRcbiAgICAgKiByZXR1cm5zIGEgc3R1YiBvYmplY3QgdGhhdCBjYW5ub3QgeWV0IHBlcmZvcm0gcmVuZGVyaW5nIHRhc2tzLiBUaGlzIGNhbiBiZSB1c2VmdWwgZm9yIHBsdW1iaW5nIGV2ZW50aW5nXG4gICAgICogZm9yIGEgRnJhbWUgdGhyb3VnaG91dCBpdHMgZW50aXJlIGxpZmVjeWNsZS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBmcm0gPSBmaW4uRnJhbWUud3JhcFN5bmMoeyB1dWlkOiAndGVzdEZyYW1lJywgbmFtZTogJ3Rlc3RGcmFtZScgfSk7XG4gICAgICogY29uc3QgaW5mbyA9IGF3YWl0IGZybS5nZXRJbmZvKCk7XG4gICAgICogY29uc29sZS5sb2coaW5mbyk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgd3JhcFN5bmMoaWRlbnRpdHkpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZyYW1lLXdyYXAtc3luYycpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGVycm9yTXNnID0gKDAsIHZhbGlkYXRlXzEkMi52YWxpZGF0ZUlkZW50aXR5KShpZGVudGl0eSk7XG4gICAgICAgIGlmIChlcnJvck1zZykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTXNnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IEluc3RhbmNlXzEkMy5fRnJhbWUodGhpcy53aXJlLCBpZGVudGl0eSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFzeW5jaHJvbm91c2x5IHJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhlIGN1cnJlbnQgZnJhbWVcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBmaW4uRnJhbWUuZ2V0Q3VycmVudCgpXG4gICAgICogLnRoZW4oZnJtID0+IGNvbnNvbGUubG9nKCdjdXJyZW50IGZyYW1lJykpXG4gICAgICogLmNhdGNoKGVyciA9PiBjb25zb2xlLmxvZyhlcnIpKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBnZXRDdXJyZW50KCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZnJhbWUtZ2V0LWN1cnJlbnQnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBJbnN0YW5jZV8xJDMuX0ZyYW1lKHRoaXMud2lyZSwgdGhpcy53aXJlLmVudmlyb25tZW50LmdldEN1cnJlbnRFbnRpdHlJZGVudGl0eSgpKSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN5bmNocm9ub3VzbHkgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGUgY3VycmVudCBmcmFtZVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IGZybSA9IGZpbi5GcmFtZS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIGNvbnN0IGluZm8gPSBhd2FpdCBmcm0uZ2V0SW5mbygpO1xuICAgICAqIGNvbnNvbGUubG9nKGluZm8pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldEN1cnJlbnRTeW5jKCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZnJhbWUtZ2V0LWN1cnJlbnQtc3luYycpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMSQzLl9GcmFtZSh0aGlzLndpcmUsIHRoaXMud2lyZS5lbnZpcm9ubWVudC5nZXRDdXJyZW50RW50aXR5SWRlbnRpdHkoKSk7XG4gICAgfVxufVxuRmFjdG9yeSQ0Ll9GcmFtZU1vZHVsZSA9IF9GcmFtZU1vZHVsZTtcblxuKGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdC8qKlxuXHQgKiBFbnRyeSBwb2ludHMgZm9yIHRoZSBPcGVuRmluIGBGcmFtZWAgQVBJIChgZmluLkZyYW1lYCkuXG5cdCAqXG5cdCAqICoge0BsaW5rIF9GcmFtZU1vZHVsZX0gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBGcmFtZWAgQVBJLCBhY2Nlc3NpYmxlIHRocm91Z2ggYGZpbi5GcmFtZWAuXG5cdCAqICoge0BsaW5rIF9GcmFtZX0gZGVzY3JpYmVzIGFuIGluc3RhbmNlIG9mIGFuIE9wZW5GaW4gRnJhbWUsIGUuZy4gYXMgcmV0dXJuZWQgYnkgYGZpbi5GcmFtZS5nZXRDdXJyZW50YC5cblx0ICpcblx0ICogVGhlc2UgYXJlIHNlcGFyYXRlIGNvZGUgZW50aXRpZXMsIGFuZCBhcmUgZG9jdW1lbnRlZCBzZXBhcmF0ZWx5LiBJbiB0aGUgW3ByZXZpb3VzIHZlcnNpb24gb2YgdGhlIEFQSSBkb2N1bWVudGF0aW9uXShodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC8zMi4xMTQuNzYuMTAvaW5kZXguaHRtbCksXG5cdCAqIGJvdGggb2YgdGhlc2Ugd2VyZSBkb2N1bWVudGVkIG9uIHRoZSBzYW1lIHBhZ2UuXG5cdCAqXG5cdCAqIFVuZGVyc2NvcmUgcHJlZml4aW5nIG9mIE9wZW5GaW4gdHlwZXMgdGhhdCBhbGlhcyBET00gZW50aXRpZXMgd2lsbCBiZSBmaXhlZCBpbiBhIGZ1dHVyZSB2ZXJzaW9uLlxuXHQgKlxuXHQgKiBAcGFja2FnZURvY3VtZW50YXRpb25cblx0ICovXG5cdHZhciBfX2NyZWF0ZUJpbmRpbmcgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcblx0ICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XG5cdCAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XG5cdCAgICB9XG5cdCAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xuXHR9KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIG9bazJdID0gbVtrXTtcblx0fSkpO1xuXHR2YXIgX19leHBvcnRTdGFyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fZXhwb3J0U3RhcikgfHwgZnVuY3Rpb24obSwgZXhwb3J0cykge1xuXHQgICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChleHBvcnRzLCBwKSkgX19jcmVhdGVCaW5kaW5nKGV4cG9ydHMsIG0sIHApO1xuXHR9O1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdF9fZXhwb3J0U3RhcihGYWN0b3J5JDQsIGV4cG9ydHMpO1xuXHRfX2V4cG9ydFN0YXIoSW5zdGFuY2UkMywgZXhwb3J0cyk7IFxufSAoZnJhbWUpKTtcblxudmFyIGdsb2JhbEhvdGtleSA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZ2xvYmFsSG90a2V5LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmdsb2JhbEhvdGtleS5HbG9iYWxIb3RrZXkgPSB2b2lkIDA7XG5jb25zdCBiYXNlXzEkNyA9IGJhc2U7XG4vKipcbiAqIFRoZSBHbG9iYWxIb3RrZXkgbW9kdWxlIGNhbiByZWdpc3Rlci91bnJlZ2lzdGVyIGEgZ2xvYmFsIGhvdGtleXMuXG4gKlxuICovXG5jbGFzcyBHbG9iYWxIb3RrZXkgZXh0ZW5kcyBiYXNlXzEkNy5FbWl0dGVyQmFzZSB7XG4gICAgLyoqXG4gICAgICogQGludGVybmFsXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iod2lyZSkge1xuICAgICAgICBzdXBlcih3aXJlLCAnZ2xvYmFsLWhvdGtleScpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlcnMgYSBnbG9iYWwgaG90a2V5IHdpdGggdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gICAgICogQHBhcmFtIGhvdGtleSBhIGhvdGtleSBzdHJpbmdcbiAgICAgKiBAcGFyYW0gbGlzdGVuZXIgY2FsbGVkIHdoZW4gdGhlIHJlZ2lzdGVyZWQgaG90a2V5IGlzIHByZXNzZWQgYnkgdGhlIHVzZXIuXG4gICAgICogQHRocm93cyBJZiB0aGUgYGhvdGtleWAgaXMgcmVzZXJ2ZWQsIHNlZSBsaXN0IGJlbG93LlxuICAgICAqIEB0aHJvd3MgaWYgdGhlIGBob3RrZXlgIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCBieSBhbm90aGVyIGFwcGxpY2F0aW9uLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgVGhlIGBob3RrZXlgIHBhcmFtZXRlciBleHBlY3RzIGFuIGVsZWN0cm9uIGNvbXBhdGlibGUgW2FjY2VsZXJhdG9yXShodHRwczovL2dpdGh1Yi5jb20vZWxlY3Ryb24vZWxlY3Ryb24vYmxvYi9tYXN0ZXIvZG9jcy9hcGkvYWNjZWxlcmF0b3IubWQpIGFuZCB0aGUgYGxpc3RlbmVyYCB3aWxsIGJlIGNhbGxlZCBpZiB0aGUgYGhvdGtleWAgaXMgcHJlc3NlZCBieSB0aGUgdXNlci5cbiAgICAgKiBJZiBzdWNjZXNzZnVsbCwgdGhlIGhvdGtleSB3aWxsIGJlICdjbGFpbWVkJyBieSB0aGUgYXBwbGljYXRpb24sIG1lYW5pbmcgdGhhdCB0aGlzIHJlZ2lzdGVyIGNhbGwgY2FuIGJlIGNhbGxlZCBtdWx0aXBsZSB0aW1lcyBmcm9tIHdpdGhpbiB0aGUgc2FtZSBhcHBsaWNhdGlvbiBidXQgd2lsbCBmYWlsIGlmIGFub3RoZXIgYXBwbGljYXRpb24gaGFzIHJlZ2lzdGVyZWQgdGhlIGhvdGtleS5cbiAgICAgKiA8YnI+VGhlIHJlZ2lzdGVyIGNhbGwgd2lsbCBmYWlsIGlmIGdpdmVuIGFueSBvZiB0aGVzZSByZXNlcnZlZCBIb3RrZXlzOlxuICAgICAqICogYENvbW1hbmRPckNvbnRyb2wrMGBcbiAgICAgKiAqIGBDb21tYW5kT3JDb250cm9sKz1gXG4gICAgICogKiBgQ29tbWFuZE9yQ29udHJvbCtQbHVzYFxuICAgICAqICogYENvbW1hbmRPckNvbnRyb2wrLWBcbiAgICAgKiAqIGBDb21tYW5kT3JDb250cm9sK19gXG4gICAgICogKiBgQ29tbWFuZE9yQ29udHJvbCtTaGlmdCtJYFxuICAgICAqICogYEY1YFxuICAgICAqICogYENvbW1hbmRPckNvbnRyb2wrUmBcbiAgICAgKiAqIGBTaGlmdCtGNWBcbiAgICAgKiAqIGBDb21tYW5kT3JDb250cm9sK1NoaWZ0K1JgXG4gICAgICpcbiAgICAgKiBSYWlzZXMgdGhlIGByZWdpc3RlcmVkYCBldmVudC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBob3RrZXkgPSAnQ29tbWFuZE9yQ29udHJvbCtYJztcbiAgICAgKlxuICAgICAqIGZpbi5HbG9iYWxIb3RrZXkucmVnaXN0ZXIoaG90a2V5LCAoKSA9PiB7XG4gICAgICogY29uc29sZS5sb2coYCR7aG90a2V5fSBwcmVzc2VkYCk7XG4gICAgICogfSlcbiAgICAgKiAudGhlbigoKSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdTdWNjZXNzJyk7XG4gICAgICogfSlcbiAgICAgKiAuY2F0Y2goZXJyID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ0Vycm9yIHJlZ2lzdGVyaW5nIHRoZSBob3RrZXknLCBlcnIpO1xuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHJlZ2lzdGVyKGhvdGtleSwgbGlzdGVuZXIpIHtcbiAgICAgICAgLy8gVE9ETzogZml4IHR5cGluZyAoaG90a2V5IGV2ZW50cyBhcmUgbm90IHR5cGVkKVxuICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG4gICAgICAgIGF3YWl0IHRoaXMub24oaG90a2V5LCBsaXN0ZW5lcik7XG4gICAgICAgIGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnbG9iYWwtaG90a2V5LXJlZ2lzdGVyJywgeyBob3RrZXkgfSk7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFVucmVnaXN0ZXJzIGEgZ2xvYmFsIGhvdGtleSB3aXRoIHRoZSBvcGVyYXRpbmcgc3lzdGVtLlxuICAgICAqIEBwYXJhbSBob3RrZXkgYSBob3RrZXkgc3RyaW5nXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBUaGlzIG1ldGhvZCB3aWxsIHVucmVnaXN0ZXIgYWxsIGV4aXN0aW5nIHJlZ2lzdHJhdGlvbnMgb2YgdGhlIGhvdGtleSB3aXRoaW4gdGhlIGFwcGxpY2F0aW9uLlxuICAgICAqIFJhaXNlcyB0aGUgYHVucmVnaXN0ZXJlZGAgZXZlbnQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgaG90a2V5ID0gJ0NvbW1hbmRPckNvbnRyb2wrWCc7XG4gICAgICpcbiAgICAgKiBmaW4uR2xvYmFsSG90a2V5LnVucmVnaXN0ZXIoaG90a2V5KVxuICAgICAqIC50aGVuKCgpID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ1N1Y2Nlc3MnKTtcbiAgICAgKiB9KVxuICAgICAqIC5jYXRjaChlcnIgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnRXJyb3IgdW5yZWdpc3RlcmluZyB0aGUgaG90a2V5JywgZXJyKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyB1bnJlZ2lzdGVyKGhvdGtleSkge1xuICAgICAgICAvLyBUT0RPOiBmaXggdHlwaW5nIChob3RrZXkgZXZlbnRzIGFyZSBub3QgdHlwZWQpXG4gICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICAgICAgYXdhaXQgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoaG90a2V5KTtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dsb2JhbC1ob3RrZXktdW5yZWdpc3RlcicsIHsgaG90a2V5IH0pO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBVbnJlZ2lzdGVycyBhbGwgZ2xvYmFsIGhvdGtleXMgZm9yIHRoZSBjdXJyZW50IGFwcGxpY2F0aW9uLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgUmFpc2VzIHRoZSBgdW5yZWdpc3RlcmVkYCBldmVudCBmb3IgZWFjaCBob3RrZXkgdW5yZWdpc3RlcmVkLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGZpbi5HbG9iYWxIb3RrZXkudW5yZWdpc3RlckFsbCgpXG4gICAgICogLnRoZW4oKCkgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnU3VjY2VzcycpO1xuICAgICAqIH0pXG4gICAgICogLmNhdGNoKGVyciA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdFcnJvciB1bnJlZ2lzdGVyaW5nIGFsbCBob3RrZXlzIGZvciB0aGlzIGFwcGxpY2F0aW9uJywgZXJyKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyB1bnJlZ2lzdGVyQWxsKCkge1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbCh0aGlzLmV2ZW50TmFtZXMoKVxuICAgICAgICAgICAgLmZpbHRlcigobmFtZSkgPT4gIShuYW1lID09PSAncmVnaXN0ZXJlZCcgfHwgbmFtZSA9PT0gJ3VucmVnaXN0ZXJlZCcpKVxuICAgICAgICAgICAgLy8gVE9ETzogZml4IHR5cGluZyAoaG90a2V5IGV2ZW50cyBhcmUgbm90IHR5cGVkKVxuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgLm1hcCgobmFtZSkgPT4gdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMobmFtZSkpKTtcbiAgICAgICAgYXdhaXQgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2dsb2JhbC1ob3RrZXktdW5yZWdpc3Rlci1hbGwnLCB7fSk7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiBhIGdpdmVuIGhvdGtleSBoYXMgYmVlbiByZWdpc3RlcmVkIGJ5IGFuIGFwcGxpY2F0aW9uIHdpdGhpbiB0aGUgY3VycmVudCBydW50aW1lLlxuICAgICAqIEBwYXJhbSBob3RrZXkgYSBob3RrZXkgc3RyaW5nXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgaG90a2V5ID0gJ0NvbW1hbmRPckNvbnRyb2wrWCc7XG4gICAgICpcbiAgICAgKiBmaW4uR2xvYmFsSG90a2V5LmlzUmVnaXN0ZXJlZChob3RrZXkpXG4gICAgICogLnRoZW4oKHJlZ2lzdGVyZWQpID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coYGhvdGtleSAke2hvdGtleX0gaXMgcmVnaXN0ZXJlZCA/ICR7cmVnaXN0ZXJlZH1gKTtcbiAgICAgKiB9KVxuICAgICAqIC5jYXRjaChlcnIgPT4ge1xuICAgICAqICAgICBjb25zb2xlLmxvZygnRXJyb3IgdW5yZWdpc3RlcmluZyB0aGUgaG90a2V5JywgZXJyKTtcbiAgICAgKiB9KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBpc1JlZ2lzdGVyZWQoaG90a2V5KSB7XG4gICAgICAgIGNvbnN0IHsgcGF5bG9hZDogeyBkYXRhIH0gfSA9IGF3YWl0IHRoaXMud2lyZS5zZW5kQWN0aW9uKCdnbG9iYWwtaG90a2V5LWlzLXJlZ2lzdGVyZWQnLCB7IGhvdGtleSB9KTtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxufVxuZ2xvYmFsSG90a2V5Lkdsb2JhbEhvdGtleSA9IEdsb2JhbEhvdGtleTtcblxudmFyIHBsYXRmb3JtID0ge307XG5cbnZhciBGYWN0b3J5JDMgPSB7fTtcblxudmFyIEluc3RhbmNlJDIgPSB7fTtcblxudmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNSA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9QbGF0Zm9ybV9jb25uZWN0VG9Qcm92aWRlcjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShJbnN0YW5jZSQyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbkluc3RhbmNlJDIuUGxhdGZvcm0gPSB2b2lkIDA7XG4vKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvcHJlZmVyLWRlZmF1bHQtZXhwb3J0LCBuby11bmRlZiAqL1xuY29uc3QgYmFzZV8xJDYgPSBiYXNlO1xuY29uc3QgdmFsaWRhdGVfMSQxID0gdmFsaWRhdGU7XG4vLyBSZXVzZSBjbGllbnRzIHRvIGF2b2lkIG92ZXJ3cml0aW5nIGFscmVhZHktcmVnaXN0ZXJlZCBjbGllbnQgaW4gcHJvdmlkZXJcbmNvbnN0IGNsaWVudE1hcCA9IG5ldyBNYXAoKTtcbi8qKiBNYW5hZ2VzIHRoZSBsaWZlIGN5Y2xlIG9mIHdpbmRvd3MgYW5kIHZpZXdzIGluIHRoZSBhcHBsaWNhdGlvbi5cbiAqXG4gKiBFbmFibGVzIHRha2luZyBzbmFwc2hvdHMgb2YgaXRzZWxmIGFuZCBhcHBseWluZyB0aGVtIHRvIHJlc3RvcmUgYSBwcmV2aW91cyBjb25maWd1cmF0aW9uXG4gKiBhcyB3ZWxsIGFzIGxpc3RlbiB0byB7QGxpbmsgT3BlbkZpbi5QbGF0Zm9ybUV2ZW50cyBwbGF0Zm9ybSBldmVudHN9LlxuICovXG5jbGFzcyBQbGF0Zm9ybSBleHRlbmRzIGJhc2VfMSQ2LkVtaXR0ZXJCYXNlIHtcbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2hhZG93XG4gICAgY29uc3RydWN0b3IoaWRlbnRpdHksIGNoYW5uZWwpIHtcbiAgICAgICAgLy8gd2UgcGlnZ3liYWNrIG9mZiBvZiBhcHBsaWNhdGlvbiBldmVudCBlbWl0dGVyIGJlY2F1c2UgZnJvbSB0aGUgY29yZSdzIHBlcnNwZWN0aXZlIHBsYXRmb3JtIGlzIGp1c3QgYW4gYXBwLlxuICAgICAgICBzdXBlcihjaGFubmVsLndpcmUsICdhcHBsaWNhdGlvbicsIGlkZW50aXR5LnV1aWQpO1xuICAgICAgICB0aGlzLmdldENsaWVudCA9IChpZGVudGl0eSkgPT4ge1xuICAgICAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLWdldC1jbGllbnQnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCB0YXJnZXQgPSBpZGVudGl0eSB8fCB0aGlzLmlkZW50aXR5O1xuICAgICAgICAgICAgY29uc3QgeyB1dWlkIH0gPSB0YXJnZXQ7XG4gICAgICAgICAgICBpZiAoIWNsaWVudE1hcC5oYXModXVpZCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjbGllbnRQcm9taXNlID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ1KHRoaXMsIF9QbGF0Zm9ybV9jb25uZWN0VG9Qcm92aWRlciwgXCJmXCIpLmNhbGwodGhpcywgdXVpZCk7XG4gICAgICAgICAgICAgICAgY2xpZW50TWFwLnNldCh1dWlkLCBjbGllbnRQcm9taXNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHdlIHNldCBpdCBhYm92ZVxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1ub24tbnVsbC1hc3NlcnRpb25cbiAgICAgICAgICAgIHJldHVybiBjbGllbnRNYXAuZ2V0KHV1aWQpO1xuICAgICAgICB9O1xuICAgICAgICBfUGxhdGZvcm1fY29ubmVjdFRvUHJvdmlkZXIuc2V0KHRoaXMsIGFzeW5jICh1dWlkKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNoYW5uZWxOYW1lID0gYGN1c3RvbS1mcmFtZS0ke3V1aWR9YDtcbiAgICAgICAgICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLl9jaGFubmVsLmNvbm5lY3QoY2hhbm5lbE5hbWUsIHsgd2FpdDogZmFsc2UgfSk7XG4gICAgICAgICAgICAgICAgY2xpZW50Lm9uRGlzY29ubmVjdGlvbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNsaWVudE1hcC5kZWxldGUodXVpZCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNsaWVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgY2xpZW50TWFwLmRlbGV0ZSh1dWlkKTtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSB0YXJnZXRlZCBQbGF0Zm9ybSBpcyBub3QgY3VycmVudGx5IHJ1bm5pbmcuIExpc3RlbiBmb3IgYXBwbGljYXRpb24tc3RhcnRlZCBldmVudCBmb3IgdGhlIGdpdmVuIFV1aWQuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogQGRlcHJlY2F0ZWQgKHJlbmFtZWQpXG4gICAgICAgICAqIEBpZ25vcmVcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMubGF1bmNoTGVnYWN5TWFuaWZlc3QgPSB0aGlzLmxhdW5jaENvbnRlbnRNYW5pZmVzdDtcbiAgICAgICAgY29uc3QgZXJyb3JNc2cgPSAoMCwgdmFsaWRhdGVfMSQxLnZhbGlkYXRlSWRlbnRpdHkpKGlkZW50aXR5KTtcbiAgICAgICAgaWYgKGVycm9yTXNnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNc2cpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2NoYW5uZWwgPSBjaGFubmVsO1xuICAgICAgICB0aGlzLmlkZW50aXR5ID0geyB1dWlkOiBpZGVudGl0eS51dWlkIH07XG4gICAgICAgIHRoaXMuTGF5b3V0ID0gdGhpcy5maW4uUGxhdGZvcm0uTGF5b3V0O1xuICAgICAgICB0aGlzLkFwcGxpY2F0aW9uID0gdGhpcy5maW4uQXBwbGljYXRpb24ud3JhcFN5bmModGhpcy5pZGVudGl0eSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgdmlldyBhbmQgYXR0YWNoZXMgaXQgdG8gYSBzcGVjaWZpZWQgdGFyZ2V0IHdpbmRvdy5cbiAgICAgKiBAcGFyYW0gdmlld09wdGlvbnMgVmlldyBjcmVhdGlvbiBvcHRpb25zXG4gICAgICogQHBhcmFtIHRhcmdldCBUaGUgd2luZG93IHRvIHdoaWNoIHRoZSBuZXcgdmlldyBpcyB0byBiZSBhdHRhY2hlZC4gSWYgbm8gdGFyZ2V0LCBjcmVhdGUgYSB2aWV3IGluIGEgbmV3IHdpbmRvdy5cbiAgICAgKiBAcGFyYW0gdGFyZ2V0VmlldyBJZiBwcm92aWRlZCwgdGhlIG5ldyB2aWV3IHdpbGwgYmUgYWRkZWQgdG8gdGhlIHNhbWUgdGFic3RyaXAgYXMgdGFyZ2V0Vmlldy5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIElmIHRoZSB2aWV3IGFscmVhZHkgZXhpc3RzLCB3aWxsIHJlcGFyZW50IHRoZSB2aWV3IHRvIHRoZSBuZXcgdGFyZ2V0LiBZb3UgZG8gbm90IG5lZWQgdG8gc2V0IGEgbmFtZSBmb3IgYSBWaWV3LlxuICAgICAqIFZpZXdzIHRoYXQgYXJlIG5vdCBwYXNzZWQgYSBuYW1lIGdldCBhIHJhbmRvbWx5IGdlbmVyYXRlZCBvbmUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogbGV0IHdpbmRvd0lkZW50aXR5O1xuICAgICAqIGlmIChmaW4ubWUuaXNXaW5kb3cpIHtcbiAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSBmaW4ubWUuaWRlbnRpdHk7XG4gICAgICogfSBlbHNlIGlmIChmaW4ubWUuaXNWaWV3KSB7XG4gICAgICogICAgIHdpbmRvd0lkZW50aXR5ID0gKGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50V2luZG93KCkpLmlkZW50aXR5O1xuICAgICAqIH0gZWxzZSB7XG4gICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3IG9yIFdpbmRvdycpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gZmluLlBsYXRmb3JtLmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICpcbiAgICAgKiBwbGF0Zm9ybS5jcmVhdGVWaWV3KHtcbiAgICAgKiAgICAgbmFtZTogJ3Rlc3RfdmlldycsXG4gICAgICogICAgIHVybDogJ2h0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL2RvY3MvcGxhdGZvcm0tYXBpJ1xuICAgICAqIH0sIHdpbmRvd0lkZW50aXR5KS50aGVuKGNvbnNvbGUubG9nKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIFJlcGFyZW50aW5nIGEgdmlldzpcbiAgICAgKiBgYGBqc1xuICAgICAqIGxldCB3aW5kb3dJZGVudGl0eTtcbiAgICAgKiBpZiAoZmluLm1lLmlzV2luZG93KSB7XG4gICAgICogICAgIHdpbmRvd0lkZW50aXR5ID0gZmluLm1lLmlkZW50aXR5O1xuICAgICAqIH0gZWxzZSBpZiAoZmluLm1lLmlzVmlldykge1xuICAgICAqICAgICB3aW5kb3dJZGVudGl0eSA9IChhd2FpdCBmaW4ubWUuZ2V0Q3VycmVudFdpbmRvdygpKS5pZGVudGl0eTtcbiAgICAgKiB9IGVsc2Uge1xuICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldyBvciBXaW5kb3cnKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBsZXQgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKiBsZXQgdmlld09wdGlvbnMgPSB7XG4gICAgICogICAgIG5hbWU6ICdleGFtcGxlX3ZpZXcnLFxuICAgICAqICAgICB1cmw6ICdodHRwczovL2V4YW1wbGUuY29tJ1xuICAgICAqIH07XG4gICAgICogLy8gYSBuZXcgdmlldyB3aWxsIG5vdyBzaG93IGluIHRoZSBjdXJyZW50IHdpbmRvd1xuICAgICAqIGF3YWl0IHBsYXRmb3JtLmNyZWF0ZVZpZXcodmlld09wdGlvbnMsIHdpbmRvd0lkZW50aXR5KTtcbiAgICAgKlxuICAgICAqIGNvbnN0IHZpZXcgPSBmaW4uVmlldy53cmFwU3luYyh7IHV1aWQ6IHdpbmRvd0lkZW50aXR5LnV1aWQsIG5hbWU6ICd5YWhvb192aWV3JyB9KTtcbiAgICAgKiAvLyByZXBhcmVudCBgZXhhbXBsZV92aWV3YCB3aGVuIGEgdmlldyBpbiB0aGUgbmV3IHdpbmRvdyBpcyBzaG93blxuICAgICAqIHZpZXcub24oJ3Nob3duJywgYXN5bmMgKCkgPT4ge1xuICAgICAqICAgICBsZXQgdmlld0lkZW50aXR5ID0geyB1dWlkOiB3aW5kb3dJZGVudGl0eS51dWlkLCBuYW1lOiAnZXhhbXBsZV92aWV3J307XG4gICAgICogICAgIGxldCB0YXJnZXQgPSB7dXVpZDogd2luZG93SWRlbnRpdHkudXVpZCwgbmFtZTogJ3Rlc3Rfd2luJ307XG4gICAgICogICAgIHBsYXRmb3JtLmNyZWF0ZVZpZXcodmlld09wdGlvbnMsIHRhcmdldCk7XG4gICAgICogfSk7XG4gICAgICpcbiAgICAgKiAvLyBjcmVhdGUgYSBuZXcgd2luZG93XG4gICAgICogYXdhaXQgcGxhdGZvcm0uY3JlYXRlV2luZG93KHtcbiAgICAgKiAgICAgbmFtZTogXCJ0ZXN0X3dpblwiLFxuICAgICAqICAgICBsYXlvdXQ6IHtcbiAgICAgKiAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgKiAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgIHR5cGU6ICdzdGFjaycsXG4gICAgICogICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnY29tcG9uZW50JyxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnROYW1lOiAndmlldycsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50U3RhdGU6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogJ3lhaG9vX3ZpZXcnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmw6ICdodHRwczovL3lhaG9vLmNvbSdcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgIF1cbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICBdXG4gICAgICogICAgIH1cbiAgICAgKiB9KS50aGVuKGNvbnNvbGUubG9nKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBjcmVhdGVWaWV3KHZpZXdPcHRpb25zLCB0YXJnZXQsIHRhcmdldFZpZXcpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLWNyZWF0ZS12aWV3JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ2NyZWF0ZS12aWV3Jywge1xuICAgICAgICAgICAgdGFyZ2V0LFxuICAgICAgICAgICAgb3B0czogdmlld09wdGlvbnMsXG4gICAgICAgICAgICB0YXJnZXRWaWV3XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIXJlc3BvbnNlIHx8ICgwLCB2YWxpZGF0ZV8xJDEudmFsaWRhdGVJZGVudGl0eSkocmVzcG9uc2UuaWRlbnRpdHkpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFdoZW4gb3ZlcndyaXRpbmcgdGhlIGNyZWF0ZVZpZXcgY2FsbCwgcGxlYXNlIHJldHVybiBhbiBvYmplY3QgdGhhdCBoYXMgYSB2YWxpZCAnaWRlbnRpdHknIHByb3BlcnR5OiAke0pTT04uc3RyaW5naWZ5KHJlc3BvbnNlKX1gKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5maW4uVmlldy53cmFwU3luYyhyZXNwb25zZS5pZGVudGl0eSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgV2luZG93LlxuICAgICAqIEBwYXJhbSBvcHRpb25zIFdpbmRvdyBjcmVhdGlvbiBvcHRpb25zXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBUaGVyZSBhcmUgdHdvIFdpbmRvdyB0eXBlcyBhdCB5b3VyIGRpc3Bvc2FsIHdoaWxlIHVzaW5nIE9wZW5GaW4gUGxhdGZvcm1zIC0gRGVmYXVsdCBXaW5kb3cgYW5kIEN1c3RvbSBXaW5kb3cuXG4gICAgICpcbiAgICAgKiBUaGUgRGVmYXVsdCBXaW5kb3cgdXNlcyB0aGUgc3RhbmRhcmQgT3BlbkZpbiBXaW5kb3cgVUkuIEl0IGNvbnRhaW5zIHRoZSBzdGFuZGFyZCBjbG9zZSwgbWF4aW1pemUgYW5kIG1pbmltaXplIGJ1dHRvbnMsXG4gICAgICogYW5kIHdpbGwgYXV0b21hdGljYWxseSByZW5kZXIgdGhlIFdpbmRvdydzIGxheW91dCBpZiBvbmUgaXMgc3BlY2lmaWVkLlxuICAgICAqXG4gICAgICogRm9yIGRlZXBlciBjdXN0b21pemF0aW9uLCB5b3UgY2FuIGJyaW5nIHlvdXIgb3duIFdpbmRvdyBjb2RlIGludG8gYSBQbGF0Zm9ybS4gVGhpcyBpcyBjYWxsZWQgYSBDdXN0b20gV2luZG93LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqXG4gICAgICogVGhlIGV4YW1wbGUgYmVsb3cgd2lsbCBjcmVhdGUgYSBEZWZhdWx0IFdpbmRvdyB3aGljaCB1c2VzIE9wZW5GaW4gZGVmYXVsdCBXaW5kb3cgVUkuPGJyPlxuICAgICAqIFRoZSBXaW5kb3cgY29udGFpbnMgdHdvIFZpZXdzIGluIGEgc3RhY2sgTGF5b3V0OlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIHBsYXRmb3JtLmNyZWF0ZVdpbmRvdyh7XG4gICAgICogICAgIGxheW91dDoge1xuICAgICAqICAgICAgICAgY29udGVudDogW1xuICAgICAqICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgdHlwZTogJ3N0YWNrJyxcbiAgICAgKiAgICAgICAgICAgICAgICAgY29udGVudDogW1xuICAgICAqICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjb21wb25lbnQnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudE5hbWU6ICd2aWV3JyxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRTdGF0ZToge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAndGVzdF92aWV3XzEnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9jYW5hcnkvUGxhdGZvcm0uaHRtbCdcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAqICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjb21wb25lbnQnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudE5hbWU6ICd2aWV3JyxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRTdGF0ZToge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAndGVzdF92aWV3XzInLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9jYW5hcnkvUGxhdGZvcm0uaHRtbCdcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgIF1cbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICBdXG4gICAgICogICAgIH1cbiAgICAgKiB9KS50aGVuKGNvbnNvbGUubG9nKTtcbiAgICAgKiBgYGBcbiAgICAgKiBUaGUgRGVmYXVsdCBXaW5kb3cncyBkZXNpZ24gY2FuIGJlIGN1c3RvbWl6ZWQgYnkgc3BlY2lmeWluZyB0aGUgYHN0eWxlc2hlZXRVcmxgIHByb3BlcnR5IGluIHRoZSBtYW5pZmVzdDpcbiAgICAgKlxuICAgICAqIGBgYGpzb25cbiAgICAgKiB7XG4gICAgICogICAgIHBsYXRmb3JtOiB7XG4gICAgICogICAgICAgICBkZWZhdWx0V2luZG93T3B0aW9uczoge1xuICAgICAqICAgICAgICAgICAgIHN0eWxlc2hlZXRVcmw6ICdzb21lLXVybC5jc3MnLFxuICAgICAqICAgICAgICAgICAgIC4uLlxuICAgICAqICAgICAgICAgfVxuICAgICAqICAgICB9XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqIEZvciBhIGxpc3Qgb2YgY29tbW9uIExheW91dCBDU1MgY2xhc3NlcyB5b3UgY2FuIG92ZXJyaWRlIGluIHlvdXIgY3VzdG9tIHN0eWxlc2hlZXQsIHNlZSA8YSBocmVmPVwidHV0b3JpYWwtbGF5b3V0U3R5bGVzLmh0bWxcIj5Vc2VmdWwgTGF5b3V0IENTUyBDbGFzc2VzPC9hPlxuICAgICAqKlxuICAgICAqIFRvIHNwZWNpZnkgYSBQbGF0Zm9ybSBDdXN0b20gV2luZG93LCBwcm92aWRlIGEgYHVybGAgcHJvcGVydHkgd2hlbiBjcmVhdGluZyBhIFdpbmRvdy5cbiAgICAgKiBJZiB5b3UgaW50ZW5kIHRvIHJlbmRlciBhIExheW91dCBpbiB5b3VyIEN1c3RvbSBXaW5kb3csIHlvdSBtdXN0IGFsc28gc3BlY2lmeSBhbiBgSFRNTEVsZW1lbnRgIHRoYXQgdGhlIExheW91dCB3aWxsIGluamVjdCBpbnRvIGFuZCBzZXQgaXRzIGBpZGAgcHJvcGVydHkgdG8gYFwibGF5b3V0LWNvbnRhaW5lclwiYC5cbiAgICAgKlxuICAgICAqIFRoZSBleGFtcGxlIGJlbG93IHdpbGwgY3JlYXRlIGEgUGxhdGZvcm0gQ3VzdG9tIFdpbmRvdzpcbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogICAgIC8vIGluIGFuIE9wZW5GaW4gYXBwOlxuICAgICAqICAgICBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqICAgICBjb25zdCB3aW5kb3dDb25maWcgPVxuICAgICAqICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgIHVybDogXCJodHRwczovL3d3dy5teS1kb21haW4uY29tL215LWN1c3RvbS13aW5kb3cuaHRtbFwiLCAvLyBoZXJlIHdlIHBvaW50IHRvIHdoZXJlIHRoZSBDdXN0b20gRnJhbWUgaXMgaG9zdGVkLlxuICAgICAqICAgICAgICAgICAgIGxheW91dDoge1xuICAgICAqICAgICAgICAgICAgICAgICBjb250ZW50OiBbXG4gICAgICogICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJzdGFja1wiLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJjb21wb25lbnRcIixcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudE5hbWU6IFwidmlld1wiLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50U3RhdGU6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiBcImFwcCAjMVwiLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogXCJodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC9jYW5hcnkvUGxhdGZvcm0uaHRtbFwiXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFwiY29tcG9uZW50XCIsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnROYW1lOiBcInZpZXdcIixcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudFN0YXRlOiB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogXCJhcHAgIzJcIixcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmw6IFwiaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvY2FuYXJ5L1BsYXRmb3JtLmh0bWxcIlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAqICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgICAgICAgICBdXG4gICAgICogICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgfTtcbiAgICAgKiAgICAgcGxhdGZvcm0uY3JlYXRlV2luZG93KHdpbmRvd0NvbmZpZyk7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBIZXJlJ3MgYW4gZXhhbXBsZSBvZiBhIG1pbmltYWxpc3QgQ3VzdG9tIFBsYXRmb3JtIFdpbmRvdyBpbXBsZW1lbnRhdGlvbjpcbiAgICAgKiBgYGBodG1sXG4gICAgICogPGh0bWw+XG4gICAgICogICAgIDxoZWFkPlxuICAgICAqICAgICAgICAgPG1ldGEgY2hhcnNldD1cInV0Zi04XCI+XG4gICAgICogICAgICAgICA8bWV0YSBuYW1lPVwidmlld3BvcnRcIiBjb250ZW50PVwid2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTFcIj5cbiAgICAgKiAgICAgICAgIDxsaW5rIHJlbD1cInN0eWxlc2hlZXRcIiB0eXBlPVwidGV4dC9jc3NcIiBocmVmPVwiLi9zdHlsZXMuY3NzXCI+XG4gICAgICogICAgIDwvaGVhZD5cbiAgICAgKiAgICAgPGJvZHk+XG4gICAgICogICAgICAgICA8ZGl2IGlkPVwib2YtZnJhbWUtbWFpblwiPlxuICAgICAqICAgICAgICAgICAgIDxkaXYgaWQ9XCJ0aXRsZS1iYXJcIj5cbiAgICAgKiAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRpdGxlLWJhci1kcmFnZ2FibGVcIj5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIDxkaXYgaWQ9XCJ0aXRsZVwiPiBUaGlzIGlzIGEgY3VzdG9tIGZyYW1lISA8L2Rpdj5cbiAgICAgKiAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICogICAgICAgICAgICAgICAgIDxkaXYgaWQ9XCJidXR0b25zLXdyYXBwZXJcIj5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJidXR0b25cIiBpZD1cIm1pbmltaXplLWJ1dHRvblwiPjwvZGl2PlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJ1dHRvblwiIGlkPVwiZXhwYW5kLWJ1dHRvblwiPjwvZGl2PlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImJ1dHRvblwiIGlkPVwiY2xvc2UtYnV0dG9uXCI+PC9kaXY+XG4gICAgICogICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAqICAgICAgICAgICAgIDwvZGl2PlxuICAgICAqICAgICAgICAgICAgIDxkaXYgaWQ9XCJsYXlvdXQtY29udGFpbmVyXCI+PC9kaXY+IDwhLS0gT3BlbkZpbiBsYXlvdXQgd291bGQgYmUgaW5qZWN0ZWQgaGVyZSAtLT5cbiAgICAgKiAgICAgICAgICAgICA8c2NyaXB0IHNyYz1cIi4vY3VzdG9tLWZyYW1lLmpzXCI+PC9zY3JpcHQ+XG4gICAgICogICAgICAgICA8L2Rpdj5cbiAgICAgKiAgICAgPC9ib2R5PlxuICAgICAqIDwvaHRtbD5cbiAgICAgKiBgYGBcbiAgICAgKiBZb3VyIEN1c3RvbSBXaW5kb3cgY2FuIHVzZSBpbi1kb21haW4gcmVzb3VyY2VzIGZvciBmdXJ0aGVyIGN1c3RvbWl6YXRpb24gKHN1Y2ggYXMgQ1NTLCBzY3JpcHRzLCBldGMuKS48YnI+XG4gICAgICogRm9yIGEgbGlzdCBvZiBjb21tb24gTGF5b3V0IENTUyBjbGFzc2VzIHlvdSBjYW4gb3ZlcnJpZGUgaW4geW91ciBzdHlsZXNoZWV0LCBzZWUgPGEgaHJlZj1cInR1dG9yaWFsLWxheW91dFN0eWxlcy5odG1sXCI+VXNlZnVsIExheW91dCBDU1MgQ2xhc3NlczwvYT5cbiAgICAgKlxuICAgICAqIFRoZSBleGFtcGxlIGFib3ZlIHdpbGwgcmVxdWlyZSB0aGUgYGJvZHlgIGVsZW1lbnQgdG8gaGF2ZSBgaGVpZ2h0OiAxMDAlO2Agc2V0IGluIG9yZGVyIHRvIHJlbmRlciB0aGUgbGF5b3V0IGNvcnJlY3RseS5cbiAgICAgKi9cbiAgICBhc3luYyBjcmVhdGVXaW5kb3cob3B0aW9ucykge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tY3JlYXRlLXdpbmRvdycsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XG4gICAgICAgIGlmICghb3B0aW9ucy5yZWFzb24pIHtcbiAgICAgICAgICAgIG9wdGlvbnMucmVhc29uID0gJ2FwaS1jYWxsJztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC5kaXNwYXRjaCgnY3JlYXRlLXZpZXctY29udGFpbmVyJywgb3B0aW9ucyk7XG4gICAgICAgIGlmICghcmVzcG9uc2UgfHwgKDAsIHZhbGlkYXRlXzEkMS52YWxpZGF0ZUlkZW50aXR5KShyZXNwb25zZS5pZGVudGl0eSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgV2hlbiBvdmVyd3JpdGluZyB0aGUgY3JlYXRlV2luZG93IGNhbGwsIHBsZWFzZSByZXR1cm4gYW4gb2JqZWN0IHRoYXQgaGFzIGEgdmFsaWQgJ2lkZW50aXR5JyBwcm9wZXJ0eTogJHtKU09OLnN0cmluZ2lmeShyZXNwb25zZSl9YCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyBpZGVudGl0eSB9ID0gcmVzcG9uc2U7XG4gICAgICAgIGNvbnN0IHJlcyA9IHRoaXMuZmluLldpbmRvdy53cmFwU3luYyhpZGVudGl0eSk7XG4gICAgICAgIC8vIHdlIGFkZCB0aGUgaWRlbnRpdHkgYXQgdGhlIHRvcCBsZXZlbCBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuXG4gICAgICAgIHJlcy5uYW1lID0gaWRlbnRpdHkubmFtZTtcbiAgICAgICAgcmVzLnV1aWQgPSBpZGVudGl0eS51dWlkO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDbG9zZXMgY3VycmVudCBwbGF0Zm9ybSwgYWxsIGl0cyB3aW5kb3dzLCBhbmQgdGhlaXIgdmlld3MuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudCgpO1xuICAgICAqIHBsYXRmb3JtLnF1aXQoKTtcbiAgICAgKiAvLyBBbGwgd2luZG93cy92aWV3cyBpbiBjdXJyZW50IGxheW91dCBwbGF0Zm9ybSB3aWxsIGNsb3NlIGFuZCBwbGF0Zm9ybSB3aWxsIHNodXQgZG93blxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHF1aXQoKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwbGF0Zm9ybS1xdWl0JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcbiAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgncXVpdCcpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDbG9zZXMgYSBzcGVjaWZpZWQgdmlldyBpbiBhIHRhcmdldCB3aW5kb3cuXG4gICAgICogQHBhcmFtIHZpZXdJZGVudGl0eSBWaWV3IGlkZW50aXR5XG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogbGV0IHdpbmRvd0lkZW50aXR5O1xuICAgICAqIGlmIChmaW4ubWUuaXNXaW5kb3cpIHtcbiAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSBmaW4ubWUuaWRlbnRpdHk7XG4gICAgICogfSBlbHNlIGlmIChmaW4ubWUuaXNWaWV3KSB7XG4gICAgICogICAgIHdpbmRvd0lkZW50aXR5ID0gKGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50V2luZG93KCkpLmlkZW50aXR5O1xuICAgICAqIH0gZWxzZSB7XG4gICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3IG9yIFdpbmRvdycpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGNvbnN0IHZpZXdPcHRpb25zID0ge1xuICAgICAqICAgICBuYW1lOiAndGVzdF92aWV3JyxcbiAgICAgKiAgICAgdXJsOiAnaHR0cHM6Ly9leGFtcGxlLmNvbSdcbiAgICAgKiB9O1xuICAgICAqXG4gICAgICogZnVuY3Rpb24gc2xlZXAobXMpIHtcbiAgICAgKiAgICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCBtcykpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLmdldEN1cnJlbnQoKTtcbiAgICAgKlxuICAgICAqIGF3YWl0IHBsYXRmb3JtLmNyZWF0ZVZpZXcodmlld09wdGlvbnMsIHdpbmRvd0lkZW50aXR5KTtcbiAgICAgKiAvLyBhIG5ldyB2aWV3IHdpbGwgbm93IHNob3cgaW4gdGhlIGN1cnJlbnQgd2luZG93XG4gICAgICpcbiAgICAgKiBhd2FpdCBzbGVlcCg1MDAwKTtcbiAgICAgKlxuICAgICAqIGNvbnN0IHZpZXdJZGVudGl0eSA9IHsgdXVpZDogd2luZG93SWRlbnRpdHkudXVpZCwgbmFtZTogJ3Rlc3Rfdmlldyd9O1xuICAgICAqIHBsYXRmb3JtLmNsb3NlVmlldyh2aWV3SWRlbnRpdHkpO1xuICAgICAqIC8vIHRoZSB2aWV3IHdpbGwgbm93IGNsb3NlXG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgY2xvc2VWaWV3KHZpZXdJZGVudGl0eSkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tY2xvc2UtdmlldycsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XG4gICAgICAgIGF3YWl0IGNsaWVudC5kaXNwYXRjaCgnY2xvc2UtdmlldycsIHtcbiAgICAgICAgICAgIHZpZXc6IHZpZXdJZGVudGl0eVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogKioqREVQUkVDQVRFRCAtIHBsZWFzZSB1c2Uge0BsaW5rIFBsYXRmb3JtLmNyZWF0ZVZpZXcgUGxhdGZvcm0uY3JlYXRlVmlld30uKioqXG4gICAgICogUmVwYXJlbnRzIGEgc3BlY2lmaWVkIHZpZXcgaW4gYSBuZXcgdGFyZ2V0IHdpbmRvdy5cbiAgICAgKiBAcGFyYW0gdmlld0lkZW50aXR5IFZpZXcgaWRlbnRpdHlcbiAgICAgKiBAcGFyYW0gdGFyZ2V0IG5ldyBvd25lciB3aW5kb3cgaWRlbnRpdHlcbiAgICAgKlxuICAgICAqL1xuICAgIGFzeW5jIHJlcGFyZW50Vmlldyh2aWV3SWRlbnRpdHksIHRhcmdldCkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICBjb25zb2xlLndhcm4oJ1BsYXRmb3JtLnJlcGFyZW50VmlldyBoYXMgYmVlbiBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIFBsYXRmb3JtLmNyZWF0ZVZpZXcnKTtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLXJlcGFyZW50LXZpZXcnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBub3JtYWxpemVkVmlld0lkZW50aXR5ID0ge1xuICAgICAgICAgICAgLi4udmlld0lkZW50aXR5LFxuICAgICAgICAgICAgdXVpZDogdmlld0lkZW50aXR5LnV1aWQgPz8gdGhpcy5pZGVudGl0eS51dWlkXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHZpZXcgPSBhd2FpdCB0aGlzLmZpbi5WaWV3LndyYXAobm9ybWFsaXplZFZpZXdJZGVudGl0eSk7XG4gICAgICAgIGNvbnN0IHZpZXdPcHRpb25zID0gYXdhaXQgdmlldy5nZXRPcHRpb25zKCk7XG4gICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVZpZXcodmlld09wdGlvbnMsIHRhcmdldCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYSBzbmFwc2hvdCBvZiB0aGUgcGxhdGZvcm0gaW4gaXRzIGN1cnJlbnQgc3RhdGUuIFlvdSBjYW4gcGFzcyB0aGUgcmV0dXJuaW5nIG9iamVjdCB0b1xuICAgICAqIFtQbGF0Zm9ybS5hcHBseVNuYXBzaG90XXtAbGluayBQbGF0Zm9ybSNhcHBseVNuYXBzaG90fSB0byBsYXVuY2ggaXQuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBUaGUgc25hcHNob3Qgd2lsbCBpbmNsdWRlIGRldGFpbHMgc3VjaCBhcyBhbiBbSVNPIGZvcm1hdF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPXzg2MDEpXG4gICAgICogdGltZXN0YW1wIG9mIHdoZW4gdGhlIHNuYXBzaG90IHdhcyB0YWtlbiwgT3BlbkZpbiBydW50aW1lIHZlcnNpb24gdGhlIHBsYXRmb3JtIGlzIHJ1bm5pbmcgb24sIG1vbml0b3IgaW5mb3JtYXRpb25cbiAgICAgKiBhbmQgdGhlIGxpc3Qgb2YgY3VycmVudGx5IHJ1bm5pbmcgd2luZG93cy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50KCk7XG4gICAgICogY29uc3Qgc25hcHNob3QgPSBhd2FpdCBwbGF0Zm9ybS5nZXRTbmFwc2hvdCgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGdldFNuYXBzaG90KCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tZ2V0LXNuYXBzaG90JywgdGhpcy5pZGVudGl0eSkuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcbiAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnZ2V0LXNuYXBzaG90Jyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqICoqTk9URSoqOiBJbnRlcm5hbCB1c2Ugb25seS4gSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1hbmFnZSB0aGUgc3RhdGUgb2YgaW5kaXZpZHVhbCB2aWV3cy5cbiAgICAgKlxuICAgICAqIFJldHVybnMgYSBzbmFwc2hvdCBvZiBhIHNpbmdsZSB2aWV3J3Mgb3B0aW9ucyBpbiBpdHMgY3VycmVudCBzdGF0ZS5cbiAgICAgKlxuICAgICAqIENhbiBiZSB1c2VkIHRvIHJlc3RvcmUgYSB2aWV3IHRvIGEgcHJldmlvdXMgc3RhdGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmlld0lkZW50aXR5IFZpZXcgaWRlbnRpdHlcbiAgICAgKlxuICAgICAqIEBpbnRlcm5hbFxuICAgICAqIEBleHBlcmltZW50YWxcbiAgICAgKiBAcmVtYXJrcyBUaGlzIHNsaWNlIG9mIHNuYXBzaG90IHN0YXRlIGlzIGVxdWl2YWxlbnQgdG8gd2hhdCBpcyBzdG9yZWQgYXMgYGNvbXBvbmVudFN0YXRlYCBmb3Igdmlld3NcbiAgICAgKiB3aGVuIGNhcHR1cmluZyBwbGF0Zm9ybSBzdGF0ZSB1c2luZyBbUGxhdGZvcm0uZ2V0U25hcHNob3Rde0BsaW5rIFBsYXRmb3JtI2dldFNuYXBzaG90fS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50KCk7XG4gICAgICogY29uc3QgdXJsID0gJ2h0dHBzOi8vZ29vZ2xlLmNvbSc7XG4gICAgICogY29uc3QgdmlldyA9IGF3YWl0IGZpbi5WaWV3LmNyZWF0ZSh7IG5hbWU6ICdteS12aWV3JywgdGFyZ2V0OiBmaW4ubWUuaWRlbnRpdHksIHVybCB9KTtcbiAgICAgKlxuICAgICAqIGF3YWl0IHZpZXcubmF2aWdhdGUodXJsKTtcbiAgICAgKlxuICAgICAqIGNvbnN0IHZpZXdTdGF0ZSA9IGF3YWl0IHBsYXRmb3JtLmdldFZpZXdTbmFwc2hvdCh2aWV3LmlkZW50aXR5KTtcbiAgICAgKlxuICAgICAqIGNvbnNvbGUubG9nKHZpZXdTdGF0ZSk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZ2V0Vmlld1NuYXBzaG90KHZpZXdJZGVudGl0eSkge1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xuICAgICAgICByZXR1cm4gY2xpZW50LmRpc3BhdGNoKCdnZXQtdmlldy1zbmFwc2hvdCcsIHsgdmlld0lkZW50aXR5IH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgc25hcHNob3QgdG8gYSBydW5uaW5nIFBsYXRmb3JtLlxuICAgICAqIFJlcXVlc3RlZCBzbmFwc2hvdCBtdXN0IGJlIGEgdmFsaWQgU25hcHNob3Qgb2JqZWN0LCBvciBhIHVybCBvciBmaWxlcGF0aCB0byBzdWNoIGFuIG9iamVjdC5cbiAgICAgKlxuICAgICAqIENhbiBvcHRpb25hbGx5IGNsb3NlIGV4aXN0aW5nIHdpbmRvd3MgYW5kIG92ZXJ3cml0ZSBjdXJyZW50IHBsYXRmb3JtIHN0YXRlIHdpdGggdGhhdCBvZiBhIHNuYXBzaG90LlxuICAgICAqXG4gICAgICogVGhlIGZ1bmN0aW9uIGFjY2VwdHMgZWl0aGVyIGEgc25hcHNob3QgdGFrZW4gdXNpbmcge0BsaW5rIFBsYXRmb3JtI2dldFNuYXBzaG90IGdldFNuYXBzaG90fSxcbiAgICAgKiBvciBhIHVybCBvciBmaWxlcGF0aCB0byBhIHNuYXBzaG90IEpTT04gb2JqZWN0LlxuICAgICAqIEBwYXJhbSByZXF1ZXN0ZWRTbmFwc2hvdCBTbmFwc2hvdCB0byBhcHBseSwgb3IgYSB1cmwgb3IgZmlsZXBhdGguXG4gICAgICogQHBhcmFtIG9wdGlvbnMgT3B0aW9uYWwgcGFyYW1ldGVycyB0byBzcGVjaWZ5IHdoZXRoZXIgZXhpc3Rpbmcgd2luZG93cyBzaG91bGQgYmUgY2xvc2VkLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgV2lsbCBjcmVhdGUgYW55IHdpbmRvd3MgYW5kIHZpZXdzIHRoYXQgYXJlIG5vdCBydW5uaW5nIGJ1dCBhcmUgcGFzc2VkIGluIHRoZSBzbmFwc2hvdCBvYmplY3QuIEFueSBWaWV3XG4gICAgICogc3BlY2lmaWVkIGluIHRoZSBzbmFwc2hvdCBpcyBhc3NpZ25lZCBhIHJhbmRvbWx5IGdlbmVyYXRlZCBuYW1lIHRvIGF2b2lkIGNvbGxpc2lvbnMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogLy8gR2V0IGEgd3JhcHBlZCBsYXlvdXQgcGxhdGZvcm0gaW5zdGFuY2VcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50KCk7XG4gICAgICpcbiAgICAgKiBjb25zdCBzbmFwc2hvdCA9IHtcbiAgICAgKiAgICAgd2luZG93czogW1xuICAgICAqICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgIGxheW91dDoge1xuICAgICAqICAgICAgICAgICAgICAgICBjb250ZW50OiBbXG4gICAgICogICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3N0YWNrJyxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50OiBbXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjb21wb25lbnQnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50TmFtZTogJ3ZpZXcnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50U3RhdGU6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAnY29tcG9uZW50X1gnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vd3d3Lm9wZW5maW4uY28nXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjb21wb25lbnQnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50TmFtZTogJ3ZpZXcnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50U3RhdGU6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAnY29tcG9uZW50X1knLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogJ2h0dHBzOi8vY2RuLm9wZW5maW4uY28vZW1iZWQtd2ViL2NoYXJ0Lmh0bWwnXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBdXG4gICAgICogICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgIF1cbiAgICAgKiAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICB9XG4gICAgICogICAgIF1cbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBwbGF0Zm9ybS5hcHBseVNuYXBzaG90KHNuYXBzaG90KTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEluIHBsYWNlIG9mIGEgc25hcHNob3Qgb2JqZWN0LCBgYXBwbHlTbmFwc2hvdGAgY2FuIHRha2UgYSB1cmwgb3IgZmlsZXBhdGggYW5kIHRvIHJldHJpZXZlIGEgSlNPTiBzbmFwc2hvdC5cbiAgICAgKlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudCgpO1xuICAgICAqIHBsYXRmb3JtLmFwcGx5U25hcHNob3QoJ2h0dHBzOi8vYXBpLmpzb25iaW4uaW8vYi81ZTZmOTAzZWY0MzMxZTY4MWZjMTIzMWQvMScpO1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogT3B0aW9uYWxseSwgYGFwcGx5U25hcHNob3RgIGNhbiBjbG9zZSBleGlzdGluZyB3aW5kb3dzIGFuZCByZXN0b3JlIGEgUGxhdGZvcm0gdG8gYSBwcmV2aW91c2x5IHNhdmVkIHN0YXRlLlxuICAgICAqIFRoaXMgaXMgYWNjb21wbGlzaGVkIGJ5IHByb3ZpZGluZyBgeyBjbG9zZUV4aXN0aW5nV2luZG93czogdHJ1ZSB9YCBhcyBhbiBvcHRpb24uXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIC8vIEdldCBhIHdyYXBwZWQgbGF5b3V0IHBsYXRmb3JtIGluc3RhbmNlXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudCgpO1xuICAgICAqXG4gICAgICogYXN5bmMgZnVuY3Rpb24gYWRkVmlld1RvV2luZG93KHdpbklkKSB7XG4gICAgICogICAgIHJldHVybiBhd2FpdCBwbGF0Zm9ybS5jcmVhdGVWaWV3KHtcbiAgICAgKiAgICAgICAgIG5hbWU6ICd0ZXN0X3ZpZXdfMycsXG4gICAgICogICAgICAgICB1cmw6ICdodHRwczovL29wZW5maW4uY28nXG4gICAgICogICAgIH0sIHdpbklkKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBhc3luYyBmdW5jdGlvbiBjcmVhdGVXaW5kb3dXaXRoVHdvVmlld3MoKSB7XG4gICAgICogICAgIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLmdldEN1cnJlbnQoKTtcbiAgICAgKlxuICAgICAqICAgICByZXR1cm4gcGxhdGZvcm0uY3JlYXRlV2luZG93KHtcbiAgICAgKiAgICAgICAgIGxheW91dDoge1xuICAgICAqICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3N0YWNrJyxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdjb21wb25lbnQnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnROYW1lOiAndmlldycsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudFN0YXRlOiB7XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAndGVzdF92aWV3XzEnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly9leGFtcGxlLmNvbSdcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnY29tcG9uZW50JyxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50TmFtZTogJ3ZpZXcnLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRTdGF0ZToge1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogJ3Rlc3Rfdmlld18yJyxcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybDogJ2h0dHBzOi8veWFob28uY29tJ1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAqICAgICAgICAgICAgICAgICB9XG4gICAgICogICAgICAgICAgICAgXVxuICAgICAqICAgICAgICAgfVxuICAgICAqICAgICB9KTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBjb25zdCB3aW4gPSBhd2FpdCBjcmVhdGVXaW5kb3dXaXRoVHdvVmlld3MoKTtcbiAgICAgKiAvLyAuLi4geW91IHdpbGwgbm93IHNlZSBhIG5ldyB3aW5kb3cgd2l0aCB0d28gdmlld3MgaW4gaXRcbiAgICAgKlxuICAgICAqIC8vIHdlIHRha2UgYSBzbmFwc2hvdCBvZiB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgYXBwLCBiZWZvcmUgY2hhbmdpbmcgaXRcbiAgICAgKiBjb25zdCBzbmFwc2hvdE9mSW5pdGlhbEFwcFN0YXRlID0gYXdhaXQgcGxhdGZvcm0uZ2V0U25hcHNob3QoKTtcbiAgICAgKlxuICAgICAqIC8vIG5vdyBsZXQncyBjaGFuZ2UgdGhlIHN0YXRlIG9mIHRoZSBhcHA6XG4gICAgICogYXdhaXQgYWRkVmlld1RvV2luZG93KHdpbi5pZGVudGl0eSk7XG4gICAgICogLy8gLi4uIHRoZSB3aW5kb3cgbm93IGhhcyB0aHJlZSB2aWV3cyBpbiBpdFxuICAgICAqXG4gICAgICogYXdhaXQgcGxhdGZvcm0uYXBwbHlTbmFwc2hvdChzbmFwc2hvdE9mSW5pdGlhbEFwcFN0YXRlLCB7IGNsb3NlRXhpc3RpbmdXaW5kb3dzOiB0cnVlIH0pO1xuICAgICAqIC8vIC4uLiB0aGUgd2luZG93IHdpbGwgcmV2ZXJ0IHRvIHByZXZpb3VzIHN0YXRlLCB3aXRoIGp1c3QgdHdvIHZpZXdzXG4gICAgICpcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBhcHBseVNuYXBzaG90KHJlcXVlc3RlZFNuYXBzaG90LCBvcHRpb25zKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwbGF0Zm9ybS1hcHBseS1zbmFwc2hvdCcsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGVyck1zZyA9ICdSZXF1ZXN0ZWQgc25hcHNob3QgbXVzdCBiZSBhIHZhbGlkIFNuYXBzaG90IG9iamVjdCwgb3IgYSB1cmwgb3IgZmlsZXBhdGggdG8gc3VjaCBhbiBvYmplY3QuJztcbiAgICAgICAgbGV0IHNuYXBzaG90O1xuICAgICAgICBpZiAodHlwZW9mIHJlcXVlc3RlZFNuYXBzaG90ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gRmV0Y2ggYW5kIHBhcnNlIHNuYXBzaG90XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5fY2hhbm5lbC53aXJlLnNlbmRBY3Rpb24oJ2dldC1hcHBsaWNhdGlvbi1tYW5pZmVzdCcsIHtcbiAgICAgICAgICAgICAgICAgICAgbWFuaWZlc3RVcmw6IHJlcXVlc3RlZFNuYXBzaG90XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc25hcHNob3QgPSByZXNwb25zZS5wYXlsb2FkLmRhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2Vyck1zZ306ICR7ZXJyfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc25hcHNob3QgPSByZXF1ZXN0ZWRTbmFwc2hvdDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXNuYXBzaG90LndpbmRvd3MpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJNc2cpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XG4gICAgICAgIGF3YWl0IGNsaWVudC5kaXNwYXRjaCgnYXBwbHktc25hcHNob3QnLCB7XG4gICAgICAgICAgICBzbmFwc2hvdCxcbiAgICAgICAgICAgIG9wdGlvbnNcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIGEgSlNPTiBtYW5pZmVzdCB1c2luZyB0aGUgYnJvd3NlciBwcm9jZXNzIGFuZCByZXR1cm5zIGEgSmF2YXNjcmlwdCBvYmplY3QuXG4gICAgICogQ2FuIGJlIG92ZXJ3cml0dGVuIHVzaW5nIHtAbGluayBQbGF0Zm9ybS5QbGF0Zm9ybU1vZHVsZS5pbml0IFBsYXRmb3JtLmluaXR9LlxuICAgICAqIEBwYXJhbSBtYW5pZmVzdFVybCBUaGUgVVJMIG9mIHRoZSBtYW5pZmVzdCB0byBmZXRjaC5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIENhbiBiZSBvdmVyd3JpdHRlbiB1c2luZyB7QGxpbmsgUGxhdGZvcm0jaW5pdCBQbGF0Zm9ybS5pbml0fS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICpcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gZmluLlBsYXRmb3JtLmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogY29uc3QgbWFuaWZlc3QgPSBhd2FpdCBwbGF0Zm9ybS5mZXRjaE1hbmlmZXN0KCdodHRwczovL3d3dy5wYXRoLXRvLW1hbmlmZXN0LmNvbS9hcHAuanNvbicpO1xuICAgICAqIGNvbnNvbGUubG9nKG1hbmlmZXN0KTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBmZXRjaE1hbmlmZXN0KG1hbmlmZXN0VXJsKSB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XG4gICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ3BsYXRmb3JtLWZldGNoLW1hbmlmZXN0JywgeyBtYW5pZmVzdFVybCB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIGEgbWFuaWZlc3QgYnkgdXJsIGFuZCBsYXVuY2hlcyBhIGxlZ2FjeSBhcHBsaWNhdGlvbiBtYW5pZmVzdCBvciBzbmFwc2hvdCBpbnRvIHRoZSBwbGF0Zm9ybS4gIFJldHVybnMgYSBwcm9taXNlIHRoYXRcbiAgICAgKiByZXNvbHZlcyB0byB0aGUgd3JhcHBlZCBQbGF0Zm9ybS5cbiAgICAgKiBAcGFyYW0gbWFuaWZlc3RVcmwgLSBUaGUgVVJMIG9mIHRoZSBtYW5pZmVzdCB0aGF0IHdpbGwgYmUgbGF1bmNoZWQgaW50byB0aGUgcGxhdGZvcm0uICBJZiB0aGlzIGFwcCBtYW5pZmVzdFxuICAgICAqIGNvbnRhaW5zIGEgc25hcHNob3QsIHRoYXQgd2lsbCBiZSBsYXVuY2hlZCBpbnRvIHRoZSBwbGF0Zm9ybS4gIElmIG5vdCwgdGhlIGFwcGxpY2F0aW9uIGRlc2NyaWJlZCBpbiBzdGFydHVwX2FwcCBvcHRpb25zXG4gICAgICogd2lsbCBiZSBsYXVuY2hlZCBpbnRvIHRoZSBwbGF0Zm9ybS4gVGhlIGFwcGxpY2FibGUgc3RhcnR1cF9hcHAgb3B0aW9ucyB3aWxsIGJlY29tZSB7QGxpbmsgT3BlbkZpbi5WaWV3Q3JlYXRpb25PcHRpb25zIFZpZXcgT3B0aW9uc30uXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBJZiB0aGUgYXBwIG1hbmlmZXN0IGNvbnRhaW5zIGEgc25hcHNob3QsIHRoYXQgd2lsbCBiZSBsYXVuY2hlZCBpbnRvIHRoZSBwbGF0Zm9ybS4gIElmIG5vdCwgdGhlXG4gICAgICogYXBwbGljYXRpb24gZGVzY3JpYmVkIGluIHN0YXJ0dXBfYXBwIG9wdGlvbnMgd2lsbCBiZSBsYXVuY2hlZCBpbnRvIHRoZSBwbGF0Zm9ybSBhcyBhIHdpbmRvdyB3aXRoIGEgc2luZ2xlIHZpZXcuXG4gICAgICogVGhlIGFwcGxpY2FibGUgc3RhcnR1cF9hcHAgb3B0aW9ucyB3aWxsIGJlY29tZSBWaWV3IE9wdGlvbnMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogdHJ5IHtcbiAgICAgKiAgICAgY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKiAgICAgYXdhaXQgcGxhdGZvcm0ubGF1bmNoQ29udGVudE1hbmlmZXN0KCdodHRwOi8vbG9jYWxob3N0OjU1NTUvYXBwLmpzb24nKTtcbiAgICAgKiAgICAgY29uc29sZS5sb2coYGNvbnRlbnQgbGF1bmNoZWQgc3VjY2Vzc2Z1bGx5IGludG8gcGxhdGZvcm1gKTtcbiAgICAgKiB9IGNhdGNoKGUpIHtcbiAgICAgKiAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgKiB9XG4gICAgICogLy8gRm9yIGEgbG9jYWwgbWFuaWZlc3QgZmlsZTpcbiAgICAgKiB0cnkge1xuICAgICAqICAgICBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqICAgICBwbGF0Zm9ybS5sYXVuY2hDb250ZW50TWFuaWZlc3QoJ2ZpbGU6Ly8vQzovc29tZWZvbGRlci9hcHAuanNvbicpO1xuICAgICAqICAgICBjb25zb2xlLmxvZyhgY29udGVudCBsYXVuY2hlZCBzdWNjZXNzZnVsbHkgaW50byBwbGF0Zm9ybWApO1xuICAgICAqIH0gY2F0Y2goZSkge1xuICAgICAqICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICovXG4gICAgYXN5bmMgbGF1bmNoQ29udGVudE1hbmlmZXN0KG1hbmlmZXN0VXJsKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwbGF0Zm9ybS1sYXVuY2gtY29udGVudC1tYW5pZmVzdCcsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgdGhpcy5nZXRDbGllbnQoKTtcbiAgICAgICAgY29uc3QgbWFuaWZlc3QgPSBhd2FpdCB0aGlzLmZldGNoTWFuaWZlc3QobWFuaWZlc3RVcmwpO1xuICAgICAgICBjbGllbnQuZGlzcGF0Y2goJ2xhdW5jaC1pbnRvLXBsYXRmb3JtJywgeyBtYW5pZmVzdCwgbWFuaWZlc3RVcmwgfSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGNvbnRleHQgb2YgYSBob3N0IHdpbmRvdy4gVGhlIGNvbnRleHQgd2lsbCBiZSBhdmFpbGFibGUgdG8gdGhlIHdpbmRvdyBpdHNlbGYsIGFuZCB0byBpdHMgY2hpbGQgVmlld3MuIEl0IHdpbGwgYmUgc2F2ZWQgaW4gYW55IHBsYXRmb3JtIHNuYXBzaG90cy5cbiAgICAgKiBJdCBjYW4gYmUgcmV0cmlldmVkIHVzaW5nIHtAbGluayBQbGF0Zm9ybSNnZXRXaW5kb3dDb250ZXh0IGdldFdpbmRvd0NvbnRleHR9LlxuICAgICAqIEBwYXJhbSBjb250ZXh0IC0gQSBmaWVsZCB3aGVyZSBzZXJpYWxpemFibGUgY29udGV4dCBkYXRhIGNhbiBiZSBzdG9yZWQgdG8gYmUgc2F2ZWQgaW4gcGxhdGZvcm0gc25hcHNob3RzLlxuICAgICAqIEBwYXJhbSB0YXJnZXQgLSBBIHRhcmdldCB3aW5kb3cgb3IgdmlldyBtYXkgb3B0aW9uYWxseSBiZSBwcm92aWRlZC4gSWYgbm8gdGFyZ2V0IGlzIHByb3ZpZGVkLCB0aGUgdXBkYXRlIHdpbGwgYmUgYXBwbGllZFxuICAgICAqIHRvIHRoZSBjdXJyZW50IHdpbmRvdyAoaWYgY2FsbGVkIGZyb20gYSBXaW5kb3cpIG9yIHRoZSBjdXJyZW50IGhvc3Qgd2luZG93IChpZiBjYWxsZWQgZnJvbSBhIFZpZXcpLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgVGhlIGNvbnRleHQgZGF0YSBtdXN0IGJlIHNlcmlhbGl6YWJsZS4gIFRoaXMgY2FuIG9ubHkgYmUgY2FsbGVkIGZyb20gYSB3aW5kb3cgb3IgdmlldyB0aGF0IGhhcyBiZWVuIGxhdW5jaGVkIGludG8gYVxuICAgICAqIHBsYXRmb3JtLlxuICAgICAqIFRoaXMgbWV0aG9kIGNhbiBiZSBjYWxsZWQgZnJvbSB0aGUgd2luZG93IGl0c2VsZiwgb3IgZnJvbSBhbnkgY2hpbGQgdmlldy4gQ29udGV4dCBkYXRhIGlzIHNoYXJlZCBieSBhbGxcbiAgICAgKiBlbnRpdGllcyB3aXRoaW4gYSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIFNldHRpbmcgb3duIGNvbnRleHQ6XG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIGNvbnN0IGNvbnRleHREYXRhID0ge1xuICAgICAqICAgICBzZWN1cml0eTogJ1NUT0NLJyxcbiAgICAgKiAgICAgY3VycmVudFZpZXc6ICdkZXRhaWxlZCdcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBhd2FpdCBwbGF0Zm9ybS5zZXRXaW5kb3dDb250ZXh0KGNvbnRleHREYXRhKTtcbiAgICAgKiAvLyBDb250ZXh0IG9mIGN1cnJlbnQgd2luZG93IGlzIG5vdyBzZXQgdG8gYGNvbnRleHREYXRhYFxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogU2V0dGluZyB0aGUgY29udGV4dCBvZiBhbm90aGVyIHdpbmRvdyBvciB2aWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKiBjb25zdCBjb250ZXh0RGF0YSA9IHtcbiAgICAgKiAgICAgc2VjdXJpdHk6ICdTVE9DSycsXG4gICAgICogICAgIGN1cnJlbnRWaWV3OiAnZGV0YWlsZWQnXG4gICAgICogfVxuICAgICAqXG4gICAgICogY29uc3Qgd2luZG93T3JWaWV3SWRlbnRpdHkgPSB7IHV1aWQ6IGZpbi5tZS51dWlkLCBuYW1lOiAnbmFtZU9mV2luZG93T3JWaWV3JyB9O1xuICAgICAqIGF3YWl0IHBsYXRmb3JtLnNldFdpbmRvd0NvbnRleHQoY29udGV4dERhdGEsIHdpbmRvd09yVmlld0lkZW50aXR5KTtcbiAgICAgKiAvLyBDb250ZXh0IG9mIHRoZSB0YXJnZXQgd2luZG93IG9yIHZpZXcgaXMgbm93IHNldCB0byBgY29udGV4dERhdGFgXG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBBIHZpZXcgY2FuIGxpc3RlbiB0byBjaGFuZ2VzIHRvIGl0cyBob3N0IHdpbmRvdydzIGNvbnRleHQgYnkgbGlzdGVuaW5nIHRvIHRoZSBgaG9zdC1jb250ZXh0LWNoYW5nZWRgIGV2ZW50LlxuICAgICAqIFRoaXMgZXZlbnQgd2lsbCBmaXJlIHdoZW4gYSBob3N0IHdpbmRvdydzIGNvbnRleHQgaXMgdXBkYXRlZCBvciB3aGVuIHRoZSB2aWV3IGlzIHJlcGFyZW50ZWQgdG8gYSBuZXcgd2luZG93OlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAvLyBGcm9tIGEgdmlld1xuICAgICAqIGNvbnN0IGNvbnRleHRDaGFuZ2VIYW5kbGVyID0gKHsgY29udGV4dCB9KSA9PiB7XG4gICAgICogICAgIGNvbnNvbGUubG9nKCdIb3N0IHdpbmRvd1xcJ3MgY29udGV4dCBoYXMgY2hhbmdlZC4gTmV3IGNvbnRleHQgZGF0YTonLCBjb250ZXh0KTtcbiAgICAgKiAgICAgLy8gcmVhY3QgdG8gbmV3IGNvbnRleHQgZGF0YSBoZXJlXG4gICAgICogfVxuICAgICAqIGF3YWl0IGZpbi5tZS5vbignaG9zdC1jb250ZXh0LWNoYW5nZWQnLCBjb250ZXh0Q2hhbmdlSGFuZGxlcik7XG4gICAgICpcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIGNvbnN0IGNvbnRleHREYXRhID0ge1xuICAgICAqICAgICBzZWN1cml0eTogJ1NUT0NLJyxcbiAgICAgKiAgICAgY3VycmVudFZpZXc6ICdkZXRhaWxlZCdcbiAgICAgKiB9XG4gICAgICogcGxhdGZvcm0uc2V0V2luZG93Q29udGV4dChjb250ZXh0RGF0YSkgLy8gY29udGV4dENoYW5nZUhhbmRsZXIgd2lsbCBsb2cgdGhlIG5ldyBjb250ZXh0XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBUbyBsaXN0ZW4gdG8gYSB3aW5kb3cncyBjb250ZXh0IHVwZGF0ZXMsIHVzZSB0aGUgYGNvbnRleHQtY2hhbmdlZGAgZXZlbnQ6XG4gICAgICogYGBganNcbiAgICAgKiAvLyBGcm9tIGEgd2luZG93XG4gICAgICogY29uc3QgY29udGV4dENoYW5nZUhhbmRsZXIgPSAoeyBjb250ZXh0IH0pID0+IHtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ1RoaXMgd2luZG93XFwncyBjb250ZXh0IGhhcyBjaGFuZ2VkLiBOZXcgY29udGV4dCBkYXRhOicsIGNvbnRleHQpO1xuICAgICAqICAgICAvLyByZWFjdCB0byBuZXcgY29udGV4dCBkYXRhIGhlcmVcbiAgICAgKiB9XG4gICAgICogYXdhaXQgZmluLm1lLm9uKCdjb250ZXh0LWNoYW5nZWQnLCBjb250ZXh0Q2hhbmdlSGFuZGxlcik7XG4gICAgICpcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIGNvbnN0IGNvbnRleHREYXRhID0ge1xuICAgICAqICAgICBzZWN1cml0eTogJ1NUT0NLJyxcbiAgICAgKiAgICAgY3VycmVudFZpZXc6ICdkZXRhaWxlZCdcbiAgICAgKiB9XG4gICAgICogcGxhdGZvcm0uc2V0V2luZG93Q29udGV4dChjb250ZXh0RGF0YSkgLy8gY29udGV4dENoYW5nZUhhbmRsZXIgd2lsbCBsb2cgdGhlIG5ldyBjb250ZXh0XG4gICAgICogYGBgXG4gICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAqL1xuICAgIGFzeW5jIHNldFdpbmRvd0NvbnRleHQoY29udGV4dCA9IHt9LCB0YXJnZXQpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLXNldC13aW5kb3ctY29udGV4dCcsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICghY29udGV4dCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQbGVhc2UgcHJvdmlkZSBhIHNlcmlhbGl6YWJsZSBvYmplY3Qgb3Igc3RyaW5nIHRvIHNldCB0aGUgY29udGV4dC4nKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xuICAgICAgICBjb25zdCB7IGVudGl0eVR5cGUgfSA9IHRhcmdldCA/IGF3YWl0IHRoaXMuZmluLlN5c3RlbS5nZXRFbnRpdHlJbmZvKHRhcmdldC51dWlkLCB0YXJnZXQubmFtZSkgOiB0aGlzLmZpbi5tZTtcbiAgICAgICAgYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdzZXQtd2luZG93LWNvbnRleHQnLCB7XG4gICAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgICAgZW50aXR5VHlwZSxcbiAgICAgICAgICAgIHRhcmdldDogdGFyZ2V0IHx8IHsgdXVpZDogdGhpcy5maW4ubWUudXVpZCwgbmFtZTogdGhpcy5maW4ubWUubmFtZSB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGNvbnRleHQgY29udGV4dCBvZiBhIGhvc3Qgd2luZG93IHRoYXQgd2FzIHByZXZpb3VzbHkgc2V0IHVzaW5nIHtAbGluayBQbGF0Zm9ybSNzZXRXaW5kb3dDb250ZXh0IHNldFdpbmRvd0NvbnRleHR9LlxuICAgICAqIFRoZSBjb250ZXh0IHdpbGwgYmUgc2F2ZWQgaW4gYW55IHBsYXRmb3JtIHNuYXBzaG90cy4gIFJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIGNvbnRleHQuXG4gICAgICogQHBhcmFtIHRhcmdldCAtIEEgdGFyZ2V0IHdpbmRvdyBvciB2aWV3IG1heSBvcHRpb25hbGx5IGJlIHByb3ZpZGVkLiBJZiBubyB0YXJnZXQgaXMgcHJvdmlkZWQsIHRhcmdldCB3aWxsIGJlXG4gICAgICogdGhlIGN1cnJlbnQgd2luZG93IChpZiBjYWxsZWQgZnJvbSBhIFdpbmRvdykgb3IgdGhlIGN1cnJlbnQgaG9zdCB3aW5kb3cgKGlmIGNhbGxlZCBmcm9tIGEgVmlldykuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBUaGlzIG1ldGhvZCBjYW4gYmUgY2FsbGVkIGZyb20gdGhlIHdpbmRvdyBpdHNlbGYsIG9yIGZyb20gYW55IGNoaWxkIHZpZXcuIENvbnRleHQgZGF0YSBpcyBzaGFyZWRcbiAgICAgKiBieSBhbGwgZW50aXRpZXMgd2l0aGluIGEgd2luZG93LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKlxuICAgICAqIFJldHJpZXZpbmcgY29udGV4dCBmcm9tIGN1cnJlbnQgd2luZG93OlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKiBjb25zdCBjdXN0b21Db250ZXh0ID0geyBhbnN3ZXI6IDQyIH07XG4gICAgICogYXdhaXQgcGxhdGZvcm0uc2V0V2luZG93Q29udGV4dChjdXN0b21Db250ZXh0KTtcbiAgICAgKlxuICAgICAqIGNvbnN0IG15Q29udGV4dCA9IGF3YWl0IHBsYXRmb3JtLmdldFdpbmRvd0NvbnRleHQoKTtcbiAgICAgKiBjb25zb2xlLmxvZyhteUNvbnRleHQpOyAvLyB7IGFuc3dlcjogNDIgfVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogUmV0cmlldmluZyB0aGUgY29udGV4dCBvZiBhbm90aGVyIHdpbmRvdyBvciB2aWV3OlxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKlxuICAgICAqIGNvbnN0IHdpbmRvd09yVmlld0lkZW50aXR5ID0geyB1dWlkOiBmaW4ubWUudXVpZCwgbmFtZTogJ25hbWVPZldpbmRvd09yVmlldycgfTtcbiAgICAgKlxuICAgICAqIGNvbnN0IHRhcmdldFdpbmRvd0NvbnRleHQgPSBhd2FpdCBwbGF0Zm9ybS5nZXRXaW5kb3dDb250ZXh0KHdpbmRvd09yVmlld0lkZW50aXR5KTtcbiAgICAgKiBjb25zb2xlLmxvZyh0YXJnZXRXaW5kb3dDb250ZXh0KTsgLy8gY29udGV4dCBvZiB0YXJnZXQgd2luZG93XG4gICAgICogYGBgXG4gICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAqL1xuICAgIGFzeW5jIGdldFdpbmRvd0NvbnRleHQodGFyZ2V0KSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwbGF0Zm9ybS1nZXQtd2luZG93LWNvbnRleHQnLCB0aGlzLmlkZW50aXR5KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLmdldENsaWVudCgpO1xuICAgICAgICBjb25zdCB7IGVudGl0eVR5cGUgfSA9IHRhcmdldCA/IGF3YWl0IHRoaXMuZmluLlN5c3RlbS5nZXRFbnRpdHlJbmZvKHRhcmdldC51dWlkLCB0YXJnZXQubmFtZSkgOiB0aGlzLmZpbi5tZTtcbiAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnZ2V0LXdpbmRvdy1jb250ZXh0Jywge1xuICAgICAgICAgICAgdGFyZ2V0OiB0YXJnZXQgfHwgeyB1dWlkOiB0aGlzLmZpbi5tZS51dWlkLCBuYW1lOiB0aGlzLmZpbi5tZS5uYW1lIH0sXG4gICAgICAgICAgICBlbnRpdHlUeXBlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBDbG9zZXMgYSB3aW5kb3cuIElmIGVuYWJsZUJlZm9yZVVubG9hZCBpcyBlbmFibGVkIGluIHRoZSBQbGF0Zm9ybSBvcHRpb25zLCBhbnkgYmVmb3JldW5sb2FkIGhhbmRsZXIgc2V0IG9uIFZpZXdzIHdpbGwgZmlyZVxuICAgICAqIFRoaXMgYmVoYXZpb3IgY2FuIGJlIGRpc2FibGVkIGJ5IHNldHRpbmcgc2tpcEJlZm9yZVVubG9hZCB0byBmYWxzZSBpbiB0aGUgb3B0aW9ucyBwYXJhbWV0ZXIuXG4gICAgICogQHBhcmFtIHdpbklkXG4gICAgICogQHBhcmFtIG9wdGlvbnNcbiAgICAgKlxuICAgICAqIEByZW1hcmtzIFRoaXMgbWV0aG9kIHdvcmtzIGJ5IHNldHRpbmcgYSBgY2xvc2UtcmVxdWVzdGVkYCBoYW5kbGVyIG9uIHRoZSBQbGF0Zm9ybSBXaW5kb3cuIElmIHlvdSBoYXZlIHlvdXIgb3duIGBjbG9zZS1yZXF1ZXN0ZWRgIGhhbmRsZXIgc2V0IG9uIHRoZSBQbGF0Zm9ybSBXaW5kb3cgYXMgd2VsbCxcbiAgICAgKiBpdCBpcyByZWNvbW1lbmRlZCB0byBtb3ZlIHRoYXQgbG9naWMgb3ZlciB0byB0aGUgW1BsYXRmb3JtUHJvdmlkZXIuY2xvc2VXaW5kb3dde0BsaW5rIFBsYXRmb3JtUHJvdmlkZXIjY2xvc2VXaW5kb3d9IG92ZXJyaWRlIHRvIGVuc3VyZSBpdCBydW5zIHdoZW4gdGhlIFdpbmRvdyBjbG9zZXMuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAvLyBDbG9zZSB0aGUgY3VycmVudCBXaW5kb3cgaW5zaWRlIGEgV2luZG93IGNvbnRleHRcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50KCk7XG4gICAgICogcGxhdGZvcm0uY2xvc2VXaW5kb3coZmluLm1lLmlkZW50aXR5KTtcbiAgICAgKlxuICAgICAqIC8vIENsb3NlIHRoZSBXaW5kb3cgZnJvbSBpbnNpZGUgYSBWaWV3IGNvbnRleHRcbiAgICAgKiBjb25zdCBwbGF0Zm9ybSA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5nZXRDdXJyZW50KCk7XG4gICAgICogY29uc3QgcGFyZW50V2luZG93ID0gYXdhaXQgZmluLm1lLmdldEN1cnJlbnRXaW5kb3coKTtcbiAgICAgKiBwbGF0Zm9ybS5jbG9zZVdpbmRvdyhwYXJlbnRXaW5kb3cuaWRlbnRpdHkpO1xuICAgICAqXG4gICAgICogLy8gQ2xvc2UgdGhlIFdpbmRvdyBhbmQgZG8gbm90IGZpcmUgdGhlIGJlZm9yZSB1bmxvYWQgaGFuZGxlciBvbiBWaWV3c1xuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLmdldEN1cnJlbnQoKTtcbiAgICAgKiBwbGF0Zm9ybS5jbG9zZVdpbmRvdyhmaW4ubWUuaWRlbnRpdHksIHsgc2tpcEJlZm9yZVVubG9hZDogdHJ1ZSB9KTtcbiAgICAgKiBgYGBcbiAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICovXG4gICAgYXN5bmMgY2xvc2VXaW5kb3cod2luZG93SWQsIG9wdGlvbnMgPSB7IHNraXBCZWZvcmVVbmxvYWQ6IGZhbHNlIH0pIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLWNsb3NlLXdpbmRvdycsIHRoaXMuaWRlbnRpdHkpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZ2V0Q2xpZW50KCk7XG4gICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2Nsb3NlLXdpbmRvdycsIHsgd2luZG93SWQsIG9wdGlvbnMgfSk7XG4gICAgfVxufVxuSW5zdGFuY2UkMi5QbGF0Zm9ybSA9IFBsYXRmb3JtO1xuX1BsYXRmb3JtX2Nvbm5lY3RUb1Byb3ZpZGVyID0gbmV3IFdlYWtNYXAoKTtcblxudmFyIGxheW91dCA9IHt9O1xuXG52YXIgRmFjdG9yeSQyID0ge307XG5cbnZhciBJbnN0YW5jZSQxID0ge307XG5cbnZhciBjb21tb25VdGlscyA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoY29tbW9uVXRpbHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuY29tbW9uVXRpbHMub3ZlcnJpZGVGcm9tQ29tcG9zYWJsZXMgPSBjb21tb25VdGlscy5pc1ZhbGlkUHJlc2V0VHlwZSA9IHZvaWQgMDtcbmZ1bmN0aW9uIGlzVmFsaWRQcmVzZXRUeXBlKHR5cGUpIHtcbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSAnY29sdW1ucyc6XG4gICAgICAgIGNhc2UgJ2dyaWQnOlxuICAgICAgICBjYXNlICdyb3dzJzpcbiAgICAgICAgY2FzZSAndGFicyc6XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG5jb21tb25VdGlscy5pc1ZhbGlkUHJlc2V0VHlwZSA9IGlzVmFsaWRQcmVzZXRUeXBlO1xuZnVuY3Rpb24gb3ZlcnJpZGVGcm9tQ29tcG9zYWJsZXMoLi4ub3ZlcnJpZGVzKSB7XG4gICAgcmV0dXJuIChiYXNlKSA9PiBvdmVycmlkZXMucmVkdWNlUmlnaHQoKHAsIGMpID0+IChiKSA9PiBjKHAoYikpLCAoeCkgPT4geCkoYmFzZSk7XG59XG5jb21tb25VdGlscy5vdmVycmlkZUZyb21Db21wb3NhYmxlcyA9IG92ZXJyaWRlRnJvbUNvbXBvc2FibGVzO1xuY29tbW9uVXRpbHMuZGVmYXVsdCA9IHsgaXNWYWxpZFByZXNldFR5cGUgfTtcblxudmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkNCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9MYXlvdXRfbGF5b3V0Q2xpZW50O1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KEluc3RhbmNlJDEsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuSW5zdGFuY2UkMS5MYXlvdXQgPSB2b2lkIDA7XG5jb25zdCBsYXp5XzEgPSBsYXp5O1xuY29uc3QgdmFsaWRhdGVfMSA9IHZhbGlkYXRlO1xuY29uc3QgYmFzZV8xJDUgPSBiYXNlO1xuY29uc3QgY29tbW9uX3V0aWxzXzEgPSBjb21tb25VdGlscztcbmNvbnN0IGxheW91dF9lbnRpdGllc18xID0gbGF5b3V0RW50aXRpZXM7XG5jb25zdCBsYXlvdXRfY29uc3RhbnRzXzEkMSA9IGxheW91dF9jb25zdGFudHM7XG4vKipcbiAqXG4gKiBMYXlvdXRzIGdpdmUgYXBwIHByb3ZpZGVycyB0aGUgYWJpbGl0eSB0byBlbWJlZCBtdWx0aXBsZSB2aWV3cyBpbiBhIHNpbmdsZSB3aW5kb3cuIFRoZSBMYXlvdXQgbmFtZXNwYWNlXG4gKiBlbmFibGVzIHRoZSBpbml0aWFsaXphdGlvbiBhbmQgbWFuaXB1bGF0aW9uIG9mIGEgd2luZG93J3MgTGF5b3V0LiBBIExheW91dCB3aWxsXG4gKiBlbWl0IGV2ZW50cyBsb2NhbGx5IG9uIHRoZSBET00gZWxlbWVudCByZXByZXNlbnRpbmcgdGhlIGxheW91dC1jb250YWluZXIuXG4gKlxuICpcbiAqICMjIyBMYXlvdXQuRE9NRXZlbnRzXG4gKlxuICogV2hlbiBhIExheW91dCBpcyBjcmVhdGVkLCBpdCBlbWl0cyBldmVudHMgb250byB0aGUgRE9NIGVsZW1lbnQgcmVwcmVzZW50aW5nIHRoZSBMYXlvdXQgY29udGFpbmVyLlxuICogVGhpcyBMYXlvdXQgY29udGFpbmVyIGlzIHRoZSBET00gZWxlbWVudCByZWZlcmVuY2VkIGJ5IGNvbnRhaW5lcklkIGluIHtAbGluayBMYXlvdXQuTGF5b3V0TW9kdWxlI2luaXQgTGF5b3V0LmluaXR9LlxuICogWW91IGNhbiB1c2UgdGhlIGJ1aWx0LWluIGV2ZW50IGVtaXR0ZXIgdG8gbGlzdGVuIHRvIHRoZXNlIGV2ZW50cyB1c2luZyBbYWRkRXZlbnRMaXN0ZW5lcl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0V2ZW50VGFyZ2V0L2FkZEV2ZW50TGlzdGVuZXIpLlxuICogVGhlIGV2ZW50cyBhcmUgZW1pdHRlZCBzeW5jaHJvbm91c2x5IGFuZCBvbmx5IGluIHRoZSBwcm9jZXNzIHdoZXJlIHRoZSBMYXlvdXQgZXhpc3RzLlxuICogQW55IHZhbHVlcyByZXR1cm5lZCBieSB0aGUgY2FsbGVkIGxpc3RlbmVycyBhcmUgaWdub3JlZCBhbmQgd2lsbCBiZSBkaXNjYXJkZWQuXG4gKiBJZiB0aGUgdGFyZ2V0IERPTSBlbGVtZW50IGlzIGRlc3Ryb3llZCwgYW55IGV2ZW50cyB0aGF0IGhhdmUgYmVlbiBzZXQgdXAgb24gdGhhdCBlbGVtZW50IHdpbGwgYmUgZGVzdHJveWVkLlxuICpcbiAqIEByZW1hcmtzIFRoZSBidWlsdC1pbiBldmVudCBlbWl0dGVyIGlzIG5vdCBhbiBPcGVuRmluIGV2ZW50IGVtaXR0ZXIgc28gaXQgZG9lc24ndCBzaGFyZSBwcm9wYWdhdGlvbiBzZW1hbnRpY3MuXG4gKlxuICogIyMjIyB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0V2ZW50VGFyZ2V0L2FkZEV2ZW50TGlzdGVuZXIgYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lciBbLCBvcHRpb25zXSk7fVxuICogQWRkcyBhIGxpc3RlbmVyIHRvIHRoZSBlbmQgb2YgdGhlIGxpc3RlbmVycyBhcnJheSBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAqIEBleGFtcGxlXG4gKiBgYGBqc1xuICogY29uc3QgbXlMYXlvdXRDb250YWluZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbGF5b3V0LWNvbnRhaW5lcicpO1xuICpcbiAqIG15TGF5b3V0Q29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ3RhYi1jcmVhdGVkJywgZnVuY3Rpb24oZXZlbnQpIHtcbiAqICAgICAgY29uc3QgeyB0YWJTZWxlY3RvciB9ID0gZXZlbnQuZGV0YWlsO1xuICogICAgICBjb25zdCB0YWJFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFiU2VsZWN0b3IpO1xuICogICAgICBjb25zdCBleGlzdGluZ0NvbG9yID0gdGFiRWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3I7XG4gKiAgICAgIHRhYkVsZW1lbnQuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gXCJyZWRcIjtcbiAqICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gKiAgICAgICAgICB0YWJFbGVtZW50LnN0eWxlLmJhY2tncm91bmRDb2xvciA9IGV4aXN0aW5nQ29sb3I7XG4gKiAgICAgIH0sIDIwMDApO1xuICogfSk7XG4gKiBgYGBcbiAqXG4gKiAjIyMjIHtAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvRXZlbnRUYXJnZXQvcmVtb3ZlRXZlbnRMaXN0ZW5lciByZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyIFssIG9wdGlvbnNdKTt9XG4gKiBBZGRzIGEgbGlzdGVuZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGlzdGVuZXJzIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICogQGV4YW1wbGVcbiAqIGBgYGpzXG4gKiBjb25zdCBteUxheW91dENvbnRhaW5lciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdsYXlvdXQtY29udGFpbmVyJyk7XG4gKlxuICogY29uc3QgbGlzdGVuZXIgPSBmdW5jdGlvbihldmVudCkge1xuICogICAgIGNvbnNvbGUubG9nKGV2ZW50LmRldGFpbCk7XG4gKiAgICAgY29uc29sZS5sb2coJ2NvbnRhaW5lci1jcmVhdGVkIGV2ZW50IGZpcmVkIG9uY2UsIHJlbW92aW5nIGxpc3RlbmVyJyk7XG4gKiAgICAgbXlMYXlvdXRDb250YWluZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignY29udGFpbmVyLWNyZWF0ZWQnLCBsaXN0ZW5lcik7XG4gKiB9O1xuICpcbiAqIG15TGF5b3V0Q29udGFpbmVyLmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRhaW5lci1jcmVhdGVkJywgbGlzdGVuZXIpO1xuICogYGBgXG4gKlxuICogIyMjIFN1cHBvcnRlZCBldmVudCB0eXBlcyBhcmU6XG4gKlxuICogKiB0YWItY3JlYXRlZFxuICogKiBjb250YWluZXItY3JlYXRlZFxuICogKiBsYXlvdXQtc3RhdGUtY2hhbmdlZFxuICogKiB0YWItY2xvc2VkXG4gKiAqIHRhYi1kcm9wcGVkXG4gKlxuICogIyMjIExheW91dCBET00gTm9kZSBFdmVudHNcbiAqXG4gKiAjIyMjIHRhYi1jcmVhdGVkXG4gKiBHZW5lcmF0ZWQgd2hlbiBhIHRhYiBpcyBjcmVhdGVkLiAgQXMgYSB1c2VyIGRyYWdzIGFuZCBkcm9wcyB0YWJzIHdpdGhpbiB3aW5kb3csIG5ldyB0YWJzIGFyZSBjcmVhdGVkLiAgQSBzaW5nbGUgdmlldyBtYXkgaGF2ZSBtdWx0aXBsZSB0YWJzIGNyZWF0ZWQgYW5kIGRlc3Ryb3llZCBkdXJpbmcgaXRzIGxpZmV0aW1lIGF0dGFjaGVkIHRvIGEgc2luZ2xlIHdpbmRvdy5cbiAqIGBgYGpzXG4gKiAvLyBUaGUgcmVzcG9uc2UgaGFzIHRoZSBmb2xsb3dpbmcgc2hhcGUgaW4gZXZlbnQuZGV0YWlsOlxuICoge1xuICogICAgIGNvbnRhaW5lclNlbGVjdG9yOiBcImNvbnRhaW5lci1jb21wb25lbnRfQVwiLFxuICogICAgIG5hbWU6IFwiY29tcG9uZW50X0FcIixcbiAqICAgICB0YWJTZWxlY3RvcjogXCJ0YWItY29tcG9uZW50X0FcIixcbiAqICAgICB0b3BpYzogXCJvcGVuZmluLURPTS1ldmVudFwiLFxuICogICAgIHR5cGU6IFwidGFiLWNyZWF0ZWRcIixcbiAqICAgICB1dWlkOiBcIk9wZW5GaW4gUE9DXCJcbiAqIH1cbiAqIGBgYFxuICpcbiAqICMjIyMgY29udGFpbmVyLWNyZWF0ZWRcbiAqIEdlbmVyYXRlZCB3aGVuIGEgY29udGFpbmVyIGlzIGNyZWF0ZWQuICBBIHNpbmdsZSB2aWV3IHdpbGwgaGF2ZSBvbmx5IG9uZSBjb250YWluZXIgZHVyaW5nIGl0cyBsaWZldGltZSBhdHRhY2hlZCB0byBhIHNpbmdsZSB3aW5kb3cgYW5kIHRoZSBjb250YWluZXIncyBsaWZlY3ljbGUgaXMgdGllZCB0byB0aGUgdmlldy4gIFRvIGRpc2NvdmVyIHdoZW4gdGhlIGNvbnRhaW5lciBpcyBkZXN0cm95ZWQsIHBsZWFzZSBsaXN0ZW4gdG8gdmlldy1kZXRhY2hlZCBldmVudC5cbiAqIGBgYGpzXG4gKiAvLyBUaGUgcmVzcG9uc2UgaGFzIHRoZSBmb2xsb3dpbmcgc2hhcGUgaW4gZXZlbnQuZGV0YWlsOlxuICoge1xuICogICAgIGNvbnRhaW5lclNlbGVjdG9yOiBcImNvbnRhaW5lci1jb21wb25lbnRfQVwiLFxuICogICAgIG5hbWU6IFwiY29tcG9uZW50X0FcIixcbiAqICAgICB0YWJTZWxlY3RvcjogXCJ0YWItY29tcG9uZW50X0FcIixcbiAqICAgICB0b3BpYzogXCJvcGVuZmluLURPTS1ldmVudFwiLFxuICogICAgIHR5cGU6IFwiY29udGFpbmVyLWNyZWF0ZWRcIixcbiAqICAgICB1dWlkOiBcIk9wZW5GaW4gUE9DXCJcbiAqIH1cbiAqIGBgYFxuICpcbiAqICMjIyBsYXlvdXQtc3RhdGUtY2hhbmdlZFxuICogR2VuZXJhdGVkIHdoZW4gdGhlIHN0YXRlIG9mIHRoZSBsYXlvdXQgY2hhbmdlcyBpbiBhbnkgd2F5LCBzdWNoIGFzIGEgdmlldyBhZGRlZC9yZW1vdmVkL3JlcGxhY2VkLiBOb3RlIHRoYXQgdGhpcyBldmVudCBjYW4gZmlyZSBmcmVxdWVudGx5IGFzIHRoZSB1bmRlcmx5aW5nIGxheW91dCBjYW4gY2hhbmdlIG11bHRpcGxlIGNvbXBvbmVudHMgZnJvbSBhbGwga2luZHMgb2YgY2hhbmdlcyAocmVzaXppbmcgZm9yIGV4YW1wbGUpLiBHaXZlbiB0aGlzLCBpdCBpcyByZWNvbW1lbmRlZCB0byBkZWJvdW5jZSB0aGlzIGV2ZW50IGFuZCB0aGVuIHlvdSBjYW4gdXNlIHRoZSB7QGxpbmsgTGF5b3V0I2dldENvbmZpZyBMYXlvdXQuZ2V0Q29uZmlnfSBBUEkgdG8gcmV0cmlldmUgdGhlIG1vc3QgdXAtdG8tZGF0ZSBzdGF0ZS5cbiAqIGBgYGpzXG4gKiAvLyBUaGUgcmVzcG9uc2UgaGFzIHRoZSBmb2xsb3dpbmcgc2hhcGUgaW4gZXZlbnQuZGV0YWlsXG4gKiB7XG4gKiAgICAgY29udGFpbmVyU2VsZWN0b3I6IFwiY29udGFpbmVyLWNvbXBvbmVudF9BXCIsXG4gKiAgICAgbmFtZTogXCJjb21wb25lbnRfQVwiLFxuICogICAgIHRhYlNlbGVjdG9yOiBcInRhYi1jb21wb25lbnRfQVwiLFxuICogICAgIHRvcGljOiBcIm9wZW5maW4tRE9NLWV2ZW50XCIsXG4gKiAgICAgdHlwZTogXCJsYXlvdXQtc3RhdGUtY2hhbmdlZFwiLFxuICogICAgIHV1aWQ6IFwiT3BlbkZpbiBQT0NcIlxuICogfVxuICogYGBgXG4gKlxuICogIyMjIyB0YWItY2xvc2VkXG4gKiBHZW5lcmF0ZWQgd2hlbiBhIHRhYiBpcyBjbG9zZWQuXG4gKiBgYGBqc1xuICogLy8gVGhlIHJlc3BvbnNlIGhhcyB0aGUgZm9sbG93aW5nIHNoYXBlIGluIGV2ZW50LmRldGFpbDpcbiAqIHtcbiAqICAgICBjb250YWluZXJTZWxlY3RvcjogXCJjb250YWluZXItY29tcG9uZW50X0FcIixcbiAqICAgICBuYW1lOiBcImNvbXBvbmVudF9BXCIsXG4gKiAgICAgdGFiU2VsZWN0b3I6IFwidGFiLWNvbXBvbmVudF9BXCIsXG4gKiAgICAgdG9waWM6IFwib3BlbmZpbi1ET00tZXZlbnRcIixcbiAqICAgICB0eXBlOiBcInRhYi1jbG9zZWRcIixcbiAqICAgICB1dWlkOiBcIk9wZW5GaW4gUE9DXCIsXG4gKiAgICAgdXJsOiBcImh0dHA6Ly9vcGVuZmluLmNvXCIgICAvLyBUaGUgdXJsIG9mIHRoZSB2aWV3IHRoYXQgd2FzIGNsb3NlZC5cbiAqIH1cbiAqIGBgYFxuICpcbiAqICMjIyMgdGFiLWRyb3BwZWRcbiAqIEdlbmVyYXRlZCB3aGVuIGEgdGFiIGlzIGRyb3BwZWQuXG4gKiBgYGBqc1xuICogLy8gVGhlIHJlc3BvbnNlIGhhcyB0aGUgZm9sbG93aW5nIHNoYXBlIGluIGV2ZW50LmRldGFpbDpcbiAqIHtcbiAqICAgICBjb250YWluZXJTZWxlY3RvcjogXCJjb250YWluZXItY29tcG9uZW50X0FcIixcbiAqICAgICBuYW1lOiBcImNvbXBvbmVudF9BXCIsXG4gKiAgICAgdGFiU2VsZWN0b3I6IFwidGFiLWNvbXBvbmVudF9BXCIsXG4gKiAgICAgdG9waWM6IFwib3BlbmZpbi1ET00tZXZlbnRcIixcbiAqICAgICB0eXBlOiBcInRhYi1kcm9wcGVkXCIsXG4gKiAgICAgdXVpZDogXCJPcGVuRmluIFBPQ1wiLFxuICogICAgIHVybDogXCJodHRwOi8vb3BlbmZpbi5jb1wiICAgIC8vIFRoZSB1cmwgb2YgdGhlIHZpZXcgbGlua2VkIHRvIHRoZSBkcm9wcGVkIHRhYi5cbiAqIH1cbiAqIGBgYFxuICovXG5jbGFzcyBMYXlvdXQgZXh0ZW5kcyBiYXNlXzEkNS5CYXNlIHtcbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2hhZG93XG4gICAgY29uc3RydWN0b3IoaWRlbnRpdHksIHdpcmUpIHtcbiAgICAgICAgc3VwZXIod2lyZSk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAaW50ZXJuYWxcbiAgICAgICAgICogTGF6aWx5IGNvbnN0cnVjdGVkIHtAbGluayBMYXlvdXRFbnRpdGllc0NsaWVudH0gYm91bmQgdG8gdGhpcyBwbGF0Zm9ybSdzIGNsaWVudCBhbmQgaWRlbnRpdHlcbiAgICAgICAgICogVGhlIGNsaWVudCBpcyBmb3Ige0BsaW5rIExheW91dEVudGl0aWVzQ29udHJvbGxlcn1cbiAgICAgICAgICovXG4gICAgICAgIF9MYXlvdXRfbGF5b3V0Q2xpZW50LnNldCh0aGlzLCBuZXcgbGF6eV8xLkxhenkoYXN5bmMgKCkgPT4gbGF5b3V0X2VudGl0aWVzXzEuTGF5b3V0Tm9kZS5uZXdMYXlvdXRFbnRpdGllc0NsaWVudChhd2FpdCB0aGlzLnBsYXRmb3JtLmdldENsaWVudCgpLCBsYXlvdXRfY29uc3RhbnRzXzEkMS5MQVlPVVRfQ09OVFJPTExFUl9JRCwgdGhpcy5pZGVudGl0eSkpKTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJlcGxhY2VzIGEgUGxhdGZvcm0gd2luZG93J3MgbGF5b3V0IHdpdGggYSBuZXcgbGF5b3V0LlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcmVtYXJrcyBBbnkgdmlld3MgdGhhdCB3ZXJlIGluIHRoZSBvbGQgbGF5b3V0IGJ1dCBub3QgdGhlIG5ldyBsYXlvdXQgd2lsbCBiZSBkZXN0cm95ZWQuIFZpZXdzIHdpbGwgYmUgYXNzaWduZWQgYSByYW5kb21seSBnZW5lcmF0ZWQgbmFtZSB0byBhdm9pZCBjb2xsaXNpb25zLlxuICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgKiBgYGBqc1xuICAgICAgICAgKiBsZXQgd2luZG93SWRlbnRpdHk7XG4gICAgICAgICAqIGlmIChmaW4ubWUuaXNXaW5kb3cpIHtcbiAgICAgICAgICogICAgIHdpbmRvd0lkZW50aXR5ID0gZmluLm1lLmlkZW50aXR5O1xuICAgICAgICAgKiB9IGVsc2UgaWYgKGZpbi5tZS5pc1ZpZXcpIHtcbiAgICAgICAgICogICAgIHdpbmRvd0lkZW50aXR5ID0gKGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50V2luZG93KCkpLmlkZW50aXR5O1xuICAgICAgICAgKiB9IGVsc2Uge1xuICAgICAgICAgKiAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgcnVubmluZyBpbiBhIHBsYXRmb3JtIFZpZXcgb3IgV2luZG93Jyk7XG4gICAgICAgICAqIH1cbiAgICAgICAgICpcbiAgICAgICAgICogY29uc3QgbGF5b3V0ID0gZmluLlBsYXRmb3JtLkxheW91dC53cmFwU3luYyh3aW5kb3dJZGVudGl0eSk7XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IG5ld0xheW91dCA9IHtcbiAgICAgICAgICogICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICogICAgICAgICB7XG4gICAgICAgICAqICAgICAgICAgICAgIHR5cGU6ICdzdGFjaycsXG4gICAgICAgICAqICAgICAgICAgICAgIGNvbnRlbnQ6IFtcbiAgICAgICAgICogICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICB0eXBlOiAnY29tcG9uZW50JyxcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICBjb21wb25lbnROYW1lOiAndmlldycsXG4gICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50U3RhdGU6IHtcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogJ25ld19jb21wb25lbnRfQTEnLFxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzQWZmaW5pdHk6ICdwc18xJyxcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20nXG4gICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICogICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICB0eXBlOiAnY29tcG9uZW50JyxcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICBjb21wb25lbnROYW1lOiAndmlldycsXG4gICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50U3RhdGU6IHtcbiAgICAgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogJ25ld19jb21wb25lbnRfQTInLFxuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB1cmw6ICdodHRwczovL2Nkbi5vcGVuZmluLmNvL2VtYmVkLXdlYi9jaGFydC5odG1sJ1xuICAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICogICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICogICAgICAgICAgICAgXVxuICAgICAgICAgKiAgICAgICAgIH1cbiAgICAgICAgICogICAgIF1cbiAgICAgICAgICogfTtcbiAgICAgICAgICpcbiAgICAgICAgICogbGF5b3V0LnJlcGxhY2UobmV3TGF5b3V0KTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqL1xuICAgICAgICB0aGlzLnJlcGxhY2UgPSBhc3luYyAobGF5b3V0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignbGF5b3V0LXJlcGxhY2UnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLnBsYXRmb3JtLmdldENsaWVudCgpO1xuICAgICAgICAgICAgYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdyZXBsYWNlLWxheW91dCcsIHtcbiAgICAgICAgICAgICAgICB0YXJnZXQ6IHRoaXMuaWRlbnRpdHksXG4gICAgICAgICAgICAgICAgb3B0czogeyBsYXlvdXQgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXBsYWNlcyB0aGUgc3BlY2lmaWVkIHZpZXcgd2l0aCBhIHZpZXcgd2l0aCB0aGUgcHJvdmlkZWQgY29uZmlndXJhdGlvbi5cbiAgICAgICAgICpcbiAgICAgICAgICogQHJlbWFya3MgVGhlIG9sZCB2aWV3IGlzIHN0cmlwcGVkIG9mIGl0cyBsaXN0ZW5lcnMgYW5kIGVpdGhlciBjbG9zZWQgb3IgYXR0YWNoZWQgdG8gdGhlIHByb3ZpZGVyIHdpbmRvd1xuICAgICAgICAgKiBkZXBlbmRpbmcgb24gYGRldGFjaE9uQ2xvc2VgIHZpZXcgb3B0aW9uLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gdmlld1RvUmVwbGFjZSBJZGVudGl0eSBvZiB0aGUgdmlldyB0byBiZSByZXBsYWNlZFxuICAgICAgICAgKiBAcGFyYW0gbmV3VmlldyBDcmVhdGlvbiBvcHRpb25zIG9mIHRoZSBuZXcgdmlldy5cbiAgICAgICAgICpcbiAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogbGV0IGN1cnJlbnRXaW5kb3c7XG4gICAgICAgICAqIGlmIChmaW4ubWUuaXNXaW5kb3cpIHtcbiAgICAgICAgICogICAgIGN1cnJlbnRXaW5kb3cgPSBmaW4ubWU7XG4gICAgICAgICAqIH0gZWxzZSBpZiAoZmluLm1lLmlzVmlldykge1xuICAgICAgICAgKiAgICAgY3VycmVudFdpbmRvdyA9IGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50V2luZG93KCk7XG4gICAgICAgICAqIH0gZWxzZSB7XG4gICAgICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldyBvciBXaW5kb3cnKTtcbiAgICAgICAgICogfVxuICAgICAgICAgKlxuICAgICAgICAgKiBjb25zdCBsYXlvdXQgPSBmaW4uUGxhdGZvcm0uTGF5b3V0LndyYXBTeW5jKGN1cnJlbnRXaW5kb3cuaWRlbnRpdHkpO1xuICAgICAgICAgKiBjb25zdCB2aWV3VG9SZXBsYWNlID0gKGF3YWl0IGN1cnJlbnRXaW5kb3cuZ2V0Q3VycmVudFZpZXdzKCkpWzBdO1xuICAgICAgICAgKiBjb25zdCBuZXdWaWV3Q29uZmlnID0ge3VybDogJ2h0dHBzOi8vZXhhbXBsZS5jb20nfTtcbiAgICAgICAgICogYXdhaXQgbGF5b3V0LnJlcGxhY2VWaWV3KHZpZXdUb1JlcGxhY2UuaWRlbnRpdHksIG5ld1ZpZXdDb25maWcpO1xuICAgICAgICAgKiBgYGBcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMucmVwbGFjZVZpZXcgPSBhc3luYyAodmlld1RvUmVwbGFjZSwgbmV3VmlldykgPT4ge1xuICAgICAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2xheW91dC1yZXBsYWNlLXZpZXcnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLnBsYXRmb3JtLmdldENsaWVudCgpO1xuICAgICAgICAgICAgYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdyZXBsYWNlLXZpZXcnLCB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0OiB0aGlzLmlkZW50aXR5LFxuICAgICAgICAgICAgICAgIG9wdHM6IHsgdmlld1RvUmVwbGFjZSwgbmV3VmlldyB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFJlcGxhY2VzIGEgUGxhdGZvcm0gd2luZG93J3MgbGF5b3V0IHdpdGggYSBwcmVzZXQgbGF5b3V0IGFycmFuZ2VtZW50IHVzaW5nIHRoZSBleGlzdGluZyBWaWV3cyBhdHRhY2hlZCB0byB0aGUgd2luZG93LlxuICAgICAgICAgKiBUaGUgcHJlc2V0IG9wdGlvbnMgYXJlIGBjb2x1bW5zYCwgYGdyaWRgLCBgcm93c2AsIGFuZCBgdGFic2AuXG4gICAgICAgICAqIEBwYXJhbSBvcHRpb25zIE1hbmRhdG9yeSBvYmplY3Qgd2l0aCBgcHJlc2V0VHlwZWAgcHJvcGVydHkgdGhhdCBzZXRzIHdoaWNoIHByZXNldCBsYXlvdXQgYXJyYW5nZW1lbnQgdG8gdXNlLlxuICAgICAgICAgKiBUaGUgcHJlc2V0IG9wdGlvbnMgYXJlIGBjb2x1bW5zYCwgYGdyaWRgLCBgcm93c2AsIGFuZCBgdGFic2AuXG4gICAgICAgICAqXG4gICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAqIGBgYGpzXG4gICAgICAgICAqIGxldCB3aW5kb3dJZGVudGl0eTtcbiAgICAgICAgICogaWYgKGZpbi5tZS5pc1dpbmRvdykge1xuICAgICAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSBmaW4ubWUuaWRlbnRpdHk7XG4gICAgICAgICAqIH0gZWxzZSBpZiAoZmluLm1lLmlzVmlldykge1xuICAgICAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSAoYXdhaXQgZmluLm1lLmdldEN1cnJlbnRXaW5kb3coKSkuaWRlbnRpdHk7XG4gICAgICAgICAqIH0gZWxzZSB7XG4gICAgICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldyBvciBXaW5kb3cnKTtcbiAgICAgICAgICogfVxuICAgICAgICAgKlxuICAgICAgICAgKiBjb25zdCBsYXlvdXQgPSBmaW4uUGxhdGZvcm0uTGF5b3V0LndyYXBTeW5jKHdpbmRvd0lkZW50aXR5KTtcbiAgICAgICAgICogYXdhaXQgbGF5b3V0LmFwcGx5UHJlc2V0KHsgcHJlc2V0VHlwZTogJ2dyaWQnIH0pO1xuICAgICAgICAgKlxuICAgICAgICAgKiAvLyB3YWl0IDUgc2Vjb25kcyB1bnRpbCB5b3UgY2hhbmdlIHRoZSBsYXlvdXQgZnJvbSBncmlkIHRvIHRhYnNcbiAgICAgICAgICogYXdhaXQgbmV3IFByb21pc2UgKHJlcyA9PiBzZXRUaW1lb3V0KHJlcywgNTAwMCkpO1xuICAgICAgICAgKiBhd2FpdCBsYXlvdXQuYXBwbHlQcmVzZXQoeyBwcmVzZXRUeXBlOiAndGFicycgfSk7XG4gICAgICAgICAqIGBgYFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5hcHBseVByZXNldCA9IGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignbGF5b3V0LWFwcGx5LXByZXNldCcpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMucGxhdGZvcm0uZ2V0Q2xpZW50KCk7XG4gICAgICAgICAgICBjb25zdCB7IHByZXNldFR5cGUgfSA9IG9wdGlvbnM7XG4gICAgICAgICAgICBpZiAoIXByZXNldFR5cGUgfHwgISgwLCBjb21tb25fdXRpbHNfMS5pc1ZhbGlkUHJlc2V0VHlwZSkocHJlc2V0VHlwZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhcHBseSBwcmVzZXQgbGF5b3V0LCBwbGVhc2UgaW5jbHVkZSBhbiBhcHBsaWNhYmxlIHByZXNldFR5cGUgcHJvcGVydHkgaW4gdGhlIFByZXNldExheW91dE9wdGlvbnMuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ2FwcGx5LXByZXNldC1sYXlvdXQnLCB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0OiB0aGlzLmlkZW50aXR5LFxuICAgICAgICAgICAgICAgIG9wdHM6IHsgcHJlc2V0VHlwZSB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZXJyb3JNc2cgPSAoMCwgdmFsaWRhdGVfMS52YWxpZGF0ZUlkZW50aXR5KShpZGVudGl0eSk7XG4gICAgICAgIGlmIChlcnJvck1zZykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yTXNnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmlkZW50aXR5ID0gaWRlbnRpdHk7XG4gICAgICAgIHRoaXMucGxhdGZvcm0gPSB0aGlzLmZpbi5QbGF0Zm9ybS53cmFwU3luYyh7IHV1aWQ6IGlkZW50aXR5LnV1aWQgfSk7XG4gICAgICAgIGlmIChpZGVudGl0eS51dWlkID09PSB0aGlzLmZpbi5tZS51dWlkICYmIGlkZW50aXR5Lm5hbWUgPT09IHRoaXMuZmluLm1lLm5hbWUpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdCA9IHRoaXMuZmluLlBsYXRmb3JtLkxheW91dC5pbml0O1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIHdpbmRvdydzIGxheW91dC4gIFJldHVybnMgdGhlIHNhbWUgaW5mb3JtYXRpb24gdGhhdCBpcyByZXR1cm5lZCBmb3IgYWxsIHdpbmRvd3MgaW4gZ2V0U25hcHNob3QuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBDYW5ub3QgYmUgY2FsbGVkIGZyb20gYSBWaWV3LlxuICAgICAqXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgbGF5b3V0ID0gZmluLlBsYXRmb3JtLkxheW91dC5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIC8vIFVzZSB3cmFwcGVkIGluc3RhbmNlIHRvIGdldCB0aGUgbGF5b3V0IGNvbmZpZ3VyYXRpb24gb2YgdGhlIGN1cnJlbnQgd2luZG93J3MgTGF5b3V0OlxuICAgICAqIGNvbnN0IGxheW91dENvbmZpZyA9IGF3YWl0IGxheW91dC5nZXRDb25maWcoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBnZXRDb25maWcoKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdsYXlvdXQtZ2V0LWNvbmZpZycpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMucGxhdGZvcm0uZ2V0Q2xpZW50KCk7XG4gICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2dldC1mcmFtZS1zbmFwc2hvdCcsIHtcbiAgICAgICAgICAgIHRhcmdldDogdGhpcy5pZGVudGl0eVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSBhdHRhY2hlZCB2aWV3cyBpbiBjdXJyZW50IHdpbmRvdyBsYXlvdXQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgbGF5b3V0ID0gZmluLlBsYXRmb3JtLkxheW91dC5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIGNvbnN0IHZpZXdzID0gYXdhaXQgbGF5b3V0LmdldEN1cnJlbnRWaWV3cygpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIGdldEN1cnJlbnRWaWV3cygpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2xheW91dC1nZXQtdmlld3MnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCB0aGlzLnBsYXRmb3JtLmdldENsaWVudCgpO1xuICAgICAgICBjb25zdCB2aWV3SWRlbnRpdGllcyA9IGF3YWl0IGNsaWVudC5kaXNwYXRjaCgnZ2V0LWxheW91dC12aWV3cycsIHtcbiAgICAgICAgICAgIHRhcmdldDogdGhpcy5pZGVudGl0eVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHZpZXdJZGVudGl0aWVzLm1hcCgoaWRlbnRpdHkpID0+IHRoaXMuZmluLlZpZXcud3JhcFN5bmMoaWRlbnRpdHkpKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHRoZSB0b3AgbGV2ZWwgY29udGVudCBpdGVtIG9mIHRoZSBsYXlvdXQuXG4gICAgICpcbiAgICAgKiBAcmVtYXJrcyBDYW5ub3QgYmUgY2FsbGVkIGZyb20gYSB2aWV3LlxuICAgICAqXG4gICAgICpcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBpZiAoIWZpbi5tZS5pc1dpbmRvdykge1xuICAgICAqICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBydW5uaW5nIGluIGEgcGxhdGZvcm0gVmlldy4nKTtcbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiAvLyBGcm9tIHRoZSBsYXlvdXQgd2luZG93XG4gICAgICogY29uc3QgbGF5b3V0ID0gZmluLlBsYXRmb3JtLkxheW91dC5nZXRDdXJyZW50U3luYygpO1xuICAgICAqIC8vIFJldHJpZXZlcyB0aGUgQ29sdW1uT3JSb3cgaW5zdGFuY2VcbiAgICAgKiBjb25zdCByb290SXRlbSA9IGF3YWl0IGxheW91dC5nZXRSb290SXRlbSgpO1xuICAgICAqIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCByb290SXRlbS5nZXRDb250ZW50KCk7XG4gICAgICogY29uc29sZS5sb2coYFRoZSByb290IENvbHVtbk9yUm93IGluc3RhbmNlIGhhcyAke2NvbnRlbnQubGVuZ3RofSBpdGVtKHMpYCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgZ2V0Um9vdEl0ZW0oKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdsYXlvdXQtZ2V0LXJvb3QtaXRlbScpLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQ0KHRoaXMsIF9MYXlvdXRfbGF5b3V0Q2xpZW50LCBcImZcIikuZ2V0VmFsdWUoKTtcbiAgICAgICAgY29uc3Qgcm9vdCA9IGF3YWl0IGNsaWVudC5nZXRSb290KCdsYXlvdXROYW1lJyBpbiB0aGlzLmlkZW50aXR5ID8gdGhpcy5pZGVudGl0eSA6IHVuZGVmaW5lZCk7XG4gICAgICAgIHJldHVybiBsYXlvdXRfZW50aXRpZXNfMS5MYXlvdXROb2RlLmdldEVudGl0eShyb290LCBjbGllbnQpO1xuICAgIH1cbn1cbkluc3RhbmNlJDEuTGF5b3V0ID0gTGF5b3V0O1xuX0xheW91dF9sYXlvdXRDbGllbnQgPSBuZXcgV2Vha01hcCgpO1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQzID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcbn07XG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQzID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufTtcbnZhciBfTGF5b3V0TW9kdWxlX2luc3RhbmNlcywgX0xheW91dE1vZHVsZV9sYXlvdXRJbml0aWFsaXphdGlvbkF0dGVtcHRlZCwgX0xheW91dE1vZHVsZV9sYXlvdXRNYW5hZ2VyLCBfTGF5b3V0TW9kdWxlX2dldExheW91dE1hbmFnZXJTcHksIF9MYXlvdXRNb2R1bGVfZ2V0U2FmZUxheW91dE1hbmFnZXI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoRmFjdG9yeSQyLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbkZhY3RvcnkkMi5MYXlvdXRNb2R1bGUgPSB2b2lkIDA7XG5jb25zdCBiYXNlXzEkNCA9IGJhc2U7XG5jb25zdCBJbnN0YW5jZV8xJDIgPSBJbnN0YW5jZSQxO1xuY29uc3QgbGF5b3V0X2NvbnN0YW50c18xID0gbGF5b3V0X2NvbnN0YW50cztcbi8qKlxuICogU3RhdGljIG5hbWVzcGFjZSBmb3IgT3BlbkZpbiBBUEkgbWV0aG9kcyB0aGF0IGludGVyYWN0IHdpdGggdGhlIHtAbGluayBMYXlvdXR9IGNsYXNzLCBhdmFpbGFibGUgdW5kZXIgYGZpbi5QbGF0Zm9ybS5MYXlvdXRgLlxuICovXG5jbGFzcyBMYXlvdXRNb2R1bGUgZXh0ZW5kcyBiYXNlXzEkNC5CYXNlIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgX0xheW91dE1vZHVsZV9pbnN0YW5jZXMuYWRkKHRoaXMpO1xuICAgICAgICBfTGF5b3V0TW9kdWxlX2xheW91dEluaXRpYWxpemF0aW9uQXR0ZW1wdGVkLnNldCh0aGlzLCBmYWxzZSk7XG4gICAgICAgIF9MYXlvdXRNb2R1bGVfbGF5b3V0TWFuYWdlci5zZXQodGhpcywgbnVsbCk7XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbml0aWFsaXplIHRoZSB3aW5kb3cncyBMYXlvdXQuXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZW1hcmtzIE11c3QgYmUgY2FsbGVkIGZyb20gYSBjdXN0b20gd2luZG93IHRoYXQgaGFzIGEgJ2xheW91dCcgb3B0aW9uIHNldCB1cG9uIGNyZWF0aW9uIG9mIHRoYXQgd2luZG93LlxuICAgICAgICAgKiBJZiBhIGNvbnRhaW5lcklkIGlzIG5vdCBwcm92aWRlZCwgdGhpcyBtZXRob2QgYXR0ZW1wdHMgdG8gZmluZCBhbiBlbGVtZW50IHdpdGggdGhlIGlkIGBsYXlvdXQtY29udGFpbmVyYC5cbiAgICAgICAgICogQSBMYXlvdXQgd2lsbCBlbWl0IGV2ZW50cyBsb2NhbGx5IG9uIHRoZSBET00gZWxlbWVudCByZXByZXNlbnRpbmcgdGhlIGxheW91dC1jb250YWluZXIuXG4gICAgICAgICAqIEluIG9yZGVyIHRvIGNhcHR1cmUgdGhlIHJlbGV2YW50IGV2ZW50cyBkdXJpbmcgTGF5b3V0IGluaXRpYXRpb24sIHNldCB1cCB0aGUgbGlzdGVuZXJzIG9uIHRoZSBET00gZWxlbWVudCBwcmlvciB0byBjYWxsaW5nIGBpbml0YC5cbiAgICAgICAgICogQHBhcmFtIG9wdGlvbnMgLSBMYXlvdXQgaW5pdCBvcHRpb25zLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAZXhwZXJpbWVudGFsXG4gICAgICAgICAqXG4gICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAqIGBgYGpzXG4gICAgICAgICAqIC8vIElmIG5vIG9wdGlvbnMgYXJlIGluY2x1ZGVkLCB0aGUgbGF5b3V0IGluIHRoZSB3aW5kb3cgb3B0aW9ucyBpcyBpbml0aWFsaXplZCBpbiBhbiBlbGVtZW50IHdpdGggdGhlIGlkIGBsYXlvdXQtY29udGFpbmVyYFxuICAgICAgICAgKiBjb25zdCBsYXlvdXQgPSBhd2FpdCBmaW4uUGxhdGZvcm0uTGF5b3V0LmluaXQoKTtcbiAgICAgICAgICogYGBgXG4gICAgICAgICAqIDxicj5cbiAgICAgICAgICpcbiAgICAgICAgICogYGBganNcbiAgICAgICAgICogY29uc3QgY29udGFpbmVySWQgPSAnbXktY3VzdG9tLWNvbnRhaW5lci1pZCc7XG4gICAgICAgICAqXG4gICAgICAgICAqIGNvbnN0IG15TGF5b3V0Q29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoY29udGFpbmVySWQpO1xuICAgICAgICAgKlxuICAgICAgICAgKiBteUxheW91dENvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCd0YWItY3JlYXRlZCcsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAqICAgICBjb25zdCB7IHRhYlNlbGVjdG9yIH0gPSBldmVudC5kZXRhaWw7XG4gICAgICAgICAqICAgICBjb25zdCB0YWJFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFiU2VsZWN0b3IpO1xuICAgICAgICAgKiAgICAgY29uc3QgZXhpc3RpbmdDb2xvciA9IHRhYkVsZW1lbnQuc3R5bGUuYmFja2dyb3VuZENvbG9yO1xuICAgICAgICAgKiAgICAgdGFiRWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBcInJlZFwiO1xuICAgICAgICAgKiAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAqICAgICAgICAgdGFiRWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBleGlzdGluZ0NvbG9yO1xuICAgICAgICAgKiAgICAgfSwgMjAwMCk7XG4gICAgICAgICAqIH0pO1xuICAgICAgICAgKlxuICAgICAgICAgKiAvLyBpbml0aWFsaXplIHRoZSBsYXlvdXQgaW50byBhbiBleGlzdGluZyBIVE1MIGVsZW1lbnQgd2l0aCB0aGUgZGl2IGBteS1jdXN0b20tY29udGFpbmVyLWlkYFxuICAgICAgICAgKiAvLyB0aGUgd2luZG93IG11c3QgaGF2ZSBiZWVuIGNyZWF0ZWQgd2l0aCBhIGxheW91dCBpbiBpdHMgd2luZG93IG9wdGlvbnNcbiAgICAgICAgICogY29uc3QgbGF5b3V0ID0gYXdhaXQgZmluLlBsYXRmb3JtLkxheW91dC5pbml0KHsgY29udGFpbmVySWQgfSk7XG4gICAgICAgICAqIGBgYFxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5pbml0ID0gYXN5bmMgKG9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2xheW91dC1pbml0JykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCF0aGlzLndpcmUuZW52aXJvbm1lbnQubGF5b3V0QWxsb3dlZEluQ29udGV4dCh0aGlzLmZpbikpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xheW91dC5pbml0IGNhbiBvbmx5IGJlIGNhbGxlZCBmcm9tIGEgV2luZG93IGNvbnRleHQuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX19jbGFzc1ByaXZhdGVGaWVsZEdldCQzKHRoaXMsIF9MYXlvdXRNb2R1bGVfbGF5b3V0SW5pdGlhbGl6YXRpb25BdHRlbXB0ZWQsIFwiZlwiKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTGF5b3V0LmluaXQgd2FzIGFscmVhZHkgY2FsbGVkLCBwbGVhc2UgdXNlIExheW91dC5jcmVhdGUgdG8gYWRkIGFkZGl0aW9uYWwgbGF5b3V0cy4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLndpcmUuZW52aXJvbm1lbnQudHlwZSA9PT0gJ29wZW5maW4nKSB7XG4gICAgICAgICAgICAgICAgLy8gcHJlbG9hZCB0aGUgY2xpZW50XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5maW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKS5nZXRDbGllbnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQkMyh0aGlzLCBfTGF5b3V0TW9kdWxlX2xheW91dEluaXRpYWxpemF0aW9uQXR0ZW1wdGVkLCB0cnVlLCBcImZcIik7XG4gICAgICAgICAgICAvLyBUT0RPOiByZW5hbWUgdG8gY3JlYXRlTGF5b3V0TWFuYWdlclxuICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQzKHRoaXMsIF9MYXlvdXRNb2R1bGVfbGF5b3V0TWFuYWdlciwgYXdhaXQgdGhpcy53aXJlLmVudmlyb25tZW50LmluaXRMYXlvdXRNYW5hZ2VyKHRoaXMuZmluLCB0aGlzLndpcmUsIG9wdGlvbnMpLCBcImZcIik7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLndpcmUuZW52aXJvbm1lbnQuYXBwbHlMYXlvdXRTbmFwc2hvdCh0aGlzLmZpbiwgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQzKHRoaXMsIF9MYXlvdXRNb2R1bGVfbGF5b3V0TWFuYWdlciwgXCJmXCIpLCBvcHRpb25zKTtcbiAgICAgICAgICAgIGNvbnN0IG1lSWRlbnRpdHkgPSB7IG5hbWU6IHRoaXMuZmluLm1lLm5hbWUsIHV1aWQ6IHRoaXMuZmluLm1lLnV1aWQgfTtcbiAgICAgICAgICAgIGlmICghb3B0aW9ucy5sYXlvdXRNYW5hZ2VyT3ZlcnJpZGUpIHtcbiAgICAgICAgICAgICAgICAvLyBDT1JFLTEwODEgdG8gYmUgcmVtb3ZlZCB3aGVuIHdlIGFjdHVhbGx5IGRlbGV0ZSB0aGUgYGxheW91dE1hbmFnZXJgIHByb3BcbiAgICAgICAgICAgICAgICAvLyBpbiBzaW5nbGUtbGF5b3V0IGNhc2UsIHdlIHJldHVybiB0aGUgdW5kb2N1bWVudGVkIGxheW91dE1hbmFnZXIgdHlwZVxuICAgICAgICAgICAgICAgIGNvbnN0IGxheW91dElkZW50aXR5ID0geyBsYXlvdXROYW1lOiBsYXlvdXRfY29uc3RhbnRzXzEuREVGQVVMVF9MQVlPVVRfS0VZLCAuLi5tZUlkZW50aXR5IH07XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMyh0aGlzLCBfTGF5b3V0TW9kdWxlX2dldExheW91dE1hbmFnZXJTcHksIFwiZlwiKS5jYWxsKHRoaXMsIGxheW91dElkZW50aXR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLndyYXBTeW5jKG1lSWRlbnRpdHkpO1xuICAgICAgICB9O1xuICAgICAgICBfTGF5b3V0TW9kdWxlX2dldExheW91dE1hbmFnZXJTcHkuc2V0KHRoaXMsIChsYXlvdXRJZGVudGl0eSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgbXNnID0gJ1tMYXlvdXRdIFlvdSBhcmUgdXNpbmcgYSBkZXByZWNhdGVkIHByb3BlcnR5IGBsYXlvdXRNYW5hZ2VyYCAtIGl0IHdpbGwgdGhyb3cgaWYgeW91IGFjY2VzcyBpdCBzdGFydGluZyBpbiB2MzcuJztcbiAgICAgICAgICAgIGNvbnN0IG1hbmFnZXJQcm94eSA9IG5ldyBQcm94eSh7fSwge1xuICAgICAgICAgICAgICAgIGdldCh0YXJnZXQsIGtleSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFtMYXlvdXQtbWdyLXByb3h5XSBhY2Nlc3NpbmcgJHtrZXkudG9TdHJpbmcoKX1gKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBjb25zdCBsYXlvdXQgPSBPYmplY3QuYXNzaWduKHRoaXMud3JhcFN5bmMobGF5b3V0SWRlbnRpdHkpLCB7IGxheW91dE1hbmFnZXI6IG1hbmFnZXJQcm94eSB9KTtcbiAgICAgICAgICAgIGNvbnN0IGxheW91dFByb3h5ID0gbmV3IFByb3h5KGxheW91dCwge1xuICAgICAgICAgICAgICAgIGdldCh0YXJnZXQsIGtleSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ID09PSAnbGF5b3V0TWFuYWdlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgW0xheW91dC1wcm94eV0gYWNjZXNzaW5nICR7a2V5LnRvU3RyaW5nKCl9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGFyZ2V0W2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gbGF5b3V0UHJveHk7XG4gICAgICAgIH0pO1xuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyB0aGUgbGF5b3V0IG1hbmFnZXIgZm9yIHRoZSBjdXJyZW50IHdpbmRvd1xuICAgICAgICAgKiBAcmV0dXJuc1xuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5nZXRDdXJyZW50TGF5b3V0TWFuYWdlclN5bmMgPSAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gX19jbGFzc1ByaXZhdGVGaWVsZEdldCQzKHRoaXMsIF9MYXlvdXRNb2R1bGVfaW5zdGFuY2VzLCBcIm1cIiwgX0xheW91dE1vZHVsZV9nZXRTYWZlTGF5b3V0TWFuYWdlcikuY2FsbCh0aGlzLCBgZmluLlBsYXRmb3JtLkxheW91dC5nZXRDdXJyZW50TGF5b3V0TWFuYWdlclN5bmMoKWApO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNyZWF0ZSA9IGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy53aXJlLmVudmlyb25tZW50LmNyZWF0ZUxheW91dChfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDModGhpcywgX0xheW91dE1vZHVsZV9pbnN0YW5jZXMsIFwibVwiLCBfTGF5b3V0TW9kdWxlX2dldFNhZmVMYXlvdXRNYW5hZ2VyKS5jYWxsKHRoaXMsIGBmaW4uUGxhdGZvcm0uTGF5b3V0LmNyZWF0ZSgpYCksIG9wdGlvbnMpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmRlc3Ryb3kgPSBhc3luYyAobGF5b3V0SWRlbnRpdHkpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndpcmUuZW52aXJvbm1lbnQuZGVzdHJveUxheW91dChfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDModGhpcywgX0xheW91dE1vZHVsZV9pbnN0YW5jZXMsIFwibVwiLCBfTGF5b3V0TW9kdWxlX2dldFNhZmVMYXlvdXRNYW5hZ2VyKS5jYWxsKHRoaXMsIGBmaW4uUGxhdGZvcm0uTGF5b3V0LmRlc3Ryb3koKWApLCBsYXlvdXRJZGVudGl0eSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFzeW5jaHJvbm91c2x5IHJldHVybnMgYSBMYXlvdXQgb2JqZWN0IHRoYXQgcmVwcmVzZW50cyBhIFdpbmRvdydzIGxheW91dC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBsZXQgd2luZG93SWRlbnRpdHk7XG4gICAgICogaWYgKCFmaW4ubWUuaXNXaW5kb3cpIHtcbiAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSBmaW4ubWUuaWRlbnRpdHk7XG4gICAgICogfSBlbHNlIGlmIChmaW4ubWUuaXNWaWV3KSB7XG4gICAgICogICAgIHdpbmRvd0lkZW50aXR5ID0gKGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50V2luZG93KCkpLmlkZW50aXR5O1xuICAgICAqIH0gZWxzZSB7XG4gICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3IG9yIFdpbmRvdycpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGNvbnN0IGxheW91dCA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5MYXlvdXQud3JhcCh3aW5kb3dJZGVudGl0eSk7XG4gICAgICogLy8gVXNlIHdyYXBwZWQgaW5zdGFuY2UgdG8gY29udHJvbCBsYXlvdXQsIGUuZy46XG4gICAgICogY29uc3QgbGF5b3V0Q29uZmlnID0gYXdhaXQgbGF5b3V0LmdldENvbmZpZygpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHdyYXAoaWRlbnRpdHkpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2xheW91dC13cmFwJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnN0YW5jZV8xJDIuTGF5b3V0KGlkZW50aXR5LCB0aGlzLndpcmUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTeW5jaHJvbm91c2x5IHJldHVybnMgYSBMYXlvdXQgb2JqZWN0IHRoYXQgcmVwcmVzZW50cyBhIFdpbmRvdydzIGxheW91dC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBsZXQgd2luZG93SWRlbnRpdHk7XG4gICAgICogaWYgKCFmaW4ubWUuaXNXaW5kb3cpIHtcbiAgICAgKiAgICAgd2luZG93SWRlbnRpdHkgPSBmaW4ubWUuaWRlbnRpdHk7XG4gICAgICogfSBlbHNlIGlmIChmaW4ubWUuaXNWaWV3KSB7XG4gICAgICogICAgIHdpbmRvd0lkZW50aXR5ID0gKGF3YWl0IGZpbi5tZS5nZXRDdXJyZW50V2luZG93KCkpLmlkZW50aXR5O1xuICAgICAqIH0gZWxzZSB7XG4gICAgICogICAgIHRocm93IG5ldyBFcnJvcignTm90IHJ1bm5pbmcgaW4gYSBwbGF0Zm9ybSBWaWV3IG9yIFdpbmRvdycpO1xuICAgICAqIH1cbiAgICAgKlxuICAgICAqIGNvbnN0IGxheW91dCA9IGZpbi5QbGF0Zm9ybS5MYXlvdXQud3JhcFN5bmMod2luZG93SWRlbnRpdHkpO1xuICAgICAqIC8vIFVzZSB3cmFwcGVkIGluc3RhbmNlIHRvIGNvbnRyb2wgbGF5b3V0LCBlLmcuOlxuICAgICAqIGNvbnN0IGxheW91dENvbmZpZyA9IGF3YWl0IGxheW91dC5nZXRDb25maWcoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICB3cmFwU3luYyhpZGVudGl0eSkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignbGF5b3V0LXdyYXAtc3luYycpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMSQyLkxheW91dChpZGVudGl0eSwgdGhpcy53aXJlKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhIExheW91dCBvYmplY3QgdGhhdCByZXByZXNlbnRzIGEgV2luZG93J3MgbGF5b3V0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IGxheW91dCA9IGF3YWl0IGZpbi5QbGF0Zm9ybS5MYXlvdXQuZ2V0Q3VycmVudCgpO1xuICAgICAqIC8vIFVzZSB3cmFwcGVkIGluc3RhbmNlIHRvIGNvbnRyb2wgbGF5b3V0LCBlLmcuOlxuICAgICAqIGNvbnN0IGxheW91dENvbmZpZyA9IGF3YWl0IGxheW91dC5nZXRDb25maWcoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBnZXRDdXJyZW50KCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignbGF5b3V0LWdldC1jdXJyZW50JykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCF0aGlzLmZpbi5tZS5pc1dpbmRvdykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgYXJlIG5vdCBpbiBhIFdpbmRvdyBjb250ZXh0LiAgT25seSBXaW5kb3dzIGNhbiBoYXZlIGEgTGF5b3V0LicpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgdXVpZCwgbmFtZSB9ID0gdGhpcy5maW4ubWU7XG4gICAgICAgIHJldHVybiB0aGlzLndyYXAoeyB1dWlkLCBuYW1lIH0pO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTeW5jaHJvbm91c2x5IHJldHVybnMgYSBMYXlvdXQgb2JqZWN0IHRoYXQgcmVwcmVzZW50cyBhIFdpbmRvdydzIGxheW91dC5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIENhbm5vdCBiZSBjYWxsZWQgZnJvbSBhIHZpZXcuXG4gICAgICpcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBsYXlvdXQgPSBmaW4uUGxhdGZvcm0uTGF5b3V0LmdldEN1cnJlbnRTeW5jKCk7XG4gICAgICogLy8gVXNlIHdyYXBwZWQgaW5zdGFuY2UgdG8gY29udHJvbCBsYXlvdXQsIGUuZy46XG4gICAgICogY29uc3QgbGF5b3V0Q29uZmlnID0gYXdhaXQgbGF5b3V0LmdldENvbmZpZygpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGdldEN1cnJlbnRTeW5jKCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignbGF5b3V0LWdldC1jdXJyZW50LXN5bmMnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoIXRoaXMuZmluLm1lLmlzV2luZG93KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBhcmUgbm90IGluIGEgV2luZG93IGNvbnRleHQuICBPbmx5IFdpbmRvd3MgY2FuIGhhdmUgYSBMYXlvdXQuJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSB0aGlzLmZpbi5tZTtcbiAgICAgICAgcmV0dXJuIHRoaXMud3JhcFN5bmMoeyB1dWlkLCBuYW1lIH0pO1xuICAgIH1cbn1cbkZhY3RvcnkkMi5MYXlvdXRNb2R1bGUgPSBMYXlvdXRNb2R1bGU7XG5fTGF5b3V0TW9kdWxlX2xheW91dEluaXRpYWxpemF0aW9uQXR0ZW1wdGVkID0gbmV3IFdlYWtNYXAoKSwgX0xheW91dE1vZHVsZV9sYXlvdXRNYW5hZ2VyID0gbmV3IFdlYWtNYXAoKSwgX0xheW91dE1vZHVsZV9nZXRMYXlvdXRNYW5hZ2VyU3B5ID0gbmV3IFdlYWtNYXAoKSwgX0xheW91dE1vZHVsZV9pbnN0YW5jZXMgPSBuZXcgV2Vha1NldCgpLCBfTGF5b3V0TW9kdWxlX2dldFNhZmVMYXlvdXRNYW5hZ2VyID0gZnVuY3Rpb24gX0xheW91dE1vZHVsZV9nZXRTYWZlTGF5b3V0TWFuYWdlcihtZXRob2QpIHtcbiAgICBpZiAoIV9fY2xhc3NQcml2YXRlRmllbGRHZXQkMyh0aGlzLCBfTGF5b3V0TW9kdWxlX2xheW91dE1hbmFnZXIsIFwiZlwiKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFlvdSBtdXN0IGNhbGwgaW5pdCBiZWZvcmUgdXNpbmcgdGhlIEFQSSAke21ldGhvZH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMyh0aGlzLCBfTGF5b3V0TW9kdWxlX2xheW91dE1hbmFnZXIsIFwiZlwiKTtcbn07XG5cbihmdW5jdGlvbiAoZXhwb3J0cykge1xuXHQvKipcblx0ICogRW50cnkgcG9pbnQgZm9yIHRoZSBPcGVuRmluIGBMYXlvdXRgIHN1YnNldCBvZiB0aGUgYFBsYXRmb3JtYCBBUEkgKGBmaW4uUGxhdGZvcm0uTGF5b3V0YCkuXG5cdCAqXG5cdCAqICoge0BsaW5rIExheW91dE1vZHVsZX0gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBMYXlvdXRgIEFQSSwgYWNjZXNzaWJsZSB0aHJvdWdoIGBmaW4uUGxhdGZvcm0uTGF5b3V0YC5cblx0ICogKiB7QGxpbmsgTGF5b3V0fSBkZXNjcmliZXMgYW4gaW5zdGFuY2Ugb2YgYW4gT3BlbkZpbiBMYXlvdXQsIGUuZy4gYXMgcmV0dXJuZWQgYnkgYGZpbi5QbGF0Zm9ybS5MYXlvdXQuZ2V0Q3VycmVudGAuXG5cdCAqXG5cdCAqIFRoZXNlIGFyZSBzZXBhcmF0ZSBjb2RlIGVudGl0aWVzLCBhbmQgYXJlIGRvY3VtZW50ZWQgc2VwYXJhdGVseS4gSW4gdGhlIFtwcmV2aW91cyB2ZXJzaW9uIG9mIHRoZSBBUEkgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvMzIuMTE0Ljc2LjEwL2luZGV4Lmh0bWwpLFxuXHQgKiBib3RoIG9mIHRoZXNlIHdlcmUgZG9jdW1lbnRlZCBvbiB0aGUgc2FtZSBwYWdlLlxuXHQgKlxuXHQgKiBAcGFja2FnZURvY3VtZW50YXRpb25cblx0ICpcblx0ICovXG5cdHZhciBfX2NyZWF0ZUJpbmRpbmcgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcblx0ICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XG5cdCAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XG5cdCAgICB9XG5cdCAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xuXHR9KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIG9bazJdID0gbVtrXTtcblx0fSkpO1xuXHR2YXIgX19leHBvcnRTdGFyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fZXhwb3J0U3RhcikgfHwgZnVuY3Rpb24obSwgZXhwb3J0cykge1xuXHQgICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChleHBvcnRzLCBwKSkgX19jcmVhdGVCaW5kaW5nKGV4cG9ydHMsIG0sIHApO1xuXHR9O1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdF9fZXhwb3J0U3RhcihGYWN0b3J5JDIsIGV4cG9ydHMpO1xuXHRfX2V4cG9ydFN0YXIoSW5zdGFuY2UkMSwgZXhwb3J0cyk7IFxufSAobGF5b3V0KSk7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShGYWN0b3J5JDMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuRmFjdG9yeSQzLlBsYXRmb3JtTW9kdWxlID0gdm9pZCAwO1xuY29uc3QgYmFzZV8xJDMgPSBiYXNlO1xuY29uc3QgSW5zdGFuY2VfMSQxID0gSW5zdGFuY2UkMjtcbmNvbnN0IGluZGV4XzEkMSA9IGxheW91dDtcbi8qKlxuICogU3RhdGljIG5hbWVzcGFjZSBmb3IgT3BlbkZpbiBBUEkgbWV0aG9kcyB0aGF0IGludGVyYWN0IHdpdGggdGhlIHtAbGluayBQbGF0Zm9ybX0gY2xhc3MsIGF2YWlsYWJsZSB1bmRlciBgZmluLlBsYXRmb3JtYC5cbiAqL1xuY2xhc3MgUGxhdGZvcm1Nb2R1bGUgZXh0ZW5kcyBiYXNlXzEkMy5CYXNlIHtcbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih3aXJlLCBjaGFubmVsKSB7XG4gICAgICAgIHN1cGVyKHdpcmUpO1xuICAgICAgICB0aGlzLl9jaGFubmVsID0gY2hhbm5lbDtcbiAgICAgICAgLyoqXG4gICAgICAgICAqXG4gICAgICAgICAqIEBkZXNjIExheW91dHMgZ2l2ZSBhcHAgcHJvdmlkZXJzIHRoZSBhYmlsaXR5IHRvIGVtYmVkIG11bHRpcGxlIHZpZXdzIGluIGEgc2luZ2xlIHdpbmRvdy4gIFRoZSBMYXlvdXQgbmFtZXNwYWNlXG4gICAgICAgICAqIGVuYWJsZXMgdGhlIGluaXRpYWxpemF0aW9uIGFuZCBtYW5pcHVsYXRpb24gb2YgYSB3aW5kb3cncyBMYXlvdXQuICBBIExheW91dCB3aWxsXG4gICAgICAgICAqIDxhIGhyZWY9XCJ0dXRvcmlhbC1MYXlvdXQuRE9NRXZlbnRzLmh0bWxcIj5lbWl0IGV2ZW50cyBsb2NhbGx5PC9hPiBvbiB0aGUgRE9NIGVsZW1lbnQgcmVwcmVzZW50aW5nIHRoZSBsYXlvdXQtY29udGFpbmVyLlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy5MYXlvdXQgPSBuZXcgaW5kZXhfMSQxLkxheW91dE1vZHVsZSh0aGlzLndpcmUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyBhIFBsYXRmb3JtLiBNdXN0IGJlIGNhbGxlZCBmcm9tIHRoZSBQcm92aWRlciB3aGVuIHVzaW5nIGEgY3VzdG9tIHByb3ZpZGVyLlxuICAgICAqIEBwYXJhbSBvcHRpb25zIC0gcGxhdGZvcm0gb3B0aW9ucyBpbmNsdWRpbmcgYSBjYWxsYmFjayBmdW5jdGlvbiB0aGF0IGNhbiBiZSB1c2VkIHRvIGV4dGVuZCBvciByZXBsYWNlXG4gICAgICogZGVmYXVsdCBQcm92aWRlciBiZWhhdmlvci5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzIE11c3QgYmUgY2FsbGVkIGZyb20gdGhlIFByb3ZpZGVyIHdoZW4gdXNpbmcgYSBjdXN0b20gcHJvdmlkZXIuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiAvLyBGcm9tIFByb3ZpZGVyIGNvbnRleHRcbiAgICAgKiBhd2FpdCBmaW4uUGxhdGZvcm0uaW5pdCgpO1xuICAgICAqIC8vIFBsYXRmb3JtIEFQSSBpcyBub3cgaG9va2VkIHVwIGFuZCB3aW5kb3dzIGNvbnRhaW5lZCBpbiB0aGUgbWFuaWZlc3Qgc25hcHNob3QgYXJlIG9wZW4uXG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBgUGxhdGZvcm0uaW5pdGAgYWNjZXB0cyBhbiBvcHRpb25zIG9iamVjdCB0aGF0IGNhbiBjb250YWluIGEgY2FsbGJhY2sgZnVuY3Rpb24gd2hpY2ggY2FuIGJlIHVzZWQgdG8gZXh0ZW5kIG9yXG4gICAgICogcmVwbGFjZSBkZWZhdWx0IFByb3ZpZGVyIGJlaGF2aW9yLiBBcyBhbiBhcmd1bWVudCwgdGhpcyBmdW5jdGlvbiB3aWxsIHJlY2VpdmUgdGhlIGBQcm92aWRlcmAgY2xhc3MsIHdoaWNoIGlzXG4gICAgICogdXNlZCB0byBoYW5kbGUgUGxhdGZvcm0gYWN0aW9ucy4gVGhlIGZ1bmN0aW9uIG11c3QgcmV0dXJuIGFuIG9iamVjdCB3aXRoIG1ldGhvZHMgdG8gaGFuZGxlIFBsYXRmb3JtIEFQSSBhY3Rpb25zLlxuICAgICAqIFRoZSByZWNvbW1lbmRlZCBhcHByb2FjaCBpcyB0byBleHRlbmQgdGhlIGBQcm92aWRlcmAgY2xhc3MsIG92ZXJyaWRpbmcgdGhlIG1ldGhvZHMgeW91IHdpc2ggdG8gYWx0ZXIsIGFuZCByZXR1cm4gYW5cbiAgICAgKiBpbnN0YW5jZSBvZiB5b3VyIHN1YmNsYXNzOlxuICAgICAqXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCBvdmVycmlkZUNhbGxiYWNrID0gYXN5bmMgKFBsYXRmb3JtUHJvdmlkZXIpID0+IHtcbiAgICAgKiAgICAgLy8gQWN0aW9ucyBjYW4gYmUgcGVyZm9ybWVkIGJlZm9yZSBpbml0aWFsaXphdGlvbi5cbiAgICAgKiAgICAgLy8gZS5nLiB3ZSBtaWdodCBhdXRoZW50aWNhdGUgYSB1c2VyLCBzZXQgdXAgYSBDaGFubmVsLCBldGMgYmVmb3JlIGluaXRpYWxpemluZyB0aGUgUGxhdGZvcm0uXG4gICAgICogICAgIGNvbnN0IHsgbWFuaWZlc3RVcmwgfSA9IGF3YWl0IGZpbi5BcHBsaWNhdGlvbi5nZXRDdXJyZW50U3luYygpLmdldEluZm8oKTtcbiAgICAgKlxuICAgICAqICAgICAvLyBFeHRlbmQgb3IgcmVwbGFjZSBkZWZhdWx0IFBsYXRmb3JtUHJvdmlkZXIgYmVoYXZpb3IgYnkgZXh0ZW5kaW5nIHRoZSBQbGF0Zm9ybVByb3ZpZGVyIGNsYXNzLlxuICAgICAqICAgICBjbGFzcyBNeU92ZXJyaWRlIGV4dGVuZHMgUGxhdGZvcm1Qcm92aWRlciB7XG4gICAgICogICAgICAgICAvLyBEZWZhdWx0IGJlaGF2aW9yIGNhbiBiZSBjaGFuZ2VkIGJ5IGltcGxlbWVudGluZyBtZXRob2RzIHdpdGggdGhlIHNhbWUgbmFtZXMgYXMgdGhvc2UgdXNlZCBieSB0aGUgZGVmYXVsdCBQbGF0Zm9ybVByb3ZpZGVyLlxuICAgICAqICAgICAgICAgYXN5bmMgZ2V0U25hcHNob3QoKSB7XG4gICAgICogICAgICAgICAgICAgLy8gU2luY2Ugd2UgYXJlIGV4dGVuZGluZyB0aGUgY2xhc3MsIHdlIGNhbiBjYWxsIGBzdXBlcmAgbWV0aG9kcyB0byBhY2Nlc3MgZGVmYXVsdCBiZWhhdmlvci5cbiAgICAgKiAgICAgICAgICAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHN1cGVyLmdldFNuYXBzaG90KCk7XG4gICAgICogICAgICAgICAgICAgLy8gQnV0IHdlIGNhbiBtb2RpZnkgcmV0dXJuIHZhbHVlcy5cbiAgICAgKiAgICAgICAgICAgICByZXR1cm4geyAuLi5zbmFwc2hvdCwgYW5zd2VyOiA0MiwgbWFuaWZlc3RVcmwgfTtcbiAgICAgKiAgICAgICAgIH1cbiAgICAgKiAgICAgICAgIGFzeW5jIHJlcGxhY2VMYXlvdXQoeyBvcHRzLCB0YXJnZXQgfSkge1xuICAgICAqICAgICAgICAgICAgIC8vIFRvIGRpc2FibGUgYW4gQVBJIG1ldGhvZCwgb3ZlcndyaXRlIHdpdGggYSBub29wIGZ1bmN0aW9uLlxuICAgICAqICAgICAgICAgICAgIHJldHVybjtcbiAgICAgKiAgICAgICAgIH1cbiAgICAgKiAgICAgfVxuICAgICAqICAgICAvLyBSZXR1cm4gaW5zdGFuY2Ugd2l0aCBtZXRob2RzIHRvIGJlIGNvbnN1bWVkIGJ5IFBsYXRmb3JtLlxuICAgICAqICAgICAvLyBUaGUgcmV0dXJuZWQgb2JqZWN0IG11c3QgaW1wbGVtZW50IGFsbCBtZXRob2RzIG9mIHRoZSBQbGF0Zm9ybVByb3ZpZGVyIGNsYXNzLlxuICAgICAqICAgICAvLyBCeSBleHRlbmRpbmcgdGhlIGNsYXNzLCB3ZSBjYW4gc2ltcGx5IGluaGVyaXQgbWV0aG9kcyB3ZSBkbyBub3Qgd2lzaCB0byBhbHRlci5cbiAgICAgKiAgICAgcmV0dXJuIG5ldyBNeU92ZXJyaWRlKCk7XG4gICAgICogfTtcbiAgICAgKlxuICAgICAqIGZpbi5QbGF0Zm9ybS5pbml0KHtvdmVycmlkZUNhbGxiYWNrfSk7XG4gICAgICogYGBgXG4gICAgICogQGV4cGVyaW1lbnRhbFxuICAgICAqL1xuICAgIGFzeW5jIGluaXQob3B0aW9ucykge1xuICAgICAgICBpZiAoIWZpbi5fX2ludGVybmFsXy5pc1BsYXRmb3JtIHx8IGZpbi5tZS5uYW1lICE9PSBmaW4ubWUudXVpZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdmaW4uUGxhdGZvcm0uaW5pdCBzaG91bGQgb25seSBiZSBjYWxsZWQgZnJvbSBhIGN1c3RvbSBwbGF0Zm9ybSBwcm92aWRlciBydW5uaW5nIGluIHRoZSBtYWluIHdpbmRvdyBvZiB0aGUgYXBwbGljYXRpb24uJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5lbnZpcm9ubWVudC5pbml0UGxhdGZvcm0odGhpcy5maW4sIG9wdGlvbnMpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBBc3luY2hyb25vdXNseSByZXR1cm5zIGEgUGxhdGZvcm0gb2JqZWN0IHRoYXQgcmVwcmVzZW50cyBhbiBleGlzdGluZyBwbGF0Zm9ybS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBjb25zdCB7IGlkZW50aXR5IH0gPSBmaW4ubWU7XG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0ud3JhcChpZGVudGl0eSk7XG4gICAgICogLy8gVXNlIHdyYXBwZWQgaW5zdGFuY2UgdG8gY29udHJvbCBsYXlvdXQsIGUuZy46XG4gICAgICogY29uc3Qgc25hcHNob3QgPSBhd2FpdCBwbGF0Zm9ybS5nZXRTbmFwc2hvdCgpO1xuICAgICAqIGBgYFxuICAgICAqL1xuICAgIGFzeW5jIHdyYXAoaWRlbnRpdHkpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLXdyYXAnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbmV3IEluc3RhbmNlXzEkMS5QbGF0Zm9ybSh7IHV1aWQ6IGlkZW50aXR5LnV1aWQgfSwgdGhpcy5fY2hhbm5lbCk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN5bmNocm9ub3VzbHkgcmV0dXJucyBhIFBsYXRmb3JtIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgYW4gZXhpc3RpbmcgcGxhdGZvcm0uXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgeyBpZGVudGl0eSB9ID0gZmluLm1lO1xuICAgICAqIGNvbnN0IHBsYXRmb3JtID0gZmluLlBsYXRmb3JtLndyYXBTeW5jKGlkZW50aXR5KTtcbiAgICAgKiAvLyBVc2Ugd3JhcHBlZCBpbnN0YW5jZSB0byBjb250cm9sIGxheW91dCwgZS5nLjpcbiAgICAgKiBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHBsYXRmb3JtLmdldFNuYXBzaG90KCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgd3JhcFN5bmMoaWRlbnRpdHkpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLXdyYXAtc3luYycpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2VcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBuZXcgSW5zdGFuY2VfMSQxLlBsYXRmb3JtKHsgdXVpZDogaWRlbnRpdHkudXVpZCB9LCB0aGlzLl9jaGFubmVsKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQXN5bmNocm9ub3VzbHkgcmV0dXJucyBhIFBsYXRmb3JtIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIGN1cnJlbnQgcGxhdGZvcm0uXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudCgpO1xuICAgICAqIC8vIFVzZSB3cmFwcGVkIGluc3RhbmNlIHRvIGNvbnRyb2wgbGF5b3V0LCBlLmcuOlxuICAgICAqIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgcGxhdGZvcm0uZ2V0U25hcHNob3QoKTtcbiAgICAgKiBgYGBcbiAgICAgKi9cbiAgICBhc3luYyBnZXRDdXJyZW50KCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tZ2V0LWN1cnJlbnQnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcy53cmFwKHsgdXVpZDogdGhpcy53aXJlLm1lLnV1aWQgfSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN5bmNocm9ub3VzbHkgcmV0dXJucyBhIFBsYXRmb3JtIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIGN1cnJlbnQgcGxhdGZvcm0uXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcbiAgICAgKiAvLyBVc2Ugd3JhcHBlZCBpbnN0YW5jZSB0byBjb250cm9sIGxheW91dCwgZS5nLjpcbiAgICAgKiBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHBsYXRmb3JtLmdldFNuYXBzaG90KCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgZ2V0Q3VycmVudFN5bmMoKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdwbGF0Zm9ybS1nZXQtY3VycmVudC1zeW5jJykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXMud3JhcFN5bmMoeyB1dWlkOiB0aGlzLndpcmUubWUudXVpZCB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbmQgc3RhcnRzIGEgUGxhdGZvcm0gYW5kIHJldHVybnMgYSB3cmFwcGVkIGFuZCBydW5uaW5nIFBsYXRmb3JtIGluc3RhbmNlLiBUaGUgd3JhcHBlZCBQbGF0Zm9ybSBtZXRob2RzIGNhblxuICAgICAqIGJlIHVzZWQgdG8gbGF1bmNoIGNvbnRlbnQgaW50byB0aGUgcGxhdGZvcm0uICBQcm9taXNlIHdpbGwgcmVqZWN0IGlmIHRoZSBwbGF0Zm9ybSBpcyBhbHJlYWR5IHJ1bm5pbmcuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogdHJ5IHtcbiAgICAgKiAgICAgY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0uc3RhcnQoe1xuICAgICAqICAgICAgICAgdXVpZDogJ3BsYXRmb3JtLTEnLFxuICAgICAqICAgICAgICAgYXV0b1Nob3c6IGZhbHNlLFxuICAgICAqICAgICAgICAgZGVmYXVsdFdpbmRvd09wdGlvbnM6IHtcbiAgICAgKiAgICAgICAgICAgICBzdHlsZXNoZWV0VXJsOiAnY3NzLXNoZWV0LXVybCcsXG4gICAgICogICAgICAgICAgICAgY29ybmVyUm91bmRpbmc6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMCxcbiAgICAgKiAgICAgICAgICAgICAgICAgd2lkdGg6IDEwXG4gICAgICogICAgICAgICAgICAgfVxuICAgICAqICAgICAgICAgfVxuICAgICAqICAgICB9KTtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ1BsYXRmb3JtIGlzIHJ1bm5pbmcnLCBwbGF0Zm9ybSk7XG4gICAgICogfSBjYXRjaChlKSB7XG4gICAgICogICAgIGNvbnNvbGUuZXJyb3IoZSk7XG4gICAgICogfVxuICAgICAqIGBgYFxuICAgICAqL1xuICAgIHN0YXJ0KHBsYXRmb3JtT3B0aW9ucykge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbigncGxhdGZvcm0tc3RhcnQnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYXN5bmMtcHJvbWlzZS1leGVjdXRvclxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCB7IHV1aWQgfSA9IHBsYXRmb3JtT3B0aW9ucztcbiAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHVzaW5nIHByaXZhdGUgdmFyaWFibGUuXG4gICAgICAgICAgICAgICAgY29uc3QgYXBwID0gYXdhaXQgdGhpcy5maW4uQXBwbGljYXRpb24uX2NyZWF0ZSh7IC4uLnBsYXRmb3JtT3B0aW9ucywgaXNQbGF0Zm9ybUNvbnRyb2xsZXI6IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogZml4IHR5cGluZyAoaW50ZXJuYWwpXG4gICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgICAgIGFwcC5vbmNlKCdwbGF0Zm9ybS1hcGktcmVhZHknLCAoKSA9PiByZXNvbHZlKHRoaXMud3JhcFN5bmMoeyB1dWlkIH0pKSk7XG4gICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciB1c2luZyBwcml2YXRlIHZhcmlhYmxlLlxuICAgICAgICAgICAgICAgIGFwcC5fcnVuKHsgdXVpZCB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0cmlldmVzIHBsYXRmb3JtcydzIG1hbmlmZXN0IGFuZCByZXR1cm5zIGEgd3JhcHBlZCBhbmQgcnVubmluZyBQbGF0Zm9ybS4gIElmIHRoZXJlIGlzIGEgc25hcHNob3QgaW4gdGhlIG1hbmlmZXN0LFxuICAgICAqIGl0IHdpbGwgYmUgbGF1bmNoZWQgaW50byB0aGUgcGxhdGZvcm0uXG4gICAgICogQHBhcmFtIG1hbmlmZXN0VXJsIC0gVGhlIFVSTCBvZiBwbGF0Zm9ybSdzIG1hbmlmZXN0LlxuICAgICAqIEBwYXJhbSBvcHRzIC0gUGFyYW1ldGVycyB0aGF0IHRoZSBSVk0gd2lsbCB1c2UuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogdHJ5IHtcbiAgICAgKiAgICAgY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBmaW4uUGxhdGZvcm0uc3RhcnRGcm9tTWFuaWZlc3QoJ2h0dHBzOi8vb3BlbmZpbi5naXRodWIuaW8vZ29sZGVuLXByb3RvdHlwZS9wdWJsaWMuanNvbicpO1xuICAgICAqICAgICBjb25zb2xlLmxvZygnUGxhdGZvcm0gaXMgcnVubmluZywgd3JhcHBlZCBwbGF0Zm9ybTogJywgcGxhdGZvcm0pO1xuICAgICAqIH0gY2F0Y2goZSkge1xuICAgICAqICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAqIH1cbiAgICAgKiAvLyBGb3IgYSBsb2NhbCBtYW5pZmVzdCBmaWxlOlxuICAgICAqIHRyeSB7XG4gICAgICogICAgIGNvbnN0IHBsYXRmb3JtID0gYXdhaXQgZmluLlBsYXRmb3JtLnN0YXJ0RnJvbU1hbmlmZXN0KCdmaWxlOi8vL0M6L3NvbWVmb2xkZXIvYXBwLmpzb24nKTtcbiAgICAgKiAgICAgY29uc29sZS5sb2coJ1BsYXRmb3JtIGlzIHJ1bm5pbmcsIHdyYXBwZWQgcGxhdGZvcm06ICcsIHBsYXRmb3JtKTtcbiAgICAgKiB9IGNhdGNoKGUpIHtcbiAgICAgKiAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgc3RhcnRGcm9tTWFuaWZlc3QobWFuaWZlc3RVcmwsIG9wdHMpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3BsYXRmb3JtLXN0YXJ0LWZyb20tbWFuaWZlc3QnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlXG4gICAgICAgIH0pO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYXN5bmMtcHJvbWlzZS1leGVjdXRvclxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHVzaW5nIHByaXZhdGUgdmFyaWFibGUuXG4gICAgICAgICAgICAgICAgY29uc3QgYXBwID0gYXdhaXQgdGhpcy5maW4uQXBwbGljYXRpb24uX2NyZWF0ZUZyb21NYW5pZmVzdChtYW5pZmVzdFVybCk7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogZml4IHR5cGluZyAoaW50ZXJuYWwpXG4gICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgICAgIGFwcC5vbmNlKCdwbGF0Zm9ybS1hcGktcmVhZHknLCAoKSA9PiByZXNvbHZlKHRoaXMud3JhcFN5bmMoeyB1dWlkOiBhcHAuaWRlbnRpdHkudXVpZCB9KSkpO1xuICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgdXNpbmcgcHJpdmF0ZSBtZXRob2Qgd2l0aG91dCB3YXJuaW5nLlxuICAgICAgICAgICAgICAgIGFwcC5fcnVuKG9wdHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbkZhY3RvcnkkMy5QbGF0Zm9ybU1vZHVsZSA9IFBsYXRmb3JtTW9kdWxlO1xuXG4oZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0dmFyIF9fY3JlYXRlQmluZGluZyA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NyZWF0ZUJpbmRpbmcpIHx8IChPYmplY3QuY3JlYXRlID8gKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgdmFyIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG0sIGspO1xuXHQgICAgaWYgKCFkZXNjIHx8IChcImdldFwiIGluIGRlc2MgPyAhbS5fX2VzTW9kdWxlIDogZGVzYy53cml0YWJsZSB8fCBkZXNjLmNvbmZpZ3VyYWJsZSkpIHtcblx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0ICAgIH1cblx0ICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG5cdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHQgICAgb1trMl0gPSBtW2tdO1xuXHR9KSk7XG5cdHZhciBfX2V4cG9ydFN0YXIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19leHBvcnRTdGFyKSB8fCBmdW5jdGlvbihtLCBleHBvcnRzKSB7XG5cdCAgICBmb3IgKHZhciBwIGluIG0pIGlmIChwICE9PSBcImRlZmF1bHRcIiAmJiAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGV4cG9ydHMsIHApKSBfX2NyZWF0ZUJpbmRpbmcoZXhwb3J0cywgbSwgcCk7XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0LyoqXG5cdCAqIEVudHJ5IHBvaW50cyBmb3IgdGhlIE9wZW5GaW4gYFBsYXRmb3JtYCBBUEkgKGBmaW4uUGxhdGZvcm1gKVxuXHQgKlxuXHQgKiAqIHtAbGluayBQbGF0Zm9ybU1vZHVsZX0gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBQbGF0Zm9ybWAgQVBJLCBhY2Nlc3NpYmxlIHRocm91Z2ggYGZpbi5QbGF0Zm9ybWAuXG5cdCAqICoge0BsaW5rIFBsYXRmb3JtfSBkZXNjcmliZXMgYW4gaW5zdGFuY2Ugb2YgYW4gT3BlbkZpbiBQbGF0Zm9ybSwgZS5nLiBhcyByZXR1cm5lZCBieSBgZmluLlBsYXRmb3JtLmdldEN1cnJlbnRgLlxuXHQgKlxuXHQgKiBUaGVzZSBhcmUgc2VwYXJhdGUgY29kZSBlbnRpdGllcywgYW5kIGFyZSBkb2N1bWVudGVkIHNlcGFyYXRlbHkuICBJbiB0aGUgW3ByZXZpb3VzIHZlcnNpb24gb2YgdGhlIEFQSSBkb2N1bWVudGF0aW9uXShodHRwczovL2Nkbi5vcGVuZmluLmNvL2RvY3MvamF2YXNjcmlwdC8zMi4xMTQuNzYuMTAvaW5kZXguaHRtbCksXG5cdCAqIGJvdGggb2YgdGhlc2Ugd2VyZSBkb2N1bWVudGVkIG9uIHRoZSBzYW1lIHBhZ2UuXG5cdCAqXG5cdCAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuXHQgKi9cblx0X19leHBvcnRTdGFyKEZhY3RvcnkkMywgZXhwb3J0cyk7XG5cdF9fZXhwb3J0U3RhcihJbnN0YW5jZSQyLCBleHBvcnRzKTsgXG59IChwbGF0Zm9ybSkpO1xuXG52YXIgbWUgPSB7fTtcblxuKGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0ZXhwb3J0cy5nZXRNZSA9IGV4cG9ydHMuZ2V0QmFzZU1lID0gZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSA9IHZvaWQgMDtcblx0Y29uc3Qgdmlld18xID0gcmVxdWlyZVZpZXcoKTtcblx0Y29uc3QgZnJhbWVfMSA9IGZyYW1lO1xuXHRjb25zdCB3aW5kb3dfMSA9IHJlcXVpcmVXaW5kb3coKTtcblx0Y29uc3QgZXh0ZXJuYWxfYXBwbGljYXRpb25fMSA9IGV4dGVybmFsQXBwbGljYXRpb247XG5cdGV4cG9ydHMuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UgPSAnWW91IGFyZSBub3QgcnVubmluZyBpbiBPcGVuRmluLic7XG5cdGZ1bmN0aW9uIGdldEJhc2VNZShlbnRpdHlUeXBlLCB1dWlkLCBuYW1lKSB7XG5cdCAgICBjb25zdCBlbnRpdHlUeXBlSGVscGVycyA9IHtcblx0ICAgICAgICBpc1ZpZXc6IGVudGl0eVR5cGUgPT09ICd2aWV3Jyxcblx0ICAgICAgICBpc1dpbmRvdzogZW50aXR5VHlwZSA9PT0gJ3dpbmRvdycsXG5cdCAgICAgICAgaXNGcmFtZTogZW50aXR5VHlwZSA9PT0gJ2lmcmFtZScsXG5cdCAgICAgICAgaXNFeHRlcm5hbDogZW50aXR5VHlwZSA9PT0gJ2V4dGVybmFsIGNvbm5lY3Rpb24nXG5cdCAgICB9O1xuXHQgICAgcmV0dXJuIHsgLi4uZW50aXR5VHlwZUhlbHBlcnMsIHV1aWQsIG5hbWUsIGVudGl0eVR5cGUgfTtcblx0fVxuXHRleHBvcnRzLmdldEJhc2VNZSA9IGdldEJhc2VNZTtcblx0Ly8gV2UgbmVlZCB0byBkbyBhIGxvdCBvZiBjYXN0aW5nIGFzIHVua25vd24gaGVyZSBiZWNhdXNlIHRoZSBjb21waWxlciBnZXQncyBjb25mdXNlZCBhYm91dCBtYXRjaGluZyB0eXBlcy4gV2hhdCBtYXR0ZXJzIGlzIHRoYXQgaXQgd29ya3Mgb24gdGhlIG91dHNpZGVcblx0ZnVuY3Rpb24gZ2V0TWUod2lyZSkge1xuXHQgICAgY29uc3QgeyB1dWlkLCBuYW1lLCBlbnRpdHlUeXBlIH0gPSB3aXJlLm1lO1xuXHQgICAgY29uc3QgdW5zdXBwb3J0ZWRJbnRlcm9wID0ge1xuXHQgICAgICAgIHNldENvbnRleHQoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGFkZENvbnRleHRIYW5kbGVyKCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBnZXRDb250ZXh0R3JvdXBzKCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBqb2luQ29udGV4dEdyb3VwKCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICByZW1vdmVGcm9tQ29udGV4dEdyb3VwKCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBnZXRBbGxDbGllbnRzSW5Db250ZXh0R3JvdXAoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGdldEluZm9Gb3JDb250ZXh0R3JvdXAoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXHQgICAgY29uc3QgZmFsbGJhY2tFcnJvck1lc3NhZ2UgPSAnSW50ZXJvcCBBUEkgaGFzIG5vdCBiZWVuIGluc3RhbnRpYXRlZC4gRWl0aGVyIGNvbm5lY3Rpb24gaGFzIGZhaWxlZCBvciB5b3UgaGF2ZSBub3QgZGVjbGFyZWQgaW50ZXJvcCBpbiB5b3VyIGNvbmZpZy4nO1xuXHQgICAgY29uc3QgZmFsbGJhY2tJbnRlcm9wID0ge1xuXHQgICAgICAgIHNldENvbnRleHQoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihmYWxsYmFja0Vycm9yTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBhZGRDb250ZXh0SGFuZGxlcigpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGZhbGxiYWNrRXJyb3JNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGdldENvbnRleHRHcm91cHMoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihmYWxsYmFja0Vycm9yTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBqb2luQ29udGV4dEdyb3VwKCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZmFsbGJhY2tFcnJvck1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgcmVtb3ZlRnJvbUNvbnRleHRHcm91cCgpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGZhbGxiYWNrRXJyb3JNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGdldEFsbENsaWVudHNJbkNvbnRleHRHcm91cCgpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGZhbGxiYWNrRXJyb3JNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGdldEluZm9Gb3JDb250ZXh0R3JvdXAoKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihmYWxsYmFja0Vycm9yTWVzc2FnZSk7XG5cdCAgICAgICAgfVxuXHQgICAgfTtcblx0ICAgIGNvbnN0IHVuc3VwcG9ydGVkRXZlbnRCYXNlID0ge1xuXHQgICAgICAgIGV2ZW50TmFtZXM6ICgpID0+IHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGV4cG9ydHMuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgZW1pdDogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBsaXN0ZW5lcnM6ICgpID0+IHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGV4cG9ydHMuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgbGlzdGVuZXJDb3VudDogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBvbjogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBhZGRMaXN0ZW5lcjogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBvbmNlOiAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHByZXBlbmRMaXN0ZW5lcjogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBwcmVwZW5kT25jZUxpc3RlbmVyOiAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHJlbW92ZUxpc3RlbmVyOiAoKSA9PiB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihleHBvcnRzLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHJlbW92ZUFsbExpc3RlbmVyczogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXhwb3J0cy5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG5cdCAgICAgICAgfVxuXHQgICAgfTtcblx0ICAgIHN3aXRjaCAoZW50aXR5VHlwZSkge1xuXHQgICAgICAgIGNhc2UgJ3ZpZXcnOlxuXHQgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihuZXcgdmlld18xLlZpZXcod2lyZSwgeyB1dWlkLCBuYW1lIH0pLCBnZXRCYXNlTWUoZW50aXR5VHlwZSwgdXVpZCwgbmFtZSksIHtcblx0ICAgICAgICAgICAgICAgIGludGVyb3A6IGZhbGxiYWNrSW50ZXJvcCxcblx0ICAgICAgICAgICAgICAgIGlzT3BlbkZpbjogdHJ1ZVxuXHQgICAgICAgICAgICB9KTtcblx0ICAgICAgICBjYXNlICd3aW5kb3cnOlxuXHQgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihuZXcgd2luZG93XzEuX1dpbmRvdyh3aXJlLCB7IHV1aWQsIG5hbWUgfSksIGdldEJhc2VNZShlbnRpdHlUeXBlLCB1dWlkLCBuYW1lKSwge1xuXHQgICAgICAgICAgICAgICAgaW50ZXJvcDogZmFsbGJhY2tJbnRlcm9wLFxuXHQgICAgICAgICAgICAgICAgaXNPcGVuRmluOiB0cnVlXG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgIGNhc2UgJ2lmcmFtZSc6XG5cdCAgICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKG5ldyBmcmFtZV8xLl9GcmFtZSh3aXJlLCB7IHV1aWQsIG5hbWUgfSksIGdldEJhc2VNZShlbnRpdHlUeXBlLCB1dWlkLCBuYW1lKSwge1xuXHQgICAgICAgICAgICAgICAgaW50ZXJvcDogZmFsbGJhY2tJbnRlcm9wLFxuXHQgICAgICAgICAgICAgICAgaXNPcGVuRmluOiB0cnVlXG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgIGNhc2UgJ2V4dGVybmFsIGNvbm5lY3Rpb24nOlxuXHQgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihuZXcgZXh0ZXJuYWxfYXBwbGljYXRpb25fMS5FeHRlcm5hbEFwcGxpY2F0aW9uKHdpcmUsIHsgdXVpZCB9KSwgZ2V0QmFzZU1lKGVudGl0eVR5cGUsIHV1aWQsIG5hbWUpLCB7XG5cdCAgICAgICAgICAgICAgICBpbnRlcm9wOiBmYWxsYmFja0ludGVyb3AsXG5cdCAgICAgICAgICAgICAgICBpc09wZW5GaW46IGZhbHNlXG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgIGRlZmF1bHQ6XG5cdCAgICAgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgICAgICAuLi5nZXRCYXNlTWUoZW50aXR5VHlwZSwgdXVpZCwgbmFtZSksXG5cdCAgICAgICAgICAgICAgICAuLi51bnN1cHBvcnRlZEV2ZW50QmFzZSxcblx0ICAgICAgICAgICAgICAgIGludGVyb3A6IHVuc3VwcG9ydGVkSW50ZXJvcCxcblx0ICAgICAgICAgICAgICAgIGlzT3BlbkZpbjogZmFsc2Vcblx0ICAgICAgICAgICAgfTtcblx0ICAgIH1cblx0fVxuXHRleHBvcnRzLmdldE1lID0gZ2V0TWU7IFxufSAobWUpKTtcblxudmFyIGludGVyb3AgPSB7fTtcblxudmFyIEZhY3RvcnkkMSA9IHt9O1xuXG52YXIgaW5hY2Nlc3NpYmxlT2JqZWN0ID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShpbmFjY2Vzc2libGVPYmplY3QsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuaW5hY2Nlc3NpYmxlT2JqZWN0LmNyZWF0ZVdhcm5pbmdPYmplY3QgPSBpbmFjY2Vzc2libGVPYmplY3QuY3JlYXRlVW51c2FibGVPYmplY3QgPSB2b2lkIDA7XG5mdW5jdGlvbiBjcmVhdGVVbnVzYWJsZU9iamVjdChtZXNzYWdlKSB7XG4gICAgY29uc3QgaGFuZGxlID0gKCkgPT4ge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgfTtcbiAgICByZXR1cm4gbmV3IFByb3h5KHt9LCB7XG4gICAgICAgIGFwcGx5OiBoYW5kbGUsXG4gICAgICAgIGNvbnN0cnVjdDogaGFuZGxlLFxuICAgICAgICBkZWZpbmVQcm9wZXJ0eTogaGFuZGxlLFxuICAgICAgICBkZWxldGVQcm9wZXJ0eTogaGFuZGxlLFxuICAgICAgICBnZXQ6IGhhbmRsZSxcbiAgICAgICAgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOiBoYW5kbGUsXG4gICAgICAgIGdldFByb3RvdHlwZU9mOiBoYW5kbGUsXG4gICAgICAgIGhhczogaGFuZGxlLFxuICAgICAgICBpc0V4dGVuc2libGU6IGhhbmRsZSxcbiAgICAgICAgb3duS2V5czogaGFuZGxlLFxuICAgICAgICBwcmV2ZW50RXh0ZW5zaW9uczogaGFuZGxlLFxuICAgICAgICBzZXQ6IGhhbmRsZSxcbiAgICAgICAgc2V0UHJvdG90eXBlT2Y6IGhhbmRsZVxuICAgIH0pO1xufVxuaW5hY2Nlc3NpYmxlT2JqZWN0LmNyZWF0ZVVudXNhYmxlT2JqZWN0ID0gY3JlYXRlVW51c2FibGVPYmplY3Q7XG5mdW5jdGlvbiBjcmVhdGVXYXJuaW5nT2JqZWN0KG1lc3NhZ2UsIG9iaikge1xuICAgIHJldHVybiBuZXcgUHJveHkob2JqLCB7XG4gICAgICAgIGdldDogKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgICBjb25zb2xlLndhcm4obWVzc2FnZSk7XG4gICAgICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXQoLi4uYXJncyk7XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgICBjb25zb2xlLndhcm4obWVzc2FnZSk7XG4gICAgICAgICAgICByZXR1cm4gUmVmbGVjdC5zZXQoLi4uYXJncyk7XG4gICAgICAgIH0sXG4gICAgICAgIGdldE93blByb3BlcnR5RGVzY3JpcHRvcjogKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgICAgICBjb25zb2xlLndhcm4obWVzc2FnZSk7XG4gICAgICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoLi4uYXJncyk7XG4gICAgICAgIH0sXG4gICAgICAgIG93bktleXM6ICguLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICAgICAgY29uc29sZS53YXJuKG1lc3NhZ2UpO1xuICAgICAgICAgICAgcmV0dXJuIFJlZmxlY3Qub3duS2V5cyguLi5hcmdzKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuaW5hY2Nlc3NpYmxlT2JqZWN0LmNyZWF0ZVdhcm5pbmdPYmplY3QgPSBjcmVhdGVXYXJuaW5nT2JqZWN0O1xuXG52YXIgSW50ZXJvcEJyb2tlciA9IHt9O1xuXG52YXIgU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlciA9IHt9O1xuXG52YXIgaGFzUmVxdWlyZWRTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyO1xuXG5mdW5jdGlvbiByZXF1aXJlU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlciAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZFNlc3Npb25Db250ZXh0R3JvdXBCcm9rZXIpIHJldHVybiBTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyO1xuXHRoYXNSZXF1aXJlZFNlc3Npb25Db250ZXh0R3JvdXBCcm9rZXIgPSAxO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlciwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdGNvbnN0IF8xID0gcmVxdWlyZUludGVyb3AoKTtcblx0bGV0IFNlc3Npb25Db250ZXh0R3JvdXBCcm9rZXIkMSA9IGNsYXNzIFNlc3Npb25Db250ZXh0R3JvdXBCcm9rZXIge1xuXHQgICAgY29uc3RydWN0b3IocHJvdmlkZXIsIGlkKSB7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlciA9IHByb3ZpZGVyO1xuXHQgICAgICAgIHRoaXMuaWQgPSBpZDtcblx0ICAgICAgICB0aGlzLmxhc3RDb250ZXh0ID0gdW5kZWZpbmVkO1xuXHQgICAgICAgIHRoaXMuY29udGV4dEdyb3VwTWFwID0gbmV3IE1hcCgpO1xuXHQgICAgICAgIHRoaXMuY2xpZW50cyA9IG5ldyBNYXAoKTtcblx0ICAgICAgICB0aGlzLnJlZ2lzdGVyTGlzdGVuZXJzKCk7XG5cdCAgICB9XG5cdCAgICByZWdpc3Rlckxpc3RlbmVycygpIHtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLnJlZ2lzdGVyKGBzZXNzaW9uQ29udGV4dEdyb3VwOmdldENvbnRleHQtJHt0aGlzLmlkfWAsIHRoaXMuZ2V0Q3VycmVudENvbnRleHQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlci5yZWdpc3Rlcihgc2Vzc2lvbkNvbnRleHRHcm91cDpzZXRDb250ZXh0LSR7dGhpcy5pZH1gLCB0aGlzLnNldENvbnRleHQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlci5yZWdpc3Rlcihgc2Vzc2lvbkNvbnRleHRHcm91cDpoYW5kbGVyQWRkZWQtJHt0aGlzLmlkfWAsIHRoaXMuaGFuZGxlckFkZGVkLmJpbmQodGhpcykpO1xuXHQgICAgICAgIHRoaXMucHJvdmlkZXIucmVnaXN0ZXIoYHNlc3Npb25Db250ZXh0R3JvdXA6aGFuZGxlclJlbW92ZWQtJHt0aGlzLmlkfWAsIHRoaXMuaGFuZGxlclJlbW92ZWQuYmluZCh0aGlzKSk7XG5cdCAgICB9XG5cdCAgICBnZXRDdXJyZW50Q29udGV4dChwYXlsb2FkKSB7XG5cdCAgICAgICAgcmV0dXJuIHBheWxvYWQudHlwZSA/IHRoaXMuY29udGV4dEdyb3VwTWFwLmdldChwYXlsb2FkLnR5cGUpIDogdGhpcy5sYXN0Q29udGV4dDtcblx0ICAgIH1cblx0ICAgIHNldENvbnRleHQocGF5bG9hZCwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCB7IGNvbnRleHQgfSA9IHBheWxvYWQ7XG5cdCAgICAgICAgY29uc3QgY29udGV4dEludGVncml0eUNoZWNrUmVzdWx0ID0gXzEuSW50ZXJvcEJyb2tlci5jaGVja0NvbnRleHRJbnRlZ3JpdHkoY29udGV4dCk7XG5cdCAgICAgICAgaWYgKGNvbnRleHRJbnRlZ3JpdHlDaGVja1Jlc3VsdC5pc1ZhbGlkID09PSBmYWxzZSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBzZXQgQ29udGV4dCAtIGJhZCBDb250ZXh0LiBSZWFzb246ICR7Y29udGV4dEludGVncml0eUNoZWNrUmVzdWx0LnJlYXNvbn0uIENvbnRleHQ6ICR7SlNPTi5zdHJpbmdpZnkoY29udGV4dCl9YCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNvbnN0IGNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKCFjbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICAvLyBUaGlzIHNob3VsZG4ndCBnZXQgaGl0LlxuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsaWVudCB3aXRoIElkZW50aXR5OiAke2NsaWVudElkZW50aXR5LnV1aWR9ICR7Y2xpZW50SWRlbnRpdHkubmFtZX0gbm90IGluIFNlc3Npb24gQ2xpZW50IFN0YXRlIE1hcGApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICAvLyBzZXQgdGhlIGNvbnRleHRcblx0ICAgICAgICB0aGlzLmNvbnRleHRHcm91cE1hcC5zZXQoY29udGV4dC50eXBlLCBjb250ZXh0KTtcblx0ICAgICAgICB0aGlzLmxhc3RDb250ZXh0ID0gY29udGV4dDtcblx0ICAgICAgICBjb25zdCBjbGllbnRTdWJzY3JpcHRpb25TdGF0ZXMgPSBBcnJheS5mcm9tKHRoaXMuY2xpZW50cy52YWx1ZXMoKSk7XG5cdCAgICAgICAgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGVzLmZvckVhY2goKGNsaWVudCkgPT4ge1xuXHQgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLWV4cHJlc3Npb25zXG5cdCAgICAgICAgICAgIGNsaWVudC5jb250ZXh0SGFuZGxlcnMuZ2V0KGNvbnRleHQudHlwZSk/LmZvckVhY2goKGhhbmRsZXJJZCkgPT4ge1xuXHQgICAgICAgICAgICAgICAgdGhpcy5wcm92aWRlci5kaXNwYXRjaChjbGllbnQuY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwgY29udGV4dCk7XG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICBpZiAoY2xpZW50Lmdsb2JhbEhhbmRsZXIpIHtcblx0ICAgICAgICAgICAgICAgIHRoaXMucHJvdmlkZXIuZGlzcGF0Y2goY2xpZW50LmNsaWVudElkZW50aXR5LCBjbGllbnQuZ2xvYmFsSGFuZGxlciwgY29udGV4dCk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIGdldENsaWVudFN0YXRlKGlkKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50cy5nZXQoaWQuZW5kcG9pbnRJZCk7XG5cdCAgICB9XG5cdCAgICBhc3luYyBoYW5kbGVyQWRkZWQocGF5bG9hZCwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCB7IGhhbmRsZXJJZCwgY29udGV4dFR5cGUgfSA9IHBheWxvYWQ7XG5cdCAgICAgICAgY29uc3QgY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUgPSB0aGlzLmdldENsaWVudFN0YXRlKGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICBpZiAoIWNsaWVudFN1YnNjcmlwdGlvblN0YXRlKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2xpZW50IHdpdGggSWRlbnRpdHk6ICR7Y2xpZW50SWRlbnRpdHkudXVpZH0gJHtjbGllbnRJZGVudGl0eS5uYW1lfSBub3QgaW4gQ2xpZW50IFN0YXRlIE1hcGApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBpZiAoY29udGV4dFR5cGUpIHtcblx0ICAgICAgICAgICAgY29uc3QgY3VycmVudEhhbmRsZXJMaXN0ID0gY2xpZW50U3Vic2NyaXB0aW9uU3RhdGUuY29udGV4dEhhbmRsZXJzLmdldChjb250ZXh0VHlwZSkgfHwgW107XG5cdCAgICAgICAgICAgIGNsaWVudFN1YnNjcmlwdGlvblN0YXRlLmNvbnRleHRIYW5kbGVycy5zZXQoY29udGV4dFR5cGUsIFsuLi5jdXJyZW50SGFuZGxlckxpc3QsIGhhbmRsZXJJZF0pO1xuXHQgICAgICAgICAgICBjb25zdCBjdXJyZW50Q29udGV4dCA9IHRoaXMuY29udGV4dEdyb3VwTWFwLmdldChjb250ZXh0VHlwZSk7XG5cdCAgICAgICAgICAgIGlmIChjdXJyZW50Q29udGV4dCkge1xuXHQgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wcm92aWRlci5kaXNwYXRjaChjbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBjdXJyZW50Q29udGV4dCk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIGNsaWVudFN1YnNjcmlwdGlvblN0YXRlLmdsb2JhbEhhbmRsZXIgPSBoYW5kbGVySWQ7XG5cdCAgICAgICAgICAgIGNvbnN0IGdsb2JhbERpc3BhdGNoUHJvbWlzZXMgPSBbLi4udGhpcy5jb250ZXh0R3JvdXBNYXAua2V5cygpXS5tYXAoYXN5bmMgKGN1cnJlbnRDb250ZXh0VHlwZSkgPT4ge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudENvbnRleHQgPSB0aGlzLmNvbnRleHRHcm91cE1hcC5nZXQoY3VycmVudENvbnRleHRUeXBlKTtcblx0ICAgICAgICAgICAgICAgIGlmIChjdXJyZW50Q29udGV4dCkge1xuXHQgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucHJvdmlkZXIuZGlzcGF0Y2goY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwgY3VycmVudENvbnRleHQpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9KTtcblx0ICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoZ2xvYmFsRGlzcGF0Y2hQcm9taXNlcyk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgaGFuZGxlclJlbW92ZWQocGF5bG9hZCwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCB7IGhhbmRsZXJJZCB9ID0gcGF5bG9hZDtcblx0ICAgICAgICBjb25zdCBjbGllbnQgPSB0aGlzLmNsaWVudHMuZ2V0KGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQpO1xuXHQgICAgICAgIGlmIChjbGllbnQpIHtcblx0ICAgICAgICAgICAgQXJyYXkuZnJvbShjbGllbnQuY29udGV4dEhhbmRsZXJzKS5mb3JFYWNoKChbLCBoYW5kbGVyc10pID0+IHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gaGFuZGxlcnMuaW5kZXhPZihoYW5kbGVySWQpO1xuXHQgICAgICAgICAgICAgICAgaWYgKGluZGV4ID4gLTEpIHtcblx0ICAgICAgICAgICAgICAgICAgICBoYW5kbGVycy5zcGxpY2UoaW5kZXgsIDEpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9KTtcblx0ICAgICAgICAgICAgaWYgKGNsaWVudC5nbG9iYWxIYW5kbGVyID09PSBoYW5kbGVySWQpIHtcblx0ICAgICAgICAgICAgICAgIGNsaWVudC5nbG9iYWxIYW5kbGVyID0gdW5kZWZpbmVkO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICBjb25zb2xlLndhcm4oYFRyeWluZyB0byByZW1vdmUgYSBoYW5kbGVyIGZyb20gYSBjbGllbnQgdGhhdCBpc24ndCBtYXBwZWQuIGhhbmRsZXJJZDogJHtoYW5kbGVySWR9LiBjbGllbnRJZGVudGl0eTogJHtjbGllbnRJZGVudGl0eX1gKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICByZWdpc3Rlck5ld0NsaWVudChjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGlmICghdGhpcy5jbGllbnRzLmhhcyhjbGllbnRJZGVudGl0eS5lbmRwb2ludElkKSkge1xuXHQgICAgICAgICAgICBjb25zdCBjbGllbnRTdWJzY3JpcHRpb25TdGF0ZSA9IHtcblx0ICAgICAgICAgICAgICAgIGNvbnRleHRIYW5kbGVyczogbmV3IE1hcCgpLFxuXHQgICAgICAgICAgICAgICAgY2xpZW50SWRlbnRpdHksXG5cdCAgICAgICAgICAgICAgICBnbG9iYWxIYW5kbGVyOiB1bmRlZmluZWRcblx0ICAgICAgICAgICAgfTtcblx0ICAgICAgICAgICAgdGhpcy5jbGllbnRzLnNldChjbGllbnRJZGVudGl0eS5lbmRwb2ludElkLCBjbGllbnRTdWJzY3JpcHRpb25TdGF0ZSk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgb25EaXNjb25uZWN0aW9uKGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgdGhpcy5jbGllbnRzLmRlbGV0ZShjbGllbnRJZGVudGl0eS5lbmRwb2ludElkKTtcblx0ICAgIH1cblx0fTtcblx0U2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlci5kZWZhdWx0ID0gU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlciQxO1xuXHRyZXR1cm4gU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlcjtcbn1cblxudmFyIHV0aWxzJDMgPSB7fTtcblxuKGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0ZXhwb3J0cy53cmFwSW50ZW50SGFuZGxlciA9IGV4cG9ydHMuQlJPS0VSX0VSUk9SUyA9IGV4cG9ydHMuZ2VuZXJhdGVPdmVycmlkZVdhcm5pbmcgPSBleHBvcnRzLmdlbmVyYXRlT3ZlcnJpZGVFcnJvciA9IGV4cG9ydHMud3JhcENvbnRleHRIYW5kbGVyID0gZXhwb3J0cy53cmFwSW5UcnlDYXRjaCA9IGV4cG9ydHMuZ2VuZXJhdGVJZCA9IHZvaWQgMDtcblx0Y29uc3QgZ2VuZXJhdGVJZCA9ICgpID0+IGAke01hdGgucmFuZG9tKCl9JHtEYXRlLm5vdygpfWA7XG5cdGV4cG9ydHMuZ2VuZXJhdGVJZCA9IGdlbmVyYXRlSWQ7XG5cdGNvbnN0IHdyYXBJblRyeUNhdGNoID0gKGYsIHByZWZpeCkgPT4gKC4uLmFyZ3MpID0+IHtcblx0ICAgIHRyeSB7XG5cdCAgICAgICAgcmV0dXJuIGYoLi4uYXJncyk7XG5cdCAgICB9XG5cdCAgICBjYXRjaCAoZSkge1xuXHQgICAgICAgIHRocm93IG5ldyBFcnJvcigocHJlZml4IHx8ICcnKSArIGUpO1xuXHQgICAgfVxuXHR9O1xuXHRleHBvcnRzLndyYXBJblRyeUNhdGNoID0gd3JhcEluVHJ5Q2F0Y2g7XG5cdGNvbnN0IHdyYXBDb250ZXh0SGFuZGxlciA9IChoYW5kbGVyLCBoYW5kbGVySWQpID0+IHtcblx0ICAgIHJldHVybiBhc3luYyAoY29udGV4dCkgPT4ge1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIGF3YWl0IGhhbmRsZXIoY29udGV4dCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciB0aHJvd24gYnkgaGFuZGxlciAke2hhbmRsZXJJZH0gZm9yIGNvbnRleHQgdHlwZSAke2NvbnRleHQudHlwZX06ICR7ZXJyb3J9YCk7XG5cdCAgICAgICAgICAgIHRocm93IGVycm9yO1xuXHQgICAgICAgIH1cblx0ICAgIH07XG5cdH07XG5cdGV4cG9ydHMud3JhcENvbnRleHRIYW5kbGVyID0gd3JhcENvbnRleHRIYW5kbGVyO1xuXHRjb25zdCBnZW5lcmF0ZU92ZXJyaWRlRXJyb3IgPSAoY2xpZW50QXBpLCBicm9rZXJBcGkpID0+IHtcblx0ICAgIHJldHVybiBgWW91IGhhdmUgdHJpZWQgdG8gdG8gdXNlICR7Y2xpZW50QXBpfSBidXQgJHticm9rZXJBcGl9IGhhcyBub3QgYmVlbiBvdmVycmlkZGVuIGluIHRoZSBJbnRlcm9wIEJyb2tlci4gUGxlYXNlIG92ZXJyaWRlIHRoaXMgZnVuY3Rpb24uIFJlZmVyIHRvIG91ciBkb2N1bWVudGF0aW9uIGZvciBtb3JlIGluZm8uYDtcblx0fTtcblx0ZXhwb3J0cy5nZW5lcmF0ZU92ZXJyaWRlRXJyb3IgPSBnZW5lcmF0ZU92ZXJyaWRlRXJyb3I7XG5cdGNvbnN0IGdlbmVyYXRlT3ZlcnJpZGVXYXJuaW5nID0gKGZkYzNDbGllbnRBcGksIGJyb2tlckFwaSwgaWRlbnRpdHksIGludGVyb3BDbGllbnRBcGkpID0+IHtcblx0ICAgIGNvbnN0IHsgdXVpZCwgbmFtZSB9ID0gaWRlbnRpdHk7XG5cdCAgICBjb25zdCBtZXNzYWdlID0gaW50ZXJvcENsaWVudEFwaVxuXHQgICAgICAgID8gYEVudGl0eSB3aXRoIGlkZW50aXR5OiAke3V1aWR9LyR7bmFtZX0gaGFzIGNhbGxlZCAke2ludGVyb3BDbGllbnRBcGl9IG9yICR7ZmRjM0NsaWVudEFwaX0gYnV0ICR7YnJva2VyQXBpfSBoYXMgbm90IGJlZW4gb3ZlcnJpZGRlbi5gXG5cdCAgICAgICAgOiBgRW50aXR5IHdpdGggaWRlbnRpdHk6ICR7dXVpZH0vJHtuYW1lfSBoYXMgY2FsbGVkICR7ZmRjM0NsaWVudEFwaX0gYnV0ICR7YnJva2VyQXBpfSBoYXMgbm90IGJlZW4gb3ZlcnJpZGRlbi5gO1xuXHQgICAgcmV0dXJuIG1lc3NhZ2U7XG5cdH07XG5cdGV4cG9ydHMuZ2VuZXJhdGVPdmVycmlkZVdhcm5pbmcgPSBnZW5lcmF0ZU92ZXJyaWRlV2FybmluZztcblx0ZXhwb3J0cy5CUk9LRVJfRVJST1JTID0ge1xuXHQgICAgZmlyZUludGVudDogKDAsIGV4cG9ydHMuZ2VuZXJhdGVPdmVycmlkZUVycm9yKSgnZmlyZUludGVudCcsICdoYW5kbGVGaXJlZEludGVudCcpLFxuXHQgICAgZmlyZUludGVudEZvckNvbnRleHQ6ICgwLCBleHBvcnRzLmdlbmVyYXRlT3ZlcnJpZGVFcnJvcikoJ2ZpcmVJbnRlbnRGb3JDb250ZXh0JywgJ2hhbmRsZUZpcmVkSW50ZW50Rm9yQ29udGV4dCcpLFxuXHQgICAgZ2V0SW5mb0ZvckludGVudDogKDAsIGV4cG9ydHMuZ2VuZXJhdGVPdmVycmlkZUVycm9yKSgnZ2V0SW5mb0ZvckludGVudCcsICdoYW5kbGVJbmZvRm9ySW50ZW50JyksXG5cdCAgICBnZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dDogKDAsIGV4cG9ydHMuZ2VuZXJhdGVPdmVycmlkZUVycm9yKSgnZ2V0SW5mb0ZvckludGVudHNCeUNvbnRleHQnLCAnaGFuZGxlSW5mb0ZvckludGVudHNCeUNvbnRleHQnKSxcblx0ICAgIGpvaW5TZXNzaW9uQ29udGV4dEdyb3VwV2l0aEpvaW5Db250ZXh0R3JvdXA6ICdUaGUgQ29udGV4dCBHcm91cCB5b3UgaGF2ZSB0cmllZCB0byBqb2luIGlzIGEgU2Vzc2lvbiBDb250ZXh0IEdyb3VwLiBDdXN0b20gQ29udGV4dCBHcm91cHMgY2FuIG9ubHkgYmUgZGVmaW5lZCBieSB0aGUgSW50ZXJvcCBCcm9rZXIgdGhyb3VnaCBjb2RlIG9yIG1hbmlmZXN0IGNvbmZpZ3VyYXRpb24uIFBsZWFzZSB1c2Ugam9pblNlc3Npb25Db250ZXh0R3JvdXAuJyxcblx0ICAgIGZkYzNPcGVuOiAoMCwgZXhwb3J0cy5nZW5lcmF0ZU92ZXJyaWRlRXJyb3IpKCdmZGMzLm9wZW4nLCAnZmRjM0hhbmRsZU9wZW4nKSxcblx0ICAgIGZkYzNGaW5kSW5zdGFuY2VzOiAoMCwgZXhwb3J0cy5nZW5lcmF0ZU92ZXJyaWRlRXJyb3IpKCdmZGMzLmZpbmRJbnN0YW5jZXMnLCAnZmRjM0hhbmRsZUZpbmRJbnN0YW5jZXMnKSxcblx0ICAgIGZkYzNHZXRBcHBNZXRhZGF0YTogKDAsIGV4cG9ydHMuZ2VuZXJhdGVPdmVycmlkZUVycm9yKSgnZmRjMy5nZXRBcHBNZXRhZGF0YScsICdmZGMzSGFuZGxlR2V0QXBwTWV0YWRhdGEnKSxcblx0ICAgIGZkYzNHZXRJbmZvOiAoMCwgZXhwb3J0cy5nZW5lcmF0ZU92ZXJyaWRlRXJyb3IpKCdmZGMzLmdldEluZm8nLCAnZmRjM0hhbmRsZUdldEluZm8nKVxuXHR9O1xuXHRjb25zdCB3cmFwSW50ZW50SGFuZGxlciA9IChoYW5kbGVyLCBoYW5kbGVySWQpID0+IHtcblx0ICAgIHJldHVybiBhc3luYyAoaW50ZW50KSA9PiB7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgcmV0dXJuIGhhbmRsZXIoaW50ZW50KTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIHRocm93biBieSBoYW5kbGVyICR7aGFuZGxlcklkfTogJHtlcnJvcn1gKTtcblx0ICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG5cdCAgICAgICAgfVxuXHQgICAgfTtcblx0fTtcblx0ZXhwb3J0cy53cmFwSW50ZW50SGFuZGxlciA9IHdyYXBJbnRlbnRIYW5kbGVyOyBcbn0gKHV0aWxzJDMpKTtcblxudmFyIFByaXZhdGVDaGFubmVsUHJvdmlkZXIgPSB7fTtcblxudmFyIGhhc1JlcXVpcmVkUHJpdmF0ZUNoYW5uZWxQcm92aWRlcjtcblxuZnVuY3Rpb24gcmVxdWlyZVByaXZhdGVDaGFubmVsUHJvdmlkZXIgKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRQcml2YXRlQ2hhbm5lbFByb3ZpZGVyKSByZXR1cm4gUHJpdmF0ZUNoYW5uZWxQcm92aWRlcjtcblx0aGFzUmVxdWlyZWRQcml2YXRlQ2hhbm5lbFByb3ZpZGVyID0gMTtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KFByaXZhdGVDaGFubmVsUHJvdmlkZXIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRQcml2YXRlQ2hhbm5lbFByb3ZpZGVyLlByaXZhdGVDaGFubmVsUHJvdmlkZXIgPSB2b2lkIDA7XG5cdGNvbnN0IEludGVyb3BCcm9rZXJfMSA9IHJlcXVpcmVJbnRlcm9wQnJva2VyKCk7XG5cdGxldCBQcml2YXRlQ2hhbm5lbFByb3ZpZGVyJDEgPSBjbGFzcyBQcml2YXRlQ2hhbm5lbFByb3ZpZGVyIHtcblx0ICAgIGNvbnN0cnVjdG9yKHByb3ZpZGVyLCBpZCkge1xuXHQgICAgICAgIHRoaXMucHJvdmlkZXIgPSBwcm92aWRlcjtcblx0ICAgICAgICB0aGlzLmlkID0gaWQ7XG5cdCAgICAgICAgdGhpcy5jbGllbnRzID0gbmV3IE1hcCgpO1xuXHQgICAgICAgIHRoaXMucmVnaXN0ZXJMaXN0ZW5lcnMoKTtcblx0ICAgICAgICB0aGlzLmNvbnRleHRCeUNvbnRleHRUeXBlID0gbmV3IE1hcCgpO1xuXHQgICAgICAgIHRoaXMubGFzdENvbnRleHQgPSB1bmRlZmluZWQ7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlci5vbkNvbm5lY3Rpb24oKGNsaWVudElkZW50aXR5KSA9PiB0aGlzLnJlZ2lzdGVyTmV3Q2xpZW50KGNsaWVudElkZW50aXR5KSk7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlci5vbkRpc2Nvbm5lY3Rpb24oYXN5bmMgKGNsaWVudElkZW50aXR5KSA9PiB7XG5cdCAgICAgICAgICAgIGNvbnN0IHsgZW5kcG9pbnRJZCB9ID0gY2xpZW50SWRlbnRpdHk7XG5cdCAgICAgICAgICAgIGlmICh0aGlzLmNsaWVudHMuaGFzKGVuZHBvaW50SWQpKSB7XG5cdCAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmhhbmRsZUNsaWVudERpc2Nvbm5lY3RpbmcoY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGlmICgoYXdhaXQgdGhpcy5wcm92aWRlci5nZXRBbGxDbGllbnRJbmZvKCkpLmxlbmd0aCA9PT0gMCkge1xuXHQgICAgICAgICAgICAgICAgdGhpcy5wcm92aWRlci5kZXN0cm95KCk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIGdldENsaWVudFN0YXRlKGlkKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50cy5nZXQoaWQuZW5kcG9pbnRJZCk7XG5cdCAgICB9XG5cdCAgICByZWdpc3Rlckxpc3RlbmVycygpIHtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLnJlZ2lzdGVyKCdicm9hZGNhc3QnLCB0aGlzLmJyb2FkY2FzdC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLnJlZ2lzdGVyKCdnZXRDdXJyZW50Q29udGV4dCcsIHRoaXMuZ2V0Q3VycmVudENvbnRleHQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlci5yZWdpc3RlcignY29udGV4dEhhbmRsZXJBZGRlZCcsIHRoaXMuY29udGV4dEhhbmRsZXJBZGRlZC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLnJlZ2lzdGVyKCdjb250ZXh0SGFuZGxlclJlbW92ZWQnLCB0aGlzLmNvbnRleHRIYW5kbGVyUmVtb3ZlZC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICB0aGlzLnByb3ZpZGVyLnJlZ2lzdGVyKCdub25TdGFuZGFyZEhhbmRsZXJSZW1vdmVkJywgdGhpcy5ub25TdGFuZGFyZEhhbmRsZXJSZW1vdmVkLmJpbmQodGhpcykpO1xuXHQgICAgICAgIHRoaXMucHJvdmlkZXIucmVnaXN0ZXIoJ29uQWRkQ29udGV4dEhhbmRsZXJBZGRlZCcsIHRoaXMub25BZGRDb250ZXh0SGFuZGxlckFkZGVkLmJpbmQodGhpcykpO1xuXHQgICAgICAgIHRoaXMucHJvdmlkZXIucmVnaXN0ZXIoJ29uRGlzY29ubmVjdEhhbmRsZXJBZGRlZCcsIHRoaXMub25EaXNjb25uZWN0SGFuZGxlckFkZGVkLmJpbmQodGhpcykpO1xuXHQgICAgICAgIHRoaXMucHJvdmlkZXIucmVnaXN0ZXIoJ29uVW5zdWJzY3JpYmVIYW5kbGVyQWRkZWQnLCB0aGlzLm9uVW5zdWJzY3JpYmVIYW5kbGVyQWRkZWQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgdGhpcy5wcm92aWRlci5yZWdpc3RlcignY2xpZW50RGlzY29ubmVjdGluZycsIChwYXlsb2FkLCBjbGllbnRJZGVudGl0eSkgPT4ge1xuXHQgICAgICAgICAgICB0aGlzLmhhbmRsZUNsaWVudERpc2Nvbm5lY3RpbmcoY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgYnJvYWRjYXN0KHBheWxvYWQsIGJyb2FkY2FzdGVyQ2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCB7IGNvbnRleHQgfSA9IHBheWxvYWQ7XG5cdCAgICAgICAgY29uc3QgYnJvYWRjYXN0ZXJDbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoYnJvYWRjYXN0ZXJDbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKCFicm9hZGNhc3RlckNsaWVudFN0YXRlKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2xpZW50IHdpdGggSWRlbnRpdHk6ICR7YnJvYWRjYXN0ZXJDbGllbnRJZGVudGl0eS51dWlkfSAke2Jyb2FkY2FzdGVyQ2xpZW50SWRlbnRpdHkubmFtZX0sIHRyaWVkIHRvIGNhbGwgYnJvYWRjYXN0LCBpcyBub3QgY29ubmVjdGVkIHRvIHRoaXMgUHJpdmF0ZSBDaGFubmVsYCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNvbnN0IGNvbnRleHRJbnRlZ3JpdHlDaGVja1Jlc3VsdCA9IEludGVyb3BCcm9rZXJfMS5JbnRlcm9wQnJva2VyLmNoZWNrQ29udGV4dEludGVncml0eShjb250ZXh0KTtcblx0ICAgICAgICBpZiAoY29udGV4dEludGVncml0eUNoZWNrUmVzdWx0LmlzVmFsaWQgPT09IGZhbHNlKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGJyb2FkY2FzdCAtIGJhZCBDb250ZXh0LiBSZWFzb246ICR7Y29udGV4dEludGVncml0eUNoZWNrUmVzdWx0LnJlYXNvbn0uIENvbnRleHQ6ICR7SlNPTi5zdHJpbmdpZnkoY29udGV4dCl9YCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHRoaXMuY29udGV4dEJ5Q29udGV4dFR5cGUuc2V0KGNvbnRleHQudHlwZSwgY29udGV4dCk7XG5cdCAgICAgICAgdGhpcy5sYXN0Q29udGV4dCA9IGNvbnRleHQ7XG5cdCAgICAgICAgQXJyYXkuZnJvbSh0aGlzLmNsaWVudHMudmFsdWVzKCkpLmZvckVhY2goKGN1cnJDbGllbnRTdGF0ZSkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCBoYW5kbGVySWRzRm9yQ29udGV4dFR5cGUgPSBjdXJyQ2xpZW50U3RhdGUuaGFuZGxlcklkc0J5Q29udGV4dFR5cGVzLmdldChjb250ZXh0LnR5cGUpO1xuXHQgICAgICAgICAgICBpZiAoaGFuZGxlcklkc0ZvckNvbnRleHRUeXBlKSB7XG5cdCAgICAgICAgICAgICAgICBoYW5kbGVySWRzRm9yQ29udGV4dFR5cGUuZm9yRWFjaCgoaGFuZGxlcklkKSA9PiB7XG5cdCAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm92aWRlci5kaXNwYXRjaChjdXJyQ2xpZW50U3RhdGUuY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwgY29udGV4dCk7XG5cdCAgICAgICAgICAgICAgICB9KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBpZiAoY3VyckNsaWVudFN0YXRlLmdsb2JhbEhhbmRsZXIpIHtcblx0ICAgICAgICAgICAgICAgIHRoaXMucHJvdmlkZXIuZGlzcGF0Y2goY3VyckNsaWVudFN0YXRlLmNsaWVudElkZW50aXR5LCBjdXJyQ2xpZW50U3RhdGUuZ2xvYmFsSGFuZGxlciwgY29udGV4dCk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIGdldEN1cnJlbnRDb250ZXh0KHBheWxvYWQsIHNlbmRlckNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgY29uc3QgeyBjb250ZXh0VHlwZSB9ID0gcGF5bG9hZDtcblx0ICAgICAgICBjb25zdCBjbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoc2VuZGVyQ2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGlmICghY2xpZW50U3RhdGUpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDbGllbnQgd2l0aCBJZGVudGl0eTogJHtzZW5kZXJDbGllbnRJZGVudGl0eS51dWlkfSAke3NlbmRlckNsaWVudElkZW50aXR5Lm5hbWV9LCB0cmllZCB0byBjYWxsIGdldEN1cnJlbnRDb250ZXh0LCBpcyBub3QgY29ubmVjdGVkIHRvIHRoaXMgUHJpdmF0ZSBDaGFubmVsYCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmIChjb250ZXh0VHlwZSAhPT0gdW5kZWZpbmVkKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRDb250ZXh0ID0gdGhpcy5jb250ZXh0QnlDb250ZXh0VHlwZS5nZXQoY29udGV4dFR5cGUpO1xuXHQgICAgICAgICAgICBpZiAoY3VycmVudENvbnRleHQpXG5cdCAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudENvbnRleHQ7XG5cdCAgICAgICAgICAgIHJldHVybiBudWxsO1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4gdGhpcy5sYXN0Q29udGV4dCA/IHRoaXMubGFzdENvbnRleHQgOiBudWxsO1xuXHQgICAgfVxuXHQgICAgY29udGV4dEhhbmRsZXJBZGRlZChwYXlsb2FkLCBzZW5kZXJDbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IHsgaGFuZGxlcklkLCBjb250ZXh0VHlwZSB9ID0gcGF5bG9hZDtcblx0ICAgICAgICBjb25zdCBzZW5kZXJDbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoc2VuZGVyQ2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGlmICghc2VuZGVyQ2xpZW50U3RhdGUpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDbGllbnQgd2l0aCBJZGVudGl0eTogJHtzZW5kZXJDbGllbnRJZGVudGl0eS51dWlkfSAke3NlbmRlckNsaWVudElkZW50aXR5Lm5hbWV9LCB0cmllZCB0byBjYWxsIGFkZENvbnRleHRMaXN0ZW5lciwgaXMgbm90IGNvbm5lY3RlZCB0byB0aGlzIFByaXZhdGUgQ2hhbm5lbGApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBpZiAoY29udGV4dFR5cGUpIHtcblx0ICAgICAgICAgICAgY29uc3QgY3VycmVudEhhbmRsZXJzTGlzdCA9IHNlbmRlckNsaWVudFN0YXRlLmhhbmRsZXJJZHNCeUNvbnRleHRUeXBlcy5nZXQoY29udGV4dFR5cGUpIHx8IFtdO1xuXHQgICAgICAgICAgICBzZW5kZXJDbGllbnRTdGF0ZS5oYW5kbGVySWRzQnlDb250ZXh0VHlwZXMuc2V0KGNvbnRleHRUeXBlLCBbLi4uY3VycmVudEhhbmRsZXJzTGlzdCwgaGFuZGxlcklkXSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICBzZW5kZXJDbGllbnRTdGF0ZS5nbG9iYWxIYW5kbGVyID0gaGFuZGxlcklkO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBBcnJheS5mcm9tKHRoaXMuY2xpZW50cy52YWx1ZXMoKSkuZm9yRWFjaCgoY3VyckNsaWVudFN0YXRlKSA9PiB7XG5cdCAgICAgICAgICAgIGlmIChjdXJyQ2xpZW50U3RhdGUuY2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCAhPT0gc2VuZGVyQ2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCAmJlxuXHQgICAgICAgICAgICAgICAgY3VyckNsaWVudFN0YXRlLm9uQWRkQ29udGV4dExpc3RlbmVySGFuZGxlcklkKSB7XG5cdCAgICAgICAgICAgICAgICB0aGlzLnByb3ZpZGVyLmRpc3BhdGNoKGN1cnJDbGllbnRTdGF0ZS5jbGllbnRJZGVudGl0eSwgY3VyckNsaWVudFN0YXRlLm9uQWRkQ29udGV4dExpc3RlbmVySGFuZGxlcklkLCBjb250ZXh0VHlwZSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIGFzeW5jIGNvbnRleHRIYW5kbGVyUmVtb3ZlZChwYXlsb2FkLCByZW1vdmluZ0NsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgLy8gTUM6IE1hZGUgdGhpcyByZW1vdmFsIGFzeW5jIHRvIGVuc3VyZSB0aGF0IG9uVW5zdWJzY3JpYmUgaGFuZGxlcnMgYXJlIGhpdCBiZWZvcmUgYW55dGhpbmcgZWxzZSBoYXBwZW5zLlxuXHQgICAgICAgIGNvbnN0IHsgaGFuZGxlcklkIH0gPSBwYXlsb2FkO1xuXHQgICAgICAgIGNvbnN0IHJlbW92aW5nQ2xpZW50U3RhdGUgPSB0aGlzLmdldENsaWVudFN0YXRlKHJlbW92aW5nQ2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGlmIChyZW1vdmluZ0NsaWVudFN0YXRlKSB7XG5cdCAgICAgICAgICAgIGxldCBjb250ZXh0VHlwZTtcblx0ICAgICAgICAgICAgaWYgKHJlbW92aW5nQ2xpZW50U3RhdGUuZ2xvYmFsSGFuZGxlciA9PT0gaGFuZGxlcklkKSB7XG5cdCAgICAgICAgICAgICAgICByZW1vdmluZ0NsaWVudFN0YXRlLmdsb2JhbEhhbmRsZXIgPSB1bmRlZmluZWQ7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IFtjdXJyQ29udGV4dFR5cGUsIGhhbmRsZXJzSWRzXSBvZiByZW1vdmluZ0NsaWVudFN0YXRlLmhhbmRsZXJJZHNCeUNvbnRleHRUeXBlcykge1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gaGFuZGxlcnNJZHMuaW5kZXhPZihoYW5kbGVySWQpO1xuXHQgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCA+IC0xKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZXJzSWRzLnNwbGljZShpbmRleCwgMSk7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHRUeXBlID0gY3VyckNvbnRleHRUeXBlO1xuXHQgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAvLyBnZXR0aW5nIG9ubHkgdmFsaWQgY2xpZW50IGNvbm5lY3Rpb25zIGhlcmUsIGl0IGlzIHBvc3NpYmxlIHdlIGhhdmVuJ3QgcmVtb3ZlZCBhIGRpc2Nvbm5lY3RlZCBjbGllbnQgZnJvbSB0aGUgbWFwIHlldFxuXHQgICAgICAgICAgICAvLyBzbyB3ZSBuZWVkIHRvIGVuc3VyZSB3ZSBkb24ndCBkaXNwYXRjaCB0byBhbnkgZGlzY29ubmVjdGVkIGNsaWVudFxuXHQgICAgICAgICAgICAvLyBUT0RPOiBUYWtlIGEgbG9vayBhdCBvdXIgY2xpZW50IGRpc2Nvbm5lY3Rpb24gbG9naWMgYW5kIHNlZSBpZiB3ZSBjYW4gaGFuZGxlIGNsaWVudCBkaXNjb25uZWN0aW9uIGNsZWFubHlcblx0ICAgICAgICAgICAgY29uc3QgY2xpZW50c1RvRGlzcGF0Y2hUbyA9IGF3YWl0IHRoaXMuZ2V0Q29ubmVjdGVkQ2xpZW50cygpO1xuXHQgICAgICAgICAgICBjb25zdCBkaXNwYXRjaFByb21pc2VzID0gY2xpZW50c1RvRGlzcGF0Y2hUby5tYXAoYXN5bmMgKG90aGVyQ2xpZW50U3RhdGUpID0+IHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IHsgY2xpZW50SWRlbnRpdHksIGNsaWVudElkZW50aXR5OiB7IGVuZHBvaW50SWQgfSwgb25VbnN1YnNjcmliZUhhbmRsZXJJZCB9ID0gb3RoZXJDbGllbnRTdGF0ZTtcblx0ICAgICAgICAgICAgICAgIGlmIChlbmRwb2ludElkICE9PSByZW1vdmluZ0NsaWVudElkZW50aXR5LmVuZHBvaW50SWQgJiYgb25VbnN1YnNjcmliZUhhbmRsZXJJZCkge1xuXHQgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucHJvdmlkZXIuZGlzcGF0Y2goY2xpZW50SWRlbnRpdHksIG9uVW5zdWJzY3JpYmVIYW5kbGVySWQsIGNvbnRleHRUeXBlKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChkaXNwYXRjaFByb21pc2VzKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFByb2JsZW0gd2hlbiBhdHRlbXB0aW5nIHRvIGRpc3BhdGNoIHRvIG9uVW5zdWJzY3JpYmVIYW5kbGVycy4gRXJyb3I6ICR7ZXJyb3J9IFJlbW92aW5nIENsaWVudDogJHtoYW5kbGVySWR9LiB1dWlkOiAke3JlbW92aW5nQ2xpZW50SWRlbnRpdHkudXVpZH0uIG5hbWU6ICR7cmVtb3ZpbmdDbGllbnRJZGVudGl0eS5uYW1lfS4gZW5kcG9pbnRJZDogJHtyZW1vdmluZ0NsaWVudElkZW50aXR5LmVuZHBvaW50SWR9YCk7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICBjb25zb2xlLndhcm4oYFRyeWluZyB0byByZW1vdmUgYSBoYW5kbGVyIGZyb20gYSBjbGllbnQgdGhhdCBpc24ndCBtYXBwZWQuIGhhbmRsZXJJZDogJHtoYW5kbGVySWR9LiB1dWlkOiAke3JlbW92aW5nQ2xpZW50SWRlbnRpdHkudXVpZH0uIG5hbWU6ICR7cmVtb3ZpbmdDbGllbnRJZGVudGl0eS5uYW1lfS4gZW5kcG9pbnRJZDogJHtyZW1vdmluZ0NsaWVudElkZW50aXR5LmVuZHBvaW50SWR9LmApO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIG5vblN0YW5kYXJkSGFuZGxlclJlbW92ZWQocGF5bG9hZCwgaWQpIHtcblx0ICAgICAgICBjb25zdCB7IGhhbmRsZXJJZCB9ID0gcGF5bG9hZDtcblx0ICAgICAgICBjb25zdCBjbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoaWQpO1xuXHQgICAgICAgIGlmIChjbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICBpZiAoY2xpZW50U3RhdGUub25EaXNjb25uZWN0SGFuZGxlcklkID09PSBoYW5kbGVySWQpIHtcblx0ICAgICAgICAgICAgICAgIGNsaWVudFN0YXRlLm9uRGlzY29ubmVjdEhhbmRsZXJJZCA9IHVuZGVmaW5lZDtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBlbHNlIGlmIChjbGllbnRTdGF0ZS5vbkFkZENvbnRleHRMaXN0ZW5lckhhbmRsZXJJZCA9PT0gaGFuZGxlcklkKSB7XG5cdCAgICAgICAgICAgICAgICBjbGllbnRTdGF0ZS5vbkFkZENvbnRleHRMaXN0ZW5lckhhbmRsZXJJZCA9IHVuZGVmaW5lZDtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBlbHNlIGlmIChjbGllbnRTdGF0ZS5vblVuc3Vic2NyaWJlSGFuZGxlcklkID09PSBoYW5kbGVySWQpIHtcblx0ICAgICAgICAgICAgICAgIGNsaWVudFN0YXRlLm9uVW5zdWJzY3JpYmVIYW5kbGVySWQgPSB1bmRlZmluZWQ7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUud2FybihgVHJ5aW5nIHRvIHJlbW92ZSBhIGhhbmRsZXIgZnJvbSBhIGNsaWVudCB0aGF0IGlzbid0IG1hcHBlZC4gaGFuZGxlcklkOiAke2hhbmRsZXJJZH0uIGNsaWVudElkZW50aXR5OiAke2lkfWApO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIG9uQWRkQ29udGV4dEhhbmRsZXJBZGRlZChwYXlsb2FkLCBzZW5kZXJDbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShzZW5kZXJDbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgY29uc3QgeyBoYW5kbGVySWQgfSA9IHBheWxvYWQ7XG5cdCAgICAgICAgaWYgKCFjbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsaWVudCB3aXRoIElkZW50aXR5OiAke3NlbmRlckNsaWVudElkZW50aXR5LnV1aWR9ICR7c2VuZGVyQ2xpZW50SWRlbnRpdHkubmFtZX0sIHRyaWVkIHRvIGNhbGwgb25BZGRDb250ZXh0TGlzdGVuZXIsIGlzIG5vdCBjb25uZWN0ZWQgdG8gdGhpcyBQcml2YXRlIENoYW5uZWxgKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2xpZW50U3RhdGUub25BZGRDb250ZXh0TGlzdGVuZXJIYW5kbGVySWQgPSBoYW5kbGVySWQ7XG5cdCAgICAgICAgLy8gRkRDMyBTcGVjIHNheXMgdGhhdCB0aGUgYWRkZWQgbGlzdGVuZXIgc2hvdWxkIGZpcmUgZm9yIGFsbCBwcmV2aW91c2x5LXJlZ2lzdGVyZWQgYWRkQ29udGV4dExpc3RlbmVycyBmcm9tIHRoZSBvdGhlciBjbGllbnRcblx0ICAgICAgICBBcnJheS5mcm9tKHRoaXMuY2xpZW50cy52YWx1ZXMoKSkuZm9yRWFjaCgob3RoZXJDbGllbnRTdGF0ZSkgPT4ge1xuXHQgICAgICAgICAgICBpZiAob3RoZXJDbGllbnRTdGF0ZS5jbGllbnRJZGVudGl0eS5lbmRwb2ludElkICE9PSBzZW5kZXJDbGllbnRJZGVudGl0eS5lbmRwb2ludElkKSB7XG5cdCAgICAgICAgICAgICAgICBBcnJheS5mcm9tKG90aGVyQ2xpZW50U3RhdGUuaGFuZGxlcklkc0J5Q29udGV4dFR5cGVzLmtleXMoKSkuZm9yRWFjaCgoc3Vic2NyaWJlZENvbnRleHRUeXBlKSA9PiB7XG5cdCAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm92aWRlci5kaXNwYXRjaChzZW5kZXJDbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBzdWJzY3JpYmVkQ29udGV4dFR5cGUpO1xuXHQgICAgICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIG9uRGlzY29ubmVjdEhhbmRsZXJBZGRlZChwYXlsb2FkLCBpZCkge1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShpZCk7XG5cdCAgICAgICAgY29uc3QgeyBoYW5kbGVySWQgfSA9IHBheWxvYWQ7XG5cdCAgICAgICAgaWYgKCFjbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsaWVudCB3aXRoIElkZW50aXR5OiAke2lkLnV1aWR9ICR7aWQubmFtZX0sIHRyaWVkIHRvIGNhbGwgb25EaXNjb25uZWN0LCBpcyBub3QgY29ubmVjdGVkIHRvIHRoaXMgUHJpdmF0ZSBDaGFubmVsYCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNsaWVudFN0YXRlLm9uRGlzY29ubmVjdEhhbmRsZXJJZCA9IGhhbmRsZXJJZDtcblx0ICAgIH1cblx0ICAgIG9uVW5zdWJzY3JpYmVIYW5kbGVyQWRkZWQocGF5bG9hZCwgaWQpIHtcblx0ICAgICAgICBjb25zdCBjbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoaWQpO1xuXHQgICAgICAgIGNvbnN0IHsgaGFuZGxlcklkIH0gPSBwYXlsb2FkO1xuXHQgICAgICAgIGlmICghY2xpZW50U3RhdGUpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDbGllbnQgd2l0aCBJZGVudGl0eTogJHtpZC51dWlkfSAke2lkLm5hbWV9LCB0cmllZCB0byBjYWxsIG9uVW5zdWJzY3JpYmUsIGlzIG5vdCBjb25uZWN0ZWQgdG8gdGhpcyBQcml2YXRlIENoYW5uZWxgKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2xpZW50U3RhdGUub25VbnN1YnNjcmliZUhhbmRsZXJJZCA9IGhhbmRsZXJJZDtcblx0ICAgIH1cblx0ICAgIHJlbW92ZUNsaWVudChkaXNjb25uZWN0aW5nQ2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCBkaXNjb25uZWN0aW5nQ2xpZW50U3RhdGUgPSB0aGlzLmdldENsaWVudFN0YXRlKGRpc2Nvbm5lY3RpbmdDbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKCFkaXNjb25uZWN0aW5nQ2xpZW50U3RhdGUpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDbGllbnQgd2l0aCBJZGVudGl0eTogJHtkaXNjb25uZWN0aW5nQ2xpZW50SWRlbnRpdHkudXVpZH0gJHtkaXNjb25uZWN0aW5nQ2xpZW50SWRlbnRpdHkubmFtZX0sIHRyaWVkIHRvIGNhbGwgZGlzY29ubmVjdCwgaXMgbm90IGNvbm5lY3RlZCB0byB0aGlzIFByaXZhdGUgQ2hhbm5lbGApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBkaXNjb25uZWN0aW5nQ2xpZW50U3RhdGUuaGFuZGxlcklkc0J5Q29udGV4dFR5cGVzLmNsZWFyKCk7XG5cdCAgICAgICAgdGhpcy5jbGllbnRzLmRlbGV0ZShkaXNjb25uZWN0aW5nQ2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZCk7XG5cdCAgICB9XG5cdCAgICBhc3luYyBmaXJlT25EaXNjb25uZWN0Rm9yT3RoZXJDbGllbnRzKGRpc2Nvbm5lY3RpbmdDbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIC8vIFRPRE86IGNhbGwgb25EaXNjb25uZWN0IEhhbmRsZXIgb2YgdGhlIG90aGVyIGNsaWVudCBvbmx5LlxuXHQgICAgICAgIC8vIENVUlJFTlRMWSwganVzdCBjYWxsaW5nIHRoZSBvbkRpc2Nvbm5lY3QgaGFuZGxlciBmb3IgYWxsIHRoZSBvdGhlciBjbGllbnRzLiBPbmNlIHdlIGxpbWl0IGl0IHRvIGp1c3Qgb25lIG90aGVyIGNsaWVudCwgd2UgY2FuIGVsaW1pbmF0ZSBhbGwgdGhlIGl0ZXJhdGlvbiBjb2RlLlxuXHQgICAgICAgIGNvbnN0IHsgZW5kcG9pbnRJZCB9ID0gZGlzY29ubmVjdGluZ0NsaWVudElkZW50aXR5O1xuXHQgICAgICAgIC8vIGdldHRpbmcgb25seSB2YWxpZCBjbGllbnQgY29ubmVjdGlvbnMgaGVyZSwgaXQgaXMgcG9zc2libGUgd2UgaGF2ZW4ndCByZW1vdmVkIGEgZGlzY29ubmVjdGVkIGNsaWVudCBmcm9tIHRoZSBtYXAgeWV0XG5cdCAgICAgICAgLy8gc28gd2UgbmVlZCB0byBlbnN1cmUgd2UgZG9uJ3QgZGlzcGF0Y2ggdG8gYW55IGRpc2Nvbm5lY3RlZCBjbGllbnRcblx0ICAgICAgICAvLyBUT0RPOiBUYWtlIGEgbG9vayBhdCBvdXIgY2xpZW50IGRpc2Nvbm5lY3Rpb24gbG9naWMgYW5kIHNlZSBpZiB3ZSBjYW4gaGFuZGxlIGNsaWVudCBkaXNjb25uZWN0aW9uIGNsZWFubHlcblx0ICAgICAgICBjb25zdCBjbGllbnRzVG9EaXNwYXRjaFRvID0gYXdhaXQgdGhpcy5nZXRDb25uZWN0ZWRDbGllbnRzKCk7XG5cdCAgICAgICAgY29uc3QgZGlzcGF0Y2hQcm9taXNlcyA9IGNsaWVudHNUb0Rpc3BhdGNoVG8ubWFwKGFzeW5jIChvdGhlckNsaWVudFN0YXRlKSA9PiB7XG5cdCAgICAgICAgICAgIGNvbnN0IHsgY2xpZW50SWRlbnRpdHk6IHsgZW5kcG9pbnRJZDogb3RoZXJDbGllbnRFbmRwb2ludElkIH0sIG9uRGlzY29ubmVjdEhhbmRsZXJJZCB9ID0gb3RoZXJDbGllbnRTdGF0ZTtcblx0ICAgICAgICAgICAgaWYgKG90aGVyQ2xpZW50RW5kcG9pbnRJZCAhPT0gZW5kcG9pbnRJZCAmJiBvbkRpc2Nvbm5lY3RIYW5kbGVySWQpIHtcblx0ICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMucHJvdmlkZXIuZGlzcGF0Y2gob3RoZXJDbGllbnRTdGF0ZS5jbGllbnRJZGVudGl0eSwgb25EaXNjb25uZWN0SGFuZGxlcklkKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKGRpc3BhdGNoUHJvbWlzZXMpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc29sZS5lcnJvcihgUHJvYmxlbSB3aGVuIGF0dGVtcHRpbmcgdG8gZGlzcGF0Y2ggdG8gb25EaXNjb25uZWN0SGFuZGxlcnMuIEVycm9yOiAke2Vycm9yfSBEaXNjb25uZWN0aW5nIENsaWVudDogdXVpZDogJHtkaXNjb25uZWN0aW5nQ2xpZW50SWRlbnRpdHkudXVpZH0uIG5hbWU6ICR7ZGlzY29ubmVjdGluZ0NsaWVudElkZW50aXR5Lm5hbWV9LiBlbmRwb2ludElkOiAke2Rpc2Nvbm5lY3RpbmdDbGllbnRJZGVudGl0eS5lbmRwb2ludElkfWApO1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIGFzeW5jIHVuc3Vic2NyaWJlQWxsKGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgY29uc3QgeyBlbmRwb2ludElkIH0gPSBjbGllbnRJZGVudGl0eTtcblx0ICAgICAgICBjb25zdCBzdGF0ZSA9IHRoaXMuY2xpZW50cy5nZXQoZW5kcG9pbnRJZCk7XG5cdCAgICAgICAgaWYgKHN0YXRlKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGNvbnRleHRUeXBlSGFuZGxlcklkcyA9IEFycmF5LmZyb20oc3RhdGUuaGFuZGxlcklkc0J5Q29udGV4dFR5cGVzLnZhbHVlcygpKS5mbGF0KCk7XG5cdCAgICAgICAgICAgIGNvbnN0IGdsb2JhbEhhbmRsZXJJZCA9IHN0YXRlLmdsb2JhbEhhbmRsZXI7XG5cdCAgICAgICAgICAgIGlmIChjb250ZXh0VHlwZUhhbmRsZXJJZHMubGVuZ3RoID4gMCkge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgdW5zdWJQcm9taXNlcyA9IGNvbnRleHRUeXBlSGFuZGxlcklkcy5tYXAoYXN5bmMgKGhhbmRsZXJJZCkgPT4ge1xuXHQgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRleHRIYW5kbGVyUmVtb3ZlZCh7IGhhbmRsZXJJZCB9LCBjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgICAgICAgICB9KTtcblx0ICAgICAgICAgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwodW5zdWJQcm9taXNlcyk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yLm1lc3NhZ2UpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGlmIChnbG9iYWxIYW5kbGVySWQpIHtcblx0ICAgICAgICAgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5jb250ZXh0SGFuZGxlclJlbW92ZWQoeyBoYW5kbGVySWQ6IGdsb2JhbEhhbmRsZXJJZCB9LCBjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yLm1lc3NhZ2UpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgYXN5bmMgaGFuZGxlQ2xpZW50RGlzY29ubmVjdGluZyhkaXNjb25uZWN0aW5nQ2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBhd2FpdCB0aGlzLnVuc3Vic2NyaWJlQWxsKGRpc2Nvbm5lY3RpbmdDbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgdGhpcy5yZW1vdmVDbGllbnQoZGlzY29ubmVjdGluZ0NsaWVudElkZW50aXR5KTtcblx0ICAgICAgICBhd2FpdCB0aGlzLmZpcmVPbkRpc2Nvbm5lY3RGb3JPdGhlckNsaWVudHMoZGlzY29ubmVjdGluZ0NsaWVudElkZW50aXR5KTtcblx0ICAgIH1cblx0ICAgIHJlZ2lzdGVyTmV3Q2xpZW50KGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgaWYgKCF0aGlzLmNsaWVudHMuaGFzKGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQpKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGNsaWVudFN1YnNjcmlwdGlvblN0YXRlID0ge1xuXHQgICAgICAgICAgICAgICAgY2xpZW50SWRlbnRpdHksXG5cdCAgICAgICAgICAgICAgICBoYW5kbGVySWRzQnlDb250ZXh0VHlwZXM6IG5ldyBNYXAoKSxcblx0ICAgICAgICAgICAgICAgIGdsb2JhbEhhbmRsZXI6IHVuZGVmaW5lZCxcblx0ICAgICAgICAgICAgICAgIG9uQWRkQ29udGV4dExpc3RlbmVySGFuZGxlcklkOiB1bmRlZmluZWQsXG5cdCAgICAgICAgICAgICAgICBvblVuc3Vic2NyaWJlSGFuZGxlcklkOiB1bmRlZmluZWQsXG5cdCAgICAgICAgICAgICAgICBvbkRpc2Nvbm5lY3RIYW5kbGVySWQ6IHVuZGVmaW5lZFxuXHQgICAgICAgICAgICB9O1xuXHQgICAgICAgICAgICB0aGlzLmNsaWVudHMuc2V0KGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQsIGNsaWVudFN1YnNjcmlwdGlvblN0YXRlKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICBhc3luYyBnZXRDb25uZWN0ZWRDbGllbnRzKCkge1xuXHQgICAgICAgIGNvbnN0IGFsbENsaWVudEluZm8gPSBhd2FpdCB0aGlzLnByb3ZpZGVyLmdldEFsbENsaWVudEluZm8oKTtcblx0ICAgICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLmNsaWVudHMudmFsdWVzKCkpLmZpbHRlcigoY2xpZW50U3RhdGUpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSBjbGllbnRTdGF0ZS5jbGllbnRJZGVudGl0eTtcblx0ICAgICAgICAgICAgcmV0dXJuIGFsbENsaWVudEluZm8uc29tZSgoY2xpZW50SW5mbykgPT4ge1xuXHQgICAgICAgICAgICAgICAgcmV0dXJuIG5hbWUgPT09IGNsaWVudEluZm8ubmFtZSAmJiB1dWlkID09PSBjbGllbnRJbmZvLnV1aWQ7XG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgc3RhdGljIGluaXQoY2hhbm5lbFByb3ZpZGVyLCBpZCkge1xuXHQgICAgICAgIHJldHVybiBuZXcgUHJpdmF0ZUNoYW5uZWxQcm92aWRlcihjaGFubmVsUHJvdmlkZXIsIGlkKTtcblx0ICAgIH1cblx0fTtcblx0UHJpdmF0ZUNoYW5uZWxQcm92aWRlci5Qcml2YXRlQ2hhbm5lbFByb3ZpZGVyID0gUHJpdmF0ZUNoYW5uZWxQcm92aWRlciQxO1xuXHRyZXR1cm4gUHJpdmF0ZUNoYW5uZWxQcm92aWRlcjtcbn1cblxudmFyIGhhc1JlcXVpcmVkSW50ZXJvcEJyb2tlcjtcblxuZnVuY3Rpb24gcmVxdWlyZUludGVyb3BCcm9rZXIgKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRJbnRlcm9wQnJva2VyKSByZXR1cm4gSW50ZXJvcEJyb2tlcjtcblx0aGFzUmVxdWlyZWRJbnRlcm9wQnJva2VyID0gMTtcblx0dmFyIF9fY2xhc3NQcml2YXRlRmllbGRTZXQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcblx0ICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcblx0ICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcblx0ICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG5cdCAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcblx0fTtcblx0dmFyIF9fY2xhc3NQcml2YXRlRmllbGRHZXQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuXHQgICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuXHQgICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG5cdCAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xuXHR9O1xuXHR2YXIgX19pbXBvcnREZWZhdWx0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9faW1wb3J0RGVmYXVsdCkgfHwgZnVuY3Rpb24gKG1vZCkge1xuXHQgICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBcImRlZmF1bHRcIjogbW9kIH07XG5cdH07XG5cdHZhciBfSW50ZXJvcEJyb2tlcl9mZGMzSW5mbywgX0ludGVyb3BCcm9rZXJfY29udGV4dEdyb3VwcywgX0ludGVyb3BCcm9rZXJfcHJvdmlkZXJQcm9taXNlO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoSW50ZXJvcEJyb2tlciwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdEludGVyb3BCcm9rZXIuSW50ZXJvcEJyb2tlciA9IHZvaWQgMDtcblx0Y29uc3QgYmFzZV8xID0gYmFzZTtcblx0Y29uc3QgU2Vzc2lvbkNvbnRleHRHcm91cEJyb2tlcl8xID0gX19pbXBvcnREZWZhdWx0KHJlcXVpcmVTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyKCkpO1xuXHRjb25zdCB1dGlsc18xID0gdXRpbHMkMztcblx0Y29uc3QgaXNFcXVhbF8xID0gX19pbXBvcnREZWZhdWx0KHJlcXVpcmUkJDMpO1xuXHRjb25zdCBQcml2YXRlQ2hhbm5lbFByb3ZpZGVyXzEgPSByZXF1aXJlUHJpdmF0ZUNoYW5uZWxQcm92aWRlcigpO1xuXHRjb25zdCBsYXp5XzEgPSBsYXp5O1xuXHRjb25zdCBkZWZhdWx0Q29udGV4dEdyb3VwcyA9IFtcblx0ICAgIHtcblx0ICAgICAgICBpZDogJ2dyZWVuJyxcblx0ICAgICAgICBkaXNwbGF5TWV0YWRhdGE6IHtcblx0ICAgICAgICAgICAgY29sb3I6ICcjMDBDQzg4Jyxcblx0ICAgICAgICAgICAgbmFtZTogJ2dyZWVuJ1xuXHQgICAgICAgIH1cblx0ICAgIH0sXG5cdCAgICB7XG5cdCAgICAgICAgaWQ6ICdwdXJwbGUnLFxuXHQgICAgICAgIGRpc3BsYXlNZXRhZGF0YToge1xuXHQgICAgICAgICAgICBjb2xvcjogJyM4QzYxRkYnLFxuXHQgICAgICAgICAgICBuYW1lOiAncHVycGxlJ1xuXHQgICAgICAgIH1cblx0ICAgIH0sXG5cdCAgICB7XG5cdCAgICAgICAgaWQ6ICdvcmFuZ2UnLFxuXHQgICAgICAgIGRpc3BsYXlNZXRhZGF0YToge1xuXHQgICAgICAgICAgICBjb2xvcjogJyNGRjhDNEMnLFxuXHQgICAgICAgICAgICBuYW1lOiAnb3JhbmdlJ1xuXHQgICAgICAgIH1cblx0ICAgIH0sXG5cdCAgICB7XG5cdCAgICAgICAgaWQ6ICdyZWQnLFxuXHQgICAgICAgIGRpc3BsYXlNZXRhZGF0YToge1xuXHQgICAgICAgICAgICBjb2xvcjogJyNGRjVFNjAnLFxuXHQgICAgICAgICAgICBuYW1lOiAncmVkJ1xuXHQgICAgICAgIH1cblx0ICAgIH0sXG5cdCAgICB7XG5cdCAgICAgICAgaWQ6ICdwaW5rJyxcblx0ICAgICAgICBkaXNwbGF5TWV0YWRhdGE6IHtcblx0ICAgICAgICAgICAgY29sb3I6ICcjRkY4RkI4Jyxcblx0ICAgICAgICAgICAgbmFtZTogJ3BpbmsnXG5cdCAgICAgICAgfVxuXHQgICAgfSxcblx0ICAgIHtcblx0ICAgICAgICBpZDogJ3llbGxvdycsXG5cdCAgICAgICAgZGlzcGxheU1ldGFkYXRhOiB7XG5cdCAgICAgICAgICAgIGNvbG9yOiAnI0U5RkY4RicsXG5cdCAgICAgICAgICAgIG5hbWU6ICd5ZWxsb3cnXG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHRdO1xuXHQvKipcblx0ICoge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL29mLWRvY3MvZG9jcy9lbmFibGUtY29sb3ItbGlua2luZ31cblx0ICpcblx0ICogVGhlIEludGVyb3AgQnJva2VyIGlzIHJlc3BvbnNpYmxlIGZvciBrZWVwaW5nIHRyYWNrIG9mIHRoZSBJbnRlcm9wIHN0YXRlIG9mIHRoZSBQbGF0Zm9ybSwgYW5kIGZvciBkaXJlY3RpbmcgbWVzc2FnZXMgdG8gdGhlIHByb3BlciBsb2NhdGlvbnMuXG5cdCAqXG5cdCAqIEByZW1hcmtzIFRoaXMgY2xhc3MgY29udGFpbnMgc29tZSB0eXBlcyByZWxhdGVkIHRvIEZEQzMgdGhhdCBhcmUgc3BlY2lmaWMgdG8gT3BlbkZpbi4ge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVycy5vcGVuZmluLmNvL29mLWRvY3MvZG9jcy9mZGMzLXN1cHBvcnQtaW4tb3BlbmZpbiBPcGVuRmluJ3MgRkRDMyBzdXBwb3J0fSBpcyBmb3J3YXJkLSBhbmQgYmFja3dhcmQtY29tcGF0aWJsZS5cblx0ICogU3RhbmRhcmQgdHlwZXMgZm9yIHtAbGluayBodHRwczovL2ZkYzMuZmlub3Mub3JnLyBGREMzfSBkbyBub3QgYXBwZWFyIGluIE9wZW5GaW7igJlzIEFQSSBkb2N1bWVudGF0aW9uLCB0byBhdm9pZCBkdXBsaWNhdGlvbi5cblx0ICpcblx0ICogLS0tXG5cdCAqXG5cdCAqIFRoZXJlIGFyZSAyIHdheXMgdG8gaW5qZWN0IGN1c3RvbSBmdW5jdGlvbmFsaXR5IGludG8gdGhlIEludGVyb3AgQnJva2VyOlxuXHQgKlxuXHQgKiAqKjEuIENvbmZpZ3VyYXRpb24qKlxuXHQgKlxuXHQgKiBBdCB0aGUgbW9tZW50LCB5b3UgY2FuIGNvbmZpZ3VyZSB0aGUgZGVmYXVsdCBjb250ZXh0IGdyb3VwcyBmb3IgdGhlIEludGVyb3AgQnJva2VyIHdpdGhvdXQgaGF2aW5nIHRvIG92ZXJyaWRlIGl0LiBUbyBkbyBzbywgaW5jbHVkZSB0aGUgYGludGVyb3BCcm9rZXJDb25maWd1cmF0aW9uYCBgY29udGV4dEdyb3Vwc2Agb3B0aW9uIGluIHlvdXIgYHBsYXRmb3JtYCBvcHRpb25zIGluIHlvdXIgbWFuaWZlc3QuIFRoaXMgaXMgdGhlIHByZWZlcnJlZCBtZXRob2QuXG5cdCAqIGBgYGpzXG5cdCAqIHtcblx0ICogICAgICBcInJ1bnRpbWVcIjoge1xuXHQgKiAgICAgICAgICBcImFyZ3VtZW50c1wiOiBcIi0tdj0xIC0taW5zcGVjdFwiLFxuXHQgKiAgICAgICAgICBcInZlcnNpb25cIjogXCJhbHBoYS12MTlcIlxuXHQgKiAgICAgIH0sXG5cdCAqICAgICAgXCJwbGF0Zm9ybVwiOiB7XG5cdCAqICAgICAgICAgIFwidXVpZFwiOiBcInBsYXRmb3JtX2N1c3RvbWl6YXRpb25fbG9jYWxcIixcblx0ICogICAgICAgICAgXCJhcHBsaWNhdGlvbkljb25cIjogXCJodHRwczovL29wZW5maW4uZ2l0aHViLmlvL2dvbGRlbi1wcm90b3R5cGUvZmF2aWNvbi5pY29cIixcblx0ICogICAgICAgICAgXCJhdXRvU2hvd1wiOiBmYWxzZSxcblx0ICogICAgICAgICAgXCJwcm92aWRlclVybFwiOiBcImh0dHA6Ly9sb2NhbGhvc3Q6NTU1NS9wcm92aWRlci5odG1sXCIsXG5cdCAqICAgICAgICAgIFwiaW50ZXJvcEJyb2tlckNvbmZpZ3VyYXRpb25cIjoge1xuXHQgKiAgICAgICAgICAgICAgXCJjb250ZXh0R3JvdXBzXCI6IFtcblx0ICogICAgICAgICAgICAgICAgICB7XG5cdCAqICAgICAgICAgICAgICAgICAgICAgIFwiaWRcIjogXCJncmVlblwiLFxuXHQgKiAgICAgICAgICAgICAgICAgICAgICBcImRpc3BsYXlNZXRhZGF0YVwiOiB7XG5cdCAqICAgICAgICAgICAgICAgICAgICAgICAgICBcImNvbG9yXCI6IFwiIzAwQ0M4OFwiLFxuXHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgXCJuYW1lXCI6IFwiZ3JlZW5cIlxuXHQgKiAgICAgICAgICAgICAgICAgICAgICB9XG5cdCAqICAgICAgICAgICAgICAgICAgfSxcblx0ICogICAgICAgICAgICAgICAgICB7XG5cdCAqICAgICAgICAgICAgICAgICAgICAgIFwiaWRcIjogXCJwdXJwbGVcIixcblx0ICogICAgICAgICAgICAgICAgICAgICAgXCJkaXNwbGF5TWV0YWRhdGFcIjoge1xuXHQgKiAgICAgICAgICAgICAgICAgICAgICAgICAgXCJjb2xvclwiOiBcIiM4QzYxRkZcIixcblx0ICogICAgICAgICAgICAgICAgICAgICAgICAgIFwibmFtZVwiOiBcInB1cnBsZVwiXG5cdCAqICAgICAgICAgICAgICAgICAgICAgIH1cblx0ICogICAgICAgICAgICAgICAgICB9LFxuXHQgKiAgICAgICAgICAgICAgXVxuXHQgKiAgICAgICAgICB9XG5cdCAqICAgICAgfVxuXHQgKiB9XG5cdCAqIGBgYFxuXHQgKlxuXHQgKiBCeSBkZWZhdWx0IHRoZSBJbnRlcm9wIEJyb2tlciBsb2dzIGFsbCBhY3Rpb25zIHRvIHRoZSBjb25zb2xlLiBZb3UgY2FuIGRpc2FibGUgdGhpcyBieSB1c2luZyB0aGUgbG9nZ2luZyBvcHRpb24gaW4gYGludGVyb3BCcm9rZXJDb25maWd1cmF0aW9uYDpcblx0ICogYGBganNcblx0ICoge1xuXHQgKiAgICAgIFwicnVudGltZVwiOiB7XG5cdCAqICAgICAgICAgIFwiYXJndW1lbnRzXCI6IFwiLS12PTEgLS1pbnNwZWN0XCIsXG5cdCAqICAgICAgICAgIFwidmVyc2lvblwiOiBcImFscGhhLXYxOVwiXG5cdCAqICAgICAgfSxcblx0ICogICAgICBcInBsYXRmb3JtXCI6IHtcblx0ICogICAgICAgICAgXCJ1dWlkXCI6IFwicGxhdGZvcm1fY3VzdG9taXphdGlvbl9sb2NhbFwiLFxuXHQgKiAgICAgICAgICBcImFwcGxpY2F0aW9uSWNvblwiOiBcImh0dHBzOi8vb3BlbmZpbi5naXRodWIuaW8vZ29sZGVuLXByb3RvdHlwZS9mYXZpY29uLmljb1wiLFxuXHQgKiAgICAgICAgICBcImF1dG9TaG93XCI6IGZhbHNlLFxuXHQgKiAgICAgICAgICBcInByb3ZpZGVyVXJsXCI6IFwiaHR0cDovL2xvY2FsaG9zdDo1NTU1L3Byb3ZpZGVyLmh0bWxcIixcblx0ICpcdFx0ICAgIFwiaW50ZXJvcEJyb2tlckNvbmZpZ3VyYXRpb25cIjoge1xuXHQgKiAgICAgICBcdFx0XCJsb2dnaW5nXCI6IHtcblx0ICogICBcdFx0XHRcdFwiYmVmb3JlQWN0aW9uXCI6IHtcblx0ICogICBcdFx0XHRcdFx0XCJlbmFibGVkXCI6IGZhbHNlXG5cdCAqICAgXHRcdFx0XHR9LFxuXHQgKiAgIFx0XHRcdFx0XCJhZnRlckFjdGlvblwiOiB7XG5cdCAqICAgXHRcdFx0XHRcdFwiZW5hYmxlZFwiOiBmYWxzZVxuXHQgKiAgIFx0XHRcdFx0fVxuXHQgKiAgIFx0XHRcdH1cblx0ICpcdFx0ICAgIH1cblx0ICogICAgICB9XG5cdCAqIH1cblx0ICogYGBgXG5cdCAqXG5cdCAqIC0tLVxuXHQgKiAqKjIuIE92ZXJyaWRpbmcqKlxuXHQgKlxuXHQgKiBTaW1pbGFybHkgdG8gaG93IHtAbGluayBodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9kb2NzL3BsYXRmb3JtLWN1c3RvbWl6YXRpb24jc2VjdGlvbi1jdXN0b21pemluZy1wbGF0Zm9ybS1iZWhhdmlvciBQbGF0Zm9ybSBPdmVycmlkaW5nfSB3b3JrcywgeW91IGNhbiBvdmVycmlkZSBmdW5jdGlvbnMgaW4gdGhlIEludGVyb3AgQnJva2VyIGluIGBmaW4uUGxhdGZvcm0uaW5pdGAuIEFuIGV4YW1wbGUgb2YgdGhhdCBpcyBzaG93biBiZWxvdy4gT3ZlcnJpZGluZyBgaXNDb25uZWN0aW9uQXV0aG9yaXplZGAgYW5kIGBpc0FjdGlvbkF1dGhvcml6ZWRgIHdpbGwgYWxsb3cgeW91IHRvIGNvbnRyb2wgYWxsb3dlZCBjb25uZWN0aW9ucyBhbmQgYWxsb3dlZCBhY3Rpb25zLlxuXHQgKlxuXHQgKiBIb3dldmVyLCBpZiB0aGVyZSBpcyBjdXN0b20gZnVuY3Rpb25hbGl0eSB5b3Ugd2lzaCB0byBpbmNsdWRlIGluIHRoZSBJbnRlcm9wIEJyb2tlciwgcGxlYXNlIGxldCB1cyBrbm93LiBXZSB3b3VsZCBsaWtlIHRvIHByb3ZpZGUgYmV0dGVyIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBzbyB0aGF0IHlvdSBkb24ndCBoYXZlIHRvIGNvbnRpbnVhbGx5IG1haW50YWluIHlvdXIgb3duIG92ZXJyaWRlIGNvZGUuXG5cdCAqXG5cdCAqIGBgYGpzXG5cdCAqIGZpbi5QbGF0Zm9ybS5pbml0KHtcblx0ICogICAgIG92ZXJyaWRlQ2FsbGJhY2s6IGFzeW5jIChQcm92aWRlcikgPT4ge1xuXHQgKiAgICAgICAgIGNsYXNzIE92ZXJyaWRlIGV4dGVuZHMgUHJvdmlkZXIge1xuXHQgKiAgICAgICAgICAgICBhc3luYyBnZXRTbmFwc2hvdCgpIHtcblx0ICogICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdiZWZvcmUgZ2V0U25hcHNob3QnKVxuXHQgKiAgICAgICAgICAgICAgICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCBzdXBlci5nZXRTbmFwc2hvdCgpO1xuXHQgKiAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ2FmdGVyIGdldFNuYXBzaG90Jylcblx0ICogICAgICAgICAgICAgICAgIHJldHVybiBzbmFwc2hvdDtcblx0ICogICAgICAgICAgICAgfVxuXHQgKlxuXHQgKiAgICAgICAgICAgICBhc3luYyBhcHBseVNuYXBzaG90KHsgc25hcHNob3QsIG9wdGlvbnMgfSkge1xuXHQgKiAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ2JlZm9yZSBhcHBseVNuYXBzaG90Jylcblx0ICogICAgICAgICAgICAgICAgIGNvbnN0IG9yaWdpbmFsUHJvbWlzZSA9IHN1cGVyLmFwcGx5U25hcHNob3QoeyBzbmFwc2hvdCwgb3B0aW9ucyB9KTtcblx0ICogICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdhZnRlciBhcHBseVNuYXBzaG90Jylcblx0ICpcblx0ICogICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbFByb21pc2U7XG5cdCAqICAgICAgICAgICAgIH1cblx0ICogICAgICAgICB9O1xuXHQgKiAgICAgICAgIHJldHVybiBuZXcgT3ZlcnJpZGUoKTtcblx0ICogICAgIH0sXG5cdCAqICAgICBpbnRlcm9wT3ZlcnJpZGU6IGFzeW5jIChJbnRlcm9wQnJva2VyKSA9PiB7XG5cdCAqICAgICAgICAgY2xhc3MgT3ZlcnJpZGUgZXh0ZW5kcyBJbnRlcm9wQnJva2VyIHtcblx0ICogICAgICAgICAgICAgYXN5bmMgam9pbkNvbnRleHRHcm91cChjaGFubmVsTmFtZSA9ICdkZWZhdWx0JywgdGFyZ2V0KSB7XG5cdCAqICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnYmVmb3JlIHN1cGVyIGpvaW5Db250ZXh0R3JvdXAnKVxuXHQgKiAgICAgICAgICAgICAgICAgc3VwZXIuam9pbkNvbnRleHRHcm91cChjaGFubmVsTmFtZSwgdGFyZ2V0KTtcblx0ICogICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdhZnRlciBzdXBlciBqb2luQ29udGV4dEdyb3VwJylcblx0ICogICAgICAgICAgICAgfVxuXHQgKiAgICAgICAgIH1cblx0ICpcblx0ICogICAgICAgcmV0dXJuIG5ldyBPdmVycmlkZSgpO1xuXHQgKiAgIH1cblx0ICogfSk7XG5cdCAqIGBgYFxuXHQgKlxuXHQgKiAtLS1cblx0ICpcblx0ICovXG5cdGxldCBJbnRlcm9wQnJva2VyJDEgPSBjbGFzcyBJbnRlcm9wQnJva2VyIGV4dGVuZHMgYmFzZV8xLkJhc2Uge1xuXHQgICAgLyoqXG5cdCAgICAgKiBAaW50ZXJuYWxcblx0ICAgICAqL1xuXHQgICAgY29uc3RydWN0b3Iod2lyZSwgY3JlYXRlUHJvdmlkZXIsIG9wdGlvbnMpIHtcblx0ICAgICAgICAvLyBUaXAgZnJvbSBQaWVycmUgYW5kIE1pY2hhZWwgZnJvbSB0aGUgb3ZlcnJpZGVDaGVjayB3b3JrOiBEb24ndCB1c2UgYm91bmQgbWV0aG9kcyBmb3Igb3ZlcnJpZGVhYmxlIEludGVyb3BCcm9rZXIgZnVuY3Rpb25zLlxuXHQgICAgICAgIHN1cGVyKHdpcmUpO1xuXHQgICAgICAgIF9JbnRlcm9wQnJva2VyX2ZkYzNJbmZvLnNldCh0aGlzLCB2b2lkIDApO1xuXHQgICAgICAgIF9JbnRlcm9wQnJva2VyX2NvbnRleHRHcm91cHMuc2V0KHRoaXMsIHZvaWQgMCk7XG5cdCAgICAgICAgX0ludGVyb3BCcm9rZXJfcHJvdmlkZXJQcm9taXNlLnNldCh0aGlzLCB2b2lkIDApO1xuXHQgICAgICAgIHRoaXMuZ2V0UHJvdmlkZXIgPSAoKSA9PiB7XG5cdCAgICAgICAgICAgIHJldHVybiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQnJva2VyX3Byb3ZpZGVyUHJvbWlzZSwgXCJmXCIpLmdldFZhbHVlKCk7XG5cdCAgICAgICAgfTtcblx0ICAgICAgICB0aGlzLmludGVyb3BDbGllbnRzID0gbmV3IE1hcCgpO1xuXHQgICAgICAgIHRoaXMuY29udGV4dEdyb3Vwc0J5SWQgPSBuZXcgTWFwKCk7XG5cdCAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfSW50ZXJvcEJyb2tlcl9jb250ZXh0R3JvdXBzLCBvcHRpb25zLmNvbnRleHRHcm91cHMgPz8gWy4uLmRlZmF1bHRDb250ZXh0R3JvdXBzXSwgXCJmXCIpO1xuXHQgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX0ludGVyb3BCcm9rZXJfZmRjM0luZm8sIG9wdGlvbnMuZmRjM0luZm8sIFwiZlwiKTtcblx0ICAgICAgICBpZiAob3B0aW9ucz8ubG9nZ2luZykge1xuXHQgICAgICAgICAgICB0aGlzLmxvZ2dpbmcgPSBvcHRpb25zLmxvZ2dpbmc7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHRoaXMuaW50ZW50Q2xpZW50TWFwID0gbmV3IE1hcCgpO1xuXHQgICAgICAgIHRoaXMubGFzdENvbnRleHRNYXAgPSBuZXcgTWFwKCk7XG5cdCAgICAgICAgdGhpcy5zZXNzaW9uQ29udGV4dEdyb3VwTWFwID0gbmV3IE1hcCgpO1xuXHQgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX0ludGVyb3BCcm9rZXJfcHJvdmlkZXJQcm9taXNlLCBuZXcgbGF6eV8xLkxhenkoY3JlYXRlUHJvdmlkZXIpLCBcImZcIik7XG5cdCAgICAgICAgdGhpcy5zZXRDb250ZXh0R3JvdXBNYXAoKTtcblx0ICAgICAgICB0aGlzLnNldHVwQ2hhbm5lbFByb3ZpZGVyKCk7XG5cdCAgICB9XG5cdCAgICBzdGF0aWMgY3JlYXRlQ2xvc2VkQ29uc3RydWN0b3IoLi4uYXJncykge1xuXHQgICAgICAgIHJldHVybiBjbGFzcyBPdmVycmlkZWFibGVCcm9rZXIgZXh0ZW5kcyBJbnRlcm9wQnJva2VyIHtcblx0ICAgICAgICAgICAgY29uc3RydWN0b3IoLi4udW51c2VkKSB7XG5cdCAgICAgICAgICAgICAgICBpZiAodW51c2VkLmxlbmd0aCkge1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnN0IFtfaWdub3JlMSwgaWdub3JlMiwgb3B0c10gPSB1bnVzZWQ7XG5cdCAgICAgICAgICAgICAgICAgICAgaWYgKG9wdHMgJiYgdHlwZW9mIG9wdHMgPT09ICdvYmplY3QnICYmICEoMCwgaXNFcXVhbF8xLmRlZmF1bHQpKG9wdHMsIGFyZ3NbMl0pKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignWW91IGhhdmUgbW9kaWZpZWQgdGhlIHBhcmFtZXRlcnMgb2YgdGhlIEludGVyb3BPdmVycmlkZSBjb25zdHJ1Y3Rvci4gVGhpcyBiZWhhdmlvciBpcyBkZXByZWNhdGVkIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gYSBmdXR1cmUgdmVyc2lvbi4gWW91IGNhbiBtb2RpZnkgdGhlc2Ugb3B0aW9ucyBpbiB5b3VyIG1hbmlmZXN0LiBQbGVhc2UgY29uc3VsdCBvdXIgSW50ZXJvcCBkb2NzIGZvciBndWlkYW5jZSBvbiBtaWdyYXRpbmcgdG8gdGhlIG5ldyBvdmVycmlkZSBzY2hlbWUuJyk7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKGFyZ3NbMF0sIGFyZ3NbMV0sIG9wdHMpO1xuXHQgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG5cdCAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG5cdCAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdZb3UgYXJlIGF0dGVtcHRpbmcgdG8gcGFzcyBhcmd1bWVudHMgdG8gdGhlIEludGVyb3BPdmVycmlkZSBjb25zdHJ1Y3Rvci4gVGhpcyBpcyBub3QgbmVjZXNzYXJ5LCBhbmQgdGhlc2UgcGFzc2VkIGFyZ3VtZW50cyB3aWxsIGJlIGlnbm9yZWQuIFlvdSBhcmUgbGlrZWx5IHVzaW5nIGFuIG9sZGVyIEludGVyb3BCcm9rZXIgb3ZlcnJpZGUgc2NoZW1lLiBQbGVhc2UgY29uc3VsdCBvdXIgSW50ZXJvcCBkb2NzIGZvciBndWlkYW5jZSBvbiBtaWdyYXRpbmcgdG8gdGhlIG5ldyBvdmVycmlkZSBzY2hlbWUuJyk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICBzdXBlciguLi5hcmdzKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH07XG5cdCAgICB9XG5cdCAgICAvKlxuXHQgICAgQ2xpZW50IEFQSVxuXHQgICAgKi9cblx0ICAgIC8qKlxuXHQgICAgICogU2V0cyBhIGNvbnRleHQgZm9yIHRoZSBjb250ZXh0IGdyb3VwIG9mIHRoZSBpbmNvbWluZyBjdXJyZW50IGVudGl0eS5cblx0ICAgICAqIEBwYXJhbSBzZXRDb250ZXh0T3B0aW9ucyAtIE5ldyBjb250ZXh0IHRvIHNldC5cblx0ICAgICAqIEBwYXJhbSBjbGllbnRJZGVudGl0eSAtIElkZW50aXR5IG9mIHRoZSBjbGllbnQgc2VuZGVyLlxuXHQgICAgICpcblx0ICAgICAqL1xuXHQgICAgc2V0Q29udGV4dCh7IGNvbnRleHQgfSwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItc2V0LWNvbnRleHQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGlmIChjbGllbnRTdGF0ZSAmJiBjbGllbnRTdGF0ZS5jb250ZXh0R3JvdXBJZCkge1xuXHQgICAgICAgICAgICBjb25zdCB7IGNvbnRleHRHcm91cElkIH0gPSBjbGllbnRTdGF0ZTtcblx0ICAgICAgICAgICAgdGhpcy5zZXRDb250ZXh0Rm9yR3JvdXAoeyBjb250ZXh0IH0sIGNvbnRleHRHcm91cElkKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSBpZiAoY2xpZW50U3RhdGUpIHtcblx0ICAgICAgICAgICAgLy8gQ2xpZW50IGhhcyBub3Qgam9pbmVkIGFueSBjb250ZXh0IGdyb3VwIGJlaGF2aW9yLlxuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBtdXN0IGpvaW4gYSBjb250ZXh0IGdyb3VwIGJlZm9yZSB5b3UgY2FuIHNldCBjb250ZXh0LicpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgLy8gVGhpcyBzaG91bGRuJ3QgZ2V0IGhpdC5cblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDbGllbnQgd2l0aCBJZGVudGl0eTogJHtjbGllbnRJZGVudGl0eS51dWlkfSAke2NsaWVudElkZW50aXR5Lm5hbWV9IG5vdCBpbiBDbGllbnQgU3RhdGUgTWFwYCk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTZXRzIGEgY29udGV4dCBmb3IgdGhlIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKiBAcGFyYW0gc2V0Q29udGV4dE9wdGlvbnMgLSBOZXcgY29udGV4dCB0byBzZXQuXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dEdyb3VwSWQgLSBDb250ZXh0IGdyb3VwIGlkLlxuXHQgICAgICpcblx0ICAgICAqL1xuXHQgICAgc2V0Q29udGV4dEZvckdyb3VwKHsgY29udGV4dCB9LCBjb250ZXh0R3JvdXBJZCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWJyb2tlci1zZXQtY29udGV4dC1mb3ItZ3JvdXAnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjb250ZXh0R3JvdXBTdGF0ZSA9IHRoaXMuY29udGV4dEdyb3Vwc0J5SWQuZ2V0KGNvbnRleHRHcm91cElkKTtcblx0ICAgICAgICBpZiAoIWNvbnRleHRHcm91cFN0YXRlKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIHNldCBjb250ZXh0IGZvciBjb250ZXh0IGdyb3VwIHRoYXQgaXNuJ3QgaW4gdGhlIGNvbnRleHQgZ3JvdXAgbWFwcGluZzogJHtjb250ZXh0R3JvdXBJZH0uYCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNvbnN0IGNvbnRleHRJbnRlZ3JpdHlDaGVja1Jlc3VsdCA9IEludGVyb3BCcm9rZXIuY2hlY2tDb250ZXh0SW50ZWdyaXR5KGNvbnRleHQpO1xuXHQgICAgICAgIGlmIChjb250ZXh0SW50ZWdyaXR5Q2hlY2tSZXN1bHQuaXNWYWxpZCA9PT0gZmFsc2UpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gc2V0IENvbnRleHQgLSBiYWQgQ29udGV4dC4gUmVhc29uOiAke2NvbnRleHRJbnRlZ3JpdHlDaGVja1Jlc3VsdC5yZWFzb259LiBDb250ZXh0OiAke0pTT04uc3RyaW5naWZ5KGNvbnRleHQpfWApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjb25zdCBicm9hZGNhc3RlZENvbnRleHRUeXBlID0gY29udGV4dC50eXBlO1xuXHQgICAgICAgIGNvbnRleHRHcm91cFN0YXRlLnNldChicm9hZGNhc3RlZENvbnRleHRUeXBlLCBjb250ZXh0KTtcblx0ICAgICAgICB0aGlzLmxhc3RDb250ZXh0TWFwLnNldChjb250ZXh0R3JvdXBJZCwgYnJvYWRjYXN0ZWRDb250ZXh0VHlwZSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50c0luU2FtZUNvbnRleHRHcm91cCA9IEFycmF5LmZyb20odGhpcy5pbnRlcm9wQ2xpZW50cy52YWx1ZXMoKSkuZmlsdGVyKChjb25uZWN0ZWRDbGllbnQpID0+IGNvbm5lY3RlZENsaWVudC5jb250ZXh0R3JvdXBJZCA9PT0gY29udGV4dEdyb3VwSWQpO1xuXHQgICAgICAgIGNsaWVudHNJblNhbWVDb250ZXh0R3JvdXAuZm9yRWFjaCgoY2xpZW50KSA9PiB7XG5cdCAgICAgICAgICAgIGZvciAoY29uc3QgWywgaGFuZGxlckluZm9dIG9mIGNsaWVudC5jb250ZXh0SGFuZGxlcnMpIHtcblx0ICAgICAgICAgICAgICAgIGlmIChJbnRlcm9wQnJva2VyLmlzQ29udGV4dFR5cGVDb21wYXRpYmxlKGJyb2FkY2FzdGVkQ29udGV4dFR5cGUsIGhhbmRsZXJJbmZvLmNvbnRleHRUeXBlKSkge1xuXHQgICAgICAgICAgICAgICAgICAgIHRoaXMuaW52b2tlQ29udGV4dEhhbmRsZXIoY2xpZW50LmNsaWVudElkZW50aXR5LCBoYW5kbGVySW5mby5oYW5kbGVySWQsIGNvbnRleHQpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEdldCBjdXJyZW50IGNvbnRleHQgZm9yIGEgY2xpZW50IHN1YnNjcmliZWQgdG8gYSBDb250ZXh0IEdyb3VwLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIEl0IHRha2VzIGFuIG9wdGlvbmFsIENvbnRleHQgVHlwZSBhcmd1bWVudCBhbmQgcmV0dXJucyB0aGUgbGFzdCBjb250ZXh0IG9mIHRoYXQgdHlwZS5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gZ2V0Q29udGV4dE9wdGlvbnMgLSBPcHRpb25zIGZvciBnZXR0aW5nIGNvbnRleHRcblx0ICAgICAqIEBwYXJhbSBjbGllbnRJZGVudGl0eSAtIElkZW50aXR5IG9mIHRoZSBjbGllbnQgc2VuZGVyLlxuXHQgICAgICpcblx0ICAgICAqL1xuXHQgICAgZ2V0Q3VycmVudENvbnRleHQoZ2V0Q3VycmVudENvbnRleHRPcHRpb25zLCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWJyb2tlci1nZXQtY3VycmVudC1jb250ZXh0JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50U3RhdGUgPSB0aGlzLmdldENsaWVudFN0YXRlKGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICBpZiAoIWNsaWVudFN0YXRlPy5jb250ZXh0R3JvdXBJZCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBtdXN0IGJlIGEgbWVtYmVyIG9mIGEgY29udGV4dCBncm91cCB0byBjYWxsIGdldEN1cnJlbnRDb250ZXh0Jyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNvbnN0IHsgY29udGV4dEdyb3VwSWQgfSA9IGNsaWVudFN0YXRlO1xuXHQgICAgICAgIGNvbnN0IGNvbnRleHRHcm91cFN0YXRlID0gdGhpcy5jb250ZXh0R3JvdXBzQnlJZC5nZXQoY29udGV4dEdyb3VwSWQpO1xuXHQgICAgICAgIGNvbnN0IGxhc3RDb250ZXh0VHlwZSA9IHRoaXMubGFzdENvbnRleHRNYXAuZ2V0KGNvbnRleHRHcm91cElkKTtcblx0ICAgICAgICBjb25zdCBjb250ZXh0VHlwZSA9IGdldEN1cnJlbnRDb250ZXh0T3B0aW9ucz8uY29udGV4dFR5cGUgPz8gbGFzdENvbnRleHRUeXBlO1xuXHQgICAgICAgIHJldHVybiBjb250ZXh0R3JvdXBTdGF0ZSAmJiBjb250ZXh0VHlwZSA/IGNvbnRleHRHcm91cFN0YXRlLmdldChjb250ZXh0VHlwZSkgOiB1bmRlZmluZWQ7XG5cdCAgICB9XG5cdCAgICAvKlxuXHQgICAgUGxhdGZvcm0gV2luZG93IEFQSXNcblx0ICAgICovXG5cdCAgICAvLyBqb2luQ29udGV4dEdyb3VwIGFuZCBhZGRDbGllbnRUb0NvbnRleHRHcm91cCBhcmUgc2VwYXJhdGUgZnVuY3Rpb25zIGhlcmUsIGZvciBlYXNpZXIgb3ZlcnJpZGVzIGFuZCBzZXBhcmF0aW9uIG9mIGNvbmNlcm5zLlxuXHQgICAgLy8gam9pbkNvbnRleHRHcm91cCBjaGVja3MgYWxsIGNvbm5lY3Rpb25zIGZvciBtYXRjaGluZyBpZGVudGl0aWVzLCBpbiBjYXNlIHdlIGhhdmUgbXVsdGlwbGUgY29ubmVjdGlvbiBmcm9tIGFuIGVudGl0eS5cblx0ICAgIC8qKlxuXHQgICAgICogSm9pbiBhbGwgY29ubmVjdGlvbnMgYXQgdGhlIGdpdmVuIGlkZW50aXR5IChvciBqdXN0IG9uZSBpZiBlbmRwb2ludElkIHByb3ZpZGVkKSB0byBjb250ZXh0IGdyb3VwIGBjb250ZXh0R3JvdXBJZGAuXG5cdCAgICAgKiBJZiBubyB0YXJnZXQgaXMgc3BlY2lmaWVkLCBpdCBhZGRzIHRoZSBzZW5kZXIgdG8gdGhlIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKiBqb2luQ29udGV4dEdyb3VwIGlzIHJlc3BvbnNpYmxlIGZvciBjaGVja2luZyBjb25uZWN0aW9ucyBhdCB0aGUgaW5jb21pbmcgaWRlbnRpdHkuIEl0IGNhbGxzIHtAbGluayBJbnRlcm9wQnJva2VyI2FkZENsaWVudFRvQ29udGV4dEdyb3VwIEludGVyb3BCcm9rZXIuYWRkQ2xpZW50VG9Db250ZXh0R3JvdXB9IHRvIGFjdHVhbGx5IGdyb3VwIHRoZSBjbGllbnQuXG5cdCAgICAgKiBVc2VkIGJ5IFBsYXRmb3JtIFdpbmRvd3MuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGpvaW5Db250ZXh0R3JvdXBPcHRpb25zIC0gSWQgb2YgdGhlIENvbnRleHQgR3JvdXAgYW5kIGlkZW50aXR5IG9mIHRoZSBlbnRpdHkgdG8gam9pbiB0byB0aGUgZ3JvdXAuXG5cdCAgICAgKiBAcGFyYW0gc2VuZGVySWRlbnRpdHkgLSBJZGVudGl0eSBvZiB0aGUgY2xpZW50IHNlbmRlci5cblx0ICAgICAqL1xuXHQgICAgYXN5bmMgam9pbkNvbnRleHRHcm91cCh7IGNvbnRleHRHcm91cElkLCB0YXJnZXQgfSwgc2VuZGVySWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItam9pbi1jb250ZXh0LWdyb3VwJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbkNvbnRleHRHcm91cE1hcC5oYXMoY29udGV4dEdyb3VwSWQpKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih1dGlsc18xLkJST0tFUl9FUlJPUlMuam9pblNlc3Npb25Db250ZXh0R3JvdXBXaXRoSm9pbkNvbnRleHRHcm91cCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmICh0YXJnZXQpIHtcblx0ICAgICAgICAgICAgLy8gSWYgYW4gZW5kcG9pbnRJZCBpcyBwcm92aWRlZCwgdXNlIHRoYXQuIFRoaXMgd2lsbCBsaWtlbHkgYmUgdXNlZCBieSBleHRlcm5hbCBhZGFwdGVycy5cblx0ICAgICAgICAgICAgaWYgKEludGVyb3BCcm9rZXIuaGFzRW5kcG9pbnRJZCh0YXJnZXQpKSB7XG5cdCAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmFkZENsaWVudFRvQ29udGV4dEdyb3VwKHsgY29udGV4dEdyb3VwSWQgfSwgdGFyZ2V0KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAvLyBTYW5pdHkgY2hlY2sgaGVyZSBpbiBjYXNlIGEgc2luZ2xlIGFwcCBoYXMgbXVsdGlwbGUgY29ubmVjdGlvbnNcblx0ICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IGFsbENvbm5lY3Rpb25zID0gdGhpcy5jaGFubmVsLmNvbm5lY3Rpb25zLmZpbHRlcigoeCkgPT4geC51dWlkID09PSB0YXJnZXQudXVpZCAmJiB4Lm5hbWUgPT09IHRhcmdldC5uYW1lKTtcblx0ICAgICAgICAgICAgICAgIGlmICghYWxsQ29ubmVjdGlvbnMubGVuZ3RoKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBHaXZlbiBJZGVudGl0eSAke3RhcmdldC51dWlkfSAke3RhcmdldC5uYW1lfSBpcyBub3QgY29ubmVjdGVkIHRvIHRoZSBJbnRlcm9wIEJyb2tlci5gKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIGlmIChhbGxDb25uZWN0aW9ucy5sZW5ndGggPiAxKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgLy8gU2hvdWxkIGZpZ3VyZSBvdXQgaG93IHdlIHdhbnQgdG8gaGFuZGxlIHRoaXMgc2l0dWF0aW9uLiBJbiB0aGUgbWVhbnRpbWUsIGp1c3QgY2hhbmdlIGNvbnRleHQgZ3JvdXAgZm9yIGFsbCBjb25uZWN0aW9ucy5cblx0ICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYE1vcmUgdGhhbiBvbmUgY29ubmVjdGlvbiBmb3VuZCBmb3IgaWRlbnRpdHkgJHt0YXJnZXQudXVpZH0gJHt0YXJnZXQubmFtZX1gKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIGNvbnN0IHByb21pc2VzID0gW107XG5cdCAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGNvbm5lY3Rpb24gb2YgYWxsQ29ubmVjdGlvbnMpIHtcblx0ICAgICAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKHRoaXMuYWRkQ2xpZW50VG9Db250ZXh0R3JvdXAoeyBjb250ZXh0R3JvdXBJZCB9LCBjb25uZWN0aW9uKSk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICAvLyBObyB0YXJnZXQgcHJvdmlkZWQsIGFkZCB0aGUgc2VuZGVyIHRvIHRoZSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICAgICAgICBhd2FpdCB0aGlzLmFkZENsaWVudFRvQ29udGV4dEdyb3VwKHsgY29udGV4dEdyb3VwSWQgfSwgc2VuZGVySWRlbnRpdHkpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8vIGFkZENsaWVudFRvQ29udGV4dEdyb3VwIGRvZXMgdGhlIGFjdHVhbCBhZGRpdGlvbiBvZiB0aGUgY2xpZW50IHRvIHRoZSBDb250ZXh0IEdyb3VwXG5cdCAgICAvKipcblx0ICAgICAqIEhlbHBlciBmdW5jdGlvbiBmb3Ige0BsaW5rIEludGVyb3BCcm9rZXIjam9pbkNvbnRleHRHcm91cCBJbnRlcm9wQnJva2VyLmpvaW5Db250ZXh0R3JvdXB9LiBEb2VzIHRoZSB3b3JrIG9mIGFjdHVhbGx5IGFkZGluZyB0aGUgY2xpZW50IHRvIHRoZSBDb250ZXh0IEdyb3VwLlxuXHQgICAgICogVXNlZCBieSBQbGF0Zm9ybSBXaW5kb3dzLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBhZGRDbGllbnRUb0NvbnRleHRHcm91cE9wdGlvbnMgLSBDb250YWlucyB0aGUgY29udGV4dEdyb3VwSWRcblx0ICAgICAqIEBwYXJhbSBjbGllbnRJZGVudGl0eSAtIElkZW50aXR5IG9mIHRoZSBjbGllbnQgc2VuZGVyLlxuXHQgICAgICovXG5cdCAgICBhc3luYyBhZGRDbGllbnRUb0NvbnRleHRHcm91cCh7IGNvbnRleHRHcm91cElkIH0sIGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtYnJva2VyLWFkZC1jbGllbnQtdG8tY29udGV4dC1ncm91cCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN1YnNjcmlwdGlvblN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgaWYgKCFjbGllbnRTdWJzY3JpcHRpb25TdGF0ZSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENsaWVudCB3aXRoIElkZW50aXR5OiAke2NsaWVudElkZW50aXR5LnV1aWR9ICR7Y2xpZW50SWRlbnRpdHkubmFtZX0gbm90IGluIENsaWVudCBTdGF0ZSBNYXBgKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgaWYgKCF0aGlzLmdldENvbnRleHRHcm91cHMoKS5maW5kKChjb250ZXh0R3JvdXBJbmZvKSA9PiBjb250ZXh0R3JvdXBJbmZvLmlkID09PSBjb250ZXh0R3JvdXBJZCkpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBBdHRlbXB0aW5nIHRvIGpvaW4gYSBjb250ZXh0IGdyb3VwIHRoYXQgZG9lcyBub3QgZXhpc3Q6ICR7Y29udGV4dEdyb3VwSWR9LiBZb3UgbWF5IG9ubHkgam9pbiBleGlzdGluZyBjb250ZXh0IGdyb3Vwcy5gKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY29uc3Qgb2xkQ29udGV4dEdyb3VwSWQgPSBjbGllbnRTdWJzY3JpcHRpb25TdGF0ZS5jb250ZXh0R3JvdXBJZDtcblx0ICAgICAgICBpZiAob2xkQ29udGV4dEdyb3VwSWQgIT09IGNvbnRleHRHcm91cElkKSB7XG5cdCAgICAgICAgICAgIGNsaWVudFN1YnNjcmlwdGlvblN0YXRlLmNvbnRleHRHcm91cElkID0gY29udGV4dEdyb3VwSWQ7XG5cdCAgICAgICAgICAgIGF3YWl0IHRoaXMuc2V0Q3VycmVudENvbnRleHRHcm91cEluQ2xpZW50T3B0aW9ucyhjbGllbnRJZGVudGl0eSwgY29udGV4dEdyb3VwSWQpO1xuXHQgICAgICAgICAgICBjb25zdCBjb250ZXh0R3JvdXBNYXAgPSB0aGlzLmNvbnRleHRHcm91cHNCeUlkLmdldChjb250ZXh0R3JvdXBJZCk7XG5cdCAgICAgICAgICAgIGZvciAoY29uc3QgWywgaGFuZGxlckluZm9dIG9mIGNsaWVudFN1YnNjcmlwdGlvblN0YXRlLmNvbnRleHRIYW5kbGVycykge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgeyBjb250ZXh0VHlwZSwgaGFuZGxlcklkIH0gPSBoYW5kbGVySW5mbztcblx0ICAgICAgICAgICAgICAgIGlmIChjb250ZXh0VHlwZSA9PT0gdW5kZWZpbmVkKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgLy8gU2VuZCB0aGlzIHNpbmdsZSBoYW5kbGVyIGFsbCBvZiB0aGUgY29udGV4dCwgYmVjYXVzZSBpdCBhY2NlcHRzIGFsbC5cblx0ICAgICAgICAgICAgICAgICAgICBjb250ZXh0R3JvdXBNYXAuZm9yRWFjaCgoY29udGV4dCwgXykgPT4ge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmludm9rZUNvbnRleHRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGNvbnRleHQpO1xuXHQgICAgICAgICAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgZWxzZSBpZiAoY29udGV4dEdyb3VwTWFwLmhhcyhjb250ZXh0VHlwZSkpIHtcblx0ICAgICAgICAgICAgICAgICAgICBjb25zdCBjb250ZXh0Rm9yVHlwZSA9IGNvbnRleHRHcm91cE1hcC5nZXQoY29udGV4dFR5cGUpO1xuXHQgICAgICAgICAgICAgICAgICAgIGlmIChjb250ZXh0Rm9yVHlwZSkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmludm9rZUNvbnRleHRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGNvbnRleHRGb3JUeXBlKTtcblx0ICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvLyBSZW1vdmVzIHRoZSB0YXJnZXQgZnJvbSBpdHMgY29udGV4dCBncm91cC4gU2ltaWxhciBzdHJ1Y3R1cmUgdG8gam9pbkNvbnRleHRHcm91cC5cblx0ICAgIC8qKlxuXHQgICAgICogUmVtb3ZlcyB0aGUgc3BlY2lmaWVkIHRhcmdldCBmcm9tIGEgY29udGV4dCBncm91cC5cblx0ICAgICAqIElmIG5vIHRhcmdldCBpcyBzcGVjaWZpZWQsIGl0IHJlbW92ZXMgdGhlIHNlbmRlciBmcm9tIHRoZWlyIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKiByZW1vdmVGcm9tQ29udGV4dEdyb3VwIGlzIHJlc3BvbnNpYmxlIGZvciBjaGVja2luZyBjb25uZWN0aW9ucyBhdCB0aGUgaW5jb21pbmcgaWRlbnRpdHkuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgSXQgY2FsbHMge0BsaW5rIEludGVyb3BCcm9rZXIjcmVtb3ZlQ2xpZW50RnJvbUNvbnRleHRHcm91cCBJbnRlcm9wQnJva2VyLnJlbW92ZUNsaWVudEZyb21Db250ZXh0R3JvdXB9IHRvIGFjdHVhbGx5IHVuZ3JvdXBcblx0ICAgICAqIHRoZSBjbGllbnQuIFVzZWQgYnkgUGxhdGZvcm0gV2luZG93cy5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gcmVtb3ZlRnJvbUNvbnRleHRHcm91cE9wdGlvbnMgLSBDb250YWlucyB0aGUgdGFyZ2V0IGlkZW50aXR5IHRvIHJlbW92ZS5cblx0ICAgICAqIEBwYXJhbSBzZW5kZXJJZGVudGl0eSAtIElkZW50aXR5IG9mIHRoZSBjbGllbnQgc2VuZGVyLlxuXHQgICAgICovXG5cdCAgICBhc3luYyByZW1vdmVGcm9tQ29udGV4dEdyb3VwKHsgdGFyZ2V0IH0sIHNlbmRlcklkZW50aXR5KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtYnJva2VyLXJlbW92ZS1mcm9tLWNvbnRleHQtZ3JvdXAnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBpZiAodGFyZ2V0KSB7XG5cdCAgICAgICAgICAgIC8vIElmIGFuIGVuZHBvaW50SWQgaXMgcHJvdmlkZWQsIHVzZSB0aGF0LiBUaGlzIHdpbGwgbGlrZWx5IGJlIHVzZWQgYnkgZXh0ZXJuYWwgYWRhcHRlcnMuXG5cdCAgICAgICAgICAgIGlmIChJbnRlcm9wQnJva2VyLmhhc0VuZHBvaW50SWQodGFyZ2V0KSkge1xuXHQgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5yZW1vdmVDbGllbnRGcm9tQ29udGV4dEdyb3VwKHRhcmdldCk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgICAgIC8vIFNhbml0eSBjaGVjayBoZXJlIGluIGNhc2UgYSBzaW5nbGUgYXBwIGhhcyBtdWx0aXBsZSBjb25uZWN0aW9uc1xuXHQgICAgICAgICAgICAgICAgY29uc3QgYWxsQ29ubmVjdGlvbnMgPSB0aGlzLmNoYW5uZWwuY29ubmVjdGlvbnMuZmlsdGVyKCh4KSA9PiB4LnV1aWQgPT09IHRhcmdldC51dWlkICYmIHgubmFtZSA9PT0gdGFyZ2V0Lm5hbWUpO1xuXHQgICAgICAgICAgICAgICAgaWYgKCFhbGxDb25uZWN0aW9ucy5sZW5ndGgpIHtcblx0ICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGNvbm5lY3Rpb24gZm91bmQgZm9yIGdpdmVuIElkZW50aXR5ICR7dGFyZ2V0LnV1aWR9ICR7dGFyZ2V0Lm5hbWV9YCk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICBpZiAoYWxsQ29ubmVjdGlvbnMubGVuZ3RoID4gMSkge1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgTW9yZSB0aGFuIG9uZSBjb25uZWN0aW9uIGZvdW5kIGZvciBpZGVudGl0eSAke3RhcmdldC51dWlkfSAke3RhcmdldC5uYW1lfWApO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBbXTtcblx0ICAgICAgICAgICAgICAgIGZvciAoY29uc3QgY29ubmVjdGlvbiBvZiBhbGxDb25uZWN0aW9ucykge1xuXHQgICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5yZW1vdmVDbGllbnRGcm9tQ29udGV4dEdyb3VwKGNvbm5lY3Rpb24pKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIC8vIE5vIHRhcmdldCBwcm92aWRlZCwgcmVtb3ZlIHRoZSBzZW5kZXIgZnJvbSB0aGUgY29udGV4dCBncm91cC5cblx0ICAgICAgICAgICAgYXdhaXQgdGhpcy5yZW1vdmVDbGllbnRGcm9tQ29udGV4dEdyb3VwKHNlbmRlcklkZW50aXR5KTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvLyByZW1vdmVDbGllbnRGcm9tQ29udGV4dEdyb3VwIGRvZXMgdGhlIGFjdHVhbCByZW1vdmUgb2YgdGhlIGNsaWVudCBmcm9tIHRoZSBDb250ZXh0IEdyb3VwXG5cdCAgICAvKipcblx0ICAgICAqIEhlbHBlciBmdW5jdGlvbiBmb3Ige0BsaW5rIEludGVyb3BCcm9rZXIjcmVtb3ZlRnJvbUNvbnRleHRHcm91cCBJbnRlcm9wQnJva2VyLnJlbW92ZUZyb21Db250ZXh0R3JvdXB9LiBEb2VzIHRoZSB3b3JrIG9mIGFjdHVhbGx5IHJlbW92aW5nIHRoZSBjbGllbnQgZnJvbSB0aGUgQ29udGV4dCBHcm91cC5cblx0ICAgICAqIFVzZWQgYnkgUGxhdGZvcm0gV2luZG93cy5cblx0ICAgICAqXG5cdCAgICAgKiBAcHJvcGVydHkgeyBDbGllbnRJZGVudGl0eSB9IGNsaWVudElkZW50aXR5IC0gSWRlbnRpdHkgb2YgdGhlIGNsaWVudCBzZW5kZXIuXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHJlbW92ZUNsaWVudEZyb21Db250ZXh0R3JvdXAoY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItcmVtb3ZlLWNsaWVudC1mcm9tLWNvbnRleHQtZ3JvdXAnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGlmIChjbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICBjbGllbnRTdGF0ZS5jb250ZXh0R3JvdXBJZCA9IHVuZGVmaW5lZDtcblx0ICAgICAgICB9XG5cdCAgICAgICAgYXdhaXQgdGhpcy5zZXRDdXJyZW50Q29udGV4dEdyb3VwSW5DbGllbnRPcHRpb25zKGNsaWVudElkZW50aXR5LCBudWxsKTtcblx0ICAgIH1cblx0ICAgIC8vIFVzZWQgYnkgcGxhdGZvcm0gd2luZG93cyB0byBrbm93IHdoYXQgY2xpZW50IGdyb3VwcyB0aGUgcHJvdmlkZXIgaGFzIGRlY2xhcmVkLiBBbHNvIHVzZWQgaW50ZXJuYWxseSB0byBhY2Nlc3MgY29udGV4dCBncm91cHMuIE92ZXJyaWRlYWJsZSBzbyB0aGF0IHRoZSBwbGF0Zm9ybSBkZXZlbG9wZXIgY2FuIG1vZGlmeSBpdC5cblx0ICAgIC8qKlxuXHQgICAgICogUmV0dXJucyB0aGUgSW50ZXJvcC1Ccm9rZXItZGVmaW5lZCBjb250ZXh0IGdyb3VwcyBhdmFpbGFibGUgZm9yIGFuIGVudGl0eSB0byBqb2luLiBCZWNhdXNlIHRoaXMgZnVuY3Rpb24gaXMgdXNlZCBpbiB0aGUgcmVzdCBvZiB0aGUgSW50ZXJvcCBCcm9rZXIgdG8gZmV0Y2ggdGhlIENvbnRleHQgR3JvdXBzLCBvdmVycmlkaW5nIHRoaXMgYWxsb3dzIHlvdSB0byBjdXN0b21pemUgdGhlIENvbnRleHQgR3JvdXBzIGZvciB0aGUgSW50ZXJvcCBCcm9rZXIuIEhvd2V2ZXIsIHdlIHJlY29tbWVuZCBjdXN0b21pemluZyB0aGUgY29udGV4dCBncm91cHMgdGhyb3VnaCBjb25maWd1cmF0aW9uIGluc3RlYWQuXG5cdCAgICAgKiBVc2VkIGJ5IFBsYXRmb3JtIFdpbmRvd3MuXG5cdCAgICAgKlxuXHQgICAgICovXG5cdCAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuXHQgICAgZ2V0Q29udGV4dEdyb3VwcygpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItZ2V0LWNvbnRleHQtZ3JvdXBzJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgLy8gQ3JlYXRlIGNvcHkgZm9yIGltbXV0YWJpbGl0eVxuXHQgICAgICAgIHJldHVybiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQnJva2VyX2NvbnRleHRHcm91cHMsIFwiZlwiKS5tYXAoKGNvbnRleHRHcm91cCkgPT4ge1xuXHQgICAgICAgICAgICByZXR1cm4geyAuLi5jb250ZXh0R3JvdXAgfTtcblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIC8vIFVzZWQgdG8gYnkgcGxhdGZvcm0gd2luZG93cyB0byBnZXQgZGlzcGxheSBtZXRhZGF0YSBmb3IgYSBjb250ZXh0IGdyb3VwLlxuXHQgICAgLyoqXG5cdCAgICAgKiBHZXRzIGRpc3BsYXkgaW5mbyBmb3IgYSBjb250ZXh0IGdyb3VwXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgVXNlZCBieSBQbGF0Zm9ybSBXaW5kb3dzLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBnZXRJbmZvRm9yQ29udGV4dEdyb3VwT3B0aW9ucyAtIENvbnRhaW5zIGNvbnRleHRHcm91cElkLCB0aGUgY29udGV4dCBncm91cCB5b3Ugd2lzaCB0byBnZXQgZGlzcGxheSBpbmZvIGZvci5cblx0ICAgICAqXG5cdCAgICAgKi9cblx0ICAgIGdldEluZm9Gb3JDb250ZXh0R3JvdXAoeyBjb250ZXh0R3JvdXBJZCB9KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtYnJva2VyLWdldC1pbmZvLWZvci1jb250ZXh0LWdyb3VwJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q29udGV4dEdyb3VwcygpLmZpbmQoKGNvbnRleHRHcm91cCkgPT4gY29udGV4dEdyb3VwLmlkID09PSBjb250ZXh0R3JvdXBJZCk7XG5cdCAgICB9XG5cdCAgICAvLyBVc2VkIGJ5IHBsYXRmb3JtIHdpbmRvd3MgdG8gZ2V0IGFsbCBjbGllbnRzIGZvciBhIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAvKipcblx0ICAgICAqIEdldHMgYWxsIGNsaWVudHMgZm9yIGEgY29udGV4dCBncm91cC5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyAqKlRoaXMgaXMgcHJpbWFyaWx5IHVzZWQgZm9yIHBsYXRmb3JtIHdpbmRvd3MuIFZpZXdzIHdpdGhpbiBhIHBsYXRmb3JtIHNob3VsZCBub3QgaGF2ZSB0byB1c2UgdGhpcyBBUEkuKipcblx0ICAgICAqIFJldHVybnMgdGhlIEludGVyb3AtQnJva2VyLWRlZmluZWQgY29udGV4dCBncm91cHMgYXZhaWxhYmxlIGZvciBhbiBlbnRpdHkgdG8gam9pbi5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gZ2V0QWxsQ2xpZW50c0luQ29udGV4dEdyb3VwT3B0aW9ucyAtIENvbnRhaW5zIGNvbnRleHRHcm91cElkLCB0aGUgY29udGV4dCBncm91cCB5b3Ugd2lzaCB0byBnZXQgY2xpZW50cyBmb3IuXG5cdCAgICAgKlxuXHQgICAgICovXG5cdCAgICBnZXRBbGxDbGllbnRzSW5Db250ZXh0R3JvdXAoeyBjb250ZXh0R3JvdXBJZCB9KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtYnJva2VyLWdldC1hbGwtY2xpZW50cy1pbi1jb250ZXh0LWdyb3VwJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50c0luQ29udGV4dEdyb3VwID0gQXJyYXkuZnJvbSh0aGlzLmludGVyb3BDbGllbnRzLnZhbHVlcygpKVxuXHQgICAgICAgICAgICAuZmlsdGVyKChjb25uZWN0ZWRDbGllbnQpID0+IGNvbm5lY3RlZENsaWVudC5jb250ZXh0R3JvdXBJZCA9PT0gY29udGV4dEdyb3VwSWQpXG5cdCAgICAgICAgICAgIC5tYXAoKHN1YnNjcmlwdGlvblN0YXRlKSA9PiB7XG5cdCAgICAgICAgICAgIHJldHVybiBzdWJzY3JpcHRpb25TdGF0ZS5jbGllbnRJZGVudGl0eTtcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gY2xpZW50c0luQ29udGV4dEdyb3VwO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXNwb25zaWJsZSBmb3IgbGF1bmNoaW5nIG9mIGFwcGxpY2F0aW9ucyB0aGF0IGNhbiBoYW5kbGUgYSBnaXZlbiBpbnRlbnQsIGFuZCBkZWxlZ2F0aW9uIG9mIGludGVudHMgdG8gdGhvc2UgYXBwbGljYXRpb25zLlxuXHQgICAgICogTXVzdCBiZSBvdmVycmlkZGVuLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFRvIG1ha2UgdGhpcyBjYWxsIEZEQzMtQ29tcGxpYW50IGl0IHdvdWxkIG5lZWQgdG8gcmV0dXJuIGFuIEludGVudFJlc29sdXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGludGVyZmFjZSBJbnRlbnRSZXNvbHV0aW9uIHtcblx0ICAgICAqICAgc291cmNlOiBUYXJnZXRBcHA7XG5cdCAgICAgKiAgIC8vIGRlcHJlY2F0ZWQsIG5vdCBhc3NpZ25hYmxlIGZyb20gaW50ZW50IGxpc3RlbmVyc1xuXHQgICAgICogICBkYXRhPzogb2JqZWN0O1xuXHQgICAgICogICB2ZXJzaW9uOiBzdHJpbmc7XG5cdCAgICAgKiB9XG5cdCAgICAgKiBgYGBcblx0ICAgICAqXG5cdCAgICAgKiBNb3JlIGluZm9ybWF0aW9uIG9uIHRoZSBJbnRlbnRSZXNvbHV0aW9uIHR5cGUgY2FuIGJlIGZvdW5kIGluIHRoZSBbRkRDMyBkb2N1bWVudGF0aW9uXShodHRwczovL2ZkYzMuZmlub3Mub3JnL2RvY3MvYXBpL3JlZi9JbnRlbnRSZXNvbHV0aW9uKS5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gaW50ZW50IFRoZSBjb21iaW5hdGlvbiBvZiBhbiBhY3Rpb24gYW5kIGEgY29udGV4dCB0aGF0IGlzIHBhc3NlZCB0byBhbiBhcHBsaWNhdGlvbiBmb3IgcmVzb2x1dGlvbi5cblx0ICAgICAqIEBwYXJhbSAgY2xpZW50SWRlbnRpdHkgSWRlbnRpdHkgb2YgdGhlIENsaWVudCBtYWtpbmcgdGhlIHJlcXVlc3QuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiAvLyBvdmVycmlkZSBjYWxsIHNvIHdlIHNldCBpbnRlbnQgdGFyZ2V0IGFuZCBjcmVhdGUgdmlldyB0aGF0IHdpbGwgaGFuZGxlIGl0XG5cdCAgICAgKiBmaW4uUGxhdGZvcm0uaW5pdCh7XG5cdCAgICAgKiAgICAgaW50ZXJvcE92ZXJyaWRlOiBhc3luYyAoSW50ZXJvcEJyb2tlcikgPT4ge1xuXHQgICAgICogICAgICAgICBjbGFzcyBPdmVycmlkZSBleHRlbmRzIEludGVyb3BCcm9rZXIge1xuXHQgICAgICogICAgICAgICAgICAgYXN5bmMgaGFuZGxlRmlyZWRJbnRlbnQoaW50ZW50KSB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgc3VwZXIuc2V0SW50ZW50VGFyZ2V0KGludGVudCwgeyB1dWlkOiAncGxhdGZvcm0tdXVpZCcsIG5hbWU6ICdpbnRlbnQtdmlldycgfSk7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zdCB3aW4gPSBmaW4uV2luZG93LndyYXBTeW5jKHsgbmFtZTogJ2ZvbycsIHV1aWQ6ICdwbGF0Zm9ybS11dWlkJyB9KTtcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zdCBjcmVhdGVkVmlldyA9IGF3YWl0IHBsYXRmb3JtLmNyZWF0ZVZpZXcoeyB1cmw6ICdodHRwOi8vb3BlbmZpbi5jbycsIG5hbWU6ICdpbnRlbnQtdmlldycgfSwgd2luLmlkZW50aXR5KTtcblx0ICAgICAqICAgICAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgfVxuXHQgICAgICogICAgICAgICByZXR1cm4gbmV3IE92ZXJyaWRlKCk7XG5cdCAgICAgKiAgICAgfVxuXHQgICAgICogfSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcblx0ICAgIGFzeW5jIGhhbmRsZUZpcmVkSW50ZW50KGludGVudCwgY2xpZW50SWRlbnRpdHkgLy8gVE9ETyhDT1JFLTgxMSk6IHJlbW92ZSBpbmxpbmUgaW50ZXJzZWN0ZWQgdHlwZVxuXHQgICAgKSB7XG5cdCAgICAgICAgY29uc3Qgd2FybmluZyA9ICgwLCB1dGlsc18xLmdlbmVyYXRlT3ZlcnJpZGVXYXJuaW5nKSgnZmRjMy5yYWlzZUludGVudCcsICdJbnRlcm9wQnJva2VyLmhhbmRsZUZpcmVkSW50ZW50JywgY2xpZW50SWRlbnRpdHksICdpbnRlcm9wQ2xpZW50LmZpcmVJbnRlbnQnKTtcblx0ICAgICAgICBjb25zb2xlLndhcm4od2FybmluZyk7XG5cdCAgICAgICAgdGhyb3cgbmV3IEVycm9yKHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5maXJlSW50ZW50KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogU2hvdWxkIGJlIGNhbGxlZCBpbiB7QGxpbmsgSW50ZXJvcEJyb2tlciNoYW5kbGVGaXJlZEludGVudCBJbnRlcm9wQnJva2VyLmhhbmRsZUZpcmVkSW50ZW50fS5cblx0ICAgICAqIFdoaWxlIGhhbmRsZUZpcmVkSW50ZW50IGlzIHJlc3BvbnNpYmxlIGZvciBsYXVuY2hpbmcgYXBwbGljYXRpb25zLCBzZXRJbnRlbnRUYXJnZXQgaXMgdXNlZCB0byB0ZWxsIHRoZSBJbnRlcm9wQnJva2VyIHdoaWNoIGFwcGxpY2F0aW9uIHNob3VsZCByZWNlaXZlIHRoZSBpbnRlbnQgd2hlbiBpdCBpcyByZWFkeS5cblx0ICAgICAqIEBwYXJhbSBpbnRlbnQgVGhlIGNvbWJpbmF0aW9uIG9mIGFuIGFjdGlvbiBhbmQgYSBjb250ZXh0IHRoYXQgaXMgcGFzc2VkIHRvIGFuIGFwcGxpY2F0aW9uIGZvciByZXNvbHV0aW9uLlxuXHQgICAgICogQHBhcmFtIHRhcmdldCAtIElkZW50aXR5IG9mIHRoZSB0YXJnZXQgdGhhdCB3aWxsIGhhbmRsZSB0aGUgaW50ZW50LlxuXHQgICAgICpcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgc2V0SW50ZW50VGFyZ2V0KGludGVudCwgdGFyZ2V0KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtYnJva2VyLXNldC1pbnRlbnQtdGFyZ2V0JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCB0aGlzIGlzIG9ubHkgZm9yIGFwaSBhbmFseXRpY3MgcHVycG9zZXNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCB0YXJnZXRJbmZvID0gdGhpcy5pbnRlbnRDbGllbnRNYXAuZ2V0KHRhcmdldC5uYW1lKTtcblx0ICAgICAgICBjb25zdCBoYW5kbGVySWQgPSBgaW50ZW50LWhhbmRsZXItJHtpbnRlbnQubmFtZX1gO1xuXHQgICAgICAgIGlmICghdGFyZ2V0SW5mbykge1xuXHQgICAgICAgICAgICB0aGlzLmludGVudENsaWVudE1hcC5zZXQodGFyZ2V0Lm5hbWUsIG5ldyBNYXAoKSk7XG5cdCAgICAgICAgICAgIGNvbnN0IG5ld0hhbmRsZXJJbmZvTWFwID0gdGhpcy5pbnRlbnRDbGllbnRNYXAuZ2V0KHRhcmdldC5uYW1lKTtcblx0ICAgICAgICAgICAgaWYgKG5ld0hhbmRsZXJJbmZvTWFwKSB7XG5cdCAgICAgICAgICAgICAgICBuZXdIYW5kbGVySW5mb01hcC5zZXQoaGFuZGxlcklkLCB7IGlzUmVhZHk6IGZhbHNlLCBwZW5kaW5nSW50ZW50czogW2ludGVudF0gfSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGhhbmRsZXJJbmZvID0gdGFyZ2V0SW5mby5nZXQoaGFuZGxlcklkKTtcblx0ICAgICAgICAgICAgaWYgKCFoYW5kbGVySW5mbykge1xuXHQgICAgICAgICAgICAgICAgdGFyZ2V0SW5mby5zZXQoaGFuZGxlcklkLCB7IGlzUmVhZHk6IGZhbHNlLCBwZW5kaW5nSW50ZW50czogW2ludGVudF0gfSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgICAgICBoYW5kbGVySW5mby5wZW5kaW5nSW50ZW50cy5wdXNoKGludGVudCk7XG5cdCAgICAgICAgICAgICAgICBpZiAoaGFuZGxlckluZm8uY2xpZW50SWRlbnRpdHkgJiYgaGFuZGxlckluZm8uaXNSZWFkeSkge1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgY2xpZW50SWRlbnRpdHksIHBlbmRpbmdJbnRlbnRzIH0gPSBoYW5kbGVySW5mbztcblx0ICAgICAgICAgICAgICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbnRlbnRUb1NlbmQgPSBwZW5kaW5nSW50ZW50c1twZW5kaW5nSW50ZW50cy5sZW5ndGggLSAxXTtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5pbnZva2VJbnRlbnRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGludGVudFRvU2VuZCk7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZXJJbmZvLnBlbmRpbmdJbnRlbnRzID0gW107XG5cdCAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBpbnZva2luZyBpbnRlbnQgaGFuZGxlciBmb3IgY2xpZW50ICR7Y2xpZW50SWRlbnRpdHkudXVpZH0vJHtjbGllbnRJZGVudGl0eS5uYW1lfS8ke2NsaWVudElkZW50aXR5LmVuZHBvaW50SWR9YCk7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZXJJbmZvLmlzUmVhZHkgPSBmYWxzZTtcblx0ICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlc3BvbnNpYmxlIGZvciByZXR1cm5pbmcgaW5mb3JtYXRpb24gb24gYSBwYXJ0aWN1bGFyIEludGVudC5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBXaGVuZXZlciBJbnRlcm9wQ2xpZW50LmdldEluZm9Gb3JJbnRlbnQgaXMgY2FsbGVkIHRoaXMgZnVuY3Rpb24gd2lsbCBmaXJlLiBUaGUgb3B0aW9ucyBhcmd1bWVudCBnaXZlcyB5b3Vcblx0ICAgICAqIGFjY2VzcyB0byB0aGUgaW50ZW50IG5hbWUgYW5kIGFueSBvcHRpb25hbCBjb250ZXh0IHRoYXQgd2FzIHBhc3NlZCBhbmQgY2xpZW50SWRlbnRpdHkgaXMgdGhlIGlkZW50aXR5IG9mIHRoZSBjbGllbnRcblx0ICAgICAqIHRoYXQgbWFkZSB0aGUgY2FsbC4gSWRlYWxseSBoZXJlIHlvdSB3b3VsZCBmZXRjaCB0aGUgaW5mbyBmb3IgdGhlIGludGVudCBhbmQgcmV0dXJuIGl0IHdpdGggdGhlIHNoYXBlIHRoYXQgdGhlXG5cdCAgICAgKiBJbnRlcm9wQ2xpZW50LmdldEluZm9Gb3JJbnRlbnQgY2FsbCBpcyBleHBlY3RpbmcuXG5cdCAgICAgKlxuXHQgICAgICogVG8gbWFrZSB0aGlzIGNhbGwgRkRDMy1Db21wbGlhbnQgaXQgd291bGQgbmVlZCB0byByZXR1cm4gYW4gQXBwIEludGVudDpcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogLy8ge1xuXHQgICAgICogLy8gICAgIGludGVudDogeyBuYW1lOiBcIlN0YXJ0Q2hhdFwiLCBkaXNwbGF5TmFtZTogXCJDaGF0XCIgfSxcblx0ICAgICAqIC8vICAgICBhcHBzOiBbeyBuYW1lOiBcIlNreXBlXCIgfSwgeyBuYW1lOiBcIlN5bXBob255XCIgfSwgeyBuYW1lOiBcIlNsYWNrXCIgfV1cblx0ICAgICAqIC8vIH1cblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqIE1vcmUgaW5mb3JtYXRpb24gb24gdGhlIEFwcEludGVudCB0eXBlIGNhbiBiZSBmb3VuZCBpbiB0aGUgW0ZEQzMgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9mZGMzLmZpbm9zLm9yZy9kb2NzL2FwaS9yZWYvQXBwSW50ZW50KS5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gb3B0aW9uc1xuXHQgICAgICogQHBhcmFtIGNsaWVudElkZW50aXR5IElkZW50aXR5IG9mIHRoZSBDbGllbnQgbWFraW5nIHRoZSByZXF1ZXN0LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLlBsYXRmb3JtLmluaXQoe1xuXHQgICAgICogICAgIGludGVyb3BPdmVycmlkZTogYXN5bmMgKEludGVyb3BCcm9rZXIpID0+IHtcblx0ICAgICAqICAgICAgICAgY2xhc3MgT3ZlcnJpZGUgZXh0ZW5kcyBJbnRlcm9wQnJva2VyIHtcblx0ICAgICAqICAgICAgICAgICAgIGFzeW5jIGhhbmRsZUluZm9Gb3JJbnRlbnQob3B0aW9ucywgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAvLyBZb3VyIGNvZGUgZ29lcyBoZXJlLlxuXHQgICAgICogICAgICAgICAgICAgfVxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIHJldHVybiBuZXcgT3ZlcnJpZGUoKTtcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuXHQgICAgYXN5bmMgaGFuZGxlSW5mb0ZvckludGVudChvcHRpb25zLCBjbGllbnRJZGVudGl0eSAvLyBUT0RPKENPUkUtODExKTogcmVtb3ZlIGlubGluZSBpbnRlcnNlY3RlZCB0eXBlXG5cdCAgICApIHtcblx0ICAgICAgICBjb25zdCB3YXJuaW5nID0gKDAsIHV0aWxzXzEuZ2VuZXJhdGVPdmVycmlkZVdhcm5pbmcpKCdmZGMzLmZpbmRJbnRlbnQnLCAnSW50ZXJvcEJyb2tlci5oYW5kbGVJbmZvRm9ySW50ZW50JywgY2xpZW50SWRlbnRpdHksICdpbnRlcm9wQ2xpZW50LmdldEluZm9Gb3JJbnRlbnQnKTtcblx0ICAgICAgICBjb25zb2xlLndhcm4od2FybmluZyk7XG5cdCAgICAgICAgdGhyb3cgbmV3IEVycm9yKHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5nZXRJbmZvRm9ySW50ZW50KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVzcG9uc2libGUgZm9yIHJldHVybmluZyBpbmZvcm1hdGlvbiBvbiB3aGljaCBJbnRlbnRzIGFyZSBtZWFudCB0byBoYW5kbGUgYSBzcGVjaWZpYyBDb250ZXh0LlxuXHQgICAgICogTXVzdCBiZSBvdmVycmlkZGVuLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFJlc3BvbnNpYmxlIGZvciByZXR1cm5pbmcgaW5mb3JtYXRpb24gb24gd2hpY2ggSW50ZW50cyBhcmUgbWVhbnQgdG8gaGFuZGxlIGEgc3BlY2lmaWMgQ29udGV4dC4gTXVzdCBiZSBvdmVycmlkZGVuLlxuXHQgICAgICpcblx0ICAgICAqIFdoZW5ldmVyIEludGVyb3BDbGllbnQuZ2V0SW5mb0ZvckludGVudHNCeUNvbnRleHQgaXMgY2FsbGVkIHRoaXMgZnVuY3Rpb24gd2lsbCBmaXJlLiBUaGUgY29udGV4dCBhcmd1bWVudCBnaXZlcyB5b3UgYWNjZXNzIHRvIHRoZSBjb250ZXh0IHRoYXQgdGhlIGNsaWVudCB3YW50cyBpbmZvcm1hdGlvbiBvbiBhbmQgY2xpZW50SWRlbnRpdHkgaXMgdGhlIGlkZW50aXR5IG9mIHRoZSBjbGllbnQgdGhhdCBtYWRlIHRoZSBjYWxsLiBJZGVhbGx5IGhlcmUgeW91IHdvdWxkIGZldGNoIHRoZSBpbmZvIGZvciBhbnkgaW50ZW50IHRoYXQgY2FuIGhhbmRsZSBhbmQgcmV0dXJuIGl0IHdpdGggdGhlIHNoYXBlIHRoYXQgdGhlIEludGVyb3BDbGllbnQuZ2V0SW5mb0ZvckludGVudHNCeUNvbnRleHQgY2FsbCBpcyBleHBlY3RpbmcuXG5cdCAgICAgKlxuXHQgICAgICogVG8gbWFrZSB0aGlzIGNhbGwgRkRDMy1Db21wbGlhbnQgaXQgd291bGQgbmVlZCB0byByZXR1cm4gYW4gYXJyYXkgb2YgQXBwSW50ZW50czpcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogLy8gW3tcblx0ICAgICAqIC8vICAgICBpbnRlbnQ6IHsgbmFtZTogXCJTdGFydENhbGxcIiwgZGlzcGxheU5hbWU6IFwiQ2FsbFwiIH0sXG5cdCAgICAgKiAvLyAgICAgYXBwczogW3sgbmFtZTogXCJTa3lwZVwiIH1dXG5cdCAgICAgKiAvLyB9LFxuXHQgICAgICogLy8ge1xuXHQgICAgICogLy8gICAgIGludGVudDogeyBuYW1lOiBcIlN0YXJ0Q2hhdFwiLCBkaXNwbGF5TmFtZTogXCJDaGF0XCIgfSxcblx0ICAgICAqIC8vICAgICBhcHBzOiBbeyBuYW1lOiBcIlNreXBlXCIgfSwgeyBuYW1lOiBcIlN5bXBob255XCIgfSwgeyBuYW1lOiBcIlNsYWNrXCIgfV1cblx0ICAgICAqIC8vIH1dO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICogTW9yZSBpbmZvcm1hdGlvbiBvbiB0aGUgQXBwSW50ZW50IHR5cGUgY2FuIGJlIGZvdW5kIGluIHRoZSBbRkRDMyBkb2N1bWVudGF0aW9uXShodHRwczovL2ZkYzMuZmlub3Mub3JnL2RvY3MvYXBpL3JlZi9BcHBJbnRlbnQpLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBjb250ZXh0IERhdGEgcGFzc2VkIGJldHdlZW4gZW50aXRpZXMgYW5kIGFwcGxpY2F0aW9ucy5cblx0ICAgICAqIEBwYXJhbSBjbGllbnRJZGVudGl0eSBJZGVudGl0eSBvZiB0aGUgQ2xpZW50IG1ha2luZyB0aGUgcmVxdWVzdC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5QbGF0Zm9ybS5pbml0KHtcblx0ICAgICAqICAgICBpbnRlcm9wT3ZlcnJpZGU6IGFzeW5jIChJbnRlcm9wQnJva2VyKSA9PiB7XG5cdCAgICAgKiAgICAgICAgIGNsYXNzIE92ZXJyaWRlIGV4dGVuZHMgSW50ZXJvcEJyb2tlciB7XG5cdCAgICAgKiAgICAgICAgICAgICBhc3luYyBoYW5kbGVJbmZvRm9ySW50ZW50c0J5Q29udGV4dChjb250ZXh0LCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICogICAgICAgICAgICAgICAgIC8vIFlvdXIgY29kZSBnb2VzIGhlcmUuXG5cdCAgICAgKiAgICAgICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgcmV0dXJuIG5ldyBPdmVycmlkZSgpO1xuXHQgICAgICogICAgIH1cblx0ICAgICAqIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBhc3luYyBoYW5kbGVJbmZvRm9ySW50ZW50c0J5Q29udGV4dChjb250ZXh0LCBjbGllbnRJZGVudGl0eSAvLyBUT0RPKENPUkUtODExKTogcmVtb3ZlIGlubGluZSBpbnRlcnNlY3RlZCB0eXBlXG5cdCAgICApIHtcblx0ICAgICAgICBjb25zdCB3YXJuaW5nID0gKDAsIHV0aWxzXzEuZ2VuZXJhdGVPdmVycmlkZVdhcm5pbmcpKCdmZGMzLmZpbmRJbnRlbnRzQnlDb250ZXh0JywgJ0ludGVyb3BCcm9rZXIuaGFuZGxlSW5mb0ZvckludGVudHNCeUNvbnRleHQnLCBjbGllbnRJZGVudGl0eSwgJ2ludGVyb3BDbGllbnQuZ2V0SW5mb0ZvckludGVudHNCeUNvbnRleHQnKTtcblx0ICAgICAgICBjb25zb2xlLndhcm4od2FybmluZyk7XG5cdCAgICAgICAgdGhyb3cgbmV3IEVycm9yKHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5nZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlc3BvbnNpYmxlIGZvciByZXNvbHZpbmcgYW4gSW50ZW50IGJhc2VkIG9uIGEgc3BlY2lmaWMgQ29udGV4dC5cblx0ICAgICAqIE11c3QgYmUgb3ZlcnJpZGRlbi5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBXaGVuZXZlciBJbnRlcm9wQ2xpZW50LmZpcmVJbnRlbnRGb3JDb250ZXh0IGlzIGNhbGxlZCB0aGlzIGZ1bmN0aW9uIHdpbGwgZmlyZS4gVGhlIGNvbnRleHRGb3JJbnRlbnQgYXJndW1lbnRcblx0ICAgICAqIGdpdmVzIHlvdSBhY2Nlc3MgdG8gdGhlIGNvbnRleHQgdGhhdCB3aWxsIGJlIHJlc29sdmVkIHRvIGFuIGludGVudC4gSXQgYWxzbyBjYW4gb3B0aW9uYWxseSBjb250YWluIGFueSBtZXRhZGF0YSByZWxldmFudFxuXHQgICAgICogdG8gcmVzb2x2aW5nIGl0LCBsaWtlIGEgc3BlY2lmaWMgYXBwIHRoZSBjbGllbnQgd2FudHMgdGhlIGNvbnRleHQgdG8gYmUgaGFuZGxlZCBieS4gVGhlIGNsaWVudElkZW50aXR5IGlzIHRoZSBpZGVudGl0eVxuXHQgICAgICogb2YgdGhlIGNsaWVudCB0aGF0IG1hZGUgdGhlIGNhbGwuXG5cdCAgICAgKlxuXHQgICAgICogVG8gbWFrZSB0aGlzIGNhbGwgRkRDMy1Db21wbGlhbnQgaXQgd291bGQgbmVlZCB0byByZXR1cm4gYW4gSW50ZW50UmVzb2x1dGlvbjpcblx0ICAgICAqXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogLy8ge1xuXHQgICAgICogLy8gICAgIGludGVudDogeyBuYW1lOiBcIlN0YXJ0Q2hhdFwiLCBkaXNwbGF5TmFtZTogXCJDaGF0XCIgfSxcblx0ICAgICAqIC8vICAgICBhcHBzOiBbeyBuYW1lOiBcIlNreXBlXCIgfSwgeyBuYW1lOiBcIlN5bXBob255XCIgfSwgeyBuYW1lOiBcIlNsYWNrXCIgfV1cblx0ICAgICAqIC8vIH1cblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqIE1vcmUgaW5mb3JtYXRpb24gb24gdGhlIEludGVudFJlc29sdXRpb24gdHlwZSBjYW4gYmUgZm91bmQgaW4gdGhlIFtGREMzIGRvY3VtZW50YXRpb25dKGh0dHBzOi8vZmRjMy5maW5vcy5vcmcvZG9jcy9hcGkvcmVmL01ldGFkYXRhI2ludGVudHJlc29sdXRpb24pLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBjb250ZXh0Rm9ySW50ZW50IERhdGEgcGFzc2VkIGJldHdlZW4gZW50aXRpZXMgYW5kIGFwcGxpY2F0aW9ucy5cblx0ICAgICAqIEBwYXJhbSBjbGllbnRJZGVudGl0eSBJZGVudGl0eSBvZiB0aGUgQ2xpZW50IG1ha2luZyB0aGUgcmVxdWVzdC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5QbGF0Zm9ybS5pbml0KHtcblx0ICAgICAqICAgICBpbnRlcm9wT3ZlcnJpZGU6IGFzeW5jIChJbnRlcm9wQnJva2VyKSA9PiB7XG5cdCAgICAgKiAgICAgICAgIGNsYXNzIE92ZXJyaWRlIGV4dGVuZHMgSW50ZXJvcEJyb2tlciB7XG5cdCAgICAgKiAgICAgICAgICAgICBhc3luYyBoYW5kbGVGaXJlZEludGVudEZvckNvbnRleHQoY29udGV4dEZvckludGVudCwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAvLyBZb3VyIGNvZGUgZ29lcyBoZXJlLlxuXHQgICAgICogICAgICAgICAgICAgfVxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIHJldHVybiBuZXcgT3ZlcnJpZGUoKTtcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuXHQgICAgYXN5bmMgaGFuZGxlRmlyZWRJbnRlbnRGb3JDb250ZXh0KGNvbnRleHRGb3JJbnRlbnQsIGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgY29uc3Qgd2FybmluZyA9ICgwLCB1dGlsc18xLmdlbmVyYXRlT3ZlcnJpZGVXYXJuaW5nKSgnZmRjMy5yYWlzZUludGVudEZvckNvbnRleHQnLCAnSW50ZXJvcEJyb2tlci5oYW5kbGVGaXJlZEludGVudEZvckNvbnRleHQnLCBjbGllbnRJZGVudGl0eSwgJ2ludGVyb3BDbGllbnQuZmlyZUludGVudEZvckNvbnRleHQnKTtcblx0ICAgICAgICBjb25zb2xlLndhcm4od2FybmluZyk7XG5cdCAgICAgICAgdGhyb3cgbmV3IEVycm9yKHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5maXJlSW50ZW50Rm9yQ29udGV4dCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFByb3ZpZGVzIHRoZSBpZGVudGl0eSBvZiBhbnkgSW50ZXJvcCBDbGllbnQgdGhhdCBkaXNjb25uZWN0cyBmcm9tIHRoZSBJbnRlcm9wIEJyb2tlci4gSXQgaXMgbWVhbnQgdG8gYmUgb3ZlcnJpZGVuLlxuXHQgICAgICogQHBhcmFtIGNsaWVudElkZW50aXR5XG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBmaW4uUGxhdGZvcm0uaW5pdCh7XG5cdCAgICAgKiAgICAgaW50ZXJvcE92ZXJyaWRlOiBhc3luYyAoSW50ZXJvcEJyb2tlcikgPT4ge1xuXHQgICAgICogICAgICAgICBjbGFzcyBPdmVycmlkZSBleHRlbmRzIEludGVyb3BCcm9rZXIge1xuXHQgICAgICogICAgICAgICAgICAgYXN5bmMgY2xpZW50RGlzY29ubmVjdGVkKGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSBjbGllbnRJZGVudGl0eTtcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgQ2xpZW50IHdpdGggaWRlbnRpdHkgJHt1dWlkfS8ke25hbWV9IGhhcyBiZWVuIGRpc2Nvbm5lY3RlZGApO1xuXHQgICAgICogICAgICAgICAgICAgfVxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIHJldHVybiBuZXcgT3ZlcnJpZGUoKTtcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuXHQgICAgYXN5bmMgY2xpZW50RGlzY29ubmVjdGVkKGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgLy8gVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgaW4gY2hhbm5lbC5vbkRpc2Nvbm5lY3Rpb24uXG5cdCAgICAgICAgLy8gSXQgaXMgbWVhbnQgdG8gYmUgb3ZlcnJpZGRlbiB0byBpbmZvcm0gd2hlbiBhbiBJbnRlcm9wIENsaWVudCBoYXMgYmVlbiBkaXNjb25uZWN0ZWQuXG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlc3BvbnNpYmxlIGZvciByZXNvbHZpbmcgYW4gZmRjMy5vcGVuIGNhbGwuXG5cdCAgICAgKiBNdXN0IGJlIG92ZXJyaWRkZW4uXG5cdCAgICAgKiBAcGFyYW0gZmRjM09wZW5PcHRpb25zIGZkYzMub3BlbiBvcHRpb25zXG5cdCAgICAgKiBAcGFyYW0gY2xpZW50SWRlbnRpdHkgSWRlbnRpdHkgb2YgdGhlIENsaWVudCBtYWtpbmcgdGhlIHJlcXVlc3QuXG5cdCAgICAgKi9cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBhc3luYyBmZGMzSGFuZGxlT3Blbih7IGFwcCwgY29udGV4dCB9LCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IHdhcm5pbmcgPSAoMCwgdXRpbHNfMS5nZW5lcmF0ZU92ZXJyaWRlV2FybmluZykoJ2ZkYzMub3BlbicsICdJbnRlcm9wQnJva2VyLmZkYzNIYW5kbGVPcGVuJywgY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGNvbnNvbGUud2Fybih3YXJuaW5nKTtcblx0ICAgICAgICB0aHJvdyBuZXcgRXJyb3IodXRpbHNfMS5CUk9LRVJfRVJST1JTLmZkYzNPcGVuKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmVzcG9uc2libGUgZm9yIHJlc29sdmluZyB0aGUgZmRjMy5maW5kSW5zdGFuY2VzIGNhbGwuXG5cdCAgICAgKiBNdXN0IGJlIG92ZXJyaWRkZW5cblx0ICAgICAqIEBwYXJhbSBhcHAgQXBwSWRlbnRpZmllciB0aGF0IHdhcyBwYXNzZWQgdG8gZmRjMy5maW5kSW5zdGFuY2VzXG5cdCAgICAgKiBAcGFyYW0gY2xpZW50SWRlbnRpdHkgSWRlbnRpdHkgb2YgdGhlIENsaWVudCBtYWtpbmcgdGhlIHJlcXVlc3QuXG5cdCAgICAgKi9cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBhc3luYyBmZGMzSGFuZGxlRmluZEluc3RhbmNlcyhhcHAsIGNsaWVudElkZW50aXR5KSB7XG5cdCAgICAgICAgY29uc3Qgd2FybmluZyA9ICgwLCB1dGlsc18xLmdlbmVyYXRlT3ZlcnJpZGVXYXJuaW5nKSgnZmRjMy5vcGVuJywgJ0ludGVyb3BCcm9rZXIuZmRjM0hhbmRsZUZpbmRJbnN0YW5jZXMnLCBjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgY29uc29sZS53YXJuKHdhcm5pbmcpO1xuXHQgICAgICAgIHRocm93IG5ldyBFcnJvcih1dGlsc18xLkJST0tFUl9FUlJPUlMuZmRjM0ZpbmRJbnN0YW5jZXMpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXNwb25zaWJsZSBmb3IgcmVzb2x2aW5nIHRoZSBmZGMzLmdldEFwcE1ldGFkYXRhIGNhbGwuXG5cdCAgICAgKiBNdXN0IGJlIG92ZXJyaWRkZW5cblx0ICAgICAqIEBwYXJhbSBhcHAgQXBwSWRlbnRpZmllciB0aGF0IHdhcyBwYXNzZWQgdG8gZmRjMy5nZXRBcHBNZXRhZGF0YVxuXHQgICAgICogQHBhcmFtIGNsaWVudElkZW50aXR5IElkZW50aXR5IG9mIHRoZSBDbGllbnQgbWFraW5nIHRoZSByZXF1ZXN0LlxuXHQgICAgICovXG5cdCAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuXHQgICAgYXN5bmMgZmRjM0hhbmRsZUdldEFwcE1ldGFkYXRhKGFwcCwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCB3YXJuaW5nID0gKDAsIHV0aWxzXzEuZ2VuZXJhdGVPdmVycmlkZVdhcm5pbmcpKCdmZGMzLmdldEFwcE1ldGFkYXRhJywgJ0ludGVyb3BCcm9rZXIuZmRjM0hhbmRsZUdldEFwcE1ldGFkYXRhJywgY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGNvbnNvbGUud2Fybih3YXJuaW5nKTtcblx0ICAgICAgICB0aHJvdyBuZXcgRXJyb3IodXRpbHNfMS5CUk9LRVJfRVJST1JTLmZkYzNHZXRBcHBNZXRhZGF0YSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGJ5IHRoZSBJbnRlcm9wIEJyb2tlciB3aGVuZXZlciBhIENvbnRleHQgaGFuZGxlciB3b3VsZCBmaXJlLlxuXHQgICAgICogRm9yIEZEQzMgMi4wIHlvdSB3b3VsZCBuZWVkIHRvIG92ZXJyaWRlIHRoaXMgZnVuY3Rpb24gYW5kIGFkZCB0aGUgY29udGV4dE1ldGFkYXRhIGFzXG5cdCAgICAgKiBwYXJ0IG9mIHRoZSBDb250ZXh0IG9iamVjdC4gVGhlbiB3b3VsZCB5b3UgbmVlZCB0byBjYWxsXG5cdCAgICAgKiBzdXBlci5pbnZva2VDb250ZXh0SGFuZGxlciBwYXNzaW5nIGl0IHRoaXMgbmV3IENvbnRleHQgb2JqZWN0IGFsb25nIHdpdGggdGhlIGNsaWVudElkZW50aXR5IGFuZCBoYW5kbGVySWRcblx0ICAgICAqIEBwYXJhbSBjbGllbnRJZGVudGl0eVxuXHQgICAgICogQHBhcmFtIGhhbmRsZXJJZFxuXHQgICAgICogQHBhcmFtIGNvbnRleHRcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5QbGF0Zm9ybS5pbml0KHtcblx0ICAgICAqICAgICBpbnRlcm9wT3ZlcnJpZGU6IGFzeW5jIChJbnRlcm9wQnJva2VyKSA9PiB7XG5cdCAgICAgKiAgICAgICAgIGNsYXNzIE92ZXJyaWRlIGV4dGVuZHMgSW50ZXJvcEJyb2tlciB7XG5cdCAgICAgKiAgICAgICAgICAgICBhc3luYyBpbnZva2VDb250ZXh0SGFuZGxlcihjbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBjb250ZXh0KSB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgcmV0dXJuIHN1cGVyLmludm9rZUNvbnRleHRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgLi4uY29udGV4dCxcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgY29udGV4dE1ldGFkYXRhOiB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBJZDogJ29wZW5maW4tYXBwJyxcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZUlkOiAnM0Q1NEQ0NTZEOUhUMCdcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICogICAgICAgICAgICAgICAgIH0pO1xuXHQgICAgICogICAgICAgICAgICAgfVxuXHQgICAgICogICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIHJldHVybiBuZXcgT3ZlcnJpZGUoKTtcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBpbnZva2VDb250ZXh0SGFuZGxlcihjbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBjb250ZXh0KSB7XG5cdCAgICAgICAgY29uc3QgcHJvdmlkZXIgPSBhd2FpdCB0aGlzLmdldFByb3ZpZGVyKCk7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgYXdhaXQgcHJvdmlkZXIuZGlzcGF0Y2goY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwgY29udGV4dCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBpbnZva2luZyBjb250ZXh0IGhhbmRsZXIgJHtoYW5kbGVySWR9IGZvciBjb250ZXh0IHR5cGUgJHtjb250ZXh0LnR5cGV9IGluIGNsaWVudCAke2NsaWVudElkZW50aXR5LnV1aWR9LyR7Y2xpZW50SWRlbnRpdHkubmFtZX0vJHtjbGllbnRJZGVudGl0eS5lbmRwb2ludElkfWAsIGVycm9yKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGJ5IHRoZSBJbnRlcm9wIEJyb2tlciB3aGVuZXZlciBhbiBJbnRlbnQgaGFuZGxlciB3b3VsZCBmaXJlLlxuXHQgICAgICogRm9yIEZEQzMgMi4wIHlvdSB3b3VsZCBuZWVkIHRvIG92ZXJyaWRlIHRoaXMgZnVuY3Rpb24gYW5kIGFkZCB0aGUgY29udGV4dE1ldGFkYXRhIGFzXG5cdCAgICAgKiBwYXJ0IG9mIHRoZSBDb250ZXh0IG9iamVjdCBpbnNpZGUgdGhlIEludGVudCBvYmplY3QuIFRoZW4gd291bGQgeW91IG5lZWQgdG8gY2FsbFxuXHQgICAgICogc3VwZXIuaW52b2tlSW50ZW50SGFuZGxlciBwYXNzaW5nIGl0IHRoaXMgbmV3IEludGVudCBvYmplY3QgYWxvbmcgd2l0aCB0aGUgY2xpZW50SWRlbnRpdHkgYW5kIGhhbmRsZXJJZFxuXHQgICAgICogQHBhcmFtIENsaWVudElkZW50aXR5XG5cdCAgICAgKiBAcGFyYW0gaGFuZGxlcklkXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dFxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLlBsYXRmb3JtLmluaXQoe1xuXHQgICAgICogICAgIGludGVyb3BPdmVycmlkZTogYXN5bmMgKEludGVyb3BCcm9rZXIpID0+IHtcblx0ICAgICAqICAgICAgICAgY2xhc3MgT3ZlcnJpZGUgZXh0ZW5kcyBJbnRlcm9wQnJva2VyIHtcblx0ICAgICAqICAgICAgICAgICAgIGFzeW5jIGludm9rZUludGVudEhhbmRsZXIoY2xpZW50SWRlbnRpdHksIGhhbmRsZXJJZCwgY29udGV4dCkge1xuXHQgICAgICogICAgICAgICAgICAgICAgIGNvbnN0IHsgY29udGV4dCB9ID0gaW50ZW50O1xuXHQgICAgICogICAgICAgICAgICAgICAgIHJldHVybiBzdXBlci5pbnZva2VJbnRlbnRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIHtcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgLi4uaW50ZW50LFxuXHQgICAgICogICAgICAgICAgICAgICAgICAgICBjb250ZXh0OiB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAuLi5jb250ZXh0LFxuXHQgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dE1ldGFkYXRhOiB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlOiB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcElkOiAnb3BlbmZpbi1hcHAnLFxuXHQgICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZUlkOiAnM0Q1NEQ0NTZEOUhUMCdcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgICAgICAgICB9KTtcblx0ICAgICAqICAgICAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgfVxuXHQgICAgICogICAgICAgICByZXR1cm4gbmV3IE92ZXJyaWRlKCk7XG5cdCAgICAgKiAgICAgfVxuXHQgICAgICogfSk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgaW52b2tlSW50ZW50SGFuZGxlcihjbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBpbnRlbnQpIHtcblx0ICAgICAgICBjb25zdCBwcm92aWRlciA9IGF3YWl0IHRoaXMuZ2V0UHJvdmlkZXIoKTtcblx0ICAgICAgICBhd2FpdCBwcm92aWRlci5kaXNwYXRjaChjbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBpbnRlbnQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXNwb25zaWJsZSBmb3IgcmVzb2x2aW5nIGZkYzMuZ2V0SW5mbyBmb3IgRkRDMyAyLjBcblx0ICAgICAqIFdvdWxkIG5lZWQgdG8gcmV0dXJuIHRoZSBvcHRpb25hbEZlYXR1cmVzIGFuZCBhcHBNZXRhZGF0YSBmb3IgdGhlIHtAbGluayBodHRwczovL2ZkYzMuZmlub3Mub3JnL2RvY3MvYXBpL3JlZi9NZXRhZGF0YSNpbXBsZW1lbnRhdGlvbm1ldGFkYXRhIEltcGxlbWVudGF0aW9uTWV0YWRhdGF9LlxuXHQgICAgICogTXVzdCBiZSBvdmVycmlkZGVuLlxuXHQgICAgICogQHBhcmFtIGNsaWVudElkZW50aXR5XG5cdCAgICAgKlxuXHQgICAgICovXG5cdCAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuXHQgICAgYXN5bmMgZmRjM0hhbmRsZUdldEluZm8ocGF5bG9hZCwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCB7IGZkYzNWZXJzaW9uIH0gPSBwYXlsb2FkO1xuXHQgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgIGZkYzNWZXJzaW9uLFxuXHQgICAgICAgICAgICAuLi5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQnJva2VyX2ZkYzNJbmZvLCBcImZcIiksXG5cdCAgICAgICAgICAgIG9wdGlvbmFsRmVhdHVyZXM6IHtcblx0ICAgICAgICAgICAgICAgIE9yaWdpbmF0aW5nQXBwTWV0YWRhdGE6IGZhbHNlLFxuXHQgICAgICAgICAgICAgICAgVXNlckNoYW5uZWxNZW1iZXJzaGlwQVBJczogdHJ1ZVxuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgICBhcHBNZXRhZGF0YToge1xuXHQgICAgICAgICAgICAgICAgYXBwSWQ6ICcnLFxuXHQgICAgICAgICAgICAgICAgaW5zdGFuY2VJZDogJydcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH07XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgYW4gYXJyYXkgb2YgaW5mbyBmb3IgZWFjaCBJbnRlcm9wIENsaWVudCBjb25uZWN0ZWQgdG8gdGhlIEludGVyb3AgQnJva2VyLlxuXHQgICAgICpcblx0ICAgICAqIEZEQzMgMi4wOiBVc2UgdGhlIGVuZHBvaW50SWQgaW4gdGhlIENsaWVudEluZm8gYXMgdGhlIGluc3RhbmNlSWQgd2hlbiBnZW5lcmF0aW5nXG5cdCAgICAgKiBhbiBBcHBJZGVudGlmaWVyLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIEZEQzMgMi4wIE5vdGU6IFdoZW4gbmVlZGluZyBhbiBpbnN0YW5jZUlkIHRvIGdlbmVyYXRlIGFuIEFwcElkZW50aWZpZXIgdXNlIHRoaXMgY2FsbCB0b1xuXHQgICAgICogZ2V0IHRoZSBlbmRwb2ludElkIGFuZCB1c2UgaXQgYXMgdGhlIGluc3RhbmNlSWQuIEluIHRoZSBFeGFtcGxlIGJlbG93IHdlIG92ZXJyaWRlIGhhbmRsZUZpcmVkSW50ZW50XG5cdCAgICAgKiBhbmQgdGhlbiBjYWxsIHN1cGVyLmdldEFsbENsaWVudEluZm8gdG8gZ2VuZXJhdGUgdGhlIEFwcElkZW50aWZpZXIgZm9yIHRoZSBJbnRlbnRSZXNvbHV0aW9uLlxuXHQgICAgICpcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIC8vIEZEQzMgMi4wIEV4YW1wbGU6XG5cdCAgICAgKiBmaW4uUGxhdGZvcm0uaW5pdCh7XG5cdCAgICAgKiAgICAgaW50ZXJvcE92ZXJyaWRlOiBhc3luYyAoSW50ZXJvcEJyb2tlciwgLi4uYXJncykgPT4ge1xuXHQgICAgICogICAgICAgICBjbGFzcyBPdmVycmlkZSBleHRlbmRzIEludGVyb3BCcm9rZXIge1xuXHQgICAgICogICAgICAgICAgICAgYXN5bmMgaGFuZGxlRmlyZWRJbnRlbnQoaW50ZW50KSB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgc3VwZXIuc2V0SW50ZW50VGFyZ2V0KGludGVudCwgeyB1dWlkOiAncGxhdGZvcm0tdXVpZCcsIG5hbWU6ICdpbnRlbnQtdmlldycgfSk7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zdCB3aW4gPSBmaW4uV2luZG93LndyYXBTeW5jKHsgbmFtZTogJ2ZvbycsIHV1aWQ6ICdwbGF0Zm9ybS11dWlkJyB9KTtcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zdCBjcmVhdGVkVmlldyA9IGF3YWl0IHBsYXRmb3JtLmNyZWF0ZVZpZXcoeyB1cmw6ICdodHRwOi8vb3BlbmZpbi5jbycsIG5hbWU6ICdpbnRlbnQtdmlldycgfSwgd2luLmlkZW50aXR5KTtcblx0ICAgICAqXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgY29uc3QgYWxsQ2xpZW50SW5mbyA9IGF3YWl0IHN1cGVyLmdldEFsbENsaWVudEluZm8oKTtcblx0ICAgICAqXG5cdCAgICAgKiAgICAgICAgICAgICAgICAgY29uc3QgaW5mb0ZvclRhcmdldCA9IGFsbENsaWVudEluZm8uZmluZCgoY2xpZW50SW5mbykgPT4ge1xuXHQgICAgICogICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2xpZW50SW5mby51dWlkID09PSAncGxhdGZvcm0tdXVpZCcgJiYgY2xpZW50SW5mby5uYW1lID09PSAnaW50ZW50LXZpZXcnO1xuXHQgICAgICogICAgICAgICAgICAgICAgIH0pO1xuXHQgICAgICpcblx0ICAgICAqICAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2UgPSB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgIGFwcElkOiAnaW50ZW50LXZpZXcnLFxuXHQgICAgICogICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZUlkOiBpbmZvRm9yVGFyZ2V0LmVuZHBvaW50SWRcblx0ICAgICAqICAgICAgICAgICAgICAgICB9XG5cdCAgICAgKlxuXHQgICAgICogICAgICAgICAgICAgICAgIHJldHVybiB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgICAgIHNvdXJjZSxcblx0ICAgICAqICAgICAgICAgICAgICAgICAgICAgaW50ZW50OiBpbnRlbnQubmFtZVxuXHQgICAgICogICAgICAgICAgICAgICAgIH1cblx0ICAgICAqXG5cdCAgICAgKiAgICAgICAgICAgICB9XG5cdCAgICAgKiAgICAgICAgIH1cblx0ICAgICAqICAgICAgICAgcmV0dXJuIG5ldyBPdmVycmlkZSguLi5hcmdzKTtcblx0ICAgICAqICAgICB9XG5cdCAgICAgKiB9KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRBbGxDbGllbnRJbmZvKCkge1xuXHQgICAgICAgIGNvbnN0IHByb3ZpZGVyID0gYXdhaXQgdGhpcy5nZXRQcm92aWRlcigpO1xuXHQgICAgICAgIHJldHVybiBwcm92aWRlci5nZXRBbGxDbGllbnRJbmZvKCk7XG5cdCAgICB9XG5cdCAgICAvKlxuXHQgICAgU25hcHNob3QgQVBJc1xuXHQgICAgKi9cblx0ICAgIC8vIFVzZWQgdG8gc2F2ZSBpbnRlcm9wIGJyb2tlciBzdGF0ZSBpbiBzbmFwc2hvdHNcblx0ICAgIGRlY29yYXRlU25hcHNob3Qoc25hcHNob3QpIHtcblx0ICAgICAgICByZXR1cm4geyAuLi5zbmFwc2hvdCwgaW50ZXJvcFNuYXBzaG90RGV0YWlsczogeyBjb250ZXh0R3JvdXBTdGF0ZXM6IHRoaXMuZ2V0Q29udGV4dEdyb3VwU3RhdGVzKCkgfSB9O1xuXHQgICAgfVxuXHQgICAgLy8gVXNlZCB0byByZXN0b3JlIGludGVyb3AgYnJva2VyIHN0YXRlIGluIHNuYXBzaG90cy5cblx0ICAgIGFwcGx5U25hcHNob3Qoc25hcHNob3QsIG9wdGlvbnMpIHtcblx0ICAgICAgICBjb25zdCBjb250ZXh0R3JvdXBTdGF0ZXMgPSBzbmFwc2hvdD8uaW50ZXJvcFNuYXBzaG90RGV0YWlscz8uY29udGV4dEdyb3VwU3RhdGVzO1xuXHQgICAgICAgIGlmIChjb250ZXh0R3JvdXBTdGF0ZXMpIHtcblx0ICAgICAgICAgICAgaWYgKCFvcHRpb25zPy5jbG9zZUV4aXN0aW5nV2luZG93cykge1xuXHQgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVFeGlzdGluZ0NsaWVudHMoY29udGV4dEdyb3VwU3RhdGVzKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB0aGlzLnJlaHlkcmF0ZUNvbnRleHRHcm91cFN0YXRlcyhjb250ZXh0R3JvdXBTdGF0ZXMpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIHVwZGF0ZUV4aXN0aW5nQ2xpZW50cyhjb250ZXh0R3JvdXBTdGF0ZXMpIHtcblx0ICAgICAgICBjb25zdCBjbGllbnRzID0gdGhpcy5pbnRlcm9wQ2xpZW50cztcblx0ICAgICAgICBjbGllbnRzLmZvckVhY2goKHN1YlN0YXRlKSA9PiB7XG5cdCAgICAgICAgICAgIGNvbnN0IHsgY2xpZW50SWRlbnRpdHksIGNvbnRleHRHcm91cElkLCBjb250ZXh0SGFuZGxlcnMgfSA9IHN1YlN0YXRlO1xuXHQgICAgICAgICAgICBpZiAoY29udGV4dEdyb3VwSWQpIHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IGdyb3VwQ29udGV4dHMgPSBjb250ZXh0R3JvdXBTdGF0ZXNbY29udGV4dEdyb3VwSWRdO1xuXHQgICAgICAgICAgICAgICAgZm9yIChjb25zdCBbLCBjb250ZXh0XSBvZiBPYmplY3QuZW50cmllcyhncm91cENvbnRleHRzKSkge1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnRleHRIYW5kbGVycy5mb3JFYWNoKChjb250ZXh0SGFuZGxlcikgPT4ge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IGhhbmRsZXJJZCwgY29udGV4dFR5cGUgfSA9IGNvbnRleHRIYW5kbGVyO1xuXHQgICAgICAgICAgICAgICAgICAgICAgICBpZiAoSW50ZXJvcEJyb2tlci5pc0NvbnRleHRUeXBlQ29tcGF0aWJsZShjb250ZXh0LnR5cGUsIGNvbnRleHRUeXBlKSkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnZva2VDb250ZXh0SGFuZGxlcihjbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBjb250ZXh0KTtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdCAgICAvLyBVc2VkIHRvIHN0b3JlIGNvbnRleHQgZ3JvdXAgc3RhdGUgaW4gc25hcHNob3RzXG5cdCAgICBnZXRDb250ZXh0R3JvdXBTdGF0ZXMoKSB7XG5cdCAgICAgICAgcmV0dXJuIEludGVyb3BCcm9rZXIudG9PYmplY3QodGhpcy5jb250ZXh0R3JvdXBzQnlJZCk7XG5cdCAgICB9XG5cdCAgICAvLyBVc2VkIHRvIHJlaHlkcmF0ZSB0aGUgY29udGV4dCBzdGF0ZSBmcm9tIGEgc25hcHNob3Rcblx0ICAgIHJlaHlkcmF0ZUNvbnRleHRHcm91cFN0YXRlcyhpbmNvbWluZ0NvbnRleHRHcm91cFN0YXRlcykge1xuXHQgICAgICAgIGNvbnN0IGNvbnRleHRHcm91cFN0YXRlcyA9IE9iamVjdC5lbnRyaWVzKGluY29taW5nQ29udGV4dEdyb3VwU3RhdGVzKTtcblx0ICAgICAgICBmb3IgKGNvbnN0IFtjb250ZXh0R3JvdXBJZCwgY29udGV4dHNdIG9mIGNvbnRleHRHcm91cFN0YXRlcykge1xuXHQgICAgICAgICAgICBjb25zdCBjb250ZXh0T2JqZWN0cyA9IE9iamVjdC5lbnRyaWVzKGNvbnRleHRzKTtcblx0ICAgICAgICAgICAgZm9yIChjb25zdCBbY29udGV4dFR5cGUsIGNvbnRleHRdIG9mIGNvbnRleHRPYmplY3RzKSB7XG5cdCAgICAgICAgICAgICAgICBpZiAodGhpcy5jb250ZXh0R3JvdXBzQnlJZC5oYXMoY29udGV4dEdyb3VwSWQpKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudENvbnRleHRHcm91cFN0YXRlID0gdGhpcy5jb250ZXh0R3JvdXBzQnlJZC5nZXQoY29udGV4dEdyb3VwSWQpO1xuXHQgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDb250ZXh0R3JvdXBTdGF0ZS5zZXQoY29udGV4dFR5cGUsIGNvbnRleHQpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBsb2dpYyB3aWxsIGNoYW5nZSB3aGVuIGR5bmFtaWMgY29udGV4dCBncm91cCBjcmVhdGlvbiBjb21lcyBpbi5cblx0ICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYEF0dGVtcHRpbmcgdG8gc2V0IGEgY29udGV4dCBncm91cCB0aGF0IGlzbid0IGluIHRoZSBjb250ZXh0IGdyb3VwIG1hcHBpbmcuIFNraXBwaW5nIGNvbnRleHQgZ3JvdXAgcmVoeWRyYXRpb24gZm9yOiAke2NvbnRleHRHcm91cElkfWApO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLypcblx0ICAgIEludGVybmFsIENvbnRleHQgSGFuZGxlciBBUElzXG5cdCAgICAqL1xuXHQgICAgLy8gVXNlZCB0byBnaXZlIGNvbnRleHQgdG8gYSBjbGllbnQgdGhhdCBoYXMgcmVnaXN0ZXJlZCB0aGVpciBjb250ZXh0IGhhbmRsZXJcblx0ICAgIGNvbnRleHRIYW5kbGVyUmVnaXN0ZXJlZCh7IGNvbnRleHRUeXBlLCBoYW5kbGVySWQgfSwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCBoYW5kbGVySW5mbyA9IHsgY29udGV4dFR5cGUsIGhhbmRsZXJJZCB9O1xuXHQgICAgICAgIGNvbnN0IGNsaWVudFN0YXRlID0gdGhpcy5nZXRDbGllbnRTdGF0ZShjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgY2xpZW50U3RhdGU/LmNvbnRleHRIYW5kbGVycy5zZXQoaGFuZGxlcklkLCBoYW5kbGVySW5mbyk7XG5cdCAgICAgICAgaWYgKGNsaWVudFN0YXRlICYmIGNsaWVudFN0YXRlLmNvbnRleHRHcm91cElkKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IHsgY29udGV4dEdyb3VwSWQgfSA9IGNsaWVudFN0YXRlO1xuXHQgICAgICAgICAgICBjb25zdCBjb250ZXh0R3JvdXBNYXAgPSB0aGlzLmNvbnRleHRHcm91cHNCeUlkLmdldChjb250ZXh0R3JvdXBJZCk7XG5cdCAgICAgICAgICAgIGlmIChjb250ZXh0VHlwZSA9PT0gdW5kZWZpbmVkKSB7XG5cdCAgICAgICAgICAgICAgICAvLyBTZW5kIHRoaXMgc2luZ2xlIGhhbmRsZXIgYWxsIG9mIHRoZSBjb250ZXh0LCBiZWNhdXNlIGl0IGFjY2VwdHMgYWxsLlxuXHQgICAgICAgICAgICAgICAgY29udGV4dEdyb3VwTWFwLmZvckVhY2goKGNvbnRleHQsIF8pID0+IHtcblx0ICAgICAgICAgICAgICAgICAgICB0aGlzLmludm9rZUNvbnRleHRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGNvbnRleHQpO1xuXHQgICAgICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgZWxzZSBpZiAoY29udGV4dEdyb3VwTWFwLmhhcyhjb250ZXh0VHlwZSkpIHtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRleHRGb3JUeXBlID0gY29udGV4dEdyb3VwTWFwLmdldChjb250ZXh0VHlwZSk7XG5cdCAgICAgICAgICAgICAgICBpZiAoY29udGV4dEZvclR5cGUpIHtcblx0ICAgICAgICAgICAgICAgICAgICB0aGlzLmludm9rZUNvbnRleHRIYW5kbGVyKGNsaWVudElkZW50aXR5LCBoYW5kbGVySWQsIGNvbnRleHRGb3JUeXBlKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBhc3luYyBpbnRlbnRIYW5kbGVyUmVnaXN0ZXJlZChwYXlsb2FkLCBjbGllbnRJZGVudGl0eSkge1xuXHQgICAgICAgIGNvbnN0IHsgaGFuZGxlcklkIH0gPSBwYXlsb2FkO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudEludGVudEluZm8gPSB0aGlzLmludGVudENsaWVudE1hcC5nZXQoY2xpZW50SWRlbnRpdHkubmFtZSk7XG5cdCAgICAgICAgY29uc3QgaGFuZGxlckluZm8gPSBjbGllbnRJbnRlbnRJbmZvPy5nZXQoaGFuZGxlcklkKTtcblx0ICAgICAgICBpZiAoIWNsaWVudEludGVudEluZm8pIHtcblx0ICAgICAgICAgICAgdGhpcy5pbnRlbnRDbGllbnRNYXAuc2V0KGNsaWVudElkZW50aXR5Lm5hbWUsIG5ldyBNYXAoKSk7XG5cdCAgICAgICAgICAgIGNvbnN0IG5ld0hhbmRsZXJJbmZvTWFwID0gdGhpcy5pbnRlbnRDbGllbnRNYXAuZ2V0KGNsaWVudElkZW50aXR5Lm5hbWUpO1xuXHQgICAgICAgICAgICBpZiAobmV3SGFuZGxlckluZm9NYXApIHtcblx0ICAgICAgICAgICAgICAgIG5ld0hhbmRsZXJJbmZvTWFwLnNldChoYW5kbGVySWQsIHsgaXNSZWFkeTogdHJ1ZSwgcGVuZGluZ0ludGVudHM6IFtdLCBjbGllbnRJZGVudGl0eSB9KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgICAgICBlbHNlIGlmICghaGFuZGxlckluZm8pIHtcblx0ICAgICAgICAgICAgY2xpZW50SW50ZW50SW5mby5zZXQoaGFuZGxlcklkLCB7IGlzUmVhZHk6IHRydWUsIHBlbmRpbmdJbnRlbnRzOiBbXSwgY2xpZW50SWRlbnRpdHkgfSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICBjb25zdCB7IHBlbmRpbmdJbnRlbnRzIH0gPSBoYW5kbGVySW5mbztcblx0ICAgICAgICAgICAgaGFuZGxlckluZm8uY2xpZW50SWRlbnRpdHkgPSBjbGllbnRJZGVudGl0eTtcblx0ICAgICAgICAgICAgaGFuZGxlckluZm8uaXNSZWFkeSA9IHRydWU7XG5cdCAgICAgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgICAgICBpZiAocGVuZGluZ0ludGVudHMubGVuZ3RoID4gMCkge1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnN0IGludGVudFRvU2VuZCA9IHBlbmRpbmdJbnRlbnRzW3BlbmRpbmdJbnRlbnRzLmxlbmd0aCAtIDFdO1xuXHQgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuaW52b2tlSW50ZW50SGFuZGxlcihjbGllbnRJZGVudGl0eSwgaGFuZGxlcklkLCBpbnRlbnRUb1NlbmQpO1xuXHQgICAgICAgICAgICAgICAgICAgIGhhbmRsZXJJbmZvLnBlbmRpbmdJbnRlbnRzID0gW107XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBpbnZva2luZyBpbnRlbnQgaGFuZGxlcjogJHtoYW5kbGVySWR9IGZvciBjbGllbnQgJHtjbGllbnRJZGVudGl0eS51dWlkfS8ke2NsaWVudElkZW50aXR5Lm5hbWV9LyR7Y2xpZW50SWRlbnRpdHkuZW5kcG9pbnRJZH1gKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8vIFVzZWQgdG8gcmVtb3ZlIGEgY29udGV4dCBoYW5kbGVyIGZvciBhIGNsaWVudFxuXHQgICAgcmVtb3ZlQ29udGV4dEhhbmRsZXIoeyBoYW5kbGVySWQgfSwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICBjb25zdCBjbGllbnRTdGF0ZSA9IHRoaXMuZ2V0Q2xpZW50U3RhdGUoY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgIGlmIChjbGllbnRTdGF0ZSkge1xuXHQgICAgICAgICAgICBjbGllbnRTdGF0ZS5jb250ZXh0SGFuZGxlcnMuZGVsZXRlKGhhbmRsZXJJZCk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgaGFuZGxlSm9pblNlc3Npb25Db250ZXh0R3JvdXAoeyBzZXNzaW9uQ29udGV4dEdyb3VwSWQgfSwgY2xpZW50SWRlbnRpdHkpIHtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICBpZiAoIXNlc3Npb25Db250ZXh0R3JvdXBJZCkge1xuXHQgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gam9pbiBzZXNzaW9uIGNvbnRleHQgZ3JvdXA6IG11c3Qgc3BlY2lmeSBncm91cCBpZC4nKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBjb25zdCBzZXNzaW9uQ29udGV4dEdyb3VwID0gdGhpcy5zZXNzaW9uQ29udGV4dEdyb3VwTWFwLmdldChzZXNzaW9uQ29udGV4dEdyb3VwSWQpO1xuXHQgICAgICAgICAgICBpZiAoc2Vzc2lvbkNvbnRleHRHcm91cCkge1xuXHQgICAgICAgICAgICAgICAgc2Vzc2lvbkNvbnRleHRHcm91cC5yZWdpc3Rlck5ld0NsaWVudChjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgICAgICBjb25zdCBuZXdTZXNzaW9uQ29udGV4dEdyb3VwQnJva2VyID0gbmV3IFNlc3Npb25Db250ZXh0R3JvdXBCcm9rZXJfMS5kZWZhdWx0KHRoaXMuY2hhbm5lbCwgc2Vzc2lvbkNvbnRleHRHcm91cElkKTtcblx0ICAgICAgICAgICAgICAgIG5ld1Nlc3Npb25Db250ZXh0R3JvdXBCcm9rZXIucmVnaXN0ZXJOZXdDbGllbnQoY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uQ29udGV4dEdyb3VwTWFwLnNldChzZXNzaW9uQ29udGV4dEdyb3VwSWQsIG5ld1Nlc3Npb25Db250ZXh0R3JvdXBCcm9rZXIpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIHJldHVybiB7IGhhc0NvbmZsaWN0OiB0aGlzLmNvbnRleHRHcm91cHNCeUlkLmhhcyhzZXNzaW9uQ29udGV4dEdyb3VwSWQpIH07XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qXG5cdCAgICBJbnRlcm5hbCBVdGlsdGllc1xuXHQgICAgKi9cblx0ICAgIC8vIEdldHRlciBmb3IgaW50ZXJvcCBpbmZvIGZvciBhIGNsaWVudC5cblx0ICAgIGdldENsaWVudFN0YXRlKGlkKSB7XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuaW50ZXJvcENsaWVudHMuZ2V0KGlkLmVuZHBvaW50SWQpO1xuXHQgICAgfVxuXHQgICAgLy8gVXRpbCBmb3IgZ2V0Q29udGV4dEdyb3VwU3RhdGVzLiBTZXJpYWxpemVzIHRoZSBjb250ZXh0R3JvdXBTdGF0ZXMgb2JqZWN0IHNvIHdlIGNhbiBzdG9yZSBpdC5cblx0ICAgIHN0YXRpYyB0b09iamVjdChtYXApIHtcblx0ICAgICAgICBjb25zdCBvYmplY3RGcm9tTWFwID0gT2JqZWN0LmZyb21FbnRyaWVzKG1hcCk7XG5cdCAgICAgICAgY29uc3QgbmV3T2JqZWN0ID0ge307XG5cdCAgICAgICAgT2JqZWN0LmVudHJpZXMob2JqZWN0RnJvbU1hcCkuZm9yRWFjaCgoW2NvbnRleHRHcm91cElkLCBjb250ZXh0TWFwXSkgPT4ge1xuXHQgICAgICAgICAgICBjb25zdCBuZXdDb250ZXh0T2JqZWN0ID0gT2JqZWN0LmZyb21FbnRyaWVzKGNvbnRleHRNYXApO1xuXHQgICAgICAgICAgICBuZXdPYmplY3RbY29udGV4dEdyb3VwSWRdID0gbmV3Q29udGV4dE9iamVjdDtcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gbmV3T2JqZWN0O1xuXHQgICAgfVxuXHQgICAgc3RhdGljIGNoZWNrQ29udGV4dEludGVncml0eShjb250ZXh0KSB7XG5cdCAgICAgICAgaWYgKCFjb250ZXh0KSB7XG5cdCAgICAgICAgICAgIHJldHVybiB7IGlzVmFsaWQ6IGZhbHNlLCByZWFzb246ICdObyBjb250ZXh0IHN1cHBsaWVkJyB9O1xuXHQgICAgICAgIH1cblx0ICAgICAgICBpZiAodHlwZW9mIGNvbnRleHQgIT09ICdvYmplY3QnKSB7XG5cdCAgICAgICAgICAgIHJldHVybiB7IGlzVmFsaWQ6IGZhbHNlLCByZWFzb246ICdDb250ZXh0IG11c3QgYmUgYW4gT2JqZWN0JyB9O1xuXHQgICAgICAgIH1cblx0ICAgICAgICBpZiAoIWNvbnRleHQudHlwZSkge1xuXHQgICAgICAgICAgICByZXR1cm4geyBpc1ZhbGlkOiBmYWxzZSwgcmVhc29uOiAnQ29udGV4dCBtdXN0IGhhdmUgYSB0eXBlIHByb3BlcnR5JyB9O1xuXHQgICAgICAgIH1cblx0ICAgICAgICBpZiAoY29udGV4dC5pZCAmJiB0eXBlb2YgY29udGV4dC5pZCAhPT0gJ29iamVjdCcpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIHtcblx0ICAgICAgICAgICAgICAgIGlzVmFsaWQ6IGZhbHNlLFxuXHQgICAgICAgICAgICAgICAgcmVhc29uOiAnQ29udGV4dCBpZCBtdXN0IGJlIGFuIE9iamVjdCBwb3B1bGF0ZWQgd2l0aCBrZXktdmFsdWUgaWRlbnRpZmllcnMgKGlmIHNldCknXG5cdCAgICAgICAgICAgIH07XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmIChjb250ZXh0LmlkKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IHsgaWQgfSA9IGNvbnRleHQ7XG5cdCAgICAgICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhpZCk7XG5cdCAgICAgICAgICAgIGxldCBmb3VuZEJhZElkZW50aWZpZXIgPSBmYWxzZTtcblx0ICAgICAgICAgICAgaWYgKCFrZXlzLmxlbmd0aCkge1xuXHQgICAgICAgICAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogZmFsc2UsIHJlYXNvbjogJ0NvbnRleHQgaWQgbXVzdCBoYXZlIGF0IGxlYXN0IG9uZSBrZXktdmFsdWUgaWRlbnRpZmllcicgfTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBrZXlzLmZvckVhY2goKGtleSkgPT4ge1xuXHQgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBrZXkgIT09ICdzdHJpbmcnIHx8IHR5cGVvZiBpZFtrZXldICE9PSAnc3RyaW5nJykge1xuXHQgICAgICAgICAgICAgICAgICAgIGZvdW5kQmFkSWRlbnRpZmllciA9IHRydWU7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICBpZiAoZm91bmRCYWRJZGVudGlmaWVyKSB7XG5cdCAgICAgICAgICAgICAgICByZXR1cm4geyBpc1ZhbGlkOiBmYWxzZSwgcmVhc29uOiAnQ29udGV4dCBpZCBrZXktdmFsdWUgaWRlbnRpZmllcnMgbXVzdCBiZSBvZiB0eXBlIHN0cmluZycgfTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgICAgICBpZiAoY29udGV4dC5uYW1lICYmIHR5cGVvZiBjb250ZXh0Lm5hbWUgIT09ICdzdHJpbmcnKSB7XG5cdCAgICAgICAgICAgIHJldHVybiB7IGlzVmFsaWQ6IGZhbHNlLCByZWFzb246ICdDb250ZXh0IG5hbWUgbXVzdCBiZSBvZiBzdHJpbmcgdHlwZSAoaWYgc2V0KScgfTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogdHJ1ZSB9O1xuXHQgICAgfVxuXHQgICAgLy8gVXRpbCB0byBjaGVjayBhIGNsaWVudCBpZGVudGl0eS5cblx0ICAgIHN0YXRpYyBoYXNFbmRwb2ludElkKHRhcmdldCkge1xuXHQgICAgICAgIHJldHVybiB0YXJnZXQuZW5kcG9pbnRJZCAhPT0gdW5kZWZpbmVkO1xuXHQgICAgfVxuXHQgICAgLy8gVXRpbCB0byBjaGVjayBpZiB3ZSBzaG91bGQgc2VuZCBhIGNvbnRleHQgdG8gYSBoYW5kbGVyLlxuXHQgICAgc3RhdGljIGlzQ29udGV4dFR5cGVDb21wYXRpYmxlKGNvbnRleHRUeXBlLCByZWdpc3RlcmVkQ29udGV4dFR5cGUpIHtcblx0ICAgICAgICByZXR1cm4gdHlwZW9mIHJlZ2lzdGVyZWRDb250ZXh0VHlwZSA9PT0gJ3VuZGVmaW5lZCcgfHwgY29udGV4dFR5cGUgPT09IHJlZ2lzdGVyZWRDb250ZXh0VHlwZTtcblx0ICAgIH1cblx0ICAgIC8vIFNldHVwIGZ1bmN0aW9uIGZvciBzdGF0ZSBtYXBwaW5nXG5cdCAgICBzZXRDb250ZXh0R3JvdXBNYXAoKSB7XG5cdCAgICAgICAgLy8gVGhpcyB3YXksIGlmIGEgdXNlciBvdmVycmlkZXMgdGhpcy5nZXRDb250ZXh0R3JvdXBzLCBpdCdzIHJlZmxlY3RlZCBpbiB0aGUgY29udGV4dEdyb3VwTWFwcGluZy5cblx0ICAgICAgICBmb3IgKGNvbnN0IGNvbnRleHRHcm91cEluZm8gb2YgdGhpcy5nZXRDb250ZXh0R3JvdXBzKCkpIHtcblx0ICAgICAgICAgICAgdGhpcy5jb250ZXh0R3JvdXBzQnlJZC5zZXQoY29udGV4dEdyb3VwSW5mby5pZCwgbmV3IE1hcCgpKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICBhc3luYyBzZXRDdXJyZW50Q29udGV4dEdyb3VwSW5DbGllbnRPcHRpb25zKGNsaWVudElkZW50aXR5LCBjb250ZXh0R3JvdXBJZCkge1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGVudGl0eUluZm8gPSBhd2FpdCB0aGlzLmZpbi5TeXN0ZW0uZ2V0RW50aXR5SW5mbyhjbGllbnRJZGVudGl0eS51dWlkLCBjbGllbnRJZGVudGl0eS5uYW1lKTtcblx0ICAgICAgICAgICAgbGV0IGVudGl0eTtcblx0ICAgICAgICAgICAgaWYgKGVudGl0eUluZm8uZW50aXR5VHlwZSA9PT0gJ3ZpZXcnKSB7XG5cdCAgICAgICAgICAgICAgICBlbnRpdHkgPSBhd2FpdCB0aGlzLmZpbi5WaWV3LndyYXAoY2xpZW50SWRlbnRpdHkpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGVsc2UgaWYgKGVudGl0eUluZm8uZW50aXR5VHlwZSA9PT0gJ3dpbmRvdycpIHtcblx0ICAgICAgICAgICAgICAgIGVudGl0eSA9IGF3YWl0IHRoaXMuZmluLldpbmRvdy53cmFwKGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBpZiAoZW50aXR5KSB7XG5cdCAgICAgICAgICAgICAgICBhd2FpdCBlbnRpdHkudXBkYXRlT3B0aW9ucyh7XG5cdCAgICAgICAgICAgICAgICAgICAgaW50ZXJvcDoge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Q29udGV4dEdyb3VwOiBjb250ZXh0R3JvdXBJZFxuXHQgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICAvLyAgTWF5IGZpbGUgaW4gaW50ZXJvcFxuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIGFzeW5jIHNldHVwQ2hhbm5lbFByb3ZpZGVyKCkge1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGNoYW5uZWwgPSBhd2FpdCB0aGlzLmdldFByb3ZpZGVyKCk7XG5cdCAgICAgICAgICAgIHRoaXMuY2hhbm5lbCA9IGNoYW5uZWw7XG5cdCAgICAgICAgICAgIHRoaXMud2lyZUNoYW5uZWwoY2hhbm5lbCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHNldHRpbmcgdXAgSW50ZXJvcCBCcm9rZXIgQ2hhbm5lbCBQcm92aWRlcjogJHtlcnJvcn1gKTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvLyBTZXR1cCBDaGFubmVsIENvbm5lY3Rpb24gTG9naWNcblx0ICAgIHdpcmVDaGFubmVsKGNoYW5uZWwpIHtcblx0ICAgICAgICBjaGFubmVsLm9uQ29ubmVjdGlvbihhc3luYyAoY2xpZW50SWRlbnRpdHksIC8vIFRPRE8oQ09SRS04MTEpOiByZW1vdmUgaW5saW5lIGludGVyc2VjdGVkIHR5cGVcblx0ICAgICAgICBwYXlsb2FkKSA9PiB7XG5cdCAgICAgICAgICAgIGlmICghKGF3YWl0IHRoaXMuaXNDb25uZWN0aW9uQXV0aG9yaXplZChjbGllbnRJZGVudGl0eSwgcGF5bG9hZCkpKSB7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENvbm5lY3Rpb24gbm90IGF1dGhvcml6ZWQgZm9yICR7Y2xpZW50SWRlbnRpdHkudXVpZH0sICR7Y2xpZW50SWRlbnRpdHkubmFtZX1gKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBpZiAoIWNsaWVudElkZW50aXR5LmVuZHBvaW50SWQpIHtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVmVyc2lvbiB0b28gb2xkIHRvIGJlIGNvbXBhdGlibGUgd2l0aCBJbnRlcm9wLiBQbGVhc2UgdXBncmFkZSB5b3VyIHJ1bnRpbWUgdG8gYSBtb3JlIHJlY2VudCB2ZXJzaW9uLicpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNvbnN0IGNsaWVudFN1YnNjcmlwdGlvblN0YXRlID0ge1xuXHQgICAgICAgICAgICAgICAgY29udGV4dEdyb3VwSWQ6IHVuZGVmaW5lZCxcblx0ICAgICAgICAgICAgICAgIGNvbnRleHRIYW5kbGVyczogbmV3IE1hcCgpLFxuXHQgICAgICAgICAgICAgICAgY2xpZW50SWRlbnRpdHlcblx0ICAgICAgICAgICAgfTtcblx0ICAgICAgICAgICAgLy8gT25seSBhbGxvdyB0aGUgY2xpZW50IHRvIGpvaW4gYSBjb250ZXh0R3JvdXAgdGhhdCBhY3R1YWxseSBleGlzdHMuXG5cdCAgICAgICAgICAgIGlmIChwYXlsb2FkPy5jdXJyZW50Q29udGV4dEdyb3VwICYmIHRoaXMuY29udGV4dEdyb3Vwc0J5SWQuaGFzKHBheWxvYWQuY3VycmVudENvbnRleHRHcm91cCkpIHtcblx0ICAgICAgICAgICAgICAgIGNsaWVudFN1YnNjcmlwdGlvblN0YXRlLmNvbnRleHRHcm91cElkID0gcGF5bG9hZD8uY3VycmVudENvbnRleHRHcm91cDtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB0aGlzLmludGVyb3BDbGllbnRzLnNldChjbGllbnRJZGVudGl0eS5lbmRwb2ludElkLCBjbGllbnRTdWJzY3JpcHRpb25TdGF0ZSk7XG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY2hhbm5lbC5vbkRpc2Nvbm5lY3Rpb24oKGNsaWVudElkZW50aXR5KSA9PiB7XG5cdCAgICAgICAgICAgIHRoaXMuaW50ZXJvcENsaWVudHMuZGVsZXRlKGNsaWVudElkZW50aXR5LmVuZHBvaW50SWQpO1xuXHQgICAgICAgICAgICBjb25zdCB0YXJnZXRJbmZvID0gdGhpcy5pbnRlbnRDbGllbnRNYXAuZ2V0KGNsaWVudElkZW50aXR5Lm5hbWUpO1xuXHQgICAgICAgICAgICBpZiAodGFyZ2V0SW5mbyAmJiBjbGllbnRJZGVudGl0eS51dWlkID09PSB0aGlzLmZpbi5tZS51dWlkKSB7XG5cdCAgICAgICAgICAgICAgICB0YXJnZXRJbmZvLmZvckVhY2goKGhhbmRsZXIpID0+IHtcblx0ICAgICAgICAgICAgICAgICAgICBoYW5kbGVyLmlzUmVhZHkgPSBmYWxzZTtcblx0ICAgICAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIHRoaXMuc2Vzc2lvbkNvbnRleHRHcm91cE1hcC5mb3JFYWNoKChzZXNzaW9uQ29udGV4dEdyb3VwKSA9PiB7XG5cdCAgICAgICAgICAgICAgICBzZXNzaW9uQ29udGV4dEdyb3VwLm9uRGlzY29ubmVjdGlvbihjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgICAgIH0pO1xuXHQgICAgICAgICAgICB0aGlzLmNsaWVudERpc2Nvbm5lY3RlZChjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY2hhbm5lbC5iZWZvcmVBY3Rpb24oYXN5bmMgKGFjdGlvbiwgcGF5bG9hZCwgY2xpZW50SWRlbnRpdHkpID0+IHtcblx0ICAgICAgICAgICAgaWYgKCEoYXdhaXQgdGhpcy5pc0FjdGlvbkF1dGhvcml6ZWQoYWN0aW9uLCBwYXlsb2FkLCBjbGllbnRJZGVudGl0eSkpKSB7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFjdGlvbiAoJHthY3Rpb259KSBub3QgYXV0aG9yaXplZCBmb3IgJHtjbGllbnRJZGVudGl0eS51dWlkfSwgJHtjbGllbnRJZGVudGl0eS5uYW1lfWApO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGlmICh0aGlzLmxvZ2dpbmc/LmJlZm9yZUFjdGlvbj8uZW5hYmxlZCkge1xuXHQgICAgICAgICAgICAgICAgY29uc29sZS5sb2coYWN0aW9uLCBwYXlsb2FkLCBjbGllbnRJZGVudGl0eSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjaGFubmVsLmFmdGVyQWN0aW9uKChhY3Rpb24sIHBheWxvYWQsIGNsaWVudElkZW50aXR5KSA9PiB7XG5cdCAgICAgICAgICAgIGlmICh0aGlzLmxvZ2dpbmc/LmFmdGVyQWN0aW9uPy5lbmFibGVkKSB7XG5cdCAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhhY3Rpb24sIHBheWxvYWQsIGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIC8vIENsaWVudCBmdW5jdGlvbnNcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdzZXRDb250ZXh0JywgdGhpcy5zZXRDb250ZXh0LmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2ZpcmVJbnRlbnQnLCB0aGlzLmhhbmRsZUZpcmVkSW50ZW50LmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2dldEN1cnJlbnRDb250ZXh0JywgdGhpcy5nZXRDdXJyZW50Q29udGV4dC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdnZXRJbmZvRm9ySW50ZW50JywgdGhpcy5oYW5kbGVJbmZvRm9ySW50ZW50LmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2dldEluZm9Gb3JJbnRlbnRzQnlDb250ZXh0JywgdGhpcy5oYW5kbGVJbmZvRm9ySW50ZW50c0J5Q29udGV4dC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdmaXJlSW50ZW50Rm9yQ29udGV4dCcsIHRoaXMuaGFuZGxlRmlyZWRJbnRlbnRGb3JDb250ZXh0LmJpbmQodGhpcykpO1xuXHQgICAgICAgIC8vIFBsYXRmb3JtIHdpbmRvdyBmdW5jdGlvbnNcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdnZXRDb250ZXh0R3JvdXBzJywgdGhpcy5nZXRDb250ZXh0R3JvdXBzLmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2pvaW5Db250ZXh0R3JvdXAnLCB0aGlzLmpvaW5Db250ZXh0R3JvdXAuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3RlcigncmVtb3ZlRnJvbUNvbnRleHRHcm91cCcsIHRoaXMucmVtb3ZlRnJvbUNvbnRleHRHcm91cC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdnZXRBbGxDbGllbnRzSW5Db250ZXh0R3JvdXAnLCB0aGlzLmdldEFsbENsaWVudHNJbkNvbnRleHRHcm91cC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdnZXRJbmZvRm9yQ29udGV4dEdyb3VwJywgdGhpcy5nZXRJbmZvRm9yQ29udGV4dEdyb3VwLmJpbmQodGhpcykpO1xuXHQgICAgICAgIC8vIEludGVybmFsIG1ldGhvZHNcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdjb250ZXh0SGFuZGxlclJlZ2lzdGVyZWQnLCB0aGlzLmNvbnRleHRIYW5kbGVyUmVnaXN0ZXJlZC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdpbnRlbnRIYW5kbGVyUmVnaXN0ZXJlZCcsIHRoaXMuaW50ZW50SGFuZGxlclJlZ2lzdGVyZWQuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3RlcigncmVtb3ZlQ29udGV4dEhhbmRsZXInLCB0aGlzLnJlbW92ZUNvbnRleHRIYW5kbGVyLmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ3Nlc3Npb25Db250ZXh0R3JvdXA6Y3JlYXRlSWZOZWVkZWQnLCB0aGlzLmhhbmRsZUpvaW5TZXNzaW9uQ29udGV4dEdyb3VwLmJpbmQodGhpcykpO1xuXHQgICAgICAgIC8vIGZkYzMgb25seSBtZXRob2RzXG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3RlcignZmRjM09wZW4nLCB0aGlzLmZkYzNIYW5kbGVPcGVuLmJpbmQodGhpcykpO1xuXHQgICAgICAgIGNoYW5uZWwucmVnaXN0ZXIoJ2ZkYzN2MkZpbmRJbnRlbnRzQnlDb250ZXh0JywgdGhpcy5oYW5kbGVJbmZvRm9ySW50ZW50c0J5Q29udGV4dC5iaW5kKHRoaXMpKTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdmZGMzRmluZEluc3RhbmNlcycsIHRoaXMuZmRjM0hhbmRsZUZpbmRJbnN0YW5jZXMuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3RlcignZmRjM0dldEFwcE1ldGFkYXRhJywgdGhpcy5mZGMzSGFuZGxlR2V0QXBwTWV0YWRhdGEuYmluZCh0aGlzKSk7XG5cdCAgICAgICAgY2hhbm5lbC5yZWdpc3RlcignZmRjM3YyR2V0SW5mbycsIGFzeW5jIChwYXlsb2FkLCBjbGllbnRJZGVudGl0eSkgPT4ge1xuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy5mZGMzSGFuZGxlR2V0SW5mby5iaW5kKHRoaXMpKHBheWxvYWQsIGNsaWVudElkZW50aXR5KTtcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdjcmVhdGVQcml2YXRlQ2hhbm5lbFByb3ZpZGVyJywgYXN5bmMgKHBheWxvYWQpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgeyBjaGFubmVsSWQgfSA9IHBheWxvYWQ7XG5cdCAgICAgICAgICAgIGNvbnN0IGNoYW5uZWxQcm92aWRlciA9IGF3YWl0IHRoaXMuZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoY2hhbm5lbElkKTtcblx0ICAgICAgICAgICAgUHJpdmF0ZUNoYW5uZWxQcm92aWRlcl8xLlByaXZhdGVDaGFubmVsUHJvdmlkZXIuaW5pdChjaGFubmVsUHJvdmlkZXIsIGNoYW5uZWxJZCk7XG5cdCAgICAgICAgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIENhbiBiZSB1c2VkIHRvIGNvbXBsZXRlbHkgcHJldmVudCBhIGNvbm5lY3Rpb24uIFJldHVybiBmYWxzZSB0byBwcmV2ZW50IGNvbm5lY3Rpb25zLiBBbGxvd3MgYWxsIGNvbm5lY3Rpb25zIGJ5IGRlZmF1bHQuXG5cdCAgICAgKiBAcGFyYW0gX2lkIHRoZSBpZGVudGl0eSB0cnlpbmMgdG8gY29ubmVjdFxuXHQgICAgICogQHBhcmFtIF9jb25uZWN0aW9uUGF5bG9hZCBvcHRpb25hbCBwYXlsb2FkIHRvIHVzZSBpbiBjdXN0b20gaW1wbGVtZW50YXRpb25zLCB3aWxsIGJlIHVuZGVmaW5lZCBieSBkZWZhdWx0XG5cdCAgICAgKi9cblx0ICAgIGlzQ29ubmVjdGlvbkF1dGhvcml6ZWQoX2lkLCBfY29ubmVjdGlvblBheWxvYWQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1icm9rZXItaXMtY29ubmVjdGlvbi1hdXRob3JpemVkJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0cnVlKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQ2FsbGVkIGJlZm9yZSBldmVyeSBhY3Rpb24gdG8gY2hlY2sgaWYgdGhpcyBlbnRpdHkgc2hvdWxkIGJlIGFsbG93ZWQgdG8gdGFrZSB0aGUgYWN0aW9uLlxuXHQgICAgICogUmV0dXJuIGZhbHNlIHRvIHByZXZlbnQgdGhlIGFjdGlvblxuXHQgICAgICogQHBhcmFtIF9hY3Rpb24gdGhlIHN0cmluZyBhY3Rpb24gdG8gYXV0aG9yaXplIGluIGNhbWVsIGNhc2Vcblx0ICAgICAqIEBwYXJhbSBfcGF5bG9hZCB0aGUgZGF0YSBiZWluZyBzZW50IGZvciB0aGlzIGFjdGlvblxuXHQgICAgICogQHBhcmFtIF9pZGVudGl0eSB0aGUgY29ubmVjdGlvbiBhdHRlbXB0aW5nIHRvIGRpc3BhdGNoIHRoaXMgYWN0aW9uXG5cdCAgICAgKi9cblx0ICAgIGlzQWN0aW9uQXV0aG9yaXplZChfYWN0aW9uLCBfcGF5bG9hZCwgX2lkZW50aXR5KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtYnJva2VyLWlzLWFjdGlvbi1hdXRob3JpemVkJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0cnVlKTtcblx0ICAgIH1cblx0fTtcblx0SW50ZXJvcEJyb2tlci5JbnRlcm9wQnJva2VyID0gSW50ZXJvcEJyb2tlciQxO1xuXHRfSW50ZXJvcEJyb2tlcl9mZGMzSW5mbyA9IG5ldyBXZWFrTWFwKCksIF9JbnRlcm9wQnJva2VyX2NvbnRleHRHcm91cHMgPSBuZXcgV2Vha01hcCgpLCBfSW50ZXJvcEJyb2tlcl9wcm92aWRlclByb21pc2UgPSBuZXcgV2Vha01hcCgpO1xuXHRyZXR1cm4gSW50ZXJvcEJyb2tlcjtcbn1cblxudmFyIEludGVyb3BDbGllbnQgPSB7fTtcblxudmFyIFNlc3Npb25Db250ZXh0R3JvdXBDbGllbnQkMSA9IHt9O1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDIgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xufTtcbnZhciBfU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudF9jbGllbnRQcm9taXNlO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KFNlc3Npb25Db250ZXh0R3JvdXBDbGllbnQkMSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5jb25zdCBiYXNlXzEkMiA9IGJhc2U7XG5jb25zdCB1dGlsc18xJDIgPSB1dGlscyQzO1xuY2xhc3MgU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudCBleHRlbmRzIGJhc2VfMSQyLkJhc2Uge1xuICAgIGNvbnN0cnVjdG9yKHdpcmUsIGNsaWVudCwgaWQpIHtcbiAgICAgICAgc3VwZXIod2lyZSk7XG4gICAgICAgIF9TZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50X2NsaWVudFByb21pc2Uuc2V0KHRoaXMsIHZvaWQgMCk7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQyKHRoaXMsIF9TZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50X2NsaWVudFByb21pc2UsIGNsaWVudCwgXCJmXCIpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXRzIGEgY29udGV4dCBmb3IgdGhlIHNlc3Npb24gY29udGV4dCBncm91cC5cbiAgICAgKiBAcGFyYW0gY29udGV4dCAtIE5ldyBjb250ZXh0IHRvIHNldC5cbiAgICAgKlxuICAgICAqIEB0dXRvcmlhbCBpbnRlcm9wLnNldENvbnRleHRcbiAgICAgKi9cbiAgICBhc3luYyBzZXRDb250ZXh0KGNvbnRleHQpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3Atc2Vzc2lvbi1jb250ZXh0LWdyb3VwLXNldC1jb250ZXh0JykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQyKHRoaXMsIF9TZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50X2NsaWVudFByb21pc2UsIFwiZlwiKTtcbiAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaChgc2Vzc2lvbkNvbnRleHRHcm91cDpzZXRDb250ZXh0LSR7dGhpcy5pZH1gLCB7XG4gICAgICAgICAgICBzZXNzaW9uQ29udGV4dEdyb3VwSWQ6IHRoaXMuaWQsXG4gICAgICAgICAgICBjb250ZXh0XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBhc3luYyBnZXRDdXJyZW50Q29udGV4dCh0eXBlKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLXNlc3Npb24tY29udGV4dC1ncm91cC1nZXQtY29udGV4dCcpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMih0aGlzLCBfU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG4gICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goYHNlc3Npb25Db250ZXh0R3JvdXA6Z2V0Q29udGV4dC0ke3RoaXMuaWR9YCwge1xuICAgICAgICAgICAgc2Vzc2lvbkNvbnRleHRHcm91cElkOiB0aGlzLmlkLFxuICAgICAgICAgICAgdHlwZVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgYXN5bmMgYWRkQ29udGV4dEhhbmRsZXIoY29udGV4dEhhbmRsZXIsIGNvbnRleHRUeXBlKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLXNlc3Npb24tY29udGV4dC1ncm91cC1hZGQtaGFuZGxlcicpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0eXBlb2YgY29udGV4dEhhbmRsZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vbi1mdW5jdGlvbiBhcmd1bWVudCBwYXNzZWQgdG8gdGhlIGZpcnN0IHBhcmFtZXRlciAnaGFuZGxlcicuIEJlIGF3YXJlIHRoYXQgdGhlIGFyZ3VtZW50IG9yZGVyIGRvZXMgbm90IG1hdGNoIHRoZSBGREMzIHN0YW5kYXJkLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDIodGhpcywgX1Nlc3Npb25Db250ZXh0R3JvdXBDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuICAgICAgICBsZXQgaGFuZGxlcklkO1xuICAgICAgICBpZiAoY29udGV4dFR5cGUpIHtcbiAgICAgICAgICAgIGhhbmRsZXJJZCA9IGBzZXNzaW9uQ29udGV4dEhhbmRsZXI6aW52b2tlLSR7dGhpcy5pZH0tJHtjb250ZXh0VHlwZX0tJHsoMCwgdXRpbHNfMSQyLmdlbmVyYXRlSWQpKCl9YDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGhhbmRsZXJJZCA9IGBzZXNzaW9uQ29udGV4dEhhbmRsZXI6aW52b2tlLSR7dGhpcy5pZH1gO1xuICAgICAgICB9XG4gICAgICAgIGNsaWVudC5yZWdpc3RlcihoYW5kbGVySWQsICgwLCB1dGlsc18xJDIud3JhcENvbnRleHRIYW5kbGVyKShjb250ZXh0SGFuZGxlciwgaGFuZGxlcklkKSk7XG4gICAgICAgIGF3YWl0IGNsaWVudC5kaXNwYXRjaChgc2Vzc2lvbkNvbnRleHRHcm91cDpoYW5kbGVyQWRkZWQtJHt0aGlzLmlkfWAsIHsgaGFuZGxlcklkLCBjb250ZXh0VHlwZSB9KTtcbiAgICAgICAgcmV0dXJuIHsgdW5zdWJzY3JpYmU6IGF3YWl0IHRoaXMuY3JlYXRlVW5zdWJzY3JpYmVDYihoYW5kbGVySWQpIH07XG4gICAgfVxuICAgIGFzeW5jIGNyZWF0ZVVuc3Vic2NyaWJlQ2IoaGFuZGxlcklkKSB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMih0aGlzLCBfU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG4gICAgICAgIHJldHVybiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBjbGllbnQucmVtb3ZlKGhhbmRsZXJJZCk7XG4gICAgICAgICAgICBhd2FpdCBjbGllbnQuZGlzcGF0Y2goYHNlc3Npb25Db250ZXh0R3JvdXA6aGFuZGxlclJlbW92ZWQtJHt0aGlzLmlkfWAsIHsgaGFuZGxlcklkIH0pO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXRVc2VySW5zdGFuY2UoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpZDogdGhpcy5pZCxcbiAgICAgICAgICAgIHNldENvbnRleHQ6ICgwLCB1dGlsc18xJDIud3JhcEluVHJ5Q2F0Y2gpKHRoaXMuc2V0Q29udGV4dC5iaW5kKHRoaXMpLCAnRmFpbGVkIHRvIHNldCBjb250ZXh0OiAnKSxcbiAgICAgICAgICAgIGdldEN1cnJlbnRDb250ZXh0OiAoMCwgdXRpbHNfMSQyLndyYXBJblRyeUNhdGNoKSh0aGlzLmdldEN1cnJlbnRDb250ZXh0LmJpbmQodGhpcyksICdGYWlsZWQgdG8gZ2V0IGNvbnRleHQ6ICcpLFxuICAgICAgICAgICAgYWRkQ29udGV4dEhhbmRsZXI6ICgwLCB1dGlsc18xJDIud3JhcEluVHJ5Q2F0Y2gpKHRoaXMuYWRkQ29udGV4dEhhbmRsZXIuYmluZCh0aGlzKSwgJ0ZhaWxlZCB0byBhZGQgY29udGV4dCBoYW5kbGVyOiAnKVxuICAgICAgICB9O1xuICAgIH1cbn1cblNlc3Npb25Db250ZXh0R3JvdXBDbGllbnQkMS5kZWZhdWx0ID0gU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudDtcbl9TZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50X2NsaWVudFByb21pc2UgPSBuZXcgV2Vha01hcCgpO1xuXG52YXIgZmRjMzFfMiA9IHt9O1xuXG52YXIgZmRjM0NvbW1vbiA9IHt9O1xuXG52YXIgdXRpbHMkMiA9IHt9O1xuXG52YXIgUHJpdmF0ZUNoYW5uZWxDbGllbnQkMSA9IHt9O1xuXG52YXIgX19jcmVhdGVCaW5kaW5nID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY3JlYXRlQmluZGluZykgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgbSwgaywgazIpIHtcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcbiAgICBpZiAoIWRlc2MgfHwgKFwiZ2V0XCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xuICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcbiAgICB9XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcbn0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcbiAgICBvW2syXSA9IG1ba107XG59KSk7XG52YXIgX19zZXRNb2R1bGVEZWZhdWx0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fc2V0TW9kdWxlRGVmYXVsdCkgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBcImRlZmF1bHRcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCB2YWx1ZTogdiB9KTtcbn0pIDogZnVuY3Rpb24obywgdikge1xuICAgIG9bXCJkZWZhdWx0XCJdID0gdjtcbn0pO1xudmFyIF9faW1wb3J0U3RhciA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2ltcG9ydFN0YXIpIHx8IGZ1bmN0aW9uIChtb2QpIHtcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xuICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICBpZiAobW9kICE9IG51bGwpIGZvciAodmFyIGsgaW4gbW9kKSBpZiAoayAhPT0gXCJkZWZhdWx0XCIgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZCwgaykpIF9fY3JlYXRlQmluZGluZyhyZXN1bHQsIG1vZCwgayk7XG4gICAgX19zZXRNb2R1bGVEZWZhdWx0KHJlc3VsdCwgbW9kKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufTtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShQcml2YXRlQ2hhbm5lbENsaWVudCQxLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblByaXZhdGVDaGFubmVsQ2xpZW50JDEuUHJpdmF0ZUNoYW5uZWxDbGllbnQgPSB2b2lkIDA7XG5jb25zdCB1dGlscyQxID0gX19pbXBvcnRTdGFyKHV0aWxzJDMpO1xuY2xhc3MgUHJpdmF0ZUNoYW5uZWxDbGllbnQge1xuICAgIGNvbnN0cnVjdG9yKGNsaWVudCwgaWQpIHtcbiAgICAgICAgdGhpcy5pZCA9IGlkO1xuICAgICAgICB0aGlzLmNsaWVudCA9IGNsaWVudDtcbiAgICAgICAgdGhpcy5saXN0ZW5lcnMgPSBuZXcgTWFwKCk7XG4gICAgfVxuICAgIGFzeW5jIGJyb2FkY2FzdChjb250ZXh0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNsaWVudC5kaXNwYXRjaCgnYnJvYWRjYXN0JywgeyBjb250ZXh0IH0pO1xuICAgIH1cbiAgICBhc3luYyBnZXRDdXJyZW50Q29udGV4dChjb250ZXh0VHlwZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5jbGllbnQuZGlzcGF0Y2goJ2dldEN1cnJlbnRDb250ZXh0JywgeyBjb250ZXh0VHlwZSB9KTtcbiAgICB9XG4gICAgYXN5bmMgYWRkQ29udGV4dExpc3RlbmVyKGNvbnRleHRUeXBlLCBoYW5kbGVyKSB7XG4gICAgICAgIGlmICh0eXBlb2YgaGFuZGxlciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm9uLWZ1bmN0aW9uIGFyZ3VtZW50IHBhc3NlZCB0byB0aGUgc2Vjb25kIHBhcmFtZXRlciAnaGFuZGxlcicuIEJlIGF3YXJlIHRoYXQgdGhlIGFyZ3VtZW50IG9yZGVyIGRvZXMgbm90IG1hdGNoIHRoZSBGREMzIHN0YW5kYXJkLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgaGFuZGxlcklkO1xuICAgICAgICBpZiAoY29udGV4dFR5cGUpIHtcbiAgICAgICAgICAgIGhhbmRsZXJJZCA9IGBjb250ZXh0SGFuZGxlcjppbnZva2UtJHt0aGlzLmlkfS0ke2NvbnRleHRUeXBlfS0ke3V0aWxzJDEuZ2VuZXJhdGVJZCgpfWA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBoYW5kbGVySWQgPSBgY29udGV4dEhhbmRsZXI6aW52b2tlLSR7dGhpcy5pZH0tJHt1dGlscyQxLmdlbmVyYXRlSWQoKX1gO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY2xpZW50LnJlZ2lzdGVyKGhhbmRsZXJJZCwgdXRpbHMkMS53cmFwQ29udGV4dEhhbmRsZXIoaGFuZGxlciwgaGFuZGxlcklkKSk7XG4gICAgICAgIGNvbnN0IGxpc3RlbmVyID0geyB1bnN1YnNjcmliZTogYXdhaXQgdGhpcy5jcmVhdGVDb250ZXh0VW5zdWJzY3JpYmVDYihoYW5kbGVySWQpIH07XG4gICAgICAgIHRoaXMubGlzdGVuZXJzLnNldChoYW5kbGVySWQsIGxpc3RlbmVyKTtcbiAgICAgICAgYXdhaXQgdGhpcy5jbGllbnQuZGlzcGF0Y2goYGNvbnRleHRIYW5kbGVyQWRkZWRgLCB7IGhhbmRsZXJJZCwgY29udGV4dFR5cGUgfSk7XG4gICAgICAgIHJldHVybiBsaXN0ZW5lcjtcbiAgICB9XG4gICAgY3JlYXRlTm9uU3RhbmRhcmRVbnN1YnNjcmliZUNiKGhhbmRsZXJJZCkge1xuICAgICAgICByZXR1cm4gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5jbGllbnQucmVtb3ZlKGhhbmRsZXJJZCk7XG4gICAgICAgICAgICB0aGlzLmxpc3RlbmVycy5kZWxldGUoaGFuZGxlcklkKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2xpZW50LmRpc3BhdGNoKCdub25TdGFuZGFyZEhhbmRsZXJSZW1vdmVkJywgeyBoYW5kbGVySWQgfSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGNyZWF0ZUNvbnRleHRVbnN1YnNjcmliZUNiKGhhbmRsZXJJZCkge1xuICAgICAgICByZXR1cm4gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5jbGllbnQucmVtb3ZlKGhhbmRsZXJJZCk7XG4gICAgICAgICAgICB0aGlzLmxpc3RlbmVycy5kZWxldGUoaGFuZGxlcklkKTtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2xpZW50LmRpc3BhdGNoKCdjb250ZXh0SGFuZGxlclJlbW92ZWQnLCB7IGhhbmRsZXJJZCB9KTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgb25BZGRDb250ZXh0TGlzdGVuZXIoaGFuZGxlcikge1xuICAgICAgICBjb25zdCBoYW5kbGVySWQgPSBgb25Db250ZXh0SGFuZGxlckFkZGVkOmludm9rZS0ke3RoaXMuaWR9LSR7dXRpbHMkMS5nZW5lcmF0ZUlkKCl9YDtcbiAgICAgICAgdGhpcy5jbGllbnQucmVnaXN0ZXIoaGFuZGxlcklkLCBoYW5kbGVyKTtcbiAgICAgICAgY29uc3QgbGlzdGVuZXIgPSB7IHVuc3Vic2NyaWJlOiB0aGlzLmNyZWF0ZU5vblN0YW5kYXJkVW5zdWJzY3JpYmVDYihoYW5kbGVySWQpIH07XG4gICAgICAgIHRoaXMubGlzdGVuZXJzLnNldChoYW5kbGVySWQsIGxpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5jbGllbnQuZGlzcGF0Y2goYG9uQWRkQ29udGV4dEhhbmRsZXJBZGRlZGAsIHsgaGFuZGxlcklkIH0pO1xuICAgICAgICByZXR1cm4gbGlzdGVuZXI7XG4gICAgfVxuICAgIG9uRGlzY29ubmVjdChoYW5kbGVyKSB7XG4gICAgICAgIGNvbnN0IGhhbmRsZXJJZCA9IGBvbkRpc2Nvbm5lY3Q6aW52b2tlLSR7dGhpcy5pZH0tJHt1dGlscyQxLmdlbmVyYXRlSWQoKX1gO1xuICAgICAgICB0aGlzLmNsaWVudC5yZWdpc3RlcihoYW5kbGVySWQsIGhhbmRsZXIpO1xuICAgICAgICBjb25zdCBsaXN0ZW5lciA9IHsgdW5zdWJzY3JpYmU6IHRoaXMuY3JlYXRlTm9uU3RhbmRhcmRVbnN1YnNjcmliZUNiKGhhbmRsZXJJZCkgfTtcbiAgICAgICAgdGhpcy5saXN0ZW5lcnMuc2V0KGhhbmRsZXJJZCwgbGlzdGVuZXIpO1xuICAgICAgICB0aGlzLmNsaWVudC5kaXNwYXRjaChgb25EaXNjb25uZWN0SGFuZGxlckFkZGVkYCwgeyBoYW5kbGVySWQgfSk7XG4gICAgICAgIHJldHVybiBsaXN0ZW5lcjtcbiAgICB9XG4gICAgb25VbnN1YnNjcmliZShoYW5kbGVyKSB7XG4gICAgICAgIGNvbnN0IGhhbmRsZXJJZCA9IGBvblVuc3Vic2NyaWJlOmludm9rZS0ke3RoaXMuaWR9LSR7dXRpbHMkMS5nZW5lcmF0ZUlkKCl9YDtcbiAgICAgICAgdGhpcy5jbGllbnQucmVnaXN0ZXIoaGFuZGxlcklkLCBoYW5kbGVyKTtcbiAgICAgICAgY29uc3QgbGlzdGVuZXIgPSB7IHVuc3Vic2NyaWJlOiB0aGlzLmNyZWF0ZU5vblN0YW5kYXJkVW5zdWJzY3JpYmVDYihoYW5kbGVySWQpIH07XG4gICAgICAgIHRoaXMubGlzdGVuZXJzLnNldChoYW5kbGVySWQsIGxpc3RlbmVyKTtcbiAgICAgICAgdGhpcy5jbGllbnQuZGlzcGF0Y2goYG9uVW5zdWJzY3JpYmVIYW5kbGVyQWRkZWRgLCB7IGhhbmRsZXJJZCB9KTtcbiAgICAgICAgcmV0dXJuIGxpc3RlbmVyO1xuICAgIH1cbiAgICBhc3luYyBjbGVhblVwQWxsU3VicygpIHtcbiAgICAgICAgY29uc3QgbGlzdGVuZXJVbnN1YnNjcmliZXJzID0gQXJyYXkuZnJvbSh0aGlzLmxpc3RlbmVycy5rZXlzKCkpO1xuICAgICAgICBsaXN0ZW5lclVuc3Vic2NyaWJlcnMuZm9yRWFjaCgoaGFuZGxlcklkKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmNsaWVudC5yZW1vdmUoaGFuZGxlcklkKTtcbiAgICAgICAgICAgIHRoaXMubGlzdGVuZXJzLmRlbGV0ZShoYW5kbGVySWQpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgYXN5bmMgZGlzY29ubmVjdCgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2xpZW50LmRpc3BhdGNoKCdjbGllbnREaXNjb25uZWN0aW5nJyk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNsZWFuVXBBbGxTdWJzKCk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNsaWVudC5kaXNjb25uZWN0KCk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IubWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5Qcml2YXRlQ2hhbm5lbENsaWVudCQxLlByaXZhdGVDaGFubmVsQ2xpZW50ID0gUHJpdmF0ZUNoYW5uZWxDbGllbnQ7XG5cbihmdW5jdGlvbiAoZXhwb3J0cykge1xuXHR2YXIgX19pbXBvcnREZWZhdWx0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9faW1wb3J0RGVmYXVsdCkgfHwgZnVuY3Rpb24gKG1vZCkge1xuXHQgICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBcImRlZmF1bHRcIjogbW9kIH07XG5cdH07XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0ZXhwb3J0cy5nZXRJbnRlbnRSZXNvbHV0aW9uID0gZXhwb3J0cy5pc0NoYW5uZWwgPSBleHBvcnRzLmlzQ29udGV4dCA9IGV4cG9ydHMuY29ubmVjdFByaXZhdGVDaGFubmVsID0gZXhwb3J0cy5idWlsZEFwcENoYW5uZWxPYmplY3QgPSBleHBvcnRzLmJ1aWxkUHJpdmF0ZUNoYW5uZWxPYmplY3QgPSBleHBvcnRzLkNoYW5uZWxFcnJvciA9IGV4cG9ydHMuUmVzdWx0RXJyb3IgPSBleHBvcnRzLlVuc3VwcG9ydGVkQ2hhbm5lbEFwaUVycm9yID0gZXhwb3J0cy5nZXRVbnN1cHBvcnRlZENoYW5uZWxBcGlzID0gdm9pZCAwO1xuXHRjb25zdCB1dGlsc18xID0gdXRpbHMkMztcblx0Y29uc3QgUHJpdmF0ZUNoYW5uZWxDbGllbnRfMSA9IFByaXZhdGVDaGFubmVsQ2xpZW50JDE7XG5cdGNvbnN0IGlzRXF1YWxfMSA9IF9faW1wb3J0RGVmYXVsdChyZXF1aXJlJCQzKTtcblx0Y29uc3QgZ2V0VW5zdXBwb3J0ZWRDaGFubmVsQXBpcyA9IChjaGFubmVsVHlwZSkgPT4ge1xuXHQgICAgcmV0dXJuIHtcblx0ICAgICAgICBhZGRDb250ZXh0TGlzdGVuZXI6ICgpID0+IHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkQ2hhbm5lbEFwaUVycm9yKCdDaGFubmVsLmFkZENvbnRleHRMaXN0ZW5lcicsIGNoYW5uZWxUeXBlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGJyb2FkY2FzdDogKCkgPT4ge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgVW5zdXBwb3J0ZWRDaGFubmVsQXBpRXJyb3IoJ0NoYW5uZWwuYnJvYWRjYXN0JywgY2hhbm5lbFR5cGUpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgZ2V0Q3VycmVudENvbnRleHQ6ICgpID0+IHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkQ2hhbm5lbEFwaUVycm9yKCdDaGFubmVsLmdldEN1cnJlbnRDb250ZXh0JywgY2hhbm5lbFR5cGUpO1xuXHQgICAgICAgIH1cblx0ICAgIH07XG5cdH07XG5cdGV4cG9ydHMuZ2V0VW5zdXBwb3J0ZWRDaGFubmVsQXBpcyA9IGdldFVuc3VwcG9ydGVkQ2hhbm5lbEFwaXM7XG5cdGNsYXNzIFVuc3VwcG9ydGVkQ2hhbm5lbEFwaUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuXHQgICAgY29uc3RydWN0b3IoYXBpTmFtZSwgY2hhbm5lbFR5cGUgPSAnU3lzdGVtJykge1xuXHQgICAgICAgIHN1cGVyKGFwaU5hbWUpO1xuXHQgICAgICAgIHRoaXMubWVzc2FnZSA9IGBDYWxsaW5nICR7YXBpTmFtZX0gb24gYW4gaW5zdGFuY2Ugb2YgYSAke2NoYW5uZWxUeXBlfSBDaGFubmVsIHJldHVybmVkIGJ5IGZkYzMuZ2V0JHtjaGFubmVsVHlwZX1DaGFubmVscyBpcyBub3Qgc3VwcG9ydGVkLiBJZiB5b3Ugd291bGQgbGlrZSB0byB1c2UgYSAke2NoYW5uZWxUeXBlfSBDaGFubmVsLCBwbGVhc2UgdXNlIGZkYzMuam9pbkNoYW5uZWwsIGZkYzMuYWRkQ29udGV4dExpc3RlbmVyLCBhbmQgZmRjMy5icm9hZGNhc3QgaW5zdGVhZC5gO1xuXHQgICAgfVxuXHR9XG5cdGV4cG9ydHMuVW5zdXBwb3J0ZWRDaGFubmVsQXBpRXJyb3IgPSBVbnN1cHBvcnRlZENoYW5uZWxBcGlFcnJvcjtcblx0dmFyIFJlc3VsdEVycm9yO1xuXHQoZnVuY3Rpb24gKFJlc3VsdEVycm9yKSB7XG5cdCAgICAvKiogUmV0dXJuZWQgaWYgdGhlIGBJbnRlbnRIYW5kbGVyYCBleGl0ZWQgd2l0aG91dCByZXR1cm5pbmcgYSBQcm9taXNlIG9yIHRoYXRcblx0ICAgICAqICBQcm9taXNlIHdhcyBub3QgcmVzb2x2ZWQgd2l0aCBhIENvbnRleHQgb3IgQ2hhbm5lbCBvYmplY3QuXG5cdCAgICAgKi9cblx0ICAgIFJlc3VsdEVycm9yW1wiTm9SZXN1bHRSZXR1cm5lZFwiXSA9IFwiTm9SZXN1bHRSZXR1cm5lZFwiO1xuXHQgICAgLyoqIFJldHVybmVkIGlmIHRoZSBgSW50ZW50SGFuZGxlcmAgZnVuY3Rpb24gcHJvY2Vzc2luZyB0aGUgcmFpc2VkIGludGVudFxuXHQgICAgICogIHRocm93cyBhbiBlcnJvciBvciByZWplY3RzIHRoZSBQcm9taXNlIGl0IHJldHVybmVkLlxuXHQgICAgICovXG5cdCAgICBSZXN1bHRFcnJvcltcIkludGVudEhhbmRsZXJSZWplY3RlZFwiXSA9IFwiSW50ZW50SGFuZGxlclJlamVjdGVkXCI7XG5cdH0pKFJlc3VsdEVycm9yID0gZXhwb3J0cy5SZXN1bHRFcnJvciB8fCAoZXhwb3J0cy5SZXN1bHRFcnJvciA9IHt9KSk7XG5cdChmdW5jdGlvbiAoQ2hhbm5lbEVycm9yKSB7XG5cdCAgICAvKiogUmV0dXJuZWQgaWYgdGhlIHNwZWNpZmllZCBjaGFubmVsIGlzIG5vdCBmb3VuZCB3aGVuIGF0dGVtcHRpbmcgdG8gam9pbiBhXG5cdCAgICAgKiAgY2hhbm5lbCB2aWEgdGhlIGBqb2luVXNlckNoYW5uZWxgIGZ1bmN0aW9uIG9mIHRoZSBEZXNrdG9wQWdlbnQgKGBmZGMzYCkuXG5cdCAgICAgKi9cblx0ICAgIENoYW5uZWxFcnJvcltcIk5vQ2hhbm5lbEZvdW5kXCJdID0gXCJOb0NoYW5uZWxGb3VuZFwiO1xuXHQgICAgLyoqIFNIT1VMRCBiZSByZXR1cm5lZCB3aGVuIGEgcmVxdWVzdCB0byBqb2luIGEgdXNlciBjaGFubmVsIG9yIHRvIGEgcmV0cmlldmVcblx0ICAgICAqICBhIENoYW5uZWwgb2JqZWN0IHZpYSB0aGUgYGpvaW5Vc2VyQ2hhbm5lbGAgb3IgYGdldE9yQ3JlYXRlQ2hhbm5lbGAgbWV0aG9kc1xuXHQgICAgICogIG9mIHRoZSBEZXNrdG9wQWdlbnQgKGBmZGMzYCkgb2JqZWN0IGlzIGRlbmllZC5cblx0ICAgICAqL1xuXHQgICAgQ2hhbm5lbEVycm9yW1wiQWNjZXNzRGVuaWVkXCJdID0gXCJBY2Nlc3NEZW5pZWRcIjtcblx0ICAgIC8qKiBTSE9VTEQgYmUgcmV0dXJuZWQgd2hlbiBhIGNoYW5uZWwgY2Fubm90IGJlIGNyZWF0ZWQgb3IgcmV0cmlldmVkIHZpYSB0aGVcblx0ICAgICAqICBgZ2V0T3JDcmVhdGVDaGFubmVsYCBtZXRob2Qgb2YgdGhlIERlc2t0b3BBZ2VudCAoYGZkYzNgKS5cblx0ICAgICAqL1xuXHQgICAgQ2hhbm5lbEVycm9yW1wiQ3JlYXRpb25GYWlsZWRcIl0gPSBcIkNyZWF0aW9uRmFpbGVkXCI7XG5cdH0pKGV4cG9ydHMuQ2hhbm5lbEVycm9yIHx8IChleHBvcnRzLkNoYW5uZWxFcnJvciA9IHt9KSk7XG5cdGNvbnN0IGJ1aWxkUHJpdmF0ZUNoYW5uZWxPYmplY3QgPSAocHJpdmF0ZUNoYW5uZWxDbGllbnQpID0+IHtcblx0ICAgIGxldCBjbGllbnREaXNjb25uZWN0ZWQgPSBmYWxzZTtcblx0ICAgIGNvbnN0IGNoZWNrSWZDbGllbnREaXNjb25uZWN0ZWQgPSAoKSA9PiB7XG5cdCAgICAgICAgaWYgKGNsaWVudERpc2Nvbm5lY3RlZCkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1ByaXZhdGUgQ2hhbm5lbCBDbGllbnQgaGFzIGJlZW4gZGlzY29ubmVjdGVkIGZyb20gdGhlIFByaXZhdGUgQ2hhbm5lbCcpO1xuXHQgICAgICAgIH1cblx0ICAgIH07XG5cdCAgICByZXR1cm4ge1xuXHQgICAgICAgIGlkOiBwcml2YXRlQ2hhbm5lbENsaWVudC5pZCxcblx0ICAgICAgICB0eXBlOiAncHJpdmF0ZScsXG5cdCAgICAgICAgYnJvYWRjYXN0OiBhc3luYyAoY29udGV4dCkgPT4ge1xuXHQgICAgICAgICAgICBjaGVja0lmQ2xpZW50RGlzY29ubmVjdGVkKCk7XG5cdCAgICAgICAgICAgIHJldHVybiBwcml2YXRlQ2hhbm5lbENsaWVudC5icm9hZGNhc3QoY29udGV4dCk7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBnZXRDdXJyZW50Q29udGV4dDogYXN5bmMgKGNvbnRleHRUeXBlKSA9PiB7XG5cdCAgICAgICAgICAgIGNoZWNrSWZDbGllbnREaXNjb25uZWN0ZWQoKTtcblx0ICAgICAgICAgICAgcmV0dXJuIHByaXZhdGVDaGFubmVsQ2xpZW50LmdldEN1cnJlbnRDb250ZXh0KGNvbnRleHRUeXBlKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgVE9ETyBbQ09SRS0xNTI0XVxuXHQgICAgICAgIGFkZENvbnRleHRMaXN0ZW5lcjogYXN5bmMgKGNvbnRleHRUeXBlLCBoYW5kbGVyKSA9PiB7XG5cdCAgICAgICAgICAgIGNoZWNrSWZDbGllbnREaXNjb25uZWN0ZWQoKTtcblx0ICAgICAgICAgICAgbGV0IGhhbmRsZXJJblVzZSA9IGhhbmRsZXI7XG5cdCAgICAgICAgICAgIGxldCBjb250ZXh0VHlwZUluVXNlID0gY29udGV4dFR5cGU7XG5cdCAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGV4dFR5cGUgPT09ICdmdW5jdGlvbicpIHtcblx0ICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignYWRkQ29udGV4dExpc3RlbmVyKGhhbmRsZXIpIGhhcyBiZWVuIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgYWRkQ29udGV4dExpc3RlbmVyKG51bGwsIGhhbmRsZXIpJyk7XG5cdCAgICAgICAgICAgICAgICBoYW5kbGVySW5Vc2UgPSBjb250ZXh0VHlwZTtcblx0ICAgICAgICAgICAgICAgIGNvbnRleHRUeXBlSW5Vc2UgPSBudWxsO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gcHJpdmF0ZUNoYW5uZWxDbGllbnQuYWRkQ29udGV4dExpc3RlbmVyKGNvbnRleHRUeXBlSW5Vc2UsIGhhbmRsZXJJblVzZSk7XG5cdCAgICAgICAgICAgIHJldHVybiBsaXN0ZW5lcjtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIG9uQWRkQ29udGV4dExpc3RlbmVyOiAoaGFuZGxlcikgPT4ge1xuXHQgICAgICAgICAgICBjaGVja0lmQ2xpZW50RGlzY29ubmVjdGVkKCk7XG5cdCAgICAgICAgICAgIHJldHVybiBwcml2YXRlQ2hhbm5lbENsaWVudC5vbkFkZENvbnRleHRMaXN0ZW5lcihoYW5kbGVyKTtcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGRpc2Nvbm5lY3Q6IGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgY2hlY2tJZkNsaWVudERpc2Nvbm5lY3RlZCgpO1xuXHQgICAgICAgICAgICBjbGllbnREaXNjb25uZWN0ZWQgPSB0cnVlO1xuXHQgICAgICAgICAgICByZXR1cm4gcHJpdmF0ZUNoYW5uZWxDbGllbnQuZGlzY29ubmVjdCgpO1xuXHQgICAgICAgIH0sXG5cdCAgICAgICAgb25EaXNjb25uZWN0OiAoaGFuZGxlcikgPT4ge1xuXHQgICAgICAgICAgICBjaGVja0lmQ2xpZW50RGlzY29ubmVjdGVkKCk7XG5cdCAgICAgICAgICAgIHJldHVybiBwcml2YXRlQ2hhbm5lbENsaWVudC5vbkRpc2Nvbm5lY3QoaGFuZGxlcik7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBvblVuc3Vic2NyaWJlOiAoaGFuZGxlcikgPT4ge1xuXHQgICAgICAgICAgICBjaGVja0lmQ2xpZW50RGlzY29ubmVjdGVkKCk7XG5cdCAgICAgICAgICAgIHJldHVybiBwcml2YXRlQ2hhbm5lbENsaWVudC5vblVuc3Vic2NyaWJlKGhhbmRsZXIpO1xuXHQgICAgICAgIH1cblx0ICAgIH07XG5cdH07XG5cdGV4cG9ydHMuYnVpbGRQcml2YXRlQ2hhbm5lbE9iamVjdCA9IGJ1aWxkUHJpdmF0ZUNoYW5uZWxPYmplY3Q7XG5cdGNvbnN0IGJ1aWxkQXBwQ2hhbm5lbE9iamVjdCA9IChzZXNzaW9uQ29udGV4dEdyb3VwKSA9PiB7XG5cdCAgICByZXR1cm4ge1xuXHQgICAgICAgIGlkOiBzZXNzaW9uQ29udGV4dEdyb3VwLmlkLFxuXHQgICAgICAgIHR5cGU6ICdhcHAnLFxuXHQgICAgICAgIGJyb2FkY2FzdDogc2Vzc2lvbkNvbnRleHRHcm91cC5zZXRDb250ZXh0LFxuXHQgICAgICAgIGdldEN1cnJlbnRDb250ZXh0OiBhc3luYyAoY29udGV4dFR5cGUpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgY29udGV4dCA9IGF3YWl0IHNlc3Npb25Db250ZXh0R3JvdXAuZ2V0Q3VycmVudENvbnRleHQoY29udGV4dFR5cGUpO1xuXHQgICAgICAgICAgICByZXR1cm4gY29udGV4dCA9PT0gdW5kZWZpbmVkID8gbnVsbCA6IGNvbnRleHQ7XG5cdCAgICAgICAgfSxcblx0ICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIFRPRE8gW0NPUkUtMTUyNF1cblx0ICAgICAgICBhZGRDb250ZXh0TGlzdGVuZXI6IChjb250ZXh0VHlwZSwgaGFuZGxlcikgPT4ge1xuXHQgICAgICAgICAgICBsZXQgcmVhbEhhbmRsZXI7XG5cdCAgICAgICAgICAgIGxldCByZWFsVHlwZTtcblx0ICAgICAgICAgICAgaWYgKHR5cGVvZiBjb250ZXh0VHlwZSA9PT0gJ2Z1bmN0aW9uJykge1xuXHQgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKCdhZGRDb250ZXh0TGlzdGVuZXIoaGFuZGxlcikgaGFzIGJlZW4gZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBhZGRDb250ZXh0TGlzdGVuZXIobnVsbCwgaGFuZGxlciknKTtcblx0ICAgICAgICAgICAgICAgIHJlYWxIYW5kbGVyID0gY29udGV4dFR5cGU7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgICAgICByZWFsSGFuZGxlciA9IGhhbmRsZXI7XG5cdCAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnRleHRUeXBlID09PSAnc3RyaW5nJykge1xuXHQgICAgICAgICAgICAgICAgICAgIHJlYWxUeXBlID0gY29udGV4dFR5cGU7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgY29uc3QgbGlzdGVuZXIgPSAoYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICAgICAgbGV0IGZpcnN0ID0gdHJ1ZTtcblx0ICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRDb250ZXh0ID0gYXdhaXQgc2Vzc2lvbkNvbnRleHRHcm91cC5nZXRDdXJyZW50Q29udGV4dChyZWFsVHlwZSk7XG5cdCAgICAgICAgICAgICAgICBjb25zdCB3cmFwcGVkSGFuZGxlciA9IChjb250ZXh0LCBjb250ZXh0TWV0YWRhdGEpID0+IHtcblx0ICAgICAgICAgICAgICAgICAgICBpZiAoZmlyc3QpIHtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3QgPSBmYWxzZTtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCgwLCBpc0VxdWFsXzEuZGVmYXVsdCkoY3VycmVudENvbnRleHQsIGNvbnRleHQpKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbnNpc3RlbnQtcmV0dXJuXG5cdCAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlYWxIYW5kbGVyKGNvbnRleHQsIGNvbnRleHRNZXRhZGF0YSk7XG5cdCAgICAgICAgICAgICAgICB9O1xuXHQgICAgICAgICAgICAgICAgcmV0dXJuIHNlc3Npb25Db250ZXh0R3JvdXAuYWRkQ29udGV4dEhhbmRsZXIod3JhcHBlZEhhbmRsZXIsIHJlYWxUeXBlKTtcblx0ICAgICAgICAgICAgfSkoKTtcblx0ICAgICAgICAgICAgcmV0dXJuIHtcblx0ICAgICAgICAgICAgICAgIC4uLmxpc3RlbmVyLFxuXHQgICAgICAgICAgICAgICAgdW5zdWJzY3JpYmU6ICgpID0+IGxpc3RlbmVyLnRoZW4oKGwpID0+IGwudW5zdWJzY3JpYmUoKSlcblx0ICAgICAgICAgICAgfTtcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXHR9O1xuXHRleHBvcnRzLmJ1aWxkQXBwQ2hhbm5lbE9iamVjdCA9IGJ1aWxkQXBwQ2hhbm5lbE9iamVjdDtcblx0Y29uc3QgY29ubmVjdFByaXZhdGVDaGFubmVsID0gYXN5bmMgKGNoYW5uZWxJZCkgPT4ge1xuXHQgICAgdHJ5IHtcblx0ICAgICAgICBjb25zdCBjaGFubmVsQ2xpZW50ID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KGNoYW5uZWxJZCk7XG5cdCAgICAgICAgY29uc3QgcHJpdmF0ZUNoYW5uZWxDbGllbnQgPSBuZXcgUHJpdmF0ZUNoYW5uZWxDbGllbnRfMS5Qcml2YXRlQ2hhbm5lbENsaWVudChjaGFubmVsQ2xpZW50LCBjaGFubmVsSWQpO1xuXHQgICAgICAgIHJldHVybiAoMCwgZXhwb3J0cy5idWlsZFByaXZhdGVDaGFubmVsT2JqZWN0KShwcml2YXRlQ2hhbm5lbENsaWVudCk7XG5cdCAgICB9XG5cdCAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFByaXZhdGUgQ2hhbm5lbCB3aXRoIGlkOiAke2NoYW5uZWxJZH0gZG9lc24ndCBleGlzdGApO1xuXHQgICAgfVxuXHR9O1xuXHRleHBvcnRzLmNvbm5lY3RQcml2YXRlQ2hhbm5lbCA9IGNvbm5lY3RQcml2YXRlQ2hhbm5lbDtcblx0Y29uc3QgaXNDb250ZXh0ID0gKGNvbnRleHQpID0+IHtcblx0ICAgIGlmIChjb250ZXh0ICYmIHR5cGVvZiBjb250ZXh0ID09PSAnb2JqZWN0JyAmJiAndHlwZScgaW4gY29udGV4dCkge1xuXHQgICAgICAgIGNvbnN0IHsgdHlwZSB9ID0gY29udGV4dDtcblx0ICAgICAgICByZXR1cm4gdHlwZW9mIHR5cGUgPT09ICdzdHJpbmcnO1xuXHQgICAgfVxuXHQgICAgcmV0dXJuIGZhbHNlO1xuXHR9O1xuXHRleHBvcnRzLmlzQ29udGV4dCA9IGlzQ29udGV4dDtcblx0Y29uc3QgaXNDaGFubmVsID0gKGNoYW5uZWwpID0+IHtcblx0ICAgIGlmIChjaGFubmVsICYmIHR5cGVvZiBjaGFubmVsID09PSAnb2JqZWN0JyAmJiAndHlwZScgaW4gY2hhbm5lbCAmJiAnaWQnIGluIGNoYW5uZWwpIHtcblx0ICAgICAgICBjb25zdCB7IHR5cGUsIGlkIH0gPSBjaGFubmVsO1xuXHQgICAgICAgIHJldHVybiB0eXBlb2YgdHlwZSA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIGlkID09PSAnc3RyaW5nJyAmJiAodHlwZSA9PT0gJ2FwcCcgfHwgdHlwZSA9PT0gJ3ByaXZhdGUnKTtcblx0ICAgIH1cblx0ICAgIHJldHVybiBmYWxzZTtcblx0fTtcblx0ZXhwb3J0cy5pc0NoYW5uZWwgPSBpc0NoYW5uZWw7XG5cdGNvbnN0IGdldEludGVudFJlc29sdXRpb24gPSBhc3luYyAoaW50ZXJvcE1vZHVsZSwgY29udGV4dCwgYXBwLCBpbnRlbnQpID0+IHtcblx0ICAgIC8vIEdlbmVyYXRlIGFuIElEIHRvIG1ha2UgYSBzZXNzaW9uIGNvbnRleHQgZ3JvdXAgd2l0aC4gV2Ugd2lsbCBwYXNzIHRoYXQgSUQgdG8gdGhlIEJyb2tlci5cblx0ICAgIC8vIFRoZSBicm9rZXIgd2lsbCB0aGVuIHNldENvbnRleHQgb24gdGhhdCBzZXNzaW9uIGNvbnRleHQgZ3JvdXAgbGF0ZXIgd2l0aCBvdXIgSW50ZW50IFJlc3VsdCxcblx0ICAgIGNvbnN0IGd1aWQgPSAoMCwgdXRpbHNfMS5nZW5lcmF0ZUlkKSgpOyAvLyBUT0RPIG1ha2UgdGhpcyB1bmRlZmluZWQgaW4gd2ViXG5cdCAgICAvLyBQcm9taXNlIHdlJ2xsIHVzZSBpbiBnZXRSZXN1bHRcblx0ICAgIGNvbnN0IGdldFJlc3VsdFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cdCAgICAgICAgZmluLkludGVyQXBwbGljYXRpb25CdXMuc3Vic2NyaWJlKHsgdXVpZDogJyonIH0sIGd1aWQsIChpbnRlbnRSZXN1bHQpID0+IHtcblx0ICAgICAgICAgICAgcmVzb2x2ZShpbnRlbnRSZXN1bHQpO1xuXHQgICAgICAgIH0pLmNhdGNoKCgpID0+IHJlamVjdChuZXcgRXJyb3IoJ2dldFJlc3VsdCBpcyBub3Qgc3VwcG9ydGVkIGluIHRoaXMgZW52aXJvbm1lbnQnKSkpO1xuXHQgICAgfSk7XG5cdCAgICAvLyBBZGRpbmcgdGhlIGludGVudFJlc29sdXRpb25SZXN1bHRJZCB0byB0aGUgaW50ZW50T2JqLiBCZWNhdXNlIGZpcmVJbnRlbnQgb25seSBhY2NlcHRzIGEgc2luZ2xlIGFyZywgd2UgaGF2ZSB0byBzbGFwIGl0IGluIGhlcmUuXG5cdCAgICBjb25zdCBtZXRhZGF0YSA9IGFwcCA/IHsgdGFyZ2V0OiBhcHAsIGludGVudFJlc29sdXRpb25SZXN1bHRJZDogZ3VpZCB9IDogeyBpbnRlbnRSZXNvbHV0aW9uUmVzdWx0SWQ6IGd1aWQgfTtcblx0ICAgIGNvbnN0IGludGVudE9iaiA9IGludGVudCA/IHsgbmFtZTogaW50ZW50LCBjb250ZXh0LCBtZXRhZGF0YSB9IDogeyAuLi5jb250ZXh0LCBtZXRhZGF0YSB9O1xuXHQgICAgLy8gU2V0IHVwIHRoZSBnZXRSZXN1bHQgY2FsbC5cblx0ICAgIGNvbnN0IGdldFJlc3VsdCA9IGFzeW5jICgpID0+IHtcblx0ICAgICAgICBsZXQgaW50ZW50UmVzdWx0ID0gYXdhaXQgZ2V0UmVzdWx0UHJvbWlzZTtcblx0ICAgICAgICBpZiAoIWludGVudFJlc3VsdCB8fCB0eXBlb2YgaW50ZW50UmVzdWx0ICE9PSAnb2JqZWN0Jykge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoUmVzdWx0RXJyb3IuTm9SZXN1bHRSZXR1cm5lZCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNvbnN0IHsgZXJyb3IgfSA9IGludGVudFJlc3VsdDtcblx0ICAgICAgICBpZiAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFJlc3VsdEVycm9yLkludGVudEhhbmRsZXJSZWplY3RlZCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGlmICgoMCwgZXhwb3J0cy5pc0NoYW5uZWwpKGludGVudFJlc3VsdCkpIHtcblx0ICAgICAgICAgICAgY29uc3QgeyBpZCwgdHlwZSB9ID0gaW50ZW50UmVzdWx0O1xuXHQgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcblx0ICAgICAgICAgICAgICAgIGNhc2UgJ3ByaXZhdGUnOiB7XG5cdCAgICAgICAgICAgICAgICAgICAgaW50ZW50UmVzdWx0ID0gYXdhaXQgKDAsIGV4cG9ydHMuY29ubmVjdFByaXZhdGVDaGFubmVsKShpZCk7XG5cdCAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICBjYXNlICdhcHAnOiB7XG5cdCAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkNvbnRleHRHcm91cCA9IGF3YWl0IGludGVyb3BNb2R1bGUuam9pblNlc3Npb25Db250ZXh0R3JvdXAoaWQpO1xuXHQgICAgICAgICAgICAgICAgICAgIGludGVudFJlc3VsdCA9ICgwLCBleHBvcnRzLmJ1aWxkQXBwQ2hhbm5lbE9iamVjdCkoc2Vzc2lvbkNvbnRleHRHcm91cCk7XG5cdCAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSBpZiAoISgwLCBleHBvcnRzLmlzQ29udGV4dCkoaW50ZW50UmVzdWx0KSkge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoUmVzdWx0RXJyb3IuTm9SZXN1bHRSZXR1cm5lZCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiBpbnRlbnRSZXN1bHQ7XG5cdCAgICB9O1xuXHQgICAgLy8gRmluYWxseSBmaXJlIHRoZSBpbnRlbnQuXG5cdCAgICBjb25zdCBpbnRlbnRSZXNvbHV0aW9uSW5mb0Zyb21Ccm9rZXIgPSBpbnRlbnRcblx0ICAgICAgICA/IGF3YWl0IGludGVyb3BNb2R1bGUuZmlyZUludGVudChpbnRlbnRPYmopXG5cdCAgICAgICAgOiBhd2FpdCBpbnRlcm9wTW9kdWxlLmZpcmVJbnRlbnRGb3JDb250ZXh0KGludGVudE9iaik7XG5cdCAgICBpZiAodHlwZW9mIGludGVudFJlc29sdXRpb25JbmZvRnJvbUJyb2tlciAhPT0gJ29iamVjdCcpIHtcblx0ICAgICAgICByZXR1cm4ge1xuXHQgICAgICAgICAgICBzb3VyY2U6IHtcblx0ICAgICAgICAgICAgICAgIGFwcElkOiAnJyxcblx0ICAgICAgICAgICAgICAgIGluc3RhbmNlSWQ6ICcnXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIGludGVudDogJycsXG5cdCAgICAgICAgICAgIHZlcnNpb246ICcyLjAnLFxuXHQgICAgICAgICAgICBnZXRSZXN1bHRcblx0ICAgICAgICB9O1xuXHQgICAgfVxuXHQgICAgcmV0dXJuIHsgLi4uaW50ZW50UmVzb2x1dGlvbkluZm9Gcm9tQnJva2VyLCBnZXRSZXN1bHQgfTtcblx0fTtcblx0ZXhwb3J0cy5nZXRJbnRlbnRSZXNvbHV0aW9uID0gZ2V0SW50ZW50UmVzb2x1dGlvbjsgXG59ICh1dGlscyQyKSk7XG5cbnZhciBoYXNSZXF1aXJlZEZkYzNDb21tb247XG5cbmZ1bmN0aW9uIHJlcXVpcmVGZGMzQ29tbW9uICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkRmRjM0NvbW1vbikgcmV0dXJuIGZkYzNDb21tb247XG5cdGhhc1JlcXVpcmVkRmRjM0NvbW1vbiA9IDE7XG5cdHZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcblx0ICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcblx0ICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuXHQgICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcblx0fTtcblx0dmFyIF9fY2xhc3NQcml2YXRlRmllbGRTZXQgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZFNldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcblx0ICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcblx0ICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcblx0ICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG5cdCAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcblx0fTtcblx0dmFyIF9faW1wb3J0RGVmYXVsdCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2ltcG9ydERlZmF1bHQpIHx8IGZ1bmN0aW9uIChtb2QpIHtcblx0ICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgXCJkZWZhdWx0XCI6IG1vZCB9O1xuXHR9O1xuXHR2YXIgX0ZEQzNNb2R1bGVCYXNlX3Byb2R1Y2VyO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZmRjM0NvbW1vbiwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdGZkYzNDb21tb24uRkRDM01vZHVsZUJhc2UgPSB2b2lkIDA7XG5cdGNvbnN0IHV0aWxzXzEgPSB1dGlscyQyO1xuXHRjb25zdCB1dGlsc18yID0gdXRpbHMkMztcblx0Y29uc3QgSW50ZXJvcENsaWVudF8xID0gcmVxdWlyZUludGVyb3BDbGllbnQoKTtcblx0Y29uc3QgaXNFcXVhbF8xID0gX19pbXBvcnREZWZhdWx0KHJlcXVpcmUkJDMpO1xuXHRjbGFzcyBGREMzTW9kdWxlQmFzZSB7XG5cdCAgICBnZXQgY2xpZW50KCkge1xuXHQgICAgICAgIHJldHVybiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9GREMzTW9kdWxlQmFzZV9wcm9kdWNlciwgXCJmXCIpLmNhbGwodGhpcyk7XG5cdCAgICB9XG5cdCAgICBnZXQgZmluKCkge1xuXHQgICAgICAgIHJldHVybiB0aGlzLndpcmUuZ2V0RmluKCk7XG5cdCAgICB9XG5cdCAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlbGVzcy1jb25zdHJ1Y3RvclxuXHQgICAgY29uc3RydWN0b3IocHJvZHVjZXIsIHdpcmUpIHtcblx0ICAgICAgICB0aGlzLndpcmUgPSB3aXJlO1xuXHQgICAgICAgIF9GREMzTW9kdWxlQmFzZV9wcm9kdWNlci5zZXQodGhpcywgdm9pZCAwKTtcblx0ICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9GREMzTW9kdWxlQmFzZV9wcm9kdWNlciwgcHJvZHVjZXIsIFwiZlwiKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQnJvYWRjYXN0cyBhIGNvbnRleHQgZm9yIHRoZSBjaGFubmVsIG9mIHRoZSBjdXJyZW50IGVudGl0eS5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0IC0gTmV3IGNvbnRleHQgdG8gc2V0LlxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmJyb2FkY2FzdFxuXHQgICAgICogQHN0YXRpY1xuXHQgICAgICovXG5cdCAgICBhc3luYyBicm9hZGNhc3QoY29udGV4dCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLWJyb2FkY2FzdCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiB0aGlzLmNsaWVudC5zZXRDb250ZXh0KGNvbnRleHQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBMYXVuY2hlcyBhbiBhcHAgd2l0aCB0YXJnZXQgaW5mb3JtYXRpb24sIHdoaWNoIGNhbiBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgYW4gQXBwTWV0YWRhdGEgb2JqZWN0LlxuXHQgICAgICogQHBhcmFtIGFwcFxuXHQgICAgICogQHBhcmFtIGNvbnRleHRcblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5vcGVuXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIF9vcGVuKGFwcCwgY29udGV4dCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLW9wZW4nKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICByZXR1cm4gYXdhaXQgSW50ZXJvcENsaWVudF8xLkludGVyb3BDbGllbnQuZmVycnlGZGMzQ2FsbCh0aGlzLmNsaWVudCwgJ2ZkYzNPcGVuJywgeyBhcHAsIGNvbnRleHQgfSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zdCBlcnJvclRvVGhyb3cgPSBlcnJvci5tZXNzYWdlID09PSB1dGlsc18yLkJST0tFUl9FUlJPUlMuZmRjM09wZW4gPyAnUmVzb2x2ZXJVbmF2YWlsYWJsZScgOiBlcnJvci5tZXNzYWdlO1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JUb1Rocm93KTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICBhc3luYyBfZ2V0Q2hhbm5lbHMoKSB7XG5cdCAgICAgICAgY29uc3QgY2hhbm5lbHMgPSBhd2FpdCB0aGlzLmNsaWVudC5nZXRDb250ZXh0R3JvdXBzKCk7XG5cdCAgICAgICAgLy8gZmRjMyBpbXBsZW1lbnRhdGlvbiBvZiBnZXRTeXN0ZW1DaGFubmVscyByZXR1cm5zIGFuIGFycmF5IG9mIGNoYW5uZWxzLCBoYXZlIHRvIGRlY29yYXRlIG92ZXJcblx0ICAgICAgICAvLyB0aGlzIHNvIHBlb3BsZSBrbm93IHRoYXQgdGhlc2UgQVBJcyBhcmUgbm90IHN1cHBvcnRlZFxuXHQgICAgICAgIHJldHVybiBjaGFubmVscy5tYXAoKGNoYW5uZWwpID0+IHtcblx0ICAgICAgICAgICAgcmV0dXJuIHsgLi4uY2hhbm5lbCwgdHlwZTogJ3N5c3RlbScsIC4uLigwLCB1dGlsc18xLmdldFVuc3VwcG9ydGVkQ2hhbm5lbEFwaXMpKCkgfTtcblx0ICAgICAgICB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0dXJucyBhIENoYW5uZWwgb2JqZWN0IGZvciB0aGUgc3BlY2lmaWVkIGNoYW5uZWwsIGNyZWF0aW5nIGl0IGFzIGFuIEFwcCBDaGFubmVsIGlmIGl0IGRvZXMgbm90IGV4aXN0LlxuXHQgICAgICogQHBhcmFtIGNoYW5uZWxJZFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmdldE9yQ3JlYXRlQ2hhbm5lbFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRPckNyZWF0ZUNoYW5uZWwoY2hhbm5lbElkKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtZ2V0LW9yLWNyZWF0ZS1jaGFubmVsJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3Qgc3lzdGVtQ2hhbm5lbHMgPSBhd2FpdCB0aGlzLl9nZXRDaGFubmVscygpO1xuXHQgICAgICAgIGNvbnN0IHVzZXJDaGFubmVsID0gc3lzdGVtQ2hhbm5lbHMuZmluZCgoY2hhbm5lbCkgPT4gY2hhbm5lbC5pZCA9PT0gY2hhbm5lbElkKTtcblx0ICAgICAgICBpZiAodXNlckNoYW5uZWwpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIHsgLi4udXNlckNoYW5uZWwsIHR5cGU6ICdzeXN0ZW0nLCAuLi4oMCwgdXRpbHNfMS5nZXRVbnN1cHBvcnRlZENoYW5uZWxBcGlzKSgpIH07XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIGNvbnN0IHNlc3Npb25Db250ZXh0R3JvdXAgPSBhd2FpdCB0aGlzLmNsaWVudC5qb2luU2Vzc2lvbkNvbnRleHRHcm91cChjaGFubmVsSWQpO1xuXHQgICAgICAgICAgICByZXR1cm4gKDAsIHV0aWxzXzEuYnVpbGRBcHBDaGFubmVsT2JqZWN0KShzZXNzaW9uQ29udGV4dEdyb3VwKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IubWVzc2FnZSk7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih1dGlsc18xLkNoYW5uZWxFcnJvci5DcmVhdGlvbkZhaWxlZCk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXR1cm5zIHRoZSBJbnRlcm9wLUJyb2tlci1kZWZpbmVkIGNvbnRleHQgZ3JvdXBzIGF2YWlsYWJsZSBmb3IgYW4gZW50aXR5IHRvIGpvaW4uXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuZ2V0U3lzdGVtQ2hhbm5lbHNcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0U3lzdGVtQ2hhbm5lbHMoKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtZ2V0LXN5c3RlbS1jaGFubmVscycpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiB0aGlzLl9nZXRDaGFubmVscygpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBKb2luIGFsbCBJbnRlcm9wIENsaWVudHMgYXQgdGhlIGdpdmVuIGlkZW50aXR5IHRvIGNvbnRleHQgZ3JvdXAgYGNvbnRleHRHcm91cElkYC5cblx0ICAgICAqIElmIG5vIHRhcmdldCBpcyBzcGVjaWZpZWQsIGl0IGFkZHMgdGhlIHNlbmRlciB0byB0aGUgY29udGV4dCBncm91cC5cblx0ICAgICAqIEJlY2F1c2UgbXVsdGlwbGUgQ2hhbm5lbCBjb25uZWN0aW9ucy9JbnRlcm9wIENsaWVudHMgY2FuIHBvdGVudGlhbGx5IGV4aXN0IGF0IGEgYHV1aWRgL2BuYW1lYCBjb21ibywgd2UgY3VycmVudGx5IGpvaW4gYWxsIENoYW5uZWwgY29ubmVjdGlvbnMvSW50ZXJvcCBDbGllbnRzIGF0IHRoZSBnaXZlbiBpZGVudGl0eSB0byB0aGUgY29udGV4dCBncm91cC5cblx0ICAgICAqIElmIGFuIGBlbmRwb2ludElkYCBpcyBwcm92aWRlZCAod2hpY2ggaXMgdW5saWtlbHksIHVubGVzcyB0aGUgY2FsbCBpcyBjb21pbmcgZnJvbSBhbiBleHRlcm5hbCBhZGFwdGVyKSwgdGhlbiB3ZSBvbmx5IGpvaW4gdGhhdCBzaW5nbGUgY29ubmVjdGlvbiB0byB0aGUgY29udGV4dCBncm91cC5cblx0ICAgICAqIEZvciBhbGwgaW50ZW50cyBhbmQgcHVycG9zZXMsIHRoZXJlIHdpbGwgb25seSBiZSAxIGNvbm5lY3Rpb24gcHJlc2VudCBpbiBQbGF0Zm9ybSBhbmQgQnJvd3NlciBpbXBsZW1lbnRhdGlvbnMsIHNvIHRoaXMgcG9pbnQgaXMgbW9yZS1vci1sZXNzIG1vb3QuXG5cdCAgICAgKiBAcGFyYW0gY2hhbm5lbElkIC0gSWQgb2YgdGhlIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuam9pbkNoYW5uZWxcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgam9pbkNoYW5uZWwoY2hhbm5lbElkKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtam9pbi1jaGFubmVsJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY2xpZW50LmpvaW5Db250ZXh0R3JvdXAoY2hhbm5lbElkKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGlmIChlcnJvci5tZXNzYWdlID09PSB1dGlsc18yLkJST0tFUl9FUlJPUlMuam9pblNlc3Npb25Db250ZXh0R3JvdXBXaXRoSm9pbkNvbnRleHRHcm91cCkge1xuXHQgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignVGhlIENoYW5uZWwgeW91IGhhdmUgdHJpZWQgdG8gam9pbiBpcyBhbiBBcHAgQ2hhbm5lbC4gQ3VzdG9tIENoYW5uZWxzIGNhbiBvbmx5IGJlIGRlZmluZWQgYnkgdGhlIEludGVyb3AgQnJva2VyIHRocm91Z2ggY29kZSBvciBtYW5pZmVzdCBjb25maWd1cmF0aW9uLiBQbGVhc2UgdXNlIGdldE9yQ3JlYXRlQ2hhbm5lbC4nKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBlbHNlIHtcblx0ICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IubWVzc2FnZSk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgaWYgKGVycm9yLm1lc3NhZ2Uuc3RhcnRzV2l0aCgnQXR0ZW1wdGluZyB0byBqb2luIGEgY29udGV4dCBncm91cCB0aGF0IGRvZXMgbm90IGV4aXN0JykpIHtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih1dGlsc18xLkNoYW5uZWxFcnJvci5Ob0NoYW5uZWxGb3VuZCk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHV0aWxzXzEuQ2hhbm5lbEVycm9yLkFjY2Vzc0RlbmllZCk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXR1cm5zIHRoZSBDaGFubmVsIHRoYXQgdGhlIGVudGl0eSBpcyBzdWJzY3JpYmVkIHRvLiBSZXR1cm5zIG51bGwgaWYgbm90IGpvaW5lZCB0byBhIGNoYW5uZWwuXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuZ2V0Q3VycmVudENoYW5uZWxcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0Q3VycmVudENoYW5uZWwoKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtZ2V0LWN1cnJlbnQtY2hhbm5lbCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGN1cnJlbnRDb250ZXh0R3JvdXBJbmZvID0gYXdhaXQgdGhpcy5nZXRDdXJyZW50Q29udGV4dEdyb3VwSW5mbygpO1xuXHQgICAgICAgIGlmICghY3VycmVudENvbnRleHRHcm91cEluZm8pIHtcblx0ICAgICAgICAgICAgcmV0dXJuIG51bGw7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiB0aGlzLmJ1aWxkQ2hhbm5lbE9iamVjdChjdXJyZW50Q29udGV4dEdyb3VwSW5mbyk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlbW92ZXMgdGhlIHNwZWNpZmllZCB0YXJnZXQgZnJvbSBhIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKiBJZiBubyB0YXJnZXQgaXMgc3BlY2lmaWVkLCBpdCByZW1vdmVzIHRoZSBzZW5kZXIgZnJvbSB0aGVpciBjb250ZXh0IGdyb3VwLlxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmxlYXZlQ3VycmVudENoYW5uZWxcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgbGVhdmVDdXJyZW50Q2hhbm5lbCgpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1sZWF2ZS1jdXJyZW50LWNoYW5uZWwnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gdGhpcy5jbGllbnQucmVtb3ZlRnJvbUNvbnRleHRHcm91cCgpO1xuXHQgICAgfVxuXHQgICAgLy8gdXRpbHNcblx0ICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzXG5cdCAgICBhc3luYyBnZXRDdXJyZW50Q29udGV4dEdyb3VwSW5mbygpIHtcblx0ICAgICAgICBjb25zdCBjb250ZXh0R3JvdXBzID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0Q29udGV4dEdyb3VwcygpO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudHNJbkN0eEdyb3Vwc1Byb21pc2UgPSBjb250ZXh0R3JvdXBzLm1hcChhc3luYyAoY3R4R3JvdXApID0+IHtcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50LmdldEFsbENsaWVudHNJbkNvbnRleHRHcm91cChjdHhHcm91cC5pZCk7XG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50c0luQ3R4R3JvdXBzID0gYXdhaXQgUHJvbWlzZS5hbGwoY2xpZW50c0luQ3R4R3JvdXBzUHJvbWlzZSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50SWR4ID0gY2xpZW50c0luQ3R4R3JvdXBzLmZpbmRJbmRleCgoY2xpZW50SWRlbnRpdHlBcnIpID0+IHtcblx0ICAgICAgICAgICAgcmV0dXJuIGNsaWVudElkZW50aXR5QXJyLnNvbWUoKGNsaWVudElkZW50aXR5KSA9PiB7XG5cdCAgICAgICAgICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IGNsaWVudElkZW50aXR5O1xuXHQgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMud2lyZS5tZS51dWlkID09PSB1dWlkICYmIHRoaXMud2lyZS5tZS5uYW1lID09PSBuYW1lO1xuXHQgICAgICAgICAgICB9KTtcblx0ICAgICAgICB9KTtcblx0ICAgICAgICByZXR1cm4gY29udGV4dEdyb3Vwc1tjbGllbnRJZHhdO1xuXHQgICAgfVxuXHQgICAgYXN5bmMgYnVpbGRDaGFubmVsT2JqZWN0KGN1cnJlbnRDb250ZXh0R3JvdXBJbmZvKSB7XG5cdCAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuXHQgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgIC4uLmN1cnJlbnRDb250ZXh0R3JvdXBJbmZvLFxuXHQgICAgICAgICAgICB0eXBlOiAnc3lzdGVtJyxcblx0ICAgICAgICAgICAgYWRkQ29udGV4dExpc3RlbmVyOiAoLi4uW2NvbnRleHRUeXBlLCBoYW5kbGVyXSkgPT4ge1xuXHQgICAgICAgICAgICAgICAgbGV0IHJlYWxIYW5kbGVyO1xuXHQgICAgICAgICAgICAgICAgbGV0IHJlYWxUeXBlO1xuXHQgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjb250ZXh0VHlwZSA9PT0gJ2Z1bmN0aW9uJykge1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignYWRkQ29udGV4dExpc3RlbmVyKGhhbmRsZXIpIGhhcyBiZWVuIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgYWRkQ29udGV4dExpc3RlbmVyKG51bGwsIGhhbmRsZXIpJyk7XG5cdCAgICAgICAgICAgICAgICAgICAgcmVhbEhhbmRsZXIgPSBjb250ZXh0VHlwZTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICAgICAgICAgIHJlYWxIYW5kbGVyID0gaGFuZGxlcjtcblx0ICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnRleHRUeXBlID09PSAnc3RyaW5nJykge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICByZWFsVHlwZSA9IGNvbnRleHRUeXBlO1xuXHQgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gKGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgICAgICAgICBsZXQgZmlyc3QgPSB0cnVlO1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRDb250ZXh0ID0gYXdhaXQgdGhpcy5jbGllbnQuZ2V0Q3VycmVudENvbnRleHQocmVhbFR5cGUpO1xuXHQgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdyYXBwZWRIYW5kbGVyID0gKGNvbnRleHQsIGNvbnRleHRNZXRhZGF0YSkgPT4ge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmlyc3QpIHtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0ID0gZmFsc2U7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKDAsIGlzRXF1YWxfMS5kZWZhdWx0KShjdXJyZW50Q29udGV4dCwgY29udGV4dCkpIHtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG5cdCAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbnNpc3RlbnQtcmV0dXJuXG5cdCAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZWFsSGFuZGxlcihjb250ZXh0LCBjb250ZXh0TWV0YWRhdGEpO1xuXHQgICAgICAgICAgICAgICAgICAgIH07XG5cdCAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50LmFkZENvbnRleHRIYW5kbGVyKHdyYXBwZWRIYW5kbGVyLCByZWFsVHlwZSk7XG5cdCAgICAgICAgICAgICAgICB9KSgpO1xuXHQgICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBUT0RPIFtDT1JFLTE1MjRdXG5cdCAgICAgICAgICAgICAgICByZXR1cm4ge1xuXHQgICAgICAgICAgICAgICAgICAgIC4uLmxpc3RlbmVyLFxuXHQgICAgICAgICAgICAgICAgICAgIHVuc3Vic2NyaWJlOiAoKSA9PiBsaXN0ZW5lci50aGVuKChsKSA9PiBsLnVuc3Vic2NyaWJlKCkpXG5cdCAgICAgICAgICAgICAgICB9O1xuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgICBicm9hZGNhc3Q6IHRoaXMuYnJvYWRjYXN0LmJpbmQodGhpcyksXG5cdCAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgVHlwZXNjcmlwdCBmYWlscyB0byBpbmZlciB0aGUgcmV0dXJudHlwZSBpcyBhIFByb21pc2Vcblx0ICAgICAgICAgICAgZ2V0Q3VycmVudENvbnRleHQ6IGFzeW5jIChjb250ZXh0VHlwZSkgPT4ge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgY29udGV4dCA9IGF3YWl0IHRoaXMuY2xpZW50LmdldEN1cnJlbnRDb250ZXh0KGNvbnRleHRUeXBlKTtcblx0ICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgVHlwZXNjcmlwdCBmYWlscyB0byBpbmZlciB0aGUgcmV0dXJudHlwZSBpcyBhIFByb21pc2Vcblx0ICAgICAgICAgICAgICAgIHJldHVybiBjb250ZXh0ID09PSB1bmRlZmluZWQgPyBudWxsIDogY29udGV4dDtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH07XG5cdCAgICB9XG5cdH1cblx0ZmRjM0NvbW1vbi5GREMzTW9kdWxlQmFzZSA9IEZEQzNNb2R1bGVCYXNlO1xuXHRfRkRDM01vZHVsZUJhc2VfcHJvZHVjZXIgPSBuZXcgV2Vha01hcCgpO1xuXHRyZXR1cm4gZmRjM0NvbW1vbjtcbn1cblxudmFyIGhhc1JlcXVpcmVkRmRjMzFfMjtcblxuZnVuY3Rpb24gcmVxdWlyZUZkYzMxXzIgKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRGZGMzMV8yKSByZXR1cm4gZmRjMzFfMjtcblx0aGFzUmVxdWlyZWRGZGMzMV8yID0gMTtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGZkYzMxXzIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRmZGMzMV8yLkZkYzNNb2R1bGUgPSB2b2lkIDA7XG5cdGNvbnN0IHV0aWxzXzEgPSB1dGlscyQzO1xuXHRjb25zdCBmZGMzX2NvbW1vbl8xID0gcmVxdWlyZUZkYzNDb21tb24oKTtcblx0LyoqXG5cdCAqIEB2ZXJzaW9uIDEuMlxuXHQgKiBUaGUgRkRDMyBDbGllbnQgTGlicmFyeSBwcm92aWRlcyBhIHNldCBBUElzIHRvIGJlIHVzZWQgZm9yIEZEQzMgY29tcGxpYW5jZSxcblx0ICogd2hpbGUgdXNpbmcgb3VyIEludGVyb3AgQVBJIHVuZGVyIHRoZSBob29kLiBJbiBvcmRlciB0byB1c2UgdGhpcyBzZXQgb2YgQVBJc1xuXHQgKiB5b3Ugd2lsbCBuZWVkIHRvIHNldCB1cCB5b3VyIG93biB7QGxpbmsgSW50ZXJvcEJyb2tlciBJbnRlcm9wQnJva2VyfSBvciB1c2UgYSBQbGF0Zm9ybSBhcHBsaWNhdGlvbiwgd2hpY2ggZG9lcyB0aGUgc2V0dXAgZm9yIHlvdS4gUmVmZXIgdG8gb3VyIGRvY3VtZW50YXRpb24gb25cblx0ICogb3VyIHtAbGluayBodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9vZi1kb2NzL2RvY3MvZW5hYmxlLWNvbG9yLWxpbmtpbmcgSW50ZXJvcCBBUEl9LlxuXHQgKlxuXHQgKiBUbyBlbmFibGUgdGhlIEZEQzMgQVBJcyBpbiBhIHtAbGluayBXaW5kb3cgV2luZG93fSBvciB7QGxpbmsgVmlldyBWaWV3fSwgYWRkIHRoZSBmZGMzSW50ZXJvcEFwaVxuXHQgKiBwcm9wZXJ0eSB0byBpdHMgb3B0aW9uczpcblx0ICpcblx0ICogYGBganNcblx0ICoge1xuXHQgKiAgICAgYXV0b1Nob3c6IGZhbHNlLFxuXHQgKiAgICAgc2F2ZVdpbmRvd1N0YXRlOiB0cnVlLFxuXHQgKiAgICAgdXJsOiAnaHR0cHM6Ly9vcGVuZmluLmNvJyxcblx0ICogICAgIGZkYzNJbnRlcm9wQXBpOiAnMS4yJ1xuXHQgKiB9XG5cdCAqIGBgYFxuXHQgKlxuXHQgKiBJZiB1c2luZyBhIHtAbGluayBQbGF0Zm9ybSBQbGF0Zm9ybSB9IGFwcGxpY2F0aW9uLCB5b3UgY2FuIHNldCB0aGlzIHByb3BlcnR5IGluIGRlZmF1bHRXaW5kb3dPcHRpb25zIGFuZCBkZWZhdWx0Vmlld09wdGlvbnMuXG5cdCAqXG5cdCAqIEluIG9yZGVyIHRvIGVuc3VyZSB0aGF0IHRoZSBGREMzIEFwaSBpcyByZWFkeSBiZWZvcmUgdXNlLCB5b3UgY2FuIHVzZSB0aGUgJ2ZkYzNSZWFkeScgZXZlbnQgZmlyZWQgb24gdGhlIERPTSBXaW5kb3cgb2JqZWN0OlxuXHQgKlxuXHQgKiBgYGBqc1xuXHQgKiBmdW5jdGlvbiBmZGMzQWN0aW9uKCkge1xuXHQgKiAgICAgLy8gTWFrZSBzb21lIGZkYzMgQVBJIGNhbGxzIGhlcmVcblx0ICogfVxuXHQgKlxuXHQgKiBpZiAod2luZG93LmZkYzMpIHtcblx0ICogICAgZmRjM0FjdGlvbigpO1xuXHQgKiB9IGVsc2Uge1xuXHQgKiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignZmRjM1JlYWR5JywgZmRjM0FjdGlvbik7XG5cdCAqIH1cblx0ICogYGBgXG5cdCAqL1xuXHRjbGFzcyBGZGMzTW9kdWxlIGV4dGVuZHMgZmRjM19jb21tb25fMS5GREMzTW9kdWxlQmFzZSB7XG5cdCAgICBhc3luYyBvcGVuKGFwcCwgY29udGV4dCkge1xuXHQgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlcnNjb3JlLWRhbmdsZVxuXHQgICAgICAgIGF3YWl0IHN1cGVyLl9vcGVuKGFwcCwgY29udGV4dCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEFkZCBhIGNvbnRleHQgaGFuZGxlciBmb3IgaW5jb21pbmcgY29udGV4dC4gSWYgYW4gZW50aXR5IGlzIHBhcnQgb2YgYSBjb250ZXh0IGdyb3VwLCBhbmQgdGhlbiBzZXRzIGl0cyBjb250ZXh0IGhhbmRsZXIsIGl0IHdpbGwgcmVjZWl2ZSBhbGwgb2YgaXRzIGRlY2xhcmVkIGNvbnRleHRzLiBJZiB5b3Ugd2lzaCB0byBsaXN0ZW4gZm9yIGFsbCBpbmNvbWluZyBjb250ZXh0cywgcGFzcyBgbnVsbGAgZm9yIHRoZSBjb250ZXh0VHlwZSBhcmd1bWVudC5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0VHlwZSAtIFRoZSB0eXBlIG9mIGNvbnRleHQgeW91IHdpc2ggdG8gaGFuZGxlLlxuXHQgICAgICogQHBhcmFtIGhhbmRsZXIgLSBIYW5kbGVyIGZvciBpbmNvbWluZyBjb250ZXh0LlxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmFkZENvbnRleHRMaXN0ZW5lclxuXHQgICAgICogQHN0YXRpY1xuXHQgICAgICovXG5cdCAgICAvLyBAdHMtZXhwZWN0LWVycm9yIFRPRE8gW0NPUkUtMTUyNF1cblx0ICAgIGFkZENvbnRleHRMaXN0ZW5lcihjb250ZXh0VHlwZSwgaGFuZGxlcikge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLWFkZC1jb250ZXh0LWxpc3RlbmVyJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgbGV0IGxpc3RlbmVyO1xuXHQgICAgICAgIGlmICh0eXBlb2YgY29udGV4dFR5cGUgPT09ICdmdW5jdGlvbicpIHtcblx0ICAgICAgICAgICAgY29uc29sZS53YXJuKCdhZGRDb250ZXh0TGlzdGVuZXIoaGFuZGxlcikgaGFzIGJlZW4gZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBhZGRDb250ZXh0TGlzdGVuZXIobnVsbCwgaGFuZGxlciknKTtcblx0ICAgICAgICAgICAgbGlzdGVuZXIgPSB0aGlzLmNsaWVudC5hZGRDb250ZXh0SGFuZGxlcihjb250ZXh0VHlwZSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICBsaXN0ZW5lciA9IHRoaXMuY2xpZW50LmFkZENvbnRleHRIYW5kbGVyKGhhbmRsZXIsIGNvbnRleHRUeXBlID09PSBudWxsID8gdW5kZWZpbmVkIDogY29udGV4dFR5cGUpO1xuXHQgICAgICAgIH1cblx0ICAgICAgICByZXR1cm4ge1xuXHQgICAgICAgICAgICAuLi5saXN0ZW5lcixcblx0ICAgICAgICAgICAgdW5zdWJzY3JpYmU6ICgpID0+IGxpc3RlbmVyLnRoZW4oKGwpID0+IGwudW5zdWJzY3JpYmUoKSlcblx0ICAgICAgICB9O1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBBZGRzIGEgbGlzdGVuZXIgZm9yIGluY29taW5nIEludGVudHMuXG5cdCAgICAgKiBAcGFyYW0gaW50ZW50IC0gTmFtZSBvZiB0aGUgSW50ZW50XG5cdCAgICAgKiBAcGFyYW0gaGFuZGxlciAtIEhhbmRsZXIgZm9yIGluY29taW5nIEludGVudFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmFkZEludGVudExpc3RlbmVyXG5cdCAgICAgKiBAc3RhdGljXG5cdCAgICAgKi9cblx0ICAgIGFkZEludGVudExpc3RlbmVyKGludGVudCwgaGFuZGxlcikge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLWFkZC1pbnRlbnQtbGlzdGVuZXInKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjb250ZXh0SGFuZGxlciA9IChyYWlzZWRJbnRlbnQpID0+IHtcblx0ICAgICAgICAgICAgY29uc3QgeyBjb250ZXh0LCBtZXRhZGF0YTogaW50ZW50TWV0YWRhdGEgfSA9IHJhaXNlZEludGVudDtcblx0ICAgICAgICAgICAgY29uc3QgeyBtZXRhZGF0YSB9ID0gY29udGV4dDtcblx0ICAgICAgICAgICAgY29uc3QgaW50ZW50UmVzb2x1dGlvblJlc3VsdElkID0gaW50ZW50TWV0YWRhdGE/LmludGVudFJlc29sdXRpb25SZXN1bHRJZCB8fCBtZXRhZGF0YT8uaW50ZW50UmVzb2x1dGlvblJlc3VsdElkO1xuXHQgICAgICAgICAgICBpZiAoaW50ZW50UmVzb2x1dGlvblJlc3VsdElkKSB7XG5cdCAgICAgICAgICAgICAgICB0aGlzLmZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLnB1Ymxpc2goaW50ZW50UmVzb2x1dGlvblJlc3VsdElkLCBudWxsKS5jYXRjaCgoKSA9PiBudWxsKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBoYW5kbGVyKHJhaXNlZEludGVudC5jb250ZXh0KTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIGNvbnN0IGxpc3RlbmVyID0gdGhpcy5jbGllbnQucmVnaXN0ZXJJbnRlbnRIYW5kbGVyKGNvbnRleHRIYW5kbGVyLCBpbnRlbnQsIHtcblx0ICAgICAgICAgICAgZmRjM1ZlcnNpb246ICcxLjInXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgcmV0dXJuIHtcblx0ICAgICAgICAgICAgLi4ubGlzdGVuZXIsXG5cdCAgICAgICAgICAgIHVuc3Vic2NyaWJlOiAoKSA9PiBsaXN0ZW5lci50aGVuKChsKSA9PiBsLnVuc3Vic2NyaWJlKCkpXG5cdCAgICAgICAgfTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmFpc2VzIGEgc3BlY2lmaWMgaW50ZW50LlxuXHQgICAgICogQHBhcmFtIGludGVudCBOYW1lIG9mIHRoZSBJbnRlbnQuXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dCBDb250ZXh0IGFzc29jaWF0ZWQgd2l0aCB0aGUgSW50ZW50LlxuXHQgICAgICogQHBhcmFtICBhcHAgQXBwIHRoYXQgd2lsbCByZXNvbHZlIHRoZSBJbnRlbnQuIFRoaXMgaXMgYWRkZWQgYXMgbWV0YWRhdGEgdG8gdGhlIEludGVudC4gQ2FuIGJlIGFjY2Vzc2VkIGJ5IHRoZSBhcHAgcHJvdmlkZXIgaW4ge0BsaW5rIEludGVyb3BCcm9rZXIjaGFuZGxlRmlyZWRJbnRlbnQgSW50ZXJvcEJyb2tlci5oYW5kbGVGaXJlZEludGVudH0uXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMucmFpc2VJbnRlbnRcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgcmFpc2VJbnRlbnQoaW50ZW50LCBjb250ZXh0LCBhcHApIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1yYWlzZS1pbnRlbnQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBpbnRlbnRPYmogPSBhcHBcblx0ICAgICAgICAgICAgPyB7IG5hbWU6IGludGVudCwgY29udGV4dCwgbWV0YWRhdGE6IHsgdGFyZ2V0OiBhcHAgfSB9XG5cdCAgICAgICAgICAgIDogeyBuYW1lOiBpbnRlbnQsIGNvbnRleHQgfTtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5jbGllbnQuZmlyZUludGVudChpbnRlbnRPYmopO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc3QgZXJyb3JUb1Rocm93ID0gZXJyb3IubWVzc2FnZSA9PT0gdXRpbHNfMS5CUk9LRVJfRVJST1JTLmZpcmVJbnRlbnQgPyAnUmVzb2x2ZXJVbmF2YWlsYWJsZScgOiBlcnJvci5tZXNzYWdlO1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JUb1Rocm93KTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEZpbmQgb3V0IG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgYSBwYXJ0aWN1bGFyIGludGVudCBieSBwYXNzaW5nIGl0cyBuYW1lLCBhbmQgb3B0aW9uYWxseSBpdHMgY29udGV4dC5cblx0ICAgICAqIEBwYXJhbSBpbnRlbnQgTmFtZSBvZiB0aGUgSW50ZW50XG5cdCAgICAgKiBAcGFyYW0gY29udGV4dFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmZpbmRJbnRlbnRcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZmluZEludGVudChpbnRlbnQsIGNvbnRleHQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1maW5kLWludGVudCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNsaWVudC5nZXRJbmZvRm9ySW50ZW50KHsgbmFtZTogaW50ZW50LCBjb250ZXh0IH0pO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc3QgZXJyb3JUb1Rocm93ID0gZXJyb3IubWVzc2FnZSA9PT0gdXRpbHNfMS5CUk9LRVJfRVJST1JTLmdldEluZm9Gb3JJbnRlbnQgPyAnUmVzb2x2ZXJVbmF2YWlsYWJsZScgOiBlcnJvci5tZXNzYWdlO1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JUb1Rocm93KTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEZpbmQgYWxsIHRoZSBhdmFpbGFibGUgaW50ZW50cyBmb3IgYSBwYXJ0aWN1bGFyIGNvbnRleHQuXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmZpbmRJbnRlbnRzQnlDb250ZXh0XG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGZpbmRJbnRlbnRzQnlDb250ZXh0KGNvbnRleHQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1maW5kLWludGVudHMtYnktY29udGV4dCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmNsaWVudC5nZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dChjb250ZXh0KTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGVycm9yVG9UaHJvdyA9IGVycm9yLm1lc3NhZ2UgPT09IHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5nZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dCA/ICdSZXNvbHZlclVuYXZhaWxhYmxlJyA6IGVycm9yLm1lc3NhZ2U7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclRvVGhyb3cpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogRmluZHMgYW5kIHJhaXNlcyBhbiBpbnRlbnQgYWdhaW5zdCBhIHRhcmdldCBhcHAgYmFzZWQgcHVyZWx5IG9uIGNvbnRleHQgZGF0YS5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0XG5cdCAgICAgKiBAcGFyYW0gYXBwXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMucmFpc2VJbnRlbnRGb3JDb250ZXh0XG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHJhaXNlSW50ZW50Rm9yQ29udGV4dChjb250ZXh0LCBhcHApIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1yYWlzZS1pbnRlbnQtZm9yLWNvbnRleHQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5jbGllbnQuZmlyZUludGVudEZvckNvbnRleHQoeyAuLi5jb250ZXh0LCBtZXRhZGF0YTogeyB0YXJnZXQ6IGFwcCB9IH0pO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc3QgZXJyb3JUb1Rocm93ID0gZXJyb3IubWVzc2FnZSA9PT0gdXRpbHNfMS5CUk9LRVJfRVJST1JTLmZpcmVJbnRlbnRGb3JDb250ZXh0ID8gJ1Jlc29sdmVyVW5hdmFpbGFibGUnIDogZXJyb3IubWVzc2FnZTtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yVG9UaHJvdyk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXR1cm5zIGEgQ2hhbm5lbCBvYmplY3QgZm9yIHRoZSBzcGVjaWZpZWQgY2hhbm5lbCwgY3JlYXRpbmcgaXQgYXMgYW4gQXBwIENoYW5uZWwgaWYgaXQgZG9lcyBub3QgZXhpc3QuXG5cdCAgICAgKiBAcGFyYW0gY2hhbm5lbElkXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuZ2V0T3JDcmVhdGVDaGFubmVsXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldE9yQ3JlYXRlQ2hhbm5lbChjaGFubmVsSWQpIHtcblx0ICAgICAgICByZXR1cm4gc3VwZXIuZ2V0T3JDcmVhdGVDaGFubmVsKGNoYW5uZWxJZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgbWV0YWRhdGEgcmVsYXRpbmcgdG8gdGhlIEZEQzMgb2JqZWN0IGFuZCBpdHMgcHJvdmlkZXIsIGluY2x1ZGluZyB0aGUgc3VwcG9ydGVkIHZlcnNpb24gb2YgdGhlIEZEQzMgc3BlY2lmaWNhdGlvbiBhbmQgdGhlIG5hbWUgb2YgdGhlIHByb3ZpZGVyIG9mIHRoZSBpbXBsZW1lbnRhdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5nZXRJbmZvXG5cdCAgICAgKi9cblx0ICAgIGdldEluZm8oKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtZ2V0LWluZm8nKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCB2ZXJzaW9uID0gdGhpcy53aXJlLmVudmlyb25tZW50LmdldEFkYXB0ZXJWZXJzaW9uU3luYygpO1xuXHQgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgIHByb3ZpZGVyVmVyc2lvbjogdmVyc2lvbixcblx0ICAgICAgICAgICAgcHJvdmlkZXI6IGBvcGVuZmluLSR7dGhpcy53aXJlLm1lLnV1aWR9YCxcblx0ICAgICAgICAgICAgZmRjM1ZlcnNpb246ICcxLjInXG5cdCAgICAgICAgfTtcblx0ICAgIH1cblx0fVxuXHRmZGMzMV8yLkZkYzNNb2R1bGUgPSBGZGMzTW9kdWxlO1xuXHRyZXR1cm4gZmRjMzFfMjtcbn1cblxudmFyIGZkYzMyXzAgPSB7fTtcblxudmFyIGhhc1JlcXVpcmVkRmRjMzJfMDtcblxuZnVuY3Rpb24gcmVxdWlyZUZkYzMyXzAgKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRGZGMzMl8wKSByZXR1cm4gZmRjMzJfMDtcblx0aGFzUmVxdWlyZWRGZGMzMl8wID0gMTtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGZkYzMyXzAsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRmZGMzMl8wLkZkYzNNb2R1bGUyID0gdm9pZCAwO1xuXHRjb25zdCBmZGMzX2NvbW1vbl8xID0gcmVxdWlyZUZkYzNDb21tb24oKTtcblx0Y29uc3QgdXRpbHNfMSA9IHV0aWxzJDM7XG5cdGNvbnN0IEludGVyb3BDbGllbnRfMSA9IHJlcXVpcmVJbnRlcm9wQ2xpZW50KCk7XG5cdGNvbnN0IHV0aWxzXzIgPSB1dGlscyQyO1xuXHRjb25zdCBQcml2YXRlQ2hhbm5lbENsaWVudF8xID0gUHJpdmF0ZUNoYW5uZWxDbGllbnQkMTtcblx0LyoqXG5cdCAqIEB2ZXJzaW9uIDIuMFxuXHQgKiBUaGUgRkRDMyBDbGllbnQgTGlicmFyeSBwcm92aWRlcyBhIHNldCBBUElzIHRvIGJlIHVzZWQgZm9yIEZEQzMgY29tcGxpYW5jZSxcblx0ICogd2hpbGUgdXNpbmcgb3VyIEludGVyb3AgQVBJIHVuZGVyIHRoZSBob29kLiBJbiBvcmRlciB0byB1c2UgdGhpcyBzZXQgb2YgQVBJc1xuXHQgKiB5b3Ugd2lsbCBuZWVkIHRvIHNldCB1cCB5b3VyIG93biB7QGxpbmsgSW50ZXJvcEJyb2tlciBJbnRlcm9wQnJva2VyfSBvciB1c2UgYSBQbGF0Zm9ybSBhcHBsaWNhdGlvbiwgd2hpY2ggZG9lcyB0aGUgc2V0dXAgZm9yIHlvdS4gUmVmZXIgdG8gb3VyIGRvY3VtZW50YXRpb24gb25cblx0ICogb3VyIHtAbGluayBodHRwczovL2RldmVsb3BlcnMub3BlbmZpbi5jby9vZi1kb2NzL2RvY3MvZW5hYmxlLWNvbnRleHQtc2hhcmluZyBJbnRlcm9wIEFQSX0uXG5cdCAqXG5cdCAqIFRvIGVuYWJsZSB0aGUgRkRDMyBBUElzIGluIGEge0BsaW5rIFdpbmRvdyBXaW5kb3d9IG9yIHtAbGluayBWaWV3IFZpZXd9LCBhZGQgdGhlIGZkYzNJbnRlcm9wQXBpXG5cdCAqIHByb3BlcnR5IHRvIGl0cyBvcHRpb25zOlxuXHQgKlxuXHQgKiBgYGBqc1xuXHQgKiB7XG5cdCAqICAgICBhdXRvU2hvdzogZmFsc2UsXG5cdCAqICAgICBzYXZlV2luZG93U3RhdGU6IHRydWUsXG5cdCAqICAgICB1cmw6ICdodHRwczovL29wZW5maW4uY28nLFxuXHQgKiAgICAgZmRjM0ludGVyb3BBcGk6ICcyLjAnXG5cdCAqIH1cblx0ICogYGBgXG5cdCAqXG5cdCAqIElmIHVzaW5nIGEge0BsaW5rIFBsYXRmb3JtIFBsYXRmb3JtIH0gYXBwbGljYXRpb24sIHlvdSBjYW4gc2V0IHRoaXMgcHJvcGVydHkgaW4gZGVmYXVsdFdpbmRvd09wdGlvbnMgYW5kIGRlZmF1bHRWaWV3T3B0aW9ucy5cblx0ICpcblx0ICogSW4gb3JkZXIgdG8gZW5zdXJlIHRoYXQgdGhlIEZEQzMgQXBpIGlzIHJlYWR5IGJlZm9yZSB1c2UsIHlvdSBjYW4gdXNlIHRoZSAnZmRjM1JlYWR5JyBldmVudCBmaXJlZCBvbiB0aGUgRE9NIFdpbmRvdyBvYmplY3Q6XG5cdCAqXG5cdCAqIGBgYGpzXG5cdCAqIGZ1bmN0aW9uIGZkYzNBY3Rpb24oKSB7XG5cdCAqICAgICAvLyBNYWtlIHNvbWUgZmRjMyBBUEkgY2FsbHMgaGVyZVxuXHQgKiB9XG5cdCAqXG5cdCAqIGlmICh3aW5kb3cuZmRjMykge1xuXHQgKiAgICBmZGMzQWN0aW9uKCk7XG5cdCAqIH0gZWxzZSB7XG5cdCAqICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdmZGMzUmVhZHknLCBmZGMzQWN0aW9uKTtcblx0ICogfVxuXHQgKiBgYGBcblx0ICovXG5cdGNsYXNzIEZkYzNNb2R1bGUyIGV4dGVuZHMgZmRjM19jb21tb25fMS5GREMzTW9kdWxlQmFzZSB7XG5cdCAgICAvKipcblx0ICAgICAqIExhdW5jaGVzIGFuIGFwcCwgc3BlY2lmaWVkIHZpYSBhbiBBcHBJZGVudGlmaWVyIG9iamVjdC5cblx0ICAgICAqIEBwYXJhbSBhcHBcblx0ICAgICAqIEBwYXJhbSBjb250ZXh0XG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMub3BlblxuXHQgICAgICovXG5cdCAgICBhc3luYyBvcGVuKGFwcCwgY29udGV4dCkge1xuXHQgICAgICAgIGlmICh0eXBlb2YgYXBwID09PSAnc3RyaW5nJykge1xuXHQgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1Bhc3NpbmcgYSBzdHJpbmcgYXMgdGhlIGFwcCBwYXJhbWV0ZXIgaXMgZGVwcmVjYXRlZCwgcGxlYXNlIHVzZSBhbiBBcHBJZGVudGlmaWVyICh7IGFwcElkOiBzdHJpbmc7IGluc3RhbmNlSWQ/OiBzdHJpbmcgfSkuJyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlcnNjb3JlLWRhbmdsZVxuXHQgICAgICAgIHJldHVybiBzdXBlci5fb3BlbihhcHAsIGNvbnRleHQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBGaW5kIGFsbCB0aGUgYXZhaWxhYmxlIGluc3RhbmNlcyBmb3IgYSBwYXJ0aWN1bGFyIGFwcGxpY2F0aW9uLlxuXHQgICAgICogQHBhcmFtIGFwcFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzdjIuZmluZEluc3RhbmNlc1xuXHQgICAgICovXG5cdCAgICBhc3luYyBmaW5kSW5zdGFuY2VzKGFwcCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLWZpbmQtaW5zdGFuY2VzJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgcmV0dXJuIGF3YWl0IEludGVyb3BDbGllbnRfMS5JbnRlcm9wQ2xpZW50LmZlcnJ5RmRjM0NhbGwodGhpcy5jbGllbnQsICdmZGMzRmluZEluc3RhbmNlcycsIGFwcCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zdCBlcnJvclRvVGhyb3cgPSBlcnJvci5tZXNzYWdlID09PSB1dGlsc18xLkJST0tFUl9FUlJPUlMuZmRjM0ZpbmRJbnN0YW5jZXMgPyAnUmVzb2x2ZXJVbmF2YWlsYWJsZScgOiBlcnJvci5tZXNzYWdlO1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JUb1Rocm93KTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHJpZXZlcyB0aGUgQXBwTWV0YWRhdGEgZm9yIGFuIEFwcElkZW50aWZpZXIsIHdoaWNoIHByb3ZpZGVzIGFkZGl0aW9uYWwgbWV0YWRhdGEgKHN1Y2ggYXMgaWNvbnMsIGEgdGl0bGUgYW5kIGRlc2NyaXB0aW9uKSBmcm9tIHRoZSBBcHAgRGlyZWN0b3J5IHJlY29yZCBmb3IgdGhlIGFwcGxpY2F0aW9uLCB0aGF0IG1heSBiZSB1c2VkIGZvciBkaXNwbGF5IHB1cnBvc2VzLlxuXHQgICAgICogQHBhcmFtIGFwcFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzdjIuZ2V0QXBwTWV0YWRhdGFcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0QXBwTWV0YWRhdGEoYXBwKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtZ2V0LWFwcC1tZXRhZGF0YScpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIHJldHVybiBhd2FpdCBJbnRlcm9wQ2xpZW50XzEuSW50ZXJvcENsaWVudC5mZXJyeUZkYzNDYWxsKHRoaXMuY2xpZW50LCAnZmRjM0dldEFwcE1ldGFkYXRhJywgYXBwKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGVycm9yVG9UaHJvdyA9IGVycm9yLm1lc3NhZ2UgPT09IHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5mZGMzR2V0QXBwTWV0YWRhdGEgPyAnUmVzb2x2ZXJVbmF2YWlsYWJsZScgOiBlcnJvci5tZXNzYWdlO1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JUb1Rocm93KTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEFkZCBhIGNvbnRleHQgaGFuZGxlciBmb3IgaW5jb21pbmcgY29udGV4dC4gSWYgYW4gZW50aXR5IGlzIHBhcnQgb2YgYSBjb250ZXh0IGdyb3VwLCBhbmQgdGhlbiBzZXRzIGl0cyBjb250ZXh0IGhhbmRsZXIsIGl0IHdpbGwgcmVjZWl2ZSBhbGwgb2YgaXRzIGRlY2xhcmVkIGNvbnRleHRzLiBJZiB5b3Ugd2lzaCB0byBsaXN0ZW4gZm9yIGFsbCBpbmNvbWluZyBjb250ZXh0cywgcGFzcyBgbnVsbGAgZm9yIHRoZSBjb250ZXh0VHlwZSBhcmd1bWVudC5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0VHlwZVxuXHQgICAgICogQHBhcmFtIGhhbmRsZXJcblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5hZGRDb250ZXh0TGlzdGVuZXJcblx0ICAgICAqL1xuXHQgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBUT0RPIFtDT1JFLTE1MjRdXG5cdCAgICBhc3luYyBhZGRDb250ZXh0TGlzdGVuZXIoY29udGV4dFR5cGUsIGhhbmRsZXIpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1hZGQtY29udGV4dC1saXN0ZW5lcicpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIC8vIFRoZSBGREMzIENvbnRleHRIYW5kbGVyIG9ubHkgZXhwZWN0cyB0aGUgY29udGV4dCBhbmQgb3B0aW9uYWwgQ29udGV4dE1ldGFkYXRhLCBzbyB3ZSB3cmFwIHRoZSBoYW5kbGVyXG5cdCAgICAgICAgLy8gaGVyZSBzbyBpdCBvbmx5IGdldHMgcGFzc2VkIHRoZXNlIHBhcmFtZXRlcnNcblx0ICAgICAgICBjb25zdCBnZXRXcmFwcGVkSGFuZGxlciA9IChoYW5kbGVyVG9XcmFwKSA9PiB7XG5cdCAgICAgICAgICAgIHJldHVybiAoY29udGV4dCkgPT4ge1xuXHQgICAgICAgICAgICAgICAgY29uc3QgeyBjb250ZXh0TWV0YWRhdGEsIC4uLnJlc3QgfSA9IGNvbnRleHQ7XG5cdCAgICAgICAgICAgICAgICBjb25zdCBhcmdzID0gY29udGV4dE1ldGFkYXRhID8gW3sgLi4ucmVzdCB9LCBjb250ZXh0TWV0YWRhdGFdIDogW2NvbnRleHQsIG51bGxdO1xuXHQgICAgICAgICAgICAgICAgaGFuZGxlclRvV3JhcCguLi5hcmdzKTtcblx0ICAgICAgICAgICAgfTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIGxldCBhY3R1YWxIYW5kbGVyID0gaGFuZGxlcjtcblx0ICAgICAgICBsZXQgd3JhcHBlZEhhbmRsZXIgPSBnZXRXcmFwcGVkSGFuZGxlcihhY3R1YWxIYW5kbGVyKTtcblx0ICAgICAgICBpZiAodHlwZW9mIGNvbnRleHRUeXBlID09PSAnZnVuY3Rpb24nKSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUud2FybignYWRkQ29udGV4dExpc3RlbmVyKGhhbmRsZXIpIGhhcyBiZWVuIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgYWRkQ29udGV4dExpc3RlbmVyKG51bGwsIGhhbmRsZXIpJyk7XG5cdCAgICAgICAgICAgIGFjdHVhbEhhbmRsZXIgPSBjb250ZXh0VHlwZTtcblx0ICAgICAgICAgICAgd3JhcHBlZEhhbmRsZXIgPSBnZXRXcmFwcGVkSGFuZGxlcihhY3R1YWxIYW5kbGVyKTtcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50LmFkZENvbnRleHRIYW5kbGVyKHdyYXBwZWRIYW5kbGVyKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50LmFkZENvbnRleHRIYW5kbGVyKHdyYXBwZWRIYW5kbGVyLCBjb250ZXh0VHlwZSA9PT0gbnVsbCA/IHVuZGVmaW5lZCA6IGNvbnRleHRUeXBlKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogRmluZCBvdXQgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBhIHBhcnRpY3VsYXIgaW50ZW50IGJ5IHBhc3NpbmcgaXRzIG5hbWUsIGFuZCBvcHRpb25hbGx5IGl0cyBjb250ZXh0IGFuZCByZXN1bHRUeXBlLlxuXHQgICAgICogQHBhcmFtIGludGVudCBOYW1lIG9mIHRoZSBJbnRlbnRcblx0ICAgICAqIEBwYXJhbSBjb250ZXh0IENvbnRleHRcblx0ICAgICAqIEBwYXJhbSByZXN1bHRUeXBlIFRoZSB0eXBlIG9mIHJlc3VsdCByZXR1cm5lZCBmb3IgYW55IGludGVudCBzcGVjaWZpZWQgZHVyaW5nIHJlc29sdXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuZmluZEludGVudFxuXHQgICAgICovXG5cdCAgICBhc3luYyBmaW5kSW50ZW50KGludGVudCwgY29udGV4dCwgcmVzdWx0VHlwZSkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdmZGMzLWZpbmQtaW50ZW50JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuY2xpZW50LmdldEluZm9Gb3JJbnRlbnQoeyBuYW1lOiBpbnRlbnQsIGNvbnRleHQsIG1ldGFkYXRhOiB7IHJlc3VsdFR5cGUgfSB9KTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGVycm9yVG9UaHJvdyA9IGVycm9yLm1lc3NhZ2UgPT09IHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5nZXRJbmZvRm9ySW50ZW50ID8gJ1Jlc29sdmVyVW5hdmFpbGFibGUnIDogZXJyb3IubWVzc2FnZTtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yVG9UaHJvdyk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBGaW5kIGFsbCB0aGUgYXZhaWxhYmxlIGludGVudHMgZm9yIGEgcGFydGljdWxhciBjb250ZXh0LlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRcblx0ICAgICAqIEBwYXJhbSByZXN1bHRUeXBlIFRoZSB0eXBlIG9mIHJlc3VsdCByZXR1cm5lZCBmb3IgYW55IGludGVudCBzcGVjaWZpZWQgZHVyaW5nIHJlc29sdXRpb24uXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzN2Mi5maW5kSW50ZW50c0J5Q29udGV4dFxuXHQgICAgICovXG5cdCAgICBhc3luYyBmaW5kSW50ZW50c0J5Q29udGV4dChjb250ZXh0LCByZXN1bHRUeXBlKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtZmluZC1pbnRlbnRzLWJ5LWNvbnRleHQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBwYXlsb2FkID0gcmVzdWx0VHlwZSA/IHsgY29udGV4dCwgbWV0YWRhdGE6IHsgcmVzdWx0VHlwZSB9IH0gOiBjb250ZXh0O1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIHJldHVybiBhd2FpdCBJbnRlcm9wQ2xpZW50XzEuSW50ZXJvcENsaWVudC5mZXJyeUZkYzNDYWxsKHRoaXMuY2xpZW50LCAnZmRjM3YyRmluZEludGVudHNCeUNvbnRleHQnLCBwYXlsb2FkKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGVycm9yVG9UaHJvdyA9IGVycm9yLm1lc3NhZ2UgPT09IHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5nZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dCA/ICdSZXNvbHZlclVuYXZhaWxhYmxlJyA6IGVycm9yLm1lc3NhZ2U7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvclRvVGhyb3cpO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmFpc2VzIGEgc3BlY2lmaWMgaW50ZW50IGZvciByZXNvbHV0aW9uIGFnYWluc3QgYXBwcyByZWdpc3RlcmVkIHdpdGggdGhlIGRlc2t0b3AgYWdlbnQuXG5cdCAgICAgKiBAcGFyYW0gaW50ZW50IE5hbWUgb2YgdGhlIEludGVudFxuXHQgICAgICogQHBhcmFtIGNvbnRleHQgQ29udGV4dCBhc3NvY2lhdGVkIHdpdGggdGhlIEludGVudFxuXHQgICAgICogQHBhcmFtIGFwcFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzdjIucmFpc2VJbnRlbnRcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgcmFpc2VJbnRlbnQoaW50ZW50LCBjb250ZXh0LCBhcHApIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignZmRjMy1yYWlzZS1pbnRlbnQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyB3ZSBkbyBub3Qgd2FudCB0byBleHBvc2UgdGhpcyBlcnJvciwganVzdCBjb250aW51ZSBpZiB0aGlzIGFuYWx5dGljcy1vbmx5IGNhbGwgZmFpbHNcblx0ICAgICAgICB9KTtcblx0ICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICBpZiAodHlwZW9mIGFwcCA9PT0gJ3N0cmluZycpIHtcblx0ICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignUGFzc2luZyBhIHN0cmluZyBhcyB0aGUgYXBwIHBhcmFtZXRlciBpcyBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIGFuIEFwcElkZW50aWZpZXIgKHsgYXBwSWQ6IHN0cmluZzsgaW5zdGFuY2VJZD86IHN0cmluZyB9KS4nKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICByZXR1cm4gKDAsIHV0aWxzXzIuZ2V0SW50ZW50UmVzb2x1dGlvbikodGhpcy5jbGllbnQsIGNvbnRleHQsIGFwcCwgaW50ZW50KTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgY2F0Y2ggKGVycm9yKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IGVycm9yVG9UaHJvdyA9IGVycm9yLm1lc3NhZ2UgPT09IHV0aWxzXzEuQlJPS0VSX0VSUk9SUy5maXJlSW50ZW50ID8gJ1Jlc29sdmVyVW5hdmFpbGFibGUnIDogZXJyb3IubWVzc2FnZTtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGVycm9yVG9UaHJvdyk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBGaW5kcyBhbmQgcmFpc2VzIGFuIGludGVudCBhZ2FpbnN0IGFwcHMgcmVnaXN0ZXJlZCB3aXRoIHRoZSBkZXNrdG9wIGFnZW50IGJhc2VkIHB1cmVseSBvbiB0aGUgdHlwZSBvZiB0aGUgY29udGV4dCBkYXRhLlxuXHQgICAgICogQHBhcmFtIGNvbnRleHQgQ29udGV4dCBhc3NvY2lhdGVkIHdpdGggdGhlIEludGVudFxuXHQgICAgICogQHBhcmFtIGFwcFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzdjIucmFpc2VJbnRlbnRGb3JDb250ZXh0XG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIHJhaXNlSW50ZW50Rm9yQ29udGV4dChjb250ZXh0LCBhcHApIHtcblx0ICAgICAgICAvLyBUT0RPOiBXZSBoYXZlIHRvIGRvIHRoZSBzYW1lIHRoaW5nIHdlIGRvIGZvciByYWlzZUludGVudCBoZXJlIGFzIHdlbGwuXG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtcmFpc2UtaW50ZW50LWZvci1jb250ZXh0JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gd2UgZG8gbm90IHdhbnQgdG8gZXhwb3NlIHRoaXMgZXJyb3IsIGp1c3QgY29udGludWUgaWYgdGhpcyBhbmFseXRpY3Mtb25seSBjYWxsIGZhaWxzXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgaWYgKHR5cGVvZiBhcHAgPT09ICdzdHJpbmcnKSB7XG5cdCAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1Bhc3NpbmcgYSBzdHJpbmcgYXMgdGhlIGFwcCBwYXJhbWV0ZXIgaXMgZGVwcmVjYXRlZCwgcGxlYXNlIHVzZSBhbiBBcHBJZGVudGlmaWVyICh7IGFwcElkOiBzdHJpbmc7IGluc3RhbmNlSWQ/OiBzdHJpbmcgfSkuJyk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgcmV0dXJuICgwLCB1dGlsc18yLmdldEludGVudFJlc29sdXRpb24pKHRoaXMuY2xpZW50LCBjb250ZXh0LCBhcHApO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgY29uc3QgZXJyb3JUb1Rocm93ID0gZXJyb3IubWVzc2FnZSA9PT0gdXRpbHNfMS5CUk9LRVJfRVJST1JTLmZpcmVJbnRlbnQgPyAnUmVzb2x2ZXJVbmF2YWlsYWJsZScgOiBlcnJvci5tZXNzYWdlO1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JUb1Rocm93KTtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEFkZHMgYSBsaXN0ZW5lciBmb3IgaW5jb21pbmcgaW50ZW50cy5cblx0ICAgICAqIEBwYXJhbSBpbnRlbnQgIE5hbWUgb2YgdGhlIEludGVudFxuXHQgICAgICogQHBhcmFtIGhhbmRsZXIgQSBjYWxsYmFjayB0aGF0IGhhbmRsZXMgYSBjb250ZXh0IGV2ZW50IGFuZCBtYXkgcmV0dXJuIGEgcHJvbWlzZSBvZiBhIENvbnRleHQgb3IgQ2hhbm5lbCBvYmplY3QgdG8gYmUgcmV0dXJuZWQgdG8gdGhlIGFwcGxpY2F0aW9uIHRoYXQgcmFpc2VkIHRoZSBpbnRlbnQuXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuYWRkSW50ZW50TGlzdGVuZXJcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgYWRkSW50ZW50TGlzdGVuZXIoaW50ZW50LCBoYW5kbGVyKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ZkYzMtYWRkLWludGVudC1saXN0ZW5lcicpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGV4cG9zZSB0aGlzIGVycm9yLCBqdXN0IGNvbnRpbnVlIGlmIHRoaXMgYW5hbHl0aWNzLW9ubHkgY2FsbCBmYWlsc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGlmICh0eXBlb2YgaW50ZW50ICE9PSAnc3RyaW5nJykge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYW4gSW50ZW50IG5hbWUnKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgLy8gVGhlIEZEQzMgSW50ZW50ZXIgaGFuZGxlciBvbmx5IGV4cGVjdHMgdGhlIGNvbnRleHQgYW5kIGNvbnRleHRNZXRhZGF0YSB0byBiZSBwYXNzZWQgdG8gdGhlIGhhbmRsZXIsXG5cdCAgICAgICAgLy8gc28gd2Ugd3JhcCBpdCBoZXJlIGFuZCBvbmx5IHBhc3MgdGhvc2UgcGFyYW1hdGVycy5cblx0ICAgICAgICBjb25zdCBjb250ZXh0SGFuZGxlciA9IGFzeW5jIChyYWlzZWRJbnRlbnQpID0+IHtcblx0ICAgICAgICAgICAgbGV0IGludGVudFJlc3VsdDtcblx0ICAgICAgICAgICAgbGV0IGludGVudFJlc3VsdFRvU2VuZDtcblx0ICAgICAgICAgICAgY29uc3QgeyBjb250ZXh0LCBtZXRhZGF0YTogaW50ZW50TWV0YWRhdGEgfSA9IHJhaXNlZEludGVudDtcblx0ICAgICAgICAgICAgY29uc3QgeyBjb250ZXh0TWV0YWRhdGEsIG1ldGFkYXRhLCAuLi5yZXN0IH0gPSBjb250ZXh0O1xuXHQgICAgICAgICAgICBjb25zdCBpbnRlbnRSZXNvbHV0aW9uUmVzdWx0SWQgPSBpbnRlbnRNZXRhZGF0YT8uaW50ZW50UmVzb2x1dGlvblJlc3VsdElkIHx8IG1ldGFkYXRhPy5pbnRlbnRSZXNvbHV0aW9uUmVzdWx0SWQ7XG5cdCAgICAgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgICAgICBjb25zdCBuZXdDb250ZXh0ID0gbWV0YWRhdGEgPyB7IG1ldGFkYXRhLCAuLi5yZXN0IH0gOiB7IC4uLnJlc3QgfTtcblx0ICAgICAgICAgICAgICAgIGludGVudFJlc3VsdCA9IGF3YWl0IGhhbmRsZXIobmV3Q29udGV4dCwgY29udGV4dE1ldGFkYXRhKTtcblx0ICAgICAgICAgICAgICAgIGludGVudFJlc3VsdFRvU2VuZCA9IGludGVudFJlc3VsdDtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgICAgIGludGVudFJlc3VsdCA9IGVycm9yO1xuXHQgICAgICAgICAgICAgICAgaW50ZW50UmVzdWx0VG9TZW5kID0geyBlcnJvcjogdHJ1ZSB9O1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGlmIChpbnRlbnRSZXNvbHV0aW9uUmVzdWx0SWQpIHtcblx0ICAgICAgICAgICAgICAgIHRoaXMuZmluLkludGVyQXBwbGljYXRpb25CdXMucHVibGlzaChpbnRlbnRSZXNvbHV0aW9uUmVzdWx0SWQsIGludGVudFJlc3VsdFRvU2VuZCkuY2F0Y2goKCkgPT4gbnVsbCk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgaWYgKGludGVudFJlc3VsdCBpbnN0YW5jZW9mIEVycm9yKSB7XG5cdCAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoaW50ZW50UmVzdWx0Lm1lc3NhZ2UpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIHJldHVybiBpbnRlbnRSZXN1bHQ7XG5cdCAgICAgICAgfTtcblx0ICAgICAgICByZXR1cm4gdGhpcy5jbGllbnQucmVnaXN0ZXJJbnRlbnRIYW5kbGVyKGNvbnRleHRIYW5kbGVyLCBpbnRlbnQsIHsgZmRjM1ZlcnNpb246ICcyLjAnIH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXR1cm5zIGEgQ2hhbm5lbCBvYmplY3QgZm9yIHRoZSBzcGVjaWZpZWQgY2hhbm5lbCwgY3JlYXRpbmcgaXQgYXMgYW4gQXBwIENoYW5uZWwgaWYgaXQgZG9lcyBub3QgZXhpc3QuXG5cdCAgICAgKiBAcGFyYW0gY2hhbm5lbElkXG5cdCAgICAgKlxuXHQgICAgICogQHR1dG9yaWFsIGZkYzMuZ2V0T3JDcmVhdGVDaGFubmVsXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldE9yQ3JlYXRlQ2hhbm5lbChjaGFubmVsSWQpIHtcblx0ICAgICAgICByZXR1cm4gc3VwZXIuZ2V0T3JDcmVhdGVDaGFubmVsKGNoYW5uZWxJZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJldHVybnMgYSBDaGFubmVsIHdpdGggYW4gYXV0by1nZW5lcmF0ZWQgaWRlbnRpdHkgdGhhdCBpcyBpbnRlbmRlZCBmb3IgcHJpdmF0ZSBjb21tdW5pY2F0aW9uIGJldHdlZW4gYXBwbGljYXRpb25zLiBQcmltYXJpbHkgdXNlZCB0byBjcmVhdGUgY2hhbm5lbHMgdGhhdCB3aWxsIGJlIHJldHVybmVkIHRvIG90aGVyIGFwcGxpY2F0aW9ucyB2aWEgYW4gSW50ZW50UmVzb2x1dGlvbiBmb3IgYSByYWlzZWQgaW50ZW50LlxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzdjIuY3JlYXRlUHJpdmF0ZUNoYW5uZWxcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgY3JlYXRlUHJpdmF0ZUNoYW5uZWwoKSB7XG5cdCAgICAgICAgY29uc3QgY2hhbm5lbElkID0gKDAsIHV0aWxzXzEuZ2VuZXJhdGVJZCkoKTtcblx0ICAgICAgICBhd2FpdCBJbnRlcm9wQ2xpZW50XzEuSW50ZXJvcENsaWVudC5mZXJyeUZkYzNDYWxsKHRoaXMuY2xpZW50LCAnY3JlYXRlUHJpdmF0ZUNoYW5uZWxQcm92aWRlcicsIHsgY2hhbm5lbElkIH0pO1xuXHQgICAgICAgIGNvbnN0IGNoYW5uZWxDbGllbnQgPSBhd2FpdCB0aGlzLmZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY29ubmVjdChjaGFubmVsSWQpO1xuXHQgICAgICAgIGNvbnN0IG5ld1ByaXZhdGVDaGFubmVsQ2xpZW50ID0gbmV3IFByaXZhdGVDaGFubmVsQ2xpZW50XzEuUHJpdmF0ZUNoYW5uZWxDbGllbnQoY2hhbm5lbENsaWVudCwgY2hhbm5lbElkKTtcblx0ICAgICAgICByZXR1cm4gKDAsIHV0aWxzXzIuYnVpbGRQcml2YXRlQ2hhbm5lbE9iamVjdCkobmV3UHJpdmF0ZUNoYW5uZWxDbGllbnQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXRyaWV2ZXMgYSBsaXN0IG9mIHRoZSBVc2VyIENoYW5uZWxzIGF2YWlsYWJsZSBmb3IgdGhlIGFwcCB0byBqb2luLlxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzdjIuZ2V0VXNlckNoYW5uZWxzXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldFVzZXJDaGFubmVscygpIHtcblx0ICAgICAgICBjb25zdCBjaGFubmVscyA9IGF3YWl0IHRoaXMuY2xpZW50LmdldENvbnRleHRHcm91cHMoKTtcblx0ICAgICAgICAvLyBmZGMzIGltcGxlbWVudGF0aW9uIG9mIGdldFVzZXJDaGFubmVscyByZXR1cm5zIG9uIGFycmF5IG9mIGNoYW5uZWxzLCBoYXZlIHRvIGRlY29yYXRlIG92ZXJcblx0ICAgICAgICAvLyB0aGlzIHNvIHBlb3BsZSBrbm93IHRoYXQgdGhlc2UgQVBJcyBhcmUgbm90IHN1cHBvcnRlZFxuXHQgICAgICAgIHJldHVybiBjaGFubmVscy5tYXAoKGNoYW5uZWwpID0+IHtcblx0ICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBUT0RPIFtDT1JFLTE1MjRdXG5cdCAgICAgICAgICAgIHJldHVybiB7IC4uLmNoYW5uZWwsIHR5cGU6ICd1c2VyJywgLi4uKDAsIHV0aWxzXzIuZ2V0VW5zdXBwb3J0ZWRDaGFubmVsQXBpcykoJ1VzZXInKSB9O1xuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXRyaWV2ZXMgYSBsaXN0IG9mIHRoZSBVc2VyIENoYW5uZWxzIGF2YWlsYWJsZSBmb3IgdGhlIGFwcCB0byBqb2luLlxuXHQgICAgICpcblx0ICAgICAqIEBkZXByZWNhdGVkIFBsZWFzZSB1c2Uge0BsaW5rIGZkYzMuZ2V0VXNlckNoYW5uZWxzIGZkYzMuZ2V0VXNlckNoYW5uZWxzfSBpbnN0ZWFkXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5nZXRTeXN0ZW1DaGFubmVsc1xuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRTeXN0ZW1DaGFubmVscygpIHtcblx0ICAgICAgICBjb25zb2xlLndhcm4oJ1RoaXMgQVBJIGhhcyBiZWVuIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgZmRjMy5nZXRVc2VyQ2hhbm5lbHMgaW5zdGVhZC4nKTtcblx0ICAgICAgICByZXR1cm4gc3VwZXIuZ2V0U3lzdGVtQ2hhbm5lbHMoKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogSm9pbiBhbiBhcHAgdG8gYSBzcGVjaWZpZWQgVXNlciBjaGFubmVsLlxuXHQgICAgICogQHBhcmFtIGNoYW5uZWxJZCBDaGFubmVsIG5hbWVcblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjM3YyLmpvaW5Vc2VyQ2hhbm5lbFxuXHQgICAgICovXG5cdCAgICBhc3luYyBqb2luVXNlckNoYW5uZWwoY2hhbm5lbElkKSB7XG5cdCAgICAgICAgcmV0dXJuIHN1cGVyLmpvaW5DaGFubmVsKGNoYW5uZWxJZCk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEpvaW4gYW4gYXBwIHRvIGEgc3BlY2lmaWVkIFVzZXIgY2hhbm5lbC5cblx0ICAgICAqIEBwYXJhbSBjaGFubmVsSWQgQ2hhbm5lbCBuYW1lXG5cdCAgICAgKiBAZGVwcmVjYXRlZCBQbGVhc2UgdXNlIHtAbGluayBmZGMzLmpvaW5Vc2VyQ2hhbm5lbCBmZGMzLmpvaW5Vc2VyQ2hhbm5lbH0gaW5zdGVhZFxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzLmpvaW5DaGFubmVsXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGpvaW5DaGFubmVsKGNoYW5uZWxJZCkge1xuXHQgICAgICAgIGNvbnNvbGUud2FybignVGhpcyBBUEkgaGFzIGJlZW4gZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBmZGMzLmpvaW5Vc2VyQ2hhbm5lbCBpbnN0ZWFkLicpO1xuXHQgICAgICAgIHJldHVybiBzdXBlci5qb2luQ2hhbm5lbChjaGFubmVsSWQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBSZXR1cm5zIHRoZSBDaGFubmVsIG9iamVjdCBmb3IgdGhlIGN1cnJlbnQgVXNlciBjaGFubmVsIG1lbWJlcnNoaXBcblx0ICAgICAqXG5cdCAgICAgKiBAdHV0b3JpYWwgZmRjMy5nZXRDdXJyZW50Q2hhbm5lbFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRDdXJyZW50Q2hhbm5lbCgpIHtcblx0ICAgICAgICBjb25zdCBjdXJyZW50Q2hhbm5lbCA9IGF3YWl0IHN1cGVyLmdldEN1cnJlbnRDaGFubmVsKCk7XG5cdCAgICAgICAgaWYgKCFjdXJyZW50Q2hhbm5lbCkge1xuXHQgICAgICAgICAgICByZXR1cm4gbnVsbDtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIHtcblx0ICAgICAgICAgICAgLi4uY3VycmVudENoYW5uZWwsXG5cdCAgICAgICAgICAgIHR5cGU6ICd1c2VyJyxcblx0ICAgICAgICAgICAgYnJvYWRjYXN0OiB0aGlzLmJyb2FkY2FzdC5iaW5kKHRoaXMpXG5cdCAgICAgICAgfTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogUmV0cmlldmVzIGluZm9ybWF0aW9uIGFib3V0IHRoZSBGREMzIGltcGxlbWVudGF0aW9uLCBpbmNsdWRpbmcgdGhlIHN1cHBvcnRlZCB2ZXJzaW9uIG9mIHRoZSBGREMzIHNwZWNpZmljYXRpb24sIHRoZSBuYW1lIG9mIHRoZSBwcm92aWRlciBvZiB0aGUgaW1wbGVtZW50YXRpb24sIGl0cyBvd24gdmVyc2lvbiBudW1iZXIsIGRldGFpbHMgb2Ygd2hldGhlciBvcHRpb25hbCBBUEkgZmVhdHVyZXMgYXJlIGltcGxlbWVudGVkIGFuZCB0aGUgbWV0YWRhdGEgb2YgdGhlIGNhbGxpbmcgYXBwbGljYXRpb24gYWNjb3JkaW5nIHRvIHRoZSBkZXNrdG9wIGFnZW50LlxuXHQgICAgICogZmRjM0hhbmRsZUdldEluZm8gbXVzdCBiZSBvdmVycmlkZGVuIGluIHRoZSBJbnRlcm9wQnJva2VyIHNvIHRoYXQgdGhlIEltcGxlbWVudGF0aW9uTWV0YWRhdGEgd2lsbCBoYXZlIHRoZSBhcHBNZXRhZGF0YSBpbmZvLlxuXHQgICAgICpcblx0ICAgICAqIEB0dXRvcmlhbCBmZGMzdjIuZ2V0SW5mb1xuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRJbmZvKCkge1xuXHQgICAgICAgIHJldHVybiBJbnRlcm9wQ2xpZW50XzEuSW50ZXJvcENsaWVudC5mZXJyeUZkYzNDYWxsKHRoaXMuY2xpZW50LCAnZmRjM3YyR2V0SW5mbycsIHsgZmRjM1ZlcnNpb246ICcyLjAnIH0pO1xuXHQgICAgfVxuXHR9XG5cdGZkYzMyXzAuRmRjM01vZHVsZTIgPSBGZGMzTW9kdWxlMjtcblx0cmV0dXJuIGZkYzMyXzA7XG59XG5cbnZhciBoYXNSZXF1aXJlZEludGVyb3BDbGllbnQ7XG5cbmZ1bmN0aW9uIHJlcXVpcmVJbnRlcm9wQ2xpZW50ICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkSW50ZXJvcENsaWVudCkgcmV0dXJuIEludGVyb3BDbGllbnQ7XG5cdGhhc1JlcXVpcmVkSW50ZXJvcENsaWVudCA9IDE7XG5cdHZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG5cdCAgICBpZiAoa2luZCA9PT0gXCJtXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIG1ldGhvZCBpcyBub3Qgd3JpdGFibGVcIik7XG5cdCAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XG5cdCAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuXHQgICAgcmV0dXJuIChraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlciwgdmFsdWUpIDogZiA/IGYudmFsdWUgPSB2YWx1ZSA6IHN0YXRlLnNldChyZWNlaXZlciwgdmFsdWUpKSwgdmFsdWU7XG5cdH07XG5cdHZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0ID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRHZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIGtpbmQsIGYpIHtcblx0ICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcblx0ICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuXHQgICAgcmV0dXJuIGtpbmQgPT09IFwibVwiID8gZiA6IGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyKSA6IGYgPyBmLnZhbHVlIDogc3RhdGUuZ2V0KHJlY2VpdmVyKTtcblx0fTtcblx0dmFyIF9faW1wb3J0RGVmYXVsdCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2ltcG9ydERlZmF1bHQpIHx8IGZ1bmN0aW9uIChtb2QpIHtcblx0ICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgXCJkZWZhdWx0XCI6IG1vZCB9O1xuXHR9O1xuXHR2YXIgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgX0ludGVyb3BDbGllbnRfc2Vzc2lvbkNvbnRleHRHcm91cHM7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShJbnRlcm9wQ2xpZW50LCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0SW50ZXJvcENsaWVudC5JbnRlcm9wQ2xpZW50ID0gdm9pZCAwO1xuXHRjb25zdCBiYXNlXzEgPSBiYXNlO1xuXHRjb25zdCBTZXNzaW9uQ29udGV4dEdyb3VwQ2xpZW50XzEgPSBfX2ltcG9ydERlZmF1bHQoU2Vzc2lvbkNvbnRleHRHcm91cENsaWVudCQxKTtcblx0Y29uc3QgZmRjM18xXzJfMSA9IHJlcXVpcmVGZGMzMV8yKCk7XG5cdGNvbnN0IGZkYzNfMl8wXzEgPSByZXF1aXJlRmRjMzJfMCgpO1xuXHRjb25zdCB1dGlsc18xID0gdXRpbHMkMztcblx0LyoqXG5cdCAqIFRoZSBJbnRlcm9wIENsaWVudCBBUEkgaXMgYnJva2VuIHVwIGludG8gdHdvIGdyb3Vwczpcblx0ICpcblx0ICogKipDb250ZW50IEZhY2luZyBBUElzKiogLSBGb3IgQXBwbGljYXRpb24gRGV2ZWxvcGVycyBwdXR0aW5nIFZpZXdzIGludG8gYSBQbGF0Zm9ybSBXaW5kb3csIHdobyBjYXJlIGFib3V0IENvbnRleHQuIFRoZXNlIGFyZSBBUElzIHRoYXQgc2VuZCBvdXQgYW5kIHJlY2VpdmUgdGhlIENvbnRleHQgZGF0YSB0aGF0IGZsb3dzIGJldHdlZW4gYXBwbGljYXRpb25zLiBUaGluayBvZiB0aGlzIGFzIHRoZSBXYXRlciBpbiB0aGUgSW50ZXJvcCBQaXBlcy5cblx0ICpcblx0ICogKipDb250ZXh0IEdyb3VwaW5nIEFQSXMqKiAtIEZvciBQbGF0Zm9ybSBEZXZlbG9wZXJzLCB0byBhZGQgYW5kIHJlbW92ZSBWaWV3cyB0byBhbmQgZnJvbSBDb250ZXh0IEdyb3Vwcy4gVGhlc2UgQVBJcyBhcmUgdXRpbGl6ZWQgdW5kZXItdGhlLWhvb2QgaW4gUGxhdGZvcm1zLCBzbyB0aGV5IGRvbid0IG5lZWQgdG8gYmUgdXNlZCB0byBwYXJ0aWNpcGF0ZSBpbiBJbnRlcm9wLiBUaGVzZSBhcmUgdGhlIEFQSXMgdGhhdCBkZWNpZGUgd2hpY2ggZW50aXRpZXMgdGhlIGNvbnRleHQgZGF0YSBmbG93cyBiZXR3ZWVuLiBUaGluayBvZiB0aGVzZSBhcyB0aGUgdmFsdmVzIG9yIHBpcGVzIHRoYXQgY29udHJvbCB0aGUgZmxvdyBvZiBDb250ZXh0IERhdGEgZm9yIEludGVyb3AuXG5cdCAqXG5cdCAqIC0tLVxuXHQgKlxuXHQgKiBBbGwgQVBJcyBhcmUgYXZhaWxhYmxlIGF0IHRoZSBgZmluLm1lLmludGVyb3BgIG5hbWVzcGFjZS5cblx0ICpcblx0ICogLS0tXG5cdCAqXG5cdCAqICoqWW91IG9ubHkgbmVlZCAyIHRoaW5ncyB0byBwYXJ0aWNpcGF0ZSBpbiBJbnRlcm9wIENvbnRleHQgR3JvdXBpbmc6Kipcblx0ICogKiBBIENvbnRleHQgSGFuZGxlciBmb3IgaW5jb21pbmcgY29udGV4dDoge0BsaW5rIEludGVyb3BDbGllbnQjYWRkQ29udGV4dEhhbmRsZXIgYWRkQ29udGV4dEhhbmRsZXIoaGFuZGxlciwgY29udGV4dFR5cGU/KX1cblx0ICogKiBDYWxsIHNldENvbnRleHQgb24geW91ciBjb250ZXh0IGdyb3VwIHdoZW4geW91IHdhbnQgdG8gc2hhcmUgY29udGV4dCB3aXRoIG90aGVyIGdyb3VwIG1lbWJlcnM6IHtAbGluayBJbnRlcm9wQ2xpZW50I3NldENvbnRleHQgc2V0Q29udGV4dChjb250ZXh0KX1cblx0ICpcblx0ICogLS0tXG5cdCAqXG5cdCAqICMjIyMjIENvbnN0cnVjdG9yXG5cdCAqIFJldHVybmVkIGJ5IHtAbGluayBJbnRlcm9wLmNvbm5lY3RTeW5jIEludGVyb3AuY29ubmVjdFN5bmN9LlxuXHQgKlxuXHQgKiAtLS1cblx0ICpcblx0ICogIyMjIyMgSW50ZXJvcCBtZXRob2RzIGludGVuZGVkIGZvciBWaWV3c1xuXHQgKlxuXHQgKlxuXHQgKiAqKkNvbnRleHQgR3JvdXBzIEFQSSoqXG5cdCAqICAqIHtAbGluayBJbnRlcm9wQ2xpZW50I2FkZENvbnRleHRIYW5kbGVyIGFkZENvbnRleHRIYW5kbGVyKGhhbmRsZXIsIGNvbnRleHRUeXBlPyl9XG5cdCAqICAqIHtAbGluayBJbnRlcm9wQ2xpZW50I3NldENvbnRleHQgc2V0Q29udGV4dChjb250ZXh0KX1cblx0ICogICoge0BsaW5rIEludGVyb3BDbGllbnQjZ2V0Q3VycmVudENvbnRleHQgZ2V0Q3VycmVudENvbnRleHQoY29udGV4dFR5cGU/KX1cblx0ICogICoge0BsaW5rIEludGVyb3BDbGllbnQjam9pblNlc3Npb25Db250ZXh0R3JvdXAgam9pblNlc3Npb25Db250ZXh0R3JvdXAoc2Vzc2lvbkNvbnRleHRHcm91cElkKX1cblx0ICpcblx0ICpcblx0ICogKipJbnRlbnRzIEFQSSoqXG5cdCAqICAqIHtAbGluayBJbnRlcm9wQ2xpZW50I2ZpcmVJbnRlbnQgZmlyZUludGVudChpbnRlbnQpfVxuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNyZWdpc3RlckludGVudEhhbmRsZXIgcmVnaXN0ZXJJbnRlbnRIYW5kbGVyKGludGVudEhhbmRsZXIsIGludGVudE5hbWUpfVxuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNnZXRJbmZvRm9ySW50ZW50IGdldEluZm9Gb3JJbnRlbnQoaW5mb0ZvckludGVudE9wdGlvbnMpfVxuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNnZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dCBnZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dChjb250ZXh0KX1cblx0ICogICoge0BsaW5rIEludGVyb3BDbGllbnQjZmlyZUludGVudEZvckNvbnRleHQgZmlyZUludGVudEZvckNvbnRleHQoY29udGV4dEZvckludGVudCl9XG5cdCAqXG5cdCAqICMjIyMjIEludGVyb3AgbWV0aG9kcyBpbnRlbmRlZCBmb3IgV2luZG93c1xuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNnZXRDb250ZXh0R3JvdXBzIGdldENvbnRleHRHcm91cHMoKX1cblx0ICogICoge0BsaW5rIEludGVyb3BDbGllbnQjam9pbkNvbnRleHRHcm91cCBqb2luQ29udGV4dEdyb3VwKGNvbnRleHRHcm91cElkLCB0YXJnZXQ/KX1cblx0ICogICoge0BsaW5rIEludGVyb3BDbGllbnQjcmVtb3ZlRnJvbUNvbnRleHRHcm91cCByZW1vdmVGcm9tQ29udGV4dEdyb3VwKHRhcmdldD8pfVxuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNnZXRJbmZvRm9yQ29udGV4dEdyb3VwIGdldEluZm9Gb3JDb250ZXh0R3JvdXAoY29udGV4dEdyb3VwSWQpfVxuXHQgKiAgKiB7QGxpbmsgSW50ZXJvcENsaWVudCNnZXRBbGxDbGllbnRzSW5Db250ZXh0R3JvdXAgZ2V0QWxsQ2xpZW50c0luQ29udGV4dEdyb3VwKGNvbnRleHRHcm91cElkKX1cblx0ICpcblx0ICovXG5cdGxldCBJbnRlcm9wQ2xpZW50JDEgPSBjbGFzcyBJbnRlcm9wQ2xpZW50IGV4dGVuZHMgYmFzZV8xLkJhc2Uge1xuXHQgICAgLyoqXG5cdCAgICAgKiBAaW50ZXJuYWxcblx0ICAgICAqL1xuXHQgICAgY29uc3RydWN0b3Iod2lyZSwgY2xpZW50UHJvbWlzZSkge1xuXHQgICAgICAgIHN1cGVyKHdpcmUpO1xuXHQgICAgICAgIF9JbnRlcm9wQ2xpZW50X2NsaWVudFByb21pc2Uuc2V0KHRoaXMsIHZvaWQgMCk7XG5cdCAgICAgICAgX0ludGVyb3BDbGllbnRfc2Vzc2lvbkNvbnRleHRHcm91cHMuc2V0KHRoaXMsIHZvaWQgMCk7XG5cdCAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfSW50ZXJvcENsaWVudF9zZXNzaW9uQ29udGV4dEdyb3VwcywgbmV3IE1hcCgpLCBcImZcIik7XG5cdCAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBjbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICB9XG5cdCAgICAvKlxuXHQgICAgQ2xpZW50IEFQSXNcblx0ICAgICovXG5cdCAgICAvKipcblx0ICAgICAqIFNldHMgYSBjb250ZXh0IGZvciB0aGUgY29udGV4dCBncm91cCBvZiB0aGUgY3VycmVudCBlbnRpdHkuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgVGhlIGVudGl0eSBtdXN0IGJlIHBhcnQgb2YgYSBjb250ZXh0IGdyb3VwIGluIG9yZGVyIHNldCBhIGNvbnRleHQuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGNvbnRleHQgLSBOZXcgY29udGV4dCB0byBzZXQuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBzZXRJbnN0cnVtZW50Q29udGV4dCA9IGFzeW5jICh0aWNrZXIpID0+IHtcblx0ICAgICAqICAgICBmaW4ubWUuaW50ZXJvcC5zZXRDb250ZXh0KHt0eXBlOiAnaW5zdHJ1bWVudCcsIGlkOiB7dGlja2VyfX0pXG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogLy8gVGhlIHVzZXIgY2xpY2tzIGFuIGluc3RydW1lbnQgb2YgaW50ZXJlc3QuIFdlIHdhbnQgdG8gc2V0IHRoYXQgSW5zdHJ1bWVudCBjb250ZXh0IHNvIHRoYXQgdGhlIHJlc3Qgb2Ygb3VyIHdvcmtmbG93IHVwZGF0ZXMgd2l0aCBpbmZvcm1hdGlvbiBmb3IgdGhhdCBpbnN0cnVtZW50XG5cdCAgICAgKiBpbnN0cnVtZW50RWxlbWVudC5vbignY2xpY2snLCAoZXZ0KSA9PiB7XG5cdCAgICAgKiAgICAgc2V0SW5zdHJ1bWVudENvbnRleHQoZXZ0LnRpY2tlcilcblx0ICAgICAqIH0pXG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgc2V0Q29udGV4dChjb250ZXh0KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtY2xpZW50LXNldC1jb250ZXh0JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnc2V0Q29udGV4dCcsIHsgY29udGV4dCB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogQWRkIGEgY29udGV4dCBoYW5kbGVyIGZvciBpbmNvbWluZyBjb250ZXh0LiBJZiBhbiBlbnRpdHkgaXMgcGFydCBvZiBhIGNvbnRleHQgZ3JvdXAsIGFuZCB0aGVuIHNldHMgaXRzIGNvbnRleHQgaGFuZGxlcixcblx0ICAgICAqIGl0IHdpbGwgcmVjZWl2ZSBhbGwgb2YgaXRzIGRlY2xhcmVkIGNvbnRleHRzLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBoYW5kbGVyIC0gSGFuZGxlciBmb3IgaW5jb21pbmcgY29udGV4dC5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0VHlwZSAtIFRoZSB0eXBlIG9mIGNvbnRleHQgeW91IHdpc2ggdG8gaGFuZGxlLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZnVuY3Rpb24gaGFuZGxlSW5jb21pbmdDb250ZXh0KGNvbnRleHRJbmZvKSB7XG5cdCAgICAgKiAgICAgY29uc3QgeyB0eXBlLCBpZCB9ID0gY29udGV4dEluZm87XG5cdCAgICAgKiAgICAgc3dpdGNoICh0eXBlKSB7XG5cdCAgICAgKiAgICAgICAgIGNhc2UgJ2luc3RydW1lbnQnOlxuXHQgICAgICogICAgICAgICAgICAgaGFuZGxlSW5zdHJ1bWVudENvbnRleHQoY29udGV4dEluZm8pO1xuXHQgICAgICogICAgICAgICAgICAgYnJlYWs7XG5cdCAgICAgKiAgICAgICAgIGNhc2UgJ2NvdW50cnknOlxuXHQgICAgICogICAgICAgICAgICAgaGFuZGxlQ291bnRyeUNvbnRleHQoY29udGV4dEluZm8pO1xuXHQgICAgICogICAgICAgICAgICAgYnJlYWs7XG5cdCAgICAgKlxuXHQgICAgICogICAgICAgICBkZWZhdWx0OlxuXHQgICAgICogICAgICAgICAgICAgYnJlYWs7XG5cdCAgICAgKiAgICAgfVxuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqXG5cdCAgICAgKiBmdW5jdGlvbiBoYW5kbGVJbnN0cnVtZW50Q29udGV4dChjb250ZXh0SW5mbykge1xuXHQgICAgICogICAgIGNvbnN0IHsgdHlwZSwgaWQgfSA9IGNvbnRleHRJbmZvO1xuXHQgICAgICogICAgIGNvbnNvbGUubG9nKCdjb250ZXh0SW5mbyBmb3IgaW5zdHJ1bWVudCcsIGNvbnRleHRJbmZvKVxuXHQgICAgICogfVxuXHQgICAgICpcblx0ICAgICAqIGZ1bmN0aW9uIGhhbmRsZUNvdW50cnlDb250ZXh0KGNvbnRleHRJbmZvKSB7XG5cdCAgICAgKiAgICAgY29uc3QgeyB0eXBlLCBpZCB9ID0gY29udGV4dEluZm87XG5cdCAgICAgKiAgICAgY29uc29sZS5sb2coJ2NvbnRleHRJbmZvIGZvciBjb3VudHJ5JywgY29udGV4dEluZm8pXG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZmluLm1lLmludGVyb3AuYWRkQ29udGV4dEhhbmRsZXIoaGFuZGxlSW5jb21pbmdDb250ZXh0KTtcblx0ICAgICAqIGBgYFxuXHQgICAgICpcblx0ICAgICAqXG5cdCAgICAgKiBQYXNzaW5nIGluIGEgY29udGV4dCB0eXBlIGFzIHRoZSBzZWNvbmQgcGFyYW1ldGVyIHdpbGwgY2F1c2UgdGhlIGhhbmRsZXIgdG8gb25seSBiZSBpbnZva2VkIHdpdGggdGhhdCBjb250ZXh0IHR5cGUuXG5cdCAgICAgKlxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZ1bmN0aW9uIGhhbmRsZUluc3RydW1lbnRDb250ZXh0KGNvbnRleHRJbmZvKSB7XG5cdCAgICAgKiAgICAgY29uc3QgeyB0eXBlLCBpZCB9ID0gY29udGV4dEluZm87XG5cdCAgICAgKiAgICAgY29uc29sZS5sb2coJ2NvbnRleHRJbmZvIGZvciBpbnN0cnVtZW50JywgY29udGV4dEluZm8pXG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZnVuY3Rpb24gaGFuZGxlQ291bnRyeUNvbnRleHQoY29udGV4dEluZm8pIHtcblx0ICAgICAqICAgICBjb25zdCB7IHR5cGUsIGlkIH0gPSBjb250ZXh0SW5mbztcblx0ICAgICAqICAgICBjb25zb2xlLmxvZygnY29udGV4dEluZm8gZm9yIGNvdW50cnknLCBjb250ZXh0SW5mbylcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKlxuXHQgICAgICogZmluLm1lLmludGVyb3AuYWRkQ29udGV4dEhhbmRsZXIoaGFuZGxlSW5zdHJ1bWVudENvbnRleHQsICdpbnN0cnVtZW50Jylcblx0ICAgICAqIGZpbi5tZS5pbnRlcm9wLmFkZENvbnRleHRIYW5kbGVyKGhhbmRsZUNvdW50cnlDb250ZXh0LCAnY291bnRyeScpXG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgYWRkQ29udGV4dEhhbmRsZXIoaGFuZGxlciwgY29udGV4dFR5cGUpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtYWRkLWNvbnRleHQtaGFuZGxlcicpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGlmICh0eXBlb2YgaGFuZGxlciAhPT0gJ2Z1bmN0aW9uJykge1xuXHQgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOb24tZnVuY3Rpb24gYXJndW1lbnQgcGFzc2VkIHRvIHRoZSBmaXJzdCBwYXJhbWV0ZXIgJ2hhbmRsZXInLiBCZSBhd2FyZSB0aGF0IHRoZSBhcmd1bWVudCBvcmRlciBkb2VzIG5vdCBtYXRjaCB0aGUgRkRDMyBzdGFuZGFyZC5cIik7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIGxldCBoYW5kbGVySWQ7XG5cdCAgICAgICAgaWYgKGNvbnRleHRUeXBlKSB7XG5cdCAgICAgICAgICAgIGhhbmRsZXJJZCA9IGBpbnZva2VDb250ZXh0SGFuZGxlci0ke2NvbnRleHRUeXBlfS0keygwLCB1dGlsc18xLmdlbmVyYXRlSWQpKCl9YDtcblx0ICAgICAgICB9XG5cdCAgICAgICAgZWxzZSB7XG5cdCAgICAgICAgICAgIGhhbmRsZXJJZCA9ICdpbnZva2VDb250ZXh0SGFuZGxlcic7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNvbnN0IHdyYXBwZWRIYW5kbGVyID0gKDAsIHV0aWxzXzEud3JhcENvbnRleHRIYW5kbGVyKShoYW5kbGVyLCBoYW5kbGVySWQpO1xuXHQgICAgICAgIGNsaWVudC5yZWdpc3RlcihoYW5kbGVySWQsIHdyYXBwZWRIYW5kbGVyKTtcblx0ICAgICAgICBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ2NvbnRleHRIYW5kbGVyUmVnaXN0ZXJlZCcsIHsgaGFuZGxlcklkLCBjb250ZXh0VHlwZSB9KTtcblx0ICAgICAgICByZXR1cm4ge1xuXHQgICAgICAgICAgICB1bnN1YnNjcmliZTogYXN5bmMgKCkgPT4ge1xuXHQgICAgICAgICAgICAgICAgY2xpZW50LnJlbW92ZShoYW5kbGVySWQpO1xuXHQgICAgICAgICAgICAgICAgYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdyZW1vdmVDb250ZXh0SGFuZGxlcicsIHsgaGFuZGxlcklkIH0pO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfTtcblx0ICAgIH1cblx0ICAgIC8qXG5cdCAgICBQbGF0Zm9ybSBXaW5kb3cgQVBJc1xuXHQgICAgKi9cblx0ICAgIC8qKlxuXHQgICAgICogUmV0dXJucyB0aGUgSW50ZXJvcC1Ccm9rZXItZGVmaW5lZCBjb250ZXh0IGdyb3VwcyBhdmFpbGFibGUgZm9yIGFuIGVudGl0eSB0byBqb2luLlxuXHQgICAgICogVXNlZCBieSBQbGF0Zm9ybSBXaW5kb3dzLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogZmluLm1lLmludGVyb3AuZ2V0Q29udGV4dEdyb3VwcygpXG5cdCAgICAgKiAgICAgICAgIC50aGVuKGNvbnRleHRHcm91cHMgPT4ge1xuXHQgICAgICogICAgICAgICAgICAgY29udGV4dEdyb3Vwcy5mb3JFYWNoKGNvbnRleHRHcm91cCA9PiB7XG5cdCAgICAgKiAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coY29udGV4dEdyb3VwLmRpc3BsYXlNZXRhZGF0YS5uYW1lKVxuXHQgICAgICogICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGNvbnRleHRHcm91cC5kaXNwbGF5TWV0YWRhdGEuY29sb3IpXG5cdCAgICAgKiAgICAgICAgICAgICB9KVxuXHQgICAgICogICAgICAgICB9KVxuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldENvbnRleHRHcm91cHMoKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtY2xpZW50LWdldC1jb250ZXh0LWdyb3VwcycpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2dldENvbnRleHRHcm91cHMnKTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogSm9pbiBhbGwgSW50ZXJvcCBDbGllbnRzIGF0IHRoZSBnaXZlbiBpZGVudGl0eSB0byBjb250ZXh0IGdyb3VwIGBjb250ZXh0R3JvdXBJZGAuXG5cdCAgICAgKiBJZiBubyB0YXJnZXQgaXMgc3BlY2lmaWVkLCBpdCBhZGRzIHRoZSBzZW5kZXIgdG8gdGhlIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgQmVjYXVzZSBtdWx0aXBsZSBDaGFubmVsIGNvbm5lY3Rpb25zL0ludGVyb3AgQ2xpZW50cyBjYW4gcG90ZW50aWFsbHkgZXhpc3QgYXQgYSBgdXVpZGAvYG5hbWVgIGNvbWJvLCB3ZSBjdXJyZW50bHkgam9pbiBhbGwgQ2hhbm5lbCBjb25uZWN0aW9ucy9JbnRlcm9wIENsaWVudHMgYXQgdGhlIGdpdmVuIGlkZW50aXR5IHRvIHRoZSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICogSWYgYW4gYGVuZHBvaW50SWRgIGlzIHByb3ZpZGVkICh3aGljaCBpcyB1bmxpa2VseSwgdW5sZXNzIHRoZSBjYWxsIGlzIGNvbWluZyBmcm9tIGFuIGV4dGVybmFsIGFkYXB0ZXIpLCB0aGVuIHdlIG9ubHkgam9pbiB0aGF0IHNpbmdsZSBjb25uZWN0aW9uIHRvIHRoZSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICogRm9yIGFsbCBpbnRlbnRzIGFuZCBwdXJwb3NlcywgdGhlcmUgd2lsbCBvbmx5IGJlIDEgY29ubmVjdGlvbiBwcmVzZW50IGluIFBsYXRmb3JtIGFuZCBCcm93c2VyIGltcGxtZW50YXRpb25zLCBzbyB0aGlzIHBvaW50IGlzIG1vcmUtb3ItbGVzcyBtb290LlxuXHQgICAgICogVXNlZCBieSBQbGF0Zm9ybSBXaW5kb3dzLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSBjb250ZXh0R3JvdXBJZCAtIElkIG9mIHRoZSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICogQHBhcmFtIHRhcmdldCAtIElkZW50aXR5IG9mIHRoZSBlbnRpdHkgeW91IHdpc2ggdG8gam9pbiB0byBhIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqIGBgYGpzXG5cdCAgICAgKiBqb2luVmlld1RvQ29udGV4dEdyb3VwID0gYXN5bmMgKGNvbnRleHRHcm91cElkLCB2aWV3KSA9PiB7XG5cdCAgICAgKiAgICAgYXdhaXQgZmluLm1lLmludGVyb3Auam9pbkNvbnRleHRHcm91cChjb250ZXh0R3JvdXBJZCwgdmlldyk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0TGFzdEZvY3VzZWRWaWV3KClcblx0ICAgICAqICAgICAudGhlbihsYXN0Rm9jdXNlZFZpZXdJZGVudGl0eSA9PiB7XG5cdCAgICAgKiAgICAgICAgIGpvaW5WaWV3VG9Db250ZXh0R3JvdXAoJ3JlZCcsIGxhc3RGb2N1c2VkVmlld0lkZW50aXR5KVxuXHQgICAgICogICAgIH0pXG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgam9pbkNvbnRleHRHcm91cChjb250ZXh0R3JvdXBJZCwgdGFyZ2V0KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtY2xpZW50LWpvaW4tY29udGV4dC1ncm91cCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIGlmICghY29udGV4dEdyb3VwSWQpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjb250ZXh0R3JvdXBJZCBzcGVjaWZpZWQgZm9yIGpvaW5Db250ZXh0R3JvdXAuJyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2pvaW5Db250ZXh0R3JvdXAnLCB7IGNvbnRleHRHcm91cElkLCB0YXJnZXQgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlbW92ZXMgdGhlIHNwZWNpZmllZCB0YXJnZXQgZnJvbSBhIGNvbnRleHQgZ3JvdXAuXG5cdCAgICAgKiBJZiBubyB0YXJnZXQgaXMgc3BlY2lmaWVkLCBpdCByZW1vdmVzIHRoZSBzZW5kZXIgZnJvbSB0aGVpciBjb250ZXh0IGdyb3VwLlxuXHQgICAgICogVXNlZCBieSBQbGF0Zm9ybSBXaW5kb3dzLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSB0YXJnZXQgLSBJZGVudGl0eSBvZiB0aGUgZW50aXR5IHlvdSB3aXNoIHRvIGpvaW4gdG8gYSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogcmVtb3ZlVmlld0Zyb21Db250ZXh0R3JvdXAgPSBhc3luYyAodmlldykgPT4ge1xuXHQgICAgICogICAgIGF3YWl0IGZpbi5tZS5pbnRlcm9wLnJlbW92ZUZyb21Db250ZXh0R3JvdXAodmlldyk7XG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogZ2V0TGFzdEZvY3VzZWRWaWV3KClcblx0ICAgICAqICAgICAudGhlbihsYXN0Rm9jdXNlZFZpZXdJZGVudGl0eSA9PiB7XG5cdCAgICAgKiAgICAgICAgIHJlbW92ZVZpZXdGcm9tQ29udGV4dEdyb3VwKGxhc3RGb2N1c2VkVmlld0lkZW50aXR5KVxuXHQgICAgICogICAgIH0pXG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgcmVtb3ZlRnJvbUNvbnRleHRHcm91cCh0YXJnZXQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtcmVtb3ZlLWZyb20tY29udGV4dC1ncm91cCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ3JlbW92ZUZyb21Db250ZXh0R3JvdXAnLCB7IHRhcmdldCB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0cyBhbGwgY2xpZW50cyBmb3IgYSBjb250ZXh0IGdyb3VwLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzICoqVGhpcyBpcyBwcmltYXJpbHkgdXNlZCBmb3IgcGxhdGZvcm0gd2luZG93cy4gVmlld3Mgd2l0aGluIGEgcGxhdGZvcm0gc2hvdWxkIG5vdCBoYXZlIHRvIHVzZSB0aGlzIEFQSS4qKlxuXHQgICAgICpcblx0ICAgICAqIFJldHVybnMgdGhlIEludGVyb3AtQnJva2VyLWRlZmluZWQgY29udGV4dCBncm91cHMgYXZhaWxhYmxlIGZvciBhbiBlbnRpdHkgdG8gam9pbi5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0R3JvdXBJZCAtIFRoZSBpZCBvZiBjb250ZXh0IGdyb3VwIHlvdSB3aXNoIHRvIGdldCBjbGllbnRzIGZvci5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5tZS5pbnRlcm9wLmdldEFsbENsaWVudHNJbkNvbnRleHRHcm91cCgncmVkJylcblx0ICAgICAqICAgICAudGhlbihjbGllbnRzSW5Db250ZXh0R3JvdXAgPT4ge1xuXHQgICAgICogICAgICAgICBjb25zb2xlLmxvZyhjbGllbnRzSW5Db250ZXh0R3JvdXApXG5cdCAgICAgKiAgICAgfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRBbGxDbGllbnRzSW5Db250ZXh0R3JvdXAoY29udGV4dEdyb3VwSWQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtZ2V0LWFsbC1jbGllbnRzLWluLWNvbnRleHQtZ3JvdXAnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQ2xpZW50X2NsaWVudFByb21pc2UsIFwiZlwiKTtcblx0ICAgICAgICBpZiAoIWNvbnRleHRHcm91cElkKSB7XG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gY29udGV4dEdyb3VwSWQgc3BlY2lmaWVkIGZvciBnZXRBbGxDbGllbnRzSW5Db250ZXh0R3JvdXAuJyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2dldEFsbENsaWVudHNJbkNvbnRleHRHcm91cCcsIHsgY29udGV4dEdyb3VwSWQgfSk7XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEdldHMgZGlzcGxheSBpbmZvIGZvciBhIGNvbnRleHQgZ3JvdXBcblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBVc2VkIGJ5IFBsYXRmb3JtIFdpbmRvd3MuXG5cdCAgICAgKiBAcGFyYW0gY29udGV4dEdyb3VwSWQgLSBUaGUgaWQgb2YgY29udGV4dCBncm91cCB5b3Ugd2lzaCB0byBnZXQgZGlzcGxheSBpbmZvIGZvci5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGZpbi5tZS5pbnRlcm9wLmdldEluZm9Gb3JDb250ZXh0R3JvdXAoJ3JlZCcpXG5cdCAgICAgKiAgICAgLnRoZW4oY29udGV4dEdyb3VwSW5mbyA9PiB7XG5cdCAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKGNvbnRleHRHcm91cEluZm8uZGlzcGxheU1ldGFkYXRhLm5hbWUpXG5cdCAgICAgKiAgICAgICAgIGNvbnNvbGUubG9nKGNvbnRleHRHcm91cEluZm8uZGlzcGxheU1ldGFkYXRhLmNvbG9yKVxuXHQgICAgICogICAgIH0pXG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0SW5mb0ZvckNvbnRleHRHcm91cChjb250ZXh0R3JvdXBJZCkge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWNsaWVudC1nZXQtaW5mby1mb3ItY29udGV4dC1ncm91cCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIGlmICghY29udGV4dEdyb3VwSWQpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjb250ZXh0R3JvdXBJZCBzcGVjaWZpZWQgZm9yIGdldEluZm9Gb3JDb250ZXh0R3JvdXAuJyk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2dldEluZm9Gb3JDb250ZXh0R3JvdXAnLCB7IGNvbnRleHRHcm91cElkIH0pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTZW5kcyBhbiBpbnRlbnQgdG8gdGhlIEludGVyb3AgQnJva2VyIHRvIHJlc29sdmUuXG5cdCAgICAgKiBAcGFyYW0gaW50ZW50IC0gVGhlIGNvbWJpbmF0aW9uIG9mIGFuIGFjdGlvbiBhbmQgYSBjb250ZXh0IHRoYXQgaXMgcGFzc2VkIHRvIGFuIGFwcGxpY2F0aW9uIGZvciByZXNvbHV0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogLy8gVmlldyB3YW50cyB0byBmaXJlIGFuIEludGVudCBhZnRlciBhIHVzZXIgY2xpY2tzIG9uIGEgdGlja2VyXG5cdCAgICAgKiB0aWNrZXJFbGVtZW50Lm9uKCdjbGljaycsIChlbGVtZW50KSA9PiB7XG5cdCAgICAgKiAgICAgY29uc3QgdGlja2VyID0gZWxlbWVudC5pbm5lclRleHQ7XG5cdCAgICAgKiAgICAgY29uc3QgaW50ZW50ID0ge1xuXHQgICAgICogICAgICAgICBuYW1lOiAnVmlld0NoYXJ0Jyxcblx0ICAgICAqICAgICAgICAgY29udGV4dDoge3R5cGU6ICdmZGMzLmluc3RydW1lbnQnLCBpZDogeyB0aWNrZXIgfX1cblx0ICAgICAqICAgICB9XG5cdCAgICAgKlxuXHQgICAgICogICAgIGZpbi5tZS5pbnRlcm9wLmZpcmVJbnRlbnQoaW50ZW50KTtcblx0ICAgICAqIH0pXG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZmlyZUludGVudChpbnRlbnQpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtZmlyZS1pbnRlbnQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIHRoaXMgaXMgb25seSBmb3IgYXBpIGFuYWx5dGljcyBwdXJwb3Nlc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2ZpcmVJbnRlbnQnLCBpbnRlbnQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBBZGRzIGFuIGludGVudCBoYW5kbGVyIGZvciBpbmNvbWluZyBpbnRlbnRzLiBUaGUgbGFzdCBpbnRlbnQgc2VudCBvZiB0aGUgbmFtZSBzdWJzY3JpYmVkIHRvIHdpbGwgYmUgcmVjZWl2ZWQuXG5cdCAgICAgKiBAcGFyYW0gaGFuZGxlciAtIFJlZ2lzdGVyZWQgZnVuY3Rpb24gbWVhbnQgdG8gaGFuZGxlIGEgc3BlY2lmaWMgaW50ZW50IHR5cGUuXG5cdCAgICAgKiBAcGFyYW0gaW50ZW50TmFtZSAtIFRoZSBuYW1lIG9mIGFuIGludGVudC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IGludGVudEhhbmRsZXIgPSAoaW50ZW50KSA9PiB7XG5cdCAgICAgKiAgICAgY29uc3QgeyBjb250ZXh0IH0gPSBpbnRlbnQ7XG5cdCAgICAgKiAgICAgbXlWaWV3Q2hhcnRIYW5kbGVyKGNvbnRleHQpO1xuXHQgICAgICogfTtcblx0ICAgICAqXG5cdCAgICAgKiBjb25zdCBzdWJzY3JpcHRpb24gPSBhd2FpdCBmaW4ubWUuaW50ZXJvcC5yZWdpc3RlckludGVudEhhbmRsZXIoaW50ZW50SGFuZGxlciwgJ1ZpZXdDaGFydCcpO1xuXHQgICAgICpcblx0ICAgICAqIGZ1bmN0aW9uIG15QXBwQ2xvc2VTZXF1ZW5jZSgpIHtcblx0ICAgICAqICAgICAvLyB0byB1bnN1YnNjcmliZSB0aGUgaGFuZGxlciwgc2ltcGx5IGNhbGw6XG5cdCAgICAgKiAgICAgc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG5cdCAgICAgKiB9XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgcmVnaXN0ZXJJbnRlbnRIYW5kbGVyKGhhbmRsZXIsIGludGVudE5hbWUsIG9wdGlvbnMpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtcmVnaXN0ZXItaW50ZW50LWhhbmRsZXInKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIHRoaXMgaXMgb25seSBmb3IgYXBpIGFuYWx5dGljcyBwdXJwb3Nlc1xuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIGNvbnN0IGhhbmRsZXJJZCA9IGBpbnRlbnQtaGFuZGxlci0ke2ludGVudE5hbWV9YDtcblx0ICAgICAgICBjb25zdCB3cmFwcGVkSGFuZGxlciA9ICgwLCB1dGlsc18xLndyYXBJbnRlbnRIYW5kbGVyKShoYW5kbGVyLCBoYW5kbGVySWQpO1xuXHQgICAgICAgIHRyeSB7XG5cdCAgICAgICAgICAgIGF3YWl0IGNsaWVudC5yZWdpc3RlcihoYW5kbGVySWQsIHdyYXBwZWRIYW5kbGVyKTtcblx0ICAgICAgICAgICAgYXdhaXQgY2xpZW50LmRpc3BhdGNoKCdpbnRlbnRIYW5kbGVyUmVnaXN0ZXJlZCcsIHsgaGFuZGxlcklkLCAuLi5vcHRpb25zIH0pO1xuXHQgICAgICAgIH1cblx0ICAgICAgICBjYXRjaCAoZXJyb3IpIHtcblx0ICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gcmVnaXN0ZXIgaW50ZW50IGhhbmRsZXInKTtcblx0ICAgICAgICB9XG5cdCAgICAgICAgcmV0dXJuIHtcblx0ICAgICAgICAgICAgdW5zdWJzY3JpYmU6IGFzeW5jICgpID0+IHtcblx0ICAgICAgICAgICAgICAgIGNsaWVudC5yZW1vdmUoaGFuZGxlcklkKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH07XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIEdldHMgdGhlIGxhc3QgY29udGV4dCBvZiB0aGUgQ29udGV4dCBHcm91cCBjdXJyZW50bHkgc3Vic2NyaWJlZCB0by4gSXQgdGFrZXMgYW4gb3B0aW9uYWwgQ29udGV4dCBUeXBlIGFuZCByZXR1cm5zIHRoZVxuXHQgICAgICogbGFzdCBjb250ZXh0IG9mIHRoYXQgdHlwZS5cblx0ICAgICAqIEBwYXJhbSBjb250ZXh0VHlwZVxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogYXdhaXQgZmluLm1lLmludGVyb3Auam9pbkNvbnRleHRHcm91cCgneWVsbG93Jyk7XG5cdCAgICAgKiBhd2FpdCBmaW4ubWUuaW50ZXJvcC5zZXRDb250ZXh0KHsgdHlwZTogJ2luc3RydW1lbnQnLCBpZDogeyB0aWNrZXI6ICdGT08nIH19KTtcblx0ICAgICAqIGNvbnN0IGN1cnJlbnRDb250ZXh0ID0gYXdhaXQgZmluLm1lLmludGVyb3AuZ2V0Q3VycmVudENvbnRleHQoKTtcblx0ICAgICAqXG5cdCAgICAgKiAvLyB3aXRoIGEgc3BlY2lmaWMgY29udGV4dFxuXHQgICAgICogYXdhaXQgZmluLm1lLmludGVyb3Auam9pbkNvbnRleHRHcm91cCgneWVsbG93Jyk7XG5cdCAgICAgKiBhd2FpdCBmaW4ubWUuaW50ZXJvcC5zZXRDb250ZXh0KHsgdHlwZTogJ2NvdW50cnknLCBpZDogeyBJU09BTFBIQTM6ICdVUycgfX0pO1xuXHQgICAgICogYXdhaXQgZmluLm1lLmludGVyb3Auc2V0Q29udGV4dCh7IHR5cGU6ICdpbnN0cnVtZW50JywgaWQ6IHsgdGlja2VyOiAnRk9PJyB9fSk7XG5cdCAgICAgKiBjb25zdCBjdXJyZW50Q29udGV4dCA9IGF3YWl0IGZpbi5tZS5pbnRlcm9wLmdldEN1cnJlbnRDb250ZXh0KCdjb3VudHJ5Jyk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgZ2V0Q3VycmVudENvbnRleHQoY29udGV4dFR5cGUpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jbGllbnQtZ2V0LWN1cnJlbnQtY29udGV4dCcpLmNhdGNoKChlKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goJ2dldEN1cnJlbnRDb250ZXh0JywgeyBjb250ZXh0VHlwZSB9KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogR2V0IGluZm9ybWF0aW9uIGZvciBhIHBhcnRpY3VsYXIgSW50ZW50IGZyb20gdGhlIEludGVyb3AgQnJva2VyLlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFRvIHJlc29sdmUgdGhpcyBpbmZvLCB0aGUgZnVuY3Rpb24gaGFuZGxlSW5mb0ZvckludGVudCBpcyBtZWFudCB0byBiZSBvdmVycmlkZGVuIGluIHRoZSBJbnRlcm9wIEJyb2tlci5cblx0ICAgICAqIFRoZSBmb3JtYXQgZm9yIHRoZSByZXNwb25zZSB3aWxsIGJlIGRldGVybWluZWQgYnkgdGhlIEFwcCBQcm92aWRlciBvdmVycmlkaW5nIHRoZSBmdW5jdGlvbi5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gb3B0aW9uc1xuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3QgaW50ZW50SW5mbyA9IGF3YWl0IGZpbi5tZS5pbnRlcm9wLmdldEluZm9Gb3JJbnRlbnQoJ1ZpZXdDaGFydCcpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIGdldEluZm9Gb3JJbnRlbnQob3B0aW9ucykge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWNsaWVudC1nZXQtaW5mby1mb3ItaW50ZW50JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnZ2V0SW5mb0ZvckludGVudCcsIG9wdGlvbnMpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBHZXQgaW5mb3JtYXRpb24gZnJvbSB0aGUgSW50ZXJvcCBCcm9rZXIgb24gYWxsIEludGVudHMgdGhhdCBhcmUgbWVhbnQgdG8gaGFuZGxlIGEgcGFydGljdWxhciBjb250ZXh0LlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFRvIHJlc29sdmUgdGhpcyBpbmZvLCB0aGUgZnVuY3Rpb24gaGFuZGxlSW5mb0ZvckludGVudHNCeUNvbnRleHQgaXMgbWVhbnQgdG8gYmUgb3ZlcnJpZGRlbiBpbiB0aGUgSW50ZXJvcCBCcm9rZXIuXG5cdCAgICAgKiBUaGUgZm9ybWF0IGZvciB0aGUgcmVzcG9uc2Ugd2lsbCBiZSBkZXRlcm1pbmVkIGJ5IHRoZSBBcHAgUHJvdmlkZXIgb3ZlcnJpZGluZyB0aGUgZnVuY3Rpb24uXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIHRpY2tlckVsZW1lbnQub24oJ2NsaWNrJywgKGVsZW1lbnQpID0+IHtcblx0ICAgICAqICAgICBjb25zdCB0aWNrZXIgPSBlbGVtZW50LmlubmVyVGV4dDtcblx0ICAgICAqXG5cdCAgICAgKiAgICAgY29uc3QgY29udGV4dCA9IHtcblx0ICAgICAqICAgICAgICAgdHlwZTogJ2ZkYzMuaW5zdHJ1bWVudCcsXG5cdCAgICAgKiAgICAgICAgIGlkOiB7XG5cdCAgICAgKiAgICAgICAgICAgICB0aWNrZXJcblx0ICAgICAqICAgICAgICAgfVxuXHQgICAgICogICAgIH1cblx0ICAgICAqXG5cdCAgICAgKiAgICAgY29uc3QgaW50ZW50c0luZm8gPSBhd2FpdCBmaW4ubWUuaW50ZXJvcC5nZXRJbmZvRm9ySW50ZW50QnlDb250ZXh0KGNvbnRleHQpO1xuXHQgICAgICogfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBnZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dChjb250ZXh0KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtY2xpZW50LWdldC1pbmZvLWZvci1pbnRlbnRzLWJ5LWNvbnRleHQnKS5jYXRjaCgoZSkgPT4ge1xuXHQgICAgICAgICAgICAvLyBkb24ndCBleHBvc2UsIGFuYWx5dGljcy1vbmx5IGNhbGxcblx0ICAgICAgICB9KTtcblx0ICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQ2xpZW50X2NsaWVudFByb21pc2UsIFwiZlwiKTtcblx0ICAgICAgICByZXR1cm4gY2xpZW50LmRpc3BhdGNoKCdnZXRJbmZvRm9ySW50ZW50c0J5Q29udGV4dCcsIGNvbnRleHQpO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBTZW5kcyBhIENvbnRleHQgdGhhdCB3aWxsIGJlIHJlc29sdmVkIHRvIGFuIEludGVudCBieSB0aGUgSW50ZXJvcCBCcm9rZXIuXG5cdCAgICAgKiBUaGlzIGNvbnRleHQgYWNjZXB0cyBhIG1ldGFkYXRhIHByb3BlcnR5LlxuXHQgICAgICpcblx0ICAgICAqIEByZW1hcmtzIFRvIHJlc29sdmUgdGhpcyBpbmZvLCB0aGUgZnVuY3Rpb24gaGFuZGxlRmlyZWRJbnRlbnRCeUNvbnRleHQgaXMgbWVhbnQgdG8gYmUgb3ZlcnJpZGRlbiBpbiB0aGUgSW50ZXJvcCBCcm9rZXIuXG5cdCAgICAgKiBUaGUgZm9ybWF0IGZvciB0aGUgcmVzcG9uc2Ugd2lsbCBiZSBkZXRlcm1pbmVkIGJ5IHRoZSBBcHAgUHJvdmlkZXIgb3ZlcnJpZGluZyB0aGUgZnVuY3Rpb24uXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIGNvbnRleHRcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIHRpY2tlckVsZW1lbnQub24oJ2NsaWNrJywgKGVsZW1lbnQpID0+IHtcblx0ICAgICAqICAgICBjb25zdCB0aWNrZXIgPSBlbGVtZW50LmlubmVyVGV4dDtcblx0ICAgICAqXG5cdCAgICAgKiAgICAgY29uc3QgY29udGV4dCA9IHtcblx0ICAgICAqICAgICAgICAgdHlwZTogJ2ZkYzMuaW5zdHJ1bWVudCcsXG5cdCAgICAgKiAgICAgICAgIGlkOiB7XG5cdCAgICAgKiAgICAgICAgICAgICB0aWNrZXJcblx0ICAgICAqICAgICAgICAgfVxuXHQgICAgICogICAgIH1cblx0ICAgICAqXG5cdCAgICAgKiAgICAgY29uc3QgaW50ZW50UmVzb2x1dGlvbiA9IGF3YWl0IGZpbi5tZS5pbnRlcm9wLmZpcmVJbnRlbnRGb3JDb250ZXh0KGNvbnRleHQpO1xuXHQgICAgICogfSlcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBmaXJlSW50ZW50Rm9yQ29udGV4dChjb250ZXh0KSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtY2xpZW50LWZpcmUtaW50ZW50LWZvci1jb250ZXh0JykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5kaXNwYXRjaCgnZmlyZUludGVudEZvckNvbnRleHQnLCBjb250ZXh0KTtcblx0ICAgIH1cblx0ICAgIC8qKlxuXHQgICAgICogSm9pbiB0aGUgY3VycmVudCBlbnRpdHkgdG8gc2Vzc2lvbiBjb250ZXh0IGdyb3VwIGBzZXNzaW9uQ29udGV4dEdyb3VwSWRgIGFuZCByZXR1cm4gYSBzZXNzaW9uQ29udGV4dEdyb3VwIGluc3RhbmNlLlxuXHQgICAgICogSWYgdGhlIHNlc3Npb25Db250ZXh0R3JvdXAgZG9lc24ndCBleGlzdCwgb25lIHdpbGwgZ2V0IGNyZWF0ZWQuXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3MgU2Vzc2lvbiBDb250ZXh0IEdyb3VwcyBkbyBub3QgcGVyc2lzdCBiZXR3ZWVuIHJ1bnMgYW5kIGFyZW4ndCBwcmVzZW50IG9uIHNuYXBzaG90cy5cblx0ICAgICAqIEBwYXJhbSBzZXNzaW9uQ29udGV4dEdyb3VwSWQgLSBJZCBvZiB0aGUgY29udGV4dCBncm91cC5cblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogU2F5IHdlIHdhbnQgdG8gaGF2ZSBhIFNlc3Npb24gQ29udGV4dCBHcm91cCB0aGF0IGhvbGRzIFVJIHRoZW1lIGluZm9ybWF0aW9uIGZvciBhbGwgYXBwcyB0byBjb25zdW1lOlxuXHQgICAgICpcblx0ICAgICAqIE15IGNvbG9yLXBpY2tlciBWaWV3OlxuXHQgICAgICogYGBganNcblx0ICAgICAqICAgICBjb25zdCB0aGVtZVNlc3Npb25Db250ZXh0R3JvdXAgPSBhd2FpdCBmaW4ubWUuaW50ZXJvcC5qb2luU2Vzc2lvbkNvbnRleHRHcm91cCgndGhlbWUnKTtcblx0ICAgICAqXG5cdCAgICAgKiAgICAgY29uc3QgbXlDb2xvclBpY2tlckVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY29sb3ItcGFsZXR0ZS1waWNrZXInKTtcblx0ICAgICAqICAgICBteUNvbG9yUGlja2VyRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCBldmVudCA9PiB7XG5cdCAgICAgKiAgICAgICAgIHRoZW1lU2Vzc2lvbkNvbnRleHRHcm91cC5zZXRDb250ZXh0KHsgdHlwZTogJ2NvbG9yLXBhbGV0dGUnLCBzZWxlY3Rpb246IGV2ZW50LnZhbHVlIH0pO1xuXHQgICAgICogICAgIH0pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKlxuXHQgICAgICogSW4gb3RoZXIgdmlld3M6XG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogICAgIGNvbnN0IHRoZW1lU2Vzc2lvbkNvbnRleHRHcm91cCA9IGF3YWl0IGZpbi5tZS5pbnRlcm9wLmpvaW5TZXNzaW9uQ29udGV4dEdyb3VwKCd0aGVtZScpO1xuXHQgICAgICpcblx0ICAgICAqICAgICBjb25zdCBjaGFuZ2VDb2xvclBhbGV0dGUgPSAoeyBzZWxlY3Rpb24gfSkgPT4ge1xuXHQgICAgICogICAgICAgICAvLyBjaGFuZ2UgdGhlIGNvbG9yIHBhbGV0dGUgdG8gdGhlIHNlbGVjdGlvblxuXHQgICAgICogICAgIH07XG5cdCAgICAgKlxuXHQgICAgICogICAgIC8vIElmIHRoZSBjb250ZXh0IGlzIGFscmVhZHkgc2V0IGJ5IHRoZSB0aW1lIHRoZSBoYW5kbGVyIHdhcyBzZXQsIHRoZSBoYW5kbGVyIHdpbGwgZ2V0IGludm9rZWQgaW1tZWRpYXRlbHkgd2l0aCB0aGUgY3VycmVudCBjb250ZXh0LlxuXHQgICAgICogICAgIHRoZW1lU2Vzc2lvbkNvbnRleHRHcm91cC5hZGRDb250ZXh0SGFuZGxlcihjaGFuZ2VDb2xvclBhbGV0dGUsICdjb2xvci1wYWxldHRlJyk7XG5cdCAgICAgKiBgYGBcblx0ICAgICAqL1xuXHQgICAgYXN5bmMgam9pblNlc3Npb25Db250ZXh0R3JvdXAoc2Vzc2lvbkNvbnRleHRHcm91cElkKSB7XG5cdCAgICAgICAgdHJ5IHtcblx0ICAgICAgICAgICAgY29uc3QgY3VycmVudFNlc3Npb25Db250ZXh0R3JvdXAgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9JbnRlcm9wQ2xpZW50X3Nlc3Npb25Db250ZXh0R3JvdXBzLCBcImZcIikuZ2V0KHNlc3Npb25Db250ZXh0R3JvdXBJZCk7XG5cdCAgICAgICAgICAgIGlmIChjdXJyZW50U2Vzc2lvbkNvbnRleHRHcm91cCkge1xuXHQgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRTZXNzaW9uQ29udGV4dEdyb3VwLmdldFVzZXJJbnN0YW5jZSgpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgICAgICBjb25zdCB7IGhhc0NvbmZsaWN0IH0gPSBhd2FpdCBjbGllbnQuZGlzcGF0Y2goJ3Nlc3Npb25Db250ZXh0R3JvdXA6Y3JlYXRlSWZOZWVkZWQnLCB7XG5cdCAgICAgICAgICAgICAgICBzZXNzaW9uQ29udGV4dEdyb3VwSWRcblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgICAgIGlmIChoYXNDb25mbGljdCkge1xuXHQgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBBIChub24tc2Vzc2lvbikgY29udGV4dCBncm91cCB3aXRoIHRoZSBuYW1lIFwiJHtzZXNzaW9uQ29udGV4dEdyb3VwSWR9XCIgYWxyZWFkeSBleGlzdHMuIElmIHlvdSBhcmUgdHJ5aW5nIHRvIGpvaW4gYSBDb250ZXh0IEdyb3VwLCBjYWxsIGpvaW5Db250ZXh0R3JvdXAgaW5zdGVhZC5gKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBjb25zdCBuZXdTZXNzaW9uQ29udGV4dEdyb3VwID0gbmV3IFNlc3Npb25Db250ZXh0R3JvdXBDbGllbnRfMS5kZWZhdWx0KHRoaXMud2lyZSwgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIiksIHNlc3Npb25Db250ZXh0R3JvdXBJZCk7XG5cdCAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX0ludGVyb3BDbGllbnRfc2Vzc2lvbkNvbnRleHRHcm91cHMsIFwiZlwiKS5zZXQoc2Vzc2lvbkNvbnRleHRHcm91cElkLCBuZXdTZXNzaW9uQ29udGV4dEdyb3VwKTtcblx0ICAgICAgICAgICAgcmV0dXJuIG5ld1Nlc3Npb25Db250ZXh0R3JvdXAuZ2V0VXNlckluc3RhbmNlKCk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGNhdGNoIChlcnJvcikge1xuXHQgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciB0aHJvd24gdHJ5aW5nIHRvIGNyZWF0ZSBTZXNzaW9uIENvbnRleHQgR3JvdXAgd2l0aCBpZCBcIiR7c2Vzc2lvbkNvbnRleHRHcm91cElkfVwiOiAke2Vycm9yfWApO1xuXHQgICAgICAgICAgICB0aHJvdyBlcnJvcjtcblx0ICAgICAgICB9XG5cdCAgICB9XG5cdCAgICAvKipcblx0ICAgICAqIFJlZ2lzdGVyIGEgbGlzdGVuZXIgdGhhdCBpcyBjYWxsZWQgd2hlbiB0aGUgSW50ZXJvcCBDbGllbnQgaGFzIGJlZW4gZGlzY29ubmVjdGVkIGZyb20gdGhlIEludGVyb3AgQnJva2VyLlxuXHQgICAgICogT25seSBvbmUgbGlzdGVuZXIgcGVyIEludGVyb3AgQ2xpZW50IGNhbiBiZSBzZXQuXG5cdCAgICAgKiBAcGFyYW0gbGlzdGVuZXJcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICogYGBganNcblx0ICAgICAqIGNvbnN0IGxpc3RlbmVyID0gKGV2ZW50KSA9PiB7XG5cdCAgICAgKiAgICAgY29uc3QgeyB0eXBlLCB0b3BpYywgYnJva2VyTmFtZX0gPSBldmVudDtcblx0ICAgICAqICAgICBjb25zb2xlLmxvZyhgRGlzY29ubmVjdGVkIGZyb20gSW50ZXJvcCBCcm9rZXIgJHticm9rZXJOYW1lfSBgKTtcblx0ICAgICAqIH1cblx0ICAgICAqXG5cdCAgICAgKiBhd2FpdCBmaW4ubWUuaW50ZXJvcC5vbkRpc2Nvbm5lY3Rpb24obGlzdGVuZXIpO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGFzeW5jIG9uRGlzY29ubmVjdGlvbihsaXN0ZW5lcikge1xuXHQgICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdpbnRlcm9wLWNsaWVudC1hZGQtb25kaXNjb25uZWN0aW9uLWxpc3RlbmVyJykuY2F0Y2goKGUpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfSW50ZXJvcENsaWVudF9jbGllbnRQcm9taXNlLCBcImZcIik7XG5cdCAgICAgICAgcmV0dXJuIGNsaWVudC5vbkRpc2Nvbm5lY3Rpb24oKGV2ZW50KSA9PiB7XG5cdCAgICAgICAgICAgIGNvbnN0IHsgdXVpZCB9ID0gZXZlbnQ7XG5cdCAgICAgICAgICAgIGxpc3RlbmVyKHsgdHlwZTogJ2ludGVyb3AtYnJva2VyJywgdG9waWM6ICdkaXNjb25uZWN0ZWQnLCBicm9rZXJOYW1lOiB1dWlkIH0pO1xuXHQgICAgICAgIH0pO1xuXHQgICAgfVxuXHQgICAgZ2V0RkRDM1N5bmModmVyc2lvbikge1xuXHQgICAgICAgIHN3aXRjaCAodmVyc2lvbikge1xuXHQgICAgICAgICAgICBjYXNlICcxLjInOlxuXHQgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBmZGMzXzFfMl8xLkZkYzNNb2R1bGUoKCkgPT4gdGhpcywgdGhpcy53aXJlKTtcblx0ICAgICAgICAgICAgY2FzZSAnMi4wJzpcblx0ICAgICAgICAgICAgICAgIHJldHVybiBuZXcgZmRjM18yXzBfMS5GZGMzTW9kdWxlMigoKSA9PiB0aGlzLCB0aGlzLndpcmUpO1xuXHQgICAgICAgICAgICBkZWZhdWx0OlxuXHQgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIEZEQzMgdmVyc2lvbiBwcm92aWRlZDogJHt2ZXJzaW9ufS4gTXVzdCBiZSAnMS4yJyBvciAnMi4wJ2ApO1xuXHQgICAgICAgIH1cblx0ICAgIH1cblx0ICAgIGFzeW5jIGdldEZEQzModmVyc2lvbikge1xuXHQgICAgICAgIHJldHVybiB0aGlzLmdldEZEQzNTeW5jKHZlcnNpb24pO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBAaW50ZXJuYWxcblx0ICAgICAqXG5cdCAgICAgKiBVc2VkIHRvIGZlcnJ5IGZkYzMtb25seSBjYWxscyBmcm9tIHRoZSBmZGMzIHNoaW0gdG8gdGhlIEludGVyb3AgQnJva2VyXG5cdCAgICAgKi9cblx0ICAgIHN0YXRpYyBhc3luYyBmZXJyeUZkYzNDYWxsKGludGVyb3BDbGllbnQsIGFjdGlvbiwgcGF5bG9hZCkge1xuXHQgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQoaW50ZXJvcENsaWVudCwgX0ludGVyb3BDbGllbnRfY2xpZW50UHJvbWlzZSwgXCJmXCIpO1xuXHQgICAgICAgIHJldHVybiBjbGllbnQuZGlzcGF0Y2goYWN0aW9uLCBwYXlsb2FkIHx8IG51bGwpO1xuXHQgICAgfVxuXHR9O1xuXHRJbnRlcm9wQ2xpZW50LkludGVyb3BDbGllbnQgPSBJbnRlcm9wQ2xpZW50JDE7XG5cdF9JbnRlcm9wQ2xpZW50X2NsaWVudFByb21pc2UgPSBuZXcgV2Vha01hcCgpLCBfSW50ZXJvcENsaWVudF9zZXNzaW9uQ29udGV4dEdyb3VwcyA9IG5ldyBXZWFrTWFwKCk7XG5cdHJldHVybiBJbnRlcm9wQ2xpZW50O1xufVxuXG52YXIgb3ZlcnJpZGVDaGVjayA9IHt9O1xuXG52YXIgaGFzUmVxdWlyZWRPdmVycmlkZUNoZWNrO1xuXG5mdW5jdGlvbiByZXF1aXJlT3ZlcnJpZGVDaGVjayAoKSB7XG5cdGlmIChoYXNSZXF1aXJlZE92ZXJyaWRlQ2hlY2spIHJldHVybiBvdmVycmlkZUNoZWNrO1xuXHRoYXNSZXF1aXJlZE92ZXJyaWRlQ2hlY2sgPSAxO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkob3ZlcnJpZGVDaGVjaywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdG92ZXJyaWRlQ2hlY2sub3ZlcnJpZGVDaGVjayA9IG92ZXJyaWRlQ2hlY2suY2hlY2tGREMzMk92ZXJyaWRlcyA9IG92ZXJyaWRlQ2hlY2suZ2V0RGVmYXVsdFZpZXdGZGMzVmVyc2lvbkZyb21BcHBJbmZvID0gdm9pZCAwO1xuXHRjb25zdCBJbnRlcm9wQnJva2VyXzEgPSByZXF1aXJlSW50ZXJvcEJyb2tlcigpO1xuXHRmdW5jdGlvbiBnZXREZWZhdWx0Vmlld0ZkYzNWZXJzaW9uRnJvbUFwcEluZm8oeyBtYW5pZmVzdCwgaW5pdGlhbE9wdGlvbnMgfSkge1xuXHQgICAgY29uc3Qgc2V0VmVyc2lvbiA9IG1hbmlmZXN0Py5wbGF0Zm9ybT8uZGVmYXVsdFZpZXdPcHRpb25zPy5mZGMzSW50ZXJvcEFwaSA/PyBpbml0aWFsT3B0aW9ucy5kZWZhdWx0Vmlld09wdGlvbnM/LmZkYzNJbnRlcm9wQXBpO1xuXHQgICAgcmV0dXJuIFsnMS4yJywgJzIuMCddLmluY2x1ZGVzKHNldFZlcnNpb24gPz8gJycpID8gc2V0VmVyc2lvbiA6IHVuZGVmaW5lZDtcblx0fVxuXHRvdmVycmlkZUNoZWNrLmdldERlZmF1bHRWaWV3RmRjM1ZlcnNpb25Gcm9tQXBwSW5mbyA9IGdldERlZmF1bHRWaWV3RmRjM1ZlcnNpb25Gcm9tQXBwSW5mbztcblx0ZnVuY3Rpb24gY2hlY2tGREMzMk92ZXJyaWRlcyhvdmVycmlkZGVuQnJva2VyKSB7XG5cdCAgICAvLyBUaGVzZSBhcmUgdGhlIEFQSXMgdGhhdCBtdXN0IGJlIG92ZXJyaWRkZW4gZm9yIEZEQzMgMi4wIGNvbXBsaWFuY2Vcblx0ICAgIGNvbnN0IG11c3RPdmVycmlkZUFQSXMgPSBbXG5cdCAgICAgICAgJ2ZkYzNIYW5kbGVGaW5kSW5zdGFuY2VzJyxcblx0ICAgICAgICAnaGFuZGxlSW5mb0ZvckludGVudCcsXG5cdCAgICAgICAgJ2hhbmRsZUluZm9Gb3JJbnRlbnRzQnlDb250ZXh0Jyxcblx0ICAgICAgICAnZmRjM0hhbmRsZUdldEFwcE1ldGFkYXRhJyxcblx0ICAgICAgICAnZmRjM0hhbmRsZUdldEluZm8nLFxuXHQgICAgICAgICdmZGMzSGFuZGxlT3BlbicsXG5cdCAgICAgICAgJ2hhbmRsZUZpcmVkSW50ZW50Jyxcblx0ICAgICAgICAnaGFuZGxlRmlyZWRJbnRlbnRGb3JDb250ZXh0J1xuXHQgICAgXTtcblx0ICAgIHJldHVybiBtdXN0T3ZlcnJpZGVBUElzLmZpbHRlcigoYXBpKSA9PiB7XG5cdCAgICAgICAgcmV0dXJuIG92ZXJyaWRkZW5Ccm9rZXJbYXBpXSA9PT0gSW50ZXJvcEJyb2tlcl8xLkludGVyb3BCcm9rZXIucHJvdG90eXBlW2FwaV07XG5cdCAgICB9KTtcblx0fVxuXHRvdmVycmlkZUNoZWNrLmNoZWNrRkRDMzJPdmVycmlkZXMgPSBjaGVja0ZEQzMyT3ZlcnJpZGVzO1xuXHRmdW5jdGlvbiBvdmVycmlkZUNoZWNrJDEob3ZlcnJpZGRlbkJyb2tlciwgZmRjM0ludGVyb3BBcGkpIHtcblx0ICAgIGlmIChmZGMzSW50ZXJvcEFwaSAmJiBmZGMzSW50ZXJvcEFwaSA9PT0gJzIuMCcpIHtcblx0ICAgICAgICBjb25zdCBub3RPdmVycmlkZGVuID0gY2hlY2tGREMzMk92ZXJyaWRlcyhvdmVycmlkZGVuQnJva2VyKTtcblx0ICAgICAgICBpZiAobm90T3ZlcnJpZGRlbi5sZW5ndGggPiAwKSB7XG5cdCAgICAgICAgICAgIGNvbnNvbGUud2FybihgV0FSTklORzogRkRDMyAyLjAgaGFzIGJlZW4gc2V0IGFzIGEgZGVmYXVsdCBvcHRpb24gZm9yIFZpZXdzIGluIHRoaXMgUGxhdGZvcm0sIGJ1dCB0aGUgcmVxdWlyZWQgSW50ZXJvcEJyb2tlciBBUElzIGZvciBGREMzIDIuMCBjb21wbGlhbmNlIGhhdmUgbm90IGFsbCBiZWVuIG92ZXJyaWRkZW4uXFxuVGhlIGZvbGxvd2luZyBBUElzIG5lZWQgdG8gYmUgb3ZlcnJpZGRlbjpcXG4ke25vdE92ZXJyaWRkZW4uam9pbignXFxuJyl9YCk7XG5cdCAgICAgICAgfVxuXHQgICAgfVxuXHR9XG5cdG92ZXJyaWRlQ2hlY2sub3ZlcnJpZGVDaGVjayA9IG92ZXJyaWRlQ2hlY2skMTtcblx0cmV0dXJuIG92ZXJyaWRlQ2hlY2s7XG59XG5cbnZhciBoYXNSZXF1aXJlZEZhY3Rvcnk7XG5cbmZ1bmN0aW9uIHJlcXVpcmVGYWN0b3J5ICgpIHtcblx0aWYgKGhhc1JlcXVpcmVkRmFjdG9yeSkgcmV0dXJuIEZhY3RvcnkkMTtcblx0aGFzUmVxdWlyZWRGYWN0b3J5ID0gMTtcblx0dmFyIF9faW1wb3J0RGVmYXVsdCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2ltcG9ydERlZmF1bHQpIHx8IGZ1bmN0aW9uIChtb2QpIHtcblx0ICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgXCJkZWZhdWx0XCI6IG1vZCB9O1xuXHR9O1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoRmFjdG9yeSQxLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcblx0RmFjdG9yeSQxLkludGVyb3BNb2R1bGUgPSB2b2lkIDA7XG5cdGNvbnN0IGNsb25lRGVlcF8xID0gX19pbXBvcnREZWZhdWx0KHJlcXVpcmUkJDAkMSk7XG5cdGNvbnN0IGluYWNjZXNzaWJsZU9iamVjdF8xID0gaW5hY2Nlc3NpYmxlT2JqZWN0O1xuXHRjb25zdCBiYXNlXzEgPSBiYXNlO1xuXHRjb25zdCBJbnRlcm9wQnJva2VyXzEgPSByZXF1aXJlSW50ZXJvcEJyb2tlcigpO1xuXHRjb25zdCBJbnRlcm9wQ2xpZW50XzEgPSByZXF1aXJlSW50ZXJvcENsaWVudCgpO1xuXHRjb25zdCBvdmVycmlkZUNoZWNrXzEgPSByZXF1aXJlT3ZlcnJpZGVDaGVjaygpO1xuXHRjb25zdCBjb21tb25fdXRpbHNfMSA9IGNvbW1vblV0aWxzO1xuXHRjb25zdCBkZWZhdWx0T3ZlcnJpZGUgPSAoQ2xhc3MpID0+IG5ldyBDbGFzcygpO1xuXHRjb25zdCBCcm9rZXJQYXJhbUFjY2Vzc0Vycm9yID0gJ1lvdSBoYXZlIGF0dGVtcHRlZCB0byB1c2Ugb3IgbW9kaWZ5IEludGVyb3BCcm9rZXIgcGFyYW1ldGVycywgd2hpY2ggaXMgbm90IGFsbG93ZWQuIFlvdSBhcmUgbGlrZWx5IHVzaW5nIGFuIG9sZGVyIEludGVyb3BCcm9rZXIgb3ZlcnJpZGUgc2NoZW1lLiBQbGVhc2UgY29uc3VsdCBvdXIgSW50ZXJvcCBkb2NzIGZvciBndWlkYW5jZSBvbiBtaWdyYXRpbmcgdG8gdGhlIG5ldyBvdmVycmlkZSBzY2hlbWUuJztcblx0LyoqXG5cdCAqIE1hbmFnZXMgY3JlYXRpb24gb2YgSW50ZXJvcCBCcm9rZXJzIGFuZCBJbnRlcm9wIENsaWVudHMuIFRoZXNlIEFQSXMgYXJlIGNhbGxlZCB1bmRlci10aGUtaG9vZCBpbiBQbGF0Zm9ybXMuXG5cdCAqXG5cdCAqL1xuXHRjbGFzcyBJbnRlcm9wTW9kdWxlIGV4dGVuZHMgYmFzZV8xLkJhc2Uge1xuXHQgICAgLyoqXG5cdCAgICAgKiBJbml0aWFsaXplcyBhbiBJbnRlcm9wIEJyb2tlci4gVGhpcyBpcyBjYWxsZWQgdW5kZXItdGhlLWhvb2QgZm9yIFBsYXRmb3Jtcy5cblx0ICAgICAqXG5cdCAgICAgKiBAcmVtYXJrcyBGb3IgUGxhdGZvcm1zLCB0aGlzIGlzIHNldCB1cCBhdXRvbWF0aWNhbGx5LiBXZSBhZHZpc2UgdG8gb25seSBjcmVhdGUgeW91ciBvd24gSW50ZXJvcCBCcm9rZXJcblx0ICAgICAqIHdoZW4gbm90IHVzaW5nIGEgUGxhdGZvcm0gYXBwLiBZb3UgY2FuIG92ZXJyaWRlIGZ1bmN0aW9ucyBpbiB0aGUgSW50ZXJvcCBCcm9rZXIuIE1vcmUgaW5mbyB7QGxpbmsgSW50ZXJvcEJyb2tlciBoZXJlfS5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0gbmFtZSAtIE5hbWUgb2YgdGhlIEludGVyb3AgQnJva2VyLlxuXHQgICAgICogQHBhcmFtIG92ZXJyaWRlIC0gQSBjYWxsYmFjayBmdW5jdGlvbiBvciBhcnJheSBvZiBjYWxsYmFjayBmdW5jdGlvbnMgdGhhdCBjYW4gYmUgdXNlZCB0byBleHRlbmQgb3IgcmVwbGFjZSBkZWZhdWx0IEludGVyb3AgQnJva2VyIGJlaGF2aW9yLlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGAganNcblx0ICAgICAqIGNvbnN0IGludGVyb3BCcm9rZXIgPSBhd2FpdCBmaW4uSW50ZXJvcC5pbml0KCdvcGVuZmluJyk7XG5cdCAgICAgKiBjb25zdCBjb250ZXh0R3JvdXBzID0gYXdhaXQgaW50ZXJvcEJyb2tlci5nZXRDb250ZXh0R3JvdXBzKCk7XG5cdCAgICAgKiBjb25zb2xlLmxvZyhjb250ZXh0R3JvdXBzKTtcblx0ICAgICAqIGBgYFxuXHQgICAgICovXG5cdCAgICBhc3luYyBpbml0KG5hbWUsIG92ZXJyaWRlID0gZGVmYXVsdE92ZXJyaWRlKSB7XG5cdCAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ2ludGVyb3AtaW5pdCcpLmNhdGNoKCgpID0+IHtcblx0ICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG5cdCAgICAgICAgfSk7XG5cdCAgICAgICAgLy8gQWxsb3dzIGZvciBtYW5pZmVzdC1sZXZlbCBjb25maWd1cmF0aW9uLCB3aXRob3V0IGhhdmluZyB0byBvdmVycmlkZS4gKGUuZy4gc3BlY2lmeWluZyBjdXN0b20gY29udGV4dCBncm91cHMpXG5cdCAgICAgICAgY29uc3Qgb3B0aW9ucyA9IGF3YWl0IHRoaXMud2lyZS5lbnZpcm9ubWVudC5nZXRJbnRlcm9wSW5mbyh0aGlzLndpcmUuZ2V0RmluKCkpO1xuXHQgICAgICAgIGNvbnN0IG9iamVjdFRoYXRUaHJvd3MgPSAoMCwgaW5hY2Nlc3NpYmxlT2JqZWN0XzEuY3JlYXRlVW51c2FibGVPYmplY3QpKEJyb2tlclBhcmFtQWNjZXNzRXJyb3IpO1xuXHQgICAgICAgIGNvbnN0IHdhcm5pbmdPcHRzQ2xvbmUgPSAoMCwgaW5hY2Nlc3NpYmxlT2JqZWN0XzEuY3JlYXRlV2FybmluZ09iamVjdCkoQnJva2VyUGFyYW1BY2Nlc3NFcnJvciwgKDAsIGNsb25lRGVlcF8xLmRlZmF1bHQpKG9wdGlvbnMpKTtcblx0ICAgICAgICBjb25zdCBnZXRQcm92aWRlciA9ICgpID0+IHtcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jcmVhdGUoYGludGVyb3AtYnJva2VyLSR7bmFtZX1gKTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIGNvbnN0IHRocm93aW5nR2V0UHJvdmlkZXIgPSBhc3luYyAoKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG5cdCAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihCcm9rZXJQYXJhbUFjY2Vzc0Vycm9yKTtcblx0ICAgICAgICB9O1xuXHQgICAgICAgIGNvbnN0IE92ZXJyaWRlYWJsZUJyb2tlciA9IEludGVyb3BCcm9rZXJfMS5JbnRlcm9wQnJva2VyLmNyZWF0ZUNsb3NlZENvbnN0cnVjdG9yKHRoaXMud2lyZSwgZ2V0UHJvdmlkZXIsIG9wdGlvbnMpO1xuXHQgICAgICAgIGxldCBicm9rZXI7XG5cdCAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkob3ZlcnJpZGUpKSB7XG5cdCAgICAgICAgICAgIGNvbnN0IEJyb2tlckNvbnN0cnVjdG9yID0gKDAsIGNvbW1vbl91dGlsc18xLm92ZXJyaWRlRnJvbUNvbXBvc2FibGVzKSguLi5vdmVycmlkZSkoT3ZlcnJpZGVhYmxlQnJva2VyKTtcblx0ICAgICAgICAgICAgLy8gV2UgbmVlZCB0byB1c2UgdGhlc2Ugb2JqZWN0cyBiZWNhdXNlIHJlbW92aW5nIHRoZW0gZW50aXJlbHkgd291bGQgYmUgYSBicmVha2luZyBjaGFuZ2UgYW5kIHdlIHdhbnQgYW4gaW5mb3JtYXRpdmUgZXJyb3Jcblx0ICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuXHQgICAgICAgICAgICBicm9rZXIgPSBuZXcgQnJva2VyQ29uc3RydWN0b3Iob2JqZWN0VGhhdFRocm93cywgdGhyb3dpbmdHZXRQcm92aWRlciwgd2FybmluZ09wdHNDbG9uZSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgIGVsc2Uge1xuXHQgICAgICAgICAgICAvLyBXZSBuZWVkIHRvIHVzZSB0aGVzZSBvYmplY3RzIGJlY2F1c2UgcmVtb3ZpbmcgdGhlbSBlbnRpcmVseSB3b3VsZCBiZSBhIGJyZWFraW5nIGNoYW5nZSBhbmQgd2Ugd2FudCBhbiBpbmZvcm1hdGl2ZSBlcnJvclxuXHQgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yXG5cdCAgICAgICAgICAgIGJyb2tlciA9IGF3YWl0IG92ZXJyaWRlKE92ZXJyaWRlYWJsZUJyb2tlciwgb2JqZWN0VGhhdFRocm93cywgdGhyb3dpbmdHZXRQcm92aWRlciwgd2FybmluZ09wdHNDbG9uZSk7XG5cdCAgICAgICAgfVxuXHQgICAgICAgICgwLCBvdmVycmlkZUNoZWNrXzEub3ZlcnJpZGVDaGVjaykoYnJva2VyLCBvcHRpb25zLmZkYzNWZXJzaW9uKTtcblx0ICAgICAgICByZXR1cm4gYnJva2VyO1xuXHQgICAgfVxuXHQgICAgLyoqXG5cdCAgICAgKiBDb25uZWN0cyBhIGNsaWVudCB0byBhbiBJbnRlcm9wIGJyb2tlci4gVGhpcyBpcyBjYWxsZWQgdW5kZXItdGhlLWhvb2QgZm9yIFZpZXdzIGluIGEgUGxhdGZvcm0uXG5cdCAgICAgKlxuXHQgICAgICogQHJlbWFya3Ncblx0ICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIEludGVyb3AgQnJva2VyIHRvIGNvbm5lY3QgdG8uIEZvciBQbGF0Zm9ybXMsIHRoaXMgd2lsbCBkZWZhdWx0IHRvIHRoZSB1dWlkIG9mIHRoZSBQbGF0Zm9ybS5cblx0ICAgICAqIEBwYXJhbSBpbnRlcm9wQ29uZmlnIC0gSW5mb3JtYXRpb24gcmVsZXZhbnQgdG8gdGhlIEludGVyb3AgQnJva2VyLiBUeXBpY2FsbHkgYSBkZWNsYXJhdGlvbiBvZlxuXHQgICAgICogd2hhdCBjb250ZXh0KHMpIHRoZSBlbnRpdHkgd2FudHMgdG8gc3Vic2NyaWJlIHRvLCBhbmQgdGhlIGN1cnJlbnQgQ29udGV4dCBHcm91cCBvZiB0aGUgZW50aXR5LlxuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKiBgYGBqc1xuXHQgICAgICogY29uc3QgaW50ZXJvcENvbmZpZyA9IHtcblx0ICAgICAqICAgICBjdXJyZW50Q29udGV4dEdyb3VwOiAnZ3JlZW4nXG5cdCAgICAgKiB9XG5cdCAgICAgKlxuXHQgICAgICogY29uc3QgaW50ZXJvcEJyb2tlciA9IGF3YWl0IGZpbi5JbnRlcm9wLmluaXQoJ29wZW5maW4nKTtcblx0ICAgICAqIGNvbnN0IGNsaWVudCA9IGF3YWl0IGZpbi5JbnRlcm9wLmNvbm5lY3RTeW5jKCdvcGVuZmluJywgaW50ZXJvcENvbmZpZyk7XG5cdCAgICAgKiBjb25zdCBjb250ZXh0R3JvdXBJbmZvID0gYXdhaXQgY2xpZW50LmdldEluZm9Gb3JDb250ZXh0R3JvdXAoKTtcblx0ICAgICAqIGNvbnNvbGUubG9nKGNvbnRleHRHcm91cEluZm8pO1xuXHQgICAgICogYGBgXG5cdCAgICAgKi9cblx0ICAgIGNvbm5lY3RTeW5jKG5hbWUsIGludGVyb3BDb25maWcpIHtcblx0ICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignaW50ZXJvcC1jb25uZWN0LXN5bmMnKS5jYXRjaCgoKSA9PiB7XG5cdCAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuXHQgICAgICAgIH0pO1xuXHQgICAgICAgIHJldHVybiBuZXcgSW50ZXJvcENsaWVudF8xLkludGVyb3BDbGllbnQodGhpcy53aXJlLCB0aGlzLndpcmUuZW52aXJvbm1lbnQud2hlblJlYWR5KCkudGhlbigoKSA9PiB7XG5cdCAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY29ubmVjdChgaW50ZXJvcC1icm9rZXItJHtuYW1lfWAsIHtcblx0ICAgICAgICAgICAgICAgIHBheWxvYWQ6IGludGVyb3BDb25maWdcblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgfSkpO1xuXHQgICAgfVxuXHR9XG5cdEZhY3RvcnkkMS5JbnRlcm9wTW9kdWxlID0gSW50ZXJvcE1vZHVsZTtcblx0cmV0dXJuIEZhY3RvcnkkMTtcbn1cblxudmFyIGhhc1JlcXVpcmVkSW50ZXJvcDtcblxuZnVuY3Rpb24gcmVxdWlyZUludGVyb3AgKCkge1xuXHRpZiAoaGFzUmVxdWlyZWRJbnRlcm9wKSByZXR1cm4gaW50ZXJvcDtcblx0aGFzUmVxdWlyZWRJbnRlcm9wID0gMTtcblx0KGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdFx0LyoqXG5cdFx0ICogRW50cnkgcG9pbnQgZm9yIHRoZSBPcGVuRmluIGBJbnRlcm9wYCBBUEkgKGBmaW4uSW50ZXJvcGApLlxuXHRcdCAqXG5cdFx0ICogKiB7QGxpbmsgSW50ZXJvcE1vZHVsZX0gY29udGFpbnMgc3RhdGljIG1lbWJlcnMgb2YgdGhlIGBJbnRlcm9wYCBBUEkgKGF2YWlsYWJsZSB1bmRlciBgZmluLkludGVyb3BgKVxuXHRcdCAqICoge0BsaW5rIEludGVyb3BDbGllbnR9IGFuZCB7QGxpbmsgSW50ZXJvcEJyb2tlcn0gZG9jdW1lbnQgaW5zdGFuY2VzIG9mIHRoZWlyIHJlc3BlY3RpdmUgY2xhc3Nlcy5cblx0XHQgKlxuXHRcdCAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuXHRcdCAqL1xuXHRcdHZhciBfX2NyZWF0ZUJpbmRpbmcgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHRcdCAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuXHRcdCAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XG5cdFx0ICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XG5cdFx0ICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcblx0XHQgICAgfVxuXHRcdCAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xuXHRcdH0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XG5cdFx0ICAgIGlmIChrMiA9PT0gdW5kZWZpbmVkKSBrMiA9IGs7XG5cdFx0ICAgIG9bazJdID0gbVtrXTtcblx0XHR9KSk7XG5cdFx0dmFyIF9fZXhwb3J0U3RhciA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2V4cG9ydFN0YXIpIHx8IGZ1bmN0aW9uKG0sIGV4cG9ydHMpIHtcblx0XHQgICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChleHBvcnRzLCBwKSkgX19jcmVhdGVCaW5kaW5nKGV4cG9ydHMsIG0sIHApO1xuXHRcdH07XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuXHRcdF9fZXhwb3J0U3RhcihyZXF1aXJlRmFjdG9yeSgpLCBleHBvcnRzKTtcblx0XHRfX2V4cG9ydFN0YXIocmVxdWlyZUludGVyb3BDbGllbnQoKSwgZXhwb3J0cyk7XG5cdFx0X19leHBvcnRTdGFyKHJlcXVpcmVJbnRlcm9wQnJva2VyKCksIGV4cG9ydHMpOyBcblx0fSAoaW50ZXJvcCkpO1xuXHRyZXR1cm4gaW50ZXJvcDtcbn1cblxudmFyIHNuYXBzaG90U291cmNlID0ge307XG5cbnZhciBGYWN0b3J5ID0ge307XG5cbnZhciBJbnN0YW5jZSA9IHt9O1xuXG52YXIgdXRpbHMgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KHV0aWxzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbnV0aWxzLmdldFNuYXBzaG90U291cmNlQ2hhbm5lbE5hbWUgPSB2b2lkIDA7XG5jb25zdCBjaGFubmVsUHJlZml4ID0gJ3NuYXBzaG90LXNvdXJjZS1wcm92aWRlci0nO1xuY29uc3QgZ2V0U25hcHNob3RTb3VyY2VDaGFubmVsTmFtZSA9IChpZCkgPT4gYCR7Y2hhbm5lbFByZWZpeH0ke2lkLnV1aWR9YDtcbnV0aWxzLmdldFNuYXBzaG90U291cmNlQ2hhbm5lbE5hbWUgPSBnZXRTbmFwc2hvdFNvdXJjZUNoYW5uZWxOYW1lO1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCQxID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fY2xhc3NQcml2YXRlRmllbGRTZXQpIHx8IGZ1bmN0aW9uIChyZWNlaXZlciwgc3RhdGUsIHZhbHVlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB3cml0ZSBwcml2YXRlIG1lbWJlciB0byBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufTtcbnZhciBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jbGFzc1ByaXZhdGVGaWVsZEdldCkgfHwgZnVuY3Rpb24gKHJlY2VpdmVyLCBzdGF0ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4ga2luZCA9PT0gXCJtXCIgPyBmIDoga2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIpIDogZiA/IGYudmFsdWUgOiBzdGF0ZS5nZXQocmVjZWl2ZXIpO1xufTtcbnZhciBfU25hcHNob3RTb3VyY2VfaWRlbnRpdHksIF9TbmFwc2hvdFNvdXJjZV9nZXRDb25uZWN0aW9uLCBfU25hcHNob3RTb3VyY2VfZ2V0Q2xpZW50LCBfU25hcHNob3RTb3VyY2Vfc3RhcnRDb25uZWN0aW9uLCBfU25hcHNob3RTb3VyY2Vfc2V0VXBDb25uZWN0aW9uTGlzdGVuZXI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoSW5zdGFuY2UsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuSW5zdGFuY2UuU25hcHNob3RTb3VyY2UgPSB2b2lkIDA7XG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uICovXG5jb25zdCBiYXNlXzEkMSA9IGJhc2U7XG5jb25zdCB1dGlsc18xJDEgPSB1dGlscztcbmNvbnN0IGNvbm5lY3Rpb25NYXAgPSBuZXcgTWFwKCk7XG4vKipcbiAqIEVuYWJsZXMgY29uZmlndXJpbmcgYSBTbmFwc2hvdFNvdXJjZSB3aXRoIGN1c3RvbSBnZXRTbmFwc2hvdCBhbmQgYXBwbHlTbmFwc2hvdCBtZXRob2RzLlxuICpcbiAqIEB0eXBlUGFyYW0gU25hcHNob3QgSW1wbGVtZW50YXRpb24tZGVmaW5lZCBzaGFwZSBvZiBhbiBhcHBsaWNhdGlvbiBzbmFwc2hvdC4gIEFsbG93c1xuICogY3VzdG9tIHNuYXBzaG90IGltcGxlbWVudGF0aW9ucyBmb3IgbGVnYWN5IGFwcGxpY2F0aW9ucyB0byBkZWZpbmUgdGhlaXIgb3duIHNuYXBzaG90IGZvcm1hdC5cbiAqL1xuY2xhc3MgU25hcHNob3RTb3VyY2UgZXh0ZW5kcyBiYXNlXzEkMS5CYXNlIHtcbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih3aXJlLCBpZCkge1xuICAgICAgICBzdXBlcih3aXJlKTtcbiAgICAgICAgX1NuYXBzaG90U291cmNlX2lkZW50aXR5LnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICBfU25hcHNob3RTb3VyY2VfZ2V0Q29ubmVjdGlvbi5zZXQodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFjb25uZWN0aW9uTWFwLmhhcyh0aGlzLmlkZW50aXR5LnV1aWQpKSB7XG4gICAgICAgICAgICAgICAgY29ubmVjdGlvbk1hcC5zZXQodGhpcy5pZGVudGl0eS51dWlkLCB7IGV2ZW50RmlyZWQ6IG51bGwsIGNsaWVudFByb21pc2U6IG51bGwgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29ubmVjdGlvbk1hcC5nZXQodGhpcy5pZGVudGl0eS51dWlkKTtcbiAgICAgICAgfSk7XG4gICAgICAgIF9TbmFwc2hvdFNvdXJjZV9nZXRDbGllbnQuc2V0KHRoaXMsICgpID0+IHtcbiAgICAgICAgICAgIGlmICghX19jbGFzc1ByaXZhdGVGaWVsZEdldCQxKHRoaXMsIF9TbmFwc2hvdFNvdXJjZV9nZXRDb25uZWN0aW9uLCBcImZcIikuY2FsbCh0aGlzKS5jbGllbnRQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQxKHRoaXMsIF9TbmFwc2hvdFNvdXJjZV9nZXRDb25uZWN0aW9uLCBcImZcIikuY2FsbCh0aGlzKS5jbGllbnRQcm9taXNlID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCQxKHRoaXMsIF9TbmFwc2hvdFNvdXJjZV9zdGFydENvbm5lY3Rpb24sIFwiZlwiKS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMSh0aGlzLCBfU25hcHNob3RTb3VyY2VfZ2V0Q29ubmVjdGlvbiwgXCJmXCIpLmNhbGwodGhpcykuY2xpZW50UHJvbWlzZTtcbiAgICAgICAgfSk7XG4gICAgICAgIF9TbmFwc2hvdFNvdXJjZV9zdGFydENvbm5lY3Rpb24uc2V0KHRoaXMsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5uZWxOYW1lID0gKDAsIHV0aWxzXzEkMS5nZXRTbmFwc2hvdFNvdXJjZUNoYW5uZWxOYW1lKSh0aGlzLmlkZW50aXR5KTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKCFfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2dldENvbm5lY3Rpb24sIFwiZlwiKS5jYWxsKHRoaXMpLmV2ZW50RmlyZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQxKHRoaXMsIF9TbmFwc2hvdFNvdXJjZV9zZXRVcENvbm5lY3Rpb25MaXN0ZW5lciwgXCJmXCIpLmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IHRoaXMuZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KGNoYW5uZWxOYW1lLCB7IHdhaXQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgIGNsaWVudC5vbkRpc2Nvbm5lY3Rpb24oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2dldENvbm5lY3Rpb24sIFwiZlwiKS5jYWxsKHRoaXMpLmNsaWVudFByb21pc2UgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2dldENvbm5lY3Rpb24sIFwiZlwiKS5jYWxsKHRoaXMpLmV2ZW50RmlyZWQgPSBudWxsO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBjbGllbnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMSh0aGlzLCBfU25hcHNob3RTb3VyY2VfZ2V0Q29ubmVjdGlvbiwgXCJmXCIpLmNhbGwodGhpcykuY2xpZW50UHJvbWlzZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIHRhcmdldGVkIFNuYXBzaG90U291cmNlIGlzIG5vdCBjdXJyZW50bHkgaW5pdGlhbGl6ZWQuIEF3YWl0IHRoaXMgb2JqZWN0J3MgcmVhZHkoKSBtZXRob2QuXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgX1NuYXBzaG90U291cmNlX3NldFVwQ29ubmVjdGlvbkxpc3RlbmVyLnNldCh0aGlzLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjaGFubmVsTmFtZSA9ICgwLCB1dGlsc18xJDEuZ2V0U25hcHNob3RTb3VyY2VDaGFubmVsTmFtZSkodGhpcy5pZGVudGl0eSk7XG4gICAgICAgICAgICBsZXQgcmVzb2x2ZTtcbiAgICAgICAgICAgIGxldCByZWplY3Q7XG4gICAgICAgICAgICBjb25zdCBldmVudEZpcmVkID0gbmV3IFByb21pc2UoKHksIG4pID0+IHtcbiAgICAgICAgICAgICAgICByZXNvbHZlID0geTtcbiAgICAgICAgICAgICAgICByZWplY3QgPSBuO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2dldENvbm5lY3Rpb24sIFwiZlwiKS5jYWxsKHRoaXMpLmV2ZW50RmlyZWQgPSBldmVudEZpcmVkO1xuICAgICAgICAgICAgY29uc3QgbGlzdGVuZXIgPSBhc3luYyAoZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlLmNoYW5uZWxOYW1lID09PSBjaGFubmVsTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5maW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLnJlbW92ZUxpc3RlbmVyKCdjb25uZWN0ZWQnLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5maW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLm9uKCdjb25uZWN0ZWQnLCBsaXN0ZW5lcik7XG4gICAgICAgIH0pO1xuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2lkZW50aXR5LCBpZCwgXCJmXCIpO1xuICAgIH1cbiAgICBnZXQgaWRlbnRpdHkoKSB7XG4gICAgICAgIHJldHVybiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2lkZW50aXR5LCBcImZcIik7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0byBkZXRlcm1pbmUgaWYgdGhlIFNuYXBzaG90U291cmNlIGhhcyBiZWVuIGluaXRpYWxpemVkLlxuICAgICAqXG4gICAgICogQHJlbWFya3MgVXNlIHdoZW4gdGhlIHBhcmVudCBhcHBsaWNhdGlvbiBpcyBzdGFydGluZyB1cCB0byBlbnN1cmUgdGhlIFNuYXBzaG90U291cmNlIGlzIGFibGUgdG8gYWNjZXB0IGFuZFxuICAgICAqIGFwcGx5IGEgc25hcHNob3QgdXNpbmcgdGhlIHtAbGluayBTbmFwc2hvdFNvdXJjZSNhcHBseVNuYXBzaG90IGFwcGx5U25hcHNob3R9IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYGBganNcbiAgICAgKiBsZXQgc25hcHNob3RTb3VyY2UgPSBmaW4uU25hcHNob3RTb3VyY2Uud3JhcFN5bmMoZmluLm1lKTtcbiAgICAgKlxuICAgICAqIGNvbnN0IHNuYXBzaG90UHJvdmlkZXIgPSB7XG4gICAgICogICAgIGFzeW5jIGdldFNuYXBzaG90KCkgeyByZXR1cm4gJ2ZvbycgfSxcbiAgICAgKiAgICAgYXN5bmMgYXBwbHlTbmFwc2hvdChzbmFwc2hvdCkge1xuICAgICAqICAgICAgIGNvbnNvbGUubG9nKHNuYXBzaG90KTtcbiAgICAgKiAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAqICAgICB9XG4gICAgICogfVxuICAgICAqIGF3YWl0IGZpbi5TbmFwc2hvdFNvdXJjZS5pbml0KHNuYXBzaG90UHJvdmlkZXIpO1xuICAgICAqXG4gICAgICogdHJ5IHtcbiAgICAgKiAgIGF3YWl0IHNuYXBzaG90U291cmNlLnJlYWR5KCk7XG4gICAgICogICBhd2FpdCBzbmFwc2hvdFNvdXJjZS5hcHBseVNuYXBzaG90KCdmb28nKTtcbiAgICAgKiB9IGNhdGNoIChlcnIpIHtcbiAgICAgKiAgIGNvbnNvbGUubG9nKGVycilcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgcmVhZHkoKSB7XG4gICAgICAgIHRoaXMud2lyZS5zZW5kQWN0aW9uKCdzbmFwc2hvdC1zb3VyY2UtcmVhZHknKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG4gICAgICAgIH0pO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYXN5bmMtcHJvbWlzZS1leGVjdXRvclxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gSWYgZ2V0Q2xpZW50IHdhcyBhbHJlYWR5IGNhbGxlZCBiZWZvcmUgdGhpcywgZG8gd2UgaGF2ZSBhIHRpbWluZyBpc3N1ZSB3aGVyZSB0aGUgY2hhbm5lbCBtaWdodCBoYXZlIGJlZW4gY3JlYXRlZCBidXQgd2UgbWlzc2VkIHRoZSBldmVudCBidXQgdGhpcyBzdGlsbCBmYWlscz9cbiAgICAgICAgICAgIGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQkMSh0aGlzLCBfU25hcHNob3RTb3VyY2VfZ2V0Q2xpZW50LCBcImZcIikuY2FsbCh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gaXQgd2FzIG5vdCBydW5uaW5nLlxuICAgICAgICAgICAgYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQxKHRoaXMsIF9TbmFwc2hvdFNvdXJjZV9nZXRDb25uZWN0aW9uLCBcImZcIikuY2FsbCh0aGlzKS5ldmVudEZpcmVkO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qKlxuICAgICAqIENhbGwgdGhlIFNuYXBzaG90U291cmNlJ3MgZ2V0U25hcHNob3QgbWV0aG9kIGRlZmluZWQgYnkge0BsaW5rIFNuYXBzaG90U291cmNlLlNuYXBzaG90U291cmNlTW9kdWxlI2luaXQgaW5pdH0uXG4gICAgICpcbiAgICAgKi9cbiAgICBhc3luYyBnZXRTbmFwc2hvdCgpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NuYXBzaG90LXNvdXJjZS1nZXQtc25hcHNob3QnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0JDEodGhpcywgX1NuYXBzaG90U291cmNlX2dldENsaWVudCwgXCJmXCIpLmNhbGwodGhpcyk7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gKGF3YWl0IGNsaWVudC5kaXNwYXRjaCgnZ2V0LXNuYXBzaG90JykpO1xuICAgICAgICByZXR1cm4gKGF3YWl0IHJlc3BvbnNlKS5zbmFwc2hvdDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQ2FsbCB0aGUgU25hcHNob3RTb3VyY2UncyBhcHBseVNuYXBzaG90IG1ldGhvZCBkZWZpbmVkIGJ5IHtAbGluayBTbmFwc2hvdFNvdXJjZS5TbmFwc2hvdFNvdXJjZU1vZHVsZSNpbml0IGluaXR9LlxuICAgICAqXG4gICAgICovXG4gICAgYXN5bmMgYXBwbHlTbmFwc2hvdChzbmFwc2hvdCkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignc25hcHNob3Qtc291cmNlLWFwcGx5LXNuYXBzaG90JykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCQxKHRoaXMsIF9TbmFwc2hvdFNvdXJjZV9nZXRDbGllbnQsIFwiZlwiKS5jYWxsKHRoaXMpO1xuICAgICAgICByZXR1cm4gY2xpZW50LmRpc3BhdGNoKCdhcHBseS1zbmFwc2hvdCcsIHsgc25hcHNob3QgfSk7XG4gICAgfVxufVxuSW5zdGFuY2UuU25hcHNob3RTb3VyY2UgPSBTbmFwc2hvdFNvdXJjZTtcbl9TbmFwc2hvdFNvdXJjZV9pZGVudGl0eSA9IG5ldyBXZWFrTWFwKCksIF9TbmFwc2hvdFNvdXJjZV9nZXRDb25uZWN0aW9uID0gbmV3IFdlYWtNYXAoKSwgX1NuYXBzaG90U291cmNlX2dldENsaWVudCA9IG5ldyBXZWFrTWFwKCksIF9TbmFwc2hvdFNvdXJjZV9zdGFydENvbm5lY3Rpb24gPSBuZXcgV2Vha01hcCgpLCBfU25hcHNob3RTb3VyY2Vfc2V0VXBDb25uZWN0aW9uTGlzdGVuZXIgPSBuZXcgV2Vha01hcCgpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoRmFjdG9yeSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5GYWN0b3J5LlNuYXBzaG90U291cmNlTW9kdWxlID0gdm9pZCAwO1xuY29uc3QgYmFzZV8xID0gYmFzZTtcbmNvbnN0IEluc3RhbmNlXzEgPSBJbnN0YW5jZTtcbmNvbnN0IHV0aWxzXzEgPSB1dGlscztcbi8qKlxuICogU3RhdGljIG5hbWVzcGFjZSBmb3IgT3BlbkZpbiBBUEkgbWV0aG9kcyB0aGF0IGludGVyYWN0IHdpdGggdGhlIHtAbGluayBTbmFwc2hvdFNvdXJjZX0gY2xhc3MsIGF2YWlsYWJsZSB1bmRlciBgZmluLlNuYXBzaG90U291cmNlYC5cbiAqL1xuY2xhc3MgU25hcHNob3RTb3VyY2VNb2R1bGUgZXh0ZW5kcyBiYXNlXzEuQmFzZSB7XG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZXMgYSBTbmFwc2hvdFNvdXJjZSB3aXRoIHRoZSBnZXRTbmFwc2hvdCBhbmQgYXBwbHlTbmFwc2hvdCBtZXRob2RzIGRlZmluZWQuXG4gICAgICpcbiAgICAgKiBAdHlwZVBhcmFtIFNuYXBzaG90IEltcGxlbWVudGF0aW9uLWRlZmluZWQgc2hhcGUgb2YgYW4gYXBwbGljYXRpb24gc25hcHNob3QuICBBbGxvd3NcbiAgICAgKiBjdXN0b20gc25hcHNob3QgaW1wbGVtZW50YXRpb25zIGZvciBsZWdhY3kgYXBwbGljYXRpb25zIHRvIGRlZmluZSB0aGVpciBvd24gc25hcHNob3QgZm9ybWF0LlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHNuYXBzaG90UHJvdmlkZXIgPSB7XG4gICAgICogICAgIGFzeW5jIGdldFNuYXBzaG90KCkge1xuICAgICAqICAgICAgIGNvbnN0IGJvdW5kcyA9IGF3YWl0IGZpbi5tZS5nZXRCb3VuZHMoKTtcbiAgICAgKiAgICAgICByZXR1cm4gYm91bmRzO1xuICAgICAqICAgICAgfSxcbiAgICAgKiAgICAgYXN5bmMgYXBwbHlTbmFwc2hvdChzbmFwc2hvdCkge1xuICAgICAqICAgICAgIGF3YWl0IGZpbi5tZS5zZXRCb3VuZHMoc25hcHNob3QpO1xuICAgICAqICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICogICAgIH1cbiAgICAgKiB9XG4gICAgICpcbiAgICAgKiBhd2FpdCBmaW4uU25hcHNob3RTb3VyY2UuaW5pdChzbmFwc2hvdFByb3ZpZGVyKTtcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqL1xuICAgIGFzeW5jIGluaXQocHJvdmlkZXIpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NuYXBzaG90LXNvdXJjZS1pbml0JykuY2F0Y2goKGUpID0+IHtcbiAgICAgICAgICAgIC8vIGRvbid0IGV4cG9zZSwgYW5hbHl0aWNzLW9ubHkgY2FsbFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHR5cGVvZiBwcm92aWRlciAhPT0gJ29iamVjdCcgfHxcbiAgICAgICAgICAgIHR5cGVvZiBwcm92aWRlci5nZXRTbmFwc2hvdCAhPT0gJ2Z1bmN0aW9uJyB8fFxuICAgICAgICAgICAgdHlwZW9mIHByb3ZpZGVyLmFwcGx5U25hcHNob3QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigneW91IG11c3QgcGFzcyBpbiBhIHZhbGlkIFNuYXBzaG90UHJvdmlkZXInKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjaGFubmVsID0gYXdhaXQgdGhpcy5maW4uSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsLmNyZWF0ZSgoMCwgdXRpbHNfMS5nZXRTbmFwc2hvdFNvdXJjZUNoYW5uZWxOYW1lKSh0aGlzLmZpbi5tZSkpO1xuICAgICAgICBjaGFubmVsLnJlZ2lzdGVyKCdnZXQtc25hcHNob3QnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHByb3ZpZGVyLmdldFNuYXBzaG90KCk7XG4gICAgICAgICAgICByZXR1cm4geyBzbmFwc2hvdCB9O1xuICAgICAgICB9KTtcbiAgICAgICAgY2hhbm5lbC5yZWdpc3RlcignYXBwbHktc25hcHNob3QnLCAoeyBzbmFwc2hvdCB9KSA9PiBwcm92aWRlci5hcHBseVNuYXBzaG90KHNuYXBzaG90KSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIFN5bmNocm9ub3VzbHkgcmV0dXJucyBhIFNuYXBzaG90U291cmNlIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIGN1cnJlbnQgU25hcHNob3RTb3VyY2UuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGBgYGpzXG4gICAgICogY29uc3Qgc25hcHNob3RTb3VyY2UgPSBmaW4uU25hcHNob3RTb3VyY2Uud3JhcFN5bmMoZmluLm1lKTtcbiAgICAgKiAvLyBVc2Ugd3JhcHBlZCBpbnN0YW5jZSdzIGdldFNuYXBzaG90IG1ldGhvZCwgZS5nLjpcbiAgICAgKiBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHNuYXBzaG90U291cmNlLmdldFNuYXBzaG90KCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgd3JhcFN5bmMoaWRlbnRpdHkpIHtcbiAgICAgICAgdGhpcy53aXJlLnNlbmRBY3Rpb24oJ3NuYXBzaG90LXNvdXJjZS13cmFwLXN5bmMnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbmV3IEluc3RhbmNlXzEuU25hcHNob3RTb3VyY2UodGhpcy53aXJlLCBpZGVudGl0eSk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEFzeW5jaHJvbm91c2x5IHJldHVybnMgYSBTbmFwc2hvdFNvdXJjZSBvYmplY3QgdGhhdCByZXByZXNlbnRzIHRoZSBjdXJyZW50IFNuYXBzaG90U291cmNlLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGBqc1xuICAgICAqIGNvbnN0IHNuYXBzaG90U291cmNlID0gYXdhaXQgZmluLlNuYXBzaG90U291cmNlLndyYXAoZmluLm1lKTtcbiAgICAgKiAvLyBVc2Ugd3JhcHBlZCBpbnN0YW5jZSdzIGdldFNuYXBzaG90IG1ldGhvZCwgZS5nLjpcbiAgICAgKiBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHNuYXBzaG90U291cmNlLmdldFNuYXBzaG90KCk7XG4gICAgICogYGBgXG4gICAgICovXG4gICAgYXN5bmMgd3JhcChpZGVudGl0eSkge1xuICAgICAgICB0aGlzLndpcmUuc2VuZEFjdGlvbignc25hcHNob3Qtc291cmNlLXdyYXAnKS5jYXRjaCgoZSkgPT4ge1xuICAgICAgICAgICAgLy8gZG9uJ3QgZXhwb3NlLCBhbmFseXRpY3Mtb25seSBjYWxsXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcy53cmFwU3luYyhpZGVudGl0eSk7XG4gICAgfVxufVxuRmFjdG9yeS5TbmFwc2hvdFNvdXJjZU1vZHVsZSA9IFNuYXBzaG90U291cmNlTW9kdWxlO1xuXG4oZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0LyoqXG5cdCAqIEVudHJ5IHBvaW50cyBmb3IgdGhlIE9wZW5GaW4gYFNuYXBzaG90U291cmNlYCBBUEkgKGBmaW4uU25hcHNob3RTb3VyY2VgKS5cblx0ICpcblx0ICogKiB7QGxpbmsgU25hcHNob3RTb3VyY2VNb2R1bGV9IGNvbnRhaW5zIHN0YXRpYyBtZW1iZXJzIG9mIHRoZSBgU25hcHNob3RTb3VyY2VgIEFQSSwgYWNjZXNzaWJsZSB0aHJvdWdoIGBmaW4uU25hcHNob3RTb3VyY2VgLlxuXHQgKiAqIHtAbGluayBTbmFwc2hvdFNvdXJjZX0gZGVzY3JpYmVzIGFuIGluc3RhbmNlIG9mIGFuIE9wZW5GaW4gU25hcHNob3RTb3VyY2UsIGUuZy4gYXMgcmV0dXJuZWQgYnkgYGZpbi5TbmFwc2hvdFNvdXJjZS53cmFwYC5cblx0ICpcblx0ICogVGhlc2UgYXJlIHNlcGFyYXRlIGNvZGUgZW50aXRpZXMsIGFuZCBhcmUgZG9jdW1lbnRlZCBzZXBhcmF0ZWx5LiAgSW4gdGhlIFtwcmV2aW91cyB2ZXJzaW9uIG9mIHRoZSBBUEkgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9jZG4ub3BlbmZpbi5jby9kb2NzL2phdmFzY3JpcHQvMzIuMTE0Ljc2LjEwL2luZGV4Lmh0bWwpLFxuXHQgKiBib3RoIG9mIHRoZXNlIHdlcmUgZG9jdW1lbnRlZCBvbiB0aGUgc2FtZSBwYWdlLlxuXHQgKlxuXHQgKiBAcGFja2FnZURvY3VtZW50YXRpb25cblx0ICovXG5cdHZhciBfX2NyZWF0ZUJpbmRpbmcgPSAoY29tbW9uanNHbG9iYWwgJiYgY29tbW9uanNHbG9iYWwuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcblx0ICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XG5cdCAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XG5cdCAgICB9XG5cdCAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgazIsIGRlc2MpO1xuXHR9KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuXHQgICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcblx0ICAgIG9bazJdID0gbVtrXTtcblx0fSkpO1xuXHR2YXIgX19leHBvcnRTdGFyID0gKGNvbW1vbmpzR2xvYmFsICYmIGNvbW1vbmpzR2xvYmFsLl9fZXhwb3J0U3RhcikgfHwgZnVuY3Rpb24obSwgZXhwb3J0cykge1xuXHQgICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChleHBvcnRzLCBwKSkgX19jcmVhdGVCaW5kaW5nKGV4cG9ydHMsIG0sIHApO1xuXHR9O1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5cdF9fZXhwb3J0U3RhcihGYWN0b3J5LCBleHBvcnRzKTtcblx0X19leHBvcnRTdGFyKEluc3RhbmNlLCBleHBvcnRzKTsgXG59IChzbmFwc2hvdFNvdXJjZSkpO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZmluJDIsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIEZpbl8xID0gZmluJDIuRmluID0gdm9pZCAwO1xuY29uc3QgZXZlbnRzXzEkMyA9IHJlcXVpcmUkJDA7XG4vLyBJbXBvcnQgZnJvbSB0aGUgZmlsZSByYXRoZXIgdGhhbiB0aGUgZGlyZWN0b3J5IGluIGNhc2Ugc29tZW9uZSBjb25zdW1pbmcgdHlwZXMgaXMgdXNpbmcgbW9kdWxlIHJlc29sdXRpb24gb3RoZXIgdGhhbiBcIm5vZGVcIlxuY29uc3QgaW5kZXhfMSA9IHN5c3RlbTtcbmNvbnN0IGluZGV4XzIgPSByZXF1aXJlV2luZG93KCk7XG5jb25zdCBpbmRleF8zID0gcmVxdWlyZUFwcGxpY2F0aW9uKCk7XG5jb25zdCBpbmRleF80ID0gaW50ZXJhcHBidXM7XG5jb25zdCBpbmRleF81ID0gY2xpcGJvYXJkO1xuY29uc3QgaW5kZXhfNiA9IGV4dGVybmFsQXBwbGljYXRpb247XG5jb25zdCBpbmRleF83ID0gZnJhbWU7XG5jb25zdCBpbmRleF84ID0gZ2xvYmFsSG90a2V5O1xuY29uc3QgaW5kZXhfOSA9IHJlcXVpcmVWaWV3KCk7XG5jb25zdCBpbmRleF8xMCA9IHBsYXRmb3JtO1xuY29uc3QgbWVfMSQyID0gbWU7XG5jb25zdCBpbnRlcm9wXzEgPSByZXF1aXJlSW50ZXJvcCgpO1xuY29uc3Qgc25hcHNob3Rfc291cmNlXzEgPSBzbmFwc2hvdFNvdXJjZTtcbi8qKlxuICogQGludGVybmFsXG4gKi9cbmNsYXNzIEZpbiBleHRlbmRzIGV2ZW50c18xJDMuRXZlbnRFbWl0dGVyIHtcbiAgICAvKipcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih3aXJlKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMud2lyZSA9IHdpcmU7XG4gICAgICAgIHRoaXMuU3lzdGVtID0gbmV3IGluZGV4XzEuU3lzdGVtKHdpcmUpO1xuICAgICAgICB0aGlzLldpbmRvdyA9IG5ldyBpbmRleF8yLl9XaW5kb3dNb2R1bGUod2lyZSk7XG4gICAgICAgIHRoaXMuQXBwbGljYXRpb24gPSBuZXcgaW5kZXhfMy5BcHBsaWNhdGlvbk1vZHVsZSh3aXJlKTtcbiAgICAgICAgdGhpcy5JbnRlckFwcGxpY2F0aW9uQnVzID0gbmV3IGluZGV4XzQuSW50ZXJBcHBsaWNhdGlvbkJ1cyh3aXJlKTtcbiAgICAgICAgdGhpcy5DbGlwYm9hcmQgPSBuZXcgaW5kZXhfNS5DbGlwYm9hcmQod2lyZSk7XG4gICAgICAgIHRoaXMuRXh0ZXJuYWxBcHBsaWNhdGlvbiA9IG5ldyBpbmRleF82LkV4dGVybmFsQXBwbGljYXRpb25Nb2R1bGUod2lyZSk7XG4gICAgICAgIHRoaXMuRnJhbWUgPSBuZXcgaW5kZXhfNy5fRnJhbWVNb2R1bGUod2lyZSk7XG4gICAgICAgIHRoaXMuR2xvYmFsSG90a2V5ID0gbmV3IGluZGV4XzguR2xvYmFsSG90a2V5KHdpcmUpO1xuICAgICAgICB0aGlzLlBsYXRmb3JtID0gbmV3IGluZGV4XzEwLlBsYXRmb3JtTW9kdWxlKHdpcmUsIHRoaXMuSW50ZXJBcHBsaWNhdGlvbkJ1cy5DaGFubmVsKTtcbiAgICAgICAgdGhpcy5WaWV3ID0gbmV3IGluZGV4XzkuVmlld01vZHVsZSh3aXJlKTtcbiAgICAgICAgdGhpcy5JbnRlcm9wID0gbmV3IGludGVyb3BfMS5JbnRlcm9wTW9kdWxlKHdpcmUpO1xuICAgICAgICB0aGlzLlNuYXBzaG90U291cmNlID0gbmV3IHNuYXBzaG90X3NvdXJjZV8xLlNuYXBzaG90U291cmNlTW9kdWxlKHdpcmUpO1xuICAgICAgICB3aXJlLnJlZ2lzdGVyRmluKHRoaXMpO1xuICAgICAgICB0aGlzLm1lID0gKDAsIG1lXzEkMi5nZXRNZSkod2lyZSk7XG4gICAgICAgIC8vIEhhbmRsZSBkaXNjb25uZWN0IGV2ZW50c1xuICAgICAgICB3aXJlLm9uKCdkaXNjb25uZWN0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmVtaXQoJ2Rpc2Nvbm5lY3RlZCcpO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5GaW5fMSA9IGZpbiQyLkZpbiA9IEZpbjtcblxudmFyIHRyYW5zcG9ydCA9IHt9O1xuXG52YXIgd2lyZSA9IHt9O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkod2lyZSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG53aXJlLmlzSW50ZXJuYWxDb25uZWN0Q29uZmlnID0gd2lyZS5pc1BvcnREaXNjb3ZlcnlDb25maWcgPSB3aXJlLmlzTmV3Q29ubmVjdENvbmZpZyA9IHdpcmUuaXNDb25maWdXaXRoUmVjZWl2ZXIgPSB3aXJlLmlzUmVtb3RlQ29uZmlnID0gd2lyZS5pc0V4aXN0aW5nQ29ubmVjdENvbmZpZyA9IHdpcmUuaXNFeHRlcm5hbENvbmZpZyA9IHZvaWQgMDtcbmZ1bmN0aW9uIGlzRXh0ZXJuYWxDb25maWcoY29uZmlnKSB7XG4gICAgaWYgKHR5cGVvZiBjb25maWcubWFuaWZlc3RVcmwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG53aXJlLmlzRXh0ZXJuYWxDb25maWcgPSBpc0V4dGVybmFsQ29uZmlnO1xuZnVuY3Rpb24gaXNFeGlzdGluZ0Nvbm5lY3RDb25maWcoY29uZmlnKSB7XG4gICAgcmV0dXJuIGhhc1V1aWQoY29uZmlnKSAmJiB0eXBlb2YgY29uZmlnLmFkZHJlc3MgPT09ICdzdHJpbmcnO1xufVxud2lyZS5pc0V4aXN0aW5nQ29ubmVjdENvbmZpZyA9IGlzRXhpc3RpbmdDb25uZWN0Q29uZmlnO1xuZnVuY3Rpb24gaXNSZW1vdGVDb25maWcoY29uZmlnKSB7XG4gICAgcmV0dXJuIGlzRXhpc3RpbmdDb25uZWN0Q29uZmlnKGNvbmZpZykgJiYgdHlwZW9mIGNvbmZpZy50b2tlbiA9PT0gJ3N0cmluZyc7XG59XG53aXJlLmlzUmVtb3RlQ29uZmlnID0gaXNSZW1vdGVDb25maWc7XG5mdW5jdGlvbiBpc0NvbmZpZ1dpdGhSZWNlaXZlcihjb25maWcpIHtcbiAgICByZXR1cm4gdHlwZW9mIGNvbmZpZy5yZWNlaXZlciA9PT0gJ29iamVjdCcgJiYgaXNSZW1vdGVDb25maWcoeyAuLi5jb25maWcsIGFkZHJlc3M6ICcnIH0pO1xufVxud2lyZS5pc0NvbmZpZ1dpdGhSZWNlaXZlciA9IGlzQ29uZmlnV2l0aFJlY2VpdmVyO1xuZnVuY3Rpb24gaGFzVXVpZChjb25maWcpIHtcbiAgICByZXR1cm4gdHlwZW9mIGNvbmZpZy51dWlkID09PSAnc3RyaW5nJztcbn1cbmZ1bmN0aW9uIGhhc1J1bnRpbWVWZXJzaW9uKGNvbmZpZykge1xuICAgIHJldHVybiBjb25maWcucnVudGltZSAmJiB0eXBlb2YgY29uZmlnLnJ1bnRpbWUudmVyc2lvbiA9PT0gJ3N0cmluZyc7XG59XG5mdW5jdGlvbiBpc05ld0Nvbm5lY3RDb25maWcoY29uZmlnKSB7XG4gICAgcmV0dXJuIGhhc1V1aWQoY29uZmlnKSAmJiBoYXNSdW50aW1lVmVyc2lvbihjb25maWcpO1xufVxud2lyZS5pc05ld0Nvbm5lY3RDb25maWcgPSBpc05ld0Nvbm5lY3RDb25maWc7XG5mdW5jdGlvbiBpc1BvcnREaXNjb3ZlcnlDb25maWcoY29uZmlnKSB7XG4gICAgcmV0dXJuIChpc0V4dGVybmFsQ29uZmlnKGNvbmZpZykgJiYgaGFzUnVudGltZVZlcnNpb24oY29uZmlnKSkgfHwgaXNOZXdDb25uZWN0Q29uZmlnKGNvbmZpZyk7XG59XG53aXJlLmlzUG9ydERpc2NvdmVyeUNvbmZpZyA9IGlzUG9ydERpc2NvdmVyeUNvbmZpZztcbmZ1bmN0aW9uIGlzSW50ZXJuYWxDb25uZWN0Q29uZmlnKGNvbmZpZykge1xuICAgIHJldHVybiBpc0V4aXN0aW5nQ29ubmVjdENvbmZpZyhjb25maWcpIHx8IGlzTmV3Q29ubmVjdENvbmZpZyhjb25maWcpO1xufVxud2lyZS5pc0ludGVybmFsQ29ubmVjdENvbmZpZyA9IGlzSW50ZXJuYWxDb25uZWN0Q29uZmlnO1xuXG52YXIgZXZlbnRBZ2dyZWdhdG9yID0ge307XG5cbnZhciBlbWl0dGVyTWFwID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShlbWl0dGVyTWFwLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmVtaXR0ZXJNYXAuRW1pdHRlck1hcCA9IHZvaWQgMDtcbmNvbnN0IGV2ZW50c18xJDIgPSByZXF1aXJlJCQwO1xuY2xhc3MgRW1pdHRlck1hcCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuc3RvcmFnZSA9IG5ldyBNYXAoKTtcbiAgICB9XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcbiAgICBoYXNoS2V5cyhrZXlzKSB7XG4gICAgICAgIGNvbnN0IGhhc2hlZCA9IGtleXMubWFwKG5vcm1hbGl6ZVN0cmluZyk7XG4gICAgICAgIHJldHVybiBoYXNoZWQuam9pbignLycpO1xuICAgIH1cbiAgICBnZXRPckNyZWF0ZShrZXlzKSB7XG4gICAgICAgIGNvbnN0IGhhc2ggPSB0aGlzLmhhc2hLZXlzKGtleXMpO1xuICAgICAgICBpZiAoIXRoaXMuc3RvcmFnZS5oYXMoaGFzaCkpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoaGFzaCwgbmV3IGV2ZW50c18xJDIuRXZlbnRFbWl0dGVyKCkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdlIHNldCBpdCBhYm92ZVxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldChoYXNoKTtcbiAgICB9XG4gICAgaGFzKGtleXMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5oYXModGhpcy5oYXNoS2V5cyhrZXlzKSk7XG4gICAgfVxuICAgIGRlbGV0ZShrZXlzKSB7XG4gICAgICAgIGNvbnN0IGhhc2ggPSB0aGlzLmhhc2hLZXlzKGtleXMpO1xuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmRlbGV0ZShoYXNoKTtcbiAgICB9XG59XG5lbWl0dGVyTWFwLkVtaXR0ZXJNYXAgPSBFbWl0dGVyTWFwO1xuZnVuY3Rpb24gbm9ybWFsaXplU3RyaW5nKHMpIHtcbiAgICBjb25zdCBiID0gQnVmZmVyLmZyb20ocyk7XG4gICAgcmV0dXJuIGIudG9TdHJpbmcoJ2Jhc2U2NCcpO1xufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXZlbnRBZ2dyZWdhdG9yLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmNvbnN0IGVtaXR0ZXJNYXBfMSA9IGVtaXR0ZXJNYXA7XG5mdW5jdGlvbiBpc0V2ZW50TWVzc2FnZShtZXNzYWdlKSB7XG4gICAgcmV0dXJuIG1lc3NhZ2UuYWN0aW9uID09PSAncHJvY2Vzcy1kZXNrdG9wLWV2ZW50Jztcbn1cbmZ1bmN0aW9uIG1hcEtleUZyb21FdmVudChldmVudCkge1xuICAgIGNvbnN0IHsgdG9waWMgfSA9IGV2ZW50O1xuICAgIGlmICh0b3BpYyA9PT0gJ2ZyYW1lJyB8fCB0b3BpYyA9PT0gJ3dpbmRvdycgfHwgdG9waWMgPT09ICd2aWV3Jykge1xuICAgICAgICBjb25zdCB7IHV1aWQsIG5hbWUgfSA9IGV2ZW50O1xuICAgICAgICByZXR1cm4gW3RvcGljLCB1dWlkLCBuYW1lXTtcbiAgICB9XG4gICAgaWYgKHRvcGljID09PSAnYXBwbGljYXRpb24nKSB7XG4gICAgICAgIGNvbnN0IHsgdXVpZCB9ID0gZXZlbnQ7XG4gICAgICAgIHJldHVybiBbdG9waWMsIHV1aWRdO1xuICAgIH1cbiAgICByZXR1cm4gW3RvcGljXTtcbn1cbmNsYXNzIEV2ZW50QWdncmVnYXRvciBleHRlbmRzIGVtaXR0ZXJNYXBfMS5FbWl0dGVyTWFwIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoLi4uYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50ID0gKG1lc3NhZ2UpID0+IHtcbiAgICAgICAgICAgIGlmIChpc0V2ZW50TWVzc2FnZShtZXNzYWdlKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgcGF5bG9hZCB9ID0gbWVzc2FnZTtcbiAgICAgICAgICAgICAgICBjb25zdCBhY2Nlc3NvciA9IG1hcEtleUZyb21FdmVudChwYXlsb2FkKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5oYXMoYWNjZXNzb3IpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0T3JDcmVhdGUoYWNjZXNzb3IpLmVtaXQocGF5bG9hZC50eXBlLCBwYXlsb2FkKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuICAgIH1cbn1cbmV2ZW50QWdncmVnYXRvci5kZWZhdWx0ID0gRXZlbnRBZ2dyZWdhdG9yO1xuXG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZFNldCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCB2YWx1ZSwga2luZCwgZikge1xuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XG4gICAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgd3JpdGUgcHJpdmF0ZSBtZW1iZXIgdG8gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcbn07XG52YXIgX19jbGFzc1ByaXZhdGVGaWVsZEdldCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KSB8fCBmdW5jdGlvbiAocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gICAgaWYgKGtpbmQgPT09IFwiYVwiICYmICFmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBhY2Nlc3NvciB3YXMgZGVmaW5lZCB3aXRob3V0IGEgZ2V0dGVyXCIpO1xuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHJlYWQgcHJpdmF0ZSBtZW1iZXIgZnJvbSBhbiBvYmplY3Qgd2hvc2UgY2xhc3MgZGlkIG5vdCBkZWNsYXJlIGl0XCIpO1xuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59O1xudmFyIF9faW1wb3J0RGVmYXVsdCA9IChjb21tb25qc0dsb2JhbCAmJiBjb21tb25qc0dsb2JhbC5fX2ltcG9ydERlZmF1bHQpIHx8IGZ1bmN0aW9uIChtb2QpIHtcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IFwiZGVmYXVsdFwiOiBtb2QgfTtcbn07XG52YXIgX1RyYW5zcG9ydF93aXJlLCBfVHJhbnNwb3J0X2Zpbjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0cmFuc3BvcnQsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIFRyYW5zcG9ydF8xID0gdHJhbnNwb3J0LlRyYW5zcG9ydCA9IHZvaWQgMDtcbmNvbnN0IGV2ZW50c18xJDEgPSByZXF1aXJlJCQwO1xuY29uc3Qgd2lyZV8xID0gd2lyZTtcbmNvbnN0IHRyYW5zcG9ydF9lcnJvcnNfMSA9IHRyYW5zcG9ydEVycm9ycztcbmNvbnN0IGV2ZW50QWdncmVnYXRvcl8xID0gX19pbXBvcnREZWZhdWx0KGV2ZW50QWdncmVnYXRvcik7XG5jb25zdCBtZV8xJDEgPSBtZTtcbmNvbnN0IGVycm9yc18xID0gZXJyb3JzO1xuY2xhc3MgVHJhbnNwb3J0IGV4dGVuZHMgZXZlbnRzXzEkMS5FdmVudEVtaXR0ZXIge1xuICAgIGNvbnN0cnVjdG9yKFdpcmVUeXBlLCBlbnZpcm9ubWVudCwgY29uZmlnKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMud2lyZUxpc3RlbmVycyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy50b3BpY1JlZk1hcCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5ldmVudEFnZ3JlZ2F0b3IgPSBuZXcgZXZlbnRBZ2dyZWdhdG9yXzEuZGVmYXVsdCgpO1xuICAgICAgICB0aGlzLm1lc3NhZ2VIYW5kbGVycyA9IFt0aGlzLmV2ZW50QWdncmVnYXRvci5kaXNwYXRjaEV2ZW50XTtcbiAgICAgICAgX1RyYW5zcG9ydF93aXJlLnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICAvLyBUeXBpbmcgYXMgdW5rbm93biB0byBhdm9pZCBjaXJjdWxhciBkZXBlbmRlbmN5LCBzaG91bGQgbm90IGJlIHVzZWQgZGlyZWN0bHkuXG4gICAgICAgIF9UcmFuc3BvcnRfZmluLnNldCh0aGlzLCB2b2lkIDApO1xuICAgICAgICB0aGlzLmNvbm5lY3RTeW5jID0gKCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgd2lyZSA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1RyYW5zcG9ydF93aXJlLCBcImZcIik7XG4gICAgICAgICAgICB3aXJlLmNvbm5lY3RTeW5jKCk7XG4gICAgICAgIH07XG4gICAgICAgIC8vIFRoaXMgZnVuY3Rpb24gaXMgb25seSB1c2VkIGluIG91ciB0ZXN0cy5cbiAgICAgICAgdGhpcy5nZXRQb3J0ID0gKCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgd2lyZSA9IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1RyYW5zcG9ydF93aXJlLCBcImZcIik7XG4gICAgICAgICAgICByZXR1cm4gd2lyZS5nZXRQb3J0KCk7XG4gICAgICAgIH07XG4gICAgICAgIF9fY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX1RyYW5zcG9ydF93aXJlLCBuZXcgV2lyZVR5cGUodGhpcy5vbm1lc3NhZ2UuYmluZCh0aGlzKSksIFwiZlwiKTtcbiAgICAgICAgdGhpcy5lbnZpcm9ubWVudCA9IGVudmlyb25tZW50O1xuICAgICAgICB0aGlzLnNlbmRSYXcgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9UcmFuc3BvcnRfd2lyZSwgXCJmXCIpLnNlbmQuYmluZChfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9UcmFuc3BvcnRfd2lyZSwgXCJmXCIpKTtcbiAgICAgICAgdGhpcy5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKHRoaXMuaGFuZGxlTWVzc2FnZS5iaW5kKHRoaXMpKTtcbiAgICAgICAgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfVHJhbnNwb3J0X3dpcmUsIFwiZlwiKS5vbignZGlzY29ubmVjdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgZm9yIChjb25zdCBbLCB7IGhhbmRsZU5hY2sgfV0gb2YgdGhpcy53aXJlTGlzdGVuZXJzKSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlTmFjayh7IHJlYXNvbjogJ1JlbW90ZSBjb25uZWN0aW9uIGhhcyBjbG9zZWQnIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy53aXJlTGlzdGVuZXJzLmNsZWFyKCk7XG4gICAgICAgICAgICB0aGlzLmVtaXQoJ2Rpc2Nvbm5lY3RlZCcpO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgeyB1dWlkLCBuYW1lIH0gPSBjb25maWc7XG4gICAgICAgIGNvbnN0IGVudGl0eVR5cGUgPSB0aGlzLmVudmlyb25tZW50LmdldEN1cnJlbnRFbnRpdHlUeXBlKCk7XG4gICAgICAgIHRoaXMubWUgPSAoMCwgbWVfMSQxLmdldEJhc2VNZSkoZW50aXR5VHlwZSwgdXVpZCwgbmFtZSk7XG4gICAgfVxuICAgIGdldEZpbigpIHtcbiAgICAgICAgaWYgKCFfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9UcmFuc3BvcnRfZmluLCBcImZcIikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gRmluIG9iamVjdCByZWdpc3RlcmVkIGZvciB0aGlzIHRyYW5zcG9ydCcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9UcmFuc3BvcnRfZmluLCBcImZcIik7XG4gICAgfVxuICAgIHJlZ2lzdGVyRmluKF9maW4pIHtcbiAgICAgICAgaWYgKF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1RyYW5zcG9ydF9maW4sIFwiZlwiKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGaW4gb2JqZWN0IGhhcyBhbHJlYWR5IGJlZW4gcmVnaXN0ZXJlZCBmb3IgdGhpcyB0cmFuc3BvcnQnKTtcbiAgICAgICAgfVxuICAgICAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9UcmFuc3BvcnRfZmluLCBfZmluLCBcImZcIik7XG4gICAgfVxuICAgIHNodXRkb3duKCkge1xuICAgICAgICBjb25zdCB3aXJlID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfVHJhbnNwb3J0X3dpcmUsIFwiZlwiKTtcbiAgICAgICAgcmV0dXJuIHdpcmUuc2h1dGRvd24oKTtcbiAgICB9XG4gICAgYXN5bmMgY29ubmVjdChjb25maWcpIHtcbiAgICAgICAgaWYgKCgwLCB3aXJlXzEuaXNDb25maWdXaXRoUmVjZWl2ZXIpKGNvbmZpZykpIHtcbiAgICAgICAgICAgIGF3YWl0IF9fY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX1RyYW5zcG9ydF93aXJlLCBcImZcIikuY29ubmVjdChjb25maWcucmVjZWl2ZXIpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYXV0aG9yaXplKGNvbmZpZyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCgwLCB3aXJlXzEuaXNSZW1vdGVDb25maWcpKGNvbmZpZykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbm5lY3RSZW1vdGUoY29uZmlnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKDAsIHdpcmVfMS5pc0V4aXN0aW5nQ29ubmVjdENvbmZpZykoY29uZmlnKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdEJ5UG9ydChjb25maWcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgoMCwgd2lyZV8xLmlzTmV3Q29ubmVjdENvbmZpZykoY29uZmlnKSkge1xuICAgICAgICAgICAgY29uc3QgcG9ydCA9IGF3YWl0IHRoaXMuZW52aXJvbm1lbnQucmV0cmlldmVQb3J0KGNvbmZpZyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25uZWN0QnlQb3J0KHsgLi4uY29uZmlnLCBhZGRyZXNzOiBgd3M6Ly9sb2NhbGhvc3Q6JHtwb3J0fWAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgYXN5bmMgY29ubmVjdFJlbW90ZShjb25maWcpIHtcbiAgICAgICAgYXdhaXQgX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfVHJhbnNwb3J0X3dpcmUsIFwiZlwiKS5jb25uZWN0KG5ldyAodGhpcy5lbnZpcm9ubWVudC5nZXRXc0NvbnN0cnVjdG9yKCkpKGNvbmZpZy5hZGRyZXNzKSk7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGhvcml6ZShjb25maWcpO1xuICAgIH1cbiAgICBhc3luYyBjb25uZWN0QnlQb3J0KGNvbmZpZykge1xuICAgICAgICBjb25zdCB7IGFkZHJlc3MsIHV1aWQgfSA9IGNvbmZpZztcbiAgICAgICAgY29uc3QgcmVxQXV0aFBheWxvYWQgPSB7IC4uLmNvbmZpZywgdHlwZTogJ2ZpbGUtdG9rZW4nIH07XG4gICAgICAgIGNvbnN0IHdpcmUgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9UcmFuc3BvcnRfd2lyZSwgXCJmXCIpO1xuICAgICAgICBhd2FpdCB3aXJlLmNvbm5lY3QobmV3ICh0aGlzLmVudmlyb25tZW50LmdldFdzQ29uc3RydWN0b3IoKSkoY29uZmlnLmFkZHJlc3MpKTtcbiAgICAgICAgY29uc3QgcmVxdWVzdEV4dEF1dGhSZXQgPSBhd2FpdCB0aGlzLnNlbmRBY3Rpb24oJ3JlcXVlc3QtZXh0ZXJuYWwtYXV0aG9yaXphdGlvbicsIHtcbiAgICAgICAgICAgIHV1aWQsXG4gICAgICAgICAgICB0eXBlOiAnZmlsZS10b2tlbidcbiAgICAgICAgfSwgdHJ1ZSk7XG4gICAgICAgIGlmIChyZXF1ZXN0RXh0QXV0aFJldC5hY3Rpb24gIT09ICdleHRlcm5hbC1hdXRob3JpemF0aW9uLXJlc3BvbnNlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IHRyYW5zcG9ydF9lcnJvcnNfMS5VbmV4cGVjdGVkQWN0aW9uRXJyb3IocmVxdWVzdEV4dEF1dGhSZXQuYWN0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLmVudmlyb25tZW50LndyaXRlVG9rZW4ocmVxdWVzdEV4dEF1dGhSZXQucGF5bG9hZC5maWxlLCByZXF1ZXN0RXh0QXV0aFJldC5wYXlsb2FkLnRva2VuKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aG9yaXplKHJlcUF1dGhQYXlsb2FkKTtcbiAgICB9XG4gICAgYXN5bmMgYXV0aG9yaXplKHJlcUF1dGhQYXlsb2FkKSB7XG4gICAgICAgIGNvbnN0IHJlcXVlc3RBdXRoUmV0ID0gYXdhaXQgdGhpcy5zZW5kQWN0aW9uKCdyZXF1ZXN0LWF1dGhvcml6YXRpb24nLCByZXFBdXRoUGF5bG9hZCwgdHJ1ZSk7XG4gICAgICAgIGlmIChyZXF1ZXN0QXV0aFJldC5hY3Rpb24gIT09ICdhdXRob3JpemF0aW9uLXJlc3BvbnNlJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IHRyYW5zcG9ydF9lcnJvcnNfMS5VbmV4cGVjdGVkQWN0aW9uRXJyb3IocmVxdWVzdEF1dGhSZXQuYWN0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChyZXF1ZXN0QXV0aFJldC5wYXlsb2FkLnN1Y2Nlc3MgIT09IHRydWUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyB0cmFuc3BvcnRfZXJyb3JzXzEuUnVudGltZUVycm9yKHJlcXVlc3RBdXRoUmV0LnBheWxvYWQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHNlbmRBY3Rpb24oYWN0aW9uLCBwYXlsb2FkID0ge30sIHVuY29ycmVsYXRlZCA9IGZhbHNlXG4gICAgLy8gc3BlY2lhbFJlc3BvbnNlIHR5cGUgaXMgb25seSB1c2VkIGZvciAncmVxdWVzdEF1dGhvcml6YXRpb24nXG4gICAgKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgICAgICAgbGV0IGNhbmNlbCA9ICgpID0+IHsgfTtcbiAgICAgICAgLy8gV2Ugd2FudCB0aGUgY2FsbHNpdGUgZnJvbSB0aGUgY2FsbGVyIG9mIHRoaXMgZnVuY3Rpb24sIG5vdCBmcm9tIGhlcmUuXG4gICAgICAgIGNvbnN0IGNhbGxTaXRlcyA9IHRyYW5zcG9ydF9lcnJvcnNfMS5SdW50aW1lRXJyb3IuZ2V0Q2FsbFNpdGUoMSk7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2VJZCA9IHRoaXMuZW52aXJvbm1lbnQuZ2V0TmV4dE1lc3NhZ2VJZCgpO1xuICAgICAgICBjb25zdCBwcm9tID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY2FuY2VsID0gcmVqZWN0O1xuICAgICAgICAgICAgY29uc3QgbXNnID0ge1xuICAgICAgICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICAgICAgICBwYXlsb2FkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2VJZFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHdpcmUgPSBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9UcmFuc3BvcnRfd2lyZSwgXCJmXCIpO1xuICAgICAgICAgICAgdGhpcy5hZGRXaXJlTGlzdGVuZXIobWVzc2FnZUlkLCByZXNvbHZlLCAocGF5bG9hZCkgPT4gdGhpcy5uYWNrSGFuZGxlcihwYXlsb2FkLCByZWplY3QsIGNhbGxTaXRlcyksIHVuY29ycmVsYXRlZCk7XG4gICAgICAgICAgICByZXR1cm4gd2lyZS5zZW5kKG1zZykuY2F0Y2gocmVqZWN0KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHByb20sIHsgY2FuY2VsLCBtZXNzYWdlSWQgfSk7XG4gICAgfVxuICAgIG5hY2tIYW5kbGVyKHBheWxvYWRPck1lc3NhZ2UsIHJlamVjdCwgY2FsbFNpdGVzKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcGF5bG9hZE9yTWVzc2FnZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIC8vIE5PVEU6IHRoaXMgaXMgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHRvIHN1cHBvcnQgcGxhaW4gc3RyaW5nIHJlamVjdGlvbnNcbiAgICAgICAgICAgIHJlamVjdChwYXlsb2FkT3JNZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlamVjdChuZXcgdHJhbnNwb3J0X2Vycm9yc18xLlJ1bnRpbWVFcnJvcihwYXlsb2FkT3JNZXNzYWdlLCBjYWxsU2l0ZXMpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmZXJyeUFjdGlvbihvcmlnRGF0YSkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgaWQgPSB0aGlzLmVudmlyb25tZW50LmdldE5leHRNZXNzYWdlSWQoKTtcbiAgICAgICAgICAgIG9yaWdEYXRhLm1lc3NhZ2VJZCA9IGlkO1xuICAgICAgICAgICAgY29uc3QgcmVzb2x2ZXIgPSAoZGF0YSkgPT4ge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoZGF0YS5wYXlsb2FkKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCB3aXJlID0gX19jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfVHJhbnNwb3J0X3dpcmUsIFwiZlwiKTtcbiAgICAgICAgICAgIHJldHVybiB3aXJlXG4gICAgICAgICAgICAgICAgLnNlbmQob3JpZ0RhdGEpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gdGhpcy5hZGRXaXJlTGlzdGVuZXIoaWQsIHJlc29sdmVyLCAocGF5bG9hZCkgPT4gdGhpcy5uYWNrSGFuZGxlcihwYXlsb2FkLCByZWplY3QpLCBmYWxzZSkpXG4gICAgICAgICAgICAgICAgLmNhdGNoKHJlamVjdCk7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKGhhbmRsZXIpIHtcbiAgICAgICAgdGhpcy5tZXNzYWdlSGFuZGxlcnMucHVzaChoYW5kbGVyKTtcbiAgICB9XG4gICAgYWRkV2lyZUxpc3RlbmVyKGlkLCByZXNvbHZlLCBoYW5kbGVOYWNrLCB1bmNvcnJlbGF0ZWQpIHtcbiAgICAgICAgaWYgKHVuY29ycmVsYXRlZCkge1xuICAgICAgICAgICAgdGhpcy51bmNvcnJlbGF0ZWRMaXN0ZW5lciA9IHJlc29sdmU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAodGhpcy53aXJlTGlzdGVuZXJzLmhhcyhpZCkpIHtcbiAgICAgICAgICAgIGhhbmRsZU5hY2soe1xuICAgICAgICAgICAgICAgIHJlYXNvbjogJ0R1cGxpY2F0ZSBoYW5kbGVyIGlkJyxcbiAgICAgICAgICAgICAgICBlcnJvcjogKDAsIGVycm9yc18xLmVycm9yVG9QT0pPKShuZXcgdHJhbnNwb3J0X2Vycm9yc18xLkR1cGxpY2F0ZUNvcnJlbGF0aW9uRXJyb3IoU3RyaW5nKGlkKSkpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMud2lyZUxpc3RlbmVycy5zZXQoaWQsIHsgcmVzb2x2ZSwgaGFuZGxlTmFjayB9KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBUaW1lb3V0IGFuZCByZWplY3QoKT9cbiAgICB9XG4gICAgLy8gVGhpcyBtZXRob2QgZXhlY3V0ZXMgbWVzc2FnZSBoYW5kbGVycyB1bnRpbCB0aGUgX29uZV8gdGhhdCBoYW5kbGVzIHRoZSBtZXNzYWdlIChyZXR1cm5zIHRydXRoeSkgaGFzIHJ1blxuICAgIG9ubWVzc2FnZShkYXRhKSB7XG4gICAgICAgIGZvciAoY29uc3QgaCBvZiB0aGlzLm1lc3NhZ2VIYW5kbGVycykge1xuICAgICAgICAgICAgaC5jYWxsKG51bGwsIGRhdGEpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGhhbmRsZU1lc3NhZ2UoZGF0YSkge1xuICAgICAgICBjb25zdCBpZCA9IGRhdGEuY29ycmVsYXRpb25JZCB8fCBOYU47XG4gICAgICAgIGlmICghKCdjb3JyZWxhdGlvbklkJyBpbiBkYXRhKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMudW5jb3JyZWxhdGVkTGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnVuY29ycmVsYXRlZExpc3RlbmVyLmNhbGwobnVsbCwgZGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnVuY29ycmVsYXRlZExpc3RlbmVyID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIGVtcHR5IGJsb2NrXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCF0aGlzLndpcmVMaXN0ZW5lcnMuaGFzKGlkKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy8gV2UganVzdCBjaGVja2VkIGZvciBleGlzdGVuY2UgYWJvdmVcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICAgICAgICBjb25zdCB7IHJlc29sdmUsIGhhbmRsZU5hY2sgfSA9IHRoaXMud2lyZUxpc3RlbmVycy5nZXQoaWQpO1xuICAgICAgICAgICAgaWYgKGRhdGEuYWN0aW9uICE9PSAnYWNrJykge1xuICAgICAgICAgICAgICAgIGhhbmRsZU5hY2soeyByZWFzb246ICdEaWQgbm90IHJlY2VpdmUgYWNrIGFjdGlvbicsIGVycm9yOiAoMCwgZXJyb3JzXzEuZXJyb3JUb1BPSk8pKG5ldyB0cmFuc3BvcnRfZXJyb3JzXzEuTm9BY2tFcnJvcihkYXRhLmFjdGlvbikpIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoISgncGF5bG9hZCcgaW4gZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAvLyBJJ20gbm90IHN1cmUgd2hlbiB0aGlzIGNvZGUgd291bGQgYWN0dWFsbHkgcnVuLCBidXQgcGFzc2luZyBpbiBzb21ldGhpbmcgdGhhdCBkb2Vlc24ndCBoYXZlIGEgcmVhc29uIHRvIHRoZSBydW50aW1lZXJyb3IgY29uc3RydWN0b3Igd2lsbCBub3QgZW5kIHdlbGwuXG4gICAgICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS5yZWFzb24gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZU5hY2soZGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ1JlY2VpdmVkIGludmFsaWQgcmVzcG9uc2UgZnJvbSBjb3JlJywgZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZU5hY2soeyByZWFzb246ICdpbnZhbGlkIHJlc3BvbnNlIHNoYXBlJyB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICghZGF0YS5wYXlsb2FkLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICBoYW5kbGVOYWNrKGRhdGEucGF5bG9hZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXNvbHZlLmNhbGwobnVsbCwgZGF0YSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLndpcmVMaXN0ZW5lcnMuZGVsZXRlKGlkKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59XG5UcmFuc3BvcnRfMSA9IHRyYW5zcG9ydC5UcmFuc3BvcnQgPSBUcmFuc3BvcnQ7XG5fVHJhbnNwb3J0X3dpcmUgPSBuZXcgV2Vha01hcCgpLCBfVHJhbnNwb3J0X2ZpbiA9IG5ldyBXZWFrTWFwKCk7XG5cbnZhciBtb2NrRW52aXJvbm1lbnQgPSB7fTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KG1vY2tFbnZpcm9ubWVudCwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgTW9ja0Vudmlyb25tZW50XzEgPSBtb2NrRW52aXJvbm1lbnQuTW9ja0Vudmlyb25tZW50ID0gdm9pZCAwO1xuY29uc3QgbWVfMSA9IG1lO1xuY2xhc3MgTW9ja0Vudmlyb25tZW50IHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy50eXBlID0gJ290aGVyJztcbiAgICAgICAgdGhpcy5jaGlsZFZpZXdzID0gdHJ1ZTtcbiAgICB9XG4gICAgZ2V0QWRhcHRlclZlcnNpb25TeW5jKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGFzeW5jIGdldEludGVyb3BJbmZvKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGdldERlZmF1bHRDaGFubmVsT3B0aW9ucygpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICBnZXRSdGNQZWVyKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGxheW91dEFsbG93ZWRJbkNvbnRleHQoX2Zpbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGluaXRMYXlvdXRNYW5hZ2VyKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGFwcGx5TGF5b3V0U25hcHNob3QoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgYXN5bmMgY3JlYXRlTGF5b3V0KCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGFzeW5jIGRlc3Ryb3lMYXlvdXQoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgYXN5bmMgcmVzb2x2ZUxheW91dCgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICBpbml0UGxhdGZvcm0oKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgb2JzZXJ2ZUJvdW5kcygpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICB3cml0ZVRva2VuKHBhdGgsIHRva2VuKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgcmV0cmlldmVQb3J0KGNvbmZpZykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGdldE5leHRNZXNzYWdlSWQoKSB7XG4gICAgICAgIHJldHVybiBgbW9jay1tZXNzYWdlLWlkLSR7TWF0aC5yYW5kb20oKX1gO1xuICAgIH1cbiAgICBnZXRSYW5kb21JZCgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICBjcmVhdGVDaGlsZENvbnRlbnQob3B0aW9ucykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGdldFdlYldpbmRvdyhpZGVudGl0eSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGdldEN1cnJlbnRFbnRpdHlJZGVudGl0eSgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICBnZXRDdXJyZW50RW50aXR5VHlwZSgpIHtcbiAgICAgICAgcmV0dXJuICd1bmtub3duJztcbiAgICB9XG4gICAgcmFpc2VFdmVudChldmVudE5hbWUsIGV2ZW50QXJncykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVfMS5lbnZpcm9ubWVudFVuc3VwcG9ydGVkTWVzc2FnZSk7XG4gICAgfVxuICAgIGdldFVybCgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lXzEuZW52aXJvbm1lbnRVbnN1cHBvcnRlZE1lc3NhZ2UpO1xuICAgIH1cbiAgICB3aGVuUmVhZHkoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZV8xLmVudmlyb25tZW50VW5zdXBwb3J0ZWRNZXNzYWdlKTtcbiAgICB9XG4gICAgZ2V0V3NDb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdNZXRob2Qgbm90IGltcGxlbWVudGVkLicpO1xuICAgIH1cbn1cbk1vY2tFbnZpcm9ubWVudF8xID0gbW9ja0Vudmlyb25tZW50Lk1vY2tFbnZpcm9ubWVudCA9IE1vY2tFbnZpcm9ubWVudDtcblxudmFyIG1vY2tXaXJlID0ge307XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2NrV2lyZSwgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgTW9ja1dpcmVfMSA9IG1vY2tXaXJlLk1vY2tXaXJlID0gdm9pZCAwO1xuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG5jb25zdCBldmVudHNfMSA9IHJlcXVpcmUkJDA7XG5jbGFzcyBNb2NrV2lyZSBleHRlbmRzIGV2ZW50c18xLkV2ZW50RW1pdHRlciB7XG4gICAgY29ubmVjdCgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgYXJlIG5vdCBydW5uaW5nIGluIE9wZW5GaW4uJyk7XG4gICAgfVxuICAgIGNvbm5lY3RTeW5jKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBhcmUgbm90IHJ1bm5pbmcgaW4gT3BlbkZpbi4nKTtcbiAgICB9XG4gICAgc2VuZChkYXRhKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IGFyZSBub3QgcnVubmluZyBpbiBPcGVuRmluLicpO1xuICAgIH1cbiAgICBzaHV0ZG93bigpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgYXJlIG5vdCBydW5uaW5nIGluIE9wZW5GaW4uJyk7XG4gICAgfVxuICAgIGdldFBvcnQoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVGhpcyB0cmFuc3BvcnQgaGFzIG5vIHBvcnQnKTtcbiAgICB9XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZWxlc3MtY29uc3RydWN0b3JcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICB9XG59XG5Nb2NrV2lyZV8xID0gbW9ja1dpcmUuTW9ja1dpcmUgPSBNb2NrV2lyZTtcblxuY29uc3QgZmluJDEgPSAoKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdz8uZmluKSB8fFxuICAgICgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGVudmlyb25tZW50ID0gbmV3IE1vY2tFbnZpcm9ubWVudF8xKCk7XG4gICAgICAgIGNvbnN0IHRyYW5zcG9ydCA9IG5ldyBUcmFuc3BvcnRfMShNb2NrV2lyZV8xLCBlbnZpcm9ubWVudCwge1xuICAgICAgICAgICAgdXVpZDogJycsXG4gICAgICAgICAgICBuYW1lOiAnJ1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG5ldyBGaW5fMSh0cmFuc3BvcnQpO1xuICAgIH0pKCkpO1xuXG5leHBvcnRzLk9wZW5GaW4gPSBPcGVuRmluJDE7XG5leHBvcnRzLmRlZmF1bHQgPSBPcGVuRmluJDE7XG5leHBvcnRzLmZpbiA9IGZpbiQxO1xuIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbid1c2Ugc3RyaWN0JztcblxudmFyIFIgPSB0eXBlb2YgUmVmbGVjdCA9PT0gJ29iamVjdCcgPyBSZWZsZWN0IDogbnVsbFxudmFyIFJlZmxlY3RBcHBseSA9IFIgJiYgdHlwZW9mIFIuYXBwbHkgPT09ICdmdW5jdGlvbidcbiAgPyBSLmFwcGx5XG4gIDogZnVuY3Rpb24gUmVmbGVjdEFwcGx5KHRhcmdldCwgcmVjZWl2ZXIsIGFyZ3MpIHtcbiAgICByZXR1cm4gRnVuY3Rpb24ucHJvdG90eXBlLmFwcGx5LmNhbGwodGFyZ2V0LCByZWNlaXZlciwgYXJncyk7XG4gIH1cblxudmFyIFJlZmxlY3RPd25LZXlzXG5pZiAoUiAmJiB0eXBlb2YgUi5vd25LZXlzID09PSAnZnVuY3Rpb24nKSB7XG4gIFJlZmxlY3RPd25LZXlzID0gUi5vd25LZXlzXG59IGVsc2UgaWYgKE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMpIHtcbiAgUmVmbGVjdE93bktleXMgPSBmdW5jdGlvbiBSZWZsZWN0T3duS2V5cyh0YXJnZXQpIHtcbiAgICByZXR1cm4gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGFyZ2V0KVxuICAgICAgLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHRhcmdldCkpO1xuICB9O1xufSBlbHNlIHtcbiAgUmVmbGVjdE93bktleXMgPSBmdW5jdGlvbiBSZWZsZWN0T3duS2V5cyh0YXJnZXQpIHtcbiAgICByZXR1cm4gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGFyZ2V0KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gUHJvY2Vzc0VtaXRXYXJuaW5nKHdhcm5pbmcpIHtcbiAgaWYgKGNvbnNvbGUgJiYgY29uc29sZS53YXJuKSBjb25zb2xlLndhcm4od2FybmluZyk7XG59XG5cbnZhciBOdW1iZXJJc05hTiA9IE51bWJlci5pc05hTiB8fCBmdW5jdGlvbiBOdW1iZXJJc05hTih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgIT09IHZhbHVlO1xufVxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gIEV2ZW50RW1pdHRlci5pbml0LmNhbGwodGhpcyk7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbm1vZHVsZS5leHBvcnRzLm9uY2UgPSBvbmNlO1xuXG4vLyBCYWNrd2FyZHMtY29tcGF0IHdpdGggbm9kZSAwLjEwLnhcbkV2ZW50RW1pdHRlci5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX2V2ZW50cyA9IHVuZGVmaW5lZDtcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX2V2ZW50c0NvdW50ID0gMDtcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX21heExpc3RlbmVycyA9IHVuZGVmaW5lZDtcblxuLy8gQnkgZGVmYXVsdCBFdmVudEVtaXR0ZXJzIHdpbGwgcHJpbnQgYSB3YXJuaW5nIGlmIG1vcmUgdGhhbiAxMCBsaXN0ZW5lcnMgYXJlXG4vLyBhZGRlZCB0byBpdC4gVGhpcyBpcyBhIHVzZWZ1bCBkZWZhdWx0IHdoaWNoIGhlbHBzIGZpbmRpbmcgbWVtb3J5IGxlYWtzLlxudmFyIGRlZmF1bHRNYXhMaXN0ZW5lcnMgPSAxMDtcblxuZnVuY3Rpb24gY2hlY2tMaXN0ZW5lcihsaXN0ZW5lcikge1xuICBpZiAodHlwZW9mIGxpc3RlbmVyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVGhlIFwibGlzdGVuZXJcIiBhcmd1bWVudCBtdXN0IGJlIG9mIHR5cGUgRnVuY3Rpb24uIFJlY2VpdmVkIHR5cGUgJyArIHR5cGVvZiBsaXN0ZW5lcik7XG4gIH1cbn1cblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KEV2ZW50RW1pdHRlciwgJ2RlZmF1bHRNYXhMaXN0ZW5lcnMnLCB7XG4gIGVudW1lcmFibGU6IHRydWUsXG4gIGdldDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIH0sXG4gIHNldDogZnVuY3Rpb24oYXJnKSB7XG4gICAgaWYgKHR5cGVvZiBhcmcgIT09ICdudW1iZXInIHx8IGFyZyA8IDAgfHwgTnVtYmVySXNOYU4oYXJnKSkge1xuICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RoZSB2YWx1ZSBvZiBcImRlZmF1bHRNYXhMaXN0ZW5lcnNcIiBpcyBvdXQgb2YgcmFuZ2UuIEl0IG11c3QgYmUgYSBub24tbmVnYXRpdmUgbnVtYmVyLiBSZWNlaXZlZCAnICsgYXJnICsgJy4nKTtcbiAgICB9XG4gICAgZGVmYXVsdE1heExpc3RlbmVycyA9IGFyZztcbiAgfVxufSk7XG5cbkV2ZW50RW1pdHRlci5pbml0ID0gZnVuY3Rpb24oKSB7XG5cbiAgaWYgKHRoaXMuX2V2ZW50cyA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICB0aGlzLl9ldmVudHMgPT09IE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKS5fZXZlbnRzKSB7XG4gICAgdGhpcy5fZXZlbnRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICB0aGlzLl9ldmVudHNDb3VudCA9IDA7XG4gIH1cblxuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSB0aGlzLl9tYXhMaXN0ZW5lcnMgfHwgdW5kZWZpbmVkO1xufTtcblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0TWF4TGlzdGVuZXJzKG4pIHtcbiAgaWYgKHR5cGVvZiBuICE9PSAnbnVtYmVyJyB8fCBuIDwgMCB8fCBOdW1iZXJJc05hTihuKSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdUaGUgdmFsdWUgb2YgXCJuXCIgaXMgb3V0IG9mIHJhbmdlLiBJdCBtdXN0IGJlIGEgbm9uLW5lZ2F0aXZlIG51bWJlci4gUmVjZWl2ZWQgJyArIG4gKyAnLicpO1xuICB9XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gX2dldE1heExpc3RlbmVycyh0aGF0KSB7XG4gIGlmICh0aGF0Ll9tYXhMaXN0ZW5lcnMgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gIHJldHVybiB0aGF0Ll9tYXhMaXN0ZW5lcnM7XG59XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZ2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TWF4TGlzdGVuZXJzKCkge1xuICByZXR1cm4gX2dldE1heExpc3RlbmVycyh0aGlzKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQodHlwZSkge1xuICB2YXIgYXJncyA9IFtdO1xuICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgYXJncy5wdXNoKGFyZ3VtZW50c1tpXSk7XG4gIHZhciBkb0Vycm9yID0gKHR5cGUgPT09ICdlcnJvcicpO1xuXG4gIHZhciBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gIGlmIChldmVudHMgIT09IHVuZGVmaW5lZClcbiAgICBkb0Vycm9yID0gKGRvRXJyb3IgJiYgZXZlbnRzLmVycm9yID09PSB1bmRlZmluZWQpO1xuICBlbHNlIGlmICghZG9FcnJvcilcbiAgICByZXR1cm4gZmFsc2U7XG5cbiAgLy8gSWYgdGhlcmUgaXMgbm8gJ2Vycm9yJyBldmVudCBsaXN0ZW5lciB0aGVuIHRocm93LlxuICBpZiAoZG9FcnJvcikge1xuICAgIHZhciBlcjtcbiAgICBpZiAoYXJncy5sZW5ndGggPiAwKVxuICAgICAgZXIgPSBhcmdzWzBdO1xuICAgIGlmIChlciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAvLyBOb3RlOiBUaGUgY29tbWVudHMgb24gdGhlIGB0aHJvd2AgbGluZXMgYXJlIGludGVudGlvbmFsLCB0aGV5IHNob3dcbiAgICAgIC8vIHVwIGluIE5vZGUncyBvdXRwdXQgaWYgdGhpcyByZXN1bHRzIGluIGFuIHVuaGFuZGxlZCBleGNlcHRpb24uXG4gICAgICB0aHJvdyBlcjsgLy8gVW5oYW5kbGVkICdlcnJvcicgZXZlbnRcbiAgICB9XG4gICAgLy8gQXQgbGVhc3QgZ2l2ZSBzb21lIGtpbmQgb2YgY29udGV4dCB0byB0aGUgdXNlclxuICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuaGFuZGxlZCBlcnJvci4nICsgKGVyID8gJyAoJyArIGVyLm1lc3NhZ2UgKyAnKScgOiAnJykpO1xuICAgIGVyci5jb250ZXh0ID0gZXI7XG4gICAgdGhyb3cgZXJyOyAvLyBVbmhhbmRsZWQgJ2Vycm9yJyBldmVudFxuICB9XG5cbiAgdmFyIGhhbmRsZXIgPSBldmVudHNbdHlwZV07XG5cbiAgaWYgKGhhbmRsZXIgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gZmFsc2U7XG5cbiAgaWYgKHR5cGVvZiBoYW5kbGVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgUmVmbGVjdEFwcGx5KGhhbmRsZXIsIHRoaXMsIGFyZ3MpO1xuICB9IGVsc2Uge1xuICAgIHZhciBsZW4gPSBoYW5kbGVyLmxlbmd0aDtcbiAgICB2YXIgbGlzdGVuZXJzID0gYXJyYXlDbG9uZShoYW5kbGVyLCBsZW4pO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpXG4gICAgICBSZWZsZWN0QXBwbHkobGlzdGVuZXJzW2ldLCB0aGlzLCBhcmdzKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuZnVuY3Rpb24gX2FkZExpc3RlbmVyKHRhcmdldCwgdHlwZSwgbGlzdGVuZXIsIHByZXBlbmQpIHtcbiAgdmFyIG07XG4gIHZhciBldmVudHM7XG4gIHZhciBleGlzdGluZztcblxuICBjaGVja0xpc3RlbmVyKGxpc3RlbmVyKTtcblxuICBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcbiAgaWYgKGV2ZW50cyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgZXZlbnRzID0gdGFyZ2V0Ll9ldmVudHMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgIHRhcmdldC5fZXZlbnRzQ291bnQgPSAwO1xuICB9IGVsc2Uge1xuICAgIC8vIFRvIGF2b2lkIHJlY3Vyc2lvbiBpbiB0aGUgY2FzZSB0aGF0IHR5cGUgPT09IFwibmV3TGlzdGVuZXJcIiEgQmVmb3JlXG4gICAgLy8gYWRkaW5nIGl0IHRvIHRoZSBsaXN0ZW5lcnMsIGZpcnN0IGVtaXQgXCJuZXdMaXN0ZW5lclwiLlxuICAgIGlmIChldmVudHMubmV3TGlzdGVuZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGFyZ2V0LmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICAgICAgICAgIGxpc3RlbmVyLmxpc3RlbmVyID8gbGlzdGVuZXIubGlzdGVuZXIgOiBsaXN0ZW5lcik7XG5cbiAgICAgIC8vIFJlLWFzc2lnbiBgZXZlbnRzYCBiZWNhdXNlIGEgbmV3TGlzdGVuZXIgaGFuZGxlciBjb3VsZCBoYXZlIGNhdXNlZCB0aGVcbiAgICAgIC8vIHRoaXMuX2V2ZW50cyB0byBiZSBhc3NpZ25lZCB0byBhIG5ldyBvYmplY3RcbiAgICAgIGV2ZW50cyA9IHRhcmdldC5fZXZlbnRzO1xuICAgIH1cbiAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXTtcbiAgfVxuXG4gIGlmIChleGlzdGluZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgZXhpc3RpbmcgPSBldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgICArK3RhcmdldC5fZXZlbnRzQ291bnQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBleGlzdGluZyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgICBleGlzdGluZyA9IGV2ZW50c1t0eXBlXSA9XG4gICAgICAgIHByZXBlbmQgPyBbbGlzdGVuZXIsIGV4aXN0aW5nXSA6IFtleGlzdGluZywgbGlzdGVuZXJdO1xuICAgICAgLy8gSWYgd2UndmUgYWxyZWFkeSBnb3QgYW4gYXJyYXksIGp1c3QgYXBwZW5kLlxuICAgIH0gZWxzZSBpZiAocHJlcGVuZCkge1xuICAgICAgZXhpc3RpbmcudW5zaGlmdChsaXN0ZW5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV4aXN0aW5nLnB1c2gobGlzdGVuZXIpO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGZvciBsaXN0ZW5lciBsZWFrXG4gICAgbSA9IF9nZXRNYXhMaXN0ZW5lcnModGFyZ2V0KTtcbiAgICBpZiAobSA+IDAgJiYgZXhpc3RpbmcubGVuZ3RoID4gbSAmJiAhZXhpc3Rpbmcud2FybmVkKSB7XG4gICAgICBleGlzdGluZy53YXJuZWQgPSB0cnVlO1xuICAgICAgLy8gTm8gZXJyb3IgY29kZSBmb3IgdGhpcyBzaW5jZSBpdCBpcyBhIFdhcm5pbmdcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1yZXN0cmljdGVkLXN5bnRheFxuICAgICAgdmFyIHcgPSBuZXcgRXJyb3IoJ1Bvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgbGVhayBkZXRlY3RlZC4gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nLmxlbmd0aCArICcgJyArIFN0cmluZyh0eXBlKSArICcgbGlzdGVuZXJzICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAnYWRkZWQuIFVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAnaW5jcmVhc2UgbGltaXQnKTtcbiAgICAgIHcubmFtZSA9ICdNYXhMaXN0ZW5lcnNFeGNlZWRlZFdhcm5pbmcnO1xuICAgICAgdy5lbWl0dGVyID0gdGFyZ2V0O1xuICAgICAgdy50eXBlID0gdHlwZTtcbiAgICAgIHcuY291bnQgPSBleGlzdGluZy5sZW5ndGg7XG4gICAgICBQcm9jZXNzRW1pdFdhcm5pbmcodyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHJldHVybiBfYWRkTGlzdGVuZXIodGhpcywgdHlwZSwgbGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgICByZXR1cm4gX2FkZExpc3RlbmVyKHRoaXMsIHR5cGUsIGxpc3RlbmVyLCB0cnVlKTtcbiAgICB9O1xuXG5mdW5jdGlvbiBvbmNlV3JhcHBlcigpIHtcbiAgaWYgKCF0aGlzLmZpcmVkKSB7XG4gICAgdGhpcy50YXJnZXQucmVtb3ZlTGlzdGVuZXIodGhpcy50eXBlLCB0aGlzLndyYXBGbik7XG4gICAgdGhpcy5maXJlZCA9IHRydWU7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApXG4gICAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5jYWxsKHRoaXMudGFyZ2V0KTtcbiAgICByZXR1cm4gdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLnRhcmdldCwgYXJndW1lbnRzKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBfb25jZVdyYXAodGFyZ2V0LCB0eXBlLCBsaXN0ZW5lcikge1xuICB2YXIgc3RhdGUgPSB7IGZpcmVkOiBmYWxzZSwgd3JhcEZuOiB1bmRlZmluZWQsIHRhcmdldDogdGFyZ2V0LCB0eXBlOiB0eXBlLCBsaXN0ZW5lcjogbGlzdGVuZXIgfTtcbiAgdmFyIHdyYXBwZWQgPSBvbmNlV3JhcHBlci5iaW5kKHN0YXRlKTtcbiAgd3JhcHBlZC5saXN0ZW5lciA9IGxpc3RlbmVyO1xuICBzdGF0ZS53cmFwRm4gPSB3cmFwcGVkO1xuICByZXR1cm4gd3JhcHBlZDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gb25jZSh0eXBlLCBsaXN0ZW5lcikge1xuICBjaGVja0xpc3RlbmVyKGxpc3RlbmVyKTtcbiAgdGhpcy5vbih0eXBlLCBfb25jZVdyYXAodGhpcywgdHlwZSwgbGlzdGVuZXIpKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnByZXBlbmRPbmNlTGlzdGVuZXIgPVxuICAgIGZ1bmN0aW9uIHByZXBlbmRPbmNlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIGNoZWNrTGlzdGVuZXIobGlzdGVuZXIpO1xuICAgICAgdGhpcy5wcmVwZW5kTGlzdGVuZXIodHlwZSwgX29uY2VXcmFwKHRoaXMsIHR5cGUsIGxpc3RlbmVyKSk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4vLyBFbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWYgYW5kIG9ubHkgaWYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkLlxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9XG4gICAgZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgIHZhciBsaXN0LCBldmVudHMsIHBvc2l0aW9uLCBpLCBvcmlnaW5hbExpc3RlbmVyO1xuXG4gICAgICBjaGVja0xpc3RlbmVyKGxpc3RlbmVyKTtcblxuICAgICAgZXZlbnRzID0gdGhpcy5fZXZlbnRzO1xuICAgICAgaWYgKGV2ZW50cyA9PT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gdGhpcztcblxuICAgICAgbGlzdCA9IGV2ZW50c1t0eXBlXTtcbiAgICAgIGlmIChsaXN0ID09PSB1bmRlZmluZWQpXG4gICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICBpZiAobGlzdCA9PT0gbGlzdGVuZXIgfHwgbGlzdC5saXN0ZW5lciA9PT0gbGlzdGVuZXIpIHtcbiAgICAgICAgaWYgKC0tdGhpcy5fZXZlbnRzQ291bnQgPT09IDApXG4gICAgICAgICAgdGhpcy5fZXZlbnRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgZGVsZXRlIGV2ZW50c1t0eXBlXTtcbiAgICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3QubGlzdGVuZXIgfHwgbGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBsaXN0ICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHBvc2l0aW9uID0gLTE7XG5cbiAgICAgICAgZm9yIChpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgIGlmIChsaXN0W2ldID09PSBsaXN0ZW5lciB8fCBsaXN0W2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikge1xuICAgICAgICAgICAgb3JpZ2luYWxMaXN0ZW5lciA9IGxpc3RbaV0ubGlzdGVuZXI7XG4gICAgICAgICAgICBwb3NpdGlvbiA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocG9zaXRpb24gPCAwKVxuICAgICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICAgIGlmIChwb3NpdGlvbiA9PT0gMClcbiAgICAgICAgICBsaXN0LnNoaWZ0KCk7XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHNwbGljZU9uZShsaXN0LCBwb3NpdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpXG4gICAgICAgICAgZXZlbnRzW3R5cGVdID0gbGlzdFswXTtcblxuICAgICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIG9yaWdpbmFsTGlzdGVuZXIgfHwgbGlzdGVuZXIpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9mZiA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID1cbiAgICBmdW5jdGlvbiByZW1vdmVBbGxMaXN0ZW5lcnModHlwZSkge1xuICAgICAgdmFyIGxpc3RlbmVycywgZXZlbnRzLCBpO1xuXG4gICAgICBldmVudHMgPSB0aGlzLl9ldmVudHM7XG4gICAgICBpZiAoZXZlbnRzID09PSB1bmRlZmluZWQpXG4gICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICAvLyBub3QgbGlzdGVuaW5nIGZvciByZW1vdmVMaXN0ZW5lciwgbm8gbmVlZCB0byBlbWl0XG4gICAgICBpZiAoZXZlbnRzLnJlbW92ZUxpc3RlbmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB0aGlzLl9ldmVudHMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAgICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgfSBlbHNlIGlmIChldmVudHNbdHlwZV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGlmICgtLXRoaXMuX2V2ZW50c0NvdW50ID09PSAwKVxuICAgICAgICAgICAgdGhpcy5fZXZlbnRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBkZWxldGUgZXZlbnRzW3R5cGVdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICAvLyBlbWl0IHJlbW92ZUxpc3RlbmVyIGZvciBhbGwgbGlzdGVuZXJzIG9uIGFsbCBldmVudHNcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMoZXZlbnRzKTtcbiAgICAgICAgdmFyIGtleTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICBrZXkgPSBrZXlzW2ldO1xuICAgICAgICAgIGlmIChrZXkgPT09ICdyZW1vdmVMaXN0ZW5lcicpIGNvbnRpbnVlO1xuICAgICAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoJ3JlbW92ZUxpc3RlbmVyJyk7XG4gICAgICAgIHRoaXMuX2V2ZW50cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgIHRoaXMuX2V2ZW50c0NvdW50ID0gMDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG5cbiAgICAgIGxpc3RlbmVycyA9IGV2ZW50c1t0eXBlXTtcblxuICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICAgICAgfSBlbHNlIGlmIChsaXN0ZW5lcnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAvLyBMSUZPIG9yZGVyXG4gICAgICAgIGZvciAoaSA9IGxpc3RlbmVycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzW2ldKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG5mdW5jdGlvbiBfbGlzdGVuZXJzKHRhcmdldCwgdHlwZSwgdW53cmFwKSB7XG4gIHZhciBldmVudHMgPSB0YXJnZXQuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzID09PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIFtdO1xuXG4gIHZhciBldmxpc3RlbmVyID0gZXZlbnRzW3R5cGVdO1xuICBpZiAoZXZsaXN0ZW5lciA9PT0gdW5kZWZpbmVkKVxuICAgIHJldHVybiBbXTtcblxuICBpZiAodHlwZW9mIGV2bGlzdGVuZXIgPT09ICdmdW5jdGlvbicpXG4gICAgcmV0dXJuIHVud3JhcCA/IFtldmxpc3RlbmVyLmxpc3RlbmVyIHx8IGV2bGlzdGVuZXJdIDogW2V2bGlzdGVuZXJdO1xuXG4gIHJldHVybiB1bndyYXAgP1xuICAgIHVud3JhcExpc3RlbmVycyhldmxpc3RlbmVyKSA6IGFycmF5Q2xvbmUoZXZsaXN0ZW5lciwgZXZsaXN0ZW5lci5sZW5ndGgpO1xufVxuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uIGxpc3RlbmVycyh0eXBlKSB7XG4gIHJldHVybiBfbGlzdGVuZXJzKHRoaXMsIHR5cGUsIHRydWUpO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yYXdMaXN0ZW5lcnMgPSBmdW5jdGlvbiByYXdMaXN0ZW5lcnModHlwZSkge1xuICByZXR1cm4gX2xpc3RlbmVycyh0aGlzLCB0eXBlLCBmYWxzZSk7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLmxpc3RlbmVyQ291bnQgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZW1pdHRlci5saXN0ZW5lckNvdW50KHR5cGUpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBsaXN0ZW5lckNvdW50LmNhbGwoZW1pdHRlciwgdHlwZSk7XG4gIH1cbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGxpc3RlbmVyQ291bnQ7XG5mdW5jdGlvbiBsaXN0ZW5lckNvdW50KHR5cGUpIHtcbiAgdmFyIGV2ZW50cyA9IHRoaXMuX2V2ZW50cztcblxuICBpZiAoZXZlbnRzICE9PSB1bmRlZmluZWQpIHtcbiAgICB2YXIgZXZsaXN0ZW5lciA9IGV2ZW50c1t0eXBlXTtcblxuICAgIGlmICh0eXBlb2YgZXZsaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfSBlbHNlIGlmIChldmxpc3RlbmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBldmxpc3RlbmVyLmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gMDtcbn1cblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5ldmVudE5hbWVzID0gZnVuY3Rpb24gZXZlbnROYW1lcygpIHtcbiAgcmV0dXJuIHRoaXMuX2V2ZW50c0NvdW50ID4gMCA/IFJlZmxlY3RPd25LZXlzKHRoaXMuX2V2ZW50cykgOiBbXTtcbn07XG5cbmZ1bmN0aW9uIGFycmF5Q2xvbmUoYXJyLCBuKSB7XG4gIHZhciBjb3B5ID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSlcbiAgICBjb3B5W2ldID0gYXJyW2ldO1xuICByZXR1cm4gY29weTtcbn1cblxuZnVuY3Rpb24gc3BsaWNlT25lKGxpc3QsIGluZGV4KSB7XG4gIGZvciAoOyBpbmRleCArIDEgPCBsaXN0Lmxlbmd0aDsgaW5kZXgrKylcbiAgICBsaXN0W2luZGV4XSA9IGxpc3RbaW5kZXggKyAxXTtcbiAgbGlzdC5wb3AoKTtcbn1cblxuZnVuY3Rpb24gdW53cmFwTGlzdGVuZXJzKGFycikge1xuICB2YXIgcmV0ID0gbmV3IEFycmF5KGFyci5sZW5ndGgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHJldC5sZW5ndGg7ICsraSkge1xuICAgIHJldFtpXSA9IGFycltpXS5saXN0ZW5lciB8fCBhcnJbaV07XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gb25jZShlbWl0dGVyLCBuYW1lKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgZnVuY3Rpb24gZXJyb3JMaXN0ZW5lcihlcnIpIHtcbiAgICAgIGVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIobmFtZSwgcmVzb2x2ZXIpO1xuICAgICAgcmVqZWN0KGVycik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVzb2x2ZXIoKSB7XG4gICAgICBpZiAodHlwZW9mIGVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgZW1pdHRlci5yZW1vdmVMaXN0ZW5lcignZXJyb3InLCBlcnJvckxpc3RlbmVyKTtcbiAgICAgIH1cbiAgICAgIHJlc29sdmUoW10uc2xpY2UuY2FsbChhcmd1bWVudHMpKTtcbiAgICB9O1xuXG4gICAgZXZlbnRUYXJnZXRBZ25vc3RpY0FkZExpc3RlbmVyKGVtaXR0ZXIsIG5hbWUsIHJlc29sdmVyLCB7IG9uY2U6IHRydWUgfSk7XG4gICAgaWYgKG5hbWUgIT09ICdlcnJvcicpIHtcbiAgICAgIGFkZEVycm9ySGFuZGxlcklmRXZlbnRFbWl0dGVyKGVtaXR0ZXIsIGVycm9yTGlzdGVuZXIsIHsgb25jZTogdHJ1ZSB9KTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBhZGRFcnJvckhhbmRsZXJJZkV2ZW50RW1pdHRlcihlbWl0dGVyLCBoYW5kbGVyLCBmbGFncykge1xuICBpZiAodHlwZW9mIGVtaXR0ZXIub24gPT09ICdmdW5jdGlvbicpIHtcbiAgICBldmVudFRhcmdldEFnbm9zdGljQWRkTGlzdGVuZXIoZW1pdHRlciwgJ2Vycm9yJywgaGFuZGxlciwgZmxhZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGV2ZW50VGFyZ2V0QWdub3N0aWNBZGRMaXN0ZW5lcihlbWl0dGVyLCBuYW1lLCBsaXN0ZW5lciwgZmxhZ3MpIHtcbiAgaWYgKHR5cGVvZiBlbWl0dGVyLm9uID09PSAnZnVuY3Rpb24nKSB7XG4gICAgaWYgKGZsYWdzLm9uY2UpIHtcbiAgICAgIGVtaXR0ZXIub25jZShuYW1lLCBsaXN0ZW5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVtaXR0ZXIub24obmFtZSwgbGlzdGVuZXIpO1xuICAgIH1cbiAgfSBlbHNlIGlmICh0eXBlb2YgZW1pdHRlci5hZGRFdmVudExpc3RlbmVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgLy8gRXZlbnRUYXJnZXQgZG9lcyBub3QgaGF2ZSBgZXJyb3JgIGV2ZW50IHNlbWFudGljcyBsaWtlIE5vZGVcbiAgICAvLyBFdmVudEVtaXR0ZXJzLCB3ZSBkbyBub3QgbGlzdGVuIGZvciBgZXJyb3JgIGV2ZW50cyBoZXJlLlxuICAgIGVtaXR0ZXIuYWRkRXZlbnRMaXN0ZW5lcihuYW1lLCBmdW5jdGlvbiB3cmFwTGlzdGVuZXIoYXJnKSB7XG4gICAgICAvLyBJRSBkb2VzIG5vdCBoYXZlIGJ1aWx0aW4gYHsgb25jZTogdHJ1ZSB9YCBzdXBwb3J0IHNvIHdlXG4gICAgICAvLyBoYXZlIHRvIGRvIGl0IG1hbnVhbGx5LlxuICAgICAgaWYgKGZsYWdzLm9uY2UpIHtcbiAgICAgICAgZW1pdHRlci5yZW1vdmVFdmVudExpc3RlbmVyKG5hbWUsIHdyYXBMaXN0ZW5lcik7XG4gICAgICB9XG4gICAgICBsaXN0ZW5lcihhcmcpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1RoZSBcImVtaXR0ZXJcIiBhcmd1bWVudCBtdXN0IGJlIG9mIHR5cGUgRXZlbnRFbWl0dGVyLiBSZWNlaXZlZCB0eXBlICcgKyB0eXBlb2YgZW1pdHRlcik7XG4gIH1cbn1cbiIsInZhciBnZXROYXRpdmUgPSByZXF1aXJlKCcuL19nZXROYXRpdmUnKSxcbiAgICByb290ID0gcmVxdWlyZSgnLi9fcm9vdCcpO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyB0aGF0IGFyZSB2ZXJpZmllZCB0byBiZSBuYXRpdmUuICovXG52YXIgRGF0YVZpZXcgPSBnZXROYXRpdmUocm9vdCwgJ0RhdGFWaWV3Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gRGF0YVZpZXc7XG4iLCJ2YXIgaGFzaENsZWFyID0gcmVxdWlyZSgnLi9faGFzaENsZWFyJyksXG4gICAgaGFzaERlbGV0ZSA9IHJlcXVpcmUoJy4vX2hhc2hEZWxldGUnKSxcbiAgICBoYXNoR2V0ID0gcmVxdWlyZSgnLi9faGFzaEdldCcpLFxuICAgIGhhc2hIYXMgPSByZXF1aXJlKCcuL19oYXNoSGFzJyksXG4gICAgaGFzaFNldCA9IHJlcXVpcmUoJy4vX2hhc2hTZXQnKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgaGFzaCBvYmplY3QuXG4gKlxuICogQHByaXZhdGVcbiAqIEBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtBcnJheX0gW2VudHJpZXNdIFRoZSBrZXktdmFsdWUgcGFpcnMgdG8gY2FjaGUuXG4gKi9cbmZ1bmN0aW9uIEhhc2goZW50cmllcykge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IGVudHJpZXMgPT0gbnVsbCA/IDAgOiBlbnRyaWVzLmxlbmd0aDtcblxuICB0aGlzLmNsZWFyKCk7XG4gIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgdmFyIGVudHJ5ID0gZW50cmllc1tpbmRleF07XG4gICAgdGhpcy5zZXQoZW50cnlbMF0sIGVudHJ5WzFdKTtcbiAgfVxufVxuXG4vLyBBZGQgbWV0aG9kcyB0byBgSGFzaGAuXG5IYXNoLnByb3RvdHlwZS5jbGVhciA9IGhhc2hDbGVhcjtcbkhhc2gucHJvdG90eXBlWydkZWxldGUnXSA9IGhhc2hEZWxldGU7XG5IYXNoLnByb3RvdHlwZS5nZXQgPSBoYXNoR2V0O1xuSGFzaC5wcm90b3R5cGUuaGFzID0gaGFzaEhhcztcbkhhc2gucHJvdG90eXBlLnNldCA9IGhhc2hTZXQ7XG5cbm1vZHVsZS5leHBvcnRzID0gSGFzaDtcbiIsInZhciBsaXN0Q2FjaGVDbGVhciA9IHJlcXVpcmUoJy4vX2xpc3RDYWNoZUNsZWFyJyksXG4gICAgbGlzdENhY2hlRGVsZXRlID0gcmVxdWlyZSgnLi9fbGlzdENhY2hlRGVsZXRlJyksXG4gICAgbGlzdENhY2hlR2V0ID0gcmVxdWlyZSgnLi9fbGlzdENhY2hlR2V0JyksXG4gICAgbGlzdENhY2hlSGFzID0gcmVxdWlyZSgnLi9fbGlzdENhY2hlSGFzJyksXG4gICAgbGlzdENhY2hlU2V0ID0gcmVxdWlyZSgnLi9fbGlzdENhY2hlU2V0Jyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBsaXN0IGNhY2hlIG9iamVjdC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0FycmF5fSBbZW50cmllc10gVGhlIGtleS12YWx1ZSBwYWlycyB0byBjYWNoZS5cbiAqL1xuZnVuY3Rpb24gTGlzdENhY2hlKGVudHJpZXMpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICBsZW5ndGggPSBlbnRyaWVzID09IG51bGwgPyAwIDogZW50cmllcy5sZW5ndGg7XG5cbiAgdGhpcy5jbGVhcigpO1xuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIHZhciBlbnRyeSA9IGVudHJpZXNbaW5kZXhdO1xuICAgIHRoaXMuc2V0KGVudHJ5WzBdLCBlbnRyeVsxXSk7XG4gIH1cbn1cblxuLy8gQWRkIG1ldGhvZHMgdG8gYExpc3RDYWNoZWAuXG5MaXN0Q2FjaGUucHJvdG90eXBlLmNsZWFyID0gbGlzdENhY2hlQ2xlYXI7XG5MaXN0Q2FjaGUucHJvdG90eXBlWydkZWxldGUnXSA9IGxpc3RDYWNoZURlbGV0ZTtcbkxpc3RDYWNoZS5wcm90b3R5cGUuZ2V0ID0gbGlzdENhY2hlR2V0O1xuTGlzdENhY2hlLnByb3RvdHlwZS5oYXMgPSBsaXN0Q2FjaGVIYXM7XG5MaXN0Q2FjaGUucHJvdG90eXBlLnNldCA9IGxpc3RDYWNoZVNldDtcblxubW9kdWxlLmV4cG9ydHMgPSBMaXN0Q2FjaGU7XG4iLCJ2YXIgZ2V0TmF0aXZlID0gcmVxdWlyZSgnLi9fZ2V0TmF0aXZlJyksXG4gICAgcm9vdCA9IHJlcXVpcmUoJy4vX3Jvb3QnKTtcblxuLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgdGhhdCBhcmUgdmVyaWZpZWQgdG8gYmUgbmF0aXZlLiAqL1xudmFyIE1hcCA9IGdldE5hdGl2ZShyb290LCAnTWFwJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gTWFwO1xuIiwidmFyIG1hcENhY2hlQ2xlYXIgPSByZXF1aXJlKCcuL19tYXBDYWNoZUNsZWFyJyksXG4gICAgbWFwQ2FjaGVEZWxldGUgPSByZXF1aXJlKCcuL19tYXBDYWNoZURlbGV0ZScpLFxuICAgIG1hcENhY2hlR2V0ID0gcmVxdWlyZSgnLi9fbWFwQ2FjaGVHZXQnKSxcbiAgICBtYXBDYWNoZUhhcyA9IHJlcXVpcmUoJy4vX21hcENhY2hlSGFzJyksXG4gICAgbWFwQ2FjaGVTZXQgPSByZXF1aXJlKCcuL19tYXBDYWNoZVNldCcpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBtYXAgY2FjaGUgb2JqZWN0IHRvIHN0b3JlIGtleS12YWx1ZSBwYWlycy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0FycmF5fSBbZW50cmllc10gVGhlIGtleS12YWx1ZSBwYWlycyB0byBjYWNoZS5cbiAqL1xuZnVuY3Rpb24gTWFwQ2FjaGUoZW50cmllcykge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IGVudHJpZXMgPT0gbnVsbCA/IDAgOiBlbnRyaWVzLmxlbmd0aDtcblxuICB0aGlzLmNsZWFyKCk7XG4gIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgdmFyIGVudHJ5ID0gZW50cmllc1tpbmRleF07XG4gICAgdGhpcy5zZXQoZW50cnlbMF0sIGVudHJ5WzFdKTtcbiAgfVxufVxuXG4vLyBBZGQgbWV0aG9kcyB0byBgTWFwQ2FjaGVgLlxuTWFwQ2FjaGUucHJvdG90eXBlLmNsZWFyID0gbWFwQ2FjaGVDbGVhcjtcbk1hcENhY2hlLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBtYXBDYWNoZURlbGV0ZTtcbk1hcENhY2hlLnByb3RvdHlwZS5nZXQgPSBtYXBDYWNoZUdldDtcbk1hcENhY2hlLnByb3RvdHlwZS5oYXMgPSBtYXBDYWNoZUhhcztcbk1hcENhY2hlLnByb3RvdHlwZS5zZXQgPSBtYXBDYWNoZVNldDtcblxubW9kdWxlLmV4cG9ydHMgPSBNYXBDYWNoZTtcbiIsInZhciBnZXROYXRpdmUgPSByZXF1aXJlKCcuL19nZXROYXRpdmUnKSxcbiAgICByb290ID0gcmVxdWlyZSgnLi9fcm9vdCcpO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyB0aGF0IGFyZSB2ZXJpZmllZCB0byBiZSBuYXRpdmUuICovXG52YXIgUHJvbWlzZSA9IGdldE5hdGl2ZShyb290LCAnUHJvbWlzZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFByb21pc2U7XG4iLCJ2YXIgZ2V0TmF0aXZlID0gcmVxdWlyZSgnLi9fZ2V0TmF0aXZlJyksXG4gICAgcm9vdCA9IHJlcXVpcmUoJy4vX3Jvb3QnKTtcblxuLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgdGhhdCBhcmUgdmVyaWZpZWQgdG8gYmUgbmF0aXZlLiAqL1xudmFyIFNldCA9IGdldE5hdGl2ZShyb290LCAnU2V0Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gU2V0O1xuIiwidmFyIE1hcENhY2hlID0gcmVxdWlyZSgnLi9fTWFwQ2FjaGUnKSxcbiAgICBzZXRDYWNoZUFkZCA9IHJlcXVpcmUoJy4vX3NldENhY2hlQWRkJyksXG4gICAgc2V0Q2FjaGVIYXMgPSByZXF1aXJlKCcuL19zZXRDYWNoZUhhcycpO1xuXG4vKipcbiAqXG4gKiBDcmVhdGVzIGFuIGFycmF5IGNhY2hlIG9iamVjdCB0byBzdG9yZSB1bmlxdWUgdmFsdWVzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7QXJyYXl9IFt2YWx1ZXNdIFRoZSB2YWx1ZXMgdG8gY2FjaGUuXG4gKi9cbmZ1bmN0aW9uIFNldENhY2hlKHZhbHVlcykge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IHZhbHVlcyA9PSBudWxsID8gMCA6IHZhbHVlcy5sZW5ndGg7XG5cbiAgdGhpcy5fX2RhdGFfXyA9IG5ldyBNYXBDYWNoZTtcbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICB0aGlzLmFkZCh2YWx1ZXNbaW5kZXhdKTtcbiAgfVxufVxuXG4vLyBBZGQgbWV0aG9kcyB0byBgU2V0Q2FjaGVgLlxuU2V0Q2FjaGUucHJvdG90eXBlLmFkZCA9IFNldENhY2hlLnByb3RvdHlwZS5wdXNoID0gc2V0Q2FjaGVBZGQ7XG5TZXRDYWNoZS5wcm90b3R5cGUuaGFzID0gc2V0Q2FjaGVIYXM7XG5cbm1vZHVsZS5leHBvcnRzID0gU2V0Q2FjaGU7XG4iLCJ2YXIgTGlzdENhY2hlID0gcmVxdWlyZSgnLi9fTGlzdENhY2hlJyksXG4gICAgc3RhY2tDbGVhciA9IHJlcXVpcmUoJy4vX3N0YWNrQ2xlYXInKSxcbiAgICBzdGFja0RlbGV0ZSA9IHJlcXVpcmUoJy4vX3N0YWNrRGVsZXRlJyksXG4gICAgc3RhY2tHZXQgPSByZXF1aXJlKCcuL19zdGFja0dldCcpLFxuICAgIHN0YWNrSGFzID0gcmVxdWlyZSgnLi9fc3RhY2tIYXMnKSxcbiAgICBzdGFja1NldCA9IHJlcXVpcmUoJy4vX3N0YWNrU2V0Jyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIHN0YWNrIGNhY2hlIG9iamVjdCB0byBzdG9yZSBrZXktdmFsdWUgcGFpcnMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtBcnJheX0gW2VudHJpZXNdIFRoZSBrZXktdmFsdWUgcGFpcnMgdG8gY2FjaGUuXG4gKi9cbmZ1bmN0aW9uIFN0YWNrKGVudHJpZXMpIHtcbiAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fID0gbmV3IExpc3RDYWNoZShlbnRyaWVzKTtcbiAgdGhpcy5zaXplID0gZGF0YS5zaXplO1xufVxuXG4vLyBBZGQgbWV0aG9kcyB0byBgU3RhY2tgLlxuU3RhY2sucHJvdG90eXBlLmNsZWFyID0gc3RhY2tDbGVhcjtcblN0YWNrLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBzdGFja0RlbGV0ZTtcblN0YWNrLnByb3RvdHlwZS5nZXQgPSBzdGFja0dldDtcblN0YWNrLnByb3RvdHlwZS5oYXMgPSBzdGFja0hhcztcblN0YWNrLnByb3RvdHlwZS5zZXQgPSBzdGFja1NldDtcblxubW9kdWxlLmV4cG9ydHMgPSBTdGFjaztcbiIsInZhciByb290ID0gcmVxdWlyZSgnLi9fcm9vdCcpO1xuXG4vKiogQnVpbHQtaW4gdmFsdWUgcmVmZXJlbmNlcy4gKi9cbnZhciBTeW1ib2wgPSByb290LlN5bWJvbDtcblxubW9kdWxlLmV4cG9ydHMgPSBTeW1ib2w7XG4iLCJ2YXIgcm9vdCA9IHJlcXVpcmUoJy4vX3Jvb3QnKTtcblxuLyoqIEJ1aWx0LWluIHZhbHVlIHJlZmVyZW5jZXMuICovXG52YXIgVWludDhBcnJheSA9IHJvb3QuVWludDhBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSBVaW50OEFycmF5O1xuIiwidmFyIGdldE5hdGl2ZSA9IHJlcXVpcmUoJy4vX2dldE5hdGl2ZScpLFxuICAgIHJvb3QgPSByZXF1aXJlKCcuL19yb290Jyk7XG5cbi8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHRoYXQgYXJlIHZlcmlmaWVkIHRvIGJlIG5hdGl2ZS4gKi9cbnZhciBXZWFrTWFwID0gZ2V0TmF0aXZlKHJvb3QsICdXZWFrTWFwJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gV2Vha01hcDtcbiIsIi8qKlxuICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmZvckVhY2hgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICovXG5mdW5jdGlvbiBhcnJheUVhY2goYXJyYXksIGl0ZXJhdGVlKSB7XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG5cbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICBpZiAoaXRlcmF0ZWUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpID09PSBmYWxzZSkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHJldHVybiBhcnJheTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBhcnJheUVhY2g7XG4iLCIvKipcbiAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5maWx0ZXJgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvclxuICogaXRlcmF0ZWUgc2hvcnRoYW5kcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gW2FycmF5XSBUaGUgYXJyYXkgdG8gaXRlcmF0ZSBvdmVyLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZGljYXRlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBmaWx0ZXJlZCBhcnJheS5cbiAqL1xuZnVuY3Rpb24gYXJyYXlGaWx0ZXIoYXJyYXksIHByZWRpY2F0ZSkge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IGFycmF5ID09IG51bGwgPyAwIDogYXJyYXkubGVuZ3RoLFxuICAgICAgcmVzSW5kZXggPSAwLFxuICAgICAgcmVzdWx0ID0gW107XG5cbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICB2YXIgdmFsdWUgPSBhcnJheVtpbmRleF07XG4gICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgcmVzdWx0W3Jlc0luZGV4KytdID0gdmFsdWU7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYXJyYXlGaWx0ZXI7XG4iLCJ2YXIgYmFzZVRpbWVzID0gcmVxdWlyZSgnLi9fYmFzZVRpbWVzJyksXG4gICAgaXNBcmd1bWVudHMgPSByZXF1aXJlKCcuL2lzQXJndW1lbnRzJyksXG4gICAgaXNBcnJheSA9IHJlcXVpcmUoJy4vaXNBcnJheScpLFxuICAgIGlzQnVmZmVyID0gcmVxdWlyZSgnLi9pc0J1ZmZlcicpLFxuICAgIGlzSW5kZXggPSByZXF1aXJlKCcuL19pc0luZGV4JyksXG4gICAgaXNUeXBlZEFycmF5ID0gcmVxdWlyZSgnLi9pc1R5cGVkQXJyYXknKTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGFycmF5IG9mIHRoZSBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIHRoZSBhcnJheS1saWtlIGB2YWx1ZWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHF1ZXJ5LlxuICogQHBhcmFtIHtib29sZWFufSBpbmhlcml0ZWQgU3BlY2lmeSByZXR1cm5pbmcgaW5oZXJpdGVkIHByb3BlcnR5IG5hbWVzLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAqL1xuZnVuY3Rpb24gYXJyYXlMaWtlS2V5cyh2YWx1ZSwgaW5oZXJpdGVkKSB7XG4gIHZhciBpc0FyciA9IGlzQXJyYXkodmFsdWUpLFxuICAgICAgaXNBcmcgPSAhaXNBcnIgJiYgaXNBcmd1bWVudHModmFsdWUpLFxuICAgICAgaXNCdWZmID0gIWlzQXJyICYmICFpc0FyZyAmJiBpc0J1ZmZlcih2YWx1ZSksXG4gICAgICBpc1R5cGUgPSAhaXNBcnIgJiYgIWlzQXJnICYmICFpc0J1ZmYgJiYgaXNUeXBlZEFycmF5KHZhbHVlKSxcbiAgICAgIHNraXBJbmRleGVzID0gaXNBcnIgfHwgaXNBcmcgfHwgaXNCdWZmIHx8IGlzVHlwZSxcbiAgICAgIHJlc3VsdCA9IHNraXBJbmRleGVzID8gYmFzZVRpbWVzKHZhbHVlLmxlbmd0aCwgU3RyaW5nKSA6IFtdLFxuICAgICAgbGVuZ3RoID0gcmVzdWx0Lmxlbmd0aDtcblxuICBmb3IgKHZhciBrZXkgaW4gdmFsdWUpIHtcbiAgICBpZiAoKGluaGVyaXRlZCB8fCBoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCBrZXkpKSAmJlxuICAgICAgICAhKHNraXBJbmRleGVzICYmIChcbiAgICAgICAgICAgLy8gU2FmYXJpIDkgaGFzIGVudW1lcmFibGUgYGFyZ3VtZW50cy5sZW5ndGhgIGluIHN0cmljdCBtb2RlLlxuICAgICAgICAgICBrZXkgPT0gJ2xlbmd0aCcgfHxcbiAgICAgICAgICAgLy8gTm9kZS5qcyAwLjEwIGhhcyBlbnVtZXJhYmxlIG5vbi1pbmRleCBwcm9wZXJ0aWVzIG9uIGJ1ZmZlcnMuXG4gICAgICAgICAgIChpc0J1ZmYgJiYgKGtleSA9PSAnb2Zmc2V0JyB8fCBrZXkgPT0gJ3BhcmVudCcpKSB8fFxuICAgICAgICAgICAvLyBQaGFudG9tSlMgMiBoYXMgZW51bWVyYWJsZSBub24taW5kZXggcHJvcGVydGllcyBvbiB0eXBlZCBhcnJheXMuXG4gICAgICAgICAgIChpc1R5cGUgJiYgKGtleSA9PSAnYnVmZmVyJyB8fCBrZXkgPT0gJ2J5dGVMZW5ndGgnIHx8IGtleSA9PSAnYnl0ZU9mZnNldCcpKSB8fFxuICAgICAgICAgICAvLyBTa2lwIGluZGV4IHByb3BlcnRpZXMuXG4gICAgICAgICAgIGlzSW5kZXgoa2V5LCBsZW5ndGgpXG4gICAgICAgICkpKSB7XG4gICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGFycmF5TGlrZUtleXM7XG4iLCIvKipcbiAqIEFwcGVuZHMgdGhlIGVsZW1lbnRzIG9mIGB2YWx1ZXNgIHRvIGBhcnJheWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBtb2RpZnkuXG4gKiBAcGFyYW0ge0FycmF5fSB2YWx1ZXMgVGhlIHZhbHVlcyB0byBhcHBlbmQuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAqL1xuZnVuY3Rpb24gYXJyYXlQdXNoKGFycmF5LCB2YWx1ZXMpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICBsZW5ndGggPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgb2Zmc2V0ID0gYXJyYXkubGVuZ3RoO1xuXG4gIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgYXJyYXlbb2Zmc2V0ICsgaW5kZXhdID0gdmFsdWVzW2luZGV4XTtcbiAgfVxuICByZXR1cm4gYXJyYXk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYXJyYXlQdXNoO1xuIiwiLyoqXG4gKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uc29tZWAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yIGl0ZXJhdGVlXG4gKiBzaG9ydGhhbmRzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5fSBbYXJyYXldIFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbnkgZWxlbWVudCBwYXNzZXMgdGhlIHByZWRpY2F0ZSBjaGVjayxcbiAqICBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGFycmF5U29tZShhcnJheSwgcHJlZGljYXRlKSB7XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgbGVuZ3RoID0gYXJyYXkgPT0gbnVsbCA/IDAgOiBhcnJheS5sZW5ndGg7XG5cbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICBpZiAocHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBhcnJheVNvbWU7XG4iLCJ2YXIgYmFzZUFzc2lnblZhbHVlID0gcmVxdWlyZSgnLi9fYmFzZUFzc2lnblZhbHVlJyksXG4gICAgZXEgPSByZXF1aXJlKCcuL2VxJyk7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogQXNzaWducyBgdmFsdWVgIHRvIGBrZXlgIG9mIGBvYmplY3RgIGlmIHRoZSBleGlzdGluZyB2YWx1ZSBpcyBub3QgZXF1aXZhbGVudFxuICogdXNpbmcgW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIG1vZGlmeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gYXNzaWduLlxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gYXNzaWduLlxuICovXG5mdW5jdGlvbiBhc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgdmFyIG9ialZhbHVlID0gb2JqZWN0W2tleV07XG4gIGlmICghKGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpICYmIGVxKG9ialZhbHVlLCB2YWx1ZSkpIHx8XG4gICAgICAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhKGtleSBpbiBvYmplY3QpKSkge1xuICAgIGJhc2VBc3NpZ25WYWx1ZShvYmplY3QsIGtleSwgdmFsdWUpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYXNzaWduVmFsdWU7XG4iLCJ2YXIgZXEgPSByZXF1aXJlKCcuL2VxJyk7XG5cbi8qKlxuICogR2V0cyB0aGUgaW5kZXggYXQgd2hpY2ggdGhlIGBrZXlgIGlzIGZvdW5kIGluIGBhcnJheWAgb2Yga2V5LXZhbHVlIHBhaXJzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gaW5zcGVjdC5cbiAqIEBwYXJhbSB7Kn0ga2V5IFRoZSBrZXkgdG8gc2VhcmNoIGZvci5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBtYXRjaGVkIHZhbHVlLCBlbHNlIGAtMWAuXG4gKi9cbmZ1bmN0aW9uIGFzc29jSW5kZXhPZihhcnJheSwga2V5KSB7XG4gIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG4gIHdoaWxlIChsZW5ndGgtLSkge1xuICAgIGlmIChlcShhcnJheVtsZW5ndGhdWzBdLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGVuZ3RoO1xuICAgIH1cbiAgfVxuICByZXR1cm4gLTE7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYXNzb2NJbmRleE9mO1xuIiwidmFyIGNvcHlPYmplY3QgPSByZXF1aXJlKCcuL19jb3B5T2JqZWN0JyksXG4gICAga2V5cyA9IHJlcXVpcmUoJy4va2V5cycpO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmFzc2lnbmAgd2l0aG91dCBzdXBwb3J0IGZvciBtdWx0aXBsZSBzb3VyY2VzXG4gKiBvciBgY3VzdG9taXplcmAgZnVuY3Rpb25zLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBkZXN0aW5hdGlvbiBvYmplY3QuXG4gKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBzb3VyY2Ugb2JqZWN0LlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAqL1xuZnVuY3Rpb24gYmFzZUFzc2lnbihvYmplY3QsIHNvdXJjZSkge1xuICByZXR1cm4gb2JqZWN0ICYmIGNvcHlPYmplY3Qoc291cmNlLCBrZXlzKHNvdXJjZSksIG9iamVjdCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUFzc2lnbjtcbiIsInZhciBjb3B5T2JqZWN0ID0gcmVxdWlyZSgnLi9fY29weU9iamVjdCcpLFxuICAgIGtleXNJbiA9IHJlcXVpcmUoJy4va2V5c0luJyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uYXNzaWduSW5gIHdpdGhvdXQgc3VwcG9ydCBmb3IgbXVsdGlwbGUgc291cmNlc1xuICogb3IgYGN1c3RvbWl6ZXJgIGZ1bmN0aW9ucy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgc291cmNlIG9iamVjdC5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gKi9cbmZ1bmN0aW9uIGJhc2VBc3NpZ25JbihvYmplY3QsIHNvdXJjZSkge1xuICByZXR1cm4gb2JqZWN0ICYmIGNvcHlPYmplY3Qoc291cmNlLCBrZXlzSW4oc291cmNlKSwgb2JqZWN0KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlQXNzaWduSW47XG4iLCJ2YXIgZGVmaW5lUHJvcGVydHkgPSByZXF1aXJlKCcuL19kZWZpbmVQcm9wZXJ0eScpO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBhc3NpZ25WYWx1ZWAgYW5kIGBhc3NpZ25NZXJnZVZhbHVlYCB3aXRob3V0XG4gKiB2YWx1ZSBjaGVja3MuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBtb2RpZnkuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHByb3BlcnR5IHRvIGFzc2lnbi5cbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGFzc2lnbi5cbiAqL1xuZnVuY3Rpb24gYmFzZUFzc2lnblZhbHVlKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5ID09ICdfX3Byb3RvX18nICYmIGRlZmluZVByb3BlcnR5KSB7XG4gICAgZGVmaW5lUHJvcGVydHkob2JqZWN0LCBrZXksIHtcbiAgICAgICdjb25maWd1cmFibGUnOiB0cnVlLFxuICAgICAgJ2VudW1lcmFibGUnOiB0cnVlLFxuICAgICAgJ3ZhbHVlJzogdmFsdWUsXG4gICAgICAnd3JpdGFibGUnOiB0cnVlXG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VBc3NpZ25WYWx1ZTtcbiIsInZhciBTdGFjayA9IHJlcXVpcmUoJy4vX1N0YWNrJyksXG4gICAgYXJyYXlFYWNoID0gcmVxdWlyZSgnLi9fYXJyYXlFYWNoJyksXG4gICAgYXNzaWduVmFsdWUgPSByZXF1aXJlKCcuL19hc3NpZ25WYWx1ZScpLFxuICAgIGJhc2VBc3NpZ24gPSByZXF1aXJlKCcuL19iYXNlQXNzaWduJyksXG4gICAgYmFzZUFzc2lnbkluID0gcmVxdWlyZSgnLi9fYmFzZUFzc2lnbkluJyksXG4gICAgY2xvbmVCdWZmZXIgPSByZXF1aXJlKCcuL19jbG9uZUJ1ZmZlcicpLFxuICAgIGNvcHlBcnJheSA9IHJlcXVpcmUoJy4vX2NvcHlBcnJheScpLFxuICAgIGNvcHlTeW1ib2xzID0gcmVxdWlyZSgnLi9fY29weVN5bWJvbHMnKSxcbiAgICBjb3B5U3ltYm9sc0luID0gcmVxdWlyZSgnLi9fY29weVN5bWJvbHNJbicpLFxuICAgIGdldEFsbEtleXMgPSByZXF1aXJlKCcuL19nZXRBbGxLZXlzJyksXG4gICAgZ2V0QWxsS2V5c0luID0gcmVxdWlyZSgnLi9fZ2V0QWxsS2V5c0luJyksXG4gICAgZ2V0VGFnID0gcmVxdWlyZSgnLi9fZ2V0VGFnJyksXG4gICAgaW5pdENsb25lQXJyYXkgPSByZXF1aXJlKCcuL19pbml0Q2xvbmVBcnJheScpLFxuICAgIGluaXRDbG9uZUJ5VGFnID0gcmVxdWlyZSgnLi9faW5pdENsb25lQnlUYWcnKSxcbiAgICBpbml0Q2xvbmVPYmplY3QgPSByZXF1aXJlKCcuL19pbml0Q2xvbmVPYmplY3QnKSxcbiAgICBpc0FycmF5ID0gcmVxdWlyZSgnLi9pc0FycmF5JyksXG4gICAgaXNCdWZmZXIgPSByZXF1aXJlKCcuL2lzQnVmZmVyJyksXG4gICAgaXNNYXAgPSByZXF1aXJlKCcuL2lzTWFwJyksXG4gICAgaXNPYmplY3QgPSByZXF1aXJlKCcuL2lzT2JqZWN0JyksXG4gICAgaXNTZXQgPSByZXF1aXJlKCcuL2lzU2V0JyksXG4gICAga2V5cyA9IHJlcXVpcmUoJy4va2V5cycpLFxuICAgIGtleXNJbiA9IHJlcXVpcmUoJy4va2V5c0luJyk7XG5cbi8qKiBVc2VkIHRvIGNvbXBvc2UgYml0bWFza3MgZm9yIGNsb25pbmcuICovXG52YXIgQ0xPTkVfREVFUF9GTEFHID0gMSxcbiAgICBDTE9ORV9GTEFUX0ZMQUcgPSAyLFxuICAgIENMT05FX1NZTUJPTFNfRkxBRyA9IDQ7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBhcmdzVGFnID0gJ1tvYmplY3QgQXJndW1lbnRzXScsXG4gICAgYXJyYXlUYWcgPSAnW29iamVjdCBBcnJheV0nLFxuICAgIGJvb2xUYWcgPSAnW29iamVjdCBCb29sZWFuXScsXG4gICAgZGF0ZVRhZyA9ICdbb2JqZWN0IERhdGVdJyxcbiAgICBlcnJvclRhZyA9ICdbb2JqZWN0IEVycm9yXScsXG4gICAgZnVuY1RhZyA9ICdbb2JqZWN0IEZ1bmN0aW9uXScsXG4gICAgZ2VuVGFnID0gJ1tvYmplY3QgR2VuZXJhdG9yRnVuY3Rpb25dJyxcbiAgICBtYXBUYWcgPSAnW29iamVjdCBNYXBdJyxcbiAgICBudW1iZXJUYWcgPSAnW29iamVjdCBOdW1iZXJdJyxcbiAgICBvYmplY3RUYWcgPSAnW29iamVjdCBPYmplY3RdJyxcbiAgICByZWdleHBUYWcgPSAnW29iamVjdCBSZWdFeHBdJyxcbiAgICBzZXRUYWcgPSAnW29iamVjdCBTZXRdJyxcbiAgICBzdHJpbmdUYWcgPSAnW29iamVjdCBTdHJpbmddJyxcbiAgICBzeW1ib2xUYWcgPSAnW29iamVjdCBTeW1ib2xdJyxcbiAgICB3ZWFrTWFwVGFnID0gJ1tvYmplY3QgV2Vha01hcF0nO1xuXG52YXIgYXJyYXlCdWZmZXJUYWcgPSAnW29iamVjdCBBcnJheUJ1ZmZlcl0nLFxuICAgIGRhdGFWaWV3VGFnID0gJ1tvYmplY3QgRGF0YVZpZXddJyxcbiAgICBmbG9hdDMyVGFnID0gJ1tvYmplY3QgRmxvYXQzMkFycmF5XScsXG4gICAgZmxvYXQ2NFRhZyA9ICdbb2JqZWN0IEZsb2F0NjRBcnJheV0nLFxuICAgIGludDhUYWcgPSAnW29iamVjdCBJbnQ4QXJyYXldJyxcbiAgICBpbnQxNlRhZyA9ICdbb2JqZWN0IEludDE2QXJyYXldJyxcbiAgICBpbnQzMlRhZyA9ICdbb2JqZWN0IEludDMyQXJyYXldJyxcbiAgICB1aW50OFRhZyA9ICdbb2JqZWN0IFVpbnQ4QXJyYXldJyxcbiAgICB1aW50OENsYW1wZWRUYWcgPSAnW29iamVjdCBVaW50OENsYW1wZWRBcnJheV0nLFxuICAgIHVpbnQxNlRhZyA9ICdbb2JqZWN0IFVpbnQxNkFycmF5XScsXG4gICAgdWludDMyVGFnID0gJ1tvYmplY3QgVWludDMyQXJyYXldJztcblxuLyoqIFVzZWQgdG8gaWRlbnRpZnkgYHRvU3RyaW5nVGFnYCB2YWx1ZXMgc3VwcG9ydGVkIGJ5IGBfLmNsb25lYC4gKi9cbnZhciBjbG9uZWFibGVUYWdzID0ge307XG5jbG9uZWFibGVUYWdzW2FyZ3NUYWddID0gY2xvbmVhYmxlVGFnc1thcnJheVRhZ10gPVxuY2xvbmVhYmxlVGFnc1thcnJheUJ1ZmZlclRhZ10gPSBjbG9uZWFibGVUYWdzW2RhdGFWaWV3VGFnXSA9XG5jbG9uZWFibGVUYWdzW2Jvb2xUYWddID0gY2xvbmVhYmxlVGFnc1tkYXRlVGFnXSA9XG5jbG9uZWFibGVUYWdzW2Zsb2F0MzJUYWddID0gY2xvbmVhYmxlVGFnc1tmbG9hdDY0VGFnXSA9XG5jbG9uZWFibGVUYWdzW2ludDhUYWddID0gY2xvbmVhYmxlVGFnc1tpbnQxNlRhZ10gPVxuY2xvbmVhYmxlVGFnc1tpbnQzMlRhZ10gPSBjbG9uZWFibGVUYWdzW21hcFRhZ10gPVxuY2xvbmVhYmxlVGFnc1tudW1iZXJUYWddID0gY2xvbmVhYmxlVGFnc1tvYmplY3RUYWddID1cbmNsb25lYWJsZVRhZ3NbcmVnZXhwVGFnXSA9IGNsb25lYWJsZVRhZ3Nbc2V0VGFnXSA9XG5jbG9uZWFibGVUYWdzW3N0cmluZ1RhZ10gPSBjbG9uZWFibGVUYWdzW3N5bWJvbFRhZ10gPVxuY2xvbmVhYmxlVGFnc1t1aW50OFRhZ10gPSBjbG9uZWFibGVUYWdzW3VpbnQ4Q2xhbXBlZFRhZ10gPVxuY2xvbmVhYmxlVGFnc1t1aW50MTZUYWddID0gY2xvbmVhYmxlVGFnc1t1aW50MzJUYWddID0gdHJ1ZTtcbmNsb25lYWJsZVRhZ3NbZXJyb3JUYWddID0gY2xvbmVhYmxlVGFnc1tmdW5jVGFnXSA9XG5jbG9uZWFibGVUYWdzW3dlYWtNYXBUYWddID0gZmFsc2U7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY2xvbmVgIGFuZCBgXy5jbG9uZURlZXBgIHdoaWNoIHRyYWNrc1xuICogdHJhdmVyc2VkIG9iamVjdHMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNsb25lLlxuICogQHBhcmFtIHtib29sZWFufSBiaXRtYXNrIFRoZSBiaXRtYXNrIGZsYWdzLlxuICogIDEgLSBEZWVwIGNsb25lXG4gKiAgMiAtIEZsYXR0ZW4gaW5oZXJpdGVkIHByb3BlcnRpZXNcbiAqICA0IC0gQ2xvbmUgc3ltYm9sc1xuICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY2xvbmluZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBba2V5XSBUaGUga2V5IG9mIGB2YWx1ZWAuXG4gKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIHBhcmVudCBvYmplY3Qgb2YgYHZhbHVlYC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbc3RhY2tdIFRyYWNrcyB0cmF2ZXJzZWQgb2JqZWN0cyBhbmQgdGhlaXIgY2xvbmUgY291bnRlcnBhcnRzLlxuICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGNsb25lZCB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gYmFzZUNsb25lKHZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBrZXksIG9iamVjdCwgc3RhY2spIHtcbiAgdmFyIHJlc3VsdCxcbiAgICAgIGlzRGVlcCA9IGJpdG1hc2sgJiBDTE9ORV9ERUVQX0ZMQUcsXG4gICAgICBpc0ZsYXQgPSBiaXRtYXNrICYgQ0xPTkVfRkxBVF9GTEFHLFxuICAgICAgaXNGdWxsID0gYml0bWFzayAmIENMT05FX1NZTUJPTFNfRkxBRztcblxuICBpZiAoY3VzdG9taXplcikge1xuICAgIHJlc3VsdCA9IG9iamVjdCA/IGN1c3RvbWl6ZXIodmFsdWUsIGtleSwgb2JqZWN0LCBzdGFjaykgOiBjdXN0b21pemVyKHZhbHVlKTtcbiAgfVxuICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIGlmICghaXNPYmplY3QodmFsdWUpKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHZhciBpc0FyciA9IGlzQXJyYXkodmFsdWUpO1xuICBpZiAoaXNBcnIpIHtcbiAgICByZXN1bHQgPSBpbml0Q2xvbmVBcnJheSh2YWx1ZSk7XG4gICAgaWYgKCFpc0RlZXApIHtcbiAgICAgIHJldHVybiBjb3B5QXJyYXkodmFsdWUsIHJlc3VsdCk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciB0YWcgPSBnZXRUYWcodmFsdWUpLFxuICAgICAgICBpc0Z1bmMgPSB0YWcgPT0gZnVuY1RhZyB8fCB0YWcgPT0gZ2VuVGFnO1xuXG4gICAgaWYgKGlzQnVmZmVyKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGNsb25lQnVmZmVyKHZhbHVlLCBpc0RlZXApO1xuICAgIH1cbiAgICBpZiAodGFnID09IG9iamVjdFRhZyB8fCB0YWcgPT0gYXJnc1RhZyB8fCAoaXNGdW5jICYmICFvYmplY3QpKSB7XG4gICAgICByZXN1bHQgPSAoaXNGbGF0IHx8IGlzRnVuYykgPyB7fSA6IGluaXRDbG9uZU9iamVjdCh2YWx1ZSk7XG4gICAgICBpZiAoIWlzRGVlcCkge1xuICAgICAgICByZXR1cm4gaXNGbGF0XG4gICAgICAgICAgPyBjb3B5U3ltYm9sc0luKHZhbHVlLCBiYXNlQXNzaWduSW4ocmVzdWx0LCB2YWx1ZSkpXG4gICAgICAgICAgOiBjb3B5U3ltYm9scyh2YWx1ZSwgYmFzZUFzc2lnbihyZXN1bHQsIHZhbHVlKSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghY2xvbmVhYmxlVGFnc1t0YWddKSB7XG4gICAgICAgIHJldHVybiBvYmplY3QgPyB2YWx1ZSA6IHt9O1xuICAgICAgfVxuICAgICAgcmVzdWx0ID0gaW5pdENsb25lQnlUYWcodmFsdWUsIHRhZywgaXNEZWVwKTtcbiAgICB9XG4gIH1cbiAgLy8gQ2hlY2sgZm9yIGNpcmN1bGFyIHJlZmVyZW5jZXMgYW5kIHJldHVybiBpdHMgY29ycmVzcG9uZGluZyBjbG9uZS5cbiAgc3RhY2sgfHwgKHN0YWNrID0gbmV3IFN0YWNrKTtcbiAgdmFyIHN0YWNrZWQgPSBzdGFjay5nZXQodmFsdWUpO1xuICBpZiAoc3RhY2tlZCkge1xuICAgIHJldHVybiBzdGFja2VkO1xuICB9XG4gIHN0YWNrLnNldCh2YWx1ZSwgcmVzdWx0KTtcblxuICBpZiAoaXNTZXQodmFsdWUpKSB7XG4gICAgdmFsdWUuZm9yRWFjaChmdW5jdGlvbihzdWJWYWx1ZSkge1xuICAgICAgcmVzdWx0LmFkZChiYXNlQ2xvbmUoc3ViVmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIHN1YlZhbHVlLCB2YWx1ZSwgc3RhY2spKTtcbiAgICB9KTtcbiAgfSBlbHNlIGlmIChpc01hcCh2YWx1ZSkpIHtcbiAgICB2YWx1ZS5mb3JFYWNoKGZ1bmN0aW9uKHN1YlZhbHVlLCBrZXkpIHtcbiAgICAgIHJlc3VsdC5zZXQoa2V5LCBiYXNlQ2xvbmUoc3ViVmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGtleSwgdmFsdWUsIHN0YWNrKSk7XG4gICAgfSk7XG4gIH1cblxuICB2YXIga2V5c0Z1bmMgPSBpc0Z1bGxcbiAgICA/IChpc0ZsYXQgPyBnZXRBbGxLZXlzSW4gOiBnZXRBbGxLZXlzKVxuICAgIDogKGlzRmxhdCA/IGtleXNJbiA6IGtleXMpO1xuXG4gIHZhciBwcm9wcyA9IGlzQXJyID8gdW5kZWZpbmVkIDoga2V5c0Z1bmModmFsdWUpO1xuICBhcnJheUVhY2gocHJvcHMgfHwgdmFsdWUsIGZ1bmN0aW9uKHN1YlZhbHVlLCBrZXkpIHtcbiAgICBpZiAocHJvcHMpIHtcbiAgICAgIGtleSA9IHN1YlZhbHVlO1xuICAgICAgc3ViVmFsdWUgPSB2YWx1ZVtrZXldO1xuICAgIH1cbiAgICAvLyBSZWN1cnNpdmVseSBwb3B1bGF0ZSBjbG9uZSAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgIGFzc2lnblZhbHVlKHJlc3VsdCwga2V5LCBiYXNlQ2xvbmUoc3ViVmFsdWUsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGtleSwgdmFsdWUsIHN0YWNrKSk7XG4gIH0pO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VDbG9uZTtcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vaXNPYmplY3QnKTtcblxuLyoqIEJ1aWx0LWluIHZhbHVlIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0Q3JlYXRlID0gT2JqZWN0LmNyZWF0ZTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jcmVhdGVgIHdpdGhvdXQgc3VwcG9ydCBmb3IgYXNzaWduaW5nXG4gKiBwcm9wZXJ0aWVzIHRvIHRoZSBjcmVhdGVkIG9iamVjdC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IHByb3RvIFRoZSBvYmplY3QgdG8gaW5oZXJpdCBmcm9tLlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbmV3IG9iamVjdC5cbiAqL1xudmFyIGJhc2VDcmVhdGUgPSAoZnVuY3Rpb24oKSB7XG4gIGZ1bmN0aW9uIG9iamVjdCgpIHt9XG4gIHJldHVybiBmdW5jdGlvbihwcm90bykge1xuICAgIGlmICghaXNPYmplY3QocHJvdG8pKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuICAgIGlmIChvYmplY3RDcmVhdGUpIHtcbiAgICAgIHJldHVybiBvYmplY3RDcmVhdGUocHJvdG8pO1xuICAgIH1cbiAgICBvYmplY3QucHJvdG90eXBlID0gcHJvdG87XG4gICAgdmFyIHJlc3VsdCA9IG5ldyBvYmplY3Q7XG4gICAgb2JqZWN0LnByb3RvdHlwZSA9IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xufSgpKTtcblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlQ3JlYXRlO1xuIiwidmFyIGFycmF5UHVzaCA9IHJlcXVpcmUoJy4vX2FycmF5UHVzaCcpLFxuICAgIGlzQXJyYXkgPSByZXF1aXJlKCcuL2lzQXJyYXknKTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgZ2V0QWxsS2V5c2AgYW5kIGBnZXRBbGxLZXlzSW5gIHdoaWNoIHVzZXNcbiAqIGBrZXlzRnVuY2AgYW5kIGBzeW1ib2xzRnVuY2AgdG8gZ2V0IHRoZSBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIGFuZFxuICogc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHBhcmFtIHtGdW5jdGlvbn0ga2V5c0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGdldCB0aGUga2V5cyBvZiBgb2JqZWN0YC5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IHN5bWJvbHNGdW5jIFRoZSBmdW5jdGlvbiB0byBnZXQgdGhlIHN5bWJvbHMgb2YgYG9iamVjdGAuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzIGFuZCBzeW1ib2xzLlxuICovXG5mdW5jdGlvbiBiYXNlR2V0QWxsS2V5cyhvYmplY3QsIGtleXNGdW5jLCBzeW1ib2xzRnVuYykge1xuICB2YXIgcmVzdWx0ID0ga2V5c0Z1bmMob2JqZWN0KTtcbiAgcmV0dXJuIGlzQXJyYXkob2JqZWN0KSA/IHJlc3VsdCA6IGFycmF5UHVzaChyZXN1bHQsIHN5bWJvbHNGdW5jKG9iamVjdCkpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VHZXRBbGxLZXlzO1xuIiwidmFyIFN5bWJvbCA9IHJlcXVpcmUoJy4vX1N5bWJvbCcpLFxuICAgIGdldFJhd1RhZyA9IHJlcXVpcmUoJy4vX2dldFJhd1RhZycpLFxuICAgIG9iamVjdFRvU3RyaW5nID0gcmVxdWlyZSgnLi9fb2JqZWN0VG9TdHJpbmcnKTtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIG51bGxUYWcgPSAnW29iamVjdCBOdWxsXScsXG4gICAgdW5kZWZpbmVkVGFnID0gJ1tvYmplY3QgVW5kZWZpbmVkXSc7XG5cbi8qKiBCdWlsdC1pbiB2YWx1ZSByZWZlcmVuY2VzLiAqL1xudmFyIHN5bVRvU3RyaW5nVGFnID0gU3ltYm9sID8gU3ltYm9sLnRvU3RyaW5nVGFnIDogdW5kZWZpbmVkO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBnZXRUYWdgIHdpdGhvdXQgZmFsbGJhY2tzIGZvciBidWdneSBlbnZpcm9ubWVudHMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHF1ZXJ5LlxuICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgYHRvU3RyaW5nVGFnYC5cbiAqL1xuZnVuY3Rpb24gYmFzZUdldFRhZyh2YWx1ZSkge1xuICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgIHJldHVybiB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkVGFnIDogbnVsbFRhZztcbiAgfVxuICByZXR1cm4gKHN5bVRvU3RyaW5nVGFnICYmIHN5bVRvU3RyaW5nVGFnIGluIE9iamVjdCh2YWx1ZSkpXG4gICAgPyBnZXRSYXdUYWcodmFsdWUpXG4gICAgOiBvYmplY3RUb1N0cmluZyh2YWx1ZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUdldFRhZztcbiIsInZhciBiYXNlR2V0VGFnID0gcmVxdWlyZSgnLi9fYmFzZUdldFRhZycpLFxuICAgIGlzT2JqZWN0TGlrZSA9IHJlcXVpcmUoJy4vaXNPYmplY3RMaWtlJyk7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBhcmdzVGFnID0gJ1tvYmplY3QgQXJndW1lbnRzXSc7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNBcmd1bWVudHNgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGBhcmd1bWVudHNgIG9iamVjdCxcbiAqL1xuZnVuY3Rpb24gYmFzZUlzQXJndW1lbnRzKHZhbHVlKSB7XG4gIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGJhc2VHZXRUYWcodmFsdWUpID09IGFyZ3NUYWc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUlzQXJndW1lbnRzO1xuIiwidmFyIGJhc2VJc0VxdWFsRGVlcCA9IHJlcXVpcmUoJy4vX2Jhc2VJc0VxdWFsRGVlcCcpLFxuICAgIGlzT2JqZWN0TGlrZSA9IHJlcXVpcmUoJy4vaXNPYmplY3RMaWtlJyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNFcXVhbGAgd2hpY2ggc3VwcG9ydHMgcGFydGlhbCBjb21wYXJpc29uc1xuICogYW5kIHRyYWNrcyB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuXG4gKiAgMSAtIFVub3JkZXJlZCBjb21wYXJpc29uXG4gKiAgMiAtIFBhcnRpYWwgY29tcGFyaXNvblxuICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gKiBAcGFyYW0ge09iamVjdH0gW3N0YWNrXSBUcmFja3MgdHJhdmVyc2VkIGB2YWx1ZWAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmFsdWVzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGJhc2VJc0VxdWFsKHZhbHVlLCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgc3RhY2spIHtcbiAgaWYgKHZhbHVlID09PSBvdGhlcikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIGlmICh2YWx1ZSA9PSBudWxsIHx8IG90aGVyID09IG51bGwgfHwgKCFpc09iamVjdExpa2UodmFsdWUpICYmICFpc09iamVjdExpa2Uob3RoZXIpKSkge1xuICAgIHJldHVybiB2YWx1ZSAhPT0gdmFsdWUgJiYgb3RoZXIgIT09IG90aGVyO1xuICB9XG4gIHJldHVybiBiYXNlSXNFcXVhbERlZXAodmFsdWUsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBiYXNlSXNFcXVhbCwgc3RhY2spO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VJc0VxdWFsO1xuIiwidmFyIFN0YWNrID0gcmVxdWlyZSgnLi9fU3RhY2snKSxcbiAgICBlcXVhbEFycmF5cyA9IHJlcXVpcmUoJy4vX2VxdWFsQXJyYXlzJyksXG4gICAgZXF1YWxCeVRhZyA9IHJlcXVpcmUoJy4vX2VxdWFsQnlUYWcnKSxcbiAgICBlcXVhbE9iamVjdHMgPSByZXF1aXJlKCcuL19lcXVhbE9iamVjdHMnKSxcbiAgICBnZXRUYWcgPSByZXF1aXJlKCcuL19nZXRUYWcnKSxcbiAgICBpc0FycmF5ID0gcmVxdWlyZSgnLi9pc0FycmF5JyksXG4gICAgaXNCdWZmZXIgPSByZXF1aXJlKCcuL2lzQnVmZmVyJyksXG4gICAgaXNUeXBlZEFycmF5ID0gcmVxdWlyZSgnLi9pc1R5cGVkQXJyYXknKTtcblxuLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3IgdmFsdWUgY29tcGFyaXNvbnMuICovXG52YXIgQ09NUEFSRV9QQVJUSUFMX0ZMQUcgPSAxO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgYXJnc1RhZyA9ICdbb2JqZWN0IEFyZ3VtZW50c10nLFxuICAgIGFycmF5VGFnID0gJ1tvYmplY3QgQXJyYXldJyxcbiAgICBvYmplY3RUYWcgPSAnW29iamVjdCBPYmplY3RdJztcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsYCBmb3IgYXJyYXlzIGFuZCBvYmplY3RzIHdoaWNoIHBlcmZvcm1zXG4gKiBkZWVwIGNvbXBhcmlzb25zIGFuZCB0cmFja3MgdHJhdmVyc2VkIG9iamVjdHMgZW5hYmxpbmcgb2JqZWN0cyB3aXRoIGNpcmN1bGFyXG4gKiByZWZlcmVuY2VzIHRvIGJlIGNvbXBhcmVkLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBiYXNlSXNFcXVhbGAgZm9yIG1vcmUgZGV0YWlscy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGN1c3RvbWl6ZXIgVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbc3RhY2tdIFRyYWNrcyB0cmF2ZXJzZWQgYG9iamVjdGAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBiYXNlSXNFcXVhbERlZXAob2JqZWN0LCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjaykge1xuICB2YXIgb2JqSXNBcnIgPSBpc0FycmF5KG9iamVjdCksXG4gICAgICBvdGhJc0FyciA9IGlzQXJyYXkob3RoZXIpLFxuICAgICAgb2JqVGFnID0gb2JqSXNBcnIgPyBhcnJheVRhZyA6IGdldFRhZyhvYmplY3QpLFxuICAgICAgb3RoVGFnID0gb3RoSXNBcnIgPyBhcnJheVRhZyA6IGdldFRhZyhvdGhlcik7XG5cbiAgb2JqVGFnID0gb2JqVGFnID09IGFyZ3NUYWcgPyBvYmplY3RUYWcgOiBvYmpUYWc7XG4gIG90aFRhZyA9IG90aFRhZyA9PSBhcmdzVGFnID8gb2JqZWN0VGFnIDogb3RoVGFnO1xuXG4gIHZhciBvYmpJc09iaiA9IG9ialRhZyA9PSBvYmplY3RUYWcsXG4gICAgICBvdGhJc09iaiA9IG90aFRhZyA9PSBvYmplY3RUYWcsXG4gICAgICBpc1NhbWVUYWcgPSBvYmpUYWcgPT0gb3RoVGFnO1xuXG4gIGlmIChpc1NhbWVUYWcgJiYgaXNCdWZmZXIob2JqZWN0KSkge1xuICAgIGlmICghaXNCdWZmZXIob3RoZXIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIG9iaklzQXJyID0gdHJ1ZTtcbiAgICBvYmpJc09iaiA9IGZhbHNlO1xuICB9XG4gIGlmIChpc1NhbWVUYWcgJiYgIW9iaklzT2JqKSB7XG4gICAgc3RhY2sgfHwgKHN0YWNrID0gbmV3IFN0YWNrKTtcbiAgICByZXR1cm4gKG9iaklzQXJyIHx8IGlzVHlwZWRBcnJheShvYmplY3QpKVxuICAgICAgPyBlcXVhbEFycmF5cyhvYmplY3QsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKVxuICAgICAgOiBlcXVhbEJ5VGFnKG9iamVjdCwgb3RoZXIsIG9ialRhZywgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjayk7XG4gIH1cbiAgaWYgKCEoYml0bWFzayAmIENPTVBBUkVfUEFSVElBTF9GTEFHKSkge1xuICAgIHZhciBvYmpJc1dyYXBwZWQgPSBvYmpJc09iaiAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgJ19fd3JhcHBlZF9fJyksXG4gICAgICAgIG90aElzV3JhcHBlZCA9IG90aElzT2JqICYmIGhhc093blByb3BlcnR5LmNhbGwob3RoZXIsICdfX3dyYXBwZWRfXycpO1xuXG4gICAgaWYgKG9iaklzV3JhcHBlZCB8fCBvdGhJc1dyYXBwZWQpIHtcbiAgICAgIHZhciBvYmpVbndyYXBwZWQgPSBvYmpJc1dyYXBwZWQgPyBvYmplY3QudmFsdWUoKSA6IG9iamVjdCxcbiAgICAgICAgICBvdGhVbndyYXBwZWQgPSBvdGhJc1dyYXBwZWQgPyBvdGhlci52YWx1ZSgpIDogb3RoZXI7XG5cbiAgICAgIHN0YWNrIHx8IChzdGFjayA9IG5ldyBTdGFjayk7XG4gICAgICByZXR1cm4gZXF1YWxGdW5jKG9ialVud3JhcHBlZCwgb3RoVW53cmFwcGVkLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdGFjayk7XG4gICAgfVxuICB9XG4gIGlmICghaXNTYW1lVGFnKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHN0YWNrIHx8IChzdGFjayA9IG5ldyBTdGFjayk7XG4gIHJldHVybiBlcXVhbE9iamVjdHMob2JqZWN0LCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjayk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUlzRXF1YWxEZWVwO1xuIiwidmFyIGdldFRhZyA9IHJlcXVpcmUoJy4vX2dldFRhZycpLFxuICAgIGlzT2JqZWN0TGlrZSA9IHJlcXVpcmUoJy4vaXNPYmplY3RMaWtlJyk7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBtYXBUYWcgPSAnW29iamVjdCBNYXBdJztcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5pc01hcGAgd2l0aG91dCBOb2RlLmpzIG9wdGltaXphdGlvbnMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBtYXAsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gYmFzZUlzTWFwKHZhbHVlKSB7XG4gIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGdldFRhZyh2YWx1ZSkgPT0gbWFwVGFnO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VJc01hcDtcbiIsInZhciBpc0Z1bmN0aW9uID0gcmVxdWlyZSgnLi9pc0Z1bmN0aW9uJyksXG4gICAgaXNNYXNrZWQgPSByZXF1aXJlKCcuL19pc01hc2tlZCcpLFxuICAgIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9pc09iamVjdCcpLFxuICAgIHRvU291cmNlID0gcmVxdWlyZSgnLi9fdG9Tb3VyY2UnKTtcblxuLyoqXG4gKiBVc2VkIHRvIG1hdGNoIGBSZWdFeHBgXG4gKiBbc3ludGF4IGNoYXJhY3RlcnNdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLXBhdHRlcm5zKS5cbiAqL1xudmFyIHJlUmVnRXhwQ2hhciA9IC9bXFxcXF4kLiorPygpW1xcXXt9fF0vZztcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IGhvc3QgY29uc3RydWN0b3JzIChTYWZhcmkpLiAqL1xudmFyIHJlSXNIb3N0Q3RvciA9IC9eXFxbb2JqZWN0IC4rP0NvbnN0cnVjdG9yXFxdJC87XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBmdW5jUHJvdG8gPSBGdW5jdGlvbi5wcm90b3R5cGUsXG4gICAgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKiogVXNlZCB0byByZXNvbHZlIHRoZSBkZWNvbXBpbGVkIHNvdXJjZSBvZiBmdW5jdGlvbnMuICovXG52YXIgZnVuY1RvU3RyaW5nID0gZnVuY1Byb3RvLnRvU3RyaW5nO1xuXG4vKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4vKiogVXNlZCB0byBkZXRlY3QgaWYgYSBtZXRob2QgaXMgbmF0aXZlLiAqL1xudmFyIHJlSXNOYXRpdmUgPSBSZWdFeHAoJ14nICtcbiAgZnVuY1RvU3RyaW5nLmNhbGwoaGFzT3duUHJvcGVydHkpLnJlcGxhY2UocmVSZWdFeHBDaGFyLCAnXFxcXCQmJylcbiAgLnJlcGxhY2UoL2hhc093blByb3BlcnR5fChmdW5jdGlvbikuKj8oPz1cXFxcXFwoKXwgZm9yIC4rPyg/PVxcXFxcXF0pL2csICckMS4qPycpICsgJyQnXG4pO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzTmF0aXZlYCB3aXRob3V0IGJhZCBzaGltIGNoZWNrcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIG5hdGl2ZSBmdW5jdGlvbixcbiAqICBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGJhc2VJc05hdGl2ZSh2YWx1ZSkge1xuICBpZiAoIWlzT2JqZWN0KHZhbHVlKSB8fCBpc01hc2tlZCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgdmFyIHBhdHRlcm4gPSBpc0Z1bmN0aW9uKHZhbHVlKSA/IHJlSXNOYXRpdmUgOiByZUlzSG9zdEN0b3I7XG4gIHJldHVybiBwYXR0ZXJuLnRlc3QodG9Tb3VyY2UodmFsdWUpKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlSXNOYXRpdmU7XG4iLCJ2YXIgZ2V0VGFnID0gcmVxdWlyZSgnLi9fZ2V0VGFnJyksXG4gICAgaXNPYmplY3RMaWtlID0gcmVxdWlyZSgnLi9pc09iamVjdExpa2UnKTtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIHNldFRhZyA9ICdbb2JqZWN0IFNldF0nO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmlzU2V0YCB3aXRob3V0IE5vZGUuanMgb3B0aW1pemF0aW9ucy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHNldCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBiYXNlSXNTZXQodmFsdWUpIHtcbiAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgZ2V0VGFnKHZhbHVlKSA9PSBzZXRUYWc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUlzU2V0O1xuIiwidmFyIGJhc2VHZXRUYWcgPSByZXF1aXJlKCcuL19iYXNlR2V0VGFnJyksXG4gICAgaXNMZW5ndGggPSByZXF1aXJlKCcuL2lzTGVuZ3RoJyksXG4gICAgaXNPYmplY3RMaWtlID0gcmVxdWlyZSgnLi9pc09iamVjdExpa2UnKTtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIGFyZ3NUYWcgPSAnW29iamVjdCBBcmd1bWVudHNdJyxcbiAgICBhcnJheVRhZyA9ICdbb2JqZWN0IEFycmF5XScsXG4gICAgYm9vbFRhZyA9ICdbb2JqZWN0IEJvb2xlYW5dJyxcbiAgICBkYXRlVGFnID0gJ1tvYmplY3QgRGF0ZV0nLFxuICAgIGVycm9yVGFnID0gJ1tvYmplY3QgRXJyb3JdJyxcbiAgICBmdW5jVGFnID0gJ1tvYmplY3QgRnVuY3Rpb25dJyxcbiAgICBtYXBUYWcgPSAnW29iamVjdCBNYXBdJyxcbiAgICBudW1iZXJUYWcgPSAnW29iamVjdCBOdW1iZXJdJyxcbiAgICBvYmplY3RUYWcgPSAnW29iamVjdCBPYmplY3RdJyxcbiAgICByZWdleHBUYWcgPSAnW29iamVjdCBSZWdFeHBdJyxcbiAgICBzZXRUYWcgPSAnW29iamVjdCBTZXRdJyxcbiAgICBzdHJpbmdUYWcgPSAnW29iamVjdCBTdHJpbmddJyxcbiAgICB3ZWFrTWFwVGFnID0gJ1tvYmplY3QgV2Vha01hcF0nO1xuXG52YXIgYXJyYXlCdWZmZXJUYWcgPSAnW29iamVjdCBBcnJheUJ1ZmZlcl0nLFxuICAgIGRhdGFWaWV3VGFnID0gJ1tvYmplY3QgRGF0YVZpZXddJyxcbiAgICBmbG9hdDMyVGFnID0gJ1tvYmplY3QgRmxvYXQzMkFycmF5XScsXG4gICAgZmxvYXQ2NFRhZyA9ICdbb2JqZWN0IEZsb2F0NjRBcnJheV0nLFxuICAgIGludDhUYWcgPSAnW29iamVjdCBJbnQ4QXJyYXldJyxcbiAgICBpbnQxNlRhZyA9ICdbb2JqZWN0IEludDE2QXJyYXldJyxcbiAgICBpbnQzMlRhZyA9ICdbb2JqZWN0IEludDMyQXJyYXldJyxcbiAgICB1aW50OFRhZyA9ICdbb2JqZWN0IFVpbnQ4QXJyYXldJyxcbiAgICB1aW50OENsYW1wZWRUYWcgPSAnW29iamVjdCBVaW50OENsYW1wZWRBcnJheV0nLFxuICAgIHVpbnQxNlRhZyA9ICdbb2JqZWN0IFVpbnQxNkFycmF5XScsXG4gICAgdWludDMyVGFnID0gJ1tvYmplY3QgVWludDMyQXJyYXldJztcblxuLyoqIFVzZWQgdG8gaWRlbnRpZnkgYHRvU3RyaW5nVGFnYCB2YWx1ZXMgb2YgdHlwZWQgYXJyYXlzLiAqL1xudmFyIHR5cGVkQXJyYXlUYWdzID0ge307XG50eXBlZEFycmF5VGFnc1tmbG9hdDMyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Zsb2F0NjRUYWddID1cbnR5cGVkQXJyYXlUYWdzW2ludDhUYWddID0gdHlwZWRBcnJheVRhZ3NbaW50MTZUYWddID1cbnR5cGVkQXJyYXlUYWdzW2ludDMyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW3VpbnQ4VGFnXSA9XG50eXBlZEFycmF5VGFnc1t1aW50OENsYW1wZWRUYWddID0gdHlwZWRBcnJheVRhZ3NbdWludDE2VGFnXSA9XG50eXBlZEFycmF5VGFnc1t1aW50MzJUYWddID0gdHJ1ZTtcbnR5cGVkQXJyYXlUYWdzW2FyZ3NUYWddID0gdHlwZWRBcnJheVRhZ3NbYXJyYXlUYWddID1cbnR5cGVkQXJyYXlUYWdzW2FycmF5QnVmZmVyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Jvb2xUYWddID1cbnR5cGVkQXJyYXlUYWdzW2RhdGFWaWV3VGFnXSA9IHR5cGVkQXJyYXlUYWdzW2RhdGVUYWddID1cbnR5cGVkQXJyYXlUYWdzW2Vycm9yVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Z1bmNUYWddID1cbnR5cGVkQXJyYXlUYWdzW21hcFRhZ10gPSB0eXBlZEFycmF5VGFnc1tudW1iZXJUYWddID1cbnR5cGVkQXJyYXlUYWdzW29iamVjdFRhZ10gPSB0eXBlZEFycmF5VGFnc1tyZWdleHBUYWddID1cbnR5cGVkQXJyYXlUYWdzW3NldFRhZ10gPSB0eXBlZEFycmF5VGFnc1tzdHJpbmdUYWddID1cbnR5cGVkQXJyYXlUYWdzW3dlYWtNYXBUYWddID0gZmFsc2U7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNUeXBlZEFycmF5YCB3aXRob3V0IE5vZGUuanMgb3B0aW1pemF0aW9ucy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHR5cGVkIGFycmF5LCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGJhc2VJc1R5cGVkQXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiZcbiAgICBpc0xlbmd0aCh2YWx1ZS5sZW5ndGgpICYmICEhdHlwZWRBcnJheVRhZ3NbYmFzZUdldFRhZyh2YWx1ZSldO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VJc1R5cGVkQXJyYXk7XG4iLCJ2YXIgaXNQcm90b3R5cGUgPSByZXF1aXJlKCcuL19pc1Byb3RvdHlwZScpLFxuICAgIG5hdGl2ZUtleXMgPSByZXF1aXJlKCcuL19uYXRpdmVLZXlzJyk7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ua2V5c2Agd2hpY2ggZG9lc24ndCB0cmVhdCBzcGFyc2UgYXJyYXlzIGFzIGRlbnNlLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICovXG5mdW5jdGlvbiBiYXNlS2V5cyhvYmplY3QpIHtcbiAgaWYgKCFpc1Byb3RvdHlwZShvYmplY3QpKSB7XG4gICAgcmV0dXJuIG5hdGl2ZUtleXMob2JqZWN0KTtcbiAgfVxuICB2YXIgcmVzdWx0ID0gW107XG4gIGZvciAodmFyIGtleSBpbiBPYmplY3Qob2JqZWN0KSkge1xuICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSAmJiBrZXkgIT0gJ2NvbnN0cnVjdG9yJykge1xuICAgICAgcmVzdWx0LnB1c2goa2V5KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlS2V5cztcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vaXNPYmplY3QnKSxcbiAgICBpc1Byb3RvdHlwZSA9IHJlcXVpcmUoJy4vX2lzUHJvdG90eXBlJyksXG4gICAgbmF0aXZlS2V5c0luID0gcmVxdWlyZSgnLi9fbmF0aXZlS2V5c0luJyk7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ua2V5c0luYCB3aGljaCBkb2Vzbid0IHRyZWF0IHNwYXJzZSBhcnJheXMgYXMgZGVuc2UuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gKi9cbmZ1bmN0aW9uIGJhc2VLZXlzSW4ob2JqZWN0KSB7XG4gIGlmICghaXNPYmplY3Qob2JqZWN0KSkge1xuICAgIHJldHVybiBuYXRpdmVLZXlzSW4ob2JqZWN0KTtcbiAgfVxuICB2YXIgaXNQcm90byA9IGlzUHJvdG90eXBlKG9iamVjdCksXG4gICAgICByZXN1bHQgPSBbXTtcblxuICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG4gICAgaWYgKCEoa2V5ID09ICdjb25zdHJ1Y3RvcicgJiYgKGlzUHJvdG8gfHwgIWhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSkpIHtcbiAgICAgIHJlc3VsdC5wdXNoKGtleSk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUtleXNJbjtcbiIsIi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udGltZXNgIHdpdGhvdXQgc3VwcG9ydCBmb3IgaXRlcmF0ZWUgc2hvcnRoYW5kc1xuICogb3IgbWF4IGFycmF5IGxlbmd0aCBjaGVja3MuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgdGltZXMgdG8gaW52b2tlIGBpdGVyYXRlZWAuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiByZXN1bHRzLlxuICovXG5mdW5jdGlvbiBiYXNlVGltZXMobiwgaXRlcmF0ZWUpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICByZXN1bHQgPSBBcnJheShuKTtcblxuICB3aGlsZSAoKytpbmRleCA8IG4pIHtcbiAgICByZXN1bHRbaW5kZXhdID0gaXRlcmF0ZWUoaW5kZXgpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZVRpbWVzO1xuIiwiLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy51bmFyeWAgd2l0aG91dCBzdXBwb3J0IGZvciBzdG9yaW5nIG1ldGFkYXRhLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjYXAgYXJndW1lbnRzIGZvci5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGNhcHBlZCBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gYmFzZVVuYXJ5KGZ1bmMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIGZ1bmModmFsdWUpO1xuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VVbmFyeTtcbiIsIi8qKlxuICogQ2hlY2tzIGlmIGEgYGNhY2hlYCB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gY2FjaGUgVGhlIGNhY2hlIHRvIHF1ZXJ5LlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGNhY2hlSGFzKGNhY2hlLCBrZXkpIHtcbiAgcmV0dXJuIGNhY2hlLmhhcyhrZXkpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNhY2hlSGFzO1xuIiwidmFyIFVpbnQ4QXJyYXkgPSByZXF1aXJlKCcuL19VaW50OEFycmF5Jyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNsb25lIG9mIGBhcnJheUJ1ZmZlcmAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXlCdWZmZXJ9IGFycmF5QnVmZmVyIFRoZSBhcnJheSBidWZmZXIgdG8gY2xvbmUuXG4gKiBAcmV0dXJucyB7QXJyYXlCdWZmZXJ9IFJldHVybnMgdGhlIGNsb25lZCBhcnJheSBidWZmZXIuXG4gKi9cbmZ1bmN0aW9uIGNsb25lQXJyYXlCdWZmZXIoYXJyYXlCdWZmZXIpIHtcbiAgdmFyIHJlc3VsdCA9IG5ldyBhcnJheUJ1ZmZlci5jb25zdHJ1Y3RvcihhcnJheUJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgbmV3IFVpbnQ4QXJyYXkocmVzdWx0KS5zZXQobmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjbG9uZUFycmF5QnVmZmVyO1xuIiwidmFyIHJvb3QgPSByZXF1aXJlKCcuL19yb290Jyk7XG5cbi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgZXhwb3J0c2AuICovXG52YXIgZnJlZUV4cG9ydHMgPSB0eXBlb2YgZXhwb3J0cyA9PSAnb2JqZWN0JyAmJiBleHBvcnRzICYmICFleHBvcnRzLm5vZGVUeXBlICYmIGV4cG9ydHM7XG5cbi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgbW9kdWxlYC4gKi9cbnZhciBmcmVlTW9kdWxlID0gZnJlZUV4cG9ydHMgJiYgdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUgJiYgIW1vZHVsZS5ub2RlVHlwZSAmJiBtb2R1bGU7XG5cbi8qKiBEZXRlY3QgdGhlIHBvcHVsYXIgQ29tbW9uSlMgZXh0ZW5zaW9uIGBtb2R1bGUuZXhwb3J0c2AuICovXG52YXIgbW9kdWxlRXhwb3J0cyA9IGZyZWVNb2R1bGUgJiYgZnJlZU1vZHVsZS5leHBvcnRzID09PSBmcmVlRXhwb3J0cztcblxuLyoqIEJ1aWx0LWluIHZhbHVlIHJlZmVyZW5jZXMuICovXG52YXIgQnVmZmVyID0gbW9kdWxlRXhwb3J0cyA/IHJvb3QuQnVmZmVyIDogdW5kZWZpbmVkLFxuICAgIGFsbG9jVW5zYWZlID0gQnVmZmVyID8gQnVmZmVyLmFsbG9jVW5zYWZlIDogdW5kZWZpbmVkO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBjbG9uZSBvZiAgYGJ1ZmZlcmAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QnVmZmVyfSBidWZmZXIgVGhlIGJ1ZmZlciB0byBjbG9uZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gKiBAcmV0dXJucyB7QnVmZmVyfSBSZXR1cm5zIHRoZSBjbG9uZWQgYnVmZmVyLlxuICovXG5mdW5jdGlvbiBjbG9uZUJ1ZmZlcihidWZmZXIsIGlzRGVlcCkge1xuICBpZiAoaXNEZWVwKSB7XG4gICAgcmV0dXJuIGJ1ZmZlci5zbGljZSgpO1xuICB9XG4gIHZhciBsZW5ndGggPSBidWZmZXIubGVuZ3RoLFxuICAgICAgcmVzdWx0ID0gYWxsb2NVbnNhZmUgPyBhbGxvY1Vuc2FmZShsZW5ndGgpIDogbmV3IGJ1ZmZlci5jb25zdHJ1Y3RvcihsZW5ndGgpO1xuXG4gIGJ1ZmZlci5jb3B5KHJlc3VsdCk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2xvbmVCdWZmZXI7XG4iLCJ2YXIgY2xvbmVBcnJheUJ1ZmZlciA9IHJlcXVpcmUoJy4vX2Nsb25lQXJyYXlCdWZmZXInKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgY2xvbmUgb2YgYGRhdGFWaWV3YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IGRhdGFWaWV3IFRoZSBkYXRhIHZpZXcgdG8gY2xvbmUuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0RlZXBdIFNwZWNpZnkgYSBkZWVwIGNsb25lLlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgY2xvbmVkIGRhdGEgdmlldy5cbiAqL1xuZnVuY3Rpb24gY2xvbmVEYXRhVmlldyhkYXRhVmlldywgaXNEZWVwKSB7XG4gIHZhciBidWZmZXIgPSBpc0RlZXAgPyBjbG9uZUFycmF5QnVmZmVyKGRhdGFWaWV3LmJ1ZmZlcikgOiBkYXRhVmlldy5idWZmZXI7XG4gIHJldHVybiBuZXcgZGF0YVZpZXcuY29uc3RydWN0b3IoYnVmZmVyLCBkYXRhVmlldy5ieXRlT2Zmc2V0LCBkYXRhVmlldy5ieXRlTGVuZ3RoKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjbG9uZURhdGFWaWV3O1xuIiwiLyoqIFVzZWQgdG8gbWF0Y2ggYFJlZ0V4cGAgZmxhZ3MgZnJvbSB0aGVpciBjb2VyY2VkIHN0cmluZyB2YWx1ZXMuICovXG52YXIgcmVGbGFncyA9IC9cXHcqJC87XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNsb25lIG9mIGByZWdleHBgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gcmVnZXhwIFRoZSByZWdleHAgdG8gY2xvbmUuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgcmVnZXhwLlxuICovXG5mdW5jdGlvbiBjbG9uZVJlZ0V4cChyZWdleHApIHtcbiAgdmFyIHJlc3VsdCA9IG5ldyByZWdleHAuY29uc3RydWN0b3IocmVnZXhwLnNvdXJjZSwgcmVGbGFncy5leGVjKHJlZ2V4cCkpO1xuICByZXN1bHQubGFzdEluZGV4ID0gcmVnZXhwLmxhc3RJbmRleDtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjbG9uZVJlZ0V4cDtcbiIsInZhciBTeW1ib2wgPSByZXF1aXJlKCcuL19TeW1ib2wnKTtcblxuLyoqIFVzZWQgdG8gY29udmVydCBzeW1ib2xzIHRvIHByaW1pdGl2ZXMgYW5kIHN0cmluZ3MuICovXG52YXIgc3ltYm9sUHJvdG8gPSBTeW1ib2wgPyBTeW1ib2wucHJvdG90eXBlIDogdW5kZWZpbmVkLFxuICAgIHN5bWJvbFZhbHVlT2YgPSBzeW1ib2xQcm90byA/IHN5bWJvbFByb3RvLnZhbHVlT2YgOiB1bmRlZmluZWQ7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNsb25lIG9mIHRoZSBgc3ltYm9sYCBvYmplY3QuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBzeW1ib2wgVGhlIHN5bWJvbCBvYmplY3QgdG8gY2xvbmUuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjbG9uZWQgc3ltYm9sIG9iamVjdC5cbiAqL1xuZnVuY3Rpb24gY2xvbmVTeW1ib2woc3ltYm9sKSB7XG4gIHJldHVybiBzeW1ib2xWYWx1ZU9mID8gT2JqZWN0KHN5bWJvbFZhbHVlT2YuY2FsbChzeW1ib2wpKSA6IHt9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNsb25lU3ltYm9sO1xuIiwidmFyIGNsb25lQXJyYXlCdWZmZXIgPSByZXF1aXJlKCcuL19jbG9uZUFycmF5QnVmZmVyJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNsb25lIG9mIGB0eXBlZEFycmF5YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IHR5cGVkQXJyYXkgVGhlIHR5cGVkIGFycmF5IHRvIGNsb25lLlxuICogQHBhcmFtIHtib29sZWFufSBbaXNEZWVwXSBTcGVjaWZ5IGEgZGVlcCBjbG9uZS5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCB0eXBlZCBhcnJheS5cbiAqL1xuZnVuY3Rpb24gY2xvbmVUeXBlZEFycmF5KHR5cGVkQXJyYXksIGlzRGVlcCkge1xuICB2YXIgYnVmZmVyID0gaXNEZWVwID8gY2xvbmVBcnJheUJ1ZmZlcih0eXBlZEFycmF5LmJ1ZmZlcikgOiB0eXBlZEFycmF5LmJ1ZmZlcjtcbiAgcmV0dXJuIG5ldyB0eXBlZEFycmF5LmNvbnN0cnVjdG9yKGJ1ZmZlciwgdHlwZWRBcnJheS5ieXRlT2Zmc2V0LCB0eXBlZEFycmF5Lmxlbmd0aCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2xvbmVUeXBlZEFycmF5O1xuIiwiLyoqXG4gKiBDb3BpZXMgdGhlIHZhbHVlcyBvZiBgc291cmNlYCB0byBgYXJyYXlgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5fSBzb3VyY2UgVGhlIGFycmF5IHRvIGNvcHkgdmFsdWVzIGZyb20uXG4gKiBAcGFyYW0ge0FycmF5fSBbYXJyYXk9W11dIFRoZSBhcnJheSB0byBjb3B5IHZhbHVlcyB0by5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyBgYXJyYXlgLlxuICovXG5mdW5jdGlvbiBjb3B5QXJyYXkoc291cmNlLCBhcnJheSkge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IHNvdXJjZS5sZW5ndGg7XG5cbiAgYXJyYXkgfHwgKGFycmF5ID0gQXJyYXkobGVuZ3RoKSk7XG4gIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgYXJyYXlbaW5kZXhdID0gc291cmNlW2luZGV4XTtcbiAgfVxuICByZXR1cm4gYXJyYXk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY29weUFycmF5O1xuIiwidmFyIGFzc2lnblZhbHVlID0gcmVxdWlyZSgnLi9fYXNzaWduVmFsdWUnKSxcbiAgICBiYXNlQXNzaWduVmFsdWUgPSByZXF1aXJlKCcuL19iYXNlQXNzaWduVmFsdWUnKTtcblxuLyoqXG4gKiBDb3BpZXMgcHJvcGVydGllcyBvZiBgc291cmNlYCB0byBgb2JqZWN0YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IHNvdXJjZSBUaGUgb2JqZWN0IHRvIGNvcHkgcHJvcGVydGllcyBmcm9tLlxuICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IGlkZW50aWZpZXJzIHRvIGNvcHkuXG4gKiBAcGFyYW0ge09iamVjdH0gW29iamVjdD17fV0gVGhlIG9iamVjdCB0byBjb3B5IHByb3BlcnRpZXMgdG8uXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb3BpZWQgdmFsdWVzLlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAqL1xuZnVuY3Rpb24gY29weU9iamVjdChzb3VyY2UsIHByb3BzLCBvYmplY3QsIGN1c3RvbWl6ZXIpIHtcbiAgdmFyIGlzTmV3ID0gIW9iamVjdDtcbiAgb2JqZWN0IHx8IChvYmplY3QgPSB7fSk7XG5cbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICBsZW5ndGggPSBwcm9wcy5sZW5ndGg7XG5cbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICB2YXIga2V5ID0gcHJvcHNbaW5kZXhdO1xuXG4gICAgdmFyIG5ld1ZhbHVlID0gY3VzdG9taXplclxuICAgICAgPyBjdXN0b21pemVyKG9iamVjdFtrZXldLCBzb3VyY2Vba2V5XSwga2V5LCBvYmplY3QsIHNvdXJjZSlcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgaWYgKG5ld1ZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIG5ld1ZhbHVlID0gc291cmNlW2tleV07XG4gICAgfVxuICAgIGlmIChpc05ldykge1xuICAgICAgYmFzZUFzc2lnblZhbHVlKG9iamVjdCwga2V5LCBuZXdWYWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2lnblZhbHVlKG9iamVjdCwga2V5LCBuZXdWYWx1ZSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBvYmplY3Q7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY29weU9iamVjdDtcbiIsInZhciBjb3B5T2JqZWN0ID0gcmVxdWlyZSgnLi9fY29weU9iamVjdCcpLFxuICAgIGdldFN5bWJvbHMgPSByZXF1aXJlKCcuL19nZXRTeW1ib2xzJyk7XG5cbi8qKlxuICogQ29waWVzIG93biBzeW1ib2xzIG9mIGBzb3VyY2VgIHRvIGBvYmplY3RgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3QgdG8gY29weSBzeW1ib2xzIGZyb20uXG4gKiBAcGFyYW0ge09iamVjdH0gW29iamVjdD17fV0gVGhlIG9iamVjdCB0byBjb3B5IHN5bWJvbHMgdG8uXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICovXG5mdW5jdGlvbiBjb3B5U3ltYm9scyhzb3VyY2UsIG9iamVjdCkge1xuICByZXR1cm4gY29weU9iamVjdChzb3VyY2UsIGdldFN5bWJvbHMoc291cmNlKSwgb2JqZWN0KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb3B5U3ltYm9scztcbiIsInZhciBjb3B5T2JqZWN0ID0gcmVxdWlyZSgnLi9fY29weU9iamVjdCcpLFxuICAgIGdldFN5bWJvbHNJbiA9IHJlcXVpcmUoJy4vX2dldFN5bWJvbHNJbicpO1xuXG4vKipcbiAqIENvcGllcyBvd24gYW5kIGluaGVyaXRlZCBzeW1ib2xzIG9mIGBzb3VyY2VgIHRvIGBvYmplY3RgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gc291cmNlIFRoZSBvYmplY3QgdG8gY29weSBzeW1ib2xzIGZyb20uXG4gKiBAcGFyYW0ge09iamVjdH0gW29iamVjdD17fV0gVGhlIG9iamVjdCB0byBjb3B5IHN5bWJvbHMgdG8uXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICovXG5mdW5jdGlvbiBjb3B5U3ltYm9sc0luKHNvdXJjZSwgb2JqZWN0KSB7XG4gIHJldHVybiBjb3B5T2JqZWN0KHNvdXJjZSwgZ2V0U3ltYm9sc0luKHNvdXJjZSksIG9iamVjdCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY29weVN5bWJvbHNJbjtcbiIsInZhciByb290ID0gcmVxdWlyZSgnLi9fcm9vdCcpO1xuXG4vKiogVXNlZCB0byBkZXRlY3Qgb3ZlcnJlYWNoaW5nIGNvcmUtanMgc2hpbXMuICovXG52YXIgY29yZUpzRGF0YSA9IHJvb3RbJ19fY29yZS1qc19zaGFyZWRfXyddO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNvcmVKc0RhdGE7XG4iLCJ2YXIgZ2V0TmF0aXZlID0gcmVxdWlyZSgnLi9fZ2V0TmF0aXZlJyk7XG5cbnZhciBkZWZpbmVQcm9wZXJ0eSA9IChmdW5jdGlvbigpIHtcbiAgdHJ5IHtcbiAgICB2YXIgZnVuYyA9IGdldE5hdGl2ZShPYmplY3QsICdkZWZpbmVQcm9wZXJ0eScpO1xuICAgIGZ1bmMoe30sICcnLCB7fSk7XG4gICAgcmV0dXJuIGZ1bmM7XG4gIH0gY2F0Y2ggKGUpIHt9XG59KCkpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRlZmluZVByb3BlcnR5O1xuIiwidmFyIFNldENhY2hlID0gcmVxdWlyZSgnLi9fU2V0Q2FjaGUnKSxcbiAgICBhcnJheVNvbWUgPSByZXF1aXJlKCcuL19hcnJheVNvbWUnKSxcbiAgICBjYWNoZUhhcyA9IHJlcXVpcmUoJy4vX2NhY2hlSGFzJyk7XG5cbi8qKiBVc2VkIHRvIGNvbXBvc2UgYml0bWFza3MgZm9yIHZhbHVlIGNvbXBhcmlzb25zLiAqL1xudmFyIENPTVBBUkVfUEFSVElBTF9GTEFHID0gMSxcbiAgICBDT01QQVJFX1VOT1JERVJFRF9GTEFHID0gMjtcblxuLyoqXG4gKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsRGVlcGAgZm9yIGFycmF5cyB3aXRoIHN1cHBvcnQgZm9yXG4gKiBwYXJ0aWFsIGRlZXAgY29tcGFyaXNvbnMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBjb21wYXJlLlxuICogQHBhcmFtIHtBcnJheX0gb3RoZXIgVGhlIG90aGVyIGFycmF5IHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBiYXNlSXNFcXVhbGAgZm9yIG1vcmUgZGV0YWlscy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGN1c3RvbWl6ZXIgVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGFjayBUcmFja3MgdHJhdmVyc2VkIGBhcnJheWAgYW5kIGBvdGhlcmAgb2JqZWN0cy5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYXJyYXlzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGVxdWFsQXJyYXlzKGFycmF5LCBvdGhlciwgYml0bWFzaywgY3VzdG9taXplciwgZXF1YWxGdW5jLCBzdGFjaykge1xuICB2YXIgaXNQYXJ0aWFsID0gYml0bWFzayAmIENPTVBBUkVfUEFSVElBTF9GTEFHLFxuICAgICAgYXJyTGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgb3RoTGVuZ3RoID0gb3RoZXIubGVuZ3RoO1xuXG4gIGlmIChhcnJMZW5ndGggIT0gb3RoTGVuZ3RoICYmICEoaXNQYXJ0aWFsICYmIG90aExlbmd0aCA+IGFyckxlbmd0aCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgLy8gQ2hlY2sgdGhhdCBjeWNsaWMgdmFsdWVzIGFyZSBlcXVhbC5cbiAgdmFyIGFyclN0YWNrZWQgPSBzdGFjay5nZXQoYXJyYXkpO1xuICB2YXIgb3RoU3RhY2tlZCA9IHN0YWNrLmdldChvdGhlcik7XG4gIGlmIChhcnJTdGFja2VkICYmIG90aFN0YWNrZWQpIHtcbiAgICByZXR1cm4gYXJyU3RhY2tlZCA9PSBvdGhlciAmJiBvdGhTdGFja2VkID09IGFycmF5O1xuICB9XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgcmVzdWx0ID0gdHJ1ZSxcbiAgICAgIHNlZW4gPSAoYml0bWFzayAmIENPTVBBUkVfVU5PUkRFUkVEX0ZMQUcpID8gbmV3IFNldENhY2hlIDogdW5kZWZpbmVkO1xuXG4gIHN0YWNrLnNldChhcnJheSwgb3RoZXIpO1xuICBzdGFjay5zZXQob3RoZXIsIGFycmF5KTtcblxuICAvLyBJZ25vcmUgbm9uLWluZGV4IHByb3BlcnRpZXMuXG4gIHdoaWxlICgrK2luZGV4IDwgYXJyTGVuZ3RoKSB7XG4gICAgdmFyIGFyclZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICBvdGhWYWx1ZSA9IG90aGVyW2luZGV4XTtcblxuICAgIGlmIChjdXN0b21pemVyKSB7XG4gICAgICB2YXIgY29tcGFyZWQgPSBpc1BhcnRpYWxcbiAgICAgICAgPyBjdXN0b21pemVyKG90aFZhbHVlLCBhcnJWYWx1ZSwgaW5kZXgsIG90aGVyLCBhcnJheSwgc3RhY2spXG4gICAgICAgIDogY3VzdG9taXplcihhcnJWYWx1ZSwgb3RoVmFsdWUsIGluZGV4LCBhcnJheSwgb3RoZXIsIHN0YWNrKTtcbiAgICB9XG4gICAgaWYgKGNvbXBhcmVkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChjb21wYXJlZCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgYXJyYXlzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgaWYgKHNlZW4pIHtcbiAgICAgIGlmICghYXJyYXlTb21lKG90aGVyLCBmdW5jdGlvbihvdGhWYWx1ZSwgb3RoSW5kZXgpIHtcbiAgICAgICAgICAgIGlmICghY2FjaGVIYXMoc2Vlbiwgb3RoSW5kZXgpICYmXG4gICAgICAgICAgICAgICAgKGFyclZhbHVlID09PSBvdGhWYWx1ZSB8fCBlcXVhbEZ1bmMoYXJyVmFsdWUsIG90aFZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdGFjaykpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBzZWVuLnB1c2gob3RoSW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pKSB7XG4gICAgICAgIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKCEoXG4gICAgICAgICAgYXJyVmFsdWUgPT09IG90aFZhbHVlIHx8XG4gICAgICAgICAgICBlcXVhbEZ1bmMoYXJyVmFsdWUsIG90aFZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdGFjaylcbiAgICAgICAgKSkge1xuICAgICAgcmVzdWx0ID0gZmFsc2U7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgc3RhY2tbJ2RlbGV0ZSddKGFycmF5KTtcbiAgc3RhY2tbJ2RlbGV0ZSddKG90aGVyKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBlcXVhbEFycmF5cztcbiIsInZhciBTeW1ib2wgPSByZXF1aXJlKCcuL19TeW1ib2wnKSxcbiAgICBVaW50OEFycmF5ID0gcmVxdWlyZSgnLi9fVWludDhBcnJheScpLFxuICAgIGVxID0gcmVxdWlyZSgnLi9lcScpLFxuICAgIGVxdWFsQXJyYXlzID0gcmVxdWlyZSgnLi9fZXF1YWxBcnJheXMnKSxcbiAgICBtYXBUb0FycmF5ID0gcmVxdWlyZSgnLi9fbWFwVG9BcnJheScpLFxuICAgIHNldFRvQXJyYXkgPSByZXF1aXJlKCcuL19zZXRUb0FycmF5Jyk7XG5cbi8qKiBVc2VkIHRvIGNvbXBvc2UgYml0bWFza3MgZm9yIHZhbHVlIGNvbXBhcmlzb25zLiAqL1xudmFyIENPTVBBUkVfUEFSVElBTF9GTEFHID0gMSxcbiAgICBDT01QQVJFX1VOT1JERVJFRF9GTEFHID0gMjtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIGJvb2xUYWcgPSAnW29iamVjdCBCb29sZWFuXScsXG4gICAgZGF0ZVRhZyA9ICdbb2JqZWN0IERhdGVdJyxcbiAgICBlcnJvclRhZyA9ICdbb2JqZWN0IEVycm9yXScsXG4gICAgbWFwVGFnID0gJ1tvYmplY3QgTWFwXScsXG4gICAgbnVtYmVyVGFnID0gJ1tvYmplY3QgTnVtYmVyXScsXG4gICAgcmVnZXhwVGFnID0gJ1tvYmplY3QgUmVnRXhwXScsXG4gICAgc2V0VGFnID0gJ1tvYmplY3QgU2V0XScsXG4gICAgc3RyaW5nVGFnID0gJ1tvYmplY3QgU3RyaW5nXScsXG4gICAgc3ltYm9sVGFnID0gJ1tvYmplY3QgU3ltYm9sXSc7XG5cbnZhciBhcnJheUJ1ZmZlclRhZyA9ICdbb2JqZWN0IEFycmF5QnVmZmVyXScsXG4gICAgZGF0YVZpZXdUYWcgPSAnW29iamVjdCBEYXRhVmlld10nO1xuXG4vKiogVXNlZCB0byBjb252ZXJ0IHN5bWJvbHMgdG8gcHJpbWl0aXZlcyBhbmQgc3RyaW5ncy4gKi9cbnZhciBzeW1ib2xQcm90byA9IFN5bWJvbCA/IFN5bWJvbC5wcm90b3R5cGUgOiB1bmRlZmluZWQsXG4gICAgc3ltYm9sVmFsdWVPZiA9IHN5bWJvbFByb3RvID8gc3ltYm9sUHJvdG8udmFsdWVPZiA6IHVuZGVmaW5lZDtcblxuLyoqXG4gKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYGJhc2VJc0VxdWFsRGVlcGAgZm9yIGNvbXBhcmluZyBvYmplY3RzIG9mXG4gKiB0aGUgc2FtZSBgdG9TdHJpbmdUYWdgLlxuICpcbiAqICoqTm90ZToqKiBUaGlzIGZ1bmN0aW9uIG9ubHkgc3VwcG9ydHMgY29tcGFyaW5nIHZhbHVlcyB3aXRoIHRhZ3Mgb2ZcbiAqIGBCb29sZWFuYCwgYERhdGVgLCBgRXJyb3JgLCBgTnVtYmVyYCwgYFJlZ0V4cGAsIG9yIGBTdHJpbmdgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvdGhlciBUaGUgb3RoZXIgb2JqZWN0IHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge3N0cmluZ30gdGFnIFRoZSBgdG9TdHJpbmdUYWdgIG9mIHRoZSBvYmplY3RzIHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBmbGFncy4gU2VlIGBiYXNlSXNFcXVhbGAgZm9yIG1vcmUgZGV0YWlscy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGN1c3RvbWl6ZXIgVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpc29ucy5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGVxdWFsRnVuYyBUaGUgZnVuY3Rpb24gdG8gZGV0ZXJtaW5lIGVxdWl2YWxlbnRzIG9mIHZhbHVlcy5cbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGFjayBUcmFja3MgdHJhdmVyc2VkIGBvYmplY3RgIGFuZCBgb3RoZXJgIG9iamVjdHMuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gZXF1YWxCeVRhZyhvYmplY3QsIG90aGVyLCB0YWcsIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spIHtcbiAgc3dpdGNoICh0YWcpIHtcbiAgICBjYXNlIGRhdGFWaWV3VGFnOlxuICAgICAgaWYgKChvYmplY3QuYnl0ZUxlbmd0aCAhPSBvdGhlci5ieXRlTGVuZ3RoKSB8fFxuICAgICAgICAgIChvYmplY3QuYnl0ZU9mZnNldCAhPSBvdGhlci5ieXRlT2Zmc2V0KSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBvYmplY3QgPSBvYmplY3QuYnVmZmVyO1xuICAgICAgb3RoZXIgPSBvdGhlci5idWZmZXI7XG5cbiAgICBjYXNlIGFycmF5QnVmZmVyVGFnOlxuICAgICAgaWYgKChvYmplY3QuYnl0ZUxlbmd0aCAhPSBvdGhlci5ieXRlTGVuZ3RoKSB8fFxuICAgICAgICAgICFlcXVhbEZ1bmMobmV3IFVpbnQ4QXJyYXkob2JqZWN0KSwgbmV3IFVpbnQ4QXJyYXkob3RoZXIpKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcblxuICAgIGNhc2UgYm9vbFRhZzpcbiAgICBjYXNlIGRhdGVUYWc6XG4gICAgY2FzZSBudW1iZXJUYWc6XG4gICAgICAvLyBDb2VyY2UgYm9vbGVhbnMgdG8gYDFgIG9yIGAwYCBhbmQgZGF0ZXMgdG8gbWlsbGlzZWNvbmRzLlxuICAgICAgLy8gSW52YWxpZCBkYXRlcyBhcmUgY29lcmNlZCB0byBgTmFOYC5cbiAgICAgIHJldHVybiBlcSgrb2JqZWN0LCArb3RoZXIpO1xuXG4gICAgY2FzZSBlcnJvclRhZzpcbiAgICAgIHJldHVybiBvYmplY3QubmFtZSA9PSBvdGhlci5uYW1lICYmIG9iamVjdC5tZXNzYWdlID09IG90aGVyLm1lc3NhZ2U7XG5cbiAgICBjYXNlIHJlZ2V4cFRhZzpcbiAgICBjYXNlIHN0cmluZ1RhZzpcbiAgICAgIC8vIENvZXJjZSByZWdleGVzIHRvIHN0cmluZ3MgYW5kIHRyZWF0IHN0cmluZ3MsIHByaW1pdGl2ZXMgYW5kIG9iamVjdHMsXG4gICAgICAvLyBhcyBlcXVhbC4gU2VlIGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1yZWdleHAucHJvdG90eXBlLnRvc3RyaW5nXG4gICAgICAvLyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgcmV0dXJuIG9iamVjdCA9PSAob3RoZXIgKyAnJyk7XG5cbiAgICBjYXNlIG1hcFRhZzpcbiAgICAgIHZhciBjb252ZXJ0ID0gbWFwVG9BcnJheTtcblxuICAgIGNhc2Ugc2V0VGFnOlxuICAgICAgdmFyIGlzUGFydGlhbCA9IGJpdG1hc2sgJiBDT01QQVJFX1BBUlRJQUxfRkxBRztcbiAgICAgIGNvbnZlcnQgfHwgKGNvbnZlcnQgPSBzZXRUb0FycmF5KTtcblxuICAgICAgaWYgKG9iamVjdC5zaXplICE9IG90aGVyLnNpemUgJiYgIWlzUGFydGlhbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICAvLyBBc3N1bWUgY3ljbGljIHZhbHVlcyBhcmUgZXF1YWwuXG4gICAgICB2YXIgc3RhY2tlZCA9IHN0YWNrLmdldChvYmplY3QpO1xuICAgICAgaWYgKHN0YWNrZWQpIHtcbiAgICAgICAgcmV0dXJuIHN0YWNrZWQgPT0gb3RoZXI7XG4gICAgICB9XG4gICAgICBiaXRtYXNrIHw9IENPTVBBUkVfVU5PUkRFUkVEX0ZMQUc7XG5cbiAgICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgb2JqZWN0cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgICAgc3RhY2suc2V0KG9iamVjdCwgb3RoZXIpO1xuICAgICAgdmFyIHJlc3VsdCA9IGVxdWFsQXJyYXlzKGNvbnZlcnQob2JqZWN0KSwgY29udmVydChvdGhlciksIGJpdG1hc2ssIGN1c3RvbWl6ZXIsIGVxdWFsRnVuYywgc3RhY2spO1xuICAgICAgc3RhY2tbJ2RlbGV0ZSddKG9iamVjdCk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuXG4gICAgY2FzZSBzeW1ib2xUYWc6XG4gICAgICBpZiAoc3ltYm9sVmFsdWVPZikge1xuICAgICAgICByZXR1cm4gc3ltYm9sVmFsdWVPZi5jYWxsKG9iamVjdCkgPT0gc3ltYm9sVmFsdWVPZi5jYWxsKG90aGVyKTtcbiAgICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZXF1YWxCeVRhZztcbiIsInZhciBnZXRBbGxLZXlzID0gcmVxdWlyZSgnLi9fZ2V0QWxsS2V5cycpO1xuXG4vKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciB2YWx1ZSBjb21wYXJpc29ucy4gKi9cbnZhciBDT01QQVJFX1BBUlRJQUxfRkxBRyA9IDE7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlSXNFcXVhbERlZXBgIGZvciBvYmplY3RzIHdpdGggc3VwcG9ydCBmb3JcbiAqIHBhcnRpYWwgZGVlcCBjb21wYXJpc29ucy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge09iamVjdH0gb3RoZXIgVGhlIG90aGVyIG9iamVjdCB0byBjb21wYXJlLlxuICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgZmxhZ3MuIFNlZSBgYmFzZUlzRXF1YWxgIGZvciBtb3JlIGRldGFpbHMuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjdXN0b21pemVyIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaXNvbnMuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBlcXVhbEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRldGVybWluZSBlcXVpdmFsZW50cyBvZiB2YWx1ZXMuXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhY2sgVHJhY2tzIHRyYXZlcnNlZCBgb2JqZWN0YCBhbmQgYG90aGVyYCBvYmplY3RzLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBvYmplY3RzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGVxdWFsT2JqZWN0cyhvYmplY3QsIG90aGVyLCBiaXRtYXNrLCBjdXN0b21pemVyLCBlcXVhbEZ1bmMsIHN0YWNrKSB7XG4gIHZhciBpc1BhcnRpYWwgPSBiaXRtYXNrICYgQ09NUEFSRV9QQVJUSUFMX0ZMQUcsXG4gICAgICBvYmpQcm9wcyA9IGdldEFsbEtleXMob2JqZWN0KSxcbiAgICAgIG9iakxlbmd0aCA9IG9ialByb3BzLmxlbmd0aCxcbiAgICAgIG90aFByb3BzID0gZ2V0QWxsS2V5cyhvdGhlciksXG4gICAgICBvdGhMZW5ndGggPSBvdGhQcm9wcy5sZW5ndGg7XG5cbiAgaWYgKG9iakxlbmd0aCAhPSBvdGhMZW5ndGggJiYgIWlzUGFydGlhbCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICB2YXIgaW5kZXggPSBvYmpMZW5ndGg7XG4gIHdoaWxlIChpbmRleC0tKSB7XG4gICAgdmFyIGtleSA9IG9ialByb3BzW2luZGV4XTtcbiAgICBpZiAoIShpc1BhcnRpYWwgPyBrZXkgaW4gb3RoZXIgOiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG90aGVyLCBrZXkpKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICAvLyBDaGVjayB0aGF0IGN5Y2xpYyB2YWx1ZXMgYXJlIGVxdWFsLlxuICB2YXIgb2JqU3RhY2tlZCA9IHN0YWNrLmdldChvYmplY3QpO1xuICB2YXIgb3RoU3RhY2tlZCA9IHN0YWNrLmdldChvdGhlcik7XG4gIGlmIChvYmpTdGFja2VkICYmIG90aFN0YWNrZWQpIHtcbiAgICByZXR1cm4gb2JqU3RhY2tlZCA9PSBvdGhlciAmJiBvdGhTdGFja2VkID09IG9iamVjdDtcbiAgfVxuICB2YXIgcmVzdWx0ID0gdHJ1ZTtcbiAgc3RhY2suc2V0KG9iamVjdCwgb3RoZXIpO1xuICBzdGFjay5zZXQob3RoZXIsIG9iamVjdCk7XG5cbiAgdmFyIHNraXBDdG9yID0gaXNQYXJ0aWFsO1xuICB3aGlsZSAoKytpbmRleCA8IG9iakxlbmd0aCkge1xuICAgIGtleSA9IG9ialByb3BzW2luZGV4XTtcbiAgICB2YXIgb2JqVmFsdWUgPSBvYmplY3Rba2V5XSxcbiAgICAgICAgb3RoVmFsdWUgPSBvdGhlcltrZXldO1xuXG4gICAgaWYgKGN1c3RvbWl6ZXIpIHtcbiAgICAgIHZhciBjb21wYXJlZCA9IGlzUGFydGlhbFxuICAgICAgICA/IGN1c3RvbWl6ZXIob3RoVmFsdWUsIG9ialZhbHVlLCBrZXksIG90aGVyLCBvYmplY3QsIHN0YWNrKVxuICAgICAgICA6IGN1c3RvbWl6ZXIob2JqVmFsdWUsIG90aFZhbHVlLCBrZXksIG9iamVjdCwgb3RoZXIsIHN0YWNrKTtcbiAgICB9XG4gICAgLy8gUmVjdXJzaXZlbHkgY29tcGFyZSBvYmplY3RzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgaWYgKCEoY29tcGFyZWQgPT09IHVuZGVmaW5lZFxuICAgICAgICAgID8gKG9ialZhbHVlID09PSBvdGhWYWx1ZSB8fCBlcXVhbEZ1bmMob2JqVmFsdWUsIG90aFZhbHVlLCBiaXRtYXNrLCBjdXN0b21pemVyLCBzdGFjaykpXG4gICAgICAgICAgOiBjb21wYXJlZFxuICAgICAgICApKSB7XG4gICAgICByZXN1bHQgPSBmYWxzZTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBza2lwQ3RvciB8fCAoc2tpcEN0b3IgPSBrZXkgPT0gJ2NvbnN0cnVjdG9yJyk7XG4gIH1cbiAgaWYgKHJlc3VsdCAmJiAhc2tpcEN0b3IpIHtcbiAgICB2YXIgb2JqQ3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcixcbiAgICAgICAgb3RoQ3RvciA9IG90aGVyLmNvbnN0cnVjdG9yO1xuXG4gICAgLy8gTm9uIGBPYmplY3RgIG9iamVjdCBpbnN0YW5jZXMgd2l0aCBkaWZmZXJlbnQgY29uc3RydWN0b3JzIGFyZSBub3QgZXF1YWwuXG4gICAgaWYgKG9iakN0b3IgIT0gb3RoQ3RvciAmJlxuICAgICAgICAoJ2NvbnN0cnVjdG9yJyBpbiBvYmplY3QgJiYgJ2NvbnN0cnVjdG9yJyBpbiBvdGhlcikgJiZcbiAgICAgICAgISh0eXBlb2Ygb2JqQ3RvciA9PSAnZnVuY3Rpb24nICYmIG9iakN0b3IgaW5zdGFuY2VvZiBvYmpDdG9yICYmXG4gICAgICAgICAgdHlwZW9mIG90aEN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiBvdGhDdG9yIGluc3RhbmNlb2Ygb3RoQ3RvcikpIHtcbiAgICAgIHJlc3VsdCA9IGZhbHNlO1xuICAgIH1cbiAgfVxuICBzdGFja1snZGVsZXRlJ10ob2JqZWN0KTtcbiAgc3RhY2tbJ2RlbGV0ZSddKG90aGVyKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBlcXVhbE9iamVjdHM7XG4iLCIvKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzLiAqL1xudmFyIGZyZWVHbG9iYWwgPSB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbCAmJiBnbG9iYWwuT2JqZWN0ID09PSBPYmplY3QgJiYgZ2xvYmFsO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZyZWVHbG9iYWw7XG4iLCJ2YXIgYmFzZUdldEFsbEtleXMgPSByZXF1aXJlKCcuL19iYXNlR2V0QWxsS2V5cycpLFxuICAgIGdldFN5bWJvbHMgPSByZXF1aXJlKCcuL19nZXRTeW1ib2xzJyksXG4gICAga2V5cyA9IHJlcXVpcmUoJy4va2V5cycpO1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXJyYXkgb2Ygb3duIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgYW5kIHN5bWJvbHMgb2YgYG9iamVjdGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMgYW5kIHN5bWJvbHMuXG4gKi9cbmZ1bmN0aW9uIGdldEFsbEtleXMob2JqZWN0KSB7XG4gIHJldHVybiBiYXNlR2V0QWxsS2V5cyhvYmplY3QsIGtleXMsIGdldFN5bWJvbHMpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGdldEFsbEtleXM7XG4iLCJ2YXIgYmFzZUdldEFsbEtleXMgPSByZXF1aXJlKCcuL19iYXNlR2V0QWxsS2V5cycpLFxuICAgIGdldFN5bWJvbHNJbiA9IHJlcXVpcmUoJy4vX2dldFN5bWJvbHNJbicpLFxuICAgIGtleXNJbiA9IHJlcXVpcmUoJy4va2V5c0luJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBhcnJheSBvZiBvd24gYW5kIGluaGVyaXRlZCBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIGFuZFxuICogc3ltYm9scyBvZiBgb2JqZWN0YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcyBhbmQgc3ltYm9scy5cbiAqL1xuZnVuY3Rpb24gZ2V0QWxsS2V5c0luKG9iamVjdCkge1xuICByZXR1cm4gYmFzZUdldEFsbEtleXMob2JqZWN0LCBrZXlzSW4sIGdldFN5bWJvbHNJbik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0QWxsS2V5c0luO1xuIiwidmFyIGlzS2V5YWJsZSA9IHJlcXVpcmUoJy4vX2lzS2V5YWJsZScpO1xuXG4vKipcbiAqIEdldHMgdGhlIGRhdGEgZm9yIGBtYXBgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gbWFwIFRoZSBtYXAgdG8gcXVlcnkuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSByZWZlcmVuY2Uga2V5LlxuICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1hcCBkYXRhLlxuICovXG5mdW5jdGlvbiBnZXRNYXBEYXRhKG1hcCwga2V5KSB7XG4gIHZhciBkYXRhID0gbWFwLl9fZGF0YV9fO1xuICByZXR1cm4gaXNLZXlhYmxlKGtleSlcbiAgICA/IGRhdGFbdHlwZW9mIGtleSA9PSAnc3RyaW5nJyA/ICdzdHJpbmcnIDogJ2hhc2gnXVxuICAgIDogZGF0YS5tYXA7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0TWFwRGF0YTtcbiIsInZhciBiYXNlSXNOYXRpdmUgPSByZXF1aXJlKCcuL19iYXNlSXNOYXRpdmUnKSxcbiAgICBnZXRWYWx1ZSA9IHJlcXVpcmUoJy4vX2dldFZhbHVlJyk7XG5cbi8qKlxuICogR2V0cyB0aGUgbmF0aXZlIGZ1bmN0aW9uIGF0IGBrZXlgIG9mIGBvYmplY3RgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIG1ldGhvZCB0byBnZXQuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZnVuY3Rpb24gaWYgaXQncyBuYXRpdmUsIGVsc2UgYHVuZGVmaW5lZGAuXG4gKi9cbmZ1bmN0aW9uIGdldE5hdGl2ZShvYmplY3QsIGtleSkge1xuICB2YXIgdmFsdWUgPSBnZXRWYWx1ZShvYmplY3QsIGtleSk7XG4gIHJldHVybiBiYXNlSXNOYXRpdmUodmFsdWUpID8gdmFsdWUgOiB1bmRlZmluZWQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0TmF0aXZlO1xuIiwidmFyIG92ZXJBcmcgPSByZXF1aXJlKCcuL19vdmVyQXJnJyk7XG5cbi8qKiBCdWlsdC1pbiB2YWx1ZSByZWZlcmVuY2VzLiAqL1xudmFyIGdldFByb3RvdHlwZSA9IG92ZXJBcmcoT2JqZWN0LmdldFByb3RvdHlwZU9mLCBPYmplY3QpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdldFByb3RvdHlwZTtcbiIsInZhciBTeW1ib2wgPSByZXF1aXJlKCcuL19TeW1ib2wnKTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBVc2VkIHRvIHJlc29sdmUgdGhlXG4gKiBbYHRvU3RyaW5nVGFnYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZylcbiAqIG9mIHZhbHVlcy5cbiAqL1xudmFyIG5hdGl2ZU9iamVjdFRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbi8qKiBCdWlsdC1pbiB2YWx1ZSByZWZlcmVuY2VzLiAqL1xudmFyIHN5bVRvU3RyaW5nVGFnID0gU3ltYm9sID8gU3ltYm9sLnRvU3RyaW5nVGFnIDogdW5kZWZpbmVkO1xuXG4vKipcbiAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUdldFRhZ2Agd2hpY2ggaWdub3JlcyBgU3ltYm9sLnRvU3RyaW5nVGFnYCB2YWx1ZXMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHF1ZXJ5LlxuICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgcmF3IGB0b1N0cmluZ1RhZ2AuXG4gKi9cbmZ1bmN0aW9uIGdldFJhd1RhZyh2YWx1ZSkge1xuICB2YXIgaXNPd24gPSBoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCBzeW1Ub1N0cmluZ1RhZyksXG4gICAgICB0YWcgPSB2YWx1ZVtzeW1Ub1N0cmluZ1RhZ107XG5cbiAgdHJ5IHtcbiAgICB2YWx1ZVtzeW1Ub1N0cmluZ1RhZ10gPSB1bmRlZmluZWQ7XG4gICAgdmFyIHVubWFza2VkID0gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge31cblxuICB2YXIgcmVzdWx0ID0gbmF0aXZlT2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gIGlmICh1bm1hc2tlZCkge1xuICAgIGlmIChpc093bikge1xuICAgICAgdmFsdWVbc3ltVG9TdHJpbmdUYWddID0gdGFnO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWxldGUgdmFsdWVbc3ltVG9TdHJpbmdUYWddO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGdldFJhd1RhZztcbiIsInZhciBhcnJheUZpbHRlciA9IHJlcXVpcmUoJy4vX2FycmF5RmlsdGVyJyksXG4gICAgc3R1YkFycmF5ID0gcmVxdWlyZSgnLi9zdHViQXJyYXknKTtcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIEJ1aWx0LWluIHZhbHVlIHJlZmVyZW5jZXMuICovXG52YXIgcHJvcGVydHlJc0VudW1lcmFibGUgPSBvYmplY3RQcm90by5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcblxuLyogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xudmFyIG5hdGl2ZUdldFN5bWJvbHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzO1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBlbnVtZXJhYmxlIHN5bWJvbHMgb2YgYG9iamVjdGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2Ygc3ltYm9scy5cbiAqL1xudmFyIGdldFN5bWJvbHMgPSAhbmF0aXZlR2V0U3ltYm9scyA/IHN0dWJBcnJheSA6IGZ1bmN0aW9uKG9iamVjdCkge1xuICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgb2JqZWN0ID0gT2JqZWN0KG9iamVjdCk7XG4gIHJldHVybiBhcnJheUZpbHRlcihuYXRpdmVHZXRTeW1ib2xzKG9iamVjdCksIGZ1bmN0aW9uKHN5bWJvbCkge1xuICAgIHJldHVybiBwcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKG9iamVjdCwgc3ltYm9sKTtcbiAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdldFN5bWJvbHM7XG4iLCJ2YXIgYXJyYXlQdXNoID0gcmVxdWlyZSgnLi9fYXJyYXlQdXNoJyksXG4gICAgZ2V0UHJvdG90eXBlID0gcmVxdWlyZSgnLi9fZ2V0UHJvdG90eXBlJyksXG4gICAgZ2V0U3ltYm9scyA9IHJlcXVpcmUoJy4vX2dldFN5bWJvbHMnKSxcbiAgICBzdHViQXJyYXkgPSByZXF1aXJlKCcuL3N0dWJBcnJheScpO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlR2V0U3ltYm9scyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHM7XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGFuZCBpbmhlcml0ZWQgZW51bWVyYWJsZSBzeW1ib2xzIG9mIGBvYmplY3RgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHN5bWJvbHMuXG4gKi9cbnZhciBnZXRTeW1ib2xzSW4gPSAhbmF0aXZlR2V0U3ltYm9scyA/IHN0dWJBcnJheSA6IGZ1bmN0aW9uKG9iamVjdCkge1xuICB2YXIgcmVzdWx0ID0gW107XG4gIHdoaWxlIChvYmplY3QpIHtcbiAgICBhcnJheVB1c2gocmVzdWx0LCBnZXRTeW1ib2xzKG9iamVjdCkpO1xuICAgIG9iamVjdCA9IGdldFByb3RvdHlwZShvYmplY3QpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdldFN5bWJvbHNJbjtcbiIsInZhciBEYXRhVmlldyA9IHJlcXVpcmUoJy4vX0RhdGFWaWV3JyksXG4gICAgTWFwID0gcmVxdWlyZSgnLi9fTWFwJyksXG4gICAgUHJvbWlzZSA9IHJlcXVpcmUoJy4vX1Byb21pc2UnKSxcbiAgICBTZXQgPSByZXF1aXJlKCcuL19TZXQnKSxcbiAgICBXZWFrTWFwID0gcmVxdWlyZSgnLi9fV2Vha01hcCcpLFxuICAgIGJhc2VHZXRUYWcgPSByZXF1aXJlKCcuL19iYXNlR2V0VGFnJyksXG4gICAgdG9Tb3VyY2UgPSByZXF1aXJlKCcuL190b1NvdXJjZScpO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgbWFwVGFnID0gJ1tvYmplY3QgTWFwXScsXG4gICAgb2JqZWN0VGFnID0gJ1tvYmplY3QgT2JqZWN0XScsXG4gICAgcHJvbWlzZVRhZyA9ICdbb2JqZWN0IFByb21pc2VdJyxcbiAgICBzZXRUYWcgPSAnW29iamVjdCBTZXRdJyxcbiAgICB3ZWFrTWFwVGFnID0gJ1tvYmplY3QgV2Vha01hcF0nO1xuXG52YXIgZGF0YVZpZXdUYWcgPSAnW29iamVjdCBEYXRhVmlld10nO1xuXG4vKiogVXNlZCB0byBkZXRlY3QgbWFwcywgc2V0cywgYW5kIHdlYWttYXBzLiAqL1xudmFyIGRhdGFWaWV3Q3RvclN0cmluZyA9IHRvU291cmNlKERhdGFWaWV3KSxcbiAgICBtYXBDdG9yU3RyaW5nID0gdG9Tb3VyY2UoTWFwKSxcbiAgICBwcm9taXNlQ3RvclN0cmluZyA9IHRvU291cmNlKFByb21pc2UpLFxuICAgIHNldEN0b3JTdHJpbmcgPSB0b1NvdXJjZShTZXQpLFxuICAgIHdlYWtNYXBDdG9yU3RyaW5nID0gdG9Tb3VyY2UoV2Vha01hcCk7XG5cbi8qKlxuICogR2V0cyB0aGUgYHRvU3RyaW5nVGFnYCBvZiBgdmFsdWVgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIGB0b1N0cmluZ1RhZ2AuXG4gKi9cbnZhciBnZXRUYWcgPSBiYXNlR2V0VGFnO1xuXG4vLyBGYWxsYmFjayBmb3IgZGF0YSB2aWV3cywgbWFwcywgc2V0cywgYW5kIHdlYWsgbWFwcyBpbiBJRSAxMSBhbmQgcHJvbWlzZXMgaW4gTm9kZS5qcyA8IDYuXG5pZiAoKERhdGFWaWV3ICYmIGdldFRhZyhuZXcgRGF0YVZpZXcobmV3IEFycmF5QnVmZmVyKDEpKSkgIT0gZGF0YVZpZXdUYWcpIHx8XG4gICAgKE1hcCAmJiBnZXRUYWcobmV3IE1hcCkgIT0gbWFwVGFnKSB8fFxuICAgIChQcm9taXNlICYmIGdldFRhZyhQcm9taXNlLnJlc29sdmUoKSkgIT0gcHJvbWlzZVRhZykgfHxcbiAgICAoU2V0ICYmIGdldFRhZyhuZXcgU2V0KSAhPSBzZXRUYWcpIHx8XG4gICAgKFdlYWtNYXAgJiYgZ2V0VGFnKG5ldyBXZWFrTWFwKSAhPSB3ZWFrTWFwVGFnKSkge1xuICBnZXRUYWcgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHZhciByZXN1bHQgPSBiYXNlR2V0VGFnKHZhbHVlKSxcbiAgICAgICAgQ3RvciA9IHJlc3VsdCA9PSBvYmplY3RUYWcgPyB2YWx1ZS5jb25zdHJ1Y3RvciA6IHVuZGVmaW5lZCxcbiAgICAgICAgY3RvclN0cmluZyA9IEN0b3IgPyB0b1NvdXJjZShDdG9yKSA6ICcnO1xuXG4gICAgaWYgKGN0b3JTdHJpbmcpIHtcbiAgICAgIHN3aXRjaCAoY3RvclN0cmluZykge1xuICAgICAgICBjYXNlIGRhdGFWaWV3Q3RvclN0cmluZzogcmV0dXJuIGRhdGFWaWV3VGFnO1xuICAgICAgICBjYXNlIG1hcEN0b3JTdHJpbmc6IHJldHVybiBtYXBUYWc7XG4gICAgICAgIGNhc2UgcHJvbWlzZUN0b3JTdHJpbmc6IHJldHVybiBwcm9taXNlVGFnO1xuICAgICAgICBjYXNlIHNldEN0b3JTdHJpbmc6IHJldHVybiBzZXRUYWc7XG4gICAgICAgIGNhc2Ugd2Vha01hcEN0b3JTdHJpbmc6IHJldHVybiB3ZWFrTWFwVGFnO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGdldFRhZztcbiIsIi8qKlxuICogR2V0cyB0aGUgdmFsdWUgYXQgYGtleWAgb2YgYG9iamVjdGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcHJvcGVydHkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIGdldFZhbHVlKG9iamVjdCwga2V5KSB7XG4gIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IHVuZGVmaW5lZCA6IG9iamVjdFtrZXldO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGdldFZhbHVlO1xuIiwidmFyIG5hdGl2ZUNyZWF0ZSA9IHJlcXVpcmUoJy4vX25hdGl2ZUNyZWF0ZScpO1xuXG4vKipcbiAqIFJlbW92ZXMgYWxsIGtleS12YWx1ZSBlbnRyaWVzIGZyb20gdGhlIGhhc2guXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGNsZWFyXG4gKiBAbWVtYmVyT2YgSGFzaFxuICovXG5mdW5jdGlvbiBoYXNoQ2xlYXIoKSB7XG4gIHRoaXMuX19kYXRhX18gPSBuYXRpdmVDcmVhdGUgPyBuYXRpdmVDcmVhdGUobnVsbCkgOiB7fTtcbiAgdGhpcy5zaXplID0gMDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBoYXNoQ2xlYXI7XG4iLCIvKipcbiAqIFJlbW92ZXMgYGtleWAgYW5kIGl0cyB2YWx1ZSBmcm9tIHRoZSBoYXNoLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBkZWxldGVcbiAqIEBtZW1iZXJPZiBIYXNoXG4gKiBAcGFyYW0ge09iamVjdH0gaGFzaCBUaGUgaGFzaCB0byBtb2RpZnkuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZW50cnkgd2FzIHJlbW92ZWQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gaGFzaERlbGV0ZShrZXkpIHtcbiAgdmFyIHJlc3VsdCA9IHRoaXMuaGFzKGtleSkgJiYgZGVsZXRlIHRoaXMuX19kYXRhX19ba2V5XTtcbiAgdGhpcy5zaXplIC09IHJlc3VsdCA/IDEgOiAwO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGhhc2hEZWxldGU7XG4iLCJ2YXIgbmF0aXZlQ3JlYXRlID0gcmVxdWlyZSgnLi9fbmF0aXZlQ3JlYXRlJyk7XG5cbi8qKiBVc2VkIHRvIHN0YW5kLWluIGZvciBgdW5kZWZpbmVkYCBoYXNoIHZhbHVlcy4gKi9cbnZhciBIQVNIX1VOREVGSU5FRCA9ICdfX2xvZGFzaF9oYXNoX3VuZGVmaW5lZF9fJztcblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBHZXRzIHRoZSBoYXNoIHZhbHVlIGZvciBga2V5YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgZ2V0XG4gKiBAbWVtYmVyT2YgSGFzaFxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIGhhc2hHZXQoa2V5KSB7XG4gIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXztcbiAgaWYgKG5hdGl2ZUNyZWF0ZSkge1xuICAgIHZhciByZXN1bHQgPSBkYXRhW2tleV07XG4gICAgcmV0dXJuIHJlc3VsdCA9PT0gSEFTSF9VTkRFRklORUQgPyB1bmRlZmluZWQgOiByZXN1bHQ7XG4gIH1cbiAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwoZGF0YSwga2V5KSA/IGRhdGFba2V5XSA6IHVuZGVmaW5lZDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBoYXNoR2V0O1xuIiwidmFyIG5hdGl2ZUNyZWF0ZSA9IHJlcXVpcmUoJy4vX25hdGl2ZUNyZWF0ZScpO1xuXG4vKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4vKipcbiAqIENoZWNrcyBpZiBhIGhhc2ggdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgaGFzXG4gKiBAbWVtYmVyT2YgSGFzaFxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGhhc2hIYXMoa2V5KSB7XG4gIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXztcbiAgcmV0dXJuIG5hdGl2ZUNyZWF0ZSA/IChkYXRhW2tleV0gIT09IHVuZGVmaW5lZCkgOiBoYXNPd25Qcm9wZXJ0eS5jYWxsKGRhdGEsIGtleSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaGFzaEhhcztcbiIsInZhciBuYXRpdmVDcmVhdGUgPSByZXF1aXJlKCcuL19uYXRpdmVDcmVhdGUnKTtcblxuLyoqIFVzZWQgdG8gc3RhbmQtaW4gZm9yIGB1bmRlZmluZWRgIGhhc2ggdmFsdWVzLiAqL1xudmFyIEhBU0hfVU5ERUZJTkVEID0gJ19fbG9kYXNoX2hhc2hfdW5kZWZpbmVkX18nO1xuXG4vKipcbiAqIFNldHMgdGhlIGhhc2ggYGtleWAgdG8gYHZhbHVlYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgc2V0XG4gKiBAbWVtYmVyT2YgSGFzaFxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBoYXNoIGluc3RhbmNlLlxuICovXG5mdW5jdGlvbiBoYXNoU2V0KGtleSwgdmFsdWUpIHtcbiAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICB0aGlzLnNpemUgKz0gdGhpcy5oYXMoa2V5KSA/IDAgOiAxO1xuICBkYXRhW2tleV0gPSAobmF0aXZlQ3JlYXRlICYmIHZhbHVlID09PSB1bmRlZmluZWQpID8gSEFTSF9VTkRFRklORUQgOiB2YWx1ZTtcbiAgcmV0dXJuIHRoaXM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaGFzaFNldDtcbiIsIi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZXMgYW4gYXJyYXkgY2xvbmUuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBjbG9uZS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgaW5pdGlhbGl6ZWQgY2xvbmUuXG4gKi9cbmZ1bmN0aW9uIGluaXRDbG9uZUFycmF5KGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICByZXN1bHQgPSBuZXcgYXJyYXkuY29uc3RydWN0b3IobGVuZ3RoKTtcblxuICAvLyBBZGQgcHJvcGVydGllcyBhc3NpZ25lZCBieSBgUmVnRXhwI2V4ZWNgLlxuICBpZiAobGVuZ3RoICYmIHR5cGVvZiBhcnJheVswXSA9PSAnc3RyaW5nJyAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKGFycmF5LCAnaW5kZXgnKSkge1xuICAgIHJlc3VsdC5pbmRleCA9IGFycmF5LmluZGV4O1xuICAgIHJlc3VsdC5pbnB1dCA9IGFycmF5LmlucHV0O1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaW5pdENsb25lQXJyYXk7XG4iLCJ2YXIgY2xvbmVBcnJheUJ1ZmZlciA9IHJlcXVpcmUoJy4vX2Nsb25lQXJyYXlCdWZmZXInKSxcbiAgICBjbG9uZURhdGFWaWV3ID0gcmVxdWlyZSgnLi9fY2xvbmVEYXRhVmlldycpLFxuICAgIGNsb25lUmVnRXhwID0gcmVxdWlyZSgnLi9fY2xvbmVSZWdFeHAnKSxcbiAgICBjbG9uZVN5bWJvbCA9IHJlcXVpcmUoJy4vX2Nsb25lU3ltYm9sJyksXG4gICAgY2xvbmVUeXBlZEFycmF5ID0gcmVxdWlyZSgnLi9fY2xvbmVUeXBlZEFycmF5Jyk7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBib29sVGFnID0gJ1tvYmplY3QgQm9vbGVhbl0nLFxuICAgIGRhdGVUYWcgPSAnW29iamVjdCBEYXRlXScsXG4gICAgbWFwVGFnID0gJ1tvYmplY3QgTWFwXScsXG4gICAgbnVtYmVyVGFnID0gJ1tvYmplY3QgTnVtYmVyXScsXG4gICAgcmVnZXhwVGFnID0gJ1tvYmplY3QgUmVnRXhwXScsXG4gICAgc2V0VGFnID0gJ1tvYmplY3QgU2V0XScsXG4gICAgc3RyaW5nVGFnID0gJ1tvYmplY3QgU3RyaW5nXScsXG4gICAgc3ltYm9sVGFnID0gJ1tvYmplY3QgU3ltYm9sXSc7XG5cbnZhciBhcnJheUJ1ZmZlclRhZyA9ICdbb2JqZWN0IEFycmF5QnVmZmVyXScsXG4gICAgZGF0YVZpZXdUYWcgPSAnW29iamVjdCBEYXRhVmlld10nLFxuICAgIGZsb2F0MzJUYWcgPSAnW29iamVjdCBGbG9hdDMyQXJyYXldJyxcbiAgICBmbG9hdDY0VGFnID0gJ1tvYmplY3QgRmxvYXQ2NEFycmF5XScsXG4gICAgaW50OFRhZyA9ICdbb2JqZWN0IEludDhBcnJheV0nLFxuICAgIGludDE2VGFnID0gJ1tvYmplY3QgSW50MTZBcnJheV0nLFxuICAgIGludDMyVGFnID0gJ1tvYmplY3QgSW50MzJBcnJheV0nLFxuICAgIHVpbnQ4VGFnID0gJ1tvYmplY3QgVWludDhBcnJheV0nLFxuICAgIHVpbnQ4Q2xhbXBlZFRhZyA9ICdbb2JqZWN0IFVpbnQ4Q2xhbXBlZEFycmF5XScsXG4gICAgdWludDE2VGFnID0gJ1tvYmplY3QgVWludDE2QXJyYXldJyxcbiAgICB1aW50MzJUYWcgPSAnW29iamVjdCBVaW50MzJBcnJheV0nO1xuXG4vKipcbiAqIEluaXRpYWxpemVzIGFuIG9iamVjdCBjbG9uZSBiYXNlZCBvbiBpdHMgYHRvU3RyaW5nVGFnYC5cbiAqXG4gKiAqKk5vdGU6KiogVGhpcyBmdW5jdGlvbiBvbmx5IHN1cHBvcnRzIGNsb25pbmcgdmFsdWVzIHdpdGggdGFncyBvZlxuICogYEJvb2xlYW5gLCBgRGF0ZWAsIGBFcnJvcmAsIGBNYXBgLCBgTnVtYmVyYCwgYFJlZ0V4cGAsIGBTZXRgLCBvciBgU3RyaW5nYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNsb25lLlxuICogQHBhcmFtIHtzdHJpbmd9IHRhZyBUaGUgYHRvU3RyaW5nVGFnYCBvZiB0aGUgb2JqZWN0IHRvIGNsb25lLlxuICogQHBhcmFtIHtib29sZWFufSBbaXNEZWVwXSBTcGVjaWZ5IGEgZGVlcCBjbG9uZS5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGluaXRpYWxpemVkIGNsb25lLlxuICovXG5mdW5jdGlvbiBpbml0Q2xvbmVCeVRhZyhvYmplY3QsIHRhZywgaXNEZWVwKSB7XG4gIHZhciBDdG9yID0gb2JqZWN0LmNvbnN0cnVjdG9yO1xuICBzd2l0Y2ggKHRhZykge1xuICAgIGNhc2UgYXJyYXlCdWZmZXJUYWc6XG4gICAgICByZXR1cm4gY2xvbmVBcnJheUJ1ZmZlcihvYmplY3QpO1xuXG4gICAgY2FzZSBib29sVGFnOlxuICAgIGNhc2UgZGF0ZVRhZzpcbiAgICAgIHJldHVybiBuZXcgQ3Rvcigrb2JqZWN0KTtcblxuICAgIGNhc2UgZGF0YVZpZXdUYWc6XG4gICAgICByZXR1cm4gY2xvbmVEYXRhVmlldyhvYmplY3QsIGlzRGVlcCk7XG5cbiAgICBjYXNlIGZsb2F0MzJUYWc6IGNhc2UgZmxvYXQ2NFRhZzpcbiAgICBjYXNlIGludDhUYWc6IGNhc2UgaW50MTZUYWc6IGNhc2UgaW50MzJUYWc6XG4gICAgY2FzZSB1aW50OFRhZzogY2FzZSB1aW50OENsYW1wZWRUYWc6IGNhc2UgdWludDE2VGFnOiBjYXNlIHVpbnQzMlRhZzpcbiAgICAgIHJldHVybiBjbG9uZVR5cGVkQXJyYXkob2JqZWN0LCBpc0RlZXApO1xuXG4gICAgY2FzZSBtYXBUYWc6XG4gICAgICByZXR1cm4gbmV3IEN0b3I7XG5cbiAgICBjYXNlIG51bWJlclRhZzpcbiAgICBjYXNlIHN0cmluZ1RhZzpcbiAgICAgIHJldHVybiBuZXcgQ3RvcihvYmplY3QpO1xuXG4gICAgY2FzZSByZWdleHBUYWc6XG4gICAgICByZXR1cm4gY2xvbmVSZWdFeHAob2JqZWN0KTtcblxuICAgIGNhc2Ugc2V0VGFnOlxuICAgICAgcmV0dXJuIG5ldyBDdG9yO1xuXG4gICAgY2FzZSBzeW1ib2xUYWc6XG4gICAgICByZXR1cm4gY2xvbmVTeW1ib2wob2JqZWN0KTtcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGluaXRDbG9uZUJ5VGFnO1xuIiwidmFyIGJhc2VDcmVhdGUgPSByZXF1aXJlKCcuL19iYXNlQ3JlYXRlJyksXG4gICAgZ2V0UHJvdG90eXBlID0gcmVxdWlyZSgnLi9fZ2V0UHJvdG90eXBlJyksXG4gICAgaXNQcm90b3R5cGUgPSByZXF1aXJlKCcuL19pc1Byb3RvdHlwZScpO1xuXG4vKipcbiAqIEluaXRpYWxpemVzIGFuIG9iamVjdCBjbG9uZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNsb25lLlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgaW5pdGlhbGl6ZWQgY2xvbmUuXG4gKi9cbmZ1bmN0aW9uIGluaXRDbG9uZU9iamVjdChvYmplY3QpIHtcbiAgcmV0dXJuICh0eXBlb2Ygb2JqZWN0LmNvbnN0cnVjdG9yID09ICdmdW5jdGlvbicgJiYgIWlzUHJvdG90eXBlKG9iamVjdCkpXG4gICAgPyBiYXNlQ3JlYXRlKGdldFByb3RvdHlwZShvYmplY3QpKVxuICAgIDoge307XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaW5pdENsb25lT2JqZWN0O1xuIiwiLyoqIFVzZWQgYXMgcmVmZXJlbmNlcyBmb3IgdmFyaW91cyBgTnVtYmVyYCBjb25zdGFudHMuICovXG52YXIgTUFYX1NBRkVfSU5URUdFUiA9IDkwMDcxOTkyNTQ3NDA5OTE7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCB1bnNpZ25lZCBpbnRlZ2VyIHZhbHVlcy4gKi9cbnZhciByZUlzVWludCA9IC9eKD86MHxbMS05XVxcZCopJC87XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBhcnJheS1saWtlIGluZGV4LlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoPU1BWF9TQUZFX0lOVEVHRVJdIFRoZSB1cHBlciBib3VuZHMgb2YgYSB2YWxpZCBpbmRleC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgdmFsaWQgaW5kZXgsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gaXNJbmRleCh2YWx1ZSwgbGVuZ3RoKSB7XG4gIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICBsZW5ndGggPSBsZW5ndGggPT0gbnVsbCA/IE1BWF9TQUZFX0lOVEVHRVIgOiBsZW5ndGg7XG5cbiAgcmV0dXJuICEhbGVuZ3RoICYmXG4gICAgKHR5cGUgPT0gJ251bWJlcicgfHxcbiAgICAgICh0eXBlICE9ICdzeW1ib2wnICYmIHJlSXNVaW50LnRlc3QodmFsdWUpKSkgJiZcbiAgICAgICAgKHZhbHVlID4gLTEgJiYgdmFsdWUgJSAxID09IDAgJiYgdmFsdWUgPCBsZW5ndGgpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzSW5kZXg7XG4iLCIvKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHN1aXRhYmxlIGZvciB1c2UgYXMgdW5pcXVlIG9iamVjdCBrZXkuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gaXNLZXlhYmxlKHZhbHVlKSB7XG4gIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICByZXR1cm4gKHR5cGUgPT0gJ3N0cmluZycgfHwgdHlwZSA9PSAnbnVtYmVyJyB8fCB0eXBlID09ICdzeW1ib2wnIHx8IHR5cGUgPT0gJ2Jvb2xlYW4nKVxuICAgID8gKHZhbHVlICE9PSAnX19wcm90b19fJylcbiAgICA6ICh2YWx1ZSA9PT0gbnVsbCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNLZXlhYmxlO1xuIiwidmFyIGNvcmVKc0RhdGEgPSByZXF1aXJlKCcuL19jb3JlSnNEYXRhJyk7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBtZXRob2RzIG1hc3F1ZXJhZGluZyBhcyBuYXRpdmUuICovXG52YXIgbWFza1NyY0tleSA9IChmdW5jdGlvbigpIHtcbiAgdmFyIHVpZCA9IC9bXi5dKyQvLmV4ZWMoY29yZUpzRGF0YSAmJiBjb3JlSnNEYXRhLmtleXMgJiYgY29yZUpzRGF0YS5rZXlzLklFX1BST1RPIHx8ICcnKTtcbiAgcmV0dXJuIHVpZCA/ICgnU3ltYm9sKHNyYylfMS4nICsgdWlkKSA6ICcnO1xufSgpKTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYGZ1bmNgIGhhcyBpdHMgc291cmNlIG1hc2tlZC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYGZ1bmNgIGlzIG1hc2tlZCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBpc01hc2tlZChmdW5jKSB7XG4gIHJldHVybiAhIW1hc2tTcmNLZXkgJiYgKG1hc2tTcmNLZXkgaW4gZnVuYyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNNYXNrZWQ7XG4iLCIvKiogVXNlZCBmb3IgYnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGxpa2VseSBhIHByb3RvdHlwZSBvYmplY3QuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBwcm90b3R5cGUsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gaXNQcm90b3R5cGUodmFsdWUpIHtcbiAgdmFyIEN0b3IgPSB2YWx1ZSAmJiB2YWx1ZS5jb25zdHJ1Y3RvcixcbiAgICAgIHByb3RvID0gKHR5cGVvZiBDdG9yID09ICdmdW5jdGlvbicgJiYgQ3Rvci5wcm90b3R5cGUpIHx8IG9iamVjdFByb3RvO1xuXG4gIHJldHVybiB2YWx1ZSA9PT0gcHJvdG87XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNQcm90b3R5cGU7XG4iLCIvKipcbiAqIFJlbW92ZXMgYWxsIGtleS12YWx1ZSBlbnRyaWVzIGZyb20gdGhlIGxpc3QgY2FjaGUuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGNsZWFyXG4gKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gKi9cbmZ1bmN0aW9uIGxpc3RDYWNoZUNsZWFyKCkge1xuICB0aGlzLl9fZGF0YV9fID0gW107XG4gIHRoaXMuc2l6ZSA9IDA7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbGlzdENhY2hlQ2xlYXI7XG4iLCJ2YXIgYXNzb2NJbmRleE9mID0gcmVxdWlyZSgnLi9fYXNzb2NJbmRleE9mJyk7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBhcnJheVByb3RvID0gQXJyYXkucHJvdG90eXBlO1xuXG4vKiogQnVpbHQtaW4gdmFsdWUgcmVmZXJlbmNlcy4gKi9cbnZhciBzcGxpY2UgPSBhcnJheVByb3RvLnNwbGljZTtcblxuLyoqXG4gKiBSZW1vdmVzIGBrZXlgIGFuZCBpdHMgdmFsdWUgZnJvbSB0aGUgbGlzdCBjYWNoZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgZGVsZXRlXG4gKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHJlbW92ZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZW50cnkgd2FzIHJlbW92ZWQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gbGlzdENhY2hlRGVsZXRlKGtleSkge1xuICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX18sXG4gICAgICBpbmRleCA9IGFzc29jSW5kZXhPZihkYXRhLCBrZXkpO1xuXG4gIGlmIChpbmRleCA8IDApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgdmFyIGxhc3RJbmRleCA9IGRhdGEubGVuZ3RoIC0gMTtcbiAgaWYgKGluZGV4ID09IGxhc3RJbmRleCkge1xuICAgIGRhdGEucG9wKCk7XG4gIH0gZWxzZSB7XG4gICAgc3BsaWNlLmNhbGwoZGF0YSwgaW5kZXgsIDEpO1xuICB9XG4gIC0tdGhpcy5zaXplO1xuICByZXR1cm4gdHJ1ZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBsaXN0Q2FjaGVEZWxldGU7XG4iLCJ2YXIgYXNzb2NJbmRleE9mID0gcmVxdWlyZSgnLi9fYXNzb2NJbmRleE9mJyk7XG5cbi8qKlxuICogR2V0cyB0aGUgbGlzdCBjYWNoZSB2YWx1ZSBmb3IgYGtleWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGdldFxuICogQG1lbWJlck9mIExpc3RDYWNoZVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIGxpc3RDYWNoZUdldChrZXkpIHtcbiAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fLFxuICAgICAgaW5kZXggPSBhc3NvY0luZGV4T2YoZGF0YSwga2V5KTtcblxuICByZXR1cm4gaW5kZXggPCAwID8gdW5kZWZpbmVkIDogZGF0YVtpbmRleF1bMV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbGlzdENhY2hlR2V0O1xuIiwidmFyIGFzc29jSW5kZXhPZiA9IHJlcXVpcmUoJy4vX2Fzc29jSW5kZXhPZicpO1xuXG4vKipcbiAqIENoZWNrcyBpZiBhIGxpc3QgY2FjaGUgdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgaGFzXG4gKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFuIGVudHJ5IGZvciBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gbGlzdENhY2hlSGFzKGtleSkge1xuICByZXR1cm4gYXNzb2NJbmRleE9mKHRoaXMuX19kYXRhX18sIGtleSkgPiAtMTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBsaXN0Q2FjaGVIYXM7XG4iLCJ2YXIgYXNzb2NJbmRleE9mID0gcmVxdWlyZSgnLi9fYXNzb2NJbmRleE9mJyk7XG5cbi8qKlxuICogU2V0cyB0aGUgbGlzdCBjYWNoZSBga2V5YCB0byBgdmFsdWVgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBzZXRcbiAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gc2V0LlxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbGlzdCBjYWNoZSBpbnN0YW5jZS5cbiAqL1xuZnVuY3Rpb24gbGlzdENhY2hlU2V0KGtleSwgdmFsdWUpIHtcbiAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fLFxuICAgICAgaW5kZXggPSBhc3NvY0luZGV4T2YoZGF0YSwga2V5KTtcblxuICBpZiAoaW5kZXggPCAwKSB7XG4gICAgKyt0aGlzLnNpemU7XG4gICAgZGF0YS5wdXNoKFtrZXksIHZhbHVlXSk7XG4gIH0gZWxzZSB7XG4gICAgZGF0YVtpbmRleF1bMV0gPSB2YWx1ZTtcbiAgfVxuICByZXR1cm4gdGhpcztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBsaXN0Q2FjaGVTZXQ7XG4iLCJ2YXIgSGFzaCA9IHJlcXVpcmUoJy4vX0hhc2gnKSxcbiAgICBMaXN0Q2FjaGUgPSByZXF1aXJlKCcuL19MaXN0Q2FjaGUnKSxcbiAgICBNYXAgPSByZXF1aXJlKCcuL19NYXAnKTtcblxuLyoqXG4gKiBSZW1vdmVzIGFsbCBrZXktdmFsdWUgZW50cmllcyBmcm9tIHRoZSBtYXAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGNsZWFyXG4gKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAqL1xuZnVuY3Rpb24gbWFwQ2FjaGVDbGVhcigpIHtcbiAgdGhpcy5zaXplID0gMDtcbiAgdGhpcy5fX2RhdGFfXyA9IHtcbiAgICAnaGFzaCc6IG5ldyBIYXNoLFxuICAgICdtYXAnOiBuZXcgKE1hcCB8fCBMaXN0Q2FjaGUpLFxuICAgICdzdHJpbmcnOiBuZXcgSGFzaFxuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG1hcENhY2hlQ2xlYXI7XG4iLCJ2YXIgZ2V0TWFwRGF0YSA9IHJlcXVpcmUoJy4vX2dldE1hcERhdGEnKTtcblxuLyoqXG4gKiBSZW1vdmVzIGBrZXlgIGFuZCBpdHMgdmFsdWUgZnJvbSB0aGUgbWFwLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBkZWxldGVcbiAqIEBtZW1iZXJPZiBNYXBDYWNoZVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byByZW1vdmUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVudHJ5IHdhcyByZW1vdmVkLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIG1hcENhY2hlRGVsZXRlKGtleSkge1xuICB2YXIgcmVzdWx0ID0gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpWydkZWxldGUnXShrZXkpO1xuICB0aGlzLnNpemUgLT0gcmVzdWx0ID8gMSA6IDA7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbWFwQ2FjaGVEZWxldGU7XG4iLCJ2YXIgZ2V0TWFwRGF0YSA9IHJlcXVpcmUoJy4vX2dldE1hcERhdGEnKTtcblxuLyoqXG4gKiBHZXRzIHRoZSBtYXAgdmFsdWUgZm9yIGBrZXlgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBnZXRcbiAqIEBtZW1iZXJPZiBNYXBDYWNoZVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIG1hcENhY2hlR2V0KGtleSkge1xuICByZXR1cm4gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLmdldChrZXkpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG1hcENhY2hlR2V0O1xuIiwidmFyIGdldE1hcERhdGEgPSByZXF1aXJlKCcuL19nZXRNYXBEYXRhJyk7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgbWFwIHZhbHVlIGZvciBga2V5YCBleGlzdHMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGhhc1xuICogQG1lbWJlck9mIE1hcENhY2hlXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIGVudHJ5IHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFuIGVudHJ5IGZvciBga2V5YCBleGlzdHMsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gbWFwQ2FjaGVIYXMoa2V5KSB7XG4gIHJldHVybiBnZXRNYXBEYXRhKHRoaXMsIGtleSkuaGFzKGtleSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbWFwQ2FjaGVIYXM7XG4iLCJ2YXIgZ2V0TWFwRGF0YSA9IHJlcXVpcmUoJy4vX2dldE1hcERhdGEnKTtcblxuLyoqXG4gKiBTZXRzIHRoZSBtYXAgYGtleWAgdG8gYHZhbHVlYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgc2V0XG4gKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gc2V0LlxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gc2V0LlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgbWFwIGNhY2hlIGluc3RhbmNlLlxuICovXG5mdW5jdGlvbiBtYXBDYWNoZVNldChrZXksIHZhbHVlKSB7XG4gIHZhciBkYXRhID0gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLFxuICAgICAgc2l6ZSA9IGRhdGEuc2l6ZTtcblxuICBkYXRhLnNldChrZXksIHZhbHVlKTtcbiAgdGhpcy5zaXplICs9IGRhdGEuc2l6ZSA9PSBzaXplID8gMCA6IDE7XG4gIHJldHVybiB0aGlzO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG1hcENhY2hlU2V0O1xuIiwiLyoqXG4gKiBDb252ZXJ0cyBgbWFwYCB0byBpdHMga2V5LXZhbHVlIHBhaXJzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gbWFwIFRoZSBtYXAgdG8gY29udmVydC5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUga2V5LXZhbHVlIHBhaXJzLlxuICovXG5mdW5jdGlvbiBtYXBUb0FycmF5KG1hcCkge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIHJlc3VsdCA9IEFycmF5KG1hcC5zaXplKTtcblxuICBtYXAuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgcmVzdWx0WysraW5kZXhdID0gW2tleSwgdmFsdWVdO1xuICB9KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBtYXBUb0FycmF5O1xuIiwidmFyIGdldE5hdGl2ZSA9IHJlcXVpcmUoJy4vX2dldE5hdGl2ZScpO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyB0aGF0IGFyZSB2ZXJpZmllZCB0byBiZSBuYXRpdmUuICovXG52YXIgbmF0aXZlQ3JlYXRlID0gZ2V0TmF0aXZlKE9iamVjdCwgJ2NyZWF0ZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUNyZWF0ZTtcbiIsInZhciBvdmVyQXJnID0gcmVxdWlyZSgnLi9fb3ZlckFyZycpO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlS2V5cyA9IG92ZXJBcmcoT2JqZWN0LmtleXMsIE9iamVjdCk7XG5cbm1vZHVsZS5leHBvcnRzID0gbmF0aXZlS2V5cztcbiIsIi8qKlxuICogVGhpcyBmdW5jdGlvbiBpcyBsaWtlXG4gKiBbYE9iamVjdC5rZXlzYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtb2JqZWN0LmtleXMpXG4gKiBleGNlcHQgdGhhdCBpdCBpbmNsdWRlcyBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICovXG5mdW5jdGlvbiBuYXRpdmVLZXlzSW4ob2JqZWN0KSB7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgaWYgKG9iamVjdCAhPSBudWxsKSB7XG4gICAgZm9yICh2YXIga2V5IGluIE9iamVjdChvYmplY3QpKSB7XG4gICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUtleXNJbjtcbiIsInZhciBmcmVlR2xvYmFsID0gcmVxdWlyZSgnLi9fZnJlZUdsb2JhbCcpO1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGV4cG9ydHNgLiAqL1xudmFyIGZyZWVFeHBvcnRzID0gdHlwZW9mIGV4cG9ydHMgPT0gJ29iamVjdCcgJiYgZXhwb3J0cyAmJiAhZXhwb3J0cy5ub2RlVHlwZSAmJiBleHBvcnRzO1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYG1vZHVsZWAuICovXG52YXIgZnJlZU1vZHVsZSA9IGZyZWVFeHBvcnRzICYmIHR5cGVvZiBtb2R1bGUgPT0gJ29iamVjdCcgJiYgbW9kdWxlICYmICFtb2R1bGUubm9kZVR5cGUgJiYgbW9kdWxlO1xuXG4vKiogRGV0ZWN0IHRoZSBwb3B1bGFyIENvbW1vbkpTIGV4dGVuc2lvbiBgbW9kdWxlLmV4cG9ydHNgLiAqL1xudmFyIG1vZHVsZUV4cG9ydHMgPSBmcmVlTW9kdWxlICYmIGZyZWVNb2R1bGUuZXhwb3J0cyA9PT0gZnJlZUV4cG9ydHM7XG5cbi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgcHJvY2Vzc2AgZnJvbSBOb2RlLmpzLiAqL1xudmFyIGZyZWVQcm9jZXNzID0gbW9kdWxlRXhwb3J0cyAmJiBmcmVlR2xvYmFsLnByb2Nlc3M7XG5cbi8qKiBVc2VkIHRvIGFjY2VzcyBmYXN0ZXIgTm9kZS5qcyBoZWxwZXJzLiAqL1xudmFyIG5vZGVVdGlsID0gKGZ1bmN0aW9uKCkge1xuICB0cnkge1xuICAgIC8vIFVzZSBgdXRpbC50eXBlc2AgZm9yIE5vZGUuanMgMTArLlxuICAgIHZhciB0eXBlcyA9IGZyZWVNb2R1bGUgJiYgZnJlZU1vZHVsZS5yZXF1aXJlICYmIGZyZWVNb2R1bGUucmVxdWlyZSgndXRpbCcpLnR5cGVzO1xuXG4gICAgaWYgKHR5cGVzKSB7XG4gICAgICByZXR1cm4gdHlwZXM7XG4gICAgfVxuXG4gICAgLy8gTGVnYWN5IGBwcm9jZXNzLmJpbmRpbmcoJ3V0aWwnKWAgZm9yIE5vZGUuanMgPCAxMC5cbiAgICByZXR1cm4gZnJlZVByb2Nlc3MgJiYgZnJlZVByb2Nlc3MuYmluZGluZyAmJiBmcmVlUHJvY2Vzcy5iaW5kaW5nKCd1dGlsJyk7XG4gIH0gY2F0Y2ggKGUpIHt9XG59KCkpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5vZGVVdGlsO1xuIiwiLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqXG4gKiBVc2VkIHRvIHJlc29sdmUgdGhlXG4gKiBbYHRvU3RyaW5nVGFnYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZylcbiAqIG9mIHZhbHVlcy5cbiAqL1xudmFyIG5hdGl2ZU9iamVjdFRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbi8qKlxuICogQ29udmVydHMgYHZhbHVlYCB0byBhIHN0cmluZyB1c2luZyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2AuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbnZlcnQuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBjb252ZXJ0ZWQgc3RyaW5nLlxuICovXG5mdW5jdGlvbiBvYmplY3RUb1N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gbmF0aXZlT2JqZWN0VG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gb2JqZWN0VG9TdHJpbmc7XG4iLCIvKipcbiAqIENyZWF0ZXMgYSB1bmFyeSBmdW5jdGlvbiB0aGF0IGludm9rZXMgYGZ1bmNgIHdpdGggaXRzIGFyZ3VtZW50IHRyYW5zZm9ybWVkLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byB3cmFwLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gdHJhbnNmb3JtIFRoZSBhcmd1bWVudCB0cmFuc2Zvcm0uXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gb3ZlckFyZyhmdW5jLCB0cmFuc2Zvcm0pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKGFyZykge1xuICAgIHJldHVybiBmdW5jKHRyYW5zZm9ybShhcmcpKTtcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBvdmVyQXJnO1xuIiwidmFyIGZyZWVHbG9iYWwgPSByZXF1aXJlKCcuL19mcmVlR2xvYmFsJyk7XG5cbi8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZSBgc2VsZmAuICovXG52YXIgZnJlZVNlbGYgPSB0eXBlb2Ygc2VsZiA9PSAnb2JqZWN0JyAmJiBzZWxmICYmIHNlbGYuT2JqZWN0ID09PSBPYmplY3QgJiYgc2VsZjtcblxuLyoqIFVzZWQgYXMgYSByZWZlcmVuY2UgdG8gdGhlIGdsb2JhbCBvYmplY3QuICovXG52YXIgcm9vdCA9IGZyZWVHbG9iYWwgfHwgZnJlZVNlbGYgfHwgRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTtcblxubW9kdWxlLmV4cG9ydHMgPSByb290O1xuIiwiLyoqIFVzZWQgdG8gc3RhbmQtaW4gZm9yIGB1bmRlZmluZWRgIGhhc2ggdmFsdWVzLiAqL1xudmFyIEhBU0hfVU5ERUZJTkVEID0gJ19fbG9kYXNoX2hhc2hfdW5kZWZpbmVkX18nO1xuXG4vKipcbiAqIEFkZHMgYHZhbHVlYCB0byB0aGUgYXJyYXkgY2FjaGUuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGFkZFxuICogQG1lbWJlck9mIFNldENhY2hlXG4gKiBAYWxpYXMgcHVzaFxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2FjaGUuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjYWNoZSBpbnN0YW5jZS5cbiAqL1xuZnVuY3Rpb24gc2V0Q2FjaGVBZGQodmFsdWUpIHtcbiAgdGhpcy5fX2RhdGFfXy5zZXQodmFsdWUsIEhBU0hfVU5ERUZJTkVEKTtcbiAgcmV0dXJuIHRoaXM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc2V0Q2FjaGVBZGQ7XG4iLCIvKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGluIHRoZSBhcnJheSBjYWNoZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgaGFzXG4gKiBAbWVtYmVyT2YgU2V0Q2FjaGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGZvdW5kLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIHNldENhY2hlSGFzKHZhbHVlKSB7XG4gIHJldHVybiB0aGlzLl9fZGF0YV9fLmhhcyh2YWx1ZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc2V0Q2FjaGVIYXM7XG4iLCIvKipcbiAqIENvbnZlcnRzIGBzZXRgIHRvIGFuIGFycmF5IG9mIGl0cyB2YWx1ZXMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBzZXQgVGhlIHNldCB0byBjb252ZXJ0LlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSB2YWx1ZXMuXG4gKi9cbmZ1bmN0aW9uIHNldFRvQXJyYXkoc2V0KSB7XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgcmVzdWx0ID0gQXJyYXkoc2V0LnNpemUpO1xuXG4gIHNldC5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmVzdWx0WysraW5kZXhdID0gdmFsdWU7XG4gIH0pO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHNldFRvQXJyYXk7XG4iLCJ2YXIgTGlzdENhY2hlID0gcmVxdWlyZSgnLi9fTGlzdENhY2hlJyk7XG5cbi8qKlxuICogUmVtb3ZlcyBhbGwga2V5LXZhbHVlIGVudHJpZXMgZnJvbSB0aGUgc3RhY2suXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGNsZWFyXG4gKiBAbWVtYmVyT2YgU3RhY2tcbiAqL1xuZnVuY3Rpb24gc3RhY2tDbGVhcigpIHtcbiAgdGhpcy5fX2RhdGFfXyA9IG5ldyBMaXN0Q2FjaGU7XG4gIHRoaXMuc2l6ZSA9IDA7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc3RhY2tDbGVhcjtcbiIsIi8qKlxuICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIHN0YWNrLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBkZWxldGVcbiAqIEBtZW1iZXJPZiBTdGFja1xuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byByZW1vdmUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVudHJ5IHdhcyByZW1vdmVkLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIHN0YWNrRGVsZXRlKGtleSkge1xuICB2YXIgZGF0YSA9IHRoaXMuX19kYXRhX18sXG4gICAgICByZXN1bHQgPSBkYXRhWydkZWxldGUnXShrZXkpO1xuXG4gIHRoaXMuc2l6ZSA9IGRhdGEuc2l6ZTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzdGFja0RlbGV0ZTtcbiIsIi8qKlxuICogR2V0cyB0aGUgc3RhY2sgdmFsdWUgZm9yIGBrZXlgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBnZXRcbiAqIEBtZW1iZXJPZiBTdGFja1xuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIHN0YWNrR2V0KGtleSkge1xuICByZXR1cm4gdGhpcy5fX2RhdGFfXy5nZXQoa2V5KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzdGFja0dldDtcbiIsIi8qKlxuICogQ2hlY2tzIGlmIGEgc3RhY2sgdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgaGFzXG4gKiBAbWVtYmVyT2YgU3RhY2tcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgZW50cnkgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW4gZW50cnkgZm9yIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBzdGFja0hhcyhrZXkpIHtcbiAgcmV0dXJuIHRoaXMuX19kYXRhX18uaGFzKGtleSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc3RhY2tIYXM7XG4iLCJ2YXIgTGlzdENhY2hlID0gcmVxdWlyZSgnLi9fTGlzdENhY2hlJyksXG4gICAgTWFwID0gcmVxdWlyZSgnLi9fTWFwJyksXG4gICAgTWFwQ2FjaGUgPSByZXF1aXJlKCcuL19NYXBDYWNoZScpO1xuXG4vKiogVXNlZCBhcyB0aGUgc2l6ZSB0byBlbmFibGUgbGFyZ2UgYXJyYXkgb3B0aW1pemF0aW9ucy4gKi9cbnZhciBMQVJHRV9BUlJBWV9TSVpFID0gMjAwO1xuXG4vKipcbiAqIFNldHMgdGhlIHN0YWNrIGBrZXlgIHRvIGB2YWx1ZWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIHNldFxuICogQG1lbWJlck9mIFN0YWNrXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHNldC5cbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldC5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIHN0YWNrIGNhY2hlIGluc3RhbmNlLlxuICovXG5mdW5jdGlvbiBzdGFja1NldChrZXksIHZhbHVlKSB7XG4gIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXztcbiAgaWYgKGRhdGEgaW5zdGFuY2VvZiBMaXN0Q2FjaGUpIHtcbiAgICB2YXIgcGFpcnMgPSBkYXRhLl9fZGF0YV9fO1xuICAgIGlmICghTWFwIHx8IChwYWlycy5sZW5ndGggPCBMQVJHRV9BUlJBWV9TSVpFIC0gMSkpIHtcbiAgICAgIHBhaXJzLnB1c2goW2tleSwgdmFsdWVdKTtcbiAgICAgIHRoaXMuc2l6ZSA9ICsrZGF0YS5zaXplO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGRhdGEgPSB0aGlzLl9fZGF0YV9fID0gbmV3IE1hcENhY2hlKHBhaXJzKTtcbiAgfVxuICBkYXRhLnNldChrZXksIHZhbHVlKTtcbiAgdGhpcy5zaXplID0gZGF0YS5zaXplO1xuICByZXR1cm4gdGhpcztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzdGFja1NldDtcbiIsIi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBmdW5jUHJvdG8gPSBGdW5jdGlvbi5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIHJlc29sdmUgdGhlIGRlY29tcGlsZWQgc291cmNlIG9mIGZ1bmN0aW9ucy4gKi9cbnZhciBmdW5jVG9TdHJpbmcgPSBmdW5jUHJvdG8udG9TdHJpbmc7XG5cbi8qKlxuICogQ29udmVydHMgYGZ1bmNgIHRvIGl0cyBzb3VyY2UgY29kZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gY29udmVydC5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHNvdXJjZSBjb2RlLlxuICovXG5mdW5jdGlvbiB0b1NvdXJjZShmdW5jKSB7XG4gIGlmIChmdW5jICE9IG51bGwpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGZ1bmNUb1N0cmluZy5jYWxsKGZ1bmMpO1xuICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiAoZnVuYyArICcnKTtcbiAgICB9IGNhdGNoIChlKSB7fVxuICB9XG4gIHJldHVybiAnJztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB0b1NvdXJjZTtcbiIsInZhciBiYXNlQ2xvbmUgPSByZXF1aXJlKCcuL19iYXNlQ2xvbmUnKTtcblxuLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3IgY2xvbmluZy4gKi9cbnZhciBDTE9ORV9ERUVQX0ZMQUcgPSAxLFxuICAgIENMT05FX1NZTUJPTFNfRkxBRyA9IDQ7XG5cbi8qKlxuICogVGhpcyBtZXRob2QgaXMgbGlrZSBgXy5jbG9uZWAgZXhjZXB0IHRoYXQgaXQgcmVjdXJzaXZlbHkgY2xvbmVzIGB2YWx1ZWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAxLjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHJlY3Vyc2l2ZWx5IGNsb25lLlxuICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGRlZXAgY2xvbmVkIHZhbHVlLlxuICogQHNlZSBfLmNsb25lXG4gKiBAZXhhbXBsZVxuICpcbiAqIHZhciBvYmplY3RzID0gW3sgJ2EnOiAxIH0sIHsgJ2InOiAyIH1dO1xuICpcbiAqIHZhciBkZWVwID0gXy5jbG9uZURlZXAob2JqZWN0cyk7XG4gKiBjb25zb2xlLmxvZyhkZWVwWzBdID09PSBvYmplY3RzWzBdKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGNsb25lRGVlcCh2YWx1ZSkge1xuICByZXR1cm4gYmFzZUNsb25lKHZhbHVlLCBDTE9ORV9ERUVQX0ZMQUcgfCBDTE9ORV9TWU1CT0xTX0ZMQUcpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNsb25lRGVlcDtcbiIsIi8qKlxuICogUGVyZm9ybXMgYVxuICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAqIGNvbXBhcmlzb24gYmV0d2VlbiB0d28gdmFsdWVzIHRvIGRldGVybWluZSBpZiB0aGV5IGFyZSBlcXVpdmFsZW50LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmFsdWVzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIHZhciBvYmplY3QgPSB7ICdhJzogMSB9O1xuICogdmFyIG90aGVyID0geyAnYSc6IDEgfTtcbiAqXG4gKiBfLmVxKG9iamVjdCwgb2JqZWN0KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmVxKG9iamVjdCwgb3RoZXIpO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmVxKCdhJywgJ2EnKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmVxKCdhJywgT2JqZWN0KCdhJykpO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmVxKE5hTiwgTmFOKTtcbiAqIC8vID0+IHRydWVcbiAqL1xuZnVuY3Rpb24gZXEodmFsdWUsIG90aGVyKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gb3RoZXIgfHwgKHZhbHVlICE9PSB2YWx1ZSAmJiBvdGhlciAhPT0gb3RoZXIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGVxO1xuIiwidmFyIGJhc2VJc0FyZ3VtZW50cyA9IHJlcXVpcmUoJy4vX2Jhc2VJc0FyZ3VtZW50cycpLFxuICAgIGlzT2JqZWN0TGlrZSA9IHJlcXVpcmUoJy4vaXNPYmplY3RMaWtlJyk7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKiBCdWlsdC1pbiB2YWx1ZSByZWZlcmVuY2VzLiAqL1xudmFyIHByb3BlcnR5SXNFbnVtZXJhYmxlID0gb2JqZWN0UHJvdG8ucHJvcGVydHlJc0VudW1lcmFibGU7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgbGlrZWx5IGFuIGBhcmd1bWVudHNgIG9iamVjdC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBgYXJndW1lbnRzYCBvYmplY3QsXG4gKiAgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzQXJndW1lbnRzKGZ1bmN0aW9uKCkgeyByZXR1cm4gYXJndW1lbnRzOyB9KCkpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNBcmd1bWVudHMoWzEsIDIsIDNdKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbnZhciBpc0FyZ3VtZW50cyA9IGJhc2VJc0FyZ3VtZW50cyhmdW5jdGlvbigpIHsgcmV0dXJuIGFyZ3VtZW50czsgfSgpKSA/IGJhc2VJc0FyZ3VtZW50cyA6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsICdjYWxsZWUnKSAmJlxuICAgICFwcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKHZhbHVlLCAnY2FsbGVlJyk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGlzQXJndW1lbnRzO1xuIiwiLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGFuIGBBcnJheWAgb2JqZWN0LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIGFycmF5LCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNBcnJheShbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNBcnJheShkb2N1bWVudC5ib2R5LmNoaWxkcmVuKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc0FycmF5KCdhYmMnKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc0FycmF5KF8ubm9vcCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG52YXIgaXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG5cbm1vZHVsZS5leHBvcnRzID0gaXNBcnJheTtcbiIsInZhciBpc0Z1bmN0aW9uID0gcmVxdWlyZSgnLi9pc0Z1bmN0aW9uJyksXG4gICAgaXNMZW5ndGggPSByZXF1aXJlKCcuL2lzTGVuZ3RoJyk7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgYXJyYXktbGlrZS4gQSB2YWx1ZSBpcyBjb25zaWRlcmVkIGFycmF5LWxpa2UgaWYgaXQnc1xuICogbm90IGEgZnVuY3Rpb24gYW5kIGhhcyBhIGB2YWx1ZS5sZW5ndGhgIHRoYXQncyBhbiBpbnRlZ2VyIGdyZWF0ZXIgdGhhbiBvclxuICogZXF1YWwgdG8gYDBgIGFuZCBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gYE51bWJlci5NQVhfU0FGRV9JTlRFR0VSYC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhcnJheS1saWtlLCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNBcnJheUxpa2UoWzEsIDIsIDNdKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzQXJyYXlMaWtlKGRvY3VtZW50LmJvZHkuY2hpbGRyZW4pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNBcnJheUxpa2UoJ2FiYycpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNBcnJheUxpa2UoXy5ub29wKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzQXJyYXlMaWtlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSAhPSBudWxsICYmIGlzTGVuZ3RoKHZhbHVlLmxlbmd0aCkgJiYgIWlzRnVuY3Rpb24odmFsdWUpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzQXJyYXlMaWtlO1xuIiwidmFyIHJvb3QgPSByZXF1aXJlKCcuL19yb290JyksXG4gICAgc3R1YkZhbHNlID0gcmVxdWlyZSgnLi9zdHViRmFsc2UnKTtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBleHBvcnRzYC4gKi9cbnZhciBmcmVlRXhwb3J0cyA9IHR5cGVvZiBleHBvcnRzID09ICdvYmplY3QnICYmIGV4cG9ydHMgJiYgIWV4cG9ydHMubm9kZVR5cGUgJiYgZXhwb3J0cztcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBtb2R1bGVgLiAqL1xudmFyIGZyZWVNb2R1bGUgPSBmcmVlRXhwb3J0cyAmJiB0eXBlb2YgbW9kdWxlID09ICdvYmplY3QnICYmIG1vZHVsZSAmJiAhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblxuLyoqIERldGVjdCB0aGUgcG9wdWxhciBDb21tb25KUyBleHRlbnNpb24gYG1vZHVsZS5leHBvcnRzYC4gKi9cbnZhciBtb2R1bGVFeHBvcnRzID0gZnJlZU1vZHVsZSAmJiBmcmVlTW9kdWxlLmV4cG9ydHMgPT09IGZyZWVFeHBvcnRzO1xuXG4vKiogQnVpbHQtaW4gdmFsdWUgcmVmZXJlbmNlcy4gKi9cbnZhciBCdWZmZXIgPSBtb2R1bGVFeHBvcnRzID8gcm9vdC5CdWZmZXIgOiB1bmRlZmluZWQ7XG5cbi8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVJc0J1ZmZlciA9IEJ1ZmZlciA/IEJ1ZmZlci5pc0J1ZmZlciA6IHVuZGVmaW5lZDtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIGJ1ZmZlci5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMy4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIGJ1ZmZlciwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzQnVmZmVyKG5ldyBCdWZmZXIoMikpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNCdWZmZXIobmV3IFVpbnQ4QXJyYXkoMikpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xudmFyIGlzQnVmZmVyID0gbmF0aXZlSXNCdWZmZXIgfHwgc3R1YkZhbHNlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGlzQnVmZmVyO1xuIiwidmFyIGJhc2VJc0VxdWFsID0gcmVxdWlyZSgnLi9fYmFzZUlzRXF1YWwnKTtcblxuLyoqXG4gKiBQZXJmb3JtcyBhIGRlZXAgY29tcGFyaXNvbiBiZXR3ZWVuIHR3byB2YWx1ZXMgdG8gZGV0ZXJtaW5lIGlmIHRoZXkgYXJlXG4gKiBlcXVpdmFsZW50LlxuICpcbiAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBzdXBwb3J0cyBjb21wYXJpbmcgYXJyYXlzLCBhcnJheSBidWZmZXJzLCBib29sZWFucyxcbiAqIGRhdGUgb2JqZWN0cywgZXJyb3Igb2JqZWN0cywgbWFwcywgbnVtYmVycywgYE9iamVjdGAgb2JqZWN0cywgcmVnZXhlcyxcbiAqIHNldHMsIHN0cmluZ3MsIHN5bWJvbHMsIGFuZCB0eXBlZCBhcnJheXMuIGBPYmplY3RgIG9iamVjdHMgYXJlIGNvbXBhcmVkXG4gKiBieSB0aGVpciBvd24sIG5vdCBpbmhlcml0ZWQsIGVudW1lcmFibGUgcHJvcGVydGllcy4gRnVuY3Rpb25zIGFuZCBET01cbiAqIG5vZGVzIGFyZSBjb21wYXJlZCBieSBzdHJpY3QgZXF1YWxpdHksIGkuZS4gYD09PWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0geyp9IG90aGVyIFRoZSBvdGhlciB2YWx1ZSB0byBjb21wYXJlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogdmFyIG9iamVjdCA9IHsgJ2EnOiAxIH07XG4gKiB2YXIgb3RoZXIgPSB7ICdhJzogMSB9O1xuICpcbiAqIF8uaXNFcXVhbChvYmplY3QsIG90aGVyKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBvYmplY3QgPT09IG90aGVyO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNFcXVhbCh2YWx1ZSwgb3RoZXIpIHtcbiAgcmV0dXJuIGJhc2VJc0VxdWFsKHZhbHVlLCBvdGhlcik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNFcXVhbDtcbiIsInZhciBiYXNlR2V0VGFnID0gcmVxdWlyZSgnLi9fYmFzZUdldFRhZycpLFxuICAgIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9pc09iamVjdCcpO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgYXN5bmNUYWcgPSAnW29iamVjdCBBc3luY0Z1bmN0aW9uXScsXG4gICAgZnVuY1RhZyA9ICdbb2JqZWN0IEZ1bmN0aW9uXScsXG4gICAgZ2VuVGFnID0gJ1tvYmplY3QgR2VuZXJhdG9yRnVuY3Rpb25dJyxcbiAgICBwcm94eVRhZyA9ICdbb2JqZWN0IFByb3h5XSc7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBGdW5jdGlvbmAgb2JqZWN0LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgZnVuY3Rpb24sIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc0Z1bmN0aW9uKF8pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNGdW5jdGlvbigvYWJjLyk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKHZhbHVlKSB7XG4gIGlmICghaXNPYmplY3QodmFsdWUpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIC8vIFRoZSB1c2Ugb2YgYE9iamVjdCN0b1N0cmluZ2AgYXZvaWRzIGlzc3VlcyB3aXRoIHRoZSBgdHlwZW9mYCBvcGVyYXRvclxuICAvLyBpbiBTYWZhcmkgOSB3aGljaCByZXR1cm5zICdvYmplY3QnIGZvciB0eXBlZCBhcnJheXMgYW5kIG90aGVyIGNvbnN0cnVjdG9ycy5cbiAgdmFyIHRhZyA9IGJhc2VHZXRUYWcodmFsdWUpO1xuICByZXR1cm4gdGFnID09IGZ1bmNUYWcgfHwgdGFnID09IGdlblRhZyB8fCB0YWcgPT0gYXN5bmNUYWcgfHwgdGFnID09IHByb3h5VGFnO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzRnVuY3Rpb247XG4iLCIvKiogVXNlZCBhcyByZWZlcmVuY2VzIGZvciB2YXJpb3VzIGBOdW1iZXJgIGNvbnN0YW50cy4gKi9cbnZhciBNQVhfU0FGRV9JTlRFR0VSID0gOTAwNzE5OTI1NDc0MDk5MTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHZhbGlkIGFycmF5LWxpa2UgbGVuZ3RoLlxuICpcbiAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBsb29zZWx5IGJhc2VkIG9uXG4gKiBbYFRvTGVuZ3RoYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtdG9sZW5ndGgpLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgdmFsaWQgbGVuZ3RoLCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNMZW5ndGgoMyk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc0xlbmd0aChOdW1iZXIuTUlOX1ZBTFVFKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc0xlbmd0aChJbmZpbml0eSk7XG4gKiAvLyA9PiBmYWxzZVxuICpcbiAqIF8uaXNMZW5ndGgoJzMnKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzTGVuZ3RoKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ251bWJlcicgJiZcbiAgICB2YWx1ZSA+IC0xICYmIHZhbHVlICUgMSA9PSAwICYmIHZhbHVlIDw9IE1BWF9TQUZFX0lOVEVHRVI7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNMZW5ndGg7XG4iLCJ2YXIgYmFzZUlzTWFwID0gcmVxdWlyZSgnLi9fYmFzZUlzTWFwJyksXG4gICAgYmFzZVVuYXJ5ID0gcmVxdWlyZSgnLi9fYmFzZVVuYXJ5JyksXG4gICAgbm9kZVV0aWwgPSByZXF1aXJlKCcuL19ub2RlVXRpbCcpO1xuXG4vKiBOb2RlLmpzIGhlbHBlciByZWZlcmVuY2VzLiAqL1xudmFyIG5vZGVJc01hcCA9IG5vZGVVdGlsICYmIG5vZGVVdGlsLmlzTWFwO1xuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgTWFwYCBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjMuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBtYXAsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc01hcChuZXcgTWFwKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzTWFwKG5ldyBXZWFrTWFwKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbnZhciBpc01hcCA9IG5vZGVJc01hcCA/IGJhc2VVbmFyeShub2RlSXNNYXApIDogYmFzZUlzTWFwO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGlzTWFwO1xuIiwiLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyB0aGVcbiAqIFtsYW5ndWFnZSB0eXBlXShodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtZWNtYXNjcmlwdC1sYW5ndWFnZS10eXBlcylcbiAqIG9mIGBPYmplY3RgLiAoZS5nLiBhcnJheXMsIGZ1bmN0aW9ucywgb2JqZWN0cywgcmVnZXhlcywgYG5ldyBOdW1iZXIoMClgLCBhbmQgYG5ldyBTdHJpbmcoJycpYClcbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdCh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QoXy5ub29wKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KG51bGwpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNPYmplY3QodmFsdWUpIHtcbiAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gIHJldHVybiB2YWx1ZSAhPSBudWxsICYmICh0eXBlID09ICdvYmplY3QnIHx8IHR5cGUgPT0gJ2Z1bmN0aW9uJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNPYmplY3Q7XG4iLCIvKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLiBBIHZhbHVlIGlzIG9iamVjdC1saWtlIGlmIGl0J3Mgbm90IGBudWxsYFxuICogYW5kIGhhcyBhIGB0eXBlb2ZgIHJlc3VsdCBvZiBcIm9iamVjdFwiLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKHt9KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKF8ubm9vcCk7XG4gKiAvLyA9PiBmYWxzZVxuICpcbiAqIF8uaXNPYmplY3RMaWtlKG51bGwpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNPYmplY3RMaWtlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSAhPSBudWxsICYmIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0Jztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc09iamVjdExpa2U7XG4iLCJ2YXIgYmFzZUlzU2V0ID0gcmVxdWlyZSgnLi9fYmFzZUlzU2V0JyksXG4gICAgYmFzZVVuYXJ5ID0gcmVxdWlyZSgnLi9fYmFzZVVuYXJ5JyksXG4gICAgbm9kZVV0aWwgPSByZXF1aXJlKCcuL19ub2RlVXRpbCcpO1xuXG4vKiBOb2RlLmpzIGhlbHBlciByZWZlcmVuY2VzLiAqL1xudmFyIG5vZGVJc1NldCA9IG5vZGVVdGlsICYmIG5vZGVVdGlsLmlzU2V0O1xuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgU2V0YCBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjMuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzZXQsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc1NldChuZXcgU2V0KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzU2V0KG5ldyBXZWFrU2V0KTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbnZhciBpc1NldCA9IG5vZGVJc1NldCA/IGJhc2VVbmFyeShub2RlSXNTZXQpIDogYmFzZUlzU2V0O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGlzU2V0O1xuIiwidmFyIGJhc2VJc1R5cGVkQXJyYXkgPSByZXF1aXJlKCcuL19iYXNlSXNUeXBlZEFycmF5JyksXG4gICAgYmFzZVVuYXJ5ID0gcmVxdWlyZSgnLi9fYmFzZVVuYXJ5JyksXG4gICAgbm9kZVV0aWwgPSByZXF1aXJlKCcuL19ub2RlVXRpbCcpO1xuXG4vKiBOb2RlLmpzIGhlbHBlciByZWZlcmVuY2VzLiAqL1xudmFyIG5vZGVJc1R5cGVkQXJyYXkgPSBub2RlVXRpbCAmJiBub2RlVXRpbC5pc1R5cGVkQXJyYXk7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIHR5cGVkIGFycmF5LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMy4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgdHlwZWQgYXJyYXksIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc1R5cGVkQXJyYXkobmV3IFVpbnQ4QXJyYXkpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNUeXBlZEFycmF5KFtdKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbnZhciBpc1R5cGVkQXJyYXkgPSBub2RlSXNUeXBlZEFycmF5ID8gYmFzZVVuYXJ5KG5vZGVJc1R5cGVkQXJyYXkpIDogYmFzZUlzVHlwZWRBcnJheTtcblxubW9kdWxlLmV4cG9ydHMgPSBpc1R5cGVkQXJyYXk7XG4iLCJ2YXIgYXJyYXlMaWtlS2V5cyA9IHJlcXVpcmUoJy4vX2FycmF5TGlrZUtleXMnKSxcbiAgICBiYXNlS2V5cyA9IHJlcXVpcmUoJy4vX2Jhc2VLZXlzJyksXG4gICAgaXNBcnJheUxpa2UgPSByZXF1aXJlKCcuL2lzQXJyYXlMaWtlJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgb2YgYG9iamVjdGAuXG4gKlxuICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuIFNlZSB0aGVcbiAqIFtFUyBzcGVjXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3Qua2V5cylcbiAqIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogQHN0YXRpY1xuICogQHNpbmNlIDAuMS4wXG4gKiBAbWVtYmVyT2YgX1xuICogQGNhdGVnb3J5IE9iamVjdFxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAqIEBleGFtcGxlXG4gKlxuICogZnVuY3Rpb24gRm9vKCkge1xuICogICB0aGlzLmEgPSAxO1xuICogICB0aGlzLmIgPSAyO1xuICogfVxuICpcbiAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gKlxuICogXy5rZXlzKG5ldyBGb28pO1xuICogLy8gPT4gWydhJywgJ2InXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICpcbiAqIF8ua2V5cygnaGknKTtcbiAqIC8vID0+IFsnMCcsICcxJ11cbiAqL1xuZnVuY3Rpb24ga2V5cyhvYmplY3QpIHtcbiAgcmV0dXJuIGlzQXJyYXlMaWtlKG9iamVjdCkgPyBhcnJheUxpa2VLZXlzKG9iamVjdCkgOiBiYXNlS2V5cyhvYmplY3QpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGtleXM7XG4iLCJ2YXIgYXJyYXlMaWtlS2V5cyA9IHJlcXVpcmUoJy4vX2FycmF5TGlrZUtleXMnKSxcbiAgICBiYXNlS2V5c0luID0gcmVxdWlyZSgnLi9fYmFzZUtleXNJbicpLFxuICAgIGlzQXJyYXlMaWtlID0gcmVxdWlyZSgnLi9pc0FycmF5TGlrZScpO1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgb2YgYG9iamVjdGAuXG4gKlxuICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAzLjAuMFxuICogQGNhdGVnb3J5IE9iamVjdFxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSBuYW1lcy5cbiAqIEBleGFtcGxlXG4gKlxuICogZnVuY3Rpb24gRm9vKCkge1xuICogICB0aGlzLmEgPSAxO1xuICogICB0aGlzLmIgPSAyO1xuICogfVxuICpcbiAqIEZvby5wcm90b3R5cGUuYyA9IDM7XG4gKlxuICogXy5rZXlzSW4obmV3IEZvbyk7XG4gKiAvLyA9PiBbJ2EnLCAnYicsICdjJ10gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAqL1xuZnVuY3Rpb24ga2V5c0luKG9iamVjdCkge1xuICByZXR1cm4gaXNBcnJheUxpa2Uob2JqZWN0KSA/IGFycmF5TGlrZUtleXMob2JqZWN0LCB0cnVlKSA6IGJhc2VLZXlzSW4ob2JqZWN0KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBrZXlzSW47XG4iLCIvKipcbiAqIFRoaXMgbWV0aG9kIHJldHVybnMgYSBuZXcgZW1wdHkgYXJyYXkuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjEzLjBcbiAqIEBjYXRlZ29yeSBVdGlsXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIG5ldyBlbXB0eSBhcnJheS5cbiAqIEBleGFtcGxlXG4gKlxuICogdmFyIGFycmF5cyA9IF8udGltZXMoMiwgXy5zdHViQXJyYXkpO1xuICpcbiAqIGNvbnNvbGUubG9nKGFycmF5cyk7XG4gKiAvLyA9PiBbW10sIFtdXVxuICpcbiAqIGNvbnNvbGUubG9nKGFycmF5c1swXSA9PT0gYXJyYXlzWzFdKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIHN0dWJBcnJheSgpIHtcbiAgcmV0dXJuIFtdO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHN0dWJBcnJheTtcbiIsIi8qKlxuICogVGhpcyBtZXRob2QgcmV0dXJucyBgZmFsc2VgLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4xMy4wXG4gKiBAY2F0ZWdvcnkgVXRpbFxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy50aW1lcygyLCBfLnN0dWJGYWxzZSk7XG4gKiAvLyA9PiBbZmFsc2UsIGZhbHNlXVxuICovXG5mdW5jdGlvbiBzdHViRmFsc2UoKSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBzdHViRmFsc2U7XG4iLCIvLyBUaGUgbW9kdWxlIGNhY2hlXG52YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307XG5cbi8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG5mdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuXHR2YXIgY2FjaGVkTW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXTtcblx0aWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzO1xuXHR9XG5cdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG5cdHZhciBtb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdID0ge1xuXHRcdGlkOiBtb2R1bGVJZCxcblx0XHRsb2FkZWQ6IGZhbHNlLFxuXHRcdGV4cG9ydHM6IHt9XG5cdH07XG5cblx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG5cdF9fd2VicGFja19tb2R1bGVzX19bbW9kdWxlSWRdKG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG5cdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcblx0bW9kdWxlLmxvYWRlZCA9IHRydWU7XG5cblx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcblx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xufVxuXG4iLCJfX3dlYnBhY2tfcmVxdWlyZV9fLmcgPSAoZnVuY3Rpb24oKSB7XG5cdGlmICh0eXBlb2YgZ2xvYmFsVGhpcyA9PT0gJ29iamVjdCcpIHJldHVybiBnbG9iYWxUaGlzO1xuXHR0cnkge1xuXHRcdHJldHVybiB0aGlzIHx8IG5ldyBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0aWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnKSByZXR1cm4gd2luZG93O1xuXHR9XG59KSgpOyIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18ubm1kID0gKG1vZHVsZSkgPT4ge1xuXHRtb2R1bGUucGF0aHMgPSBbXTtcblx0aWYgKCFtb2R1bGUuY2hpbGRyZW4pIG1vZHVsZS5jaGlsZHJlbiA9IFtdO1xuXHRyZXR1cm4gbW9kdWxlO1xufTsiLCJpbXBvcnQgeyBmaW4gfSBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBhc3luYyAoKSA9PiB7XG5cdGNvbnN0IG9rYXkgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI29rYXlcIik7XG5cdGNvbnN0IGNhbmNlbCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjY2FuY2VsXCIpO1xuXG5cdGlmIChva2F5KSB7XG5cdFx0b2theS5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0YXdhaXQgaGFuZGxlQ2xvc2UodHJ1ZSk7XG5cdFx0fSk7XG5cdH1cblxuXHRpZiAoY2FuY2VsKSB7XG5cdFx0Y2FuY2VsLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCBoYW5kbGVDbG9zZShmYWxzZSk7XG5cdFx0fSk7XG5cdH1cblxuXHRwb3B1bGF0ZSgpO1xufSk7XG5cbi8qKlxuICogUG9wdWxhdGUgdGhlIGxpc3Qgb2Ygdmlld3MgdGhlIHdlcmUgcHJldmVudGVkLlxuICogQHBhcmFtIHZpZXdzIFRoZSBsaXN0IG9mIHZpZXdzLlxuICovXG5mdW5jdGlvbiBwb3B1bGF0ZVByZXZlbnRlZFZpZXdzKHZpZXdzOiB7IG5hbWU6IHN0cmluZyB9W10pOiB2b2lkIHtcblx0Zm9yIChjb25zdCB2aWV3IG9mIHZpZXdzKSB7XG5cdFx0Y29uc29sZS5sb2coXCJhZGQgdmlld1wiLCB2aWV3KTtcblx0XHRjb25zdCB2aWV3UCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJwXCIpO1xuXHRcdHZpZXdQLmlubmVySFRNTCA9IHZpZXcubmFtZTtcblx0XHRjb25zdCB2ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiN2aWV3c1wiKTtcblx0XHRpZiAodikge1xuXHRcdFx0di5hcHBlbmQodmlld1ApO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIFBvcHVsYXRlIHRoZSB2aWV3cy5cbiAqL1xuZnVuY3Rpb24gcG9wdWxhdGUoKTogdm9pZCB7XG5cdGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaCk7XG5cdGNvbnN0IGNsb3NlVHlwZSA9IHBhcmFtcy5nZXQoXCJjbG9zZVR5cGVcIik7XG5cblx0aWYgKGNsb3NlVHlwZSA9PT0gXCJ2aWV3XCIpIHtcblx0XHRjb25zdCBwID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInBcIik7XG5cdFx0cC5pbm5lckhUTUwgPSBcIkFyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBjbG9zZSB0aGlzIHZpZXc/IEl0IG1heSBoYXZlIHVuc2F2ZWQgY2hhbmdlcy5cIjtcblx0XHRjb25zdCB0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiN0ZXh0XCIpO1xuXHRcdGlmICh0KSB7XG5cdFx0XHR0LmFwcGVuZChwKTtcblx0XHR9XG5cdH1cblxuXHRpZiAoY2xvc2VUeXBlID09PSBcIndpbmRvd1wiKSB7XG5cdFx0Y29uc3Qgdmlld3MgPSBKU09OLnBhcnNlKHBhcmFtcy5nZXQoXCJ2aWV3c1wiKSA/PyBcIlwiKS52aWV3cztcblxuXHRcdGNvbnN0IHAxID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInBcIik7XG5cdFx0cDEuaW5uZXJIVE1MID0gXCJBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gY2xvc2UgdGhpcyB3aW5kb3c/XCI7XG5cdFx0Y29uc3QgdDEgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3RleHRcIik7XG5cdFx0aWYgKHQxKSB7XG5cdFx0XHR0MS5hcHBlbmQocDEpO1xuXHRcdH1cblxuXHRcdGNvbnN0IHAyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInBcIik7XG5cdFx0cDIuaW5uZXJIVE1MID0gXCJUaGUgZm9sbG93aW5nIHZpZXdzIG1heSBoYXZlIHVuc2F2ZWQgY2hhbmdlczpcIjtcblx0XHRjb25zdCB0MiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjdGV4dFwiKTtcblx0XHRpZiAodDIpIHtcblx0XHRcdHQyLmFwcGVuZChwMik7XG5cdFx0fVxuXG5cdFx0cG9wdWxhdGVQcmV2ZW50ZWRWaWV3cyh2aWV3cyk7XG5cdH1cbn1cblxuLyoqXG4gKiBIYW5kbGUgdGhlIGNsb3NlIGV2ZW50LlxuICogQHBhcmFtIHVzZXJEZWNpc2lvbiBUaGUgZGVjaXNpb24gdGhlIHVzZXIgbWFkZS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gaGFuZGxlQ2xvc2UodXNlckRlY2lzaW9uOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG5cdHRyeSB7XG5cdFx0Y29uc3QgY2xpZW50ID0gYXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuQ2hhbm5lbC5jb25uZWN0KFwidXNlckRlY2lzaW9uUHJvdmlkZXJcIik7XG5cdFx0YXdhaXQgY2xpZW50LmRpc3BhdGNoKFwiZ2V0LXVzZXItZGVjaXNpb25cIiwgdXNlckRlY2lzaW9uKTtcblx0XHR3aW5kb3cuY2xvc2UoKTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmxvZyhlcnJvcik7XG5cdH1cbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/js/provider.bundle.js b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/js/provider.bundle.js new file mode 100644 index 00000000..8440a161 --- /dev/null +++ b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/js/provider.bundle.js @@ -0,0 +1,103 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!********************************!*\ + !*** ./client/src/provider.ts ***! + \********************************/ +__webpack_require__.r(__webpack_exports__); +/** + * Launch a dialog. + * @param viewsPreventingUnload The views that are preventing unload. + * @param windowId The window identifier. + * @param closeType The type of the component being closed. + * @returns True if it was closed. + */ +async function launchDialog(viewsPreventingUnload, windowId, closeType) { + const views = { views: viewsPreventingUnload }; + const queryString = new URLSearchParams(`views=${JSON.stringify(views)}&closeType=${closeType}`); + const baseUrl = window.location.href.replace("provider", "dialog"); + const url = `${baseUrl}?${queryString.toString()}`; + /** + * Handle the close decision. + * @param resolve The promise resolve method. + * @param reject The promise reject method. + */ + async function handleUserDecisionPromise(resolve, reject) { + try { + const dialogWindow = fin.Window.wrapSync({ uuid: fin.me.identity.uuid, name: "before-unload-dialog" }); + const provider = await fin.InterApplicationBus.Channel.create("userDecisionProvider"); + await dialogWindow.on("closed", async () => { + await provider.destroy(); + }); + provider.register("get-user-decision", (payload) => { + const continueWithClose = payload; + resolve(continueWithClose); + }); + await fin.Window.create({ + name: "before-unload-dialog", + url, + modalParentIdentity: windowId, + frame: true, + defaultHeight: closeType === "window" ? 240 : 200, + defaultWidth: 400, + saveWindowState: false, + defaultCentered: true, + maximizable: false, + minimizable: false, + resizable: false + }); + } + catch (error) { + reject(error); + } + } + return new Promise(handleUserDecisionPromise); +} +/** + * Override the platform provider. + * @param PlatformProvider The platform provider base class. + * @returns The overridden platform provider. + */ +function overrideCallback(PlatformProvider) { + /** + * Override for the dialog. + */ + class BeforeUnloadDialogOverride extends PlatformProvider { + /** + * Get the user decision for unloading a window. + * @param payload The payload. + * @returns The close decision. + */ + async getUserDecisionForBeforeUnload(payload) { + const { windowShouldClose, viewsPreventingUnload, viewsNotPreventingUnload, windowId, closeType } = payload; + const continueWithClose = await launchDialog(viewsPreventingUnload, windowId, closeType); + if (continueWithClose) { + return { windowShouldClose, viewsToClose: [...viewsNotPreventingUnload, ...viewsPreventingUnload] }; + } + return { windowShouldClose: false, viewsToClose: [] }; + } + } + return new BeforeUnloadDialogOverride(); +} +fin.Platform.init({ overrideCallback }).catch((error) => console.error(error)); + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUFZLENBQUMscUJBQXFCLEVBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBRXpGLElBQUksaUJBQWlCLEVBQUUsQ0FBQztnQkFDdkIsT0FBTyxFQUFFLGlCQUFpQixFQUFFLFlBQVksRUFBRSxDQUFDLEdBQUcsd0JBQXdCLEVBQUUsR0FBRyxxQkFBcUIsQ0FBQyxFQUFFLENBQUM7WUFDckcsQ0FBQztZQUNELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQ3ZELENBQUM7S0FDRDtJQUNELE9BQU8sSUFBSSwwQkFBMEIsRUFBRSxDQUFDO0FBQ3pDLENBQUM7QUFFRCxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLGdCQUFnQixFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nL3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL3dhcm4tYmVmb3JlLWNsb3NpbmctZGlhbG9nL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi9jbGllbnQvc3JjL3Byb3ZpZGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSByZXF1aXJlIHNjb3BlXG52YXIgX193ZWJwYWNrX3JlcXVpcmVfXyA9IHt9O1xuXG4iLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgdHlwZSBPcGVuRmluIGZyb20gXCJAb3BlbmZpbi9jb3JlXCI7XG4vKipcbiAqIExhdW5jaCBhIGRpYWxvZy5cbiAqIEBwYXJhbSB2aWV3c1ByZXZlbnRpbmdVbmxvYWQgVGhlIHZpZXdzIHRoYXQgYXJlIHByZXZlbnRpbmcgdW5sb2FkLlxuICogQHBhcmFtIHdpbmRvd0lkIFRoZSB3aW5kb3cgaWRlbnRpZmllci5cbiAqIEBwYXJhbSBjbG9zZVR5cGUgVGhlIHR5cGUgb2YgdGhlIGNvbXBvbmVudCBiZWluZyBjbG9zZWQuXG4gKiBAcmV0dXJucyBUcnVlIGlmIGl0IHdhcyBjbG9zZWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGxhdW5jaERpYWxvZyhcblx0dmlld3NQcmV2ZW50aW5nVW5sb2FkOiBPcGVuRmluLklkZW50aXR5W10sXG5cdHdpbmRvd0lkOiBPcGVuRmluLklkZW50aXR5LFxuXHRjbG9zZVR5cGU6IFwid2luZG93XCIgfCBcInZpZXdcIlxuKTogUHJvbWlzZTxib29sZWFuPiB7XG5cdGNvbnN0IHZpZXdzID0geyB2aWV3czogdmlld3NQcmV2ZW50aW5nVW5sb2FkIH07XG5cdGNvbnN0IHF1ZXJ5U3RyaW5nID0gbmV3IFVSTFNlYXJjaFBhcmFtcyhgdmlld3M9JHtKU09OLnN0cmluZ2lmeSh2aWV3cyl9JmNsb3NlVHlwZT0ke2Nsb3NlVHlwZX1gKTtcblx0Y29uc3QgYmFzZVVybCA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmLnJlcGxhY2UoXCJwcm92aWRlclwiLCBcImRpYWxvZ1wiKTtcblx0Y29uc3QgdXJsID0gYCR7YmFzZVVybH0/JHtxdWVyeVN0cmluZy50b1N0cmluZygpfWA7XG5cblx0LyoqXG5cdCAqIEhhbmRsZSB0aGUgY2xvc2UgZGVjaXNpb24uXG5cdCAqIEBwYXJhbSByZXNvbHZlIFRoZSBwcm9taXNlIHJlc29sdmUgbWV0aG9kLlxuXHQgKiBAcGFyYW0gcmVqZWN0IFRoZSBwcm9taXNlIHJlamVjdCBtZXRob2QuXG5cdCAqL1xuXHRhc3luYyBmdW5jdGlvbiBoYW5kbGVVc2VyRGVjaXNpb25Qcm9taXNlKFxuXHRcdHJlc29sdmU6IChjbG9zZTogYm9vbGVhbikgPT4gdm9pZCxcblx0XHRyZWplY3Q6IChlcnI6IHVua25vd24pID0+IHZvaWRcblx0KTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IGRpYWxvZ1dpbmRvdyA9IGZpbi5XaW5kb3cud3JhcFN5bmMoeyB1dWlkOiBmaW4ubWUuaWRlbnRpdHkudXVpZCwgbmFtZTogXCJiZWZvcmUtdW5sb2FkLWRpYWxvZ1wiIH0pO1xuXG5cdFx0XHRjb25zdCBwcm92aWRlciA9IGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLkNoYW5uZWwuY3JlYXRlKFwidXNlckRlY2lzaW9uUHJvdmlkZXJcIik7XG5cblx0XHRcdGF3YWl0IGRpYWxvZ1dpbmRvdy5vbihcImNsb3NlZFwiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdGF3YWl0IHByb3ZpZGVyLmRlc3Ryb3koKTtcblx0XHRcdH0pO1xuXG5cdFx0XHRwcm92aWRlci5yZWdpc3RlcihcImdldC11c2VyLWRlY2lzaW9uXCIsIChwYXlsb2FkOiB1bmtub3duKSA9PiB7XG5cdFx0XHRcdGNvbnN0IGNvbnRpbnVlV2l0aENsb3NlID0gcGF5bG9hZCBhcyBib29sZWFuO1xuXHRcdFx0XHRyZXNvbHZlKGNvbnRpbnVlV2l0aENsb3NlKTtcblx0XHRcdH0pO1xuXG5cdFx0XHRhd2FpdCBmaW4uV2luZG93LmNyZWF0ZSh7XG5cdFx0XHRcdG5hbWU6IFwiYmVmb3JlLXVubG9hZC1kaWFsb2dcIixcblx0XHRcdFx0dXJsLFxuXHRcdFx0XHRtb2RhbFBhcmVudElkZW50aXR5OiB3aW5kb3dJZCxcblx0XHRcdFx0ZnJhbWU6IHRydWUsXG5cdFx0XHRcdGRlZmF1bHRIZWlnaHQ6IGNsb3NlVHlwZSA9PT0gXCJ3aW5kb3dcIiA/IDI0MCA6IDIwMCxcblx0XHRcdFx0ZGVmYXVsdFdpZHRoOiA0MDAsXG5cdFx0XHRcdHNhdmVXaW5kb3dTdGF0ZTogZmFsc2UsXG5cdFx0XHRcdGRlZmF1bHRDZW50ZXJlZDogdHJ1ZSxcblx0XHRcdFx0bWF4aW1pemFibGU6IGZhbHNlLFxuXHRcdFx0XHRtaW5pbWl6YWJsZTogZmFsc2UsXG5cdFx0XHRcdHJlc2l6YWJsZTogZmFsc2Vcblx0XHRcdH0pO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRyZWplY3QoZXJyb3IpO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gbmV3IFByb21pc2UoaGFuZGxlVXNlckRlY2lzaW9uUHJvbWlzZSk7XG59XG5cbi8qKlxuICogT3ZlcnJpZGUgdGhlIHBsYXRmb3JtIHByb3ZpZGVyLlxuICogQHBhcmFtIFBsYXRmb3JtUHJvdmlkZXIgVGhlIHBsYXRmb3JtIHByb3ZpZGVyIGJhc2UgY2xhc3MuXG4gKiBAcmV0dXJucyBUaGUgb3ZlcnJpZGRlbiBwbGF0Zm9ybSBwcm92aWRlci5cbiAqL1xuZnVuY3Rpb24gb3ZlcnJpZGVDYWxsYmFjayhcblx0UGxhdGZvcm1Qcm92aWRlcjogT3BlbkZpbi5Db25zdHJ1Y3RvcjxPcGVuRmluLlBsYXRmb3JtUHJvdmlkZXI+XG4pOiBPcGVuRmluLlBsYXRmb3JtUHJvdmlkZXIge1xuXHQvKipcblx0ICogT3ZlcnJpZGUgZm9yIHRoZSBkaWFsb2cuXG5cdCAqL1xuXHRjbGFzcyBCZWZvcmVVbmxvYWREaWFsb2dPdmVycmlkZSBleHRlbmRzIFBsYXRmb3JtUHJvdmlkZXIge1xuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgdXNlciBkZWNpc2lvbiBmb3IgdW5sb2FkaW5nIGEgd2luZG93LlxuXHRcdCAqIEBwYXJhbSBwYXlsb2FkIFRoZSBwYXlsb2FkLlxuXHRcdCAqIEByZXR1cm5zIFRoZSBjbG9zZSBkZWNpc2lvbi5cblx0XHQgKi9cblx0XHRwdWJsaWMgYXN5bmMgZ2V0VXNlckRlY2lzaW9uRm9yQmVmb3JlVW5sb2FkKFxuXHRcdFx0cGF5bG9hZDogT3BlbkZpbi5WaWV3c1ByZXZlbnRpbmdVbmxvYWRQYXlsb2FkXG5cdFx0KTogUHJvbWlzZTxPcGVuRmluLkJlZm9yZVVubG9hZFVzZXJEZWNpc2lvbj4ge1xuXHRcdFx0Y29uc3QgeyB3aW5kb3dTaG91bGRDbG9zZSwgdmlld3NQcmV2ZW50aW5nVW5sb2FkLCB2aWV3c05vdFByZXZlbnRpbmdVbmxvYWQsIHdpbmRvd0lkLCBjbG9zZVR5cGUgfSA9XG5cdFx0XHRcdHBheWxvYWQ7XG5cblx0XHRcdGNvbnN0IGNvbnRpbnVlV2l0aENsb3NlID0gYXdhaXQgbGF1bmNoRGlhbG9nKHZpZXdzUHJldmVudGluZ1VubG9hZCwgd2luZG93SWQsIGNsb3NlVHlwZSk7XG5cblx0XHRcdGlmIChjb250aW51ZVdpdGhDbG9zZSkge1xuXHRcdFx0XHRyZXR1cm4geyB3aW5kb3dTaG91bGRDbG9zZSwgdmlld3NUb0Nsb3NlOiBbLi4udmlld3NOb3RQcmV2ZW50aW5nVW5sb2FkLCAuLi52aWV3c1ByZXZlbnRpbmdVbmxvYWRdIH07XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4geyB3aW5kb3dTaG91bGRDbG9zZTogZmFsc2UsIHZpZXdzVG9DbG9zZTogW10gfTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIG5ldyBCZWZvcmVVbmxvYWREaWFsb2dPdmVycmlkZSgpO1xufVxuXG5maW4uUGxhdGZvcm0uaW5pdCh7IG92ZXJyaWRlQ2FsbGJhY2sgfSkuY2F0Y2goKGVycm9yKSA9PiBjb25zb2xlLmVycm9yKGVycm9yKSk7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/js/view.bundle.js b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/js/view.bundle.js new file mode 100644 index 00000000..13e23315 --- /dev/null +++ b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/js/view.bundle.js @@ -0,0 +1,39 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/*!****************************!*\ + !*** ./client/src/view.ts ***! + \****************************/ + +document.addEventListener("DOMContentLoaded", () => { + const params = new URLSearchParams(window.location.search); + const viewTitle = params.get("title"); + const viewHeader = document.querySelector("#view-title"); + const testInput = document.querySelector("#test-input"); + if (document && viewTitle) { + document.title = viewTitle; + } + if (viewHeader && viewTitle) { + viewHeader.innerHTML = viewTitle; + } + if (testInput) { + testInput.addEventListener("input", (event) => { + if (event.target.value !== "") { + window.addEventListener("beforeunload", beforeUnloadListener); + } + else { + window.removeEventListener("beforeunload", beforeUnloadListener); + } + }); + } +}); +/** + * Handle the before unload listener. + * @param e The event to handle. + */ +function beforeUnloadListener(e) { + e.preventDefault(); +} + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlldy5idW5kbGUuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsUUFBUSxDQUFDLGdCQUFnQixDQUFDLGtCQUFrQixFQUFFLEdBQUcsRUFBRTtJQUNsRCxNQUFNLE1BQU0sR0FBRyxJQUFJLGVBQWUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzNELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdEMsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUN6RCxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBRXhELElBQUksUUFBUSxJQUFJLFNBQVMsRUFBRSxDQUFDO1FBQzNCLFFBQVEsQ0FBQyxLQUFLLEdBQUcsU0FBUyxDQUFDO0lBQzVCLENBQUM7SUFDRCxJQUFJLFVBQVUsSUFBSSxTQUFTLEVBQUUsQ0FBQztRQUM3QixVQUFVLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztJQUNsQyxDQUFDO0lBRUQsSUFBSSxTQUFTLEVBQUUsQ0FBQztRQUNmLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUM3QyxJQUFLLEtBQUssQ0FBQyxNQUE4QixDQUFDLEtBQUssS0FBSyxFQUFFLEVBQUUsQ0FBQztnQkFDeEQsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGNBQWMsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO1lBQy9ELENBQUM7aUJBQU0sQ0FBQztnQkFDUCxNQUFNLENBQUMsbUJBQW1CLENBQUMsY0FBYyxFQUFFLG9CQUFvQixDQUFDLENBQUM7WUFDbEUsQ0FBQztRQUNGLENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztBQUNGLENBQUMsQ0FBQyxDQUFDO0FBRUg7OztHQUdHO0FBQ0gsU0FBUyxvQkFBb0IsQ0FBQyxDQUFRO0lBQ3JDLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUNwQixDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vd2Fybi1iZWZvcmUtY2xvc2luZy1kaWFsb2cvLi9jbGllbnQvc3JjL3ZpZXcudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgKCkgPT4ge1xuXHRjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuXHRjb25zdCB2aWV3VGl0bGUgPSBwYXJhbXMuZ2V0KFwidGl0bGVcIik7XG5cdGNvbnN0IHZpZXdIZWFkZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3ZpZXctdGl0bGVcIik7XG5cdGNvbnN0IHRlc3RJbnB1dCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjdGVzdC1pbnB1dFwiKTtcblxuXHRpZiAoZG9jdW1lbnQgJiYgdmlld1RpdGxlKSB7XG5cdFx0ZG9jdW1lbnQudGl0bGUgPSB2aWV3VGl0bGU7XG5cdH1cblx0aWYgKHZpZXdIZWFkZXIgJiYgdmlld1RpdGxlKSB7XG5cdFx0dmlld0hlYWRlci5pbm5lckhUTUwgPSB2aWV3VGl0bGU7XG5cdH1cblxuXHRpZiAodGVzdElucHV0KSB7XG5cdFx0dGVzdElucHV0LmFkZEV2ZW50TGlzdGVuZXIoXCJpbnB1dFwiLCAoZXZlbnQpID0+IHtcblx0XHRcdGlmICgoZXZlbnQudGFyZ2V0IGFzIEhUTUxUZXh0QXJlYUVsZW1lbnQpLnZhbHVlICE9PSBcIlwiKSB7XG5cdFx0XHRcdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKFwiYmVmb3JldW5sb2FkXCIsIGJlZm9yZVVubG9hZExpc3RlbmVyKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKFwiYmVmb3JldW5sb2FkXCIsIGJlZm9yZVVubG9hZExpc3RlbmVyKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxufSk7XG5cbi8qKlxuICogSGFuZGxlIHRoZSBiZWZvcmUgdW5sb2FkIGxpc3RlbmVyLlxuICogQHBhcmFtIGUgVGhlIGV2ZW50IHRvIGhhbmRsZS5cbiAqL1xuZnVuY3Rpb24gYmVmb3JlVW5sb2FkTGlzdGVuZXIoZTogRXZlbnQpOiB2b2lkIHtcblx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/manifest.fin.json b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/manifest.fin.json new file mode 100644 index 00000000..66f922ee --- /dev/null +++ b/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/manifest.fin.json @@ -0,0 +1,115 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "enableBeforeUnload": true, + "uuid": "platform-warn", + "icon": "https://openfin.github.io/golden-prototype/favicon.ico", + "autoShow": false, + "providerUrl": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/provider.html", + "apiDiagnostics": false, + "defaultWindowOptions": { + "contextMenu": true, + "defaultWidth": 900, + "defaultHeight": 900, + "defaultLeft": 0, + "defaultTop": 0, + "saveWindowState": false, + "backgroundThrottling": true, + "minHeight": 445, + "minWidth": 354, + "defaultCentered": true + } + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "column", + "id": "no-drop-target", + "content": [ + { + "type": "row", + "content": [ + { + "type": "stack", + "content": [ + { + "type": "component", + "title": "view1", + "componentName": "view", + "componentState": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/view.html?title=view1", + "name": "view1", + "backgroundThrottling": true, + "componentName": "view" + } + } + ] + }, + { + "type": "stack", + "content": [ + { + "type": "component", + "title": "view3", + "componentName": "view", + "componentState": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/view.html?title=view3", + "name": "view3", + "backgroundThrottling": true, + "componentName": "view" + } + } + ] + } + ] + }, + { + "type": "row", + "content": [ + { + "type": "stack", + "content": [ + { + "type": "component", + "title": "view2", + "componentName": "view", + "componentState": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/view.html?title=view2", + "name": "view2", + "componentName": "view" + } + } + ] + }, + { + "type": "stack", + "content": [ + { + "type": "component", + "title": "view4", + "componentName": "view", + "componentState": { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-platform-warn-before-closing-dialog/html/view.html?title=view4", + "name": "view4", + "backgroundThrottling": true, + "componentName": "view" + } + } + ] + } + ] + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-popup-window-advanced/common/images/icon-blue.png b/dev/john/update-logging-example/use-popup-window-advanced/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-popup-window-advanced/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-popup-window-advanced/common/style/app.css b/dev/john/update-logging-example/use-popup-window-advanced/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-advanced/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-popup-window-advanced/favicon.ico b/dev/john/update-logging-example/use-popup-window-advanced/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-popup-window-advanced/favicon.ico differ diff --git a/dev/john/update-logging-example/use-popup-window-advanced/html/app.html b/dev/john/update-logging-example/use-popup-window-advanced/html/app.html new file mode 100644 index 00000000..d35daad4 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-advanced/html/app.html @@ -0,0 +1,33 @@ + + + + + + + Popup Window | Advanced + + + + + +
+
+

Popup Window

+

How to use advanced popup window options.

+
+
+ OpenFin +
+
+
+

+ This is an example of a popup window that will either return a single result or be dismissed based on + user interaction. +

+ + +

Result

+ +
+ + diff --git a/dev/john/update-logging-example/use-popup-window-advanced/html/popup.html b/dev/john/update-logging-example/use-popup-window-advanced/html/popup.html new file mode 100644 index 00000000..b4f7d5bf --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-advanced/html/popup.html @@ -0,0 +1,24 @@ + + + + + + + Popup Window + + + + + +
+

+
+ + + + + +
+
+ + diff --git a/dev/john/update-logging-example/use-popup-window-advanced/js/app.bundle.js b/dev/john/update-logging-example/use-popup-window-advanced/js/app.bundle.js new file mode 100644 index 00000000..dd7fe031 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-advanced/js/app.bundle.js @@ -0,0 +1,83 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +document.addEventListener("DOMContentLoaded", initDom); +/** + * Initialize the DOM elements. + */ +async function initDom() { + // provision about:blank window to later show as popup + await fin.Window.create({ name: "popup", autoShow: false }); + const showPopupButton = document.querySelector("#btn-show-popup"); + if (showPopupButton) { + showPopupButton.addEventListener("click", createPopupWindow); + } +} +/** + * Create the popup window from the click. + * @param event The event to handle. + */ +async function createPopupWindow(event) { + resetPopupResult(); + const { top, right, height } = event.target.getBoundingClientRect(); + const hHeight = height / 2; + const result = await fin.me.showPopupWindow({ + name: "popup", + additionalOptions: { + customData: { + shownAsPopup: Date.now() + } + }, + url: location.href.replace("app", "popup"), + x: right + 6, + y: Math.round(top + hHeight), + height: 150, + width: 300, + hideOnClose: true + }); + renderPopupResult(result); +} +/** + * Display the popup result. + * @param result The result to display. + */ +function renderPopupResult(result) { + const res = document.querySelector("#popup-result"); + if (res) { + res.textContent = JSON.stringify(result, undefined, 2); + } +} +/** + * Clear the popup result. + */ +function resetPopupResult() { + const res = document.querySelector("#popup-result"); + if (res) { + res.textContent = "No result"; + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOztVQUFBO1VBQ0E7Ozs7O1dDREE7V0FDQTtXQUNBO1dBQ0EsdURBQXVELGlCQUFpQjtXQUN4RTtXQUNBLGdEQUFnRCxhQUFhO1dBQzdEOzs7Ozs7Ozs7QUNKQSxRQUFRLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFFdkQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsT0FBTztJQUNyQixzREFBc0Q7SUFDdEQsTUFBTSxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDNUQsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBb0IsaUJBQWlCLENBQUMsQ0FBQztJQUNyRixJQUFJLGVBQWUsRUFBRSxDQUFDO1FBQ3JCLGVBQWUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztJQUM5RCxDQUFDO0FBQ0YsQ0FBQztBQUVEOzs7R0FHRztBQUNILEtBQUssVUFBVSxpQkFBaUIsQ0FBQyxLQUFpQjtJQUNqRCxnQkFBZ0IsRUFBRSxDQUFDO0lBQ25CLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUMzQixLQUFLLENBQUMsTUFDTixDQUFDLHFCQUFxQixFQUFFLENBQUM7SUFDMUIsTUFBTSxPQUFPLEdBQUcsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUMzQixNQUFNLE1BQU0sR0FBRyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDO1FBQzNDLElBQUksRUFBRSxPQUFPO1FBQ2IsaUJBQWlCLEVBQUU7WUFDbEIsVUFBVSxFQUFFO2dCQUNYLFlBQVksRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO2FBQ3hCO1NBQ0Q7UUFDRCxHQUFHLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQztRQUMxQyxDQUFDLEVBQUUsS0FBSyxHQUFHLENBQUM7UUFDWixDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDO1FBQzVCLE1BQU0sRUFBRSxHQUFHO1FBQ1gsS0FBSyxFQUFFLEdBQUc7UUFDVixXQUFXLEVBQUUsSUFBSTtLQUNqQixDQUFDLENBQUM7SUFDSCxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUMzQixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBUyxpQkFBaUIsQ0FBQyxNQUEyQjtJQUNyRCxNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ3BELElBQUksR0FBRyxFQUFFLENBQUM7UUFDVCxHQUFHLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN4RCxDQUFDO0FBQ0YsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxnQkFBZ0I7SUFDeEIsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUNwRCxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ1QsR0FBRyxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7SUFDL0IsQ0FBQztBQUNGLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly91c2UtcG9wdXAtd2luZG93LWFkdmFuY2VkL3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctYWR2YW5jZWQvd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly91c2UtcG9wdXAtd2luZG93LWFkdmFuY2VkLy4vY2xpZW50L3NyYy9hcHAudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gVGhlIHJlcXVpcmUgc2NvcGVcbnZhciBfX3dlYnBhY2tfcmVxdWlyZV9fID0ge307XG5cbiIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsImltcG9ydCB0eXBlIE9wZW5GaW4gZnJvbSBcIkBvcGVuZmluL2NvcmVcIjtcblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgaW5pdERvbSk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgRE9NIGVsZW1lbnRzLlxuICovXG5hc3luYyBmdW5jdGlvbiBpbml0RG9tKCk6IFByb21pc2U8dm9pZD4ge1xuXHQvLyBwcm92aXNpb24gYWJvdXQ6Ymxhbmsgd2luZG93IHRvIGxhdGVyIHNob3cgYXMgcG9wdXBcblx0YXdhaXQgZmluLldpbmRvdy5jcmVhdGUoeyBuYW1lOiBcInBvcHVwXCIsIGF1dG9TaG93OiBmYWxzZSB9KTtcblx0Y29uc3Qgc2hvd1BvcHVwQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MQnV0dG9uRWxlbWVudD4oXCIjYnRuLXNob3ctcG9wdXBcIik7XG5cdGlmIChzaG93UG9wdXBCdXR0b24pIHtcblx0XHRzaG93UG9wdXBCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGNyZWF0ZVBvcHVwV2luZG93KTtcblx0fVxufVxuXG4vKipcbiAqIENyZWF0ZSB0aGUgcG9wdXAgd2luZG93IGZyb20gdGhlIGNsaWNrLlxuICogQHBhcmFtIGV2ZW50IFRoZSBldmVudCB0byBoYW5kbGUuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVBvcHVwV2luZG93KGV2ZW50OiBNb3VzZUV2ZW50KTogUHJvbWlzZTx2b2lkPiB7XG5cdHJlc2V0UG9wdXBSZXN1bHQoKTtcblx0Y29uc3QgeyB0b3AsIHJpZ2h0LCBoZWlnaHQgfTogeyB0b3A6IG51bWJlcjsgcmlnaHQ6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfSA9IChcblx0XHRldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnRcblx0KS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0Y29uc3QgaEhlaWdodCA9IGhlaWdodCAvIDI7XG5cdGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbi5tZS5zaG93UG9wdXBXaW5kb3coe1xuXHRcdG5hbWU6IFwicG9wdXBcIixcblx0XHRhZGRpdGlvbmFsT3B0aW9uczoge1xuXHRcdFx0Y3VzdG9tRGF0YToge1xuXHRcdFx0XHRzaG93bkFzUG9wdXA6IERhdGUubm93KClcblx0XHRcdH1cblx0XHR9LFxuXHRcdHVybDogbG9jYXRpb24uaHJlZi5yZXBsYWNlKFwiYXBwXCIsIFwicG9wdXBcIiksXG5cdFx0eDogcmlnaHQgKyA2LFxuXHRcdHk6IE1hdGgucm91bmQodG9wICsgaEhlaWdodCksXG5cdFx0aGVpZ2h0OiAxNTAsXG5cdFx0d2lkdGg6IDMwMCxcblx0XHRoaWRlT25DbG9zZTogdHJ1ZVxuXHR9KTtcblx0cmVuZGVyUG9wdXBSZXN1bHQocmVzdWx0KTtcbn1cblxuLyoqXG4gKiBEaXNwbGF5IHRoZSBwb3B1cCByZXN1bHQuXG4gKiBAcGFyYW0gcmVzdWx0IFRoZSByZXN1bHQgdG8gZGlzcGxheS5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyUG9wdXBSZXN1bHQocmVzdWx0OiBPcGVuRmluLlBvcHVwUmVzdWx0KTogdm9pZCB7XG5cdGNvbnN0IHJlcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjcG9wdXAtcmVzdWx0XCIpO1xuXHRpZiAocmVzKSB7XG5cdFx0cmVzLnRleHRDb250ZW50ID0gSlNPTi5zdHJpbmdpZnkocmVzdWx0LCB1bmRlZmluZWQsIDIpO1xuXHR9XG59XG5cbi8qKlxuICogQ2xlYXIgdGhlIHBvcHVwIHJlc3VsdC5cbiAqL1xuZnVuY3Rpb24gcmVzZXRQb3B1cFJlc3VsdCgpOiB2b2lkIHtcblx0Y29uc3QgcmVzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNwb3B1cC1yZXN1bHRcIik7XG5cdGlmIChyZXMpIHtcblx0XHRyZXMudGV4dENvbnRlbnQgPSBcIk5vIHJlc3VsdFwiO1xuXHR9XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-popup-window-advanced/js/popup.bundle.js b/dev/john/update-logging-example/use-popup-window-advanced/js/popup.bundle.js new file mode 100644 index 00000000..4d462ef8 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-advanced/js/popup.bundle.js @@ -0,0 +1,66 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!*****************************!*\ + !*** ./client/src/popup.ts ***! + \*****************************/ +__webpack_require__.r(__webpack_exports__); +const me = fin.me; +document.addEventListener("DOMContentLoaded", initDom); +/** + * Initialize the DOM elements. + */ +async function initDom() { + const okButton = document.querySelector("#btn-ok"); + const confirmButton = document.querySelector("#btn-confirm"); + const cancelButton = document.querySelector("#btn-cancel"); + if (okButton) { + okButton.addEventListener("click", async () => { + await me.dispatchPopupResult("ok"); + }); + } + if (confirmButton) { + confirmButton.addEventListener("click", async () => { + await me.dispatchPopupResult("confirm"); + }); + } + if (cancelButton) { + cancelButton.addEventListener("click", async () => { + await me.dispatchPopupResult("cancel"); + }); + } + await renderShownDate(); + await me.on("shown", renderShownDate); +} +/** + * Show the shown date in the UI. + */ +async function renderShownDate() { + const shownDateEl = document.querySelector("#shown-date"); + const { customData } = await me.getOptions(); + const { shownAsPopup } = customData; + if (shownDateEl) { + shownDateEl.textContent = new Date(shownAsPopup).toTimeString(); + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9wdXAuYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7O1VBQUE7VUFDQTs7Ozs7V0NEQTtXQUNBO1dBQ0E7V0FDQSx1REFBdUQsaUJBQWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0Q7Ozs7Ozs7OztBQ0pBLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxFQUFvQixDQUFDO0FBRXBDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxPQUFPLENBQUMsQ0FBQztBQUV2RDs7R0FFRztBQUNILEtBQUssVUFBVSxPQUFPO0lBQ3JCLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkQsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUM3RCxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBRTNELElBQUksUUFBUSxFQUFFLENBQUM7UUFDZCxRQUFRLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzdDLE1BQU0sRUFBRSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BDLENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVELElBQUksYUFBYSxFQUFFLENBQUM7UUFDbkIsYUFBYSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxLQUFLLElBQUksRUFBRTtZQUNsRCxNQUFNLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN6QyxDQUFDLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRCxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ2xCLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDakQsTUFBTSxFQUFFLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDeEMsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQsTUFBTSxlQUFlLEVBQUUsQ0FBQztJQUN4QixNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLGVBQWUsQ0FBQyxDQUFDO0FBQ3ZDLENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxlQUFlO0lBQzdCLE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDMUQsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQzdDLE1BQU0sRUFBRSxZQUFZLEVBQUUsR0FBNkIsVUFBVSxDQUFDO0lBQzlELElBQUksV0FBVyxFQUFFLENBQUM7UUFDakIsV0FBVyxDQUFDLFdBQVcsR0FBRyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUNqRSxDQUFDO0FBQ0YsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctYWR2YW5jZWQvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vdXNlLXBvcHVwLXdpbmRvdy1hZHZhbmNlZC93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctYWR2YW5jZWQvLi9jbGllbnQvc3JjL3BvcHVwLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSByZXF1aXJlIHNjb3BlXG52YXIgX193ZWJwYWNrX3JlcXVpcmVfXyA9IHt9O1xuXG4iLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgdHlwZSBPcGVuRmluIGZyb20gXCJAb3BlbmZpbi9jb3JlXCI7XG5cbmNvbnN0IG1lID0gZmluLm1lIGFzIE9wZW5GaW4uV2luZG93O1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBpbml0RG9tKTtcblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSBET00gZWxlbWVudHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluaXREb20oKTogUHJvbWlzZTx2b2lkPiB7XG5cdGNvbnN0IG9rQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNidG4tb2tcIik7XG5cdGNvbnN0IGNvbmZpcm1CdXR0b24gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2J0bi1jb25maXJtXCIpO1xuXHRjb25zdCBjYW5jZWxCdXR0b24gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2J0bi1jYW5jZWxcIik7XG5cblx0aWYgKG9rQnV0dG9uKSB7XG5cdFx0b2tCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGFzeW5jICgpID0+IHtcblx0XHRcdGF3YWl0IG1lLmRpc3BhdGNoUG9wdXBSZXN1bHQoXCJva1wiKTtcblx0XHR9KTtcblx0fVxuXG5cdGlmIChjb25maXJtQnV0dG9uKSB7XG5cdFx0Y29uZmlybUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0YXdhaXQgbWUuZGlzcGF0Y2hQb3B1cFJlc3VsdChcImNvbmZpcm1cIik7XG5cdFx0fSk7XG5cdH1cblxuXHRpZiAoY2FuY2VsQnV0dG9uKSB7XG5cdFx0Y2FuY2VsQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCBtZS5kaXNwYXRjaFBvcHVwUmVzdWx0KFwiY2FuY2VsXCIpO1xuXHRcdH0pO1xuXHR9XG5cblx0YXdhaXQgcmVuZGVyU2hvd25EYXRlKCk7XG5cdGF3YWl0IG1lLm9uKFwic2hvd25cIiwgcmVuZGVyU2hvd25EYXRlKTtcbn1cblxuLyoqXG4gKiBTaG93IHRoZSBzaG93biBkYXRlIGluIHRoZSBVSS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVuZGVyU2hvd25EYXRlKCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBzaG93bkRhdGVFbCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjc2hvd24tZGF0ZVwiKTtcblx0Y29uc3QgeyBjdXN0b21EYXRhIH0gPSBhd2FpdCBtZS5nZXRPcHRpb25zKCk7XG5cdGNvbnN0IHsgc2hvd25Bc1BvcHVwIH06IHsgc2hvd25Bc1BvcHVwOiBudW1iZXIgfSA9IGN1c3RvbURhdGE7XG5cdGlmIChzaG93bkRhdGVFbCkge1xuXHRcdHNob3duRGF0ZUVsLnRleHRDb250ZW50ID0gbmV3IERhdGUoc2hvd25Bc1BvcHVwKS50b1RpbWVTdHJpbmcoKTtcblx0fVxufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dev/john/update-logging-example/use-popup-window-advanced/manifest.fin.json b/dev/john/update-logging-example/use-popup-window-advanced/manifest.fin.json new file mode 100644 index 00000000..5f5d3366 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-advanced/manifest.fin.json @@ -0,0 +1,35 @@ +{ + "licenseKey": "openfin-demo-license-key", + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "how-to-use-popup-window-advanced", + "autoShow": true + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "stack", + "id": "no-drop-target", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "processAffinity": "ps_1", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-popup-window-advanced/html/app.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-popup-window-modal/common/images/icon-blue.png b/dev/john/update-logging-example/use-popup-window-modal/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-popup-window-modal/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-popup-window-modal/common/style/app.css b/dev/john/update-logging-example/use-popup-window-modal/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-modal/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-popup-window-modal/favicon.ico b/dev/john/update-logging-example/use-popup-window-modal/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-popup-window-modal/favicon.ico differ diff --git a/dev/john/update-logging-example/use-popup-window-modal/html/app.html b/dev/john/update-logging-example/use-popup-window-modal/html/app.html new file mode 100644 index 00000000..0982ea05 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-modal/html/app.html @@ -0,0 +1,30 @@ + + + + + + + Popup Window | Modal + + + + + +
+
+

Popup Window

+

How to use modal popup window options.

+
+
+ OpenFin +
+
+
+

This is an example of a modal popup window.

+ + +

Result

+ +
+ + diff --git a/dev/john/update-logging-example/use-popup-window-modal/html/popup.html b/dev/john/update-logging-example/use-popup-window-modal/html/popup.html new file mode 100644 index 00000000..27cd9882 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-modal/html/popup.html @@ -0,0 +1,24 @@ + + + + + + + Popup Window + + + + + +
+

Modal content

+
+ + + + + +
+
+ + diff --git a/dev/john/update-logging-example/use-popup-window-modal/js/app.bundle.js b/dev/john/update-logging-example/use-popup-window-modal/js/app.bundle.js new file mode 100644 index 00000000..c9035968 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-modal/js/app.bundle.js @@ -0,0 +1,80 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +document.addEventListener("DOMContentLoaded", initDom); +/** + * Initialize the DOM elements. + */ +function initDom() { + const showPopupButton = document.querySelector("#btn-show-popup"); + if (showPopupButton) { + showPopupButton.addEventListener("click", createPopupWindow); + } +} +/** + * Create the popup window from the click. + */ +async function createPopupWindow() { + const PARENT_FRAME_OFFSET = 64; + resetPopupResult(); + const parentWindow = await fin.me.getCurrentWindow(); + const { identity: modalParentIdentity } = parentWindow; + const parentBounds = await parentWindow.getBounds(); + const qHeight = parentBounds.height / 4; + const result = await fin.me.showPopupWindow({ + initialOptions: { + modalParentIdentity + }, + url: location.href.replace("app", "popup"), + x: Math.floor(parentBounds.width / 8), + y: Math.floor(parentBounds.height / 8) - PARENT_FRAME_OFFSET, + height: Math.floor(parentBounds.height - qHeight), + width: Math.floor(parentBounds.width - qHeight), + blurBehavior: "modal" + }); + renderPopupResult(result); +} +/** + * Display the popup result. + * @param result The result to display. + */ +function renderPopupResult(result) { + const res = document.querySelector("#popup-result"); + if (res) { + res.textContent = JSON.stringify(result, undefined, 2); + } +} +/** + * Clear the popup result. + */ +function resetPopupResult() { + const res = document.querySelector("#popup-result"); + if (res) { + res.textContent = "No result"; + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOztVQUFBO1VBQ0E7Ozs7O1dDREE7V0FDQTtXQUNBO1dBQ0EsdURBQXVELGlCQUFpQjtXQUN4RTtXQUNBLGdEQUFnRCxhQUFhO1dBQzdEOzs7Ozs7Ozs7QUNKQSxRQUFRLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFFdkQ7O0dBRUc7QUFDSCxTQUFTLE9BQU87SUFDZixNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDbEUsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUNyQixlQUFlLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLGlCQUFpQixDQUFDLENBQUM7SUFDOUQsQ0FBQztBQUNGLENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxpQkFBaUI7SUFDL0IsTUFBTSxtQkFBbUIsR0FBRyxFQUFFLENBQUM7SUFDL0IsZ0JBQWdCLEVBQUUsQ0FBQztJQUNuQixNQUFNLFlBQVksR0FBRyxNQUFPLEdBQUcsQ0FBQyxFQUFtQixDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDdkUsTUFBTSxFQUFFLFFBQVEsRUFBRSxtQkFBbUIsRUFBRSxHQUFHLFlBQVksQ0FBQztJQUN2RCxNQUFNLFlBQVksR0FBRyxNQUFNLFlBQVksQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUNwRCxNQUFNLE9BQU8sR0FBRyxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUN4QyxNQUFNLE1BQU0sR0FBRyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDO1FBQzNDLGNBQWMsRUFBRTtZQUNmLG1CQUFtQjtTQUNuQjtRQUNELEdBQUcsRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDO1FBQzFDLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ3JDLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEdBQUcsbUJBQW1CO1FBQzVELE1BQU0sRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDO1FBQ2pELEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDO1FBQy9DLFlBQVksRUFBRSxPQUFPO0tBQ3JCLENBQUMsQ0FBQztJQUNILGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzNCLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGlCQUFpQixDQUFDLE1BQTJCO0lBQ3JELE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDcEQsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNULEdBQUcsQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3hELENBQUM7QUFDRixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGdCQUFnQjtJQUN4QixNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ3BELElBQUksR0FBRyxFQUFFLENBQUM7UUFDVCxHQUFHLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztJQUMvQixDQUFDO0FBQ0YsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctbW9kYWwvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vdXNlLXBvcHVwLXdpbmRvdy1tb2RhbC93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctbW9kYWwvLi9jbGllbnQvc3JjL2FwcC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBpbml0RG9tKTtcblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSBET00gZWxlbWVudHMuXG4gKi9cbmZ1bmN0aW9uIGluaXREb20oKTogdm9pZCB7XG5cdGNvbnN0IHNob3dQb3B1cEJ1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjYnRuLXNob3ctcG9wdXBcIik7XG5cdGlmIChzaG93UG9wdXBCdXR0b24pIHtcblx0XHRzaG93UG9wdXBCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGNyZWF0ZVBvcHVwV2luZG93KTtcblx0fVxufVxuXG4vKipcbiAqIENyZWF0ZSB0aGUgcG9wdXAgd2luZG93IGZyb20gdGhlIGNsaWNrLlxuICovXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVQb3B1cFdpbmRvdygpOiBQcm9taXNlPHZvaWQ+IHtcblx0Y29uc3QgUEFSRU5UX0ZSQU1FX09GRlNFVCA9IDY0O1xuXHRyZXNldFBvcHVwUmVzdWx0KCk7XG5cdGNvbnN0IHBhcmVudFdpbmRvdyA9IGF3YWl0IChmaW4ubWUgYXMgT3BlbkZpbi5WaWV3KS5nZXRDdXJyZW50V2luZG93KCk7XG5cdGNvbnN0IHsgaWRlbnRpdHk6IG1vZGFsUGFyZW50SWRlbnRpdHkgfSA9IHBhcmVudFdpbmRvdztcblx0Y29uc3QgcGFyZW50Qm91bmRzID0gYXdhaXQgcGFyZW50V2luZG93LmdldEJvdW5kcygpO1xuXHRjb25zdCBxSGVpZ2h0ID0gcGFyZW50Qm91bmRzLmhlaWdodCAvIDQ7XG5cdGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbi5tZS5zaG93UG9wdXBXaW5kb3coe1xuXHRcdGluaXRpYWxPcHRpb25zOiB7XG5cdFx0XHRtb2RhbFBhcmVudElkZW50aXR5XG5cdFx0fSxcblx0XHR1cmw6IGxvY2F0aW9uLmhyZWYucmVwbGFjZShcImFwcFwiLCBcInBvcHVwXCIpLFxuXHRcdHg6IE1hdGguZmxvb3IocGFyZW50Qm91bmRzLndpZHRoIC8gOCksXG5cdFx0eTogTWF0aC5mbG9vcihwYXJlbnRCb3VuZHMuaGVpZ2h0IC8gOCkgLSBQQVJFTlRfRlJBTUVfT0ZGU0VULFxuXHRcdGhlaWdodDogTWF0aC5mbG9vcihwYXJlbnRCb3VuZHMuaGVpZ2h0IC0gcUhlaWdodCksXG5cdFx0d2lkdGg6IE1hdGguZmxvb3IocGFyZW50Qm91bmRzLndpZHRoIC0gcUhlaWdodCksXG5cdFx0Ymx1ckJlaGF2aW9yOiBcIm1vZGFsXCJcblx0fSk7XG5cdHJlbmRlclBvcHVwUmVzdWx0KHJlc3VsdCk7XG59XG5cbi8qKlxuICogRGlzcGxheSB0aGUgcG9wdXAgcmVzdWx0LlxuICogQHBhcmFtIHJlc3VsdCBUaGUgcmVzdWx0IHRvIGRpc3BsYXkuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclBvcHVwUmVzdWx0KHJlc3VsdDogT3BlbkZpbi5Qb3B1cFJlc3VsdCk6IHZvaWQge1xuXHRjb25zdCByZXMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3BvcHVwLXJlc3VsdFwiKTtcblx0aWYgKHJlcykge1xuXHRcdHJlcy50ZXh0Q29udGVudCA9IEpTT04uc3RyaW5naWZ5KHJlc3VsdCwgdW5kZWZpbmVkLCAyKTtcblx0fVxufVxuXG4vKipcbiAqIENsZWFyIHRoZSBwb3B1cCByZXN1bHQuXG4gKi9cbmZ1bmN0aW9uIHJlc2V0UG9wdXBSZXN1bHQoKTogdm9pZCB7XG5cdGNvbnN0IHJlcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjcG9wdXAtcmVzdWx0XCIpO1xuXHRpZiAocmVzKSB7XG5cdFx0cmVzLnRleHRDb250ZW50ID0gXCJObyByZXN1bHRcIjtcblx0fVxufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dev/john/update-logging-example/use-popup-window-modal/js/popup.bundle.js b/dev/john/update-logging-example/use-popup-window-modal/js/popup.bundle.js new file mode 100644 index 00000000..a6c01d8c --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-modal/js/popup.bundle.js @@ -0,0 +1,53 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!*****************************!*\ + !*** ./client/src/popup.ts ***! + \*****************************/ +__webpack_require__.r(__webpack_exports__); +const me = fin.me; +document.addEventListener("DOMContentLoaded", initDom); +/** + * Initialize the DOM elements. + */ +function initDom() { + const okButton = document.querySelector("#btn-ok"); + const confirmButton = document.querySelector("#btn-confirm"); + const cancelButton = document.querySelector("#btn-cancel"); + if (okButton) { + okButton.addEventListener("click", async () => { + await me.dispatchPopupResult("ok"); + }); + } + if (confirmButton) { + confirmButton.addEventListener("click", async () => { + await me.dispatchPopupResult("confirm"); + }); + } + if (cancelButton) { + cancelButton.addEventListener("click", async () => { + await me.dispatchPopupResult("cancel"); + }); + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9wdXAuYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7O1VBQUE7VUFDQTs7Ozs7V0NEQTtXQUNBO1dBQ0E7V0FDQSx1REFBdUQsaUJBQWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0Q7Ozs7Ozs7OztBQ0pBLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxFQUFvQixDQUFDO0FBRXBDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxPQUFPLENBQUMsQ0FBQztBQUV2RDs7R0FFRztBQUNILFNBQVMsT0FBTztJQUNmLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkQsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUM3RCxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBRTNELElBQUksUUFBUSxFQUFFLENBQUM7UUFDZCxRQUFRLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzdDLE1BQU0sRUFBRSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BDLENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVELElBQUksYUFBYSxFQUFFLENBQUM7UUFDbkIsYUFBYSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxLQUFLLElBQUksRUFBRTtZQUNsRCxNQUFNLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN6QyxDQUFDLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRCxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ2xCLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDakQsTUFBTSxFQUFFLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDeEMsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0FBQ0YsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctbW9kYWwvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vdXNlLXBvcHVwLXdpbmRvdy1tb2RhbC93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctbW9kYWwvLi9jbGllbnQvc3JjL3BvcHVwLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSByZXF1aXJlIHNjb3BlXG52YXIgX193ZWJwYWNrX3JlcXVpcmVfXyA9IHt9O1xuXG4iLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgdHlwZSBPcGVuRmluIGZyb20gXCJAb3BlbmZpbi9jb3JlXCI7XG5cbmNvbnN0IG1lID0gZmluLm1lIGFzIE9wZW5GaW4uV2luZG93O1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBpbml0RG9tKTtcblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSBET00gZWxlbWVudHMuXG4gKi9cbmZ1bmN0aW9uIGluaXREb20oKTogdm9pZCB7XG5cdGNvbnN0IG9rQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNidG4tb2tcIik7XG5cdGNvbnN0IGNvbmZpcm1CdXR0b24gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2J0bi1jb25maXJtXCIpO1xuXHRjb25zdCBjYW5jZWxCdXR0b24gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2J0bi1jYW5jZWxcIik7XG5cblx0aWYgKG9rQnV0dG9uKSB7XG5cdFx0b2tCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGFzeW5jICgpID0+IHtcblx0XHRcdGF3YWl0IG1lLmRpc3BhdGNoUG9wdXBSZXN1bHQoXCJva1wiKTtcblx0XHR9KTtcblx0fVxuXG5cdGlmIChjb25maXJtQnV0dG9uKSB7XG5cdFx0Y29uZmlybUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0YXdhaXQgbWUuZGlzcGF0Y2hQb3B1cFJlc3VsdChcImNvbmZpcm1cIik7XG5cdFx0fSk7XG5cdH1cblxuXHRpZiAoY2FuY2VsQnV0dG9uKSB7XG5cdFx0Y2FuY2VsQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCBtZS5kaXNwYXRjaFBvcHVwUmVzdWx0KFwiY2FuY2VsXCIpO1xuXHRcdH0pO1xuXHR9XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-popup-window-modal/manifest.fin.json b/dev/john/update-logging-example/use-popup-window-modal/manifest.fin.json new file mode 100644 index 00000000..57efb767 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-modal/manifest.fin.json @@ -0,0 +1,35 @@ +{ + "licenseKey": "openfin-demo-license-key", + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "how-to-use-popup-window-modal", + "autoShow": true + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "stack", + "id": "no-drop-target", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "processAffinity": "ps_1", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-popup-window-modal/html/app.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-popup-window-multiple-results/common/images/icon-blue.png b/dev/john/update-logging-example/use-popup-window-multiple-results/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-popup-window-multiple-results/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-popup-window-multiple-results/common/style/app.css b/dev/john/update-logging-example/use-popup-window-multiple-results/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-multiple-results/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-popup-window-multiple-results/favicon.ico b/dev/john/update-logging-example/use-popup-window-multiple-results/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-popup-window-multiple-results/favicon.ico differ diff --git a/dev/john/update-logging-example/use-popup-window-multiple-results/html/app.html b/dev/john/update-logging-example/use-popup-window-multiple-results/html/app.html new file mode 100644 index 00000000..f7c93b0c --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-multiple-results/html/app.html @@ -0,0 +1,32 @@ + + + + + + + Popup Window | Multiple Results + + + + + +
+
+

Popup Window

+

How to use multiple results popup window options.

+
+
+ OpenFin +
+
+
+

+ This is an example of a popup window that has the ability to return multiple results to the caller. +

+ + +

Result

+ +
+ + diff --git a/dev/john/update-logging-example/use-popup-window-multiple-results/html/popup.html b/dev/john/update-logging-example/use-popup-window-multiple-results/html/popup.html new file mode 100644 index 00000000..75eea86b --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-multiple-results/html/popup.html @@ -0,0 +1,12 @@ + + + + + + + Popup Window + + + + + diff --git a/dev/john/update-logging-example/use-popup-window-multiple-results/js/app.bundle.js b/dev/john/update-logging-example/use-popup-window-multiple-results/js/app.bundle.js new file mode 100644 index 00000000..c3654f88 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-multiple-results/js/app.bundle.js @@ -0,0 +1,81 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +document.addEventListener("DOMContentLoaded", initDom); +/** + * Initialize the DOM elements. + */ +function initDom() { + const showPopupButton = document.querySelector("#btn-show-popup"); + if (showPopupButton) { + showPopupButton.addEventListener("click", createPopupWindow); + } +} +/** + * Create the popup window from the click. + * @param event The event to handle. + */ +async function createPopupWindow(event) { + resetPopupResult(); + const { right, height } = event.target.getBoundingClientRect(); + const hHeight = height / 2; + const result = await fin.me.showPopupWindow({ + initialOptions: { + customData: await fin.me.interop.getContextGroups() + }, + url: location.href.replace("app", "popup"), + x: right + 5, + y: Math.round(hHeight + 15), + height: 30, + width: 250, + resultDispatchBehavior: "none", + onPopupResult: (popupResult) => { + renderPopupResult(popupResult); + } + }); + renderPopupResult(result); +} +/** + * Display the popup result. + * @param result The result to display. + */ +function renderPopupResult(result) { + const res = document.querySelector("#popup-result"); + if (res) { + res.textContent = JSON.stringify(result, undefined, 2); + } +} +/** + * Clear the popup result. + */ +function resetPopupResult() { + const res = document.querySelector("#popup-result"); + if (res) { + res.textContent = ""; + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOztVQUFBO1VBQ0E7Ozs7O1dDREE7V0FDQTtXQUNBO1dBQ0EsdURBQXVELGlCQUFpQjtXQUN4RTtXQUNBLGdEQUFnRCxhQUFhO1dBQzdEOzs7Ozs7Ozs7QUNKQSxRQUFRLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFFdkQ7O0dBRUc7QUFDSCxTQUFTLE9BQU87SUFDZixNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFvQixpQkFBaUIsQ0FBQyxDQUFDO0lBQ3JGLElBQUksZUFBZSxFQUFFLENBQUM7UUFDckIsZUFBZSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO0lBQzlELENBQUM7QUFDRixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsS0FBSyxVQUFVLGlCQUFpQixDQUFDLEtBQWlCO0lBQ2pELGdCQUFnQixFQUFFLENBQUM7SUFDbkIsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FDdEIsS0FBSyxDQUFDLE1BQ04sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO0lBQzFCLE1BQU0sT0FBTyxHQUFHLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDM0IsTUFBTSxNQUFNLEdBQUcsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLGVBQWUsQ0FBQztRQUMzQyxjQUFjLEVBQUU7WUFDZixVQUFVLEVBQUUsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRTtTQUNuRDtRQUNELEdBQUcsRUFBRSxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDO1FBQzFDLENBQUMsRUFBRSxLQUFLLEdBQUcsQ0FBQztRQUNaLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDM0IsTUFBTSxFQUFFLEVBQUU7UUFDVixLQUFLLEVBQUUsR0FBRztRQUNWLHNCQUFzQixFQUFFLE1BQU07UUFDOUIsYUFBYSxFQUFFLENBQUMsV0FBVyxFQUFFLEVBQUU7WUFDOUIsaUJBQWlCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDaEMsQ0FBQztLQUNELENBQUMsQ0FBQztJQUNILGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzNCLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGlCQUFpQixDQUFDLE1BQTJCO0lBQ3JELE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDcEQsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNULEdBQUcsQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3hELENBQUM7QUFDRixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGdCQUFnQjtJQUN4QixNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ3BELElBQUksR0FBRyxFQUFFLENBQUM7UUFDVCxHQUFHLENBQUMsV0FBVyxHQUFHLEVBQUUsQ0FBQztJQUN0QixDQUFDO0FBQ0YsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctbXVsdGlwbGUtcmVzdWx0cy93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly91c2UtcG9wdXAtd2luZG93LW11bHRpcGxlLXJlc3VsdHMvd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly91c2UtcG9wdXAtd2luZG93LW11bHRpcGxlLXJlc3VsdHMvLi9jbGllbnQvc3JjL2FwcC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBpbml0RG9tKTtcblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSBET00gZWxlbWVudHMuXG4gKi9cbmZ1bmN0aW9uIGluaXREb20oKTogdm9pZCB7XG5cdGNvbnN0IHNob3dQb3B1cEJ1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEJ1dHRvbkVsZW1lbnQ+KFwiI2J0bi1zaG93LXBvcHVwXCIpO1xuXHRpZiAoc2hvd1BvcHVwQnV0dG9uKSB7XG5cdFx0c2hvd1BvcHVwQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBjcmVhdGVQb3B1cFdpbmRvdyk7XG5cdH1cbn1cblxuLyoqXG4gKiBDcmVhdGUgdGhlIHBvcHVwIHdpbmRvdyBmcm9tIHRoZSBjbGljay5cbiAqIEBwYXJhbSBldmVudCBUaGUgZXZlbnQgdG8gaGFuZGxlLlxuICovXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVQb3B1cFdpbmRvdyhldmVudDogTW91c2VFdmVudCk6IFByb21pc2U8dm9pZD4ge1xuXHRyZXNldFBvcHVwUmVzdWx0KCk7XG5cdGNvbnN0IHsgcmlnaHQsIGhlaWdodCB9OiB7IHJpZ2h0OiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH0gPSAoXG5cdFx0ZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50XG5cdCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cdGNvbnN0IGhIZWlnaHQgPSBoZWlnaHQgLyAyO1xuXHRjb25zdCByZXN1bHQgPSBhd2FpdCBmaW4ubWUuc2hvd1BvcHVwV2luZG93KHtcblx0XHRpbml0aWFsT3B0aW9uczoge1xuXHRcdFx0Y3VzdG9tRGF0YTogYXdhaXQgZmluLm1lLmludGVyb3AuZ2V0Q29udGV4dEdyb3VwcygpXG5cdFx0fSxcblx0XHR1cmw6IGxvY2F0aW9uLmhyZWYucmVwbGFjZShcImFwcFwiLCBcInBvcHVwXCIpLFxuXHRcdHg6IHJpZ2h0ICsgNSxcblx0XHR5OiBNYXRoLnJvdW5kKGhIZWlnaHQgKyAxNSksXG5cdFx0aGVpZ2h0OiAzMCxcblx0XHR3aWR0aDogMjUwLFxuXHRcdHJlc3VsdERpc3BhdGNoQmVoYXZpb3I6IFwibm9uZVwiLFxuXHRcdG9uUG9wdXBSZXN1bHQ6IChwb3B1cFJlc3VsdCkgPT4ge1xuXHRcdFx0cmVuZGVyUG9wdXBSZXN1bHQocG9wdXBSZXN1bHQpO1xuXHRcdH1cblx0fSk7XG5cdHJlbmRlclBvcHVwUmVzdWx0KHJlc3VsdCk7XG59XG5cbi8qKlxuICogRGlzcGxheSB0aGUgcG9wdXAgcmVzdWx0LlxuICogQHBhcmFtIHJlc3VsdCBUaGUgcmVzdWx0IHRvIGRpc3BsYXkuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlclBvcHVwUmVzdWx0KHJlc3VsdDogT3BlbkZpbi5Qb3B1cFJlc3VsdCk6IHZvaWQge1xuXHRjb25zdCByZXMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3BvcHVwLXJlc3VsdFwiKTtcblx0aWYgKHJlcykge1xuXHRcdHJlcy50ZXh0Q29udGVudCA9IEpTT04uc3RyaW5naWZ5KHJlc3VsdCwgdW5kZWZpbmVkLCAyKTtcblx0fVxufVxuXG4vKipcbiAqIENsZWFyIHRoZSBwb3B1cCByZXN1bHQuXG4gKi9cbmZ1bmN0aW9uIHJlc2V0UG9wdXBSZXN1bHQoKTogdm9pZCB7XG5cdGNvbnN0IHJlcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjcG9wdXAtcmVzdWx0XCIpO1xuXHRpZiAocmVzKSB7XG5cdFx0cmVzLnRleHRDb250ZW50ID0gXCJcIjtcblx0fVxufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dev/john/update-logging-example/use-popup-window-multiple-results/js/popup.bundle.js b/dev/john/update-logging-example/use-popup-window-multiple-results/js/popup.bundle.js new file mode 100644 index 00000000..be76fac0 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-multiple-results/js/popup.bundle.js @@ -0,0 +1,56 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!*****************************!*\ + !*** ./client/src/popup.ts ***! + \*****************************/ +__webpack_require__.r(__webpack_exports__); +const me = fin.me; +document.addEventListener("DOMContentLoaded", initDom); +/** + * Initialize the DOM elements. + */ +async function initDom() { + await createGroupButtons(); +} +/** + * Create the group buttons. + */ +async function createGroupButtons() { + const { customData: contextGroups } = await me.getOptions(); + for (const group of contextGroups) { + const groupBtn = document.createElement("button"); + groupBtn.style.background = group.displayMetadata.color; + groupBtn.style.border = "none"; + groupBtn.style.borderRadius = "50%"; + groupBtn.style.width = "20px"; + groupBtn.style.height = "20px"; + groupBtn.style.marginRight = "1rem"; + console.log(group); + groupBtn.addEventListener("click", async () => { + await me.dispatchPopupResult(group); + }); + document.body.append(groupBtn); + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9wdXAuYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7O1VBQUE7VUFDQTs7Ozs7V0NEQTtXQUNBO1dBQ0E7V0FDQSx1REFBdUQsaUJBQWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0Q7Ozs7Ozs7OztBQ0pBLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxFQUFvQixDQUFDO0FBRXBDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxPQUFPLENBQUMsQ0FBQztBQUV2RDs7R0FFRztBQUNILEtBQUssVUFBVSxPQUFPO0lBQ3JCLE1BQU0sa0JBQWtCLEVBQUUsQ0FBQztBQUM1QixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsa0JBQWtCO0lBQ2hDLE1BQU0sRUFBRSxVQUFVLEVBQUUsYUFBYSxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDNUQsS0FBSyxNQUFNLEtBQUssSUFBSSxhQUFhLEVBQUUsQ0FBQztRQUNuQyxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2xELFFBQVEsQ0FBQyxLQUFLLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDO1FBQ3hELFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUMvQixRQUFRLENBQUMsS0FBSyxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDcEMsUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDO1FBQzlCLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUMvQixRQUFRLENBQUMsS0FBSyxDQUFDLFdBQVcsR0FBRyxNQUFNLENBQUM7UUFDcEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNuQixRQUFRLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzdDLE1BQU0sRUFBRSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JDLENBQUMsQ0FBQyxDQUFDO1FBQ0gsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDaEMsQ0FBQztBQUNGLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly91c2UtcG9wdXAtd2luZG93LW11bHRpcGxlLXJlc3VsdHMvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vdXNlLXBvcHVwLXdpbmRvdy1tdWx0aXBsZS1yZXN1bHRzL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vdXNlLXBvcHVwLXdpbmRvdy1tdWx0aXBsZS1yZXN1bHRzLy4vY2xpZW50L3NyYy9wb3B1cC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuXG5jb25zdCBtZSA9IGZpbi5tZSBhcyBPcGVuRmluLldpbmRvdztcblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgaW5pdERvbSk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgRE9NIGVsZW1lbnRzLlxuICovXG5hc3luYyBmdW5jdGlvbiBpbml0RG9tKCk6IFByb21pc2U8dm9pZD4ge1xuXHRhd2FpdCBjcmVhdGVHcm91cEJ1dHRvbnMoKTtcbn1cblxuLyoqXG4gKiBDcmVhdGUgdGhlIGdyb3VwIGJ1dHRvbnMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUdyb3VwQnV0dG9ucygpOiBQcm9taXNlPHZvaWQ+IHtcblx0Y29uc3QgeyBjdXN0b21EYXRhOiBjb250ZXh0R3JvdXBzIH0gPSBhd2FpdCBtZS5nZXRPcHRpb25zKCk7XG5cdGZvciAoY29uc3QgZ3JvdXAgb2YgY29udGV4dEdyb3Vwcykge1xuXHRcdGNvbnN0IGdyb3VwQnRuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImJ1dHRvblwiKTtcblx0XHRncm91cEJ0bi5zdHlsZS5iYWNrZ3JvdW5kID0gZ3JvdXAuZGlzcGxheU1ldGFkYXRhLmNvbG9yO1xuXHRcdGdyb3VwQnRuLnN0eWxlLmJvcmRlciA9IFwibm9uZVwiO1xuXHRcdGdyb3VwQnRuLnN0eWxlLmJvcmRlclJhZGl1cyA9IFwiNTAlXCI7XG5cdFx0Z3JvdXBCdG4uc3R5bGUud2lkdGggPSBcIjIwcHhcIjtcblx0XHRncm91cEJ0bi5zdHlsZS5oZWlnaHQgPSBcIjIwcHhcIjtcblx0XHRncm91cEJ0bi5zdHlsZS5tYXJnaW5SaWdodCA9IFwiMXJlbVwiO1xuXHRcdGNvbnNvbGUubG9nKGdyb3VwKTtcblx0XHRncm91cEJ0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0YXdhaXQgbWUuZGlzcGF0Y2hQb3B1cFJlc3VsdChncm91cCk7XG5cdFx0fSk7XG5cdFx0ZG9jdW1lbnQuYm9keS5hcHBlbmQoZ3JvdXBCdG4pO1xuXHR9XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-popup-window-multiple-results/manifest.fin.json b/dev/john/update-logging-example/use-popup-window-multiple-results/manifest.fin.json new file mode 100644 index 00000000..ec04afe9 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-multiple-results/manifest.fin.json @@ -0,0 +1,35 @@ +{ + "licenseKey": "openfin-demo-license-key", + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "how-to-use-popup-window-multiple-results", + "autoShow": true + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "stack", + "id": "no-drop-target", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "processAffinity": "ps_1", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-popup-window-multiple-results/html/app.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-popup-window-single-result/common/images/icon-blue.png b/dev/john/update-logging-example/use-popup-window-single-result/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-popup-window-single-result/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-popup-window-single-result/common/style/app.css b/dev/john/update-logging-example/use-popup-window-single-result/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-single-result/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-popup-window-single-result/favicon.ico b/dev/john/update-logging-example/use-popup-window-single-result/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-popup-window-single-result/favicon.ico differ diff --git a/dev/john/update-logging-example/use-popup-window-single-result/html/app.html b/dev/john/update-logging-example/use-popup-window-single-result/html/app.html new file mode 100644 index 00000000..fe328cbd --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-single-result/html/app.html @@ -0,0 +1,33 @@ + + + + + + + Popup Window | Single Result + + + + + +
+
+

Popup Window

+

How to use single result popup window options.

+
+
+ OpenFin +
+
+
+

+ This is an example of a popup window that will either return a single result or be dismissed based on + user interaction. +

+ + +

Result

+ +
+ + diff --git a/dev/john/update-logging-example/use-popup-window-single-result/html/popup.html b/dev/john/update-logging-example/use-popup-window-single-result/html/popup.html new file mode 100644 index 00000000..074c02d9 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-single-result/html/popup.html @@ -0,0 +1,24 @@ + + + + + + + Popup Window + + + + + +
+

Popup content

+
+ + + + + +
+
+ + diff --git a/dev/john/update-logging-example/use-popup-window-single-result/js/app.bundle.js b/dev/john/update-logging-example/use-popup-window-single-result/js/app.bundle.js new file mode 100644 index 00000000..08238008 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-single-result/js/app.bundle.js @@ -0,0 +1,74 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +document.addEventListener("DOMContentLoaded", initDom); +/** + * Initialize the DOM elements. + */ +function initDom() { + const showPopupButton = document.querySelector("#btn-show-popup"); + if (showPopupButton) { + showPopupButton.addEventListener("click", createPopupWindow); + } +} +/** + * Create the popup window from the click. + * @param event The event to handle. + */ +async function createPopupWindow(event) { + resetPopupResult(); + const { top, right, height } = event.target.getBoundingClientRect(); + const hHeight = height / 2; + const result = await fin.me.showPopupWindow({ + url: location.href.replace("app", "popup"), + x: right + 6, + y: Math.round(top + hHeight), + height: 150, + width: 300 + }); + renderPopupResult(result); +} +/** + * Display the popup result. + * @param result The result to display. + */ +function renderPopupResult(result) { + const res = document.querySelector("#popup-result"); + if (res) { + res.textContent = JSON.stringify(result, undefined, 2); + } +} +/** + * Clear the popup result. + */ +function resetPopupResult() { + const res = document.querySelector("#popup-result"); + if (res) { + res.textContent = "No result"; + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOztVQUFBO1VBQ0E7Ozs7O1dDREE7V0FDQTtXQUNBO1dBQ0EsdURBQXVELGlCQUFpQjtXQUN4RTtXQUNBLGdEQUFnRCxhQUFhO1dBQzdEOzs7Ozs7Ozs7QUNKQSxRQUFRLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFFdkQ7O0dBRUc7QUFDSCxTQUFTLE9BQU87SUFDZixNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFvQixpQkFBaUIsQ0FBQyxDQUFDO0lBQ3JGLElBQUksZUFBZSxFQUFFLENBQUM7UUFDckIsZUFBZSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO0lBQzlELENBQUM7QUFDRixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsS0FBSyxVQUFVLGlCQUFpQixDQUFDLEtBQWlCO0lBQ2pELGdCQUFnQixFQUFFLENBQUM7SUFDbkIsTUFBTSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQzNCLEtBQUssQ0FBQyxNQUNOLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUMxQixNQUFNLE9BQU8sR0FBRyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQzNCLE1BQU0sTUFBTSxHQUFHLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUM7UUFDM0MsR0FBRyxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUM7UUFDMUMsQ0FBQyxFQUFFLEtBQUssR0FBRyxDQUFDO1FBQ1osQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLE9BQU8sQ0FBQztRQUM1QixNQUFNLEVBQUUsR0FBRztRQUNYLEtBQUssRUFBRSxHQUFHO0tBQ1YsQ0FBQyxDQUFDO0lBQ0gsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDM0IsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsaUJBQWlCLENBQUMsTUFBMkI7SUFDckQsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUNwRCxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ1QsR0FBRyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDeEQsQ0FBQztBQUNGLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsZ0JBQWdCO0lBQ3hCLE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDcEQsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNULEdBQUcsQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBQy9CLENBQUM7QUFDRixDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vdXNlLXBvcHVwLXdpbmRvdy1zaW5nbGUtcmVzdWx0L3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctc2luZ2xlLXJlc3VsdC93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctc2luZ2xlLXJlc3VsdC8uL2NsaWVudC9zcmMvYXBwLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSByZXF1aXJlIHNjb3BlXG52YXIgX193ZWJwYWNrX3JlcXVpcmVfXyA9IHt9O1xuXG4iLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgdHlwZSBPcGVuRmluIGZyb20gXCJAb3BlbmZpbi9jb3JlXCI7XG5cbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJET01Db250ZW50TG9hZGVkXCIsIGluaXREb20pO1xuXG4vKipcbiAqIEluaXRpYWxpemUgdGhlIERPTSBlbGVtZW50cy5cbiAqL1xuZnVuY3Rpb24gaW5pdERvbSgpOiB2b2lkIHtcblx0Y29uc3Qgc2hvd1BvcHVwQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MQnV0dG9uRWxlbWVudD4oXCIjYnRuLXNob3ctcG9wdXBcIik7XG5cdGlmIChzaG93UG9wdXBCdXR0b24pIHtcblx0XHRzaG93UG9wdXBCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGNyZWF0ZVBvcHVwV2luZG93KTtcblx0fVxufVxuXG4vKipcbiAqIENyZWF0ZSB0aGUgcG9wdXAgd2luZG93IGZyb20gdGhlIGNsaWNrLlxuICogQHBhcmFtIGV2ZW50IFRoZSBldmVudCB0byBoYW5kbGUuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVBvcHVwV2luZG93KGV2ZW50OiBNb3VzZUV2ZW50KTogUHJvbWlzZTx2b2lkPiB7XG5cdHJlc2V0UG9wdXBSZXN1bHQoKTtcblx0Y29uc3QgeyB0b3AsIHJpZ2h0LCBoZWlnaHQgfTogeyB0b3A6IG51bWJlcjsgcmlnaHQ6IG51bWJlcjsgaGVpZ2h0OiBudW1iZXIgfSA9IChcblx0XHRldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnRcblx0KS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0Y29uc3QgaEhlaWdodCA9IGhlaWdodCAvIDI7XG5cdGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbi5tZS5zaG93UG9wdXBXaW5kb3coe1xuXHRcdHVybDogbG9jYXRpb24uaHJlZi5yZXBsYWNlKFwiYXBwXCIsIFwicG9wdXBcIiksXG5cdFx0eDogcmlnaHQgKyA2LFxuXHRcdHk6IE1hdGgucm91bmQodG9wICsgaEhlaWdodCksXG5cdFx0aGVpZ2h0OiAxNTAsXG5cdFx0d2lkdGg6IDMwMFxuXHR9KTtcblx0cmVuZGVyUG9wdXBSZXN1bHQocmVzdWx0KTtcbn1cblxuLyoqXG4gKiBEaXNwbGF5IHRoZSBwb3B1cCByZXN1bHQuXG4gKiBAcGFyYW0gcmVzdWx0IFRoZSByZXN1bHQgdG8gZGlzcGxheS5cbiAqL1xuZnVuY3Rpb24gcmVuZGVyUG9wdXBSZXN1bHQocmVzdWx0OiBPcGVuRmluLlBvcHVwUmVzdWx0KTogdm9pZCB7XG5cdGNvbnN0IHJlcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjcG9wdXAtcmVzdWx0XCIpO1xuXHRpZiAocmVzKSB7XG5cdFx0cmVzLnRleHRDb250ZW50ID0gSlNPTi5zdHJpbmdpZnkocmVzdWx0LCB1bmRlZmluZWQsIDIpO1xuXHR9XG59XG5cbi8qKlxuICogQ2xlYXIgdGhlIHBvcHVwIHJlc3VsdC5cbiAqL1xuZnVuY3Rpb24gcmVzZXRQb3B1cFJlc3VsdCgpOiB2b2lkIHtcblx0Y29uc3QgcmVzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNwb3B1cC1yZXN1bHRcIik7XG5cdGlmIChyZXMpIHtcblx0XHRyZXMudGV4dENvbnRlbnQgPSBcIk5vIHJlc3VsdFwiO1xuXHR9XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-popup-window-single-result/js/popup.bundle.js b/dev/john/update-logging-example/use-popup-window-single-result/js/popup.bundle.js new file mode 100644 index 00000000..eb938866 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-single-result/js/popup.bundle.js @@ -0,0 +1,53 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!*****************************!*\ + !*** ./client/src/popup.ts ***! + \*****************************/ +__webpack_require__.r(__webpack_exports__); +const me = fin.me; +document.addEventListener("DOMContentLoaded", initDom); +/** + * Initialize the DOM elements. + */ +function initDom() { + const okButton = document.querySelector("#btn-ok"); + const confirmButton = document.querySelector("#btn-confirm"); + const cancelButton = document.querySelector("#btn-cancel"); + if (okButton) { + okButton.addEventListener("click", async () => { + await me.dispatchPopupResult("ok"); + }); + } + if (confirmButton) { + confirmButton.addEventListener("click", async () => { + await me.dispatchPopupResult("confirm"); + }); + } + if (cancelButton) { + cancelButton.addEventListener("click", async () => { + await me.dispatchPopupResult("cancel"); + }); + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9wdXAuYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7O1VBQUE7VUFDQTs7Ozs7V0NEQTtXQUNBO1dBQ0E7V0FDQSx1REFBdUQsaUJBQWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0Q7Ozs7Ozs7OztBQ0pBLE1BQU0sRUFBRSxHQUFHLEdBQUcsQ0FBQyxFQUFvQixDQUFDO0FBRXBDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxPQUFPLENBQUMsQ0FBQztBQUV2RDs7R0FFRztBQUNILFNBQVMsT0FBTztJQUNmLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbkQsTUFBTSxhQUFhLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUM3RCxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBRTNELElBQUksUUFBUSxFQUFFLENBQUM7UUFDZCxRQUFRLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQzdDLE1BQU0sRUFBRSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3BDLENBQUMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVELElBQUksYUFBYSxFQUFFLENBQUM7UUFDbkIsYUFBYSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxLQUFLLElBQUksRUFBRTtZQUNsRCxNQUFNLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN6QyxDQUFDLENBQUMsQ0FBQztJQUNKLENBQUM7SUFFRCxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ2xCLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDakQsTUFBTSxFQUFFLENBQUMsbUJBQW1CLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDeEMsQ0FBQyxDQUFDLENBQUM7SUFDSixDQUFDO0FBQ0YsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL3VzZS1wb3B1cC13aW5kb3ctc2luZ2xlLXJlc3VsdC93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly91c2UtcG9wdXAtd2luZG93LXNpbmdsZS1yZXN1bHQvd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly91c2UtcG9wdXAtd2luZG93LXNpbmdsZS1yZXN1bHQvLi9jbGllbnQvc3JjL3BvcHVwLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSByZXF1aXJlIHNjb3BlXG52YXIgX193ZWJwYWNrX3JlcXVpcmVfXyA9IHt9O1xuXG4iLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgdHlwZSBPcGVuRmluIGZyb20gXCJAb3BlbmZpbi9jb3JlXCI7XG5cbmNvbnN0IG1lID0gZmluLm1lIGFzIE9wZW5GaW4uV2luZG93O1xuXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiRE9NQ29udGVudExvYWRlZFwiLCBpbml0RG9tKTtcblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSBET00gZWxlbWVudHMuXG4gKi9cbmZ1bmN0aW9uIGluaXREb20oKTogdm9pZCB7XG5cdGNvbnN0IG9rQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNidG4tb2tcIik7XG5cdGNvbnN0IGNvbmZpcm1CdXR0b24gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2J0bi1jb25maXJtXCIpO1xuXHRjb25zdCBjYW5jZWxCdXR0b24gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2J0bi1jYW5jZWxcIik7XG5cblx0aWYgKG9rQnV0dG9uKSB7XG5cdFx0b2tCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGFzeW5jICgpID0+IHtcblx0XHRcdGF3YWl0IG1lLmRpc3BhdGNoUG9wdXBSZXN1bHQoXCJva1wiKTtcblx0XHR9KTtcblx0fVxuXG5cdGlmIChjb25maXJtQnV0dG9uKSB7XG5cdFx0Y29uZmlybUJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0YXdhaXQgbWUuZGlzcGF0Y2hQb3B1cFJlc3VsdChcImNvbmZpcm1cIik7XG5cdFx0fSk7XG5cdH1cblxuXHRpZiAoY2FuY2VsQnV0dG9uKSB7XG5cdFx0Y2FuY2VsQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCBtZS5kaXNwYXRjaFBvcHVwUmVzdWx0KFwiY2FuY2VsXCIpO1xuXHRcdH0pO1xuXHR9XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-popup-window-single-result/manifest.fin.json b/dev/john/update-logging-example/use-popup-window-single-result/manifest.fin.json new file mode 100644 index 00000000..d587b3a8 --- /dev/null +++ b/dev/john/update-logging-example/use-popup-window-single-result/manifest.fin.json @@ -0,0 +1,35 @@ +{ + "licenseKey": "openfin-demo-license-key", + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "how-to-use-popup-window-single-result", + "autoShow": true + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "stack", + "id": "no-drop-target", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "processAffinity": "ps_1", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-popup-window-single-result/html/app.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-preloads-basic/common/images/icon-blue.png b/dev/john/update-logging-example/use-preloads-basic/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-preloads-basic/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-preloads-basic/common/style/app.css b/dev/john/update-logging-example/use-preloads-basic/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-preloads-basic/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-preloads-basic/favicon.ico b/dev/john/update-logging-example/use-preloads-basic/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-preloads-basic/favicon.ico differ diff --git a/dev/john/update-logging-example/use-preloads-basic/html/app.html b/dev/john/update-logging-example/use-preloads-basic/html/app.html new file mode 100644 index 00000000..3351673a --- /dev/null +++ b/dev/john/update-logging-example/use-preloads-basic/html/app.html @@ -0,0 +1,54 @@ + + + + + + + Preload | Basic + + + + + +
+
+

Issue Commands To a Platform

+

Use the channel API to send command to a platform.

+
+
+ OpenFin +
+
+
+

+ This is a basic example showing how a preload script can be injected into the three parts of a + platform application: +

+
    +
  • The view (this page)
  • +
  • The Window (the window containing this view)
  • +
  • The platform provider (The background hidden window loaded as part of a platform)
  • +
+ The preload scripts are called: +
    +
  • client/src/preload-view.ts
  • +
  • client/src/preload-window.ts
  • +
  • client/src/preload-platform.ts
  • +
+

+ The scripts are loaded individually into each part as defined in the manifest file: + `public/manifest.fin.json` (look for the preload definition). The scripts simply ensure they are not + executing within an iframe and then they log that they have run. This is a placeholder for you to add + your logic. +

+

+ The buttons below allow you to launch the developer tools for each part so that you can see the + console.log messages for yourself. Please note you will not see the preload scripts in the source tab + of the developer tools. +

+ + + +
+ + diff --git a/dev/john/update-logging-example/use-preloads-basic/js/app.bundle.js b/dev/john/update-logging-example/use-preloads-basic/js/app.bundle.js new file mode 100644 index 00000000..f945fb3b --- /dev/null +++ b/dev/john/update-logging-example/use-preloads-basic/js/app.bundle.js @@ -0,0 +1,74 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ + +document.addEventListener("DOMContentLoaded", async () => { + try { + await initDom(); + } + catch (error) { + console.error(error); + } +}); +/** + * Initialize the DOM elements. + */ +async function initDom() { + const showPlatformDevToolsButton = document.querySelector("#platform-devtools"); + const showWindowDevToolsButton = document.querySelector("#window-devtools"); + const showViewDevToolsButton = document.querySelector("#view-devtools"); + if (showPlatformDevToolsButton) { + showPlatformDevToolsButton.addEventListener("click", showPlatformDevTools); + } + if (showWindowDevToolsButton) { + showWindowDevToolsButton.addEventListener("click", showWindowDevTools); + } + if (showViewDevToolsButton) { + showViewDevToolsButton.addEventListener("click", showViewDevTools); + } +} +/** + * Show the developer tools for the platform. + */ +async function showPlatformDevTools() { + try { + const identity = fin.me.identity; + const platformIdentity = { uuid: identity.uuid, name: identity.uuid }; + await fin.System.showDeveloperTools(platformIdentity); + } + catch (error) { + console.error("Error showing platform developer tools:", error); + } +} +/** + * Show the develop tools for the window. + */ +async function showWindowDevTools() { + try { + const identity = fin.me.identity; + const view = fin.View.wrapSync(identity); + const hostWindow = await view.getCurrentWindow(); + await fin.System.showDeveloperTools(hostWindow.identity); + } + catch (error) { + console.error("Error showing window developer tools:", error); + } +} +/** + * Show the developer tools for the view. + */ +async function showViewDevTools() { + try { + const identity = fin.me.identity; + await fin.System.showDeveloperTools(identity); + } + catch (error) { + console.error("Error showing view developer tools:", error); + } +} + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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WyJ3ZWJwYWNrOi8vdXNlLXByZWxvYWRzLWhlbGxvLXdvcmxkLy4vY2xpZW50L3NyYy9hcHAudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgYXN5bmMgKCkgPT4ge1xuXHR0cnkge1xuXHRcdGF3YWl0IGluaXREb20oKTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTtcblx0fVxufSk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgRE9NIGVsZW1lbnRzLlxuICovXG5hc3luYyBmdW5jdGlvbiBpbml0RG9tKCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBzaG93UGxhdGZvcm1EZXZUb29sc0J1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjcGxhdGZvcm0tZGV2dG9vbHNcIik7XG5cdGNvbnN0IHNob3dXaW5kb3dEZXZUb29sc0J1dHRvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjd2luZG93LWRldnRvb2xzXCIpO1xuXHRjb25zdCBzaG93Vmlld0RldlRvb2xzQnV0dG9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiN2aWV3LWRldnRvb2xzXCIpO1xuXG5cdGlmIChzaG93UGxhdGZvcm1EZXZUb29sc0J1dHRvbikge1xuXHRcdHNob3dQbGF0Zm9ybURldlRvb2xzQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBzaG93UGxhdGZvcm1EZXZUb29scyk7XG5cdH1cblx0aWYgKHNob3dXaW5kb3dEZXZUb29sc0J1dHRvbikge1xuXHRcdHNob3dXaW5kb3dEZXZUb29sc0J1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgc2hvd1dpbmRvd0RldlRvb2xzKTtcblx0fVxuXHRpZiAoc2hvd1ZpZXdEZXZUb29sc0J1dHRvbikge1xuXHRcdHNob3dWaWV3RGV2VG9vbHNCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHNob3dWaWV3RGV2VG9vbHMpO1xuXHR9XG59XG5cbi8qKlxuICogU2hvdyB0aGUgZGV2ZWxvcGVyIHRvb2xzIGZvciB0aGUgcGxhdGZvcm0uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHNob3dQbGF0Zm9ybURldlRvb2xzKCk6IFByb21pc2U8dm9pZD4ge1xuXHR0cnkge1xuXHRcdGNvbnN0IGlkZW50aXR5ID0gZmluLm1lLmlkZW50aXR5O1xuXHRcdGNvbnN0IHBsYXRmb3JtSWRlbnRpdHkgPSB7IHV1aWQ6IGlkZW50aXR5LnV1aWQsIG5hbWU6IGlkZW50aXR5LnV1aWQgfTtcblx0XHRhd2FpdCBmaW4uU3lzdGVtLnNob3dEZXZlbG9wZXJUb29scyhwbGF0Zm9ybUlkZW50aXR5KTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKFwiRXJyb3Igc2hvd2luZyBwbGF0Zm9ybSBkZXZlbG9wZXIgdG9vbHM6XCIsIGVycm9yKTtcblx0fVxufVxuXG4vKipcbiAqIFNob3cgdGhlIGRldmVsb3AgdG9vbHMgZm9yIHRoZSB3aW5kb3cuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHNob3dXaW5kb3dEZXZUb29scygpOiBQcm9taXNlPHZvaWQ+IHtcblx0dHJ5IHtcblx0XHRjb25zdCBpZGVudGl0eSA9IGZpbi5tZS5pZGVudGl0eTtcblx0XHRjb25zdCB2aWV3ID0gZmluLlZpZXcud3JhcFN5bmMoaWRlbnRpdHkpO1xuXHRcdGNvbnN0IGhvc3RXaW5kb3cgPSBhd2FpdCB2aWV3LmdldEN1cnJlbnRXaW5kb3coKTtcblx0XHRhd2FpdCBmaW4uU3lzdGVtLnNob3dEZXZlbG9wZXJUb29scyhob3N0V2luZG93LmlkZW50aXR5KTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKFwiRXJyb3Igc2hvd2luZyB3aW5kb3cgZGV2ZWxvcGVyIHRvb2xzOlwiLCBlcnJvcik7XG5cdH1cbn1cblxuLyoqXG4gKiBTaG93IHRoZSBkZXZlbG9wZXIgdG9vbHMgZm9yIHRoZSB2aWV3LlxuICovXG5hc3luYyBmdW5jdGlvbiBzaG93Vmlld0RldlRvb2xzKCk6IFByb21pc2U8dm9pZD4ge1xuXHR0cnkge1xuXHRcdGNvbnN0IGlkZW50aXR5ID0gZmluLm1lLmlkZW50aXR5O1xuXHRcdGF3YWl0IGZpbi5TeXN0ZW0uc2hvd0RldmVsb3BlclRvb2xzKGlkZW50aXR5KTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKFwiRXJyb3Igc2hvd2luZyB2aWV3IGRldmVsb3BlciB0b29sczpcIiwgZXJyb3IpO1xuXHR9XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-preloads-basic/js/preload-platform.bundle.js b/dev/john/update-logging-example/use-preloads-basic/js/preload-platform.bundle.js new file mode 100644 index 00000000..06d0e00d --- /dev/null +++ b/dev/john/update-logging-example/use-preloads-basic/js/preload-platform.bundle.js @@ -0,0 +1,27 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/*!****************************************!*\ + !*** ./client/src/preload-platform.ts ***! + \****************************************/ + +if (window !== window.top) { + console.log("We don't want to load execute when running in an iframe."); +} +else if (document.readyState === "complete") { + initPlatformPreload(); +} +else { + window.addEventListener("load", () => { + initPlatformPreload(); + }); +} +/** + * Initialize the platform preload. + */ +function initPlatformPreload() { + console.log("Platform preload loaded."); +} + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlbG9hZC1wbGF0Zm9ybS5idW5kbGUuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsSUFBSSxNQUFNLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQzNCLE9BQU8sQ0FBQyxHQUFHLENBQUMsMERBQTBELENBQUMsQ0FBQztBQUN6RSxDQUFDO0tBQU0sSUFBSSxRQUFRLENBQUMsVUFBVSxLQUFLLFVBQVUsRUFBRSxDQUFDO0lBQy9DLG1CQUFtQixFQUFFLENBQUM7QUFDdkIsQ0FBQztLQUFNLENBQUM7SUFDUCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRTtRQUNwQyxtQkFBbUIsRUFBRSxDQUFDO0lBQ3ZCLENBQUMsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxtQkFBbUI7SUFDM0IsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO0FBQ3pDLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly91c2UtcHJlbG9hZHMtaGVsbG8td29ybGQvLi9jbGllbnQvc3JjL3ByZWxvYWQtcGxhdGZvcm0udHMiXSwic291cmNlc0NvbnRlbnQiOlsiaWYgKHdpbmRvdyAhPT0gd2luZG93LnRvcCkge1xuXHRjb25zb2xlLmxvZyhcIldlIGRvbid0IHdhbnQgdG8gbG9hZCBleGVjdXRlIHdoZW4gcnVubmluZyBpbiBhbiBpZnJhbWUuXCIpO1xufSBlbHNlIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSBcImNvbXBsZXRlXCIpIHtcblx0aW5pdFBsYXRmb3JtUHJlbG9hZCgpO1xufSBlbHNlIHtcblx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJsb2FkXCIsICgpID0+IHtcblx0XHRpbml0UGxhdGZvcm1QcmVsb2FkKCk7XG5cdH0pO1xufVxuXG4vKipcbiAqIEluaXRpYWxpemUgdGhlIHBsYXRmb3JtIHByZWxvYWQuXG4gKi9cbmZ1bmN0aW9uIGluaXRQbGF0Zm9ybVByZWxvYWQoKTogdm9pZCB7XG5cdGNvbnNvbGUubG9nKFwiUGxhdGZvcm0gcHJlbG9hZCBsb2FkZWQuXCIpO1xufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/dev/john/update-logging-example/use-preloads-basic/js/preload-view.bundle.js b/dev/john/update-logging-example/use-preloads-basic/js/preload-view.bundle.js new file mode 100644 index 00000000..e885bdc8 --- /dev/null +++ b/dev/john/update-logging-example/use-preloads-basic/js/preload-view.bundle.js @@ -0,0 +1,27 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/*!************************************!*\ + !*** ./client/src/preload-view.ts ***! + \************************************/ + +if (window !== window.top) { + console.log("We don't want to load execute when running in an iframe."); +} +else if (document.readyState === "complete") { + initViewPreload().catch(() => { }); +} +else { + window.addEventListener("load", async () => { + await initViewPreload(); + }); +} +/** + * Initialize the view preload. + */ +async function initViewPreload() { + console.log("View preload loaded."); +} + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlbG9hZC12aWV3LmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxJQUFJLE1BQU0sS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDM0IsT0FBTyxDQUFDLEdBQUcsQ0FBQywwREFBMEQsQ0FBQyxDQUFDO0FBQ3pFLENBQUM7S0FBTSxJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssVUFBVSxFQUFFLENBQUM7SUFDL0MsZUFBZSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ25DLENBQUM7S0FBTSxDQUFDO0lBQ1AsTUFBTSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxLQUFLLElBQUksRUFBRTtRQUMxQyxNQUFNLGVBQWUsRUFBRSxDQUFDO0lBQ3pCLENBQUMsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsS0FBSyxVQUFVLGVBQWU7SUFDN0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0FBQ3JDLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly91c2UtcHJlbG9hZHMtaGVsbG8td29ybGQvLi9jbGllbnQvc3JjL3ByZWxvYWQtdmlldy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpZiAod2luZG93ICE9PSB3aW5kb3cudG9wKSB7XG5cdGNvbnNvbGUubG9nKFwiV2UgZG9uJ3Qgd2FudCB0byBsb2FkIGV4ZWN1dGUgd2hlbiBydW5uaW5nIGluIGFuIGlmcmFtZS5cIik7XG59IGVsc2UgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09IFwiY29tcGxldGVcIikge1xuXHRpbml0Vmlld1ByZWxvYWQoKS5jYXRjaCgoKSA9PiB7fSk7XG59IGVsc2Uge1xuXHR3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcImxvYWRcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdGF3YWl0IGluaXRWaWV3UHJlbG9hZCgpO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSB2aWV3IHByZWxvYWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGluaXRWaWV3UHJlbG9hZCgpOiBQcm9taXNlPHZvaWQ+IHtcblx0Y29uc29sZS5sb2coXCJWaWV3IHByZWxvYWQgbG9hZGVkLlwiKTtcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-preloads-basic/js/preload-window.bundle.js b/dev/john/update-logging-example/use-preloads-basic/js/preload-window.bundle.js new file mode 100644 index 00000000..a67b0a8b --- /dev/null +++ b/dev/john/update-logging-example/use-preloads-basic/js/preload-window.bundle.js @@ -0,0 +1,27 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/*!**************************************!*\ + !*** ./client/src/preload-window.ts ***! + \**************************************/ + +if (window !== window.top) { + console.log("We don't want to load execute when running in an iframe."); +} +else if (document.readyState === "complete") { + initWindowPreload(); +} +else { + window.addEventListener("load", () => { + initWindowPreload(); + }); +} +/** + * Initialize the window preload. + */ +function initWindowPreload() { + console.log("Window preload loaded."); +} + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlbG9hZC13aW5kb3cuYnVuZGxlLmpzIiwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLElBQUksTUFBTSxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUMzQixPQUFPLENBQUMsR0FBRyxDQUFDLDBEQUEwRCxDQUFDLENBQUM7QUFDekUsQ0FBQztLQUFNLElBQUksUUFBUSxDQUFDLFVBQVUsS0FBSyxVQUFVLEVBQUUsQ0FBQztJQUMvQyxpQkFBaUIsRUFBRSxDQUFDO0FBQ3JCLENBQUM7S0FBTSxDQUFDO0lBQ1AsTUFBTSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUU7UUFDcEMsaUJBQWlCLEVBQUUsQ0FBQztJQUNyQixDQUFDLENBQUMsQ0FBQztBQUNKLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsaUJBQWlCO0lBQ3pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsd0JBQXdCLENBQUMsQ0FBQztBQUN2QyxDQUFDIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vdXNlLXByZWxvYWRzLWhlbGxvLXdvcmxkLy4vY2xpZW50L3NyYy9wcmVsb2FkLXdpbmRvdy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpZiAod2luZG93ICE9PSB3aW5kb3cudG9wKSB7XG5cdGNvbnNvbGUubG9nKFwiV2UgZG9uJ3Qgd2FudCB0byBsb2FkIGV4ZWN1dGUgd2hlbiBydW5uaW5nIGluIGFuIGlmcmFtZS5cIik7XG59IGVsc2UgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09IFwiY29tcGxldGVcIikge1xuXHRpbml0V2luZG93UHJlbG9hZCgpO1xufSBlbHNlIHtcblx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJsb2FkXCIsICgpID0+IHtcblx0XHRpbml0V2luZG93UHJlbG9hZCgpO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSB3aW5kb3cgcHJlbG9hZC5cbiAqL1xuZnVuY3Rpb24gaW5pdFdpbmRvd1ByZWxvYWQoKTogdm9pZCB7XG5cdGNvbnNvbGUubG9nKFwiV2luZG93IHByZWxvYWQgbG9hZGVkLlwiKTtcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-preloads-basic/manifest.fin.json b/dev/john/update-logging-example/use-preloads-basic/manifest.fin.json new file mode 100644 index 00000000..776cfc68 --- /dev/null +++ b/dev/john/update-logging-example/use-preloads-basic/manifest.fin.json @@ -0,0 +1,54 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "how-to-use-preloads-hello-world", + "autoShow": true, + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-preloads-basic/favicon.ico", + "preloadScripts": [ + { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-preloads-basic/js/preload-platform.bundle.js" + } + ], + "defaultWindowOptions": { + "preloadScripts": [ + { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-preloads-basic/js/preload-window.bundle.js" + } + ] + }, + "defaultViewOptions": { + "preloadScripts": [ + { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-preloads-basic/js/preload-view.bundle.js" + } + ] + } + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "stack", + "id": "no-drop-target", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "processAffinity": "ps_1", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-preloads-basic/html/app.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-preloads-restart-on-refresh/common/images/icon-blue.png b/dev/john/update-logging-example/use-preloads-restart-on-refresh/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-preloads-restart-on-refresh/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-preloads-restart-on-refresh/common/style/app.css b/dev/john/update-logging-example/use-preloads-restart-on-refresh/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-preloads-restart-on-refresh/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-preloads-restart-on-refresh/favicon.ico b/dev/john/update-logging-example/use-preloads-restart-on-refresh/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-preloads-restart-on-refresh/favicon.ico differ diff --git a/dev/john/update-logging-example/use-preloads-restart-on-refresh/js/preload-view.bundle.js b/dev/john/update-logging-example/use-preloads-restart-on-refresh/js/preload-view.bundle.js new file mode 100644 index 00000000..64f33327 --- /dev/null +++ b/dev/john/update-logging-example/use-preloads-restart-on-refresh/js/preload-view.bundle.js @@ -0,0 +1,53 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/*!************************************!*\ + !*** ./client/src/preload-view.ts ***! + \************************************/ + +if (window !== window.top) { + console.log("We don't want to load execute when running in an iframe."); +} +else if (document.readyState === "complete") { + // eslint-disable-next-line no-void + void initViewPreload(); +} +else { + window.addEventListener("load", async () => { + await initViewPreload(); + }); +} +/** + * Initialize the view preload. + */ +async function initViewPreload() { + console.log("View preload loaded."); + const navigationEntries = performance.getEntriesByType("navigation"); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (navigationEntries.length > 0 && navigationEntries[0].type === "reload") { + console.log("Navigation Entries from Performance API Indicate that this page has been reloaded."); + console.log("This example is a use case that was was asked for. Can I restart and navigate to the originally loaded url in a view when a user reloads the page?"); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const fin = window.fin; + if (fin !== undefined) { + const viewOptions = await fin.me.getOptions(); + console.log("View Options:", viewOptions); + if (location.href !== viewOptions.url) { + console.log(`Current url: ${location.href} does not match the defined view url: ${viewOptions.url} navigating to the original url on refresh.`); + location.href = viewOptions.url; + } + else { + console.log("Reload was detected on the originally loaded url. Performing no actions."); + } + } + else { + console.error("This is a preload script so should only ever be loaded into an OpenFin container"); + } + } + else { + console.log(`First load of: ${location.href}`); + } +} + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlbG9hZC12aWV3LmJ1bmRsZS5qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxJQUFJLE1BQU0sS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDM0IsT0FBTyxDQUFDLEdBQUcsQ0FBQywwREFBMEQsQ0FBQyxDQUFDO0FBQ3pFLENBQUM7S0FBTSxJQUFJLFFBQVEsQ0FBQyxVQUFVLEtBQUssVUFBVSxFQUFFLENBQUM7SUFDL0MsbUNBQW1DO0lBQ25DLEtBQUssZUFBZSxFQUFFLENBQUM7QUFDeEIsQ0FBQztLQUFNLENBQUM7SUFDUCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQzFDLE1BQU0sZUFBZSxFQUFFLENBQUM7SUFDekIsQ0FBQyxDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsZUFBZTtJQUM3QixPQUFPLENBQUMsR0FBRyxDQUFDLHNCQUFzQixDQUFDLENBQUM7SUFDcEMsTUFBTSxpQkFBaUIsR0FBRyxXQUFXLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDckUsOERBQThEO0lBQzlELElBQUksaUJBQWlCLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSyxpQkFBaUIsQ0FBQyxDQUFDLENBQVMsQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDckYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvRkFBb0YsQ0FBQyxDQUFDO1FBQ2xHLE9BQU8sQ0FBQyxHQUFHLENBQ1Ysb0pBQW9KLENBQ3BKLENBQUM7UUFDRiw4REFBOEQ7UUFDOUQsTUFBTSxHQUFHLEdBQUksTUFBYyxDQUFDLEdBQUcsQ0FBQztRQUNoQyxJQUFJLEdBQUcsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN2QixNQUFNLFdBQVcsR0FBRyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDOUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDMUMsSUFBSSxRQUFRLENBQUMsSUFBSSxLQUFLLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDdkMsT0FBTyxDQUFDLEdBQUcsQ0FDVixnQkFBZ0IsUUFBUSxDQUFDLElBQUkseUNBQXlDLFdBQVcsQ0FBQyxHQUFHLDZDQUE2QyxDQUNsSSxDQUFDO2dCQUNGLFFBQVEsQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQztZQUNqQyxDQUFDO2lCQUFNLENBQUM7Z0JBQ1AsT0FBTyxDQUFDLEdBQUcsQ0FBQywwRUFBMEUsQ0FBQyxDQUFDO1lBQ3pGLENBQUM7UUFDRixDQUFDO2FBQU0sQ0FBQztZQUNQLE9BQU8sQ0FBQyxLQUFLLENBQUMsa0ZBQWtGLENBQUMsQ0FBQztRQUNuRyxDQUFDO0lBQ0YsQ0FBQztTQUFNLENBQUM7UUFDUCxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNoRCxDQUFDO0FBQ0YsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL3VzZS1wcmVsb2Fkcy1yZXN0YXJ0LW9uLXJlZnJlc2gvLi9jbGllbnQvc3JjL3ByZWxvYWQtdmlldy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpZiAod2luZG93ICE9PSB3aW5kb3cudG9wKSB7XG5cdGNvbnNvbGUubG9nKFwiV2UgZG9uJ3Qgd2FudCB0byBsb2FkIGV4ZWN1dGUgd2hlbiBydW5uaW5nIGluIGFuIGlmcmFtZS5cIik7XG59IGVsc2UgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09IFwiY29tcGxldGVcIikge1xuXHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdm9pZFxuXHR2b2lkIGluaXRWaWV3UHJlbG9hZCgpO1xufSBlbHNlIHtcblx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJsb2FkXCIsIGFzeW5jICgpID0+IHtcblx0XHRhd2FpdCBpbml0Vmlld1ByZWxvYWQoKTtcblx0fSk7XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgdmlldyBwcmVsb2FkLlxuICovXG5hc3luYyBmdW5jdGlvbiBpbml0Vmlld1ByZWxvYWQoKTogUHJvbWlzZTx2b2lkPiB7XG5cdGNvbnNvbGUubG9nKFwiVmlldyBwcmVsb2FkIGxvYWRlZC5cIik7XG5cdGNvbnN0IG5hdmlnYXRpb25FbnRyaWVzID0gcGVyZm9ybWFuY2UuZ2V0RW50cmllc0J5VHlwZShcIm5hdmlnYXRpb25cIik7XG5cdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG5cdGlmIChuYXZpZ2F0aW9uRW50cmllcy5sZW5ndGggPiAwICYmIChuYXZpZ2F0aW9uRW50cmllc1swXSBhcyBhbnkpLnR5cGUgPT09IFwicmVsb2FkXCIpIHtcblx0XHRjb25zb2xlLmxvZyhcIk5hdmlnYXRpb24gRW50cmllcyBmcm9tIFBlcmZvcm1hbmNlIEFQSSBJbmRpY2F0ZSB0aGF0IHRoaXMgcGFnZSBoYXMgYmVlbiByZWxvYWRlZC5cIik7XG5cdFx0Y29uc29sZS5sb2coXG5cdFx0XHRcIlRoaXMgZXhhbXBsZSBpcyBhIHVzZSBjYXNlIHRoYXQgd2FzIHdhcyBhc2tlZCBmb3IuIENhbiBJIHJlc3RhcnQgYW5kIG5hdmlnYXRlIHRvIHRoZSBvcmlnaW5hbGx5IGxvYWRlZCB1cmwgaW4gYSB2aWV3IHdoZW4gYSB1c2VyIHJlbG9hZHMgdGhlIHBhZ2U/XCJcblx0XHQpO1xuXHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG5cdFx0Y29uc3QgZmluID0gKHdpbmRvdyBhcyBhbnkpLmZpbjtcblx0XHRpZiAoZmluICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdGNvbnN0IHZpZXdPcHRpb25zID0gYXdhaXQgZmluLm1lLmdldE9wdGlvbnMoKTtcblx0XHRcdGNvbnNvbGUubG9nKFwiVmlldyBPcHRpb25zOlwiLCB2aWV3T3B0aW9ucyk7XG5cdFx0XHRpZiAobG9jYXRpb24uaHJlZiAhPT0gdmlld09wdGlvbnMudXJsKSB7XG5cdFx0XHRcdGNvbnNvbGUubG9nKFxuXHRcdFx0XHRcdGBDdXJyZW50IHVybDogJHtsb2NhdGlvbi5ocmVmfSBkb2VzIG5vdCBtYXRjaCB0aGUgZGVmaW5lZCB2aWV3IHVybDogJHt2aWV3T3B0aW9ucy51cmx9IG5hdmlnYXRpbmcgdG8gdGhlIG9yaWdpbmFsIHVybCBvbiByZWZyZXNoLmBcblx0XHRcdFx0KTtcblx0XHRcdFx0bG9jYXRpb24uaHJlZiA9IHZpZXdPcHRpb25zLnVybDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNvbnNvbGUubG9nKFwiUmVsb2FkIHdhcyBkZXRlY3RlZCBvbiB0aGUgb3JpZ2luYWxseSBsb2FkZWQgdXJsLiBQZXJmb3JtaW5nIG5vIGFjdGlvbnMuXCIpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zb2xlLmVycm9yKFwiVGhpcyBpcyBhIHByZWxvYWQgc2NyaXB0IHNvIHNob3VsZCBvbmx5IGV2ZXIgYmUgbG9hZGVkIGludG8gYW4gT3BlbkZpbiBjb250YWluZXJcIik7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdGNvbnNvbGUubG9nKGBGaXJzdCBsb2FkIG9mOiAke2xvY2F0aW9uLmhyZWZ9YCk7XG5cdH1cbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-preloads-restart-on-refresh/manifest.fin.json b/dev/john/update-logging-example/use-preloads-restart-on-refresh/manifest.fin.json new file mode 100644 index 00000000..90864791 --- /dev/null +++ b/dev/john/update-logging-example/use-preloads-restart-on-refresh/manifest.fin.json @@ -0,0 +1,42 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "platform": { + "uuid": "how-to-use-preloads-restart-on-refresh", + "autoShow": false, + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-preloads-restart-on-refresh/favicon.ico", + "defaultViewOptions": { + "preloadScripts": [ + { + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-preloads-restart-on-refresh/js/preload-view.bundle.js" + } + ] + } + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "stack", + "id": "no-drop-target", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "processAffinity": "ps_1", + "url": "https://www.google.com/search?q=openfin+preload+scripts" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-security-realms/app.fin.json b/dev/john/update-logging-example/use-security-realms/app.fin.json new file mode 100644 index 00000000..c3eed38d --- /dev/null +++ b/dev/john/update-logging-example/use-security-realms/app.fin.json @@ -0,0 +1,19 @@ +{ + "licenseKey": "64605fac-add3-48a0-8710-64b38e96a2dd", + "runtime": { + "version": "38.126.83.79", + "arguments": "--v=1 --security-realm=PROD-MAIN" + }, + "shortcut": { + "company": "OpenFin", + "description": "PROD Main Application", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-security-realms/favicon.ico", + "name": "PROD Main Application" + }, + "startup_app": { + "name": "prod-main-application", + "uuid": "prod-main-application", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-security-realms/html/app.html", + "autoShow": true + } +} diff --git a/dev/john/update-logging-example/use-security-realms/assets/UseSecurityRealms.zip b/dev/john/update-logging-example/use-security-realms/assets/UseSecurityRealms.zip new file mode 100644 index 00000000..fce7c865 Binary files /dev/null and b/dev/john/update-logging-example/use-security-realms/assets/UseSecurityRealms.zip differ diff --git a/dev/john/update-logging-example/use-security-realms/common/images/icon-blue.png b/dev/john/update-logging-example/use-security-realms/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-security-realms/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-security-realms/common/style/app.css b/dev/john/update-logging-example/use-security-realms/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-security-realms/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-security-realms/favicon.ico b/dev/john/update-logging-example/use-security-realms/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-security-realms/favicon.ico differ diff --git a/dev/john/update-logging-example/use-security-realms/html/app.html b/dev/john/update-logging-example/use-security-realms/html/app.html new file mode 100644 index 00000000..1e27f630 --- /dev/null +++ b/dev/john/update-logging-example/use-security-realms/html/app.html @@ -0,0 +1,47 @@ + + + + + + + Security Realm Example + + + + + +
+
+

Security Realm Example

+

+ Security Realm Name: + +

+
+
+ OpenFin +
+
+
+
+

Security Realms

+
+ + +
+

+
+ + +
+
+ +
+
+
+

Logging

+

+			
+
+ + diff --git a/dev/john/update-logging-example/use-security-realms/html/view-app.html b/dev/john/update-logging-example/use-security-realms/html/view-app.html new file mode 100644 index 00000000..b4671642 --- /dev/null +++ b/dev/john/update-logging-example/use-security-realms/html/view-app.html @@ -0,0 +1,54 @@ + + + + + + + Security Realm Example + + + + + +
+
+

Security Realm Example

+

+ Security Realm Name: + +

+
+
+ OpenFin +
+
+
+
+

Security Realms

+
+ + +
+
+

Launch a new application in the same security realm

+ +
+
+

Launch a new application in a different security realm

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

Logging

+

+			
+
+ + diff --git a/dev/john/update-logging-example/use-security-realms/js/app.bundle.js b/dev/john/update-logging-example/use-security-realms/js/app.bundle.js new file mode 100644 index 00000000..de176198 --- /dev/null +++ b/dev/john/update-logging-example/use-security-realms/js/app.bundle.js @@ -0,0 +1,145 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +const topic = "/openfin/sample/security-realm-example"; +document.addEventListener("DOMContentLoaded", async () => { + try { + await init(); + } + catch (error) { + console.error(error); + } +}); +/** + * Initialize the DOM elements. + */ +async function init() { + const securityRealm = await getSecurityRealmInfo(); + if (securityRealm === "UAT-MAIN") { + const summary = document.querySelector("#summary"); + if (summary) { + summary.textContent = + "This UAT instance of the application will automatically launch a .net console application that is tied to the UAT security realm and will not receive messages from the PROD realm."; + } + const id = await launchNativeApp(); + console.log(id); + } + await setupSendButton(securityRealm ?? ""); + await listenToTopicAndLogMessages(securityRealm ?? ""); +} +/** + * Get the security realm info. + * @returns The security realm if it is set. + */ +async function getSecurityRealmInfo() { + try { + const runtimeInfo = await fin.System.getRuntimeInfo(); + const securityRealmName = document.querySelector("#security-realm-name"); + if (securityRealmName) { + if (runtimeInfo.securityRealm) { + securityRealmName.innerHTML += runtimeInfo.securityRealm; + return runtimeInfo.securityRealm; + } + securityRealmName.innerHTML += "No Security Realm Present"; + } + } + catch (error) { + console.error("Error getting runtime info:", error); + } +} +/** + * Setup the send button. + * @param realm The realm to use. + */ +async function setupSendButton(realm) { + const sendMessageBtn = document.querySelector("#send-message"); + if (sendMessageBtn) { + sendMessageBtn.addEventListener("click", async (e) => { + e.preventDefault(); + const iabMessage = document.querySelector("#iab-message"); + if (iabMessage) { + const messageText = iabMessage.value; + await publishMessageToTopic(messageText, realm); + } + }); + } +} +/** + * Publish a message to the topic. + * @param messageText The message text. + * @param realm The realm to send the message to. + */ +async function publishMessageToTopic(messageText, realm) { + try { + await fin.InterApplicationBus.publish(topic, { + id: fin.me.identity, + message: messageText, + realmName: realm + }); + } + catch { + // eslint-disable-next-line no-alert + alert(`Can not send message to topic: ${topic} in realm ${realm}`); + } +} +/** + * Listen for messages and log the results. + * @param realm The realm to listen on. + */ +async function listenToTopicAndLogMessages(realm) { + try { + const messageLog = document.querySelector("#message-log"); + if (messageLog) { + await fin.InterApplicationBus.subscribe({ uuid: "*" }, topic, (payload) => { + messageLog.innerHTML += `Received message from app with identity of {uuid: ${payload.id.uuid}}\n\nRealm Name: ${payload.realmName}\nMessage: ${payload.message}`; + }); + } + } + catch (error) { + if (error) { + // eslint-disable-next-line no-alert + alert(`Can not receive message from topic: ${topic} on realm ${realm}`); + } + } +} +/** + * Launch a native app. + * @returns The application identity. + */ +async function launchNativeApp() { + const nativeApp = await fin.System.launchExternalProcess({ + alias: "security-realms-native", + listener: async (result) => { + console.log("result", result); + if (result.exitCode === 1) { + console.log("Native App Has Exited"); + } + } + }); + return nativeApp; +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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LENBQUM7UUFDeEQsS0FBSyxFQUFFLHdCQUF3QjtRQUMvQixRQUFRLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQzFCLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzlCLElBQUksTUFBTSxDQUFDLFFBQVEsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDM0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1lBQ3RDLENBQUM7UUFDRixDQUFDO0tBQ0QsQ0FBQyxDQUFDO0lBRUgsT0FBTyxTQUFTLENBQUM7QUFDbEIsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL3VzZS1zZWN1cml0eS1yZWFsbXMvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vdXNlLXNlY3VyaXR5LXJlYWxtcy93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3VzZS1zZWN1cml0eS1yZWFsbXMvLi9jbGllbnQvc3JjL2FwcC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGUgcmVxdWlyZSBzY29wZVxudmFyIF9fd2VicGFja19yZXF1aXJlX18gPSB7fTtcblxuIiwiLy8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuX193ZWJwYWNrX3JlcXVpcmVfXy5yID0gKGV4cG9ydHMpID0+IHtcblx0aWYodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnRvU3RyaW5nVGFnKSB7XG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG5cdH1cblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbn07IiwiaW1wb3J0IHR5cGUgT3BlbkZpbiBmcm9tIFwiQG9wZW5maW4vY29yZVwiO1xuXG5jb25zdCB0b3BpYyA9IFwiL29wZW5maW4vc2FtcGxlL3NlY3VyaXR5LXJlYWxtLWV4YW1wbGVcIjtcblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgYXN5bmMgKCkgPT4ge1xuXHR0cnkge1xuXHRcdGF3YWl0IGluaXQoKTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTtcblx0fVxufSk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgRE9NIGVsZW1lbnRzLlxuICovXG5hc3luYyBmdW5jdGlvbiBpbml0KCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBzZWN1cml0eVJlYWxtID0gYXdhaXQgZ2V0U2VjdXJpdHlSZWFsbUluZm8oKTtcblx0aWYgKHNlY3VyaXR5UmVhbG0gPT09IFwiVUFULU1BSU5cIikge1xuXHRcdGNvbnN0IHN1bW1hcnkgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3N1bW1hcnlcIik7XG5cdFx0aWYgKHN1bW1hcnkpIHtcblx0XHRcdHN1bW1hcnkudGV4dENvbnRlbnQgPVxuXHRcdFx0XHRcIlRoaXMgVUFUIGluc3RhbmNlIG9mIHRoZSBhcHBsaWNhdGlvbiB3aWxsIGF1dG9tYXRpY2FsbHkgbGF1bmNoIGEgLm5ldCBjb25zb2xlIGFwcGxpY2F0aW9uIHRoYXQgaXMgdGllZCB0byB0aGUgVUFUIHNlY3VyaXR5IHJlYWxtIGFuZCB3aWxsIG5vdCByZWNlaXZlIG1lc3NhZ2VzIGZyb20gdGhlIFBST0QgcmVhbG0uXCI7XG5cdFx0fVxuXHRcdGNvbnN0IGlkID0gYXdhaXQgbGF1bmNoTmF0aXZlQXBwKCk7XG5cdFx0Y29uc29sZS5sb2coaWQpO1xuXHR9XG5cdGF3YWl0IHNldHVwU2VuZEJ1dHRvbihzZWN1cml0eVJlYWxtID8/IFwiXCIpO1xuXHRhd2FpdCBsaXN0ZW5Ub1RvcGljQW5kTG9nTWVzc2FnZXMoc2VjdXJpdHlSZWFsbSA/PyBcIlwiKTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIHNlY3VyaXR5IHJlYWxtIGluZm8uXG4gKiBAcmV0dXJucyBUaGUgc2VjdXJpdHkgcmVhbG0gaWYgaXQgaXMgc2V0LlxuICovXG5hc3luYyBmdW5jdGlvbiBnZXRTZWN1cml0eVJlYWxtSW5mbygpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuXHR0cnkge1xuXHRcdGNvbnN0IHJ1bnRpbWVJbmZvOiBPcGVuRmluLlJ1bnRpbWVJbmZvID0gYXdhaXQgZmluLlN5c3RlbS5nZXRSdW50aW1lSW5mbygpO1xuXHRcdGNvbnN0IHNlY3VyaXR5UmVhbG1OYW1lID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNzZWN1cml0eS1yZWFsbS1uYW1lXCIpO1xuXHRcdGlmIChzZWN1cml0eVJlYWxtTmFtZSkge1xuXHRcdFx0aWYgKHJ1bnRpbWVJbmZvLnNlY3VyaXR5UmVhbG0pIHtcblx0XHRcdFx0c2VjdXJpdHlSZWFsbU5hbWUuaW5uZXJIVE1MICs9IHJ1bnRpbWVJbmZvLnNlY3VyaXR5UmVhbG07XG5cdFx0XHRcdHJldHVybiBydW50aW1lSW5mby5zZWN1cml0eVJlYWxtO1xuXHRcdFx0fVxuXHRcdFx0c2VjdXJpdHlSZWFsbU5hbWUuaW5uZXJIVE1MICs9IFwiTm8gU2VjdXJpdHkgUmVhbG0gUHJlc2VudFwiO1xuXHRcdH1cblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKFwiRXJyb3IgZ2V0dGluZyBydW50aW1lIGluZm86XCIsIGVycm9yKTtcblx0fVxufVxuXG4vKipcbiAqIFNldHVwIHRoZSBzZW5kIGJ1dHRvbi5cbiAqIEBwYXJhbSByZWFsbSBUaGUgcmVhbG0gdG8gdXNlLlxuICovXG5hc3luYyBmdW5jdGlvbiBzZXR1cFNlbmRCdXR0b24ocmVhbG06IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBzZW5kTWVzc2FnZUJ0biA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjc2VuZC1tZXNzYWdlXCIpO1xuXHRpZiAoc2VuZE1lc3NhZ2VCdG4pIHtcblx0XHRzZW5kTWVzc2FnZUJ0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKGUpID0+IHtcblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdGNvbnN0IGlhYk1lc3NhZ2UgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxUZXh0QXJlYUVsZW1lbnQ+KFwiI2lhYi1tZXNzYWdlXCIpO1xuXHRcdFx0aWYgKGlhYk1lc3NhZ2UpIHtcblx0XHRcdFx0Y29uc3QgbWVzc2FnZVRleHQ6IHN0cmluZyA9IGlhYk1lc3NhZ2UudmFsdWU7XG5cdFx0XHRcdGF3YWl0IHB1Ymxpc2hNZXNzYWdlVG9Ub3BpYyhtZXNzYWdlVGV4dCwgcmVhbG0pO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG59XG5cbi8qKlxuICogUHVibGlzaCBhIG1lc3NhZ2UgdG8gdGhlIHRvcGljLlxuICogQHBhcmFtIG1lc3NhZ2VUZXh0IFRoZSBtZXNzYWdlIHRleHQuXG4gKiBAcGFyYW0gcmVhbG0gVGhlIHJlYWxtIHRvIHNlbmQgdGhlIG1lc3NhZ2UgdG8uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHB1Ymxpc2hNZXNzYWdlVG9Ub3BpYyhtZXNzYWdlVGV4dDogc3RyaW5nLCByZWFsbTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG5cdHRyeSB7XG5cdFx0YXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMucHVibGlzaCh0b3BpYywge1xuXHRcdFx0aWQ6IGZpbi5tZS5pZGVudGl0eSxcblx0XHRcdG1lc3NhZ2U6IG1lc3NhZ2VUZXh0LFxuXHRcdFx0cmVhbG1OYW1lOiByZWFsbVxuXHRcdH0pO1xuXHR9IGNhdGNoIHtcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYWxlcnRcblx0XHRhbGVydChgQ2FuIG5vdCBzZW5kIG1lc3NhZ2UgdG8gdG9waWM6ICR7dG9waWN9IGluIHJlYWxtICR7cmVhbG19YCk7XG5cdH1cbn1cblxuLyoqXG4gKiBMaXN0ZW4gZm9yIG1lc3NhZ2VzIGFuZCBsb2cgdGhlIHJlc3VsdHMuXG4gKiBAcGFyYW0gcmVhbG0gVGhlIHJlYWxtIHRvIGxpc3RlbiBvbi5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbGlzdGVuVG9Ub3BpY0FuZExvZ01lc3NhZ2VzKHJlYWxtOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcblx0dHJ5IHtcblx0XHRjb25zdCBtZXNzYWdlTG9nID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNtZXNzYWdlLWxvZ1wiKTtcblx0XHRpZiAobWVzc2FnZUxvZykge1xuXHRcdFx0YXdhaXQgZmluLkludGVyQXBwbGljYXRpb25CdXMuc3Vic2NyaWJlKFxuXHRcdFx0XHR7IHV1aWQ6IFwiKlwiIH0sXG5cdFx0XHRcdHRvcGljLFxuXHRcdFx0XHQocGF5bG9hZDogeyBpZDogeyB1dWlkOiBzdHJpbmcgfTsgbWVzc2FnZTogc3RyaW5nOyByZWFsbU5hbWU6IHN0cmluZyB9KSA9PiB7XG5cdFx0XHRcdFx0bWVzc2FnZUxvZy5pbm5lckhUTUwgKz0gYFJlY2VpdmVkIG1lc3NhZ2UgZnJvbSBhcHAgd2l0aCBpZGVudGl0eSBvZiB7dXVpZDogJHtwYXlsb2FkLmlkLnV1aWR9fVxcblxcblJlYWxtIE5hbWU6ICR7cGF5bG9hZC5yZWFsbU5hbWV9XFxuTWVzc2FnZTogJHtwYXlsb2FkLm1lc3NhZ2V9YDtcblx0XHRcdFx0fVxuXHRcdFx0KTtcblx0XHR9XG5cdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0aWYgKGVycm9yKSB7XG5cdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYWxlcnRcblx0XHRcdGFsZXJ0KGBDYW4gbm90IHJlY2VpdmUgbWVzc2FnZSBmcm9tIHRvcGljOiAke3RvcGljfSBvbiByZWFsbSAke3JlYWxtfWApO1xuXHRcdH1cblx0fVxufVxuXG4vKipcbiAqIExhdW5jaCBhIG5hdGl2ZSBhcHAuXG4gKiBAcmV0dXJucyBUaGUgYXBwbGljYXRpb24gaWRlbnRpdHkuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGxhdW5jaE5hdGl2ZUFwcCgpOiBQcm9taXNlPE9wZW5GaW4uQXBwbGljYXRpb25JZGVudGl0eT4ge1xuXHRjb25zdCBuYXRpdmVBcHAgPSBhd2FpdCBmaW4uU3lzdGVtLmxhdW5jaEV4dGVybmFsUHJvY2Vzcyh7XG5cdFx0YWxpYXM6IFwic2VjdXJpdHktcmVhbG1zLW5hdGl2ZVwiLFxuXHRcdGxpc3RlbmVyOiBhc3luYyAocmVzdWx0KSA9PiB7XG5cdFx0XHRjb25zb2xlLmxvZyhcInJlc3VsdFwiLCByZXN1bHQpO1xuXHRcdFx0aWYgKHJlc3VsdC5leGl0Q29kZSA9PT0gMSkge1xuXHRcdFx0XHRjb25zb2xlLmxvZyhcIk5hdGl2ZSBBcHAgSGFzIEV4aXRlZFwiKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xuXG5cdHJldHVybiBuYXRpdmVBcHA7XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/dev/john/update-logging-example/use-security-realms/js/view-app.bundle.js b/dev/john/update-logging-example/use-security-realms/js/view-app.bundle.js new file mode 100644 index 00000000..ddaec48b --- /dev/null +++ b/dev/john/update-logging-example/use-security-realms/js/view-app.bundle.js @@ -0,0 +1,159 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!********************************!*\ + !*** ./client/src/view-app.ts ***! + \********************************/ +__webpack_require__.r(__webpack_exports__); +document.addEventListener("DOMContentLoaded", async () => { + try { + await initDom(); + } + catch (error) { + console.error(error); + } +}); +const topic = "/openfin/sample/security-realm-example"; +const rootPath = location.href.replace("/html/view-app.html", "/"); +/** + * Initialize the DOM elements. + */ +async function initDom() { + const securityRealm = await getSecurityRealmInfo(); + await listenToTopicAndLogMessages(securityRealm ?? ""); + await setupSendButton(securityRealm ?? ""); + const launchAppBtn = document.querySelector("#launch-app-btn"); + if (launchAppBtn) { + launchAppBtn.addEventListener("click", async () => { + await launchProd(); + }); + } + const launchNewRealmBtn = document.querySelector("#launch-outofrealm-btn"); + if (launchNewRealmBtn) { + launchNewRealmBtn.addEventListener("click", async () => { + await launchUat(); + }); + } +} +/** + * Get the security realm. + * @returns The realm if it is set. + */ +async function getSecurityRealmInfo() { + try { + const runtimeInfo = await fin.System.getRuntimeInfo(); + const securityRealmName = document.querySelector("#security-realm-name"); + if (securityRealmName) { + if (runtimeInfo.securityRealm) { + securityRealmName.innerHTML += runtimeInfo.securityRealm; + return runtimeInfo.securityRealm; + } + securityRealmName.innerHTML += "No Security Realm Present"; + } + } + catch (error) { + console.error("Error getting runtime info:", error); + } +} +/** + * Launch the production app. + * @returns The application. + */ +async function launchProd() { + const app = await fin.Application.startFromManifest(`${rootPath}app.fin.json`); + return app; +} +/** + * Launch the uat app. + * @returns The application. + */ +async function launchUat() { + try { + const app = await fin.Application.startFromManifest(`${rootPath}uat/app.fin.json`); + return app; + } + catch (error) { + console.error("Error starting application", error); + } +} +/** + * Setup the send button. + * @param realm The realm. + */ +async function setupSendButton(realm) { + try { + const sendMessageBtn = document.querySelector("#send-message"); + if (sendMessageBtn) { + sendMessageBtn.addEventListener("click", async (e) => { + e.preventDefault(); + const iabMessage = document.querySelector("#iab-message"); + if (iabMessage) { + const messageText = iabMessage.value; + await publishMessageToTopic(messageText, realm); + } + }); + } + } + catch (error) { + console.error("Error sending IAB message", error); + } +} +/** + * Publish a message to the topic. + * @param messageText The message text. + * @param realm The realm to send the message to. + */ +async function publishMessageToTopic(messageText, realm) { + try { + await fin.InterApplicationBus.publish(topic, { + id: fin.me.identity, + message: messageText, + realmName: realm + }); + } + catch { + // eslint-disable-next-line no-alert + alert(`Can not publish message to topic: ${topic} in realm ${realm}`); + } +} +/** + * Listen for messages and log the results. + * @param realm The realm to listen on. + */ +async function listenToTopicAndLogMessages(realm) { + try { + const messageLog = document.querySelector("#message-log"); + if (messageLog) { + await fin.InterApplicationBus.subscribe({ uuid: "*" }, topic, (payload) => { + messageLog.innerHTML += `Received message from app with identity of {uuid: ${payload.id.uuid}}\n\nRealm Name: ${payload.realmName}\nMessage: ${payload.message}\n\n`; + }); + } + } + catch (error) { + if (error) { + // eslint-disable-next-line no-alert + alert(`Can not receive message from topic: ${topic} to realm ${realm}`); + } + } +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUM7SUFDSixDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1Isb0NBQW9DO1FBQ3BDLEtBQUssQ0FBQyxxQ0FBcUMsS0FBSyxhQUFhLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDdkUsQ0FBQztBQUNGLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxLQUFLLFVBQVUsMkJBQTJCLENBQUMsS0FBYTtJQUN2RCxJQUFJLENBQUM7UUFDSixNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQzFELElBQUksVUFBVSxFQUFFLENBQUM7WUFDaEIsTUFBTSxHQUFHLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUN0QyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsRUFDYixLQUFLLEVBQ0wsQ0FBQyxPQUFxRSxFQUFFLEVBQUU7Z0JBQ3pFLFVBQVUsQ0FBQyxTQUFTLElBQUkscURBQXFELE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxvQkFBb0IsT0FBTyxDQUFDLFNBQVMsY0FBYyxPQUFPLENBQUMsT0FBTyxNQUFNLENBQUM7WUFDdEssQ0FBQyxDQUNELENBQUM7UUFDSCxDQUFDO0lBQ0YsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDaEIsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNYLG9DQUFvQztZQUNwQyxLQUFLLENBQUMsdUNBQXVDLEtBQUssYUFBYSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3pFLENBQUM7SUFDRixDQUFDO0FBQ0YsQ0FBQyIsInNvdXJjZXMiOlsid2VicGFjazovL3VzZS1zZWN1cml0eS1yZWFsbXMvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vdXNlLXNlY3VyaXR5LXJlYWxtcy93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL3VzZS1zZWN1cml0eS1yZWFsbXMvLi9jbGllbnQvc3JjL3ZpZXctYXBwLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSByZXF1aXJlIHNjb3BlXG52YXIgX193ZWJwYWNrX3JlcXVpcmVfXyA9IHt9O1xuXG4iLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgdHlwZSBPcGVuRmluIGZyb20gXCJAb3BlbmZpbi9jb3JlXCI7XG5cbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJET01Db250ZW50TG9hZGVkXCIsIGFzeW5jICgpID0+IHtcblx0dHJ5IHtcblx0XHRhd2FpdCBpbml0RG9tKCk7XG5cdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0Y29uc29sZS5lcnJvcihlcnJvcik7XG5cdH1cbn0pO1xuXG5jb25zdCB0b3BpYyA9IFwiL29wZW5maW4vc2FtcGxlL3NlY3VyaXR5LXJlYWxtLWV4YW1wbGVcIjtcbmNvbnN0IHJvb3RQYXRoID0gbG9jYXRpb24uaHJlZi5yZXBsYWNlKFwiL2h0bWwvdmlldy1hcHAuaHRtbFwiLCBcIi9cIik7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgRE9NIGVsZW1lbnRzLlxuICovXG5hc3luYyBmdW5jdGlvbiBpbml0RG9tKCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBzZWN1cml0eVJlYWxtID0gYXdhaXQgZ2V0U2VjdXJpdHlSZWFsbUluZm8oKTtcblx0YXdhaXQgbGlzdGVuVG9Ub3BpY0FuZExvZ01lc3NhZ2VzKHNlY3VyaXR5UmVhbG0gPz8gXCJcIik7XG5cdGF3YWl0IHNldHVwU2VuZEJ1dHRvbihzZWN1cml0eVJlYWxtID8/IFwiXCIpO1xuXHRjb25zdCBsYXVuY2hBcHBCdG4gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2xhdW5jaC1hcHAtYnRuXCIpO1xuXHRpZiAobGF1bmNoQXBwQnRuKSB7XG5cdFx0bGF1bmNoQXBwQnRuLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCBsYXVuY2hQcm9kKCk7XG5cdFx0fSk7XG5cdH1cblxuXHRjb25zdCBsYXVuY2hOZXdSZWFsbUJ0biA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjbGF1bmNoLW91dG9mcmVhbG0tYnRuXCIpO1xuXHRpZiAobGF1bmNoTmV3UmVhbG1CdG4pIHtcblx0XHRsYXVuY2hOZXdSZWFsbUJ0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0YXdhaXQgbGF1bmNoVWF0KCk7XG5cdFx0fSk7XG5cdH1cbn1cblxuLyoqXG4gKiBHZXQgdGhlIHNlY3VyaXR5IHJlYWxtLlxuICogQHJldHVybnMgVGhlIHJlYWxtIGlmIGl0IGlzIHNldC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZ2V0U2VjdXJpdHlSZWFsbUluZm8oKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcblx0dHJ5IHtcblx0XHRjb25zdCBydW50aW1lSW5mbzogT3BlbkZpbi5SdW50aW1lSW5mbyA9IGF3YWl0IGZpbi5TeXN0ZW0uZ2V0UnVudGltZUluZm8oKTtcblx0XHRjb25zdCBzZWN1cml0eVJlYWxtTmFtZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjc2VjdXJpdHktcmVhbG0tbmFtZVwiKTtcblx0XHRpZiAoc2VjdXJpdHlSZWFsbU5hbWUpIHtcblx0XHRcdGlmIChydW50aW1lSW5mby5zZWN1cml0eVJlYWxtKSB7XG5cdFx0XHRcdHNlY3VyaXR5UmVhbG1OYW1lLmlubmVySFRNTCArPSBydW50aW1lSW5mby5zZWN1cml0eVJlYWxtO1xuXHRcdFx0XHRyZXR1cm4gcnVudGltZUluZm8uc2VjdXJpdHlSZWFsbTtcblx0XHRcdH1cblx0XHRcdHNlY3VyaXR5UmVhbG1OYW1lLmlubmVySFRNTCArPSBcIk5vIFNlY3VyaXR5IFJlYWxtIFByZXNlbnRcIjtcblx0XHR9XG5cdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0Y29uc29sZS5lcnJvcihcIkVycm9yIGdldHRpbmcgcnVudGltZSBpbmZvOlwiLCBlcnJvcik7XG5cdH1cbn1cblxuLyoqXG4gKiBMYXVuY2ggdGhlIHByb2R1Y3Rpb24gYXBwLlxuICogQHJldHVybnMgVGhlIGFwcGxpY2F0aW9uLlxuICovXG5hc3luYyBmdW5jdGlvbiBsYXVuY2hQcm9kKCk6IFByb21pc2U8T3BlbkZpbi5BcHBsaWNhdGlvbj4ge1xuXHRjb25zdCBhcHAgPSBhd2FpdCBmaW4uQXBwbGljYXRpb24uc3RhcnRGcm9tTWFuaWZlc3QoYCR7cm9vdFBhdGh9YXBwLmZpbi5qc29uYCk7XG5cdHJldHVybiBhcHA7XG59XG5cbi8qKlxuICogTGF1bmNoIHRoZSB1YXQgYXBwLlxuICogQHJldHVybnMgVGhlIGFwcGxpY2F0aW9uLlxuICovXG5hc3luYyBmdW5jdGlvbiBsYXVuY2hVYXQoKTogUHJvbWlzZTxPcGVuRmluLkFwcGxpY2F0aW9uIHwgdW5kZWZpbmVkPiB7XG5cdHRyeSB7XG5cdFx0Y29uc3QgYXBwID0gYXdhaXQgZmluLkFwcGxpY2F0aW9uLnN0YXJ0RnJvbU1hbmlmZXN0KGAke3Jvb3RQYXRofXVhdC9hcHAuZmluLmpzb25gKTtcblx0XHRyZXR1cm4gYXBwO1xuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoXCJFcnJvciBzdGFydGluZyBhcHBsaWNhdGlvblwiLCBlcnJvcik7XG5cdH1cbn1cblxuLyoqXG4gKiBTZXR1cCB0aGUgc2VuZCBidXR0b24uXG4gKiBAcGFyYW0gcmVhbG0gVGhlIHJlYWxtLlxuICovXG5hc3luYyBmdW5jdGlvbiBzZXR1cFNlbmRCdXR0b24ocmVhbG06IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHR0cnkge1xuXHRcdGNvbnN0IHNlbmRNZXNzYWdlQnRuID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNzZW5kLW1lc3NhZ2VcIik7XG5cdFx0aWYgKHNlbmRNZXNzYWdlQnRuKSB7XG5cdFx0XHRzZW5kTWVzc2FnZUJ0bi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKGUpID0+IHtcblx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRjb25zdCBpYWJNZXNzYWdlID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MSW5wdXRFbGVtZW50PihcIiNpYWItbWVzc2FnZVwiKTtcblx0XHRcdFx0aWYgKGlhYk1lc3NhZ2UpIHtcblx0XHRcdFx0XHRjb25zdCBtZXNzYWdlVGV4dDogc3RyaW5nID0gaWFiTWVzc2FnZS52YWx1ZTtcblx0XHRcdFx0XHRhd2FpdCBwdWJsaXNoTWVzc2FnZVRvVG9waWMobWVzc2FnZVRleHQsIHJlYWxtKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdGNvbnNvbGUuZXJyb3IoXCJFcnJvciBzZW5kaW5nIElBQiBtZXNzYWdlXCIsIGVycm9yKTtcblx0fVxufVxuXG4vKipcbiAqIFB1Ymxpc2ggYSBtZXNzYWdlIHRvIHRoZSB0b3BpYy5cbiAqIEBwYXJhbSBtZXNzYWdlVGV4dCBUaGUgbWVzc2FnZSB0ZXh0LlxuICogQHBhcmFtIHJlYWxtIFRoZSByZWFsbSB0byBzZW5kIHRoZSBtZXNzYWdlIHRvLlxuICovXG5hc3luYyBmdW5jdGlvbiBwdWJsaXNoTWVzc2FnZVRvVG9waWMobWVzc2FnZVRleHQ6IHN0cmluZywgcmVhbG06IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHR0cnkge1xuXHRcdGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLnB1Ymxpc2godG9waWMsIHtcblx0XHRcdGlkOiBmaW4ubWUuaWRlbnRpdHksXG5cdFx0XHRtZXNzYWdlOiBtZXNzYWdlVGV4dCxcblx0XHRcdHJlYWxtTmFtZTogcmVhbG1cblx0XHR9KTtcblx0fSBjYXRjaCB7XG5cdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWFsZXJ0XG5cdFx0YWxlcnQoYENhbiBub3QgcHVibGlzaCBtZXNzYWdlIHRvIHRvcGljOiAke3RvcGljfSBpbiByZWFsbSAke3JlYWxtfWApO1xuXHR9XG59XG5cbi8qKlxuICogTGlzdGVuIGZvciBtZXNzYWdlcyBhbmQgbG9nIHRoZSByZXN1bHRzLlxuICogQHBhcmFtIHJlYWxtIFRoZSByZWFsbSB0byBsaXN0ZW4gb24uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGxpc3RlblRvVG9waWNBbmRMb2dNZXNzYWdlcyhyZWFsbTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG5cdHRyeSB7XG5cdFx0Y29uc3QgbWVzc2FnZUxvZyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjbWVzc2FnZS1sb2dcIik7XG5cdFx0aWYgKG1lc3NhZ2VMb2cpIHtcblx0XHRcdGF3YWl0IGZpbi5JbnRlckFwcGxpY2F0aW9uQnVzLnN1YnNjcmliZShcblx0XHRcdFx0eyB1dWlkOiBcIipcIiB9LFxuXHRcdFx0XHR0b3BpYyxcblx0XHRcdFx0KHBheWxvYWQ6IHsgaWQ6IHsgdXVpZDogc3RyaW5nIH07IG1lc3NhZ2U6IHN0cmluZzsgcmVhbG1OYW1lOiBzdHJpbmcgfSkgPT4ge1xuXHRcdFx0XHRcdG1lc3NhZ2VMb2cuaW5uZXJIVE1MICs9IGBSZWNlaXZlZCBtZXNzYWdlIGZyb20gYXBwIHdpdGggaWRlbnRpdHkgb2Yge3V1aWQ6ICR7cGF5bG9hZC5pZC51dWlkfX1cXG5cXG5SZWFsbSBOYW1lOiAke3BheWxvYWQucmVhbG1OYW1lfVxcbk1lc3NhZ2U6ICR7cGF5bG9hZC5tZXNzYWdlfVxcblxcbmA7XG5cdFx0XHRcdH1cblx0XHRcdCk7XG5cdFx0fVxuXHR9IGNhdGNoIChlcnJvcikge1xuXHRcdGlmIChlcnJvcikge1xuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWFsZXJ0XG5cdFx0XHRhbGVydChgQ2FuIG5vdCByZWNlaXZlIG1lc3NhZ2UgZnJvbSB0b3BpYzogJHt0b3BpY30gdG8gcmVhbG0gJHtyZWFsbX1gKTtcblx0XHR9XG5cdH1cbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-security-realms/manifest.fin.json b/dev/john/update-logging-example/use-security-realms/manifest.fin.json new file mode 100644 index 00000000..084fb2c2 --- /dev/null +++ b/dev/john/update-logging-example/use-security-realms/manifest.fin.json @@ -0,0 +1,45 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect --security-realm=PROD-MAIN", + "version": "38.126.83.79" + }, + "shortcut": { + "company": "OpenFin", + "description": "PROD Main Platform", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-security-realms/favicon.ico", + "name": "PROD Main Platform" + }, + "platform": { + "uuid": "prod-main-platform", + "autoShow": false, + "permissions": { + "System": { + "launchExternalProcess": true + } + } + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "stack", + "id": "no-drop-target", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "processAffinity": "ps_1", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-security-realms/html/view-app.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-security-realms/uat/app.fin.json b/dev/john/update-logging-example/use-security-realms/uat/app.fin.json new file mode 100644 index 00000000..f2795879 --- /dev/null +++ b/dev/john/update-logging-example/use-security-realms/uat/app.fin.json @@ -0,0 +1,34 @@ +{ + "licenseKey": "64605fac-add3-48a0-8710-64b38e96a2dd", + "runtime": { + "version": "38.126.83.79", + "arguments": "--v=1 --security-realm=UAT-MAIN" + }, + "shortcut": { + "company": "OpenFin", + "description": "UAT Main Application", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-security-realms/favicon.ico", + "name": "UAT Main Application" + }, + "startup_app": { + "name": "uat-main-application", + "uuid": "uat-main-application", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-security-realms/html/app.html", + "autoShow": true, + "permissions": { + "System": { + "launchExternalProcess": true, + "downloadAsset": true + } + } + }, + "appAssets": [ + { + "src": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-security-realms/assets/UseSecurityRealms.zip", + "version": "0.0.0.1", + "alias": "security-realms-native", + "target": "UseSecurityRealms.exe", + "mandatory": true + } + ] +} diff --git a/dev/john/update-logging-example/use-security-realms/uat/manifest.fin.json b/dev/john/update-logging-example/use-security-realms/uat/manifest.fin.json new file mode 100644 index 00000000..e700539a --- /dev/null +++ b/dev/john/update-logging-example/use-security-realms/uat/manifest.fin.json @@ -0,0 +1,45 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect --security-realm=UAT-MAIN", + "version": "38.126.83.79" + }, + "shortcut": { + "company": "OpenFin", + "description": "UAT Main Platform", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-security-realms/favicon.ico", + "name": "UAT Main Platform" + }, + "platform": { + "uuid": "uat-main-platform", + "autoShow": false, + "permissions": { + "System": { + "launchExternalProcess": true + } + } + }, + "snapshot": { + "windows": [ + { + "layout": { + "content": [ + { + "type": "stack", + "id": "no-drop-target", + "content": [ + { + "type": "component", + "componentName": "view", + "componentState": { + "processAffinity": "ps_1", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-security-realms/html/app.html" + } + } + ] + } + ] + } + } + ] + } +} diff --git a/dev/john/update-logging-example/use-window-options/common/images/icon-blue.png b/dev/john/update-logging-example/use-window-options/common/images/icon-blue.png new file mode 100644 index 00000000..fc784502 Binary files /dev/null and b/dev/john/update-logging-example/use-window-options/common/images/icon-blue.png differ diff --git a/dev/john/update-logging-example/use-window-options/common/style/app.css b/dev/john/update-logging-example/use-window-options/common/style/app.css new file mode 100644 index 00000000..96c4673f --- /dev/null +++ b/dev/john/update-logging-example/use-window-options/common/style/app.css @@ -0,0 +1,929 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter&display=swap'); + +:root { + --brand-background: var(--theme-background-primary, #1e1f23); + --brand-border: var(--theme-background4, #2f3136); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #ffffff); + --brand-text-secondary: var(--theme-text-help, #c9cbd2); + --brand-input-background: var(--theme-background5, #383a40); + --brand-input-border: var(--theme-background6, #53565f); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #111214); + --brand-table-header-text: var(--theme-text-default, #ffffff); + --brand-table-row-even: var(--theme-background3, #24262b); + --brand-table-row-odd: var(--theme-background4, #2f3136); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); + + accent-color: var(--brand-primary); +} + +.theme-light { + --brand-background: var(--theme-background-primary, #fafbfe); + --brand-border: var(--theme-background4, #eceef1); + --brand-primary: var(--theme-brand-primary, #0a76d3); + --brand-text: var(--theme-text-default, #111214); + --brand-text-secondary: var(--theme-text-help, #2f3136); + --brand-input-background: var(--theme-background5, #dddfe4); + --brand-input-border: var(--theme-background6, #c9cbd2); + --brand-input-border-highlight: var(--theme-input-focused, #c9cbd2); + --brand-table-header: var(--theme-background1, #ffffff); + --brand-table-header-text: var(--theme-text-default, #111214); + --brand-table-row-even: var(--theme-background3, #eceef1); + --brand-table-row-odd: var(--theme-background4, #c9cbd2); + --brand-error: var(--theme-status-critical, #be1d1f); + --brand-success: var(--theme-status-success, #35c759); +} + +.primary { + color: var(--brand-primary); +} + +.error { + color: var(--brand-error); +} + +.success { + color: var(--brand-success); +} + +::selection { + background-color: var(--brand-primary); +} + +* { + font-family: Inter, 'Sans Serif', sans-serif; + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + display: flex; + justify-content: stretch; + align-items: stretch; + overflow: hidden; + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); +} + +body.border { + padding: 20px; + margin: 0; + background-color: var(--brand-background); + color: var(--brand-text); + border: 1px solid #000000; + border-radius: 5px; + width: 99%; + height: 99%; +} + +body.border-light { + border-color: var(--brand-input-border-highlight); +} + +body.small { + padding: 15px; +} + +h1 { + font-size: 24px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} +h1.tag { + font-size: 12px; + font-weight: normal; + margin-top: 5px; + color: var(--brand-text-secondary); +} + +h2 { + font-size: 20px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h3 { + font-size: 16px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h4 { + font-size: 14px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +h5 { + font-size: 12px; + font-weight: 700; + line-height: 1; + margin-block-start: 0; + margin-block-end: 0; +} + +p { + color: var(--brand-text-secondary); + font-size: 12px; + margin-block-start: 0; + margin-block-end: 0; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: var(--brand-input-background); + border-radius: 5px; +} +::-webkit-scrollbar-thumb { + background: var(--brand-border); + border-radius: 5px; + border: 1px solid var(--brand-input-border); +} +::-webkit-scrollbar-thumb:hover { + border: 1px solid var(--brand-input-border-highlight); +} + +main { + min-height: 100px; +} + +a { + color: var(--brand-primary); + font-size: 12px; + font-weight: bold; + outline: none; + text-decoration: none; +} + +a:hover, +a:focus { + text-decoration: underline; +} + +button, +input[type='button'], +::-webkit-file-upload-button, +a.button, +footer a { + background-color: var(--brand-primary); + border: 2px solid var(--brand-primary); + color: #ffffff; + border-radius: 5px; + padding: 8px 20px; + text-align: left; + cursor: pointer; + font-size: 12px; + font-weight: bold; + text-decoration: none; + outline: 0; + white-space: nowrap; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +a.button:hover, +footer a:hover { + text-decoration: none; +} + +a.button:focus, +a.button:hover, +input[type='button']:focus, +input[type='button']:hover, +input[type='file']:focus::-webkit-file-upload-button, +input[type='file']:hover::-webkit-file-upload-button, +::-webkit-file-upload-button:hover, +footer a:focus, +footer a:not(:disabled):hover, +button:not(:disabled):focus, +button:not(:disabled):hover { + background-image: linear-gradient(rgba(255, 255, 255, 0.1) 0 0); +} + +button.image { + width: 40px; + height: 40px; + padding: 0px; + display: flex; + align-items: center; + justify-content: center; +} +button.image > img { + width: 32px; + height: 32px; +} +button.secondary { + background-color: var(--brand-input-background); + color: var(--brand-text); + border-color: var(--brand-input-border); +} +button.secondary:not(:disabled):hover { + background-color: var(--brand-input-background); +} +button.plain { + border-color: transparent; + background-color: transparent; + color: var(--brand-primary); +} +button.plain:not(:disabled):not(:read-only):hover { + border-color: transparent; + background-color: transparent; +} + +button.small, +::-webkit-file-upload-button, +td button { + padding: 5px 10px; + font-size: 10px; +} +td button.plain { + width: auto; + height: auto; +} + +button.center { + text-align: center; +} + +::-webkit-file-upload-button { + margin-right: 10px; +} + +pre { + margin: 0; + padding: 5px; + border-radius: 5px; + font-size: 12px; + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + width: 100%; + min-height: 20px; +} + +header { + padding-bottom: 10px; + border-bottom: 2px solid var(--brand-border); +} + +footer { + padding-top: 10px; + border-top: 1px solid var(--brand-border); +} + +fieldset { + display: flex; + flex-direction: column; + align-items: flex-start; + border: 0; + padding: 0; + font-size: 12px; + gap: 5px; +} + +fieldset.row { + flex-direction: row; + align-items: center; + gap: 10px; +} + +label { + font-size: 12px; + font-weight: 600; +} + +select, +input[type='text'], +input[type='url'], +input[type='email'], +input[type='password'], +input[type='file'], +input[type='number'], +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'], +input[type='color'], +textarea { + border-radius: 5px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + font-size: 12px; + outline: 0; + color: var(--brand-text); + width: 50%; + min-width: 200px; + padding: 8px 12px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +textarea { + min-height: 64px; + resize: none; +} + +textarea.resizable { + resize: both; +} + +select.full, +input[type='text'].full, +input[type='email'].full, +input[type='url'].full, +input[type='password'].full, +input[type='file'].full, +input[type='number'].full, +input[type='date'].full, +input[type='time'].full, +input[type='datetime-local'].full, +input[type='month'].full, +input[type='week'].full, +input[type='range'].full, +textarea.full { + width: 95%; +} + +select:focus, +select:not(:disabled):hover, +input[type='text']:not(:read-only):focus, +input[type='text']:not(:disabled):not(:read-only):hover, +input[type='email']:not(:read-only):focus, +input[type='email']:not(:disabled):not(:read-only):hover, +input[type='url']:not(:read-only):focus, +input[type='url']:not(:disabled):not(:read-only):hover, +input[type='password']:not(:read-only):focus, +input[type='password']:not(:disabled):not(:read-only):hover, +input[type='file']:not(:read-only):focus, +input[type='file']:not(:disabled):not(:read-only):hover, +input[type='number']:not(:read-only):focus, +input[type='number']:not(:disabled):not(:read-only):hover, +input[type='date']:not(:read-only):focus, +input[type='date']:not(:disabled):not(:read-only):hover, +input[type='time']:not(:read-only):focus, +input[type='time']:not(:disabled):not(:read-only):hover, +input[type='datetime-local']:not(:read-only):focus, +input[type='datetime-local']:not(:disabled):not(:read-only):hover, +input[type='month']:not(:read-only):focus, +input[type='month']:not(:disabled):not(:read-only):hover, +input[type='week']:not(:read-only):focus, +input[type='week']:not(:disabled):not(:read-only):hover, +textarea:not(:read-only):focus, +textarea:not(:disabled):not(:read-only):hover, +input[type='checkbox']:focus, +input[type='checkbox']:not(:disabled):hover, +input[type='radio']:focus, +input[type='radio']:not(:disabled):hover, +input[type='color']:focus, +input[type='color']:not(:disabled):hover { + border-color: var(--brand-input-border-highlight); +} + +input[type='date'], +input[type='time'], +input[type='datetime-local'], +input[type='month'], +input[type='week'] { + width: 200px; + min-width: auto; +} + +.theme-dark ::-webkit-calendar-picker-indicator { + filter: invert(1); +} + +::-webkit-datetime-edit-day-field:focus, +::-webkit-datetime-edit-month-field:focus, +::-webkit-datetime-edit-year-field:focus, +::-webkit-datetime-edit-hour-field:focus, +::-webkit-datetime-edit-minute-field:focus, +::-webkit-datetime-edit-week-field:focus { + background-color: var(--brand-primary); + color: #ffffff; +} + +::-webkit-outer-spin-button, +::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='file'] { + padding: 4px 12px; +} + +select { + appearance: none; +} + +select:not([multiple]):not(:disabled) { + appearance: none; + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-size: 12px; + background-position: calc(100% - 12px) 12px; + background-color: var(--brand-input-background); +} + +.theme-dark select:not([multiple]):not(:disabled) { + background-image: url("data:image/svg+xml;utf8,"); +} + +option { + color: var(--brand-text); + padding: 6px; + margin-bottom: 1px; +} + +option:hover { + background: var(--brand-input-border) + linear-gradient(0deg, var(--brand-input-border) 0%, var(--brand-input-border) 100%); + border-radius: 5px; +} + +option:checked { + background: var(--brand-primary) linear-gradient(0deg, var(--brand-primary) 0%, var(--brand-primary) 100%); + color: #ffffff; + border-radius: 5px; +} + +input[type='range'] { + -webkit-appearance: none; + height: 20px; + width: 200px; + background: transparent; + outline: none; +} + +input[type='range']::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 10px; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + border-radius: 5px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; + height: 20px; + width: 20px; + border-radius: 5px; + margin-top: -6px; + border: 1px solid var(--brand-input-border); + background: var(--brand-input-background); + cursor: pointer; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='range']:hover::-webkit-slider-runnable-track, +input[type='range']:focus::-webkit-slider-runnable-track, +input[type='range']:hover::-webkit-slider-thumb, +input[type='range']:focus::-webkit-slider-thumb { + border-color: var(--brand-input-border-highlight); +} + +button:disabled, +select:disabled, +input:disabled, +textarea:disabled, +footer a:disabled, +a[disabled] { + opacity: 0.3; + cursor: default; + pointer-events: none; + resize: none; +} + +select:invalid, +input:invalid, +textarea:invalid { + border-color: var(--brand-error); +} + +fieldset > span { + margin-left: 10px; + width: 50px; +} + +input[type='text'].large, +input[type='password'].large, +input[type='file'].large, +input[type='email'].large, +input[type='url'].large, +input[type='date'].large, +input[type='time'].large { + font-size: 20px; + padding: 20px 10px; +} + +input[type='text'].center, +input[type='password'].center, +input[type='email'].center, +input[type='url'].center { + text-align: center; +} + +input[type='checkbox'], +input[type='radio'] { + appearance: none; + border: 1px solid var(--brand-input-border); + background-color: var(--brand-input-background); + color: var(--brand-input-text); + outline: 0; + width: 20px; + height: 20px; + margin: 2px; + box-shadow: rgb(0 0 0 / 25%) 0px 4px 4px; + transition-property: background-color, color, opacity; + transition-duration: 200ms; + transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); +} + +input[type='radio'] { + border-radius: 50%; +} + +input[type='checkbox']::before, +input[type='radio']::before { + content: ''; + display: none; + width: 16px; + height: 16px; + margin: 1px; + background-color: var(--brand-text); + opacity: 0.8; +} + +input[type='checkbox']:checked::before { + display: inline-block; + clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); +} +input[type='radio']:checked::before { + display: inline-block; + clip-path: circle(35% at 52% 50%); +} + +input[type='checkbox'] + label, +input[type='radio'] + label { + white-space: nowrap; +} + +input[type='color'] { + width: 100px; + min-width: auto; + padding: 5px; +} + +input[type='color']::-webkit-color-swatch-wrapper { + padding: 0; + background: transparent; +} + +input[type='color']::-webkit-color-swatch { + border-radius: 5px; + border: none; +} + +/* This disables the auto zoom on iDevices */ +@supports (-webkit-touch-callout: none) { + select, + input[type='text'], + input[type='url'], + input[type='email'], + input[type='password'], + input[type='file'], + input[type='number'], + input[type='date'], + input[type='time'], + input[type='datetime-local'], + input[type='month'], + input[type='week'], + input[type='color'], + textarea { + font-size: 16px; + } +} + +hr { + width: 100%; + border: 0; + border-bottom: 1px solid var(--brand-input-border); +} + +ul { + font-size: 12px; + display: flex; + flex-direction: column; + gap: 10px; + list-style-type: none; +} + +li { + font-size: 12px; + position: relative; + padding: 0 0 10px; +} + +li::before { + content: ' '; + display: inline-block; + background-color: var(--brand-primary); + width: 8px; + height: 8px; + border-radius: 2px; + position: absolute; + left: -13px; + top: 3px; +} + +em { + font-size: 12px; +} + +.row { + display: flex; + flex-direction: row; +} + +.col { + display: flex; + flex-direction: column; +} + +.fill { + flex: 1; +} + +.fill_2 { + flex: 2; +} + +.scroll { + overflow: auto; +} + +.scroll-vertical { + overflow-y: auto; +} + +.scroll-horizontal { + overflow-x: auto; +} + +.overflow-hidden { + overflow: hidden; +} + +.middle { + align-items: center; +} + +.bottom { + align-items: flex-end; +} + +.spread { + justify-content: space-between; +} + +.around { + justify-content: space-around; +} + +.left { + display: flex; + align-items: flex-start; +} + +.center { + display: flex; + justify-content: center; +} + +.right { + display: flex; + justify-content: flex-end; +} + +.wrap { + flex-wrap: wrap; +} + +.gap5 { + gap: 5px; +} + +.gap10 { + gap: 10px; +} + +.gap20 { + gap: 20px; +} + +.gap40 { + gap: 40px; +} + +.pad10 { + padding: 10px; +} + +.pad20 { + padding: 20px; +} + +.pad0 { + padding: 0px; +} + +.table { + display: flex; + flex: 1; + flex-direction: column; + font-size: 10px; +} + +table { + width: 100%; + font-size: 10px; + border: 0; + border-collapse: collapse; +} + +table, +.table { + border: var(--brand-input-border) 1px solid; +} + +.table-row { + display: flex; + flex: 1; + flex-direction: row; +} + +table > tr:first-child, +thead > tr, +.table-row.header { + background-color: var(--brand-table-header); +} + +table > tr:nth-child(even), +.table > div:nth-child(even), +tbody > tr:nth-child(odd) { + background-color: var(--brand-table-row-even); +} + +table > tr:nth-child(odd), +.table > div:not(:first-child):nth-child(odd), +tbody > tr:nth-child(even) { + background-color: var(--brand-table-row-odd); +} + +th, +.table-row.header > div { + color: var(--brand-table-header-text); + font-weight: bold; + padding: 10px 5px; + text-align: left; + word-break: break-word; +} + +.table-row > div { + flex: 1; +} + +td, +.table-row:not(.header) > div { + padding: 5px; + word-break: break-word; + color: var(--brand-text); +} + +.table-row:not(.header) > div { + display: flex; + align-items: center; +} + +@media screen and (max-width: 736px) { + .table-row { + flex-direction: column; + } + + .table-row.header { + display: none; + } + + .table-row:not(.header) > div { + display: flex; + align-items: center; + flex: 1; + gap: 10px; + } + + .table-row:not(.header) > div:before { + content: attr(data-name); + font-weight: bold; + white-space: nowrap; + width: 20%; + } + + .table-row > div.right { + justify-content: flex-start; + } + + .table-row > div.center { + justify-content: flex-start; + } +} + +.border { + border: 1px solid var(--brand-input-border); + border-radius: 5px; +} + +.drag { + user-select: none; + -webkit-app-region: drag; +} + +.no-drag { + -webkit-app-region: none; +} + +.form { + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; + font-size: 12px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 10px; + background-color: var(--brand-table-header); + border: var(--brand-input-border) 1px solid; + border-radius: 5px; + padding: 10px; +} + +.form-group.large { + gap: 20px; +} + +.width-full { + width: 100%; +} + +.max-width-full { + max-width: 100%; +} + +.width-responsive { + max-width: fit-content; +} + +.hidden { + display: none; +} + +.pointer { + cursor: pointer; +} + +.nowrap { + white-space: nowrap; +} diff --git a/dev/john/update-logging-example/use-window-options/favicon.ico b/dev/john/update-logging-example/use-window-options/favicon.ico new file mode 100644 index 00000000..0b6e09e6 Binary files /dev/null and b/dev/john/update-logging-example/use-window-options/favicon.ico differ diff --git a/dev/john/update-logging-example/use-window-options/html/app.html b/dev/john/update-logging-example/use-window-options/html/app.html new file mode 100644 index 00000000..197060a2 --- /dev/null +++ b/dev/john/update-logging-example/use-window-options/html/app.html @@ -0,0 +1,253 @@ + + + + + Window Options Builder + + + + + + + +
+
+

Window Options Builder

+

Demonstrate the customization options available for opening windows.

+
+
+ OpenFin +
+
+
+
+
+
+
+

Common

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+ +
+ + +
+
+
+
+ +
+ + +
+
+ Only used during content load +
+
+ + +
+
+ +
+

Frameless

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

Preview

+

+				
+
+
+
+
+
+ + + + +
+ +
+
+ + diff --git a/dev/john/update-logging-example/use-window-options/html/preview.html b/dev/john/update-logging-example/use-window-options/html/preview.html new file mode 100644 index 00000000..67f812ab --- /dev/null +++ b/dev/john/update-logging-example/use-window-options/html/preview.html @@ -0,0 +1,128 @@ + + + + + Window Options Preview + + + + + + +
+
+

Window Options Preview

+

Demonstrate customized window.

+
+
+ OpenFin +
+
+
+

+
+ + +
+
+ + +
+
+ + + diff --git a/dev/john/update-logging-example/use-window-options/js/app.bundle.js b/dev/john/update-logging-example/use-window-options/js/app.bundle.js new file mode 100644 index 00000000..22c58908 --- /dev/null +++ b/dev/john/update-logging-example/use-window-options/js/app.bundle.js @@ -0,0 +1,453 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ // The require scope +/******/ var __webpack_require__ = {}; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +/*!***************************!*\ + !*** ./client/src/app.ts ***! + \***************************/ +__webpack_require__.r(__webpack_exports__); +const defaultCommonOptions = { + name: "test-child", + url: window.location.href.replace("app.html", "preview.html"), + icon: undefined, + autoShow: true, + alwaysOnTop: false, + opacity: 1, + contextMenuOptions: { enabled: true }, + showTaskbarIcon: true, + resizable: true, + minimizable: true, + maximizable: true, + minWidth: 0, + maxWidth: -1, + minHeight: 0, + maxHeight: -1, + defaultCentered: false, + defaultLeft: 100, + defaultTop: 100, + defaultWidth: 800, + defaultHeight: 500, + aspectRatio: 0, + backgroundColor: undefined, + frame: true, + shadow: false +}; +const defaultFramelessOptions = { + shadow: false +}; +const defaultResizeRegion = { + size: 7, + bottomRightCorner: 9 +}; +const defaultResizeRegionSides = { + left: true, + top: true, + right: true, + bottom: true +}; +const defaultCornerRounding = { + width: 0, + height: 0 +}; +const defaultLaunchOptions = { usePlatform: false }; +let selectedCommonOptions = { ...defaultCommonOptions }; +let selectedFramelessOptions = { ...defaultFramelessOptions }; +let selectedResizeRegion = { ...defaultResizeRegion }; +let selectedResizeRegionSides = { ...defaultResizeRegionSides }; +let selectedCornerRounding = { ...defaultCornerRounding }; +let selectedLaunchOptions = { ...defaultLaunchOptions }; +let previewWindow; +document.addEventListener("DOMContentLoaded", async () => { + try { + await initDom(); + } + catch (error) { + console.error(error); + } +}); +/** + * Initialize the DOM elements. + */ +async function initDom() { + const app = fin.Application.getCurrentSync(); + const appInfo = await app.getInfo(); + if (!appInfo.initialOptions.isPlatformController) { + const usePlatformElemContainer = document.querySelector("#usePlatformContainer"); + if (usePlatformElemContainer) { + usePlatformElemContainer.style.display = "none"; + } + } + const btnPreview = document.querySelector("#btnPreview"); + if (btnPreview) { + btnPreview.addEventListener("click", async () => { + const previewOptions = { + ...finalizeWindowOptions(), + saveWindowState: false + }; + if (selectedLaunchOptions.usePlatform) { + const platform = fin.Platform.getCurrentSync(); + previewWindow = await platform.createWindow(previewOptions); + } + else { + previewWindow = await fin.Window.create(previewOptions); + } + await previewWindow.addListener("closed", () => { + previewWindow = undefined; + }); + }); + } + const btnClosePreview = document.querySelector("#btnClosePreview"); + if (btnClosePreview) { + btnClosePreview.addEventListener("click", async () => { + if (previewWindow) { + await previewWindow.removeAllListeners(); + await previewWindow.close(true); + previewWindow = undefined; + } + }); + } + const btnReset = document.querySelector("#btnReset"); + if (btnReset) { + btnReset.addEventListener("click", () => { + selectedCommonOptions = { ...defaultCommonOptions }; + selectedFramelessOptions = { ...defaultFramelessOptions }; + selectedResizeRegion = { ...defaultResizeRegion }; + selectedResizeRegionSides = { ...defaultResizeRegionSides }; + selectedCornerRounding = { ...defaultCornerRounding }; + selectedLaunchOptions = { ...defaultLaunchOptions }; + populateForm(); + updatePreview(); + }); + } + const btnCopy = document.querySelector("#btnCopy"); + if (btnCopy) { + btnCopy.addEventListener("click", async () => { + await fin.Clipboard.writeText({ data: createPreview() }); + }); + } + populateForm(); + updatePreview(); +} +/** + * Populate the form elements. + */ +function populateForm() { + // Common options + connectInput(selectedCommonOptions, "optionName", "name"); + connectInput(selectedCommonOptions, "optionUrl", "url"); + connectInput(selectedCommonOptions, "optionIcon", "icon"); + connectCheckbox(selectedCommonOptions, "optionAlwaysOnTop", "alwaysOnTop"); + connectCheckbox(selectedLaunchOptions, "optionUsePlatform", "usePlatform"); + connectRange(selectedCommonOptions, "optionOpacity", "opacity"); + connectCheckbox(selectedCommonOptions, "optionShowContextMenu", "contextMenu"); + connectCheckbox(selectedCommonOptions, "optionShowTaskbarIcon", "showTaskbarIcon"); + connectCheckbox(selectedCommonOptions, "optionMinimizable", "minimizable"); + connectCheckbox(selectedCommonOptions, "optionMaximizable", "maximizable"); + connectCheckbox(selectedCommonOptions, "optionResizable", "resizable"); + connectRange(selectedCommonOptions, "optionMinWidth", "minWidth", () => updateResizeWidth()); + connectRange(selectedCommonOptions, "optionMaxWidth", "maxWidth", () => updateResizeWidth()); + connectRange(selectedCommonOptions, "optionMinHeight", "minHeight", () => updateResizeHeight()); + connectRange(selectedCommonOptions, "optionMaxHeight", "maxHeight", () => updateResizeHeight()); + connectCheckbox(selectedCommonOptions, "optionDefaultCentered", "defaultCentered", () => updateDefaultPosition()); + connectRange(selectedCommonOptions, "optionDefaultLeft", "defaultLeft"); + connectRange(selectedCommonOptions, "optionDefaultTop", "defaultTop"); + connectRange(selectedCommonOptions, "optionDefaultWidth", "defaultWidth"); + connectRange(selectedCommonOptions, "optionDefaultHeight", "defaultHeight"); + connectRange(selectedCommonOptions, "optionAspectRatio", "aspectRatio"); + connectColor(selectedCommonOptions, "optionBackgroundColor", "backgroundColor"); + connectCheckbox(selectedCommonOptions, "optionFrame", "frame", () => updateFramelessState()); + // Frameless options + connectCheckbox(selectedFramelessOptions, "optionShadow", "shadow"); + connectRange(selectedResizeRegion, "optionEdgeResizeSize", "size"); + connectRange(selectedResizeRegion, "optionCornerResizeSize", "bottomRightCorner"); + connectCheckbox(selectedResizeRegionSides, "optionResizeRegionSideLeft", "left"); + connectCheckbox(selectedResizeRegionSides, "optionResizeRegionSideRight", "right"); + connectCheckbox(selectedResizeRegionSides, "optionResizeRegionSideTop", "top"); + connectCheckbox(selectedResizeRegionSides, "optionResizeRegionSideBottom", "bottom"); + connectRange(selectedCornerRounding, "optionCornerRoundingWidth", "width"); + connectRange(selectedCornerRounding, "optionCornerRoundingHeight", "height"); + updateFramelessState(); +} +/** + * Update the state of the frameless components. + */ +function updateFramelessState() { + const frame = selectedCommonOptions.frame ?? defaultCommonOptions.frame; + const sectionFrameless = document.querySelector("#sectionFrameless"); + if (sectionFrameless) { + sectionFrameless.style.display = frame ? "none" : "flex"; + } +} +/** + * Update the state of the resize width. + */ +function updateResizeWidth() { + if (selectedCommonOptions.maxWidth !== -1 && + selectedCommonOptions.maxWidth !== undefined && + selectedCommonOptions.minWidth !== undefined && + selectedCommonOptions.maxWidth < selectedCommonOptions.minWidth) { + selectedCommonOptions.maxWidth = selectedCommonOptions.minWidth; + const maxWidthElem = document.querySelector("#optionMaxWidth"); + if (maxWidthElem) { + maxWidthElem.valueAsNumber = selectedCommonOptions.maxWidth; + } + const maxWidthValueElem = document.querySelector("#optionMaxWidthValue"); + if (maxWidthValueElem) { + maxWidthValueElem.textContent = selectedCommonOptions.maxWidth.toString(); + } + } +} +/** + * Update the state of the resize height. + */ +function updateResizeHeight() { + if (selectedCommonOptions.maxHeight !== -1 && + selectedCommonOptions.maxHeight !== undefined && + selectedCommonOptions.minHeight !== undefined && + selectedCommonOptions.maxHeight < selectedCommonOptions.minHeight) { + selectedCommonOptions.maxHeight = selectedCommonOptions.minHeight; + const maxHeightElem = document.querySelector("#optionMaxHeight"); + if (maxHeightElem) { + maxHeightElem.valueAsNumber = selectedCommonOptions.maxHeight; + } + const maxHeightValueElem = document.querySelector("#optionMaxHeightValue"); + if (maxHeightValueElem) { + maxHeightValueElem.textContent = selectedCommonOptions.maxHeight.toString(); + } + } +} +/** + * Update the state of the default position components. + */ +function updateDefaultPosition() { + const isCentered = selectedCommonOptions.defaultCentered ?? defaultCommonOptions.defaultCentered; + const defaultPositionElem = document.querySelector("#defaultPosition"); + if (defaultPositionElem) { + defaultPositionElem.style.display = isCentered ? "none" : "flex"; + } + const optionDefaultLeft = document.querySelector("#optionDefaultLeft"); + if (optionDefaultLeft && defaultCommonOptions.defaultLeft !== undefined) { + optionDefaultLeft.valueAsNumber = defaultCommonOptions.defaultLeft; + } + const optionDefaultLeftValue = document.querySelector("#optionDefaultLeftValue"); + if (optionDefaultLeftValue && defaultCommonOptions.defaultLeft !== undefined) { + optionDefaultLeftValue.textContent = defaultCommonOptions.defaultLeft.toString(); + } + const optionDefaultTop = document.querySelector("#optionDefaultTop"); + if (optionDefaultTop && defaultCommonOptions.defaultTop !== undefined) { + optionDefaultTop.valueAsNumber = defaultCommonOptions.defaultTop; + } + const optionDefaultTopValue = document.querySelector("#optionDefaultTopValue"); + if (optionDefaultTopValue && defaultCommonOptions.defaultTop !== undefined) { + optionDefaultTopValue.textContent = defaultCommonOptions.defaultTop.toString(); + } + if (isCentered) { + delete selectedCommonOptions.defaultLeft; + delete selectedCommonOptions.defaultTop; + } +} +/** + * Set a property to an object. + * @param obj The object to set the property on. + * @param key The key to set. + * @param value The value. + */ +function setProperty(obj, key, value) { + obj[key] = value; +} +/** + * Get a property from an object. + * @param obj The object to get the property from. + * @param key The key to get + * @returns The value. + */ +function getProperty(obj, key) { + return obj[key]; +} +/** + * Connect an input to an option. + * @param selectedValues The selected value. + * @param fieldId The field id. + * @param property The property. + */ +function connectInput(selectedValues, fieldId, property) { + const option = document.querySelector(`#${fieldId}`); + if (option) { + option.value = getProperty(selectedValues, property) ?? ""; + option.addEventListener("input", () => { + setProperty(selectedValues, property, option.value === "" ? undefined : option.value); + updatePreview(); + }); + } +} +/** + * Connect a checkbox. + * @param selectedValues The selected values. + * @param fieldId The field id. + * @param property The property. + * @param changed The changed event to call. + */ +function connectCheckbox(selectedValues, fieldId, property, changed) { + const option = document.querySelector(`#${fieldId}`); + if (option) { + option.checked = getProperty(selectedValues, property); + option.addEventListener("change", () => { + setProperty(selectedValues, property, option.checked); + if (changed) { + changed(); + } + updatePreview(); + }); + } +} +/** + * Connect a range. + * @param selectedValues The selected values. + * @param fieldId The field id. + * @param property The property. + * @param changed The changed event to call. + */ +function connectRange(selectedValues, fieldId, property, changed) { + const option = document.querySelector(`#${fieldId}`); + const optionValue = document.querySelector(`#${fieldId}Value`); + if (option && optionValue) { + option.valueAsNumber = getProperty(selectedValues, property); + optionValue.textContent = getProperty(selectedValues, property); + option.addEventListener("input", () => { + setProperty(selectedValues, property, option.valueAsNumber); + optionValue.textContent = option.valueAsNumber.toString(); + if (changed) { + changed(); + } + updatePreview(); + }); + } +} +/** + * Connect a color. + * @param selectedValues The selected values. + * @param fieldId The field id. + * @param property The property. + * @param changed The changed event to call. + */ +function connectColor(selectedValues, fieldId, property, changed) { + const option = document.querySelector(`#${fieldId}`); + const optionValue = document.querySelector(`#${fieldId}Value`); + if (option && optionValue) { + option.value = getProperty(selectedValues, property); + optionValue.textContent = getProperty(selectedValues, property); + option.addEventListener("input", () => { + setProperty(selectedValues, property, option.value); + optionValue.textContent = option.value; + if (changed) { + changed(); + } + updatePreview(); + }); + } +} +/** + * Finalize the window options. + * @returns The complete window options. + */ +function finalizeWindowOptions() { + const finalWindowOptions = { + name: selectedCommonOptions.name, + url: selectedCommonOptions.url, + autoShow: selectedCommonOptions.autoShow + }; + for (const prop of Object.keys(selectedCommonOptions)) { + if (selectedCommonOptions[prop] !== defaultCommonOptions[prop]) { + finalWindowOptions[prop] = selectedCommonOptions[prop]; + } + } + if (!(selectedCommonOptions.frame ?? true)) { + for (const prop of Object.keys(selectedFramelessOptions)) { + if (selectedFramelessOptions[prop] !== defaultCommonOptions[prop]) { + finalWindowOptions[prop] = selectedFramelessOptions[prop]; + } + } + const finalRegion = {}; + if (selectedResizeRegion.bottomRightCorner !== defaultResizeRegion.bottomRightCorner) { + finalRegion.bottomRightCorner = selectedResizeRegion.bottomRightCorner; + } + if (selectedResizeRegion.size !== defaultResizeRegion.size) { + finalRegion.size = selectedResizeRegion.size; + } + if (selectedResizeRegion.sides) { + finalRegion.sides = {}; + if (selectedResizeRegion.sides?.bottom !== defaultResizeRegion.sides?.bottom) { + finalRegion.sides.bottom = selectedResizeRegion.sides?.bottom; + } + if (selectedResizeRegion.sides?.left !== defaultResizeRegion.sides?.left) { + finalRegion.sides.left = selectedResizeRegion.sides?.left; + } + if (selectedResizeRegion.sides?.top !== defaultResizeRegion.sides?.top) { + finalRegion.sides.top = selectedResizeRegion.sides?.top; + } + if (selectedResizeRegion.sides?.right !== defaultResizeRegion.sides?.right) { + finalRegion.sides.right = selectedResizeRegion.sides?.right; + } + if (Object.keys(finalRegion.sides).length === 0) { + delete finalRegion.sides; + } + } + if (Object.keys(finalRegion).length > 0) { + finalWindowOptions.resizeRegion = finalRegion; + } + for (const prop of Object.keys(selectedResizeRegionSides)) { + if (selectedResizeRegionSides[prop] !== defaultResizeRegionSides[prop]) { + finalWindowOptions.resizeRegion = finalWindowOptions.resizeRegion ?? {}; + finalWindowOptions.resizeRegion.sides = finalWindowOptions.resizeRegion.sides ?? {}; + finalWindowOptions.resizeRegion.sides[prop] = selectedResizeRegionSides[prop]; + } + } + for (const prop of Object.keys(selectedCornerRounding)) { + if (selectedCornerRounding[prop] !== defaultCornerRounding[prop]) { + finalWindowOptions.cornerRounding = finalWindowOptions.cornerRounding ?? {}; + finalWindowOptions.cornerRounding[prop] = selectedCornerRounding[prop]; + } + } + } + return finalWindowOptions; +} +/** + * Update the preview. + */ +function updatePreview() { + const previewElem = document.querySelector("#preview"); + if (previewElem) { + previewElem.textContent = createPreview(); + } +} +/** + * Create a preview. + * @returns The preview code. + */ +function createPreview() { + if (selectedLaunchOptions.usePlatform) { + return `const platform = fin.Platform.getCurrentSync(); +await platform.createWindow(${JSON.stringify(finalizeWindowOptions(), undefined, " ")});`; + } + return `await fin.Window.create(${JSON.stringify(finalizeWindowOptions(), undefined, " ")});`; +} + + +/******/ })() +; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,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LFNBQVMsYUFBYTtJQUNyQixJQUFJLHFCQUFxQixDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3ZDLE9BQU87OEJBQ3FCLElBQUksQ0FBQyxTQUFTLENBQUMscUJBQXFCLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQztJQUMxRixDQUFDO0lBQ0QsT0FBTywyQkFBMkIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDO0FBQ2hHLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly91c2Utd2luZG93LW9wdGlvbnMvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vdXNlLXdpbmRvdy1vcHRpb25zL3dlYnBhY2svcnVudGltZS9tYWtlIG5hbWVzcGFjZSBvYmplY3QiLCJ3ZWJwYWNrOi8vdXNlLXdpbmRvdy1vcHRpb25zLy4vY2xpZW50L3NyYy9hcHAudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gVGhlIHJlcXVpcmUgc2NvcGVcbnZhciBfX3dlYnBhY2tfcmVxdWlyZV9fID0ge307XG5cbiIsIi8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uciA9IChleHBvcnRzKSA9PiB7XG5cdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pO1xuXHR9XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG59OyIsImltcG9ydCB0eXBlIE9wZW5GaW4gZnJvbSBcIkBvcGVuZmluL2NvcmVcIjtcblxuY29uc3QgZGVmYXVsdENvbW1vbk9wdGlvbnM6IE9wZW5GaW4uV2luZG93Q3JlYXRpb25PcHRpb25zID0ge1xuXHRuYW1lOiBcInRlc3QtY2hpbGRcIixcblx0dXJsOiB3aW5kb3cubG9jYXRpb24uaHJlZi5yZXBsYWNlKFwiYXBwLmh0bWxcIiwgXCJwcmV2aWV3Lmh0bWxcIiksXG5cdGljb246IHVuZGVmaW5lZCxcblx0YXV0b1Nob3c6IHRydWUsXG5cdGFsd2F5c09uVG9wOiBmYWxzZSxcblx0b3BhY2l0eTogMSxcblx0Y29udGV4dE1lbnVPcHRpb25zOiB7IGVuYWJsZWQ6IHRydWUgfSxcblx0c2hvd1Rhc2tiYXJJY29uOiB0cnVlLFxuXHRyZXNpemFibGU6IHRydWUsXG5cdG1pbmltaXphYmxlOiB0cnVlLFxuXHRtYXhpbWl6YWJsZTogdHJ1ZSxcblx0bWluV2lkdGg6IDAsXG5cdG1heFdpZHRoOiAtMSxcblx0bWluSGVpZ2h0OiAwLFxuXHRtYXhIZWlnaHQ6IC0xLFxuXHRkZWZhdWx0Q2VudGVyZWQ6IGZhbHNlLFxuXHRkZWZhdWx0TGVmdDogMTAwLFxuXHRkZWZhdWx0VG9wOiAxMDAsXG5cdGRlZmF1bHRXaWR0aDogODAwLFxuXHRkZWZhdWx0SGVpZ2h0OiA1MDAsXG5cdGFzcGVjdFJhdGlvOiAwLFxuXHRiYWNrZ3JvdW5kQ29sb3I6IHVuZGVmaW5lZCxcblx0ZnJhbWU6IHRydWUsXG5cdHNoYWRvdzogZmFsc2Vcbn07XG5cbmNvbnN0IGRlZmF1bHRGcmFtZWxlc3NPcHRpb25zOiBQYXJ0aWFsPE9wZW5GaW4uV2luZG93Q3JlYXRpb25PcHRpb25zPiA9IHtcblx0c2hhZG93OiBmYWxzZVxufTtcblxuY29uc3QgZGVmYXVsdFJlc2l6ZVJlZ2lvbjogUGFydGlhbDxPcGVuRmluLlJlc2l6ZVJlZ2lvbj4gPSB7XG5cdHNpemU6IDcsXG5cdGJvdHRvbVJpZ2h0Q29ybmVyOiA5XG59O1xuXG4vKipcbiAqIFR5cGUgZm9yIHRoZSByZXNpemUgc2lkZXMuXG4gKi9cbmludGVyZmFjZSBSZXNpemVTaWRlcyB7XG5cdC8qKlxuXHQgKiBUb3AgcG9zaXRpb24uXG5cdCAqL1xuXHR0b3A6IGJvb2xlYW47XG5cdC8qKlxuXHQgKiBMZWZ0IHBvc2l0aW9uLlxuXHQgKi9cblx0bGVmdDogYm9vbGVhbjtcblx0LyoqXG5cdCAqIFJpZ2h0IHBvc2l0aW9uLlxuXHQgKi9cblx0cmlnaHQ6IGJvb2xlYW47XG5cdC8qKlxuXHQgKiBCb3R0b20gcG9zaXRpb24uXG5cdCAqL1xuXHRib3R0b206IGJvb2xlYW47XG59XG5cbmNvbnN0IGRlZmF1bHRSZXNpemVSZWdpb25TaWRlczogUGFydGlhbDxSZXNpemVTaWRlcz4gPSB7XG5cdGxlZnQ6IHRydWUsXG5cdHRvcDogdHJ1ZSxcblx0cmlnaHQ6IHRydWUsXG5cdGJvdHRvbTogdHJ1ZVxufTtcblxuY29uc3QgZGVmYXVsdENvcm5lclJvdW5kaW5nOiBQYXJ0aWFsPE9wZW5GaW4uQ29ybmVyUm91bmRpbmc+ID0ge1xuXHR3aWR0aDogMCxcblx0aGVpZ2h0OiAwXG59O1xuXG5jb25zdCBkZWZhdWx0TGF1bmNoT3B0aW9uczoge1xuXHR1c2VQbGF0Zm9ybTogYm9vbGVhbjtcbn0gPSB7IHVzZVBsYXRmb3JtOiBmYWxzZSB9O1xuXG5sZXQgc2VsZWN0ZWRDb21tb25PcHRpb25zOiBPcGVuRmluLldpbmRvd0NyZWF0aW9uT3B0aW9ucyA9IHsgLi4uZGVmYXVsdENvbW1vbk9wdGlvbnMgfTtcbmxldCBzZWxlY3RlZEZyYW1lbGVzc09wdGlvbnM6IFBhcnRpYWw8T3BlbkZpbi5XaW5kb3dDcmVhdGlvbk9wdGlvbnM+ID0geyAuLi5kZWZhdWx0RnJhbWVsZXNzT3B0aW9ucyB9O1xubGV0IHNlbGVjdGVkUmVzaXplUmVnaW9uOiBQYXJ0aWFsPE9wZW5GaW4uUmVzaXplUmVnaW9uPiA9IHsgLi4uZGVmYXVsdFJlc2l6ZVJlZ2lvbiB9O1xubGV0IHNlbGVjdGVkUmVzaXplUmVnaW9uU2lkZXM6IFBhcnRpYWw8UmVzaXplU2lkZXM+ID0geyAuLi5kZWZhdWx0UmVzaXplUmVnaW9uU2lkZXMgfTtcbmxldCBzZWxlY3RlZENvcm5lclJvdW5kaW5nOiBQYXJ0aWFsPE9wZW5GaW4uQ29ybmVyUm91bmRpbmc+ID0geyAuLi5kZWZhdWx0Q29ybmVyUm91bmRpbmcgfTtcbmxldCBzZWxlY3RlZExhdW5jaE9wdGlvbnMgPSB7IC4uLmRlZmF1bHRMYXVuY2hPcHRpb25zIH07XG5cbmxldCBwcmV2aWV3V2luZG93OiBPcGVuRmluLldpbmRvdyB8IHVuZGVmaW5lZDtcblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNvbnRlbnRMb2FkZWRcIiwgYXN5bmMgKCkgPT4ge1xuXHR0cnkge1xuXHRcdGF3YWl0IGluaXREb20oKTtcblx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTtcblx0fVxufSk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgRE9NIGVsZW1lbnRzLlxuICovXG5hc3luYyBmdW5jdGlvbiBpbml0RG9tKCk6IFByb21pc2U8dm9pZD4ge1xuXHRjb25zdCBhcHAgPSBmaW4uQXBwbGljYXRpb24uZ2V0Q3VycmVudFN5bmMoKTtcblx0Y29uc3QgYXBwSW5mbyA9IGF3YWl0IGFwcC5nZXRJbmZvKCk7XG5cdGlmICghYXBwSW5mby5pbml0aWFsT3B0aW9ucy5pc1BsYXRmb3JtQ29udHJvbGxlcikge1xuXHRcdGNvbnN0IHVzZVBsYXRmb3JtRWxlbUNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KFwiI3VzZVBsYXRmb3JtQ29udGFpbmVyXCIpO1xuXHRcdGlmICh1c2VQbGF0Zm9ybUVsZW1Db250YWluZXIpIHtcblx0XHRcdHVzZVBsYXRmb3JtRWxlbUNvbnRhaW5lci5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG5cdFx0fVxuXHR9XG5cdGNvbnN0IGJ0blByZXZpZXcgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2J0blByZXZpZXdcIik7XG5cdGlmIChidG5QcmV2aWV3KSB7XG5cdFx0YnRuUHJldmlldy5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0Y29uc3QgcHJldmlld09wdGlvbnM6IE9wZW5GaW4uV2luZG93Q3JlYXRpb25PcHRpb25zID0ge1xuXHRcdFx0XHQuLi5maW5hbGl6ZVdpbmRvd09wdGlvbnMoKSxcblx0XHRcdFx0c2F2ZVdpbmRvd1N0YXRlOiBmYWxzZVxuXHRcdFx0fTtcblx0XHRcdGlmIChzZWxlY3RlZExhdW5jaE9wdGlvbnMudXNlUGxhdGZvcm0pIHtcblx0XHRcdFx0Y29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcblx0XHRcdFx0cHJldmlld1dpbmRvdyA9IGF3YWl0IHBsYXRmb3JtLmNyZWF0ZVdpbmRvdyhwcmV2aWV3T3B0aW9ucyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRwcmV2aWV3V2luZG93ID0gYXdhaXQgZmluLldpbmRvdy5jcmVhdGUocHJldmlld09wdGlvbnMpO1xuXHRcdFx0fVxuXG5cdFx0XHRhd2FpdCBwcmV2aWV3V2luZG93LmFkZExpc3RlbmVyKFwiY2xvc2VkXCIsICgpID0+IHtcblx0XHRcdFx0cHJldmlld1dpbmRvdyA9IHVuZGVmaW5lZDtcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9XG5cblx0Y29uc3QgYnRuQ2xvc2VQcmV2aWV3ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNidG5DbG9zZVByZXZpZXdcIik7XG5cdGlmIChidG5DbG9zZVByZXZpZXcpIHtcblx0XHRidG5DbG9zZVByZXZpZXcuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGFzeW5jICgpID0+IHtcblx0XHRcdGlmIChwcmV2aWV3V2luZG93KSB7XG5cdFx0XHRcdGF3YWl0IHByZXZpZXdXaW5kb3cucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG5cdFx0XHRcdGF3YWl0IHByZXZpZXdXaW5kb3cuY2xvc2UodHJ1ZSk7XG5cdFx0XHRcdHByZXZpZXdXaW5kb3cgPSB1bmRlZmluZWQ7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHRjb25zdCBidG5SZXNldCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjYnRuUmVzZXRcIik7XG5cdGlmIChidG5SZXNldCkge1xuXHRcdGJ0blJlc2V0LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCAoKSA9PiB7XG5cdFx0XHRzZWxlY3RlZENvbW1vbk9wdGlvbnMgPSB7IC4uLmRlZmF1bHRDb21tb25PcHRpb25zIH07XG5cdFx0XHRzZWxlY3RlZEZyYW1lbGVzc09wdGlvbnMgPSB7IC4uLmRlZmF1bHRGcmFtZWxlc3NPcHRpb25zIH07XG5cdFx0XHRzZWxlY3RlZFJlc2l6ZVJlZ2lvbiA9IHsgLi4uZGVmYXVsdFJlc2l6ZVJlZ2lvbiB9O1xuXHRcdFx0c2VsZWN0ZWRSZXNpemVSZWdpb25TaWRlcyA9IHsgLi4uZGVmYXVsdFJlc2l6ZVJlZ2lvblNpZGVzIH07XG5cdFx0XHRzZWxlY3RlZENvcm5lclJvdW5kaW5nID0geyAuLi5kZWZhdWx0Q29ybmVyUm91bmRpbmcgfTtcblx0XHRcdHNlbGVjdGVkTGF1bmNoT3B0aW9ucyA9IHsgLi4uZGVmYXVsdExhdW5jaE9wdGlvbnMgfTtcblx0XHRcdHBvcHVsYXRlRm9ybSgpO1xuXHRcdFx0dXBkYXRlUHJldmlldygpO1xuXHRcdH0pO1xuXHR9XG5cblx0Y29uc3QgYnRuQ29weSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjYnRuQ29weVwiKTtcblx0aWYgKGJ0bkNvcHkpIHtcblx0XHRidG5Db3B5LmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRhd2FpdCBmaW4uQ2xpcGJvYXJkLndyaXRlVGV4dCh7IGRhdGE6IGNyZWF0ZVByZXZpZXcoKSB9KTtcblx0XHR9KTtcblx0fVxuXG5cdHBvcHVsYXRlRm9ybSgpO1xuXHR1cGRhdGVQcmV2aWV3KCk7XG59XG5cbi8qKlxuICogUG9wdWxhdGUgdGhlIGZvcm0gZWxlbWVudHMuXG4gKi9cbmZ1bmN0aW9uIHBvcHVsYXRlRm9ybSgpOiB2b2lkIHtcblx0Ly8gQ29tbW9uIG9wdGlvbnNcblx0Y29ubmVjdElucHV0KHNlbGVjdGVkQ29tbW9uT3B0aW9ucywgXCJvcHRpb25OYW1lXCIsIFwibmFtZVwiKTtcblx0Y29ubmVjdElucHV0KHNlbGVjdGVkQ29tbW9uT3B0aW9ucywgXCJvcHRpb25VcmxcIiwgXCJ1cmxcIik7XG5cdGNvbm5lY3RJbnB1dChzZWxlY3RlZENvbW1vbk9wdGlvbnMsIFwib3B0aW9uSWNvblwiLCBcImljb25cIik7XG5cdGNvbm5lY3RDaGVja2JveChzZWxlY3RlZENvbW1vbk9wdGlvbnMsIFwib3B0aW9uQWx3YXlzT25Ub3BcIiwgXCJhbHdheXNPblRvcFwiKTtcblx0Y29ubmVjdENoZWNrYm94KHNlbGVjdGVkTGF1bmNoT3B0aW9ucywgXCJvcHRpb25Vc2VQbGF0Zm9ybVwiLCBcInVzZVBsYXRmb3JtXCIpO1xuXHRjb25uZWN0UmFuZ2Uoc2VsZWN0ZWRDb21tb25PcHRpb25zLCBcIm9wdGlvbk9wYWNpdHlcIiwgXCJvcGFjaXR5XCIpO1xuXHRjb25uZWN0Q2hlY2tib3goc2VsZWN0ZWRDb21tb25PcHRpb25zLCBcIm9wdGlvblNob3dDb250ZXh0TWVudVwiLCBcImNvbnRleHRNZW51XCIpO1xuXHRjb25uZWN0Q2hlY2tib3goc2VsZWN0ZWRDb21tb25PcHRpb25zLCBcIm9wdGlvblNob3dUYXNrYmFySWNvblwiLCBcInNob3dUYXNrYmFySWNvblwiKTtcblx0Y29ubmVjdENoZWNrYm94KHNlbGVjdGVkQ29tbW9uT3B0aW9ucywgXCJvcHRpb25NaW5pbWl6YWJsZVwiLCBcIm1pbmltaXphYmxlXCIpO1xuXHRjb25uZWN0Q2hlY2tib3goc2VsZWN0ZWRDb21tb25PcHRpb25zLCBcIm9wdGlvbk1heGltaXphYmxlXCIsIFwibWF4aW1pemFibGVcIik7XG5cdGNvbm5lY3RDaGVja2JveChzZWxlY3RlZENvbW1vbk9wdGlvbnMsIFwib3B0aW9uUmVzaXphYmxlXCIsIFwicmVzaXphYmxlXCIpO1xuXHRjb25uZWN0UmFuZ2Uoc2VsZWN0ZWRDb21tb25PcHRpb25zLCBcIm9wdGlvbk1pbldpZHRoXCIsIFwibWluV2lkdGhcIiwgKCkgPT4gdXBkYXRlUmVzaXplV2lkdGgoKSk7XG5cdGNvbm5lY3RSYW5nZShzZWxlY3RlZENvbW1vbk9wdGlvbnMsIFwib3B0aW9uTWF4V2lkdGhcIiwgXCJtYXhXaWR0aFwiLCAoKSA9PiB1cGRhdGVSZXNpemVXaWR0aCgpKTtcblx0Y29ubmVjdFJhbmdlKHNlbGVjdGVkQ29tbW9uT3B0aW9ucywgXCJvcHRpb25NaW5IZWlnaHRcIiwgXCJtaW5IZWlnaHRcIiwgKCkgPT4gdXBkYXRlUmVzaXplSGVpZ2h0KCkpO1xuXHRjb25uZWN0UmFuZ2Uoc2VsZWN0ZWRDb21tb25PcHRpb25zLCBcIm9wdGlvbk1heEhlaWdodFwiLCBcIm1heEhlaWdodFwiLCAoKSA9PiB1cGRhdGVSZXNpemVIZWlnaHQoKSk7XG5cdGNvbm5lY3RDaGVja2JveChzZWxlY3RlZENvbW1vbk9wdGlvbnMsIFwib3B0aW9uRGVmYXVsdENlbnRlcmVkXCIsIFwiZGVmYXVsdENlbnRlcmVkXCIsICgpID0+XG5cdFx0dXBkYXRlRGVmYXVsdFBvc2l0aW9uKClcblx0KTtcblx0Y29ubmVjdFJhbmdlKHNlbGVjdGVkQ29tbW9uT3B0aW9ucywgXCJvcHRpb25EZWZhdWx0TGVmdFwiLCBcImRlZmF1bHRMZWZ0XCIpO1xuXHRjb25uZWN0UmFuZ2Uoc2VsZWN0ZWRDb21tb25PcHRpb25zLCBcIm9wdGlvbkRlZmF1bHRUb3BcIiwgXCJkZWZhdWx0VG9wXCIpO1xuXHRjb25uZWN0UmFuZ2Uoc2VsZWN0ZWRDb21tb25PcHRpb25zLCBcIm9wdGlvbkRlZmF1bHRXaWR0aFwiLCBcImRlZmF1bHRXaWR0aFwiKTtcblx0Y29ubmVjdFJhbmdlKHNlbGVjdGVkQ29tbW9uT3B0aW9ucywgXCJvcHRpb25EZWZhdWx0SGVpZ2h0XCIsIFwiZGVmYXVsdEhlaWdodFwiKTtcblx0Y29ubmVjdFJhbmdlKHNlbGVjdGVkQ29tbW9uT3B0aW9ucywgXCJvcHRpb25Bc3BlY3RSYXRpb1wiLCBcImFzcGVjdFJhdGlvXCIpO1xuXHRjb25uZWN0Q29sb3Ioc2VsZWN0ZWRDb21tb25PcHRpb25zLCBcIm9wdGlvbkJhY2tncm91bmRDb2xvclwiLCBcImJhY2tncm91bmRDb2xvclwiKTtcblx0Y29ubmVjdENoZWNrYm94KHNlbGVjdGVkQ29tbW9uT3B0aW9ucywgXCJvcHRpb25GcmFtZVwiLCBcImZyYW1lXCIsICgpID0+IHVwZGF0ZUZyYW1lbGVzc1N0YXRlKCkpO1xuXG5cdC8vIEZyYW1lbGVzcyBvcHRpb25zXG5cdGNvbm5lY3RDaGVja2JveChzZWxlY3RlZEZyYW1lbGVzc09wdGlvbnMsIFwib3B0aW9uU2hhZG93XCIsIFwic2hhZG93XCIpO1xuXHRjb25uZWN0UmFuZ2Uoc2VsZWN0ZWRSZXNpemVSZWdpb24sIFwib3B0aW9uRWRnZVJlc2l6ZVNpemVcIiwgXCJzaXplXCIpO1xuXHRjb25uZWN0UmFuZ2Uoc2VsZWN0ZWRSZXNpemVSZWdpb24sIFwib3B0aW9uQ29ybmVyUmVzaXplU2l6ZVwiLCBcImJvdHRvbVJpZ2h0Q29ybmVyXCIpO1xuXHRjb25uZWN0Q2hlY2tib3goc2VsZWN0ZWRSZXNpemVSZWdpb25TaWRlcywgXCJvcHRpb25SZXNpemVSZWdpb25TaWRlTGVmdFwiLCBcImxlZnRcIik7XG5cdGNvbm5lY3RDaGVja2JveChzZWxlY3RlZFJlc2l6ZVJlZ2lvblNpZGVzLCBcIm9wdGlvblJlc2l6ZVJlZ2lvblNpZGVSaWdodFwiLCBcInJpZ2h0XCIpO1xuXHRjb25uZWN0Q2hlY2tib3goc2VsZWN0ZWRSZXNpemVSZWdpb25TaWRlcywgXCJvcHRpb25SZXNpemVSZWdpb25TaWRlVG9wXCIsIFwidG9wXCIpO1xuXHRjb25uZWN0Q2hlY2tib3goc2VsZWN0ZWRSZXNpemVSZWdpb25TaWRlcywgXCJvcHRpb25SZXNpemVSZWdpb25TaWRlQm90dG9tXCIsIFwiYm90dG9tXCIpO1xuXG5cdGNvbm5lY3RSYW5nZShzZWxlY3RlZENvcm5lclJvdW5kaW5nLCBcIm9wdGlvbkNvcm5lclJvdW5kaW5nV2lkdGhcIiwgXCJ3aWR0aFwiKTtcblx0Y29ubmVjdFJhbmdlKHNlbGVjdGVkQ29ybmVyUm91bmRpbmcsIFwib3B0aW9uQ29ybmVyUm91bmRpbmdIZWlnaHRcIiwgXCJoZWlnaHRcIik7XG5cblx0dXBkYXRlRnJhbWVsZXNzU3RhdGUoKTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgdGhlIHN0YXRlIG9mIHRoZSBmcmFtZWxlc3MgY29tcG9uZW50cy5cbiAqL1xuZnVuY3Rpb24gdXBkYXRlRnJhbWVsZXNzU3RhdGUoKTogdm9pZCB7XG5cdGNvbnN0IGZyYW1lID0gc2VsZWN0ZWRDb21tb25PcHRpb25zLmZyYW1lID8/IGRlZmF1bHRDb21tb25PcHRpb25zLmZyYW1lO1xuXHRjb25zdCBzZWN0aW9uRnJhbWVsZXNzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MRWxlbWVudD4oXCIjc2VjdGlvbkZyYW1lbGVzc1wiKTtcblx0aWYgKHNlY3Rpb25GcmFtZWxlc3MpIHtcblx0XHRzZWN0aW9uRnJhbWVsZXNzLnN0eWxlLmRpc3BsYXkgPSBmcmFtZSA/IFwibm9uZVwiIDogXCJmbGV4XCI7XG5cdH1cbn1cblxuLyoqXG4gKiBVcGRhdGUgdGhlIHN0YXRlIG9mIHRoZSByZXNpemUgd2lkdGguXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVJlc2l6ZVdpZHRoKCk6IHZvaWQge1xuXHRpZiAoXG5cdFx0c2VsZWN0ZWRDb21tb25PcHRpb25zLm1heFdpZHRoICE9PSAtMSAmJlxuXHRcdHNlbGVjdGVkQ29tbW9uT3B0aW9ucy5tYXhXaWR0aCAhPT0gdW5kZWZpbmVkICYmXG5cdFx0c2VsZWN0ZWRDb21tb25PcHRpb25zLm1pbldpZHRoICE9PSB1bmRlZmluZWQgJiZcblx0XHRzZWxlY3RlZENvbW1vbk9wdGlvbnMubWF4V2lkdGggPCBzZWxlY3RlZENvbW1vbk9wdGlvbnMubWluV2lkdGhcblx0KSB7XG5cdFx0c2VsZWN0ZWRDb21tb25PcHRpb25zLm1heFdpZHRoID0gc2VsZWN0ZWRDb21tb25PcHRpb25zLm1pbldpZHRoO1xuXHRcdGNvbnN0IG1heFdpZHRoRWxlbSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTElucHV0RWxlbWVudD4oXCIjb3B0aW9uTWF4V2lkdGhcIik7XG5cdFx0aWYgKG1heFdpZHRoRWxlbSkge1xuXHRcdFx0bWF4V2lkdGhFbGVtLnZhbHVlQXNOdW1iZXIgPSBzZWxlY3RlZENvbW1vbk9wdGlvbnMubWF4V2lkdGg7XG5cdFx0fVxuXHRcdGNvbnN0IG1heFdpZHRoVmFsdWVFbGVtID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MRWxlbWVudD4oXCIjb3B0aW9uTWF4V2lkdGhWYWx1ZVwiKTtcblx0XHRpZiAobWF4V2lkdGhWYWx1ZUVsZW0pIHtcblx0XHRcdG1heFdpZHRoVmFsdWVFbGVtLnRleHRDb250ZW50ID0gc2VsZWN0ZWRDb21tb25PcHRpb25zLm1heFdpZHRoLnRvU3RyaW5nKCk7XG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogVXBkYXRlIHRoZSBzdGF0ZSBvZiB0aGUgcmVzaXplIGhlaWdodC5cbiAqL1xuZnVuY3Rpb24gdXBkYXRlUmVzaXplSGVpZ2h0KCk6IHZvaWQge1xuXHRpZiAoXG5cdFx0c2VsZWN0ZWRDb21tb25PcHRpb25zLm1heEhlaWdodCAhPT0gLTEgJiZcblx0XHRzZWxlY3RlZENvbW1vbk9wdGlvbnMubWF4SGVpZ2h0ICE9PSB1bmRlZmluZWQgJiZcblx0XHRzZWxlY3RlZENvbW1vbk9wdGlvbnMubWluSGVpZ2h0ICE9PSB1bmRlZmluZWQgJiZcblx0XHRzZWxlY3RlZENvbW1vbk9wdGlvbnMubWF4SGVpZ2h0IDwgc2VsZWN0ZWRDb21tb25PcHRpb25zLm1pbkhlaWdodFxuXHQpIHtcblx0XHRzZWxlY3RlZENvbW1vbk9wdGlvbnMubWF4SGVpZ2h0ID0gc2VsZWN0ZWRDb21tb25PcHRpb25zLm1pbkhlaWdodDtcblx0XHRjb25zdCBtYXhIZWlnaHRFbGVtID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MSW5wdXRFbGVtZW50PihcIiNvcHRpb25NYXhIZWlnaHRcIik7XG5cdFx0aWYgKG1heEhlaWdodEVsZW0pIHtcblx0XHRcdG1heEhlaWdodEVsZW0udmFsdWVBc051bWJlciA9IHNlbGVjdGVkQ29tbW9uT3B0aW9ucy5tYXhIZWlnaHQ7XG5cdFx0fVxuXHRcdGNvbnN0IG1heEhlaWdodFZhbHVlRWxlbSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KFwiI29wdGlvbk1heEhlaWdodFZhbHVlXCIpO1xuXHRcdGlmIChtYXhIZWlnaHRWYWx1ZUVsZW0pIHtcblx0XHRcdG1heEhlaWdodFZhbHVlRWxlbS50ZXh0Q29udGVudCA9IHNlbGVjdGVkQ29tbW9uT3B0aW9ucy5tYXhIZWlnaHQudG9TdHJpbmcoKTtcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4gKiBVcGRhdGUgdGhlIHN0YXRlIG9mIHRoZSBkZWZhdWx0IHBvc2l0aW9uIGNvbXBvbmVudHMuXG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZURlZmF1bHRQb3NpdGlvbigpOiB2b2lkIHtcblx0Y29uc3QgaXNDZW50ZXJlZCA9IHNlbGVjdGVkQ29tbW9uT3B0aW9ucy5kZWZhdWx0Q2VudGVyZWQgPz8gZGVmYXVsdENvbW1vbk9wdGlvbnMuZGVmYXVsdENlbnRlcmVkO1xuXG5cdGNvbnN0IGRlZmF1bHRQb3NpdGlvbkVsZW0gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxEaXZFbGVtZW50PihcIiNkZWZhdWx0UG9zaXRpb25cIik7XG5cdGlmIChkZWZhdWx0UG9zaXRpb25FbGVtKSB7XG5cdFx0ZGVmYXVsdFBvc2l0aW9uRWxlbS5zdHlsZS5kaXNwbGF5ID0gaXNDZW50ZXJlZCA/IFwibm9uZVwiIDogXCJmbGV4XCI7XG5cdH1cblxuXHRjb25zdCBvcHRpb25EZWZhdWx0TGVmdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTElucHV0RWxlbWVudD4oXCIjb3B0aW9uRGVmYXVsdExlZnRcIik7XG5cdGlmIChvcHRpb25EZWZhdWx0TGVmdCAmJiBkZWZhdWx0Q29tbW9uT3B0aW9ucy5kZWZhdWx0TGVmdCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0b3B0aW9uRGVmYXVsdExlZnQudmFsdWVBc051bWJlciA9IGRlZmF1bHRDb21tb25PcHRpb25zLmRlZmF1bHRMZWZ0O1xuXHR9XG5cdGNvbnN0IG9wdGlvbkRlZmF1bHRMZWZ0VmFsdWUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxTcGFuRWxlbWVudD4oXCIjb3B0aW9uRGVmYXVsdExlZnRWYWx1ZVwiKTtcblx0aWYgKG9wdGlvbkRlZmF1bHRMZWZ0VmFsdWUgJiYgZGVmYXVsdENvbW1vbk9wdGlvbnMuZGVmYXVsdExlZnQgIT09IHVuZGVmaW5lZCkge1xuXHRcdG9wdGlvbkRlZmF1bHRMZWZ0VmFsdWUudGV4dENvbnRlbnQgPSBkZWZhdWx0Q29tbW9uT3B0aW9ucy5kZWZhdWx0TGVmdC50b1N0cmluZygpO1xuXHR9XG5cblx0Y29uc3Qgb3B0aW9uRGVmYXVsdFRvcCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTElucHV0RWxlbWVudD4oXCIjb3B0aW9uRGVmYXVsdFRvcFwiKTtcblx0aWYgKG9wdGlvbkRlZmF1bHRUb3AgJiYgZGVmYXVsdENvbW1vbk9wdGlvbnMuZGVmYXVsdFRvcCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0b3B0aW9uRGVmYXVsdFRvcC52YWx1ZUFzTnVtYmVyID0gZGVmYXVsdENvbW1vbk9wdGlvbnMuZGVmYXVsdFRvcDtcblx0fVxuXHRjb25zdCBvcHRpb25EZWZhdWx0VG9wVmFsdWUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxTcGFuRWxlbWVudD4oXCIjb3B0aW9uRGVmYXVsdFRvcFZhbHVlXCIpO1xuXHRpZiAob3B0aW9uRGVmYXVsdFRvcFZhbHVlICYmIGRlZmF1bHRDb21tb25PcHRpb25zLmRlZmF1bHRUb3AgIT09IHVuZGVmaW5lZCkge1xuXHRcdG9wdGlvbkRlZmF1bHRUb3BWYWx1ZS50ZXh0Q29udGVudCA9IGRlZmF1bHRDb21tb25PcHRpb25zLmRlZmF1bHRUb3AudG9TdHJpbmcoKTtcblx0fVxuXG5cdGlmIChpc0NlbnRlcmVkKSB7XG5cdFx0ZGVsZXRlIHNlbGVjdGVkQ29tbW9uT3B0aW9ucy5kZWZhdWx0TGVmdDtcblx0XHRkZWxldGUgc2VsZWN0ZWRDb21tb25PcHRpb25zLmRlZmF1bHRUb3A7XG5cdH1cbn1cblxuLyoqXG4gKiBTZXQgYSBwcm9wZXJ0eSB0byBhbiBvYmplY3QuXG4gKiBAcGFyYW0gb2JqIFRoZSBvYmplY3QgdG8gc2V0IHRoZSBwcm9wZXJ0eSBvbi5cbiAqIEBwYXJhbSBrZXkgVGhlIGtleSB0byBzZXQuXG4gKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlLlxuICovXG5mdW5jdGlvbiBzZXRQcm9wZXJ0eTxULCBLIGV4dGVuZHMga2V5b2YgVD4ob2JqOiBQYXJ0aWFsPFQ+LCBrZXk6IEssIHZhbHVlOiB1bmtub3duKTogdm9pZCB7XG5cdG9ialtrZXldID0gdmFsdWUgYXMgVFtLXTtcbn1cblxuLyoqXG4gKiBHZXQgYSBwcm9wZXJ0eSBmcm9tIGFuIG9iamVjdC5cbiAqIEBwYXJhbSBvYmogVGhlIG9iamVjdCB0byBnZXQgdGhlIHByb3BlcnR5IGZyb20uXG4gKiBAcGFyYW0ga2V5IFRoZSBrZXkgdG8gZ2V0XG4gKiBAcmV0dXJucyBUaGUgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIGdldFByb3BlcnR5PFQsIEsgZXh0ZW5kcyBrZXlvZiBULCBQPihvYmo6IFBhcnRpYWw8VD4sIGtleTogSyk6IFAge1xuXHRyZXR1cm4gb2JqW2tleV0gYXMgdW5rbm93biBhcyBQO1xufVxuXG4vKipcbiAqIENvbm5lY3QgYW4gaW5wdXQgdG8gYW4gb3B0aW9uLlxuICogQHBhcmFtIHNlbGVjdGVkVmFsdWVzIFRoZSBzZWxlY3RlZCB2YWx1ZS5cbiAqIEBwYXJhbSBmaWVsZElkIFRoZSBmaWVsZCBpZC5cbiAqIEBwYXJhbSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkuXG4gKi9cbmZ1bmN0aW9uIGNvbm5lY3RJbnB1dDxULCBLIGV4dGVuZHMga2V5b2YgVD4oc2VsZWN0ZWRWYWx1ZXM6IFBhcnRpYWw8VD4sIGZpZWxkSWQ6IHN0cmluZywgcHJvcGVydHk6IEspOiB2b2lkIHtcblx0Y29uc3Qgb3B0aW9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MSW5wdXRFbGVtZW50PihgIyR7ZmllbGRJZH1gKTtcblx0aWYgKG9wdGlvbikge1xuXHRcdG9wdGlvbi52YWx1ZSA9IGdldFByb3BlcnR5KHNlbGVjdGVkVmFsdWVzLCBwcm9wZXJ0eSkgPz8gXCJcIjtcblx0XHRvcHRpb24uYWRkRXZlbnRMaXN0ZW5lcihcImlucHV0XCIsICgpID0+IHtcblx0XHRcdHNldFByb3BlcnR5KHNlbGVjdGVkVmFsdWVzLCBwcm9wZXJ0eSwgb3B0aW9uLnZhbHVlID09PSBcIlwiID8gdW5kZWZpbmVkIDogb3B0aW9uLnZhbHVlKTtcblx0XHRcdHVwZGF0ZVByZXZpZXcoKTtcblx0XHR9KTtcblx0fVxufVxuXG4vKipcbiAqIENvbm5lY3QgYSBjaGVja2JveC5cbiAqIEBwYXJhbSBzZWxlY3RlZFZhbHVlcyBUaGUgc2VsZWN0ZWQgdmFsdWVzLlxuICogQHBhcmFtIGZpZWxkSWQgVGhlIGZpZWxkIGlkLlxuICogQHBhcmFtIHByb3BlcnR5IFRoZSBwcm9wZXJ0eS5cbiAqIEBwYXJhbSBjaGFuZ2VkIFRoZSBjaGFuZ2VkIGV2ZW50IHRvIGNhbGwuXG4gKi9cbmZ1bmN0aW9uIGNvbm5lY3RDaGVja2JveDxULCBLIGV4dGVuZHMga2V5b2YgVD4oXG5cdHNlbGVjdGVkVmFsdWVzOiBQYXJ0aWFsPFQ+LFxuXHRmaWVsZElkOiBzdHJpbmcsXG5cdHByb3BlcnR5OiBLLFxuXHRjaGFuZ2VkPzogKCkgPT4gdm9pZFxuKTogdm9pZCB7XG5cdGNvbnN0IG9wdGlvbiA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTElucHV0RWxlbWVudD4oYCMke2ZpZWxkSWR9YCk7XG5cdGlmIChvcHRpb24pIHtcblx0XHRvcHRpb24uY2hlY2tlZCA9IGdldFByb3BlcnR5KHNlbGVjdGVkVmFsdWVzLCBwcm9wZXJ0eSk7XG5cdFx0b3B0aW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjaGFuZ2VcIiwgKCkgPT4ge1xuXHRcdFx0c2V0UHJvcGVydHkoc2VsZWN0ZWRWYWx1ZXMsIHByb3BlcnR5LCBvcHRpb24uY2hlY2tlZCk7XG5cdFx0XHRpZiAoY2hhbmdlZCkge1xuXHRcdFx0XHRjaGFuZ2VkKCk7XG5cdFx0XHR9XG5cdFx0XHR1cGRhdGVQcmV2aWV3KCk7XG5cdFx0fSk7XG5cdH1cbn1cblxuLyoqXG4gKiBDb25uZWN0IGEgcmFuZ2UuXG4gKiBAcGFyYW0gc2VsZWN0ZWRWYWx1ZXMgVGhlIHNlbGVjdGVkIHZhbHVlcy5cbiAqIEBwYXJhbSBmaWVsZElkIFRoZSBmaWVsZCBpZC5cbiAqIEBwYXJhbSBwcm9wZXJ0eSBUaGUgcHJvcGVydHkuXG4gKiBAcGFyYW0gY2hhbmdlZCBUaGUgY2hhbmdlZCBldmVudCB0byBjYWxsLlxuICovXG5mdW5jdGlvbiBjb25uZWN0UmFuZ2U8VCwgSyBleHRlbmRzIGtleW9mIFQ+KFxuXHRzZWxlY3RlZFZhbHVlczogUGFydGlhbDxUPixcblx0ZmllbGRJZDogc3RyaW5nLFxuXHRwcm9wZXJ0eTogSyxcblx0Y2hhbmdlZD86ICgpID0+IHZvaWRcbik6IHZvaWQge1xuXHRjb25zdCBvcHRpb24gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxJbnB1dEVsZW1lbnQ+KGAjJHtmaWVsZElkfWApO1xuXHRjb25zdCBvcHRpb25WYWx1ZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTElucHV0RWxlbWVudD4oYCMke2ZpZWxkSWR9VmFsdWVgKTtcblxuXHRpZiAob3B0aW9uICYmIG9wdGlvblZhbHVlKSB7XG5cdFx0b3B0aW9uLnZhbHVlQXNOdW1iZXIgPSBnZXRQcm9wZXJ0eShzZWxlY3RlZFZhbHVlcywgcHJvcGVydHkpO1xuXHRcdG9wdGlvblZhbHVlLnRleHRDb250ZW50ID0gZ2V0UHJvcGVydHkoc2VsZWN0ZWRWYWx1ZXMsIHByb3BlcnR5KTtcblx0XHRvcHRpb24uYWRkRXZlbnRMaXN0ZW5lcihcImlucHV0XCIsICgpID0+IHtcblx0XHRcdHNldFByb3BlcnR5KHNlbGVjdGVkVmFsdWVzLCBwcm9wZXJ0eSwgb3B0aW9uLnZhbHVlQXNOdW1iZXIpO1xuXHRcdFx0b3B0aW9uVmFsdWUudGV4dENvbnRlbnQgPSBvcHRpb24udmFsdWVBc051bWJlci50b1N0cmluZygpO1xuXHRcdFx0aWYgKGNoYW5nZWQpIHtcblx0XHRcdFx0Y2hhbmdlZCgpO1xuXHRcdFx0fVxuXHRcdFx0dXBkYXRlUHJldmlldygpO1xuXHRcdH0pO1xuXHR9XG59XG5cbi8qKlxuICogQ29ubmVjdCBhIGNvbG9yLlxuICogQHBhcmFtIHNlbGVjdGVkVmFsdWVzIFRoZSBzZWxlY3RlZCB2YWx1ZXMuXG4gKiBAcGFyYW0gZmllbGRJZCBUaGUgZmllbGQgaWQuXG4gKiBAcGFyYW0gcHJvcGVydHkgVGhlIHByb3BlcnR5LlxuICogQHBhcmFtIGNoYW5nZWQgVGhlIGNoYW5nZWQgZXZlbnQgdG8gY2FsbC5cbiAqL1xuZnVuY3Rpb24gY29ubmVjdENvbG9yPFQsIEsgZXh0ZW5kcyBrZXlvZiBUPihcblx0c2VsZWN0ZWRWYWx1ZXM6IFBhcnRpYWw8VD4sXG5cdGZpZWxkSWQ6IHN0cmluZyxcblx0cHJvcGVydHk6IEssXG5cdGNoYW5nZWQ/OiAoKSA9PiB2b2lkXG4pOiB2b2lkIHtcblx0Y29uc3Qgb3B0aW9uID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcjxIVE1MSW5wdXRFbGVtZW50PihgIyR7ZmllbGRJZH1gKTtcblx0Y29uc3Qgb3B0aW9uVmFsdWUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxJbnB1dEVsZW1lbnQ+KGAjJHtmaWVsZElkfVZhbHVlYCk7XG5cblx0aWYgKG9wdGlvbiAmJiBvcHRpb25WYWx1ZSkge1xuXHRcdG9wdGlvbi52YWx1ZSA9IGdldFByb3BlcnR5KHNlbGVjdGVkVmFsdWVzLCBwcm9wZXJ0eSk7XG5cdFx0b3B0aW9uVmFsdWUudGV4dENvbnRlbnQgPSBnZXRQcm9wZXJ0eShzZWxlY3RlZFZhbHVlcywgcHJvcGVydHkpO1xuXHRcdG9wdGlvbi5hZGRFdmVudExpc3RlbmVyKFwiaW5wdXRcIiwgKCkgPT4ge1xuXHRcdFx0c2V0UHJvcGVydHkoc2VsZWN0ZWRWYWx1ZXMsIHByb3BlcnR5LCBvcHRpb24udmFsdWUpO1xuXHRcdFx0b3B0aW9uVmFsdWUudGV4dENvbnRlbnQgPSBvcHRpb24udmFsdWU7XG5cdFx0XHRpZiAoY2hhbmdlZCkge1xuXHRcdFx0XHRjaGFuZ2VkKCk7XG5cdFx0XHR9XG5cdFx0XHR1cGRhdGVQcmV2aWV3KCk7XG5cdFx0fSk7XG5cdH1cbn1cblxuLyoqXG4gKiBGaW5hbGl6ZSB0aGUgd2luZG93IG9wdGlvbnMuXG4gKiBAcmV0dXJucyBUaGUgY29tcGxldGUgd2luZG93IG9wdGlvbnMuXG4gKi9cbmZ1bmN0aW9uIGZpbmFsaXplV2luZG93T3B0aW9ucygpOiBPcGVuRmluLldpbmRvd0NyZWF0aW9uT3B0aW9ucyB7XG5cdGNvbnN0IGZpbmFsV2luZG93T3B0aW9uczogT3BlbkZpbi5XaW5kb3dDcmVhdGlvbk9wdGlvbnMgPSB7XG5cdFx0bmFtZTogc2VsZWN0ZWRDb21tb25PcHRpb25zLm5hbWUsXG5cdFx0dXJsOiBzZWxlY3RlZENvbW1vbk9wdGlvbnMudXJsLFxuXHRcdGF1dG9TaG93OiBzZWxlY3RlZENvbW1vbk9wdGlvbnMuYXV0b1Nob3dcblx0fTtcblxuXHRmb3IgKGNvbnN0IHByb3Agb2YgT2JqZWN0LmtleXMoc2VsZWN0ZWRDb21tb25PcHRpb25zKSBhcyAoa2V5b2YgT3BlbkZpbi5XaW5kb3dDcmVhdGlvbk9wdGlvbnMpW10pIHtcblx0XHRpZiAoc2VsZWN0ZWRDb21tb25PcHRpb25zW3Byb3BdICE9PSBkZWZhdWx0Q29tbW9uT3B0aW9uc1twcm9wXSkge1xuXHRcdFx0ZmluYWxXaW5kb3dPcHRpb25zW3Byb3BdID0gc2VsZWN0ZWRDb21tb25PcHRpb25zW3Byb3BdO1xuXHRcdH1cblx0fVxuXG5cdGlmICghKHNlbGVjdGVkQ29tbW9uT3B0aW9ucy5mcmFtZSA/PyB0cnVlKSkge1xuXHRcdGZvciAoY29uc3QgcHJvcCBvZiBPYmplY3Qua2V5cyhzZWxlY3RlZEZyYW1lbGVzc09wdGlvbnMpIGFzIChrZXlvZiBPcGVuRmluLldpbmRvd0NyZWF0aW9uT3B0aW9ucylbXSkge1xuXHRcdFx0aWYgKHNlbGVjdGVkRnJhbWVsZXNzT3B0aW9uc1twcm9wXSAhPT0gZGVmYXVsdENvbW1vbk9wdGlvbnNbcHJvcF0pIHtcblx0XHRcdFx0ZmluYWxXaW5kb3dPcHRpb25zW3Byb3BdID0gc2VsZWN0ZWRGcmFtZWxlc3NPcHRpb25zW3Byb3BdO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGNvbnN0IGZpbmFsUmVnaW9uOiBPcGVuRmluLlJlc2l6ZVJlZ2lvbiA9IHt9O1xuXHRcdGlmIChzZWxlY3RlZFJlc2l6ZVJlZ2lvbi5ib3R0b21SaWdodENvcm5lciAhPT0gZGVmYXVsdFJlc2l6ZVJlZ2lvbi5ib3R0b21SaWdodENvcm5lcikge1xuXHRcdFx0ZmluYWxSZWdpb24uYm90dG9tUmlnaHRDb3JuZXIgPSBzZWxlY3RlZFJlc2l6ZVJlZ2lvbi5ib3R0b21SaWdodENvcm5lcjtcblx0XHR9XG5cdFx0aWYgKHNlbGVjdGVkUmVzaXplUmVnaW9uLnNpemUgIT09IGRlZmF1bHRSZXNpemVSZWdpb24uc2l6ZSkge1xuXHRcdFx0ZmluYWxSZWdpb24uc2l6ZSA9IHNlbGVjdGVkUmVzaXplUmVnaW9uLnNpemU7XG5cdFx0fVxuXHRcdGlmIChzZWxlY3RlZFJlc2l6ZVJlZ2lvbi5zaWRlcykge1xuXHRcdFx0ZmluYWxSZWdpb24uc2lkZXMgPSB7fTtcblx0XHRcdGlmIChzZWxlY3RlZFJlc2l6ZVJlZ2lvbi5zaWRlcz8uYm90dG9tICE9PSBkZWZhdWx0UmVzaXplUmVnaW9uLnNpZGVzPy5ib3R0b20pIHtcblx0XHRcdFx0ZmluYWxSZWdpb24uc2lkZXMuYm90dG9tID0gc2VsZWN0ZWRSZXNpemVSZWdpb24uc2lkZXM/LmJvdHRvbTtcblx0XHRcdH1cblx0XHRcdGlmIChzZWxlY3RlZFJlc2l6ZVJlZ2lvbi5zaWRlcz8ubGVmdCAhPT0gZGVmYXVsdFJlc2l6ZVJlZ2lvbi5zaWRlcz8ubGVmdCkge1xuXHRcdFx0XHRmaW5hbFJlZ2lvbi5zaWRlcy5sZWZ0ID0gc2VsZWN0ZWRSZXNpemVSZWdpb24uc2lkZXM/LmxlZnQ7XG5cdFx0XHR9XG5cdFx0XHRpZiAoc2VsZWN0ZWRSZXNpemVSZWdpb24uc2lkZXM/LnRvcCAhPT0gZGVmYXVsdFJlc2l6ZVJlZ2lvbi5zaWRlcz8udG9wKSB7XG5cdFx0XHRcdGZpbmFsUmVnaW9uLnNpZGVzLnRvcCA9IHNlbGVjdGVkUmVzaXplUmVnaW9uLnNpZGVzPy50b3A7XG5cdFx0XHR9XG5cdFx0XHRpZiAoc2VsZWN0ZWRSZXNpemVSZWdpb24uc2lkZXM/LnJpZ2h0ICE9PSBkZWZhdWx0UmVzaXplUmVnaW9uLnNpZGVzPy5yaWdodCkge1xuXHRcdFx0XHRmaW5hbFJlZ2lvbi5zaWRlcy5yaWdodCA9IHNlbGVjdGVkUmVzaXplUmVnaW9uLnNpZGVzPy5yaWdodDtcblx0XHRcdH1cblx0XHRcdGlmIChPYmplY3Qua2V5cyhmaW5hbFJlZ2lvbi5zaWRlcykubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRcdGRlbGV0ZSBmaW5hbFJlZ2lvbi5zaWRlcztcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoT2JqZWN0LmtleXMoZmluYWxSZWdpb24pLmxlbmd0aCA+IDApIHtcblx0XHRcdGZpbmFsV2luZG93T3B0aW9ucy5yZXNpemVSZWdpb24gPSBmaW5hbFJlZ2lvbjtcblx0XHR9XG5cblx0XHRmb3IgKGNvbnN0IHByb3Agb2YgT2JqZWN0LmtleXMoc2VsZWN0ZWRSZXNpemVSZWdpb25TaWRlcykgYXMgKGtleW9mIFJlc2l6ZVNpZGVzKVtdKSB7XG5cdFx0XHRpZiAoc2VsZWN0ZWRSZXNpemVSZWdpb25TaWRlc1twcm9wXSAhPT0gZGVmYXVsdFJlc2l6ZVJlZ2lvblNpZGVzW3Byb3BdKSB7XG5cdFx0XHRcdGZpbmFsV2luZG93T3B0aW9ucy5yZXNpemVSZWdpb24gPSBmaW5hbFdpbmRvd09wdGlvbnMucmVzaXplUmVnaW9uID8/IHt9O1xuXHRcdFx0XHRmaW5hbFdpbmRvd09wdGlvbnMucmVzaXplUmVnaW9uLnNpZGVzID0gZmluYWxXaW5kb3dPcHRpb25zLnJlc2l6ZVJlZ2lvbi5zaWRlcyA/PyB7fTtcblx0XHRcdFx0ZmluYWxXaW5kb3dPcHRpb25zLnJlc2l6ZVJlZ2lvbi5zaWRlc1twcm9wXSA9IHNlbGVjdGVkUmVzaXplUmVnaW9uU2lkZXNbcHJvcF07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Zm9yIChjb25zdCBwcm9wIG9mIE9iamVjdC5rZXlzKHNlbGVjdGVkQ29ybmVyUm91bmRpbmcpIGFzIChrZXlvZiBPcGVuRmluLkNvcm5lclJvdW5kaW5nKVtdKSB7XG5cdFx0XHRpZiAoc2VsZWN0ZWRDb3JuZXJSb3VuZGluZ1twcm9wXSAhPT0gZGVmYXVsdENvcm5lclJvdW5kaW5nW3Byb3BdKSB7XG5cdFx0XHRcdGZpbmFsV2luZG93T3B0aW9ucy5jb3JuZXJSb3VuZGluZyA9IGZpbmFsV2luZG93T3B0aW9ucy5jb3JuZXJSb3VuZGluZyA/PyB7fTtcblx0XHRcdFx0ZmluYWxXaW5kb3dPcHRpb25zLmNvcm5lclJvdW5kaW5nW3Byb3BdID0gc2VsZWN0ZWRDb3JuZXJSb3VuZGluZ1twcm9wXTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gZmluYWxXaW5kb3dPcHRpb25zO1xufVxuXG4vKipcbiAqIFVwZGF0ZSB0aGUgcHJldmlldy5cbiAqL1xuZnVuY3Rpb24gdXBkYXRlUHJldmlldygpOiB2b2lkIHtcblx0Y29uc3QgcHJldmlld0VsZW0gPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3ByZXZpZXdcIik7XG5cdGlmIChwcmV2aWV3RWxlbSkge1xuXHRcdHByZXZpZXdFbGVtLnRleHRDb250ZW50ID0gY3JlYXRlUHJldmlldygpO1xuXHR9XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgcHJldmlldy5cbiAqIEByZXR1cm5zIFRoZSBwcmV2aWV3IGNvZGUuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVByZXZpZXcoKTogc3RyaW5nIHtcblx0aWYgKHNlbGVjdGVkTGF1bmNoT3B0aW9ucy51c2VQbGF0Zm9ybSkge1xuXHRcdHJldHVybiBgY29uc3QgcGxhdGZvcm0gPSBmaW4uUGxhdGZvcm0uZ2V0Q3VycmVudFN5bmMoKTtcbmF3YWl0IHBsYXRmb3JtLmNyZWF0ZVdpbmRvdygke0pTT04uc3RyaW5naWZ5KGZpbmFsaXplV2luZG93T3B0aW9ucygpLCB1bmRlZmluZWQsIFwiICBcIil9KTtgO1xuXHR9XG5cdHJldHVybiBgYXdhaXQgZmluLldpbmRvdy5jcmVhdGUoJHtKU09OLnN0cmluZ2lmeShmaW5hbGl6ZVdpbmRvd09wdGlvbnMoKSwgdW5kZWZpbmVkLCBcIiAgXCIpfSk7YDtcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/dev/john/update-logging-example/use-window-options/manifest.fin.json b/dev/john/update-logging-example/use-window-options/manifest.fin.json new file mode 100644 index 00000000..884211f7 --- /dev/null +++ b/dev/john/update-logging-example/use-window-options/manifest.fin.json @@ -0,0 +1,19 @@ +{ + "runtime": { + "arguments": "--v=1 --inspect", + "version": "38.126.83.79" + }, + "startup_app": { + "name": "use-window-options", + "uuid": "use-window-options", + "description": "A guide to OpenFin Window Development", + "url": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-window-options/html/app.html", + "icon": "https://built-on-openfin.github.io/container-starter/dev/john/update-logging-example/use-window-options/favicon.ico", + "autoShow": true, + "defaultWidth": 1200, + "defaultHeight": 800, + "defaultCentered": true, + "minWidth": 800, + "minHeight": 400 + } +}