nHentai Helper

Download nHentai manga as compression file easily, and add some useful features. Also support some mirror sites.

// ==UserScript==
// @name               nHentai Helper
// @name:zh-CN         nHentai 助手
// @name:zh-TW         nHentai 助手
// @namespace          https://github.com/Tsuk1ko
// @version            3.13.0
// @author             Jindai Kirin
// @description        Download nHentai manga as compression file easily, and add some useful features. Also support some mirror sites.
// @description:zh-CN  为 nHentai 增加压缩打包下载方式以及一些辅助功能,同时还支持一些镜像站
// @description:zh-TW  爲 nHentai 增加壓縮打包下載方式以及一些輔助功能,同時還支援一些鏡像站
// @license            GPL-3.0
// @icon               https://icon.horse/icon/nhentai.net
// @homepageURL        https://github.com/Tsuk1ko/nhentai-helper
// @supportURL         https://github.com/Tsuk1ko/nhentai-helper/issues
// @include            /^https:\/\/([^/]*\.)?(nya|dog|cat|bug|qq|fox|ee|yy)hentai[0-9]*\./
// @match              https://nhentai.net/*
// @match              https://nhentai.xxx/*
// @match              https://nhentai.to/*
// @match              https://nhentai.website/*
// @require            https://unpkg.com/vue@3.4.22/dist/vue.global.prod.js
// @require            data:application/javascript,window.Vue%3DVue%3B
// @require            https://unpkg.com/element-plus@2.7.0/dist/index.full.min.js
// @require            https://unpkg.com/jquery@3.7.1/dist/jquery.slim.min.js
// @resource           element-plus-css  https://unpkg.com/element-plus@2.7.0/dist/index.css
// @connect            nhentai.net
// @connect            i.nhentai.net
// @connect            i2.nhentai.net
// @connect            i3.nhentai.net
// @connect            i5.nhentai.net
// @connect            i7.nhentai.net
// @connect            *
// @grant              GM_addStyle
// @grant              GM_getResourceText
// @grant              GM_getValue
// @grant              GM_openInTab
// @grant              GM_registerMenuCommand
// @grant              GM_setValue
// @grant              GM_xmlhttpRequest
// @grant              unsafeWindow
// @run-at             document-end
// @noframes
// ==/UserScript==

(t=>{if(typeof GM_addStyle=="function"){GM_addStyle(t);return}const o=document.createElement("style");o.textContent=t,document.head.append(o)})(' .nhentai-helper-btn:disabled{cursor:wait}.gallery>.nhentai-helper-btn{position:absolute;top:0;min-width:42px;opacity:.8}.gallery:hover>.nhentai-helper-btn{opacity:1}.gallery .download-zip-btn{left:0}.gallery .ignore-btn{display:none;right:0}.gallery:hover .ignore-btn{display:block}#page-container{position:relative}@media screen and (max-width: 768px){#page-container{padding-top:40px}}#online-view-mode-btn{position:absolute;right:0;top:0;margin:0}.btn-noty-green{background-color:#66bb6a!important}.btn-noty-blue{background-color:#42a5f5!important}.btn-noty:hover{filter:brightness(1.15)}.noty_buttons{padding-top:0!important}.pages-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-block;border-radius:3px;padding:0 .1em 0 1em;font-size:1em;width:100%;height:40px;border:0;vertical-align:top;margin-top:5px}.gallery.downloaded .caption{color:#999}.noty_close_button{display:none}.noty_layout_mixin,#noty_layout__top,#noty_layout__topLeft,#noty_layout__topCenter,#noty_layout__topRight,#noty_layout__bottom,#noty_layout__bottomLeft,#noty_layout__bottomCenter,#noty_layout__bottomRight,#noty_layout__center,#noty_layout__centerLeft,#noty_layout__centerRight{position:fixed;margin:0;padding:0;z-index:9999999;-webkit-transform:translateZ(0) scale(1,1);transform:translateZ(0) scale(1);-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-font-smoothing:subpixel-antialiased;filter:blur(0);-webkit-filter:blur(0);max-width:90%}#noty_layout__top{top:0;left:5%;width:90%}#noty_layout__topLeft{top:20px;left:20px;width:325px}#noty_layout__topCenter{top:5%;left:50%;width:325px;-webkit-transform:translate(-webkit-calc(-50% - .5px)) translateZ(0) scale(1,1);transform:translate(calc(-50% - .5px)) translateZ(0) scale(1)}#noty_layout__topRight{top:20px;right:20px;width:325px}#noty_layout__bottom{bottom:0;left:5%;width:90%}#noty_layout__bottomLeft{bottom:20px;left:20px;width:325px}#noty_layout__bottomCenter{bottom:5%;left:50%;width:325px;-webkit-transform:translate(-webkit-calc(-50% - .5px)) translateZ(0) scale(1,1);transform:translate(calc(-50% - .5px)) translateZ(0) scale(1)}#noty_layout__bottomRight{bottom:20px;right:20px;width:325px}#noty_layout__center{top:50%;left:50%;width:325px;-webkit-transform:translate(-webkit-calc(-50% - .5px),-webkit-calc(-50% - .5px)) translateZ(0) scale(1,1);transform:translate(calc(-50% - .5px),calc(-50% - .5px)) translateZ(0) scale(1)}#noty_layout__centerLeft{top:50%;left:20px;width:325px;-webkit-transform:translate(0,-webkit-calc(-50% - .5px)) translateZ(0) scale(1,1);transform:translateY(calc(-50% - .5px)) translateZ(0) scale(1)}#noty_layout__centerRight{top:50%;right:20px;width:325px;-webkit-transform:translate(0,-webkit-calc(-50% - .5px)) translateZ(0) scale(1,1);transform:translateY(calc(-50% - .5px)) translateZ(0) scale(1)}.noty_progressbar{display:none}.noty_has_timeout.noty_has_progressbar .noty_progressbar{display:block;position:absolute;left:0;bottom:0;height:3px;width:100%;background-color:#646464;opacity:.2;filter:alpha(opacity=10)}.noty_bar{-webkit-backface-visibility:hidden;-webkit-transform:translate(0,0) translateZ(0) scale(1,1);-ms-transform:translate(0,0) scale(1,1);transform:translate(0) scale(1);-webkit-font-smoothing:subpixel-antialiased;overflow:hidden}.noty_effects_open{opacity:0;-webkit-transform:translate(50%);-ms-transform:translate(50%);transform:translate(50%);-webkit-animation:noty_anim_in .5s cubic-bezier(.68,-.55,.265,1.55);animation:noty_anim_in .5s cubic-bezier(.68,-.55,.265,1.55);-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.noty_effects_close{-webkit-animation:noty_anim_out .5s cubic-bezier(.68,-.55,.265,1.55);animation:noty_anim_out .5s cubic-bezier(.68,-.55,.265,1.55);-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.noty_fix_effects_height{-webkit-animation:noty_anim_height 75ms ease-out;animation:noty_anim_height 75ms ease-out}.noty_close_with_click{cursor:pointer}.noty_close_button{position:absolute;top:2px;right:2px;font-weight:700;width:20px;height:20px;text-align:center;line-height:20px;background-color:#0000000d;border-radius:2px;cursor:pointer;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.noty_close_button:hover{background-color:#0000001a}.noty_modal{position:fixed;width:100%;height:100%;background-color:#000;z-index:10000;opacity:.3;left:0;top:0}.noty_modal.noty_modal_open{opacity:0;-webkit-animation:noty_modal_in .3s ease-out;animation:noty_modal_in .3s ease-out}.noty_modal.noty_modal_close{-webkit-animation:noty_modal_out .3s ease-out;animation:noty_modal_out .3s ease-out;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes noty_modal_in{to{opacity:.3}}@keyframes noty_modal_in{to{opacity:.3}}@-webkit-keyframes noty_modal_out{to{opacity:0}}@keyframes noty_modal_out{to{opacity:0}}@-webkit-keyframes noty_anim_in{to{-webkit-transform:translate(0);transform:translate(0);opacity:1}}@keyframes noty_anim_in{to{-webkit-transform:translate(0);transform:translate(0);opacity:1}}@-webkit-keyframes noty_anim_out{to{-webkit-transform:translate(50%);transform:translate(50%);opacity:0}}@keyframes noty_anim_out{to{-webkit-transform:translate(50%);transform:translate(50%);opacity:0}}@-webkit-keyframes noty_anim_height{to{height:0}}@keyframes noty_anim_height{to{height:0}}.noty_theme__relax.noty_bar{margin:4px 0;overflow:hidden;border-radius:2px;position:relative}.noty_theme__relax.noty_bar .noty_body{padding:10px}.noty_theme__relax.noty_bar .noty_buttons{border-top:1px solid #e7e7e7;padding:5px 10px}.noty_theme__relax.noty_type__alert,.noty_theme__relax.noty_type__notification{background-color:#fff;border:1px solid #dedede;color:#444}.noty_theme__relax.noty_type__warning{background-color:#ffeaa8;border:1px solid #FFC237;color:#826200}.noty_theme__relax.noty_type__warning .noty_buttons{border-color:#dfaa30}.noty_theme__relax.noty_type__error{background-color:#ff8181;border:1px solid #e25353;color:#fff}.noty_theme__relax.noty_type__error .noty_buttons{border-color:#8b0000}.noty_theme__relax.noty_type__info,.noty_theme__relax.noty_type__information{background-color:#78c5e7;border:1px solid #3badd6;color:#fff}.noty_theme__relax.noty_type__info .noty_buttons,.noty_theme__relax.noty_type__information .noty_buttons{border-color:#0b90c4}.noty_theme__relax.noty_type__success{background-color:#bcf5bc;border:1px solid #7cdd77;color:#006400}.noty_theme__relax.noty_type__success .noty_buttons{border-color:#50c24e}.noty_theme__metroui.noty_bar{margin:4px 0;overflow:hidden;position:relative;box-shadow:#0000004c 0 0 5px}.noty_theme__metroui.noty_bar .noty_progressbar{position:absolute;left:0;bottom:0;height:3px;width:100%;background-color:#000;opacity:.2;filter:alpha(opacity=20)}.noty_theme__metroui.noty_bar .noty_body{padding:1.25em;font-size:14px}.noty_theme__metroui.noty_bar .noty_buttons{padding:0 10px .5em}.noty_theme__metroui.noty_type__alert,.noty_theme__metroui.noty_type__notification{background-color:#fff;color:#1d1d1d}.noty_theme__metroui.noty_type__warning{background-color:#fa6800;color:#fff}.noty_theme__metroui.noty_type__error{background-color:#ce352c;color:#fff}.noty_theme__metroui.noty_type__info,.noty_theme__metroui.noty_type__information{background-color:#1ba1e2;color:#fff}.noty_theme__metroui.noty_type__success{background-color:#60a917;color:#fff}.noty_theme__mint.noty_bar{margin:4px 0;overflow:hidden;border-radius:2px;position:relative}.noty_theme__mint.noty_bar .noty_body{padding:10px;font-size:14px}.noty_theme__mint.noty_bar .noty_buttons{padding:10px}.noty_theme__mint.noty_type__alert,.noty_theme__mint.noty_type__notification{background-color:#fff;border-bottom:1px solid #D1D1D1;color:#2f2f2f}.noty_theme__mint.noty_type__warning{background-color:#ffae42;border-bottom:1px solid #E89F3C;color:#fff}.noty_theme__mint.noty_type__error{background-color:#de636f;border-bottom:1px solid #CA5A65;color:#fff}.noty_theme__mint.noty_type__info,.noty_theme__mint.noty_type__information{background-color:#7f7eff;border-bottom:1px solid #7473E8;color:#fff}.noty_theme__mint.noty_type__success{background-color:#afc765;border-bottom:1px solid #A0B55C;color:#fff}.noty_theme__sunset.noty_bar{margin:4px 0;overflow:hidden;border-radius:2px;position:relative}.noty_theme__sunset.noty_bar .noty_body{padding:10px;font-size:14px;text-shadow:1px 1px 1px rgba(0,0,0,.1)}.noty_theme__sunset.noty_bar .noty_buttons{padding:10px}.noty_theme__sunset.noty_type__alert,.noty_theme__sunset.noty_type__notification{background-color:#073b4c;color:#fff}.noty_theme__sunset.noty_type__alert .noty_progressbar,.noty_theme__sunset.noty_type__notification .noty_progressbar{background-color:#fff}.noty_theme__sunset.noty_type__warning{background-color:#ffd166;color:#fff}.noty_theme__sunset.noty_type__error{background-color:#ef476f;color:#fff}.noty_theme__sunset.noty_type__error .noty_progressbar{opacity:.4}.noty_theme__sunset.noty_type__info,.noty_theme__sunset.noty_type__information{background-color:#118ab2;color:#fff}.noty_theme__sunset.noty_type__info .noty_progressbar,.noty_theme__sunset.noty_type__information .noty_progressbar{opacity:.6}.noty_theme__sunset.noty_type__success{background-color:#06d6a0;color:#fff}.noty_theme__bootstrap-v3.noty_bar{margin:4px 0;overflow:hidden;position:relative;border:1px solid transparent;border-radius:4px}.noty_theme__bootstrap-v3.noty_bar .noty_body{padding:15px}.noty_theme__bootstrap-v3.noty_bar .noty_buttons{padding:10px}.noty_theme__bootstrap-v3.noty_bar .noty_close_button{font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2;background:transparent}.noty_theme__bootstrap-v3.noty_bar .noty_close_button:hover{background:transparent;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}.noty_theme__bootstrap-v3.noty_type__alert,.noty_theme__bootstrap-v3.noty_type__notification{background-color:#fff;color:inherit}.noty_theme__bootstrap-v3.noty_type__warning{background-color:#fcf8e3;color:#8a6d3b;border-color:#faebcc}.noty_theme__bootstrap-v3.noty_type__error{background-color:#f2dede;color:#a94442;border-color:#ebccd1}.noty_theme__bootstrap-v3.noty_type__info,.noty_theme__bootstrap-v3.noty_type__information{background-color:#d9edf7;color:#31708f;border-color:#bce8f1}.noty_theme__bootstrap-v3.noty_type__success{background-color:#dff0d8;color:#3c763d;border-color:#d6e9c6}.noty_theme__bootstrap-v4.noty_bar{margin:4px 0;overflow:hidden;position:relative;border:1px solid transparent;border-radius:.25rem}.noty_theme__bootstrap-v4.noty_bar .noty_body{padding:.75rem 1.25rem}.noty_theme__bootstrap-v4.noty_bar .noty_buttons{padding:10px}.noty_theme__bootstrap-v4.noty_bar .noty_close_button{font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.5;background:transparent}.noty_theme__bootstrap-v4.noty_bar .noty_close_button:hover{background:transparent;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.75}.noty_theme__bootstrap-v4.noty_type__alert,.noty_theme__bootstrap-v4.noty_type__notification{background-color:#fff;color:inherit}.noty_theme__bootstrap-v4.noty_type__warning{background-color:#fcf8e3;color:#8a6d3b;border-color:#faebcc}.noty_theme__bootstrap-v4.noty_type__error{background-color:#f2dede;color:#a94442;border-color:#ebccd1}.noty_theme__bootstrap-v4.noty_type__info,.noty_theme__bootstrap-v4.noty_type__information{background-color:#d9edf7;color:#31708f;border-color:#bce8f1}.noty_theme__bootstrap-v4.noty_type__success{background-color:#dff0d8;color:#3c763d;border-color:#d6e9c6}.noty_theme__semanticui.noty_bar{margin:4px 0;overflow:hidden;position:relative;border:1px solid transparent;font-size:1em;border-radius:.28571429rem;box-shadow:0 0 0 1px #22242638 inset,0 0 0 0 transparent}.noty_theme__semanticui.noty_bar .noty_body{padding:1em 1.5em;line-height:1.4285em}.noty_theme__semanticui.noty_bar .noty_buttons{padding:10px}.noty_theme__semanticui.noty_type__alert,.noty_theme__semanticui.noty_type__notification{background-color:#f8f8f9;color:#000000de}.noty_theme__semanticui.noty_type__warning{background-color:#fffaf3;color:#573a08;box-shadow:0 0 0 1px #c9ba9b inset,0 0 0 0 transparent}.noty_theme__semanticui.noty_type__error{background-color:#fff6f6;color:#9f3a38;box-shadow:0 0 0 1px #e0b4b4 inset,0 0 0 0 transparent}.noty_theme__semanticui.noty_type__info,.noty_theme__semanticui.noty_type__information{background-color:#f8ffff;color:#276f86;box-shadow:0 0 0 1px #a9d5de inset,0 0 0 0 transparent}.noty_theme__semanticui.noty_type__success{background-color:#fcfff5;color:#2c662d;box-shadow:0 0 0 1px #a3c293 inset,0 0 0 0 transparent}.noty_theme__nest.noty_bar{margin:0 0 15px;overflow:hidden;border-radius:2px;position:relative;box-shadow:#00000019 5px 4px 10px}.noty_theme__nest.noty_bar .noty_body{padding:10px;font-size:14px;text-shadow:1px 1px 1px rgba(0,0,0,.1)}.noty_theme__nest.noty_bar .noty_buttons{padding:10px}.noty_layout .noty_theme__nest.noty_bar{z-index:5}.noty_layout .noty_theme__nest.noty_bar:nth-child(2){position:absolute;top:0;margin-top:4px;margin-right:-4px;margin-left:4px;z-index:4;width:100%}.noty_layout .noty_theme__nest.noty_bar:nth-child(3){position:absolute;top:0;margin-top:8px;margin-right:-8px;margin-left:8px;z-index:3;width:100%}.noty_layout .noty_theme__nest.noty_bar:nth-child(4){position:absolute;top:0;margin-top:12px;margin-right:-12px;margin-left:12px;z-index:2;width:100%}.noty_layout .noty_theme__nest.noty_bar:nth-child(5){position:absolute;top:0;margin-top:16px;margin-right:-16px;margin-left:16px;z-index:1;width:100%}.noty_layout .noty_theme__nest.noty_bar:nth-child(n+6){position:absolute;top:0;margin-top:20px;margin-right:-20px;margin-left:20px;z-index:-1;width:100%}#noty_layout__bottomLeft .noty_theme__nest.noty_bar:nth-child(2),#noty_layout__topLeft .noty_theme__nest.noty_bar:nth-child(2){margin-top:4px;margin-left:-4px;margin-right:4px}#noty_layout__bottomLeft .noty_theme__nest.noty_bar:nth-child(3),#noty_layout__topLeft .noty_theme__nest.noty_bar:nth-child(3){margin-top:8px;margin-left:-8px;margin-right:8px}#noty_layout__bottomLeft .noty_theme__nest.noty_bar:nth-child(4),#noty_layout__topLeft .noty_theme__nest.noty_bar:nth-child(4){margin-top:12px;margin-left:-12px;margin-right:12px}#noty_layout__bottomLeft .noty_theme__nest.noty_bar:nth-child(5),#noty_layout__topLeft .noty_theme__nest.noty_bar:nth-child(5){margin-top:16px;margin-left:-16px;margin-right:16px}#noty_layout__bottomLeft .noty_theme__nest.noty_bar:nth-child(n+6),#noty_layout__topLeft .noty_theme__nest.noty_bar:nth-child(n+6){margin-top:20px;margin-left:-20px;margin-right:20px}.noty_theme__nest.noty_type__alert,.noty_theme__nest.noty_type__notification{background-color:#073b4c;color:#fff}.noty_theme__nest.noty_type__alert .noty_progressbar,.noty_theme__nest.noty_type__notification .noty_progressbar{background-color:#fff}.noty_theme__nest.noty_type__warning{background-color:#ffd166;color:#fff}.noty_theme__nest.noty_type__error{background-color:#ef476f;color:#fff}.noty_theme__nest.noty_type__error .noty_progressbar{opacity:.4}.noty_theme__nest.noty_type__info,.noty_theme__nest.noty_type__information{background-color:#118ab2;color:#fff}.noty_theme__nest.noty_type__info .noty_progressbar,.noty_theme__nest.noty_type__information .noty_progressbar{opacity:.6}.noty_theme__nest.noty_type__success{background-color:#06d6a0;color:#fff}.noty_theme__light.noty_bar{margin:4px 0;overflow:hidden;border-radius:2px;position:relative}.noty_theme__light.noty_bar .noty_body{padding:10px}.noty_theme__light.noty_bar .noty_buttons{border-top:1px solid #e7e7e7;padding:5px 10px}.noty_theme__light.noty_type__alert,.noty_theme__light.noty_type__notification{background-color:#fff;border:1px solid #dedede;color:#444}.noty_theme__light.noty_type__warning{background-color:#ffeaa8;border:1px solid #FFC237;color:#826200}.noty_theme__light.noty_type__warning .noty_buttons{border-color:#dfaa30}.noty_theme__light.noty_type__error{background-color:#ed7000;border:1px solid #e25353;color:#fff}.noty_theme__light.noty_type__error .noty_buttons{border-color:#8b0000}.noty_theme__light.noty_type__info,.noty_theme__light.noty_type__information{background-color:#78c5e7;border:1px solid #3badd6;color:#fff}.noty_theme__light.noty_type__info .noty_buttons,.noty_theme__light.noty_type__information .noty_buttons{border-color:#0b90c4}.noty_theme__light.noty_type__success{background-color:#57c880;border:1px solid #7cdd77;color:#006400}.noty_theme__light.noty_type__success .noty_buttons{border-color:#50c24e}.download-item[data-v-83b954f2]{position:relative;white-space:nowrap;padding:2px;overflow:visible}.download-item--can-cancel[data-v-83b954f2]:hover{width:calc(100% - 30px)}.download-item__cancel[data-v-83b954f2]{cursor:pointer;position:absolute;top:0;right:-30px;color:#f44336;font-size:20px;line-height:30px;width:30px}.download-item__title[data-v-83b954f2]{overflow:hidden;text-overflow:ellipsis;text-align:left}.download-item__progress[data-v-83b954f2]{background-color:#0000ff80;line-height:10px}.download-item--error .download-item__progress[data-v-83b954f2]{background-color:#ff000080}.download-item--compressing .download-item__progress[data-v-83b954f2]{background-color:#00ff0080}.download-item__progress-text[data-v-83b954f2]{transform:scale(.8)}#download-panel[data-v-f37e74c3]{overflow-x:hidden;position:fixed;top:20vh;right:0;width:calc(50vw - 620px);max-width:300px;min-width:150px;max-height:60vh;background-color:#000000b3;z-index:100;font-size:12px;overflow-y:scroll}#download-panel[data-v-f37e74c3]::-webkit-scrollbar{width:6px;background-color:#000000b3}#download-panel[data-v-f37e74c3]::-webkit-scrollbar-thumb{background-color:#fff9}.nhentai-helper-setting-help-buttons[data-v-35ed07a0]{float:left;position:absolute}.inline-item[data-v-35ed07a0]{display:inline-block}.inline-item[data-v-35ed07a0]:not(:last-of-type){margin-right:8px}.inline-item__name[data-v-35ed07a0]{margin-right:4px;-webkit-user-select:none;user-select:none}#nhentai-helper-setting-dialog .asterisk-example:before{content:"*";color:var(--el-color-danger);margin-right:4px}#nhentai-helper-setting-dialog label{font-weight:unset}#nhentai-helper-setting-dialog input:not([type=file]):not([type=checkbox]){background:inherit;color:var(--el-input-text-color, var(--el-text-color-regular))}#nhentai-helper-setting-dialog .el-input.is-disabled .el-input__inner{color:var(--el-disabled-text-color)}#nhentai-helper-setting-dialog .el-slider__stop{border:solid 1px var(--el-slider-runway-bg-color)}#nhentai-helper-setting-dialog .el-form-item:last-of-type{margin-bottom:0}#nhentai-helper-setting-dialog .el-form-item.refresh-required>.el-form-item__label-wrap>.el-form-item__label:after{content:"*";color:var(--el-color-danger);margin-left:4px}#nhentai-helper-setting-dialog .el-divider__text{color:var(--el-text-color-secondary);-webkit-user-select:none;user-select:none}#nhentai-helper-setting-dialog .m-l-16{margin-left:16px}#nhentai-helper-setting-dialog .m-b-32{margin-bottom:32px}#nhentai-helper-setting-dialog .no-sl,#nhentai-helper-setting-dialog .el-form-item__label{-webkit-user-select:none;user-select:none}#nhentai-helper-setting-dialog .el-table .el-input__prefix,#nhentai-helper-setting-dialog .el-table .el-input__suffix{line-height:30px}#nhentai-helper-setting-dialog .el-table__empty-block{display:none}.el-select-dropdown{-webkit-user-select:none;user-select:none}.language-filter[data-v-73f7b9fb]{padding-left:10px}.filter-select[data-v-73f7b9fb]{width:140px;margin-right:-140px}.filter-select[data-v-73f7b9fb] .el-input__inner{color:var(--el-input-text-color, var(--el-text-color-regular))!important;background:0 0!important}@media screen and (max-width: 644px){.language-filter[data-v-73f7b9fb]{padding:10px 0}.filter-select[data-v-73f7b9fb]{margin-right:0}} ');

(function ($, vue, elementPlus) {
  'use strict';

  var __defProp = Object.defineProperty;
  var __getOwnPropNames = Object.getOwnPropertyNames;
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  var __commonJS = (cb, mod) => function __require() {
    return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
  };
  var __publicField = (obj, key, value) => {
    __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
    return value;
  };
  var require_main_001 = __commonJS({
    "main-hERSRxmG.js"(exports, module) {
      var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
      var _GM_openInTab = /* @__PURE__ */ (() => typeof GM_openInTab != "undefined" ? GM_openInTab : void 0)();
      var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
      var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
      var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
      var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
      var _monkeyWindow = /* @__PURE__ */ (() => window)();
      const WORKER_THREAD_NUM = Math.max(navigator.hardwareConcurrency - 1, 1);
      const { pathname, host } = location;
      const IS_PAGE_MANGA_DETAIL = /^\/g\/[0-9]+\/?(\?.*)?$/.test(pathname);
      const IS_PAGE_ONLINE_VIEW = /^\/g\/[0-9]+(\/list)?\/[0-9]+\/?(\?.*)?$/.test(pathname);
      const IS_PAGE_MANGA_LIST = !IS_PAGE_MANGA_DETAIL && !IS_PAGE_ONLINE_VIEW && document.getElementsByClassName("gallery").length > 0;
      const IS_NHENTAI = host === "nhentai.net";
      const IS_NHENTAI_TO = host === "nhentai.to" || host === "nhentai.website";
      const MEDIA_URL_TEMPLATE_KEY = `media_url_template_${host}`;
      const isNodeOrElement = typeof Node === "function" ? (val) => val instanceof Node : (val) => val && typeof val === "object" && typeof val.nodeType === "number" && typeof val.nodeName === "string";
      if (IS_NHENTAI) {
        if (_GM_getValue("prevent_console_clear", false) || localStorage.getItem("NHENTAI_HELPER_DEBUG")) {
          const c = _unsafeWindow.console;
          c._clear = c.clear;
          c.clear = () => {
          };
          c._log = c.log;
          c.log = (...args) => {
            if (args.length === 1 && isNodeOrElement(args[0]))
              return;
            c._log(...args);
          };
        }
      }
      const logger = {
        log: (...args) => {
          console.log("[nhentai-helper]", ...args);
        },
        warn: (...args) => {
          console.warn("[nhentai-helper]", ...args);
        },
        error: (...args) => {
          console.error("[nhentai-helper]", ...args);
        }
      };
      /*!
       * Copyright 2012, Chris Wanstrath
       * Released under the MIT License
       * https://github.com/defunkt/jquery-pjax
       */
      (function($2) {
        function fnPjax(selector, container, options) {
          options = optionsFor(container, options);
          return this.on("click.pjax", selector, function(event) {
            var opts = options;
            if (!opts.container) {
              opts = $2.extend({}, options);
              opts.container = $2(this).attr("data-pjax");
            }
            handleClick(event, opts);
          });
        }
        function handleClick(event, container, options) {
          options = optionsFor(container, options);
          var link = event.currentTarget;
          var $link = $2(link);
          if (link.tagName.toUpperCase() !== "A")
            throw "$.fn.pjax or $.pjax.click requires an anchor element";
          if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
            return;
          if (location.protocol !== link.protocol || location.hostname !== link.hostname)
            return;
          if (link.href.indexOf("#") > -1 && stripHash(link) == stripHash(location))
            return;
          if (event.isDefaultPrevented())
            return;
          var defaults = {
            url: link.href,
            container: $link.attr("data-pjax"),
            target: link
          };
          var opts = $2.extend({}, defaults, options);
          var clickEvent = $2.Event("pjax:click");
          $link.trigger(clickEvent, [opts]);
          if (!clickEvent.isDefaultPrevented()) {
            pjax(opts);
            event.preventDefault();
            $link.trigger("pjax:clicked", [opts]);
          }
        }
        function handleSubmit(event, container, options) {
          options = optionsFor(container, options);
          var form = event.currentTarget;
          var $form = $2(form);
          if (form.tagName.toUpperCase() !== "FORM")
            throw "$.pjax.submit requires a form element";
          var defaults = {
            type: ($form.attr("method") || "GET").toUpperCase(),
            url: $form.attr("action"),
            container: $form.attr("data-pjax"),
            target: form
          };
          if (defaults.type !== "GET" && window.FormData !== void 0) {
            defaults.data = new FormData(form);
            defaults.processData = false;
            defaults.contentType = false;
          } else {
            if ($form.find(":file").length) {
              return;
            }
            defaults.data = $form.serializeArray();
          }
          pjax($2.extend({}, defaults, options));
          event.preventDefault();
        }
        function pjax(options) {
          options = $2.extend(true, {}, $2.ajaxSettings, pjax.defaults, options);
          if ($2.isFunction(options.url)) {
            options.url = options.url();
          }
          var hash = parseURL(options.url).hash;
          var containerType = $2.type(options.container);
          if (containerType !== "string") {
            throw "expected string value for 'container' option; got " + containerType;
          }
          var context = options.context = $2(options.container);
          if (!context.length) {
            throw "the container selector '" + options.container + "' did not match anything";
          }
          if (!options.data)
            options.data = {};
          if ($2.isArray(options.data)) {
            options.data.push({ name: "_pjax", value: options.container });
          } else {
            options.data._pjax = options.container;
          }
          function fire(type, args, props) {
            if (!props)
              props = {};
            props.relatedTarget = options.target;
            var event = $2.Event(type, props);
            context.trigger(event, args);
            return !event.isDefaultPrevented();
          }
          var timeoutTimer;
          options.beforeSend = function(xhr2, settings2) {
            if (settings2.type !== "GET") {
              settings2.timeout = 0;
            }
            xhr2.setRequestHeader("X-PJAX", "true");
            xhr2.setRequestHeader("X-PJAX-Container", options.container);
            if (!fire("pjax:beforeSend", [xhr2, settings2]))
              return false;
            if (settings2.timeout > 0) {
              timeoutTimer = setTimeout(function() {
                if (fire("pjax:timeout", [xhr2, options]))
                  xhr2.abort("timeout");
              }, settings2.timeout);
              settings2.timeout = 0;
            }
            var url = parseURL(settings2.url);
            if (hash)
              url.hash = hash;
            options.requestUrl = stripInternalParams(url);
          };
          options.complete = function(xhr2, textStatus) {
            if (timeoutTimer)
              clearTimeout(timeoutTimer);
            fire("pjax:complete", [xhr2, textStatus, options]);
            fire("pjax:end", [xhr2, options]);
          };
          options.error = function(xhr2, textStatus, errorThrown) {
            var container = extractContainer("", xhr2, options);
            var allowed = fire("pjax:error", [xhr2, textStatus, errorThrown, options]);
            if (options.type == "GET" && textStatus !== "abort" && allowed) {
              locationReplace(container.url);
            }
          };
          options.success = function(data, status, xhr2) {
            var previousState = pjax.state;
            var currentVersion = typeof $2.pjax.defaults.version === "function" ? $2.pjax.defaults.version() : $2.pjax.defaults.version;
            var latestVersion = xhr2.getResponseHeader("X-PJAX-Version");
            var container = extractContainer(data, xhr2, options);
            var url = parseURL(container.url);
            if (hash) {
              url.hash = hash;
              container.url = url.href;
            }
            if (currentVersion && latestVersion && currentVersion !== latestVersion) {
              locationReplace(container.url);
              return;
            }
            if (!container.contents) {
              locationReplace(container.url);
              return;
            }
            pjax.state = {
              id: options.id || uniqueId(),
              url: container.url,
              title: container.title,
              container: options.container,
              fragment: options.fragment,
              timeout: options.timeout
            };
            if (options.push || options.replace) {
              window.history.replaceState(pjax.state, container.title, container.url);
            }
            var blurFocus = $2.contains(context, document.activeElement);
            if (blurFocus) {
              try {
                document.activeElement.blur();
              } catch (e) {
              }
            }
            if (container.title)
              document.title = container.title;
            fire("pjax:beforeReplace", [container.contents, options], {
              state: pjax.state,
              previousState
            });
            context.html(container.contents);
            var autofocusEl = context.find("input[autofocus], textarea[autofocus]").last()[0];
            if (autofocusEl && document.activeElement !== autofocusEl) {
              autofocusEl.focus();
            }
            executeScriptTags(container.scripts);
            var scrollTo = options.scrollTo;
            if (hash) {
              var name = decodeURIComponent(hash.slice(1));
              var target = document.getElementById(name) || document.getElementsByName(name)[0];
              if (target)
                scrollTo = $2(target).offset().top;
            }
            if (typeof scrollTo == "number")
              $2(window).scrollTop(scrollTo);
            fire("pjax:success", [data, status, xhr2, options]);
          };
          if (!pjax.state) {
            pjax.state = {
              id: uniqueId(),
              url: window.location.href,
              title: document.title,
              container: options.container,
              fragment: options.fragment,
              timeout: options.timeout
            };
            window.history.replaceState(pjax.state, document.title);
          }
          abortXHR(pjax.xhr);
          pjax.options = options;
          var xhr = pjax.xhr = $2.ajax(options);
          if (xhr.readyState > 0) {
            if (options.push && !options.replace) {
              cachePush(pjax.state.id, [options.container, cloneContents(context)]);
              window.history.pushState(null, "", options.requestUrl);
            }
            fire("pjax:start", [xhr, options]);
            fire("pjax:send", [xhr, options]);
          }
          return pjax.xhr;
        }
        function pjaxReload(container, options) {
          var defaults = {
            url: window.location.href,
            push: false,
            replace: true,
            scrollTo: false
          };
          return pjax($2.extend(defaults, optionsFor(container, options)));
        }
        function locationReplace(url) {
          window.history.replaceState(null, "", pjax.state.url);
          window.location.replace(url);
        }
        var initialPop = true;
        var initialURL = window.location.href;
        var initialState = window.history.state;
        if (initialState && initialState.container) {
          pjax.state = initialState;
        }
        if ("state" in window.history) {
          initialPop = false;
        }
        function onPjaxPopstate(event) {
          if (!initialPop) {
            abortXHR(pjax.xhr);
          }
          var previousState = pjax.state;
          var state = event.state;
          var direction;
          if (state && state.container) {
            if (initialPop && initialURL == state.url)
              return;
            if (previousState) {
              if (previousState.id === state.id)
                return;
              direction = previousState.id < state.id ? "forward" : "back";
            }
            var cache2 = cacheMapping[state.id] || [];
            var containerSelector = cache2[0] || state.container;
            var container = $2(containerSelector), contents = cache2[1];
            if (container.length) {
              if (previousState) {
                cachePop(direction, previousState.id, [containerSelector, cloneContents(container)]);
              }
              var popstateEvent = $2.Event("pjax:popstate", {
                state,
                direction
              });
              container.trigger(popstateEvent);
              var options = {
                id: state.id,
                url: state.url,
                container: containerSelector,
                push: false,
                fragment: state.fragment,
                timeout: state.timeout,
                scrollTo: false
              };
              if (contents) {
                container.trigger("pjax:start", [null, options]);
                pjax.state = state;
                if (state.title)
                  document.title = state.title;
                var beforeReplaceEvent = $2.Event("pjax:beforeReplace", {
                  state,
                  previousState
                });
                container.trigger(beforeReplaceEvent, [contents, options]);
                container.html(contents);
                container.trigger("pjax:end", [null, options]);
              } else {
                pjax(options);
              }
              container[0].offsetHeight;
            } else {
              locationReplace(location.href);
            }
          }
          initialPop = false;
        }
        function fallbackPjax(options) {
          var url = $2.isFunction(options.url) ? options.url() : options.url, method = options.type ? options.type.toUpperCase() : "GET";
          var form = $2("<form>", {
            method: method === "GET" ? "GET" : "POST",
            action: url,
            style: "display:none"
          });
          if (method !== "GET" && method !== "POST") {
            form.append($2("<input>", {
              type: "hidden",
              name: "_method",
              value: method.toLowerCase()
            }));
          }
          var data = options.data;
          if (typeof data === "string") {
            $2.each(data.split("&"), function(index, value) {
              var pair = value.split("=");
              form.append($2("<input>", { type: "hidden", name: pair[0], value: pair[1] }));
            });
          } else if ($2.isArray(data)) {
            $2.each(data, function(index, value) {
              form.append($2("<input>", { type: "hidden", name: value.name, value: value.value }));
            });
          } else if (typeof data === "object") {
            var key;
            for (key in data)
              form.append($2("<input>", { type: "hidden", name: key, value: data[key] }));
          }
          $2(document.body).append(form);
          form.submit();
        }
        function abortXHR(xhr) {
          if (xhr && xhr.readyState < 4) {
            xhr.onreadystatechange = $2.noop;
            xhr.abort();
          }
        }
        function uniqueId() {
          return (/* @__PURE__ */ new Date()).getTime();
        }
        function cloneContents(container) {
          var cloned = container.clone();
          cloned.find("script").each(function() {
            if (!this.src)
              $2._data(this, "globalEval", false);
          });
          return cloned.contents();
        }
        function stripInternalParams(url) {
          url.search = url.search.replace(/([?&])(_pjax|_)=[^&]*/g, "").replace(/^&/, "");
          return url.href.replace(/\?($|#)/, "$1");
        }
        function parseURL(url) {
          var a = document.createElement("a");
          a.href = url;
          return a;
        }
        function stripHash(location2) {
          return location2.href.replace(/#.*/, "");
        }
        function optionsFor(container, options) {
          if (container && options) {
            options = $2.extend({}, options);
            options.container = container;
            return options;
          } else if ($2.isPlainObject(container)) {
            return container;
          } else {
            return { container };
          }
        }
        function findAll(elems, selector) {
          return elems.filter(selector).add(elems.find(selector));
        }
        function parseHTML(html2) {
          return $2.parseHTML(html2, document, true);
        }
        function extractContainer(data, xhr, options) {
          var obj = {}, fullDocument = /<html/i.test(data);
          var serverUrl = xhr.getResponseHeader("X-PJAX-URL");
          obj.url = serverUrl ? stripInternalParams(parseURL(serverUrl)) : options.requestUrl;
          var $head, $body;
          if (fullDocument) {
            $body = $2(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]));
            var head = data.match(/<head[^>]*>([\s\S.]*)<\/head>/i);
            $head = head != null ? $2(parseHTML(head[0])) : $body;
          } else {
            $head = $body = $2(parseHTML(data));
          }
          if ($body.length === 0)
            return obj;
          obj.title = findAll($head, "title").last().text();
          if (options.fragment) {
            var $fragment = $body;
            if (options.fragment !== "body") {
              $fragment = findAll($fragment, options.fragment).first();
            }
            if ($fragment.length) {
              obj.contents = options.fragment === "body" ? $fragment : $fragment.contents();
              if (!obj.title)
                obj.title = $fragment.attr("title") || $fragment.data("title");
            }
          } else if (!fullDocument) {
            obj.contents = $body;
          }
          if (obj.contents) {
            obj.contents = obj.contents.not(function() {
              return $2(this).is("title");
            });
            obj.contents.find("title").remove();
            obj.scripts = findAll(obj.contents, "script[src]").remove();
            obj.contents = obj.contents.not(obj.scripts);
          }
          if (obj.title)
            obj.title = $2.trim(obj.title);
          return obj;
        }
        function executeScriptTags(scripts) {
          if (!scripts)
            return;
          var existingScripts = $2("script[src]");
          scripts.each(function() {
            var src = this.src;
            var matchedScripts = existingScripts.filter(function() {
              return this.src === src;
            });
            if (matchedScripts.length)
              return;
            var script = document.createElement("script");
            var type = $2(this).attr("type");
            if (type)
              script.type = type;
            script.src = $2(this).attr("src");
            document.head.appendChild(script);
          });
        }
        var cacheMapping = {};
        var cacheForwardStack = [];
        var cacheBackStack = [];
        function cachePush(id, value) {
          cacheMapping[id] = value;
          cacheBackStack.push(id);
          trimCacheStack(cacheForwardStack, 0);
          trimCacheStack(cacheBackStack, pjax.defaults.maxCacheLength);
        }
        function cachePop(direction, id, value) {
          var pushStack, popStack;
          cacheMapping[id] = value;
          if (direction === "forward") {
            pushStack = cacheBackStack;
            popStack = cacheForwardStack;
          } else {
            pushStack = cacheForwardStack;
            popStack = cacheBackStack;
          }
          pushStack.push(id);
          id = popStack.pop();
          if (id)
            delete cacheMapping[id];
          trimCacheStack(pushStack, pjax.defaults.maxCacheLength);
        }
        function trimCacheStack(stack, length) {
          while (stack.length > length)
            delete cacheMapping[stack.shift()];
        }
        function findVersion() {
          return $2("meta").filter(function() {
            var name = $2(this).attr("http-equiv");
            return name && name.toUpperCase() === "X-PJAX-VERSION";
          }).attr("content");
        }
        function enable() {
          $2.fn.pjax = fnPjax;
          $2.pjax = pjax;
          $2.pjax.enable = $2.noop;
          $2.pjax.disable = disable;
          $2.pjax.click = handleClick;
          $2.pjax.submit = handleSubmit;
          $2.pjax.reload = pjaxReload;
          $2.pjax.defaults = {
            timeout: 650,
            push: true,
            replace: false,
            type: "GET",
            dataType: "html",
            scrollTo: 0,
            maxCacheLength: 20,
            version: findVersion
          };
          $2(window).on("popstate.pjax", onPjaxPopstate);
        }
        function disable() {
          $2.fn.pjax = function() {
            return this;
          };
          $2.pjax = fallbackPjax;
          $2.pjax.enable = enable;
          $2.pjax.disable = $2.noop;
          $2.pjax.click = $2.noop;
          $2.pjax.submit = $2.noop;
          $2.pjax.reload = function() {
            window.location.reload();
          };
          $2(window).off("popstate.pjax", onPjaxPopstate);
        }
        if ($2.event.props && $2.inArray("state", $2.event.props) < 0) {
          $2.event.props.push("state");
        } else if (!("state" in $2.Event.prototype)) {
          $2.event.addProp("state");
        }
        $2.support.pjax = window.history && window.history.pushState && window.history.replaceState && // pushState isn't reliable on iOS until 5.
        !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/);
        if ($2.support.pjax) {
          enable();
        } else {
          disable();
        }
      })(jQuery);
      const cssLoader = (e) => {
        const t2 = GM_getResourceText(e);
        return GM_addStyle(t2), t2;
      };
      cssLoader("element-plus-css");
      var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
      var freeSelf = typeof self == "object" && self && self.Object === Object && self;
      var root = freeGlobal || freeSelf || Function("return this")();
      var Symbol$1 = root.Symbol;
      var objectProto$i = Object.prototype;
      var hasOwnProperty$f = objectProto$i.hasOwnProperty;
      var nativeObjectToString$2 = objectProto$i.toString;
      var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : void 0;
      function getRawTag(value) {
        var isOwn = hasOwnProperty$f.call(value, symToStringTag$1), tag = value[symToStringTag$1];
        try {
          value[symToStringTag$1] = void 0;
          var unmasked = true;
        } catch (e) {
        }
        var result = nativeObjectToString$2.call(value);
        if (unmasked) {
          if (isOwn) {
            value[symToStringTag$1] = tag;
          } else {
            delete value[symToStringTag$1];
          }
        }
        return result;
      }
      var objectProto$h = Object.prototype;
      var nativeObjectToString$1 = objectProto$h.toString;
      function objectToString$1(value) {
        return nativeObjectToString$1.call(value);
      }
      var nullTag = "[object Null]", undefinedTag = "[object Undefined]";
      var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : void 0;
      function baseGetTag(value) {
        if (value == null) {
          return value === void 0 ? undefinedTag : nullTag;
        }
        return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString$1(value);
      }
      function isObjectLike(value) {
        return value != null && typeof value == "object";
      }
      var symbolTag$1 = "[object Symbol]";
      function isSymbol(value) {
        return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag$1;
      }
      function arrayMap(array, iteratee) {
        var index = -1, length = array == null ? 0 : array.length, result = Array(length);
        while (++index < length) {
          result[index] = iteratee(array[index], index, array);
        }
        return result;
      }
      var isArray$1 = Array.isArray;
      var INFINITY$2 = 1 / 0;
      var symbolProto$1 = Symbol$1 ? Symbol$1.prototype : void 0, symbolToString = symbolProto$1 ? symbolProto$1.toString : void 0;
      function baseToString(value) {
        if (typeof value == "string") {
          return value;
        }
        if (isArray$1(value)) {
          return arrayMap(value, baseToString) + "";
        }
        if (isSymbol(value)) {
          return symbolToString ? symbolToString.call(value) : "";
        }
        var result = value + "";
        return result == "0" && 1 / value == -INFINITY$2 ? "-0" : result;
      }
      var reWhitespace = /\s/;
      function trimmedEndIndex(string) {
        var index = string.length;
        while (index-- && reWhitespace.test(string.charAt(index))) {
        }
        return index;
      }
      var reTrimStart = /^\s+/;
      function baseTrim(string) {
        return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, "") : string;
      }
      function isObject$4(value) {
        var type = typeof value;
        return value != null && (type == "object" || type == "function");
      }
      var NAN = 0 / 0;
      var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
      var reIsBinary = /^0b[01]+$/i;
      var reIsOctal = /^0o[0-7]+$/i;
      var freeParseInt = parseInt;
      function toNumber(value) {
        if (typeof value == "number") {
          return value;
        }
        if (isSymbol(value)) {
          return NAN;
        }
        if (isObject$4(value)) {
          var other = typeof value.valueOf == "function" ? value.valueOf() : value;
          value = isObject$4(other) ? other + "" : other;
        }
        if (typeof value != "string") {
          return value === 0 ? value : +value;
        }
        value = baseTrim(value);
        var isBinary = reIsBinary.test(value);
        return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
      }
      var INFINITY$1 = 1 / 0, MAX_INTEGER = 17976931348623157e292;
      function toFinite(value) {
        if (!value) {
          return value === 0 ? value : 0;
        }
        value = toNumber(value);
        if (value === INFINITY$1 || value === -INFINITY$1) {
          var sign = value < 0 ? -1 : 1;
          return sign * MAX_INTEGER;
        }
        return value === value ? value : 0;
      }
      function toInteger(value) {
        var result = toFinite(value), remainder = result % 1;
        return result === result ? remainder ? result - remainder : result : 0;
      }
      function identity(value) {
        return value;
      }
      var asyncTag = "[object AsyncFunction]", funcTag$1 = "[object Function]", genTag = "[object GeneratorFunction]", proxyTag = "[object Proxy]";
      function isFunction$1(value) {
        if (!isObject$4(value)) {
          return false;
        }
        var tag = baseGetTag(value);
        return tag == funcTag$1 || tag == genTag || tag == asyncTag || tag == proxyTag;
      }
      var coreJsData = root["__core-js_shared__"];
      var maskSrcKey = function() {
        var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || "");
        return uid ? "Symbol(src)_1." + uid : "";
      }();
      function isMasked(func) {
        return !!maskSrcKey && maskSrcKey in func;
      }
      var funcProto$2 = Function.prototype;
      var funcToString$2 = funcProto$2.toString;
      function toSource(func) {
        if (func != null) {
          try {
            return funcToString$2.call(func);
          } catch (e) {
          }
          try {
            return func + "";
          } catch (e) {
          }
        }
        return "";
      }
      var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
      var reIsHostCtor = /^\[object .+?Constructor\]$/;
      var funcProto$1 = Function.prototype, objectProto$g = Object.prototype;
      var funcToString$1 = funcProto$1.toString;
      var hasOwnProperty$e = objectProto$g.hasOwnProperty;
      var reIsNative = RegExp(
        "^" + funcToString$1.call(hasOwnProperty$e).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"
      );
      function baseIsNative(value) {
        if (!isObject$4(value) || isMasked(value)) {
          return false;
        }
        var pattern = isFunction$1(value) ? reIsNative : reIsHostCtor;
        return pattern.test(toSource(value));
      }
      function getValue(object, key) {
        return object == null ? void 0 : object[key];
      }
      function getNative(object, key) {
        var value = getValue(object, key);
        return baseIsNative(value) ? value : void 0;
      }
      var WeakMap$1 = getNative(root, "WeakMap");
      function apply$1(func, thisArg, args) {
        switch (args.length) {
          case 0:
            return func.call(thisArg);
          case 1:
            return func.call(thisArg, args[0]);
          case 2:
            return func.call(thisArg, args[0], args[1]);
          case 3:
            return func.call(thisArg, args[0], args[1], args[2]);
        }
        return func.apply(thisArg, args);
      }
      var HOT_COUNT = 800, HOT_SPAN = 16;
      var nativeNow = Date.now;
      function shortOut(func) {
        var count = 0, lastCalled = 0;
        return function() {
          var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled);
          lastCalled = stamp;
          if (remaining > 0) {
            if (++count >= HOT_COUNT) {
              return arguments[0];
            }
          } else {
            count = 0;
          }
          return func.apply(void 0, arguments);
        };
      }
      function constant(value) {
        return function() {
          return value;
        };
      }
      var defineProperty = function() {
        try {
          var func = getNative(Object, "defineProperty");
          func({}, "", {});
          return func;
        } catch (e) {
        }
      }();
      var baseSetToString = !defineProperty ? identity : function(func, string) {
        return defineProperty(func, "toString", {
          "configurable": true,
          "enumerable": false,
          "value": constant(string),
          "writable": true
        });
      };
      const baseSetToString$1 = baseSetToString;
      var setToString = shortOut(baseSetToString$1);
      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;
      }
      function baseFindIndex(array, predicate, fromIndex, fromRight) {
        var length = array.length, index = fromIndex + (fromRight ? 1 : -1);
        while (fromRight ? index-- : ++index < length) {
          if (predicate(array[index], index, array)) {
            return index;
          }
        }
        return -1;
      }
      function baseIsNaN(value) {
        return value !== value;
      }
      function strictIndexOf(array, value, fromIndex) {
        var index = fromIndex - 1, length = array.length;
        while (++index < length) {
          if (array[index] === value) {
            return index;
          }
        }
        return -1;
      }
      function baseIndexOf(array, value, fromIndex) {
        return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex);
      }
      function arrayIncludes(array, value) {
        var length = array == null ? 0 : array.length;
        return !!length && baseIndexOf(array, value, 0) > -1;
      }
      var MAX_SAFE_INTEGER$1 = 9007199254740991;
      var reIsUint = /^(?:0|[1-9]\d*)$/;
      function isIndex(value, length) {
        var type = typeof value;
        length = length == null ? MAX_SAFE_INTEGER$1 : length;
        return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
      }
      function baseAssignValue(object, key, value) {
        if (key == "__proto__" && defineProperty) {
          defineProperty(object, key, {
            "configurable": true,
            "enumerable": true,
            "value": value,
            "writable": true
          });
        } else {
          object[key] = value;
        }
      }
      function eq(value, other) {
        return value === other || value !== value && other !== other;
      }
      var objectProto$f = Object.prototype;
      var hasOwnProperty$d = objectProto$f.hasOwnProperty;
      function assignValue(object, key, value) {
        var objValue = object[key];
        if (!(hasOwnProperty$d.call(object, key) && eq(objValue, value)) || value === void 0 && !(key in object)) {
          baseAssignValue(object, key, value);
        }
      }
      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) : void 0;
          if (newValue === void 0) {
            newValue = source[key];
          }
          if (isNew) {
            baseAssignValue(object, key, newValue);
          } else {
            assignValue(object, key, newValue);
          }
        }
        return object;
      }
      var nativeMax = Math.max;
      function overRest(func, start, transform2) {
        start = nativeMax(start === void 0 ? func.length - 1 : start, 0);
        return function() {
          var args = arguments, index = -1, length = nativeMax(args.length - start, 0), array = Array(length);
          while (++index < length) {
            array[index] = args[start + index];
          }
          index = -1;
          var otherArgs = Array(start + 1);
          while (++index < start) {
            otherArgs[index] = args[index];
          }
          otherArgs[start] = transform2(array);
          return apply$1(func, this, otherArgs);
        };
      }
      function baseRest(func, start) {
        return setToString(overRest(func, start, identity), func + "");
      }
      var MAX_SAFE_INTEGER = 9007199254740991;
      function isLength(value) {
        return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
      }
      function isArrayLike(value) {
        return value != null && isLength(value.length) && !isFunction$1(value);
      }
      function isIterateeCall(value, index, object) {
        if (!isObject$4(object)) {
          return false;
        }
        var type = typeof index;
        if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) {
          return eq(object[index], value);
        }
        return false;
      }
      function createAssigner(assigner) {
        return baseRest(function(object, sources) {
          var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : void 0, guard = length > 2 ? sources[2] : void 0;
          customizer = assigner.length > 3 && typeof customizer == "function" ? (length--, customizer) : void 0;
          if (guard && isIterateeCall(sources[0], sources[1], guard)) {
            customizer = length < 3 ? void 0 : customizer;
            length = 1;
          }
          object = Object(object);
          while (++index < length) {
            var source = sources[index];
            if (source) {
              assigner(object, source, index, customizer);
            }
          }
          return object;
        });
      }
      var objectProto$e = Object.prototype;
      function isPrototype(value) {
        var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto$e;
        return value === proto;
      }
      function baseTimes(n, iteratee) {
        var index = -1, result = Array(n);
        while (++index < n) {
          result[index] = iteratee(index);
        }
        return result;
      }
      var argsTag$2 = "[object Arguments]";
      function baseIsArguments(value) {
        return isObjectLike(value) && baseGetTag(value) == argsTag$2;
      }
      var objectProto$d = Object.prototype;
      var hasOwnProperty$c = objectProto$d.hasOwnProperty;
      var propertyIsEnumerable$1 = objectProto$d.propertyIsEnumerable;
      var isArguments = baseIsArguments(/* @__PURE__ */ function() {
        return arguments;
      }()) ? baseIsArguments : function(value) {
        return isObjectLike(value) && hasOwnProperty$c.call(value, "callee") && !propertyIsEnumerable$1.call(value, "callee");
      };
      function stubFalse() {
        return false;
      }
      var freeExports$1 = typeof exports == "object" && exports && !exports.nodeType && exports;
      var freeModule$1 = freeExports$1 && typeof module == "object" && module && !module.nodeType && module;
      var moduleExports$1 = freeModule$1 && freeModule$1.exports === freeExports$1;
      var Buffer = moduleExports$1 ? root.Buffer : void 0;
      var nativeIsBuffer = Buffer ? Buffer.isBuffer : void 0;
      var isBuffer$1 = nativeIsBuffer || stubFalse;
      var argsTag$1 = "[object Arguments]", arrayTag$1 = "[object Array]", boolTag$1 = "[object Boolean]", dateTag$1 = "[object Date]", errorTag$2 = "[object Error]", funcTag = "[object Function]", mapTag$2 = "[object Map]", numberTag$1 = "[object Number]", objectTag$3 = "[object Object]", regexpTag$1 = "[object RegExp]", setTag$2 = "[object Set]", stringTag$1 = "[object String]", weakMapTag$1 = "[object WeakMap]";
      var arrayBufferTag$1 = "[object ArrayBuffer]", dataViewTag$2 = "[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]";
      var typedArrayTags = {};
      typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
      typedArrayTags[argsTag$1] = typedArrayTags[arrayTag$1] = typedArrayTags[arrayBufferTag$1] = typedArrayTags[boolTag$1] = typedArrayTags[dataViewTag$2] = typedArrayTags[dateTag$1] = typedArrayTags[errorTag$2] = typedArrayTags[funcTag] = typedArrayTags[mapTag$2] = typedArrayTags[numberTag$1] = typedArrayTags[objectTag$3] = typedArrayTags[regexpTag$1] = typedArrayTags[setTag$2] = typedArrayTags[stringTag$1] = typedArrayTags[weakMapTag$1] = false;
      function baseIsTypedArray(value) {
        return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
      }
      function baseUnary(func) {
        return function(value) {
          return func(value);
        };
      }
      var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports;
      var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module;
      var moduleExports = freeModule && freeModule.exports === freeExports;
      var freeProcess = moduleExports && freeGlobal.process;
      var nodeUtil = function() {
        try {
          var types = freeModule && freeModule.require && freeModule.require("util").types;
          if (types) {
            return types;
          }
          return freeProcess && freeProcess.binding && freeProcess.binding("util");
        } catch (e) {
        }
      }();
      var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
      var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
      var objectProto$c = Object.prototype;
      var hasOwnProperty$b = objectProto$c.hasOwnProperty;
      function arrayLikeKeys(value, inherited) {
        var isArr = isArray$1(value), isArg = !isArr && isArguments(value), isBuff = !isArr && !isArg && isBuffer$1(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$b.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;
      }
      function overArg(func, transform2) {
        return function(arg) {
          return func(transform2(arg));
        };
      }
      var nativeKeys = overArg(Object.keys, Object);
      var objectProto$b = Object.prototype;
      var hasOwnProperty$a = objectProto$b.hasOwnProperty;
      function baseKeys(object) {
        if (!isPrototype(object)) {
          return nativeKeys(object);
        }
        var result = [];
        for (var key in Object(object)) {
          if (hasOwnProperty$a.call(object, key) && key != "constructor") {
            result.push(key);
          }
        }
        return result;
      }
      function keys(object) {
        return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
      }
      function nativeKeysIn(object) {
        var result = [];
        if (object != null) {
          for (var key in Object(object)) {
            result.push(key);
          }
        }
        return result;
      }
      var objectProto$a = Object.prototype;
      var hasOwnProperty$9 = objectProto$a.hasOwnProperty;
      function baseKeysIn(object) {
        if (!isObject$4(object)) {
          return nativeKeysIn(object);
        }
        var isProto = isPrototype(object), result = [];
        for (var key in object) {
          if (!(key == "constructor" && (isProto || !hasOwnProperty$9.call(object, key)))) {
            result.push(key);
          }
        }
        return result;
      }
      function keysIn(object) {
        return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
      }
      var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
        copyObject(source, keysIn(source), object, customizer);
      });
      var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/;
      function isKey(value, object) {
        if (isArray$1(value)) {
          return false;
        }
        var type = typeof value;
        if (type == "number" || type == "symbol" || type == "boolean" || value == null || isSymbol(value)) {
          return true;
        }
        return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object);
      }
      var nativeCreate = getNative(Object, "create");
      function hashClear() {
        this.__data__ = nativeCreate ? nativeCreate(null) : {};
        this.size = 0;
      }
      function hashDelete(key) {
        var result = this.has(key) && delete this.__data__[key];
        this.size -= result ? 1 : 0;
        return result;
      }
      var HASH_UNDEFINED$2 = "__lodash_hash_undefined__";
      var objectProto$9 = Object.prototype;
      var hasOwnProperty$8 = objectProto$9.hasOwnProperty;
      function hashGet(key) {
        var data = this.__data__;
        if (nativeCreate) {
          var result = data[key];
          return result === HASH_UNDEFINED$2 ? void 0 : result;
        }
        return hasOwnProperty$8.call(data, key) ? data[key] : void 0;
      }
      var objectProto$8 = Object.prototype;
      var hasOwnProperty$7 = objectProto$8.hasOwnProperty;
      function hashHas(key) {
        var data = this.__data__;
        return nativeCreate ? data[key] !== void 0 : hasOwnProperty$7.call(data, key);
      }
      var HASH_UNDEFINED$1 = "__lodash_hash_undefined__";
      function hashSet(key, value) {
        var data = this.__data__;
        this.size += this.has(key) ? 0 : 1;
        data[key] = nativeCreate && value === void 0 ? HASH_UNDEFINED$1 : value;
        return this;
      }
      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]);
        }
      }
      Hash.prototype.clear = hashClear;
      Hash.prototype["delete"] = hashDelete;
      Hash.prototype.get = hashGet;
      Hash.prototype.has = hashHas;
      Hash.prototype.set = hashSet;
      function listCacheClear() {
        this.__data__ = [];
        this.size = 0;
      }
      function assocIndexOf(array, key) {
        var length = array.length;
        while (length--) {
          if (eq(array[length][0], key)) {
            return length;
          }
        }
        return -1;
      }
      var arrayProto = Array.prototype;
      var splice = arrayProto.splice;
      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;
      }
      function listCacheGet(key) {
        var data = this.__data__, index = assocIndexOf(data, key);
        return index < 0 ? void 0 : data[index][1];
      }
      function listCacheHas(key) {
        return assocIndexOf(this.__data__, key) > -1;
      }
      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;
      }
      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]);
        }
      }
      ListCache.prototype.clear = listCacheClear;
      ListCache.prototype["delete"] = listCacheDelete;
      ListCache.prototype.get = listCacheGet;
      ListCache.prototype.has = listCacheHas;
      ListCache.prototype.set = listCacheSet;
      var Map$1 = getNative(root, "Map");
      function mapCacheClear() {
        this.size = 0;
        this.__data__ = {
          "hash": new Hash(),
          "map": new (Map$1 || ListCache)(),
          "string": new Hash()
        };
      }
      function isKeyable(value) {
        var type = typeof value;
        return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null;
      }
      function getMapData(map2, key) {
        var data = map2.__data__;
        return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map;
      }
      function mapCacheDelete(key) {
        var result = getMapData(this, key)["delete"](key);
        this.size -= result ? 1 : 0;
        return result;
      }
      function mapCacheGet(key) {
        return getMapData(this, key).get(key);
      }
      function mapCacheHas(key) {
        return getMapData(this, key).has(key);
      }
      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;
      }
      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]);
        }
      }
      MapCache.prototype.clear = mapCacheClear;
      MapCache.prototype["delete"] = mapCacheDelete;
      MapCache.prototype.get = mapCacheGet;
      MapCache.prototype.has = mapCacheHas;
      MapCache.prototype.set = mapCacheSet;
      var FUNC_ERROR_TEXT$1 = "Expected a function";
      function memoize(func, resolver) {
        if (typeof func != "function" || resolver != null && typeof resolver != "function") {
          throw new TypeError(FUNC_ERROR_TEXT$1);
        }
        var memoized = function() {
          var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache2 = memoized.cache;
          if (cache2.has(key)) {
            return cache2.get(key);
          }
          var result = func.apply(this, args);
          memoized.cache = cache2.set(key, result) || cache2;
          return result;
        };
        memoized.cache = new (memoize.Cache || MapCache)();
        return memoized;
      }
      memoize.Cache = MapCache;
      var MAX_MEMOIZE_SIZE = 500;
      function memoizeCapped(func) {
        var result = memoize(func, function(key) {
          if (cache2.size === MAX_MEMOIZE_SIZE) {
            cache2.clear();
          }
          return key;
        });
        var cache2 = result.cache;
        return result;
      }
      var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
      var reEscapeChar = /\\(\\)?/g;
      var stringToPath = memoizeCapped(function(string) {
        var result = [];
        if (string.charCodeAt(0) === 46) {
          result.push("");
        }
        string.replace(rePropName, function(match2, number2, quote, subString) {
          result.push(quote ? subString.replace(reEscapeChar, "$1") : number2 || match2);
        });
        return result;
      });
      function toString$1(value) {
        return value == null ? "" : baseToString(value);
      }
      function castPath(value, object) {
        if (isArray$1(value)) {
          return value;
        }
        return isKey(value, object) ? [value] : stringToPath(toString$1(value));
      }
      var INFINITY = 1 / 0;
      function toKey(value) {
        if (typeof value == "string" || isSymbol(value)) {
          return value;
        }
        var result = value + "";
        return result == "0" && 1 / value == -INFINITY ? "-0" : result;
      }
      function baseGet(object, path) {
        path = castPath(path, object);
        var index = 0, length = path.length;
        while (object != null && index < length) {
          object = object[toKey(path[index++])];
        }
        return index && index == length ? object : void 0;
      }
      function get(object, path, defaultValue) {
        var result = object == null ? void 0 : baseGet(object, path);
        return result === void 0 ? defaultValue : result;
      }
      function arrayPush(array, values2) {
        var index = -1, length = values2.length, offset = array.length;
        while (++index < length) {
          array[offset + index] = values2[index];
        }
        return array;
      }
      var getPrototype = overArg(Object.getPrototypeOf, Object);
      var objectTag$2 = "[object Object]";
      var funcProto = Function.prototype, objectProto$7 = Object.prototype;
      var funcToString = funcProto.toString;
      var hasOwnProperty$6 = objectProto$7.hasOwnProperty;
      var objectCtorString = funcToString.call(Object);
      function isPlainObject$1(value) {
        if (!isObjectLike(value) || baseGetTag(value) != objectTag$2) {
          return false;
        }
        var proto = getPrototype(value);
        if (proto === null) {
          return true;
        }
        var Ctor = hasOwnProperty$6.call(proto, "constructor") && proto.constructor;
        return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
      }
      var domExcTag = "[object DOMException]", errorTag$1 = "[object Error]";
      function isError(value) {
        if (!isObjectLike(value)) {
          return false;
        }
        var tag = baseGetTag(value);
        return tag == errorTag$1 || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject$1(value);
      }
      var attempt = baseRest(function(func, args) {
        try {
          return apply$1(func, void 0, args);
        } catch (e) {
          return isError(e) ? e : new Error(e);
        }
      });
      var FUNC_ERROR_TEXT = "Expected a function";
      function before(n, func) {
        var result;
        if (typeof func != "function") {
          throw new TypeError(FUNC_ERROR_TEXT);
        }
        n = toInteger(n);
        return function() {
          if (--n > 0) {
            result = func.apply(this, arguments);
          }
          if (n <= 1) {
            func = void 0;
          }
          return result;
        };
      }
      function baseSlice(array, start, end) {
        var index = -1, length = array.length;
        if (start < 0) {
          start = -start > length ? 0 : length + start;
        }
        end = end > length ? length : end;
        if (end < 0) {
          end += length;
        }
        length = start > end ? 0 : end - start >>> 0;
        start >>>= 0;
        var result = Array(length);
        while (++index < length) {
          result[index] = array[index + start];
        }
        return result;
      }
      function castSlice(array, start, end) {
        var length = array.length;
        end = end === void 0 ? length : end;
        return !start && end >= length ? array : baseSlice(array, start, end);
      }
      var rsAstralRange$2 = "\\ud800-\\udfff", rsComboMarksRange$3 = "\\u0300-\\u036f", reComboHalfMarksRange$3 = "\\ufe20-\\ufe2f", rsComboSymbolsRange$3 = "\\u20d0-\\u20ff", rsComboRange$3 = rsComboMarksRange$3 + reComboHalfMarksRange$3 + rsComboSymbolsRange$3, rsVarRange$2 = "\\ufe0e\\ufe0f";
      var rsZWJ$2 = "\\u200d";
      var reHasUnicode = RegExp("[" + rsZWJ$2 + rsAstralRange$2 + rsComboRange$3 + rsVarRange$2 + "]");
      function hasUnicode(string) {
        return reHasUnicode.test(string);
      }
      function asciiToArray(string) {
        return string.split("");
      }
      var rsAstralRange$1 = "\\ud800-\\udfff", rsComboMarksRange$2 = "\\u0300-\\u036f", reComboHalfMarksRange$2 = "\\ufe20-\\ufe2f", rsComboSymbolsRange$2 = "\\u20d0-\\u20ff", rsComboRange$2 = rsComboMarksRange$2 + reComboHalfMarksRange$2 + rsComboSymbolsRange$2, rsVarRange$1 = "\\ufe0e\\ufe0f";
      var rsAstral = "[" + rsAstralRange$1 + "]", rsCombo$2 = "[" + rsComboRange$2 + "]", rsFitz$1 = "\\ud83c[\\udffb-\\udfff]", rsModifier$1 = "(?:" + rsCombo$2 + "|" + rsFitz$1 + ")", rsNonAstral$1 = "[^" + rsAstralRange$1 + "]", rsRegional$1 = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair$1 = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsZWJ$1 = "\\u200d";
      var reOptMod$1 = rsModifier$1 + "?", rsOptVar$1 = "[" + rsVarRange$1 + "]?", rsOptJoin$1 = "(?:" + rsZWJ$1 + "(?:" + [rsNonAstral$1, rsRegional$1, rsSurrPair$1].join("|") + ")" + rsOptVar$1 + reOptMod$1 + ")*", rsSeq$1 = rsOptVar$1 + reOptMod$1 + rsOptJoin$1, rsSymbol = "(?:" + [rsNonAstral$1 + rsCombo$2 + "?", rsCombo$2, rsRegional$1, rsSurrPair$1, rsAstral].join("|") + ")";
      var reUnicode = RegExp(rsFitz$1 + "(?=" + rsFitz$1 + ")|" + rsSymbol + rsSeq$1, "g");
      function unicodeToArray(string) {
        return string.match(reUnicode) || [];
      }
      function stringToArray(string) {
        return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
      }
      function createCaseFirst(methodName) {
        return function(string) {
          string = toString$1(string);
          var strSymbols = hasUnicode(string) ? stringToArray(string) : void 0;
          var chr = strSymbols ? strSymbols[0] : string.charAt(0);
          var trailing = strSymbols ? castSlice(strSymbols, 1).join("") : string.slice(1);
          return chr[methodName]() + trailing;
        };
      }
      var upperFirst = createCaseFirst("toUpperCase");
      function capitalize$1(string) {
        return upperFirst(toString$1(string).toLowerCase());
      }
      function arrayReduce(array, iteratee, accumulator, initAccum) {
        var index = -1, length = array == null ? 0 : array.length;
        if (initAccum && length) {
          accumulator = array[++index];
        }
        while (++index < length) {
          accumulator = iteratee(accumulator, array[index], index, array);
        }
        return accumulator;
      }
      function basePropertyOf(object) {
        return function(key) {
          return object == null ? void 0 : object[key];
        };
      }
      var deburredLetters = {
        // Latin-1 Supplement block.
        "À": "A",
        "Á": "A",
        "Â": "A",
        "Ã": "A",
        "Ä": "A",
        "Å": "A",
        "à": "a",
        "á": "a",
        "â": "a",
        "ã": "a",
        "ä": "a",
        "å": "a",
        "Ç": "C",
        "ç": "c",
        "Ð": "D",
        "ð": "d",
        "È": "E",
        "É": "E",
        "Ê": "E",
        "Ë": "E",
        "è": "e",
        "é": "e",
        "ê": "e",
        "ë": "e",
        "Ì": "I",
        "Í": "I",
        "Î": "I",
        "Ï": "I",
        "ì": "i",
        "í": "i",
        "î": "i",
        "ï": "i",
        "Ñ": "N",
        "ñ": "n",
        "Ò": "O",
        "Ó": "O",
        "Ô": "O",
        "Õ": "O",
        "Ö": "O",
        "Ø": "O",
        "ò": "o",
        "ó": "o",
        "ô": "o",
        "õ": "o",
        "ö": "o",
        "ø": "o",
        "Ù": "U",
        "Ú": "U",
        "Û": "U",
        "Ü": "U",
        "ù": "u",
        "ú": "u",
        "û": "u",
        "ü": "u",
        "Ý": "Y",
        "ý": "y",
        "ÿ": "y",
        "Æ": "Ae",
        "æ": "ae",
        "Þ": "Th",
        "þ": "th",
        "ß": "ss",
        // Latin Extended-A block.
        "Ā": "A",
        "Ă": "A",
        "Ą": "A",
        "ā": "a",
        "ă": "a",
        "ą": "a",
        "Ć": "C",
        "Ĉ": "C",
        "Ċ": "C",
        "Č": "C",
        "ć": "c",
        "ĉ": "c",
        "ċ": "c",
        "č": "c",
        "Ď": "D",
        "Đ": "D",
        "ď": "d",
        "đ": "d",
        "Ē": "E",
        "Ĕ": "E",
        "Ė": "E",
        "Ę": "E",
        "Ě": "E",
        "ē": "e",
        "ĕ": "e",
        "ė": "e",
        "ę": "e",
        "ě": "e",
        "Ĝ": "G",
        "Ğ": "G",
        "Ġ": "G",
        "Ģ": "G",
        "ĝ": "g",
        "ğ": "g",
        "ġ": "g",
        "ģ": "g",
        "Ĥ": "H",
        "Ħ": "H",
        "ĥ": "h",
        "ħ": "h",
        "Ĩ": "I",
        "Ī": "I",
        "Ĭ": "I",
        "Į": "I",
        "İ": "I",
        "ĩ": "i",
        "ī": "i",
        "ĭ": "i",
        "į": "i",
        "ı": "i",
        "Ĵ": "J",
        "ĵ": "j",
        "Ķ": "K",
        "ķ": "k",
        "ĸ": "k",
        "Ĺ": "L",
        "Ļ": "L",
        "Ľ": "L",
        "Ŀ": "L",
        "Ł": "L",
        "ĺ": "l",
        "ļ": "l",
        "ľ": "l",
        "ŀ": "l",
        "ł": "l",
        "Ń": "N",
        "Ņ": "N",
        "Ň": "N",
        "Ŋ": "N",
        "ń": "n",
        "ņ": "n",
        "ň": "n",
        "ŋ": "n",
        "Ō": "O",
        "Ŏ": "O",
        "Ő": "O",
        "ō": "o",
        "ŏ": "o",
        "ő": "o",
        "Ŕ": "R",
        "Ŗ": "R",
        "Ř": "R",
        "ŕ": "r",
        "ŗ": "r",
        "ř": "r",
        "Ś": "S",
        "Ŝ": "S",
        "Ş": "S",
        "Š": "S",
        "ś": "s",
        "ŝ": "s",
        "ş": "s",
        "š": "s",
        "Ţ": "T",
        "Ť": "T",
        "Ŧ": "T",
        "ţ": "t",
        "ť": "t",
        "ŧ": "t",
        "Ũ": "U",
        "Ū": "U",
        "Ŭ": "U",
        "Ů": "U",
        "Ű": "U",
        "Ų": "U",
        "ũ": "u",
        "ū": "u",
        "ŭ": "u",
        "ů": "u",
        "ű": "u",
        "ų": "u",
        "Ŵ": "W",
        "ŵ": "w",
        "Ŷ": "Y",
        "ŷ": "y",
        "Ÿ": "Y",
        "Ź": "Z",
        "Ż": "Z",
        "Ž": "Z",
        "ź": "z",
        "ż": "z",
        "ž": "z",
        "IJ": "IJ",
        "ij": "ij",
        "Œ": "Oe",
        "œ": "oe",
        "ʼn": "'n",
        "ſ": "s"
      };
      var deburrLetter = basePropertyOf(deburredLetters);
      const deburrLetter$1 = deburrLetter;
      var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
      var rsComboMarksRange$1 = "\\u0300-\\u036f", reComboHalfMarksRange$1 = "\\ufe20-\\ufe2f", rsComboSymbolsRange$1 = "\\u20d0-\\u20ff", rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1;
      var rsCombo$1 = "[" + rsComboRange$1 + "]";
      var reComboMark = RegExp(rsCombo$1, "g");
      function deburr(string) {
        string = toString$1(string);
        return string && string.replace(reLatin, deburrLetter$1).replace(reComboMark, "");
      }
      var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
      function asciiWords(string) {
        return string.match(reAsciiWord) || [];
      }
      var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
      function hasUnicodeWord(string) {
        return reHasUnicodeWord.test(string);
      }
      var rsAstralRange = "\\ud800-\\udfff", rsComboMarksRange = "\\u0300-\\u036f", reComboHalfMarksRange = "\\ufe20-\\ufe2f", rsComboSymbolsRange = "\\u20d0-\\u20ff", rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, rsDingbatRange = "\\u2700-\\u27bf", rsLowerRange = "a-z\\xdf-\\xf6\\xf8-\\xff", rsMathOpRange = "\\xac\\xb1\\xd7\\xf7", rsNonCharRange = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf", rsPunctuationRange = "\\u2000-\\u206f", rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000", rsUpperRange = "A-Z\\xc0-\\xd6\\xd8-\\xde", rsVarRange = "\\ufe0e\\ufe0f", rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
      var rsApos$1 = "['’]", rsBreak = "[" + rsBreakRange + "]", rsCombo = "[" + rsComboRange + "]", rsDigits = "\\d+", rsDingbat = "[" + rsDingbatRange + "]", rsLower = "[" + rsLowerRange + "]", rsMisc = "[^" + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + "]", rsFitz = "\\ud83c[\\udffb-\\udfff]", rsModifier = "(?:" + rsCombo + "|" + rsFitz + ")", rsNonAstral = "[^" + rsAstralRange + "]", rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsUpper = "[" + rsUpperRange + "]", rsZWJ = "\\u200d";
      var rsMiscLower = "(?:" + rsLower + "|" + rsMisc + ")", rsMiscUpper = "(?:" + rsUpper + "|" + rsMisc + ")", rsOptContrLower = "(?:" + rsApos$1 + "(?:d|ll|m|re|s|t|ve))?", rsOptContrUpper = "(?:" + rsApos$1 + "(?:D|LL|M|RE|S|T|VE))?", reOptMod = rsModifier + "?", rsOptVar = "[" + rsVarRange + "]?", rsOptJoin = "(?:" + rsZWJ + "(?:" + [rsNonAstral, rsRegional, rsSurrPair].join("|") + ")" + rsOptVar + reOptMod + ")*", rsOrdLower = "\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])", rsOrdUpper = "\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])", rsSeq = rsOptVar + reOptMod + rsOptJoin, rsEmoji = "(?:" + [rsDingbat, rsRegional, rsSurrPair].join("|") + ")" + rsSeq;
      var reUnicodeWord = RegExp([
        rsUpper + "?" + rsLower + "+" + rsOptContrLower + "(?=" + [rsBreak, rsUpper, "$"].join("|") + ")",
        rsMiscUpper + "+" + rsOptContrUpper + "(?=" + [rsBreak, rsUpper + rsMiscLower, "$"].join("|") + ")",
        rsUpper + "?" + rsMiscLower + "+" + rsOptContrLower,
        rsUpper + "+" + rsOptContrUpper,
        rsOrdUpper,
        rsOrdLower,
        rsDigits,
        rsEmoji
      ].join("|"), "g");
      function unicodeWords(string) {
        return string.match(reUnicodeWord) || [];
      }
      function words(string, pattern, guard) {
        string = toString$1(string);
        pattern = guard ? void 0 : pattern;
        if (pattern === void 0) {
          return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
        }
        return string.match(pattern) || [];
      }
      var rsApos = "['’]";
      var reApos = RegExp(rsApos, "g");
      function createCompounder(callback) {
        return function(string) {
          return arrayReduce(words(deburr(string).replace(reApos, "")), callback, "");
        };
      }
      var camelCase = createCompounder(function(result, word, index) {
        word = word.toLowerCase();
        return result + (index ? capitalize$1(word) : word);
      });
      function castArray() {
        if (!arguments.length) {
          return [];
        }
        var value = arguments[0];
        return isArray$1(value) ? value : [value];
      }
      function stackClear() {
        this.__data__ = new ListCache();
        this.size = 0;
      }
      function stackDelete(key) {
        var data = this.__data__, result = data["delete"](key);
        this.size = data.size;
        return result;
      }
      function stackGet(key) {
        return this.__data__.get(key);
      }
      function stackHas(key) {
        return this.__data__.has(key);
      }
      var LARGE_ARRAY_SIZE = 200;
      function stackSet(key, value) {
        var data = this.__data__;
        if (data instanceof ListCache) {
          var pairs = data.__data__;
          if (!Map$1 || 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;
      }
      function Stack(entries) {
        var data = this.__data__ = new ListCache(entries);
        this.size = data.size;
      }
      Stack.prototype.clear = stackClear;
      Stack.prototype["delete"] = stackDelete;
      Stack.prototype.get = stackGet;
      Stack.prototype.has = stackHas;
      Stack.prototype.set = stackSet;
      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;
      }
      function stubArray() {
        return [];
      }
      var objectProto$6 = Object.prototype;
      var propertyIsEnumerable = objectProto$6.propertyIsEnumerable;
      var nativeGetSymbols = Object.getOwnPropertySymbols;
      var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
        if (object == null) {
          return [];
        }
        object = Object(object);
        return arrayFilter(nativeGetSymbols(object), function(symbol) {
          return propertyIsEnumerable.call(object, symbol);
        });
      };
      const getSymbols$1 = getSymbols;
      function baseGetAllKeys(object, keysFunc, symbolsFunc) {
        var result = keysFunc(object);
        return isArray$1(object) ? result : arrayPush(result, symbolsFunc(object));
      }
      function getAllKeys(object) {
        return baseGetAllKeys(object, keys, getSymbols$1);
      }
      var DataView = getNative(root, "DataView");
      var Promise$1 = getNative(root, "Promise");
      var Set$1 = getNative(root, "Set");
      var mapTag$1 = "[object Map]", objectTag$1 = "[object Object]", promiseTag = "[object Promise]", setTag$1 = "[object Set]", weakMapTag = "[object WeakMap]";
      var dataViewTag$1 = "[object DataView]";
      var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map$1), promiseCtorString = toSource(Promise$1), setCtorString = toSource(Set$1), weakMapCtorString = toSource(WeakMap$1);
      var getTag = baseGetTag;
      if (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag$1 || Map$1 && getTag(new Map$1()) != mapTag$1 || Promise$1 && getTag(Promise$1.resolve()) != promiseTag || Set$1 && getTag(new Set$1()) != setTag$1 || WeakMap$1 && getTag(new WeakMap$1()) != weakMapTag) {
        getTag = function(value) {
          var result = baseGetTag(value), Ctor = result == objectTag$1 ? value.constructor : void 0, ctorString = Ctor ? toSource(Ctor) : "";
          if (ctorString) {
            switch (ctorString) {
              case dataViewCtorString:
                return dataViewTag$1;
              case mapCtorString:
                return mapTag$1;
              case promiseCtorString:
                return promiseTag;
              case setCtorString:
                return setTag$1;
              case weakMapCtorString:
                return weakMapTag;
            }
          }
          return result;
        };
      }
      const getTag$1 = getTag;
      var Uint8Array$1 = root.Uint8Array;
      const Uint8Array$2 = Uint8Array$1;
      var HASH_UNDEFINED = "__lodash_hash_undefined__";
      function setCacheAdd(value) {
        this.__data__.set(value, HASH_UNDEFINED);
        return this;
      }
      function setCacheHas(value) {
        return this.__data__.has(value);
      }
      function SetCache(values2) {
        var index = -1, length = values2 == null ? 0 : values2.length;
        this.__data__ = new MapCache();
        while (++index < length) {
          this.add(values2[index]);
        }
      }
      SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
      SetCache.prototype.has = setCacheHas;
      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;
      }
      function cacheHas(cache2, key) {
        return cache2.has(key);
      }
      var COMPARE_PARTIAL_FLAG$5 = 1, COMPARE_UNORDERED_FLAG$3 = 2;
      function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
        var isPartial = bitmask & COMPARE_PARTIAL_FLAG$5, arrLength = array.length, othLength = other.length;
        if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
          return false;
        }
        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$3 ? new SetCache() : void 0;
        stack.set(array, other);
        stack.set(other, array);
        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 !== void 0) {
            if (compared) {
              continue;
            }
            result = false;
            break;
          }
          if (seen) {
            if (!arraySome(other, function(othValue2, othIndex) {
              if (!cacheHas(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, 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;
      }
      function mapToArray(map2) {
        var index = -1, result = Array(map2.size);
        map2.forEach(function(value, key) {
          result[++index] = [key, value];
        });
        return result;
      }
      function setToArray(set) {
        var index = -1, result = Array(set.size);
        set.forEach(function(value) {
          result[++index] = value;
        });
        return result;
      }
      var COMPARE_PARTIAL_FLAG$4 = 1, COMPARE_UNORDERED_FLAG$2 = 2;
      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]";
      var symbolProto = Symbol$1 ? Symbol$1.prototype : void 0, symbolValueOf = symbolProto ? symbolProto.valueOf : void 0;
      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$2(object), new Uint8Array$2(other))) {
              return false;
            }
            return true;
          case boolTag:
          case dateTag:
          case numberTag:
            return eq(+object, +other);
          case errorTag:
            return object.name == other.name && object.message == other.message;
          case regexpTag:
          case stringTag:
            return object == other + "";
          case mapTag:
            var convert = mapToArray;
          case setTag:
            var isPartial = bitmask & COMPARE_PARTIAL_FLAG$4;
            convert || (convert = setToArray);
            if (object.size != other.size && !isPartial) {
              return false;
            }
            var stacked = stack.get(object);
            if (stacked) {
              return stacked == other;
            }
            bitmask |= COMPARE_UNORDERED_FLAG$2;
            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;
      }
      var COMPARE_PARTIAL_FLAG$3 = 1;
      var objectProto$5 = Object.prototype;
      var hasOwnProperty$5 = objectProto$5.hasOwnProperty;
      function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
        var isPartial = bitmask & COMPARE_PARTIAL_FLAG$3, 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$5.call(other, key))) {
            return false;
          }
        }
        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);
          }
          if (!(compared === void 0 ? 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;
          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;
      }
      var COMPARE_PARTIAL_FLAG$2 = 1;
      var argsTag = "[object Arguments]", arrayTag = "[object Array]", objectTag = "[object Object]";
      var objectProto$4 = Object.prototype;
      var hasOwnProperty$4 = objectProto$4.hasOwnProperty;
      function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
        var objIsArr = isArray$1(object), othIsArr = isArray$1(other), objTag = objIsArr ? arrayTag : getTag$1(object), othTag = othIsArr ? arrayTag : getTag$1(other);
        objTag = objTag == argsTag ? objectTag : objTag;
        othTag = othTag == argsTag ? objectTag : othTag;
        var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag;
        if (isSameTag && isBuffer$1(object)) {
          if (!isBuffer$1(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$2)) {
          var objIsWrapped = objIsObj && hasOwnProperty$4.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty$4.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);
      }
      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);
      }
      var COMPARE_PARTIAL_FLAG$1 = 1, COMPARE_UNORDERED_FLAG$1 = 2;
      function baseIsMatch(object, source, matchData, customizer) {
        var index = matchData.length, length = index, noCustomizer = !customizer;
        if (object == null) {
          return !length;
        }
        object = Object(object);
        while (index--) {
          var data = matchData[index];
          if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) {
            return false;
          }
        }
        while (++index < length) {
          data = matchData[index];
          var key = data[0], objValue = object[key], srcValue = data[1];
          if (noCustomizer && data[2]) {
            if (objValue === void 0 && !(key in object)) {
              return false;
            }
          } else {
            var stack = new Stack();
            if (customizer) {
              var result = customizer(objValue, srcValue, key, object, source, stack);
            }
            if (!(result === void 0 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG$1 | COMPARE_UNORDERED_FLAG$1, customizer, stack) : result)) {
              return false;
            }
          }
        }
        return true;
      }
      function isStrictComparable(value) {
        return value === value && !isObject$4(value);
      }
      function getMatchData(object) {
        var result = keys(object), length = result.length;
        while (length--) {
          var key = result[length], value = object[key];
          result[length] = [key, value, isStrictComparable(value)];
        }
        return result;
      }
      function matchesStrictComparable(key, srcValue) {
        return function(object) {
          if (object == null) {
            return false;
          }
          return object[key] === srcValue && (srcValue !== void 0 || key in Object(object));
        };
      }
      function baseMatches(source) {
        var matchData = getMatchData(source);
        if (matchData.length == 1 && matchData[0][2]) {
          return matchesStrictComparable(matchData[0][0], matchData[0][1]);
        }
        return function(object) {
          return object === source || baseIsMatch(object, source, matchData);
        };
      }
      function baseHasIn(object, key) {
        return object != null && key in Object(object);
      }
      function hasPath(object, path, hasFunc) {
        path = castPath(path, object);
        var index = -1, length = path.length, result = false;
        while (++index < length) {
          var key = toKey(path[index]);
          if (!(result = object != null && hasFunc(object, key))) {
            break;
          }
          object = object[key];
        }
        if (result || ++index != length) {
          return result;
        }
        length = object == null ? 0 : object.length;
        return !!length && isLength(length) && isIndex(key, length) && (isArray$1(object) || isArguments(object));
      }
      function hasIn(object, path) {
        return object != null && hasPath(object, path, baseHasIn);
      }
      var COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
      function baseMatchesProperty(path, srcValue) {
        if (isKey(path) && isStrictComparable(srcValue)) {
          return matchesStrictComparable(toKey(path), srcValue);
        }
        return function(object) {
          var objValue = get(object, path);
          return objValue === void 0 && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
        };
      }
      function baseProperty(key) {
        return function(object) {
          return object == null ? void 0 : object[key];
        };
      }
      function basePropertyDeep(path) {
        return function(object) {
          return baseGet(object, path);
        };
      }
      function property(path) {
        return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
      }
      function baseIteratee(value) {
        if (typeof value == "function") {
          return value;
        }
        if (value == null) {
          return identity;
        }
        if (typeof value == "object") {
          return isArray$1(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value);
        }
        return property(value);
      }
      function arrayAggregator(array, setter, iteratee, accumulator) {
        var index = -1, length = array == null ? 0 : array.length;
        while (++index < length) {
          var value = array[index];
          setter(accumulator, value, iteratee(value), array);
        }
        return accumulator;
      }
      function createBaseFor(fromRight) {
        return function(object, iteratee, keysFunc) {
          var index = -1, iterable = Object(object), props = keysFunc(object), length = props.length;
          while (length--) {
            var key = props[fromRight ? length : ++index];
            if (iteratee(iterable[key], key, iterable) === false) {
              break;
            }
          }
          return object;
        };
      }
      var baseFor = createBaseFor();
      function baseForOwn(object, iteratee) {
        return object && baseFor(object, iteratee, keys);
      }
      function createBaseEach(eachFunc, fromRight) {
        return function(collection, iteratee) {
          if (collection == null) {
            return collection;
          }
          if (!isArrayLike(collection)) {
            return eachFunc(collection, iteratee);
          }
          var length = collection.length, index = fromRight ? length : -1, iterable = Object(collection);
          while (fromRight ? index-- : ++index < length) {
            if (iteratee(iterable[index], index, iterable) === false) {
              break;
            }
          }
          return collection;
        };
      }
      var baseEach = createBaseEach(baseForOwn);
      const baseEach$1 = baseEach;
      function baseAggregator(collection, setter, iteratee, accumulator) {
        baseEach$1(collection, function(value, key, collection2) {
          setter(accumulator, value, iteratee(value), collection2);
        });
        return accumulator;
      }
      function createAggregator(setter, initializer) {
        return function(collection, iteratee) {
          var func = isArray$1(collection) ? arrayAggregator : baseAggregator, accumulator = initializer ? initializer() : {};
          return func(collection, setter, baseIteratee(iteratee), accumulator);
        };
      }
      function isArrayLikeObject(value) {
        return isObjectLike(value) && isArrayLike(value);
      }
      function arrayIncludesWith(array, value, comparator) {
        var index = -1, length = array == null ? 0 : array.length;
        while (++index < length) {
          if (comparator(value, array[index])) {
            return true;
          }
        }
        return false;
      }
      function last(array) {
        var length = array == null ? 0 : array.length;
        return length ? array[length - 1] : void 0;
      }
      function castFunction(value) {
        return typeof value == "function" ? value : identity;
      }
      function forEach(collection, iteratee) {
        var func = isArray$1(collection) ? arrayEach : baseEach$1;
        return func(collection, castFunction(iteratee));
      }
      var htmlEscapes = {
        "&": "&amp;",
        "<": "&lt;",
        ">": "&gt;",
        '"': "&quot;",
        "'": "&#39;"
      };
      var escapeHtmlChar = basePropertyOf(htmlEscapes);
      const escapeHtmlChar$1 = escapeHtmlChar;
      var reUnescapedHtml = /[&<>"']/g, reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
      function escape$1(string) {
        string = toString$1(string);
        return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar$1) : string;
      }
      function baseFilter(collection, predicate) {
        var result = [];
        baseEach$1(collection, function(value, index, collection2) {
          if (predicate(value, index, collection2)) {
            result.push(value);
          }
        });
        return result;
      }
      function filter(collection, predicate) {
        var func = isArray$1(collection) ? arrayFilter : baseFilter;
        return func(collection, baseIteratee(predicate));
      }
      function baseMap(collection, iteratee) {
        var index = -1, result = isArrayLike(collection) ? Array(collection.length) : [];
        baseEach$1(collection, function(value, key, collection2) {
          result[++index] = iteratee(value, key, collection2);
        });
        return result;
      }
      function map(collection, iteratee) {
        var func = isArray$1(collection) ? arrayMap : baseMap;
        return func(collection, baseIteratee(iteratee));
      }
      var objectProto$3 = Object.prototype;
      var hasOwnProperty$3 = objectProto$3.hasOwnProperty;
      var groupBy = createAggregator(function(result, value, key) {
        if (hasOwnProperty$3.call(result, key)) {
          result[key].push(value);
        } else {
          baseAssignValue(result, key, [value]);
        }
      });
      function baseValues(object, props) {
        return arrayMap(props, function(key) {
          return object[key];
        });
      }
      function values(object) {
        return object == null ? [] : baseValues(object, keys(object));
      }
      var nativeMin = Math.min;
      function baseIntersection(arrays, iteratee, comparator) {
        var includes = comparator ? arrayIncludesWith : arrayIncludes, length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array(othLength), maxLength = Infinity, result = [];
        while (othIndex--) {
          var array = arrays[othIndex];
          if (othIndex && iteratee) {
            array = arrayMap(array, baseUnary(iteratee));
          }
          maxLength = nativeMin(array.length, maxLength);
          caches[othIndex] = !comparator && (iteratee || length >= 120 && array.length >= 120) ? new SetCache(othIndex && array) : void 0;
        }
        array = arrays[0];
        var index = -1, seen = caches[0];
        outer:
          while (++index < length && result.length < maxLength) {
            var value = array[index], computed2 = iteratee ? iteratee(value) : value;
            value = comparator || value !== 0 ? value : 0;
            if (!(seen ? cacheHas(seen, computed2) : includes(result, computed2, comparator))) {
              othIndex = othLength;
              while (--othIndex) {
                var cache2 = caches[othIndex];
                if (!(cache2 ? cacheHas(cache2, computed2) : includes(arrays[othIndex], computed2, comparator))) {
                  continue outer;
                }
              }
              if (seen) {
                seen.push(computed2);
              }
              result.push(value);
            }
          }
        return result;
      }
      function castArrayLikeObject(value) {
        return isArrayLikeObject(value) ? value : [];
      }
      var intersection = baseRest(function(arrays) {
        var mapped = arrayMap(arrays, castArrayLikeObject);
        return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : [];
      });
      const intersection$1 = intersection;
      function baseInverter(object, setter, iteratee, accumulator) {
        baseForOwn(object, function(value, key, object2) {
          setter(accumulator, iteratee(value), key, object2);
        });
        return accumulator;
      }
      function createInverter(setter, toIteratee) {
        return function(object, iteratee) {
          return baseInverter(object, setter, toIteratee(iteratee), {});
        };
      }
      var objectProto$2 = Object.prototype;
      var nativeObjectToString = objectProto$2.toString;
      var invert = createInverter(function(result, value, key) {
        if (value != null && typeof value.toString != "function") {
          value = nativeObjectToString.call(value);
        }
        result[value] = key;
      }, constant(identity));
      function isEqual(value, other) {
        return baseIsEqual(value, other);
      }
      function isNil(value) {
        return value == null;
      }
      var kebabCase = createCompounder(function(result, word, index) {
        return result + (index ? "-" : "") + word.toLowerCase();
      });
      function baseLt(value, other) {
        return value < other;
      }
      function mapValues(object, iteratee) {
        var result = {};
        iteratee = baseIteratee(iteratee);
        baseForOwn(object, function(value, key, object2) {
          baseAssignValue(result, key, iteratee(value, key, object2));
        });
        return result;
      }
      function baseExtremum(array, iteratee, comparator) {
        var index = -1, length = array.length;
        while (++index < length) {
          var value = array[index], current = iteratee(value);
          if (current != null && (computed2 === void 0 ? current === current && !isSymbol(current) : comparator(current, computed2))) {
            var computed2 = current, result = value;
          }
        }
        return result;
      }
      function minBy(array, iteratee) {
        return array && array.length ? baseExtremum(array, baseIteratee(iteratee), baseLt) : void 0;
      }
      function once(func) {
        return before(2, func);
      }
      var nativeFloor = Math.floor, nativeRandom = Math.random;
      function baseRandom(lower, upper) {
        return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
      }
      function arraySample(array) {
        var length = array.length;
        return length ? array[baseRandom(0, length - 1)] : void 0;
      }
      function baseSample(collection) {
        return arraySample(values(collection));
      }
      function sample(collection) {
        var func = isArray$1(collection) ? arraySample : baseSample;
        return func(collection);
      }
      var objectProto$1 = Object.prototype;
      var hasOwnProperty$2 = objectProto$1.hasOwnProperty;
      function customDefaultsAssignIn(objValue, srcValue, key, object) {
        if (objValue === void 0 || eq(objValue, objectProto$1[key]) && !hasOwnProperty$2.call(object, key)) {
          return srcValue;
        }
        return objValue;
      }
      var stringEscapes = {
        "\\": "\\",
        "'": "'",
        "\n": "n",
        "\r": "r",
        "\u2028": "u2028",
        "\u2029": "u2029"
      };
      function escapeStringChar(chr) {
        return "\\" + stringEscapes[chr];
      }
      var reInterpolate = /<%=([\s\S]+?)%>/g;
      const reInterpolate$1 = reInterpolate;
      var reEscape = /<%-([\s\S]+?)%>/g;
      const reEscape$1 = reEscape;
      var reEvaluate = /<%([\s\S]+?)%>/g;
      const reEvaluate$1 = reEvaluate;
      var templateSettings = {
        /**
         * Used to detect `data` property values to be HTML-escaped.
         *
         * @memberOf _.templateSettings
         * @type {RegExp}
         */
        "escape": reEscape$1,
        /**
         * Used to detect code to be evaluated.
         *
         * @memberOf _.templateSettings
         * @type {RegExp}
         */
        "evaluate": reEvaluate$1,
        /**
         * Used to detect `data` property values to inject.
         *
         * @memberOf _.templateSettings
         * @type {RegExp}
         */
        "interpolate": reInterpolate$1,
        /**
         * Used to reference the data object in the template text.
         *
         * @memberOf _.templateSettings
         * @type {string}
         */
        "variable": "",
        /**
         * Used to import variables into the compiled template.
         *
         * @memberOf _.templateSettings
         * @type {Object}
         */
        "imports": {
          /**
           * A reference to the `lodash` function.
           *
           * @memberOf _.templateSettings.imports
           * @type {Function}
           */
          "_": { "escape": escape$1 }
        }
      };
      var INVALID_TEMPL_VAR_ERROR_TEXT = "Invalid `variable` option passed into `_.template`";
      var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
      var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
      var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
      var reNoMatch = /($^)/;
      var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
      var objectProto = Object.prototype;
      var hasOwnProperty$1 = objectProto.hasOwnProperty;
      function template(string, options, guard) {
        var settings2 = templateSettings.imports._.templateSettings || templateSettings;
        if (guard && isIterateeCall(string, options, guard)) {
          options = void 0;
        }
        string = toString$1(string);
        options = assignInWith({}, options, settings2, customDefaultsAssignIn);
        var imports = assignInWith({}, options.imports, settings2.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys);
        var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '";
        var reDelimiters = RegExp(
          (options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate$1 ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$",
          "g"
        );
        var sourceURL = hasOwnProperty$1.call(options, "sourceURL") ? "//# sourceURL=" + (options.sourceURL + "").replace(/\s/g, " ") + "\n" : "";
        string.replace(reDelimiters, function(match2, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
          interpolateValue || (interpolateValue = esTemplateValue);
          source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
          if (escapeValue) {
            isEscaping = true;
            source += "' +\n__e(" + escapeValue + ") +\n'";
          }
          if (evaluateValue) {
            isEvaluating = true;
            source += "';\n" + evaluateValue + ";\n__p += '";
          }
          if (interpolateValue) {
            source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
          }
          index = offset + match2.length;
          return match2;
        });
        source += "';\n";
        var variable = hasOwnProperty$1.call(options, "variable") && options.variable;
        if (!variable) {
          source = "with (obj) {\n" + source + "\n}\n";
        } else if (reForbiddenIdentifierChars.test(variable)) {
          throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
        }
        source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;");
        source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}";
        var result = attempt(function() {
          return Function(importsKeys, sourceURL + "return " + source).apply(void 0, importsValues);
        });
        result.source = source;
        if (isError(result)) {
          throw result;
        }
        return result;
      }
      var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
      function getDefaultExportFromCjs(x) {
        return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
      }
      var eventemitter3 = { exports: {} };
      (function(module2) {
        var has = Object.prototype.hasOwnProperty, prefix = "~";
        function Events() {
        }
        if (Object.create) {
          Events.prototype = /* @__PURE__ */ Object.create(null);
          if (!new Events().__proto__)
            prefix = false;
        }
        function EE(fn, context, once2) {
          this.fn = fn;
          this.context = context;
          this.once = once2 || false;
        }
        function addListener(emitter, event, fn, context, once2) {
          if (typeof fn !== "function") {
            throw new TypeError("The listener must be a function");
          }
          var listener = new EE(fn, context || emitter, once2), evt = prefix ? prefix + event : event;
          if (!emitter._events[evt])
            emitter._events[evt] = listener, emitter._eventsCount++;
          else if (!emitter._events[evt].fn)
            emitter._events[evt].push(listener);
          else
            emitter._events[evt] = [emitter._events[evt], listener];
          return emitter;
        }
        function clearEvent(emitter, evt) {
          if (--emitter._eventsCount === 0)
            emitter._events = new Events();
          else
            delete emitter._events[evt];
        }
        function EventEmitter2() {
          this._events = new Events();
          this._eventsCount = 0;
        }
        EventEmitter2.prototype.eventNames = function eventNames() {
          var names = [], events, name;
          if (this._eventsCount === 0)
            return names;
          for (name in events = this._events) {
            if (has.call(events, name))
              names.push(prefix ? name.slice(1) : name);
          }
          if (Object.getOwnPropertySymbols) {
            return names.concat(Object.getOwnPropertySymbols(events));
          }
          return names;
        };
        EventEmitter2.prototype.listeners = function listeners(event) {
          var evt = prefix ? prefix + event : event, handlers2 = this._events[evt];
          if (!handlers2)
            return [];
          if (handlers2.fn)
            return [handlers2.fn];
          for (var i = 0, l = handlers2.length, ee = new Array(l); i < l; i++) {
            ee[i] = handlers2[i].fn;
          }
          return ee;
        };
        EventEmitter2.prototype.listenerCount = function listenerCount(event) {
          var evt = prefix ? prefix + event : event, listeners = this._events[evt];
          if (!listeners)
            return 0;
          if (listeners.fn)
            return 1;
          return listeners.length;
        };
        EventEmitter2.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
          var evt = prefix ? prefix + event : event;
          if (!this._events[evt])
            return false;
          var listeners = this._events[evt], len = arguments.length, args, i;
          if (listeners.fn) {
            if (listeners.once)
              this.removeListener(event, listeners.fn, void 0, true);
            switch (len) {
              case 1:
                return listeners.fn.call(listeners.context), true;
              case 2:
                return listeners.fn.call(listeners.context, a1), true;
              case 3:
                return listeners.fn.call(listeners.context, a1, a2), true;
              case 4:
                return listeners.fn.call(listeners.context, a1, a2, a3), true;
              case 5:
                return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
              case 6:
                return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
            }
            for (i = 1, args = new Array(len - 1); i < len; i++) {
              args[i - 1] = arguments[i];
            }
            listeners.fn.apply(listeners.context, args);
          } else {
            var length = listeners.length, j;
            for (i = 0; i < length; i++) {
              if (listeners[i].once)
                this.removeListener(event, listeners[i].fn, void 0, true);
              switch (len) {
                case 1:
                  listeners[i].fn.call(listeners[i].context);
                  break;
                case 2:
                  listeners[i].fn.call(listeners[i].context, a1);
                  break;
                case 3:
                  listeners[i].fn.call(listeners[i].context, a1, a2);
                  break;
                case 4:
                  listeners[i].fn.call(listeners[i].context, a1, a2, a3);
                  break;
                default:
                  if (!args)
                    for (j = 1, args = new Array(len - 1); j < len; j++) {
                      args[j - 1] = arguments[j];
                    }
                  listeners[i].fn.apply(listeners[i].context, args);
              }
            }
          }
          return true;
        };
        EventEmitter2.prototype.on = function on(event, fn, context) {
          return addListener(this, event, fn, context, false);
        };
        EventEmitter2.prototype.once = function once2(event, fn, context) {
          return addListener(this, event, fn, context, true);
        };
        EventEmitter2.prototype.removeListener = function removeListener(event, fn, context, once2) {
          var evt = prefix ? prefix + event : event;
          if (!this._events[evt])
            return this;
          if (!fn) {
            clearEvent(this, evt);
            return this;
          }
          var listeners = this._events[evt];
          if (listeners.fn) {
            if (listeners.fn === fn && (!once2 || listeners.once) && (!context || listeners.context === context)) {
              clearEvent(this, evt);
            }
          } else {
            for (var i = 0, events = [], length = listeners.length; i < length; i++) {
              if (listeners[i].fn !== fn || once2 && !listeners[i].once || context && listeners[i].context !== context) {
                events.push(listeners[i]);
              }
            }
            if (events.length)
              this._events[evt] = events.length === 1 ? events[0] : events;
            else
              clearEvent(this, evt);
          }
          return this;
        };
        EventEmitter2.prototype.removeAllListeners = function removeAllListeners(event) {
          var evt;
          if (event) {
            evt = prefix ? prefix + event : event;
            if (this._events[evt])
              clearEvent(this, evt);
          } else {
            this._events = new Events();
            this._eventsCount = 0;
          }
          return this;
        };
        EventEmitter2.prototype.off = EventEmitter2.prototype.removeListener;
        EventEmitter2.prototype.addListener = EventEmitter2.prototype.on;
        EventEmitter2.prefixed = prefix;
        EventEmitter2.EventEmitter = EventEmitter2;
        {
          module2.exports = EventEmitter2;
        }
      })(eventemitter3);
      var eventemitter3Exports = eventemitter3.exports;
      const EventEmitter = /* @__PURE__ */ getDefaultExportFromCjs(eventemitter3Exports);
      let getRandomValues;
      const rnds8 = new Uint8Array(16);
      function rng() {
        if (!getRandomValues) {
          getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
          if (!getRandomValues) {
            throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
          }
        }
        return getRandomValues(rnds8);
      }
      const byteToHex = [];
      for (let i = 0; i < 256; ++i) {
        byteToHex.push((i + 256).toString(16).slice(1));
      }
      function unsafeStringify(arr, offset = 0) {
        return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
      }
      const randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
      const native = {
        randomUUID
      };
      function v4(options, buf, offset) {
        if (native.randomUUID && !buf && !options) {
          return native.randomUUID();
        }
        options = options || {};
        const rnds = options.random || (options.rng || rng)();
        rnds[6] = rnds[6] & 15 | 64;
        rnds[8] = rnds[8] & 63 | 128;
        if (buf) {
          offset = offset || 0;
          for (let i = 0; i < 16; ++i) {
            buf[offset + i] = rnds[i];
          }
          return buf;
        }
        return unsafeStringify(rnds);
      }
      const removeAt = (array, index) => array.splice(index, 1)[0];
      class AsyncQueue {
        constructor(thread = 1) {
          __publicField(this, "queue", vue.reactive([]));
          __publicField(this, "emitter", new EventEmitter());
          __publicField(this, "canSingleStart", () => true);
          __publicField(this, "singleRunning", false);
          this.thread = thread;
        }
        get runningThreadNum() {
          return this.queue.filter(({ running }) => running).length;
        }
        get length() {
          return this.queue.length;
        }
        push(fn, info) {
          this.queue.push({
            id: v4(),
            running: false,
            fn,
            info
          });
        }
        async start() {
          if (this.thread <= 1) {
            if (this.singleRunning || this.queue.length === 0)
              return;
            this.singleRunning = true;
            do {
              if (!this.canSingleStart()) {
                this.singleRunning = false;
                return;
              }
              await this.queue[0].fn();
              this.queue.shift();
            } while (this.queue.length > 0);
            this.singleRunning = false;
            this.emitter.emit("finish");
          } else {
            const running = this.runningThreadNum;
            if (running >= this.thread || this.queue.length === running)
              return;
            const idleItems = this.queue.filter(({ running: running2 }) => !running2);
            for (let i = 0; i < Math.min(idleItems.length, this.thread - running); i++) {
              const item = idleItems[i];
              item.running = true;
              item.fn().then(async () => {
                removeAt(
                  this.queue,
                  this.queue.findIndex(({ id }) => id === item.id)
                );
                if (this.queue.length)
                  await this.start();
                else
                  this.emitter.emit("finish");
              }).catch(logger.error);
            }
          }
        }
        async skipFromError() {
          this.queue.shift();
          await this.restartFromError();
        }
        async restartFromError() {
          this.singleRunning = false;
          await this.start();
        }
      }
      var __spreadArray = function(to, from, pack) {
        if (pack || arguments.length === 2)
          for (var i = 0, l = from.length, ar; i < l; i++) {
            if (ar || !(i in from)) {
              if (!ar)
                ar = Array.prototype.slice.call(from, 0, i);
              ar[i] = from[i];
            }
          }
        return to.concat(ar || Array.prototype.slice.call(from));
      };
      var BrowserInfo = (
        /** @class */
        /* @__PURE__ */ function() {
          function BrowserInfo2(name, version, os) {
            this.name = name;
            this.version = version;
            this.os = os;
            this.type = "browser";
          }
          return BrowserInfo2;
        }()
      );
      var NodeInfo = (
        /** @class */
        /* @__PURE__ */ function() {
          function NodeInfo2(version) {
            this.version = version;
            this.type = "node";
            this.name = "node";
            this.os = process.platform;
          }
          return NodeInfo2;
        }()
      );
      var SearchBotDeviceInfo = (
        /** @class */
        /* @__PURE__ */ function() {
          function SearchBotDeviceInfo2(name, version, os, bot) {
            this.name = name;
            this.version = version;
            this.os = os;
            this.bot = bot;
            this.type = "bot-device";
          }
          return SearchBotDeviceInfo2;
        }()
      );
      var BotInfo = (
        /** @class */
        /* @__PURE__ */ function() {
          function BotInfo2() {
            this.type = "bot";
            this.bot = true;
            this.name = "bot";
            this.version = null;
            this.os = null;
          }
          return BotInfo2;
        }()
      );
      var ReactNativeInfo = (
        /** @class */
        /* @__PURE__ */ function() {
          function ReactNativeInfo2() {
            this.type = "react-native";
            this.name = "react-native";
            this.version = null;
            this.os = null;
          }
          return ReactNativeInfo2;
        }()
      );
      var SEARCHBOX_UA_REGEX = /alexa|bot|crawl(er|ing)|facebookexternalhit|feedburner|google web preview|nagios|postrank|pingdom|slurp|spider|yahoo!|yandex/;
      var SEARCHBOT_OS_REGEX = /(nuhk|curl|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask\ Jeeves\/Teoma|ia_archiver)/;
      var REQUIRED_VERSION_PARTS = 3;
      var userAgentRules = [
        ["aol", /AOLShield\/([0-9\._]+)/],
        ["edge", /Edge\/([0-9\._]+)/],
        ["edge-ios", /EdgiOS\/([0-9\._]+)/],
        ["yandexbrowser", /YaBrowser\/([0-9\._]+)/],
        ["kakaotalk", /KAKAOTALK\s([0-9\.]+)/],
        ["samsung", /SamsungBrowser\/([0-9\.]+)/],
        ["silk", /\bSilk\/([0-9._-]+)\b/],
        ["miui", /MiuiBrowser\/([0-9\.]+)$/],
        ["beaker", /BeakerBrowser\/([0-9\.]+)/],
        ["edge-chromium", /EdgA?\/([0-9\.]+)/],
        [
          "chromium-webview",
          /(?!Chrom.*OPR)wv\).*Chrom(?:e|ium)\/([0-9\.]+)(:?\s|$)/
        ],
        ["chrome", /(?!Chrom.*OPR)Chrom(?:e|ium)\/([0-9\.]+)(:?\s|$)/],
        ["phantomjs", /PhantomJS\/([0-9\.]+)(:?\s|$)/],
        ["crios", /CriOS\/([0-9\.]+)(:?\s|$)/],
        ["firefox", /Firefox\/([0-9\.]+)(?:\s|$)/],
        ["fxios", /FxiOS\/([0-9\.]+)/],
        ["opera-mini", /Opera Mini.*Version\/([0-9\.]+)/],
        ["opera", /Opera\/([0-9\.]+)(?:\s|$)/],
        ["opera", /OPR\/([0-9\.]+)(:?\s|$)/],
        ["pie", /^Microsoft Pocket Internet Explorer\/(\d+\.\d+)$/],
        ["pie", /^Mozilla\/\d\.\d+\s\(compatible;\s(?:MSP?IE|MSInternet Explorer) (\d+\.\d+);.*Windows CE.*\)$/],
        ["netfront", /^Mozilla\/\d\.\d+.*NetFront\/(\d.\d)/],
        ["ie", /Trident\/7\.0.*rv\:([0-9\.]+).*\).*Gecko$/],
        ["ie", /MSIE\s([0-9\.]+);.*Trident\/[4-7].0/],
        ["ie", /MSIE\s(7\.0)/],
        ["bb10", /BB10;\sTouch.*Version\/([0-9\.]+)/],
        ["android", /Android\s([0-9\.]+)/],
        ["ios", /Version\/([0-9\._]+).*Mobile.*Safari.*/],
        ["safari", /Version\/([0-9\._]+).*Safari/],
        ["facebook", /FB[AS]V\/([0-9\.]+)/],
        ["instagram", /Instagram\s([0-9\.]+)/],
        ["ios-webview", /AppleWebKit\/([0-9\.]+).*Mobile/],
        ["ios-webview", /AppleWebKit\/([0-9\.]+).*Gecko\)$/],
        ["curl", /^curl\/([0-9\.]+)$/],
        ["searchbot", SEARCHBOX_UA_REGEX]
      ];
      var operatingSystemRules = [
        ["iOS", /iP(hone|od|ad)/],
        ["Android OS", /Android/],
        ["BlackBerry OS", /BlackBerry|BB10/],
        ["Windows Mobile", /IEMobile/],
        ["Amazon OS", /Kindle/],
        ["Windows 3.11", /Win16/],
        ["Windows 95", /(Windows 95)|(Win95)|(Windows_95)/],
        ["Windows 98", /(Windows 98)|(Win98)/],
        ["Windows 2000", /(Windows NT 5.0)|(Windows 2000)/],
        ["Windows XP", /(Windows NT 5.1)|(Windows XP)/],
        ["Windows Server 2003", /(Windows NT 5.2)/],
        ["Windows Vista", /(Windows NT 6.0)/],
        ["Windows 7", /(Windows NT 6.1)/],
        ["Windows 8", /(Windows NT 6.2)/],
        ["Windows 8.1", /(Windows NT 6.3)/],
        ["Windows 10", /(Windows NT 10.0)/],
        ["Windows ME", /Windows ME/],
        ["Windows CE", /Windows CE|WinCE|Microsoft Pocket Internet Explorer/],
        ["Open BSD", /OpenBSD/],
        ["Sun OS", /SunOS/],
        ["Chrome OS", /CrOS/],
        ["Linux", /(Linux)|(X11)/],
        ["Mac OS", /(Mac_PowerPC)|(Macintosh)/],
        ["QNX", /QNX/],
        ["BeOS", /BeOS/],
        ["OS/2", /OS\/2/]
      ];
      function detect(userAgent) {
        if (!!userAgent) {
          return parseUserAgent(userAgent);
        }
        if (typeof document === "undefined" && typeof navigator !== "undefined" && navigator.product === "ReactNative") {
          return new ReactNativeInfo();
        }
        if (typeof navigator !== "undefined") {
          return parseUserAgent(navigator.userAgent);
        }
        return getNodeVersion();
      }
      function matchUserAgent(ua) {
        return ua !== "" && userAgentRules.reduce(function(matched, _a) {
          var browser = _a[0], regex = _a[1];
          if (matched) {
            return matched;
          }
          var uaMatch = regex.exec(ua);
          return !!uaMatch && [browser, uaMatch];
        }, false);
      }
      function parseUserAgent(ua) {
        var matchedRule = matchUserAgent(ua);
        if (!matchedRule) {
          return null;
        }
        var name = matchedRule[0], match2 = matchedRule[1];
        if (name === "searchbot") {
          return new BotInfo();
        }
        var versionParts = match2[1] && match2[1].split(".").join("_").split("_").slice(0, 3);
        if (versionParts) {
          if (versionParts.length < REQUIRED_VERSION_PARTS) {
            versionParts = __spreadArray(__spreadArray([], versionParts, true), createVersionParts(REQUIRED_VERSION_PARTS - versionParts.length), true);
          }
        } else {
          versionParts = [];
        }
        var version = versionParts.join(".");
        var os = detectOS(ua);
        var searchBotMatch = SEARCHBOT_OS_REGEX.exec(ua);
        if (searchBotMatch && searchBotMatch[1]) {
          return new SearchBotDeviceInfo(name, version, os, searchBotMatch[1]);
        }
        return new BrowserInfo(name, version, os);
      }
      function detectOS(ua) {
        for (var ii = 0, count = operatingSystemRules.length; ii < count; ii++) {
          var _a = operatingSystemRules[ii], os = _a[0], regex = _a[1];
          var match2 = regex.exec(ua);
          if (match2) {
            return os;
          }
        }
        return null;
      }
      function getNodeVersion() {
        var isNode = typeof process !== "undefined" && process.version;
        return isNode ? new NodeInfo(process.version.slice(1)) : null;
      }
      function createVersionParts(count) {
        var output = [];
        for (var ii = 0; ii < count; ii++) {
          output.push("0");
        }
        return output;
      }
      const supportLanguage = /* @__PURE__ */ new Set(["zh", "en"]);
      const defaultLocale = (() => {
        const languages = castArray(navigator.languages || navigator.language);
        for (const language of languages) {
          const lang = language.split("-")[0];
          if (supportLanguage.has(lang))
            return lang;
        }
        return "en";
      })();
      const nHentaiDownloadHosts = [
        "i.nhentai.net",
        "i2.nhentai.net",
        "i3.nhentai.net",
        "i5.nhentai.net",
        "i7.nhentai.net"
      ];
      var NHentaiDownloadHostSpecial = /* @__PURE__ */ ((NHentaiDownloadHostSpecial2) => {
        NHentaiDownloadHostSpecial2["RANDOM"] = "random";
        NHentaiDownloadHostSpecial2["BALANCE"] = "balance";
        return NHentaiDownloadHostSpecial2;
      })(NHentaiDownloadHostSpecial || {});
      const booleanValidator = (val) => typeof val === "boolean";
      const stringValidator = (val) => typeof val === "string";
      const createNumberValidator = (min, max) => (val) => typeof val === "number" && min <= val && val <= max;
      const trimFormatter = (val) => val.trim();
      const availableMetaFiles = ["ComicInfoXml", "EzeInfoJson"];
      const availableMetaFileTitleLanguage = /* @__PURE__ */ new Set(["english", "japanese"]);
      const settingDefinitions = {
        language: {
          key: "language",
          default: defaultLocale,
          validator: (val) => supportLanguage.has(val)
        },
        threadNum: {
          key: "thread_num",
          default: 8,
          validator: createNumberValidator(1, 32),
          formatter: (val) => Math.floor(val)
        },
        openOnNewTab: {
          key: "open_on_new_tab",
          default: true,
          validator: booleanValidator
        },
        customDownloadUrl: {
          key: "custom_download_url",
          default: "",
          validator: stringValidator,
          formatter: trimFormatter
        },
        compressionFilename: {
          key: "cf_name",
          default: "{{japanese}}.zip",
          validator: stringValidator,
          formatter: trimFormatter
        },
        filenameMaxArtistsNumber: {
          key: "cf_name_max_artists_number",
          default: 3,
          validator: createNumberValidator(0, Infinity)
        },
        filenameArtistsSeparator: {
          key: "cf_name_artists_separator",
          default: ", ",
          validator: stringValidator
        },
        compressionLevel: {
          key: "c_lv",
          default: 0,
          validator: createNumberValidator(0, 9),
          formatter: (val) => Math.floor(val)
        },
        compressionStreamFiles: {
          key: "c_stream_files",
          default: false,
          validator: booleanValidator
        },
        streamDownload: {
          key: "stream_download",
          default: false,
          validator: booleanValidator
        },
        seriesMode: {
          key: "series_mode",
          default: false,
          validator: booleanValidator
        },
        filenameLength: {
          key: "filename_length",
          default: 0,
          validator: (val) => val === "auto" || typeof val === "number" && val >= 0,
          formatter: (val) => typeof val === "number" ? Math.floor(val) : val
        },
        autoCancelDownloadedManga: {
          key: "auto_cancel_downloaded_doujin",
          default: false,
          validator: booleanValidator
        },
        autoRetryWhenErrorOccurs: {
          key: "auto_retry_when_error_occurs",
          default: false,
          validator: booleanValidator
        },
        autoShowAll: {
          key: "auto_show_all",
          default: false,
          validator: booleanValidator
        },
        showIgnoreButton: {
          key: "show_ignore_button",
          default: false,
          validator: booleanValidator
        },
        preventConsoleClearing: {
          key: "prevent_console_clear",
          default: false,
          validator: booleanValidator
        },
        judgeDownloadedByEnglish: {
          key: "judge_downloaded_by_english",
          default: false,
          validator: booleanValidator
        },
        judgeDownloadedByJapanese: {
          key: "judge_downloaded_by_japanese",
          default: true,
          validator: booleanValidator
        },
        judgeDownloadedByPretty: {
          key: "judge_downloaded_by_pretty",
          default: false,
          validator: booleanValidator
        },
        nHentaiDownloadHost: {
          key: "nHentai_media_host",
          default: nHentaiDownloadHosts[0],
          validator: (val) => val === "random" || val === "balance" || nHentaiDownloadHosts.includes(val)
        },
        addMetaFile: {
          key: "add_meta_file",
          default: () => [],
          validator: (val) => Array.isArray(val),
          formatter: (val) => intersection$1(val, availableMetaFiles)
        },
        metaFileTitleLanguage: {
          key: "meta_file_title_language",
          default: "english",
          validator: (val) => availableMetaFileTitleLanguage.has(val)
        },
        titleReplacement: {
          key: "title_replacement",
          default: () => [],
          validator: (val) => Array.isArray(val),
          itemValidator: (item) => item && stringValidator(item.from) && stringValidator(item.to) && booleanValidator(item.regexp)
        }
      };
      const browserDetect = detect();
      const DISABLE_STREAM_DOWNLOAD = !!browserDetect && (browserDetect.name === "safari" || browserDetect.name === "firefox");
      const readSettings = () => mapValues(
        settingDefinitions,
        ({ key, default: defaultVal }) => _GM_getValue(key, typeof defaultVal === "function" ? defaultVal() : defaultVal)
      );
      const writeableSettings = vue.reactive(readSettings());
      const settings = writeableSettings;
      if (DISABLE_STREAM_DOWNLOAD && settings.streamDownload)
        writeableSettings.streamDownload = false;
      const startWatchSettings = once(() => {
        const settingRefs = vue.toRefs(writeableSettings);
        forEach(settingRefs, (ref2, key) => {
          const cur = settingDefinitions[key];
          let valChanged = false;
          const saveValue = (val) => {
            logger.log("update setting", cur.key, vue.toRaw(val));
            _GM_setValue(cur.key, val);
          };
          vue.watch(
            ref2,
            (val) => {
              if (valChanged) {
                valChanged = false;
                saveValue(val);
                return;
              }
              const applyChange = (newVal) => {
                val = newVal;
                ref2.value = newVal;
                valChanged = true;
              };
              if (!cur.validator(val)) {
                applyChange(typeof cur.default === "function" ? cur.default() : cur.default);
                return;
              }
              if (Array.isArray(val) && cur.itemValidator) {
                const validItems = val.filter(cur.itemValidator);
                if (val.length !== validItems.length) {
                  applyChange(validItems);
                }
              }
              if (cur.formatter) {
                const formattedVal = cur.formatter(val);
                if (typeof formattedVal === "object" ? !isEqual(val, formattedVal) : val !== formattedVal) {
                  applyChange(formattedVal);
                }
              }
              if (!valChanged)
                saveValue(val);
            },
            typeof ref2.value === "object" ? { deep: true } : void 0
          );
        });
      });
      const validTitleReplacement = vue.computed(
        () => settings.titleReplacement.filter((item) => item == null ? void 0 : item.from)
      );
      const dlQueue = new AsyncQueue();
      const zipQueue = new AsyncQueue(WORKER_THREAD_NUM);
      dlQueue.canSingleStart = () => !(settings.seriesMode && zipQueue.length);
      zipQueue.emitter.on("finish", () => {
        if (settings.seriesMode)
          dlQueue.start().catch(logger.error);
      });
      const _withScopeId = (n) => (vue.pushScopeId("data-v-83b954f2"), n = n(), vue.popScopeId(), n);
      const _hoisted_1$3 = ["title"];
      const _hoisted_2$1 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("i", { class: "fa fa-times" }, null, -1));
      const _hoisted_3$1 = [
        _hoisted_2$1
      ];
      const _hoisted_4$1 = { class: "download-item__title" };
      const _hoisted_5$1 = { class: "download-item__progress-text" };
      const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({
        __name: "DownloadItem",
        props: {
          item: {},
          index: {}
        },
        setup(__props) {
          const props = __props;
          const title = vue.computed(() => {
            const { english: english2, japanese: japanese2, pretty } = props.item.gallery.title;
            return japanese2 || english2 || pretty;
          });
          const progressWidth = vue.computed(() => {
            const {
              gallery: { pages: pages2 },
              done,
              compressing,
              compressingPercent
            } = props.item;
            const page = pages2.length;
            return compressing ? compressingPercent : page && done ? (100 * done / page).toFixed(2) : 0;
          });
          const canCancel = vue.computed(() => !props.item.compressing);
          const cancel = () => {
            var _a;
            const { info } = props.index === 0 ? dlQueue.queue[0] : removeAt(dlQueue.queue, props.index);
            (_a = info == null ? void 0 : info.cancel) == null ? void 0 : _a.call(info);
          };
          return (_ctx, _cache) => {
            return vue.openBlock(), vue.createElementBlock("div", {
              class: vue.normalizeClass(["download-item", {
                "download-item--error": _ctx.item.error,
                "download-item--compressing": _ctx.item.compressing && !_ctx.item.error,
                "download-item--can-cancel": canCancel.value
              }]),
              title: title.value
            }, [
              canCancel.value ? (vue.openBlock(), vue.createElementBlock("div", {
                key: 0,
                class: "download-item__cancel",
                onClick: cancel
              }, _hoisted_3$1)) : vue.createCommentVNode("", true),
              vue.createElementVNode("div", _hoisted_4$1, vue.toDisplayString(title.value), 1),
              vue.createElementVNode("div", {
                class: "download-item__progress",
                style: vue.normalizeStyle({ width: `${progressWidth.value}%` })
              }, [
                vue.createElementVNode("div", _hoisted_5$1, vue.toDisplayString(progressWidth.value) + "%", 1)
              ], 4)
            ], 10, _hoisted_1$3);
          };
        }
      });
      const _export_sfc = (sfc, props) => {
        const target = sfc.__vccOpts || sfc;
        for (const [key, val] of props) {
          target[key] = val;
        }
        return target;
      };
      const DownloadItem = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-83b954f2"]]);
      const _hoisted_1$2 = { id: "download-panel" };
      const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
        __name: "DownloadList",
        props: {
          zipList: {},
          dlList: {}
        },
        setup(__props) {
          return (_ctx, _cache) => {
            return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2, [
              (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.zipList, (item, index) => {
                return vue.openBlock(), vue.createBlock(DownloadItem, {
                  key: index,
                  item,
                  index
                }, null, 8, ["item", "index"]);
              }), 128)),
              (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.dlList, (item, index) => {
                return vue.openBlock(), vue.createBlock(DownloadItem, {
                  key: index,
                  item,
                  index
                }, null, 8, ["item", "index"]);
              }), 128))
            ]);
          };
        }
      });
      const DownloadList = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-f37e74c3"]]);
      const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
        __name: "DownloadPanel",
        setup(__props) {
          const { title } = document;
          const zipList = vue.computed(() => zipQueue.queue.map(({ info }) => info));
          const dlList = vue.computed(() => dlQueue.queue.map(({ info }) => info));
          const infoList = vue.computed(() => [...zipList.value, ...dlList.value]);
          const error = vue.computed(() => {
            var _a;
            return !!((_a = dlList.value[0]) == null ? void 0 : _a.error);
          });
          const titleWithStatus = vue.computed(() => {
            if (error.value)
              return `[×] ${title}`;
            const len = infoList.value.length;
            return `[${len || "✓"}] ${title}`;
          });
          vue.watch(infoList, (val) => {
            sessionStorage.setItem("downloadQueue", JSON.stringify(val.map(({ gallery: gallery2 }) => gallery2)));
          });
          vue.watch(titleWithStatus, (val) => {
            document.title = val;
          });
          return (_ctx, _cache) => {
            return infoList.value.length ? (vue.openBlock(), vue.createBlock(DownloadList, {
              key: 0,
              "zip-list": zipList.value,
              "dl-list": dlList.value
            }, null, 8, ["zip-list", "dl-list"])) : vue.createCommentVNode("", true);
          };
        }
      });
      /*! Element Plus Icons Vue v2.3.1 */
      var delete_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ vue.defineComponent({
        name: "Delete",
        __name: "delete",
        setup(__props) {
          return (_ctx, _cache) => (vue.openBlock(), vue.createElementBlock("svg", {
            xmlns: "http://www.w3.org/2000/svg",
            viewBox: "0 0 1024 1024"
          }, [
            vue.createElementVNode("path", {
              fill: "currentColor",
              d: "M160 256H96a32 32 0 0 1 0-64h256V95.936a32 32 0 0 1 32-32h256a32 32 0 0 1 32 32V192h256a32 32 0 1 1 0 64h-64v672a32 32 0 0 1-32 32H192a32 32 0 0 1-32-32zm448-64v-64H416v64zM224 896h576V256H224zm192-128a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32m192 0a32 32 0 0 1-32-32V416a32 32 0 0 1 64 0v320a32 32 0 0 1-32 32"
            })
          ]));
        }
      });
      var delete_default = delete_vue_vue_type_script_setup_true_lang_default;
      var download_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ vue.defineComponent({
        name: "Download",
        __name: "download",
        setup(__props) {
          return (_ctx, _cache) => (vue.openBlock(), vue.createElementBlock("svg", {
            xmlns: "http://www.w3.org/2000/svg",
            viewBox: "0 0 1024 1024"
          }, [
            vue.createElementVNode("path", {
              fill: "currentColor",
              d: "M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64m384-253.696 236.288-236.352 45.248 45.248L508.8 704 192 387.2l45.248-45.248L480 584.704V128h64z"
            })
          ]));
        }
      });
      var download_default = download_vue_vue_type_script_setup_true_lang_default;
      var upload_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ vue.defineComponent({
        name: "Upload",
        __name: "upload",
        setup(__props) {
          return (_ctx, _cache) => (vue.openBlock(), vue.createElementBlock("svg", {
            xmlns: "http://www.w3.org/2000/svg",
            viewBox: "0 0 1024 1024"
          }, [
            vue.createElementVNode("path", {
              fill: "currentColor",
              d: "M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64m384-578.304V704h-64V247.296L237.248 490.048 192 444.8 508.8 128l316.8 316.8-45.312 45.248z"
            })
          ]));
        }
      });
      var upload_default = upload_vue_vue_type_script_setup_true_lang_default;
      /*!
        * shared v9.12.1
        * (c) 2024 kazuya kawaguchi
        * Released under the MIT License.
        */
      const inBrowser = typeof window !== "undefined";
      const makeSymbol = (name, shareable = false) => !shareable ? Symbol(name) : Symbol.for(name);
      const generateFormatCacheKey = (locale, key, source) => friendlyJSONstringify({ l: locale, k: key, s: source });
      const friendlyJSONstringify = (json) => JSON.stringify(json).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029").replace(/\u0027/g, "\\u0027");
      const isNumber = (val) => typeof val === "number" && isFinite(val);
      const isDate = (val) => toTypeString(val) === "[object Date]";
      const isRegExp = (val) => toTypeString(val) === "[object RegExp]";
      const isEmptyObject = (val) => isPlainObject(val) && Object.keys(val).length === 0;
      const assign$1 = Object.assign;
      let _globalThis;
      const getGlobalThis = () => {
        return _globalThis || (_globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {});
      };
      function escapeHtml(rawText) {
        return rawText.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
      }
      const hasOwnProperty = Object.prototype.hasOwnProperty;
      function hasOwn(obj, key) {
        return hasOwnProperty.call(obj, key);
      }
      const isArray = Array.isArray;
      const isFunction = (val) => typeof val === "function";
      const isString$1 = (val) => typeof val === "string";
      const isBoolean = (val) => typeof val === "boolean";
      const isObject$3 = (val) => val !== null && typeof val === "object";
      const isPromise = (val) => {
        return isObject$3(val) && isFunction(val.then) && isFunction(val.catch);
      };
      const objectToString = Object.prototype.toString;
      const toTypeString = (value) => objectToString.call(value);
      const isPlainObject = (val) => {
        if (!isObject$3(val))
          return false;
        const proto = Object.getPrototypeOf(val);
        return proto === null || proto.constructor === Object;
      };
      const toDisplayString = (val) => {
        return val == null ? "" : isArray(val) || isPlainObject(val) && val.toString === objectToString ? JSON.stringify(val, null, 2) : String(val);
      };
      function join$1(items, separator = "") {
        return items.reduce((str, item, index) => index === 0 ? str + item : str + separator + item, "");
      }
      function incrementer(code2) {
        let current = code2;
        return () => ++current;
      }
      function warn(msg, err) {
        if (typeof console !== "undefined") {
          console.warn(`[intlify] ` + msg);
          if (err) {
            console.warn(err.stack);
          }
        }
      }
      const isNotObjectOrIsArray = (val) => !isObject$3(val) || isArray(val);
      function deepCopy(src, des) {
        if (isNotObjectOrIsArray(src) || isNotObjectOrIsArray(des)) {
          throw new Error("Invalid value");
        }
        const stack = [{ src, des }];
        while (stack.length) {
          const { src: src2, des: des2 } = stack.pop();
          Object.keys(src2).forEach((key) => {
            if (isNotObjectOrIsArray(src2[key]) || isNotObjectOrIsArray(des2[key])) {
              des2[key] = src2[key];
            } else {
              stack.push({ src: src2[key], des: des2[key] });
            }
          });
        }
      }
      /*!
        * message-compiler v9.12.1
        * (c) 2024 kazuya kawaguchi
        * Released under the MIT License.
        */
      function createPosition(line, column, offset) {
        return { line, column, offset };
      }
      function createLocation(start, end, source) {
        const loc = { start, end };
        if (source != null) {
          loc.source = source;
        }
        return loc;
      }
      const RE_ARGS = /\{([0-9a-zA-Z]+)\}/g;
      function format$1(message, ...args) {
        if (args.length === 1 && isObject$2(args[0])) {
          args = args[0];
        }
        if (!args || !args.hasOwnProperty) {
          args = {};
        }
        return message.replace(RE_ARGS, (match2, identifier) => {
          return args.hasOwnProperty(identifier) ? args[identifier] : "";
        });
      }
      const assign = Object.assign;
      const isString = (val) => typeof val === "string";
      const isObject$2 = (val) => val !== null && typeof val === "object";
      function join(items, separator = "") {
        return items.reduce((str, item, index) => index === 0 ? str + item : str + separator + item, "");
      }
      const CompileWarnCodes = {
        USE_MODULO_SYNTAX: 1,
        __EXTEND_POINT__: 2
      };
      const warnMessages = {
        [CompileWarnCodes.USE_MODULO_SYNTAX]: `Use modulo before '{{0}}'.`
      };
      function createCompileWarn(code2, loc, ...args) {
        const msg = format$1(warnMessages[code2] || "", ...args || []);
        const message = { message: String(msg), code: code2 };
        if (loc) {
          message.location = loc;
        }
        return message;
      }
      const CompileErrorCodes = {
        // tokenizer error codes
        EXPECTED_TOKEN: 1,
        INVALID_TOKEN_IN_PLACEHOLDER: 2,
        UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER: 3,
        UNKNOWN_ESCAPE_SEQUENCE: 4,
        INVALID_UNICODE_ESCAPE_SEQUENCE: 5,
        UNBALANCED_CLOSING_BRACE: 6,
        UNTERMINATED_CLOSING_BRACE: 7,
        EMPTY_PLACEHOLDER: 8,
        NOT_ALLOW_NEST_PLACEHOLDER: 9,
        INVALID_LINKED_FORMAT: 10,
        // parser error codes
        MUST_HAVE_MESSAGES_IN_PLURAL: 11,
        UNEXPECTED_EMPTY_LINKED_MODIFIER: 12,
        UNEXPECTED_EMPTY_LINKED_KEY: 13,
        UNEXPECTED_LEXICAL_ANALYSIS: 14,
        // generator error codes
        UNHANDLED_CODEGEN_NODE_TYPE: 15,
        // minifier error codes
        UNHANDLED_MINIFIER_NODE_TYPE: 16,
        // Special value for higher-order compilers to pick up the last code
        // to avoid collision of error codes. This should always be kept as the last
        // item.
        __EXTEND_POINT__: 17
      };
      const errorMessages = {
        // tokenizer error messages
        [CompileErrorCodes.EXPECTED_TOKEN]: `Expected token: '{0}'`,
        [CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER]: `Invalid token in placeholder: '{0}'`,
        [CompileErrorCodes.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER]: `Unterminated single quote in placeholder`,
        [CompileErrorCodes.UNKNOWN_ESCAPE_SEQUENCE]: `Unknown escape sequence: \\{0}`,
        [CompileErrorCodes.INVALID_UNICODE_ESCAPE_SEQUENCE]: `Invalid unicode escape sequence: {0}`,
        [CompileErrorCodes.UNBALANCED_CLOSING_BRACE]: `Unbalanced closing brace`,
        [CompileErrorCodes.UNTERMINATED_CLOSING_BRACE]: `Unterminated closing brace`,
        [CompileErrorCodes.EMPTY_PLACEHOLDER]: `Empty placeholder`,
        [CompileErrorCodes.NOT_ALLOW_NEST_PLACEHOLDER]: `Not allowed nest placeholder`,
        [CompileErrorCodes.INVALID_LINKED_FORMAT]: `Invalid linked format`,
        // parser error messages
        [CompileErrorCodes.MUST_HAVE_MESSAGES_IN_PLURAL]: `Plural must have messages`,
        [CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_MODIFIER]: `Unexpected empty linked modifier`,
        [CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_KEY]: `Unexpected empty linked key`,
        [CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS]: `Unexpected lexical analysis in token: '{0}'`,
        // generator error messages
        [CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE]: `unhandled codegen node type: '{0}'`,
        // minimizer error messages
        [CompileErrorCodes.UNHANDLED_MINIFIER_NODE_TYPE]: `unhandled mimifier node type: '{0}'`
      };
      function createCompileError(code2, loc, options = {}) {
        const { domain, messages, args } = options;
        const msg = format$1((messages || errorMessages)[code2] || "", ...args || []);
        const error = new SyntaxError(String(msg));
        error.code = code2;
        if (loc) {
          error.location = loc;
        }
        error.domain = domain;
        return error;
      }
      function defaultOnError(error) {
        throw error;
      }
      const CHAR_SP = " ";
      const CHAR_CR = "\r";
      const CHAR_LF = "\n";
      const CHAR_LS = String.fromCharCode(8232);
      const CHAR_PS = String.fromCharCode(8233);
      function createScanner(str) {
        const _buf = str;
        let _index = 0;
        let _line = 1;
        let _column = 1;
        let _peekOffset = 0;
        const isCRLF = (index2) => _buf[index2] === CHAR_CR && _buf[index2 + 1] === CHAR_LF;
        const isLF = (index2) => _buf[index2] === CHAR_LF;
        const isPS = (index2) => _buf[index2] === CHAR_PS;
        const isLS = (index2) => _buf[index2] === CHAR_LS;
        const isLineEnd = (index2) => isCRLF(index2) || isLF(index2) || isPS(index2) || isLS(index2);
        const index = () => _index;
        const line = () => _line;
        const column = () => _column;
        const peekOffset = () => _peekOffset;
        const charAt = (offset) => isCRLF(offset) || isPS(offset) || isLS(offset) ? CHAR_LF : _buf[offset];
        const currentChar = () => charAt(_index);
        const currentPeek = () => charAt(_index + _peekOffset);
        function next() {
          _peekOffset = 0;
          if (isLineEnd(_index)) {
            _line++;
            _column = 0;
          }
          if (isCRLF(_index)) {
            _index++;
          }
          _index++;
          _column++;
          return _buf[_index];
        }
        function peek() {
          if (isCRLF(_index + _peekOffset)) {
            _peekOffset++;
          }
          _peekOffset++;
          return _buf[_index + _peekOffset];
        }
        function reset() {
          _index = 0;
          _line = 1;
          _column = 1;
          _peekOffset = 0;
        }
        function resetPeek(offset = 0) {
          _peekOffset = offset;
        }
        function skipToPeek() {
          const target = _index + _peekOffset;
          while (target !== _index) {
            next();
          }
          _peekOffset = 0;
        }
        return {
          index,
          line,
          column,
          peekOffset,
          charAt,
          currentChar,
          currentPeek,
          next,
          peek,
          reset,
          resetPeek,
          skipToPeek
        };
      }
      const EOF = void 0;
      const DOT = ".";
      const LITERAL_DELIMITER = "'";
      const ERROR_DOMAIN$3 = "tokenizer";
      function createTokenizer(source, options = {}) {
        const location2 = options.location !== false;
        const _scnr = createScanner(source);
        const currentOffset = () => _scnr.index();
        const currentPosition = () => createPosition(_scnr.line(), _scnr.column(), _scnr.index());
        const _initLoc = currentPosition();
        const _initOffset = currentOffset();
        const _context = {
          currentType: 14,
          offset: _initOffset,
          startLoc: _initLoc,
          endLoc: _initLoc,
          lastType: 14,
          lastOffset: _initOffset,
          lastStartLoc: _initLoc,
          lastEndLoc: _initLoc,
          braceNest: 0,
          inLinked: false,
          text: ""
        };
        const context = () => _context;
        const { onError } = options;
        function emitError(code2, pos, offset, ...args) {
          const ctx = context();
          pos.column += offset;
          pos.offset += offset;
          if (onError) {
            const loc = location2 ? createLocation(ctx.startLoc, pos) : null;
            const err = createCompileError(code2, loc, {
              domain: ERROR_DOMAIN$3,
              args
            });
            onError(err);
          }
        }
        function getToken(context2, type, value) {
          context2.endLoc = currentPosition();
          context2.currentType = type;
          const token = { type };
          if (location2) {
            token.loc = createLocation(context2.startLoc, context2.endLoc);
          }
          if (value != null) {
            token.value = value;
          }
          return token;
        }
        const getEndToken = (context2) => getToken(
          context2,
          14
          /* TokenTypes.EOF */
        );
        function eat(scnr, ch) {
          if (scnr.currentChar() === ch) {
            scnr.next();
            return ch;
          } else {
            emitError(CompileErrorCodes.EXPECTED_TOKEN, currentPosition(), 0, ch);
            return "";
          }
        }
        function peekSpaces(scnr) {
          let buf = "";
          while (scnr.currentPeek() === CHAR_SP || scnr.currentPeek() === CHAR_LF) {
            buf += scnr.currentPeek();
            scnr.peek();
          }
          return buf;
        }
        function skipSpaces(scnr) {
          const buf = peekSpaces(scnr);
          scnr.skipToPeek();
          return buf;
        }
        function isIdentifierStart(ch) {
          if (ch === EOF) {
            return false;
          }
          const cc = ch.charCodeAt(0);
          return cc >= 97 && cc <= 122 || // a-z
          cc >= 65 && cc <= 90 || // A-Z
          cc === 95;
        }
        function isNumberStart(ch) {
          if (ch === EOF) {
            return false;
          }
          const cc = ch.charCodeAt(0);
          return cc >= 48 && cc <= 57;
        }
        function isNamedIdentifierStart(scnr, context2) {
          const { currentType } = context2;
          if (currentType !== 2) {
            return false;
          }
          peekSpaces(scnr);
          const ret = isIdentifierStart(scnr.currentPeek());
          scnr.resetPeek();
          return ret;
        }
        function isListIdentifierStart(scnr, context2) {
          const { currentType } = context2;
          if (currentType !== 2) {
            return false;
          }
          peekSpaces(scnr);
          const ch = scnr.currentPeek() === "-" ? scnr.peek() : scnr.currentPeek();
          const ret = isNumberStart(ch);
          scnr.resetPeek();
          return ret;
        }
        function isLiteralStart(scnr, context2) {
          const { currentType } = context2;
          if (currentType !== 2) {
            return false;
          }
          peekSpaces(scnr);
          const ret = scnr.currentPeek() === LITERAL_DELIMITER;
          scnr.resetPeek();
          return ret;
        }
        function isLinkedDotStart(scnr, context2) {
          const { currentType } = context2;
          if (currentType !== 8) {
            return false;
          }
          peekSpaces(scnr);
          const ret = scnr.currentPeek() === ".";
          scnr.resetPeek();
          return ret;
        }
        function isLinkedModifierStart(scnr, context2) {
          const { currentType } = context2;
          if (currentType !== 9) {
            return false;
          }
          peekSpaces(scnr);
          const ret = isIdentifierStart(scnr.currentPeek());
          scnr.resetPeek();
          return ret;
        }
        function isLinkedDelimiterStart(scnr, context2) {
          const { currentType } = context2;
          if (!(currentType === 8 || currentType === 12)) {
            return false;
          }
          peekSpaces(scnr);
          const ret = scnr.currentPeek() === ":";
          scnr.resetPeek();
          return ret;
        }
        function isLinkedReferStart(scnr, context2) {
          const { currentType } = context2;
          if (currentType !== 10) {
            return false;
          }
          const fn = () => {
            const ch = scnr.currentPeek();
            if (ch === "{") {
              return isIdentifierStart(scnr.peek());
            } else if (ch === "@" || ch === "%" || ch === "|" || ch === ":" || ch === "." || ch === CHAR_SP || !ch) {
              return false;
            } else if (ch === CHAR_LF) {
              scnr.peek();
              return fn();
            } else {
              return isIdentifierStart(ch);
            }
          };
          const ret = fn();
          scnr.resetPeek();
          return ret;
        }
        function isPluralStart(scnr) {
          peekSpaces(scnr);
          const ret = scnr.currentPeek() === "|";
          scnr.resetPeek();
          return ret;
        }
        function detectModuloStart(scnr) {
          const spaces = peekSpaces(scnr);
          const ret = scnr.currentPeek() === "%" && scnr.peek() === "{";
          scnr.resetPeek();
          return {
            isModulo: ret,
            hasSpace: spaces.length > 0
          };
        }
        function isTextStart(scnr, reset = true) {
          const fn = (hasSpace = false, prev = "", detectModulo = false) => {
            const ch = scnr.currentPeek();
            if (ch === "{") {
              return prev === "%" ? false : hasSpace;
            } else if (ch === "@" || !ch) {
              return prev === "%" ? true : hasSpace;
            } else if (ch === "%") {
              scnr.peek();
              return fn(hasSpace, "%", true);
            } else if (ch === "|") {
              return prev === "%" || detectModulo ? true : !(prev === CHAR_SP || prev === CHAR_LF);
            } else if (ch === CHAR_SP) {
              scnr.peek();
              return fn(true, CHAR_SP, detectModulo);
            } else if (ch === CHAR_LF) {
              scnr.peek();
              return fn(true, CHAR_LF, detectModulo);
            } else {
              return true;
            }
          };
          const ret = fn();
          reset && scnr.resetPeek();
          return ret;
        }
        function takeChar(scnr, fn) {
          const ch = scnr.currentChar();
          if (ch === EOF) {
            return EOF;
          }
          if (fn(ch)) {
            scnr.next();
            return ch;
          }
          return null;
        }
        function isIdentifier(ch) {
          const cc = ch.charCodeAt(0);
          return cc >= 97 && cc <= 122 || // a-z
          cc >= 65 && cc <= 90 || // A-Z
          cc >= 48 && cc <= 57 || // 0-9
          cc === 95 || // _
          cc === 36;
        }
        function takeIdentifierChar(scnr) {
          return takeChar(scnr, isIdentifier);
        }
        function isNamedIdentifier(ch) {
          const cc = ch.charCodeAt(0);
          return cc >= 97 && cc <= 122 || // a-z
          cc >= 65 && cc <= 90 || // A-Z
          cc >= 48 && cc <= 57 || // 0-9
          cc === 95 || // _
          cc === 36 || // $
          cc === 45;
        }
        function takeNamedIdentifierChar(scnr) {
          return takeChar(scnr, isNamedIdentifier);
        }
        function isDigit(ch) {
          const cc = ch.charCodeAt(0);
          return cc >= 48 && cc <= 57;
        }
        function takeDigit(scnr) {
          return takeChar(scnr, isDigit);
        }
        function isHexDigit(ch) {
          const cc = ch.charCodeAt(0);
          return cc >= 48 && cc <= 57 || // 0-9
          cc >= 65 && cc <= 70 || // A-F
          cc >= 97 && cc <= 102;
        }
        function takeHexDigit(scnr) {
          return takeChar(scnr, isHexDigit);
        }
        function getDigits(scnr) {
          let ch = "";
          let num = "";
          while (ch = takeDigit(scnr)) {
            num += ch;
          }
          return num;
        }
        function readModulo(scnr) {
          skipSpaces(scnr);
          const ch = scnr.currentChar();
          if (ch !== "%") {
            emitError(CompileErrorCodes.EXPECTED_TOKEN, currentPosition(), 0, ch);
          }
          scnr.next();
          return "%";
        }
        function readText(scnr) {
          let buf = "";
          while (true) {
            const ch = scnr.currentChar();
            if (ch === "{" || ch === "}" || ch === "@" || ch === "|" || !ch) {
              break;
            } else if (ch === "%") {
              if (isTextStart(scnr)) {
                buf += ch;
                scnr.next();
              } else {
                break;
              }
            } else if (ch === CHAR_SP || ch === CHAR_LF) {
              if (isTextStart(scnr)) {
                buf += ch;
                scnr.next();
              } else if (isPluralStart(scnr)) {
                break;
              } else {
                buf += ch;
                scnr.next();
              }
            } else {
              buf += ch;
              scnr.next();
            }
          }
          return buf;
        }
        function readNamedIdentifier(scnr) {
          skipSpaces(scnr);
          let ch = "";
          let name = "";
          while (ch = takeNamedIdentifierChar(scnr)) {
            name += ch;
          }
          if (scnr.currentChar() === EOF) {
            emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
          }
          return name;
        }
        function readListIdentifier(scnr) {
          skipSpaces(scnr);
          let value = "";
          if (scnr.currentChar() === "-") {
            scnr.next();
            value += `-${getDigits(scnr)}`;
          } else {
            value += getDigits(scnr);
          }
          if (scnr.currentChar() === EOF) {
            emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
          }
          return value;
        }
        function isLiteral2(ch) {
          return ch !== LITERAL_DELIMITER && ch !== CHAR_LF;
        }
        function readLiteral(scnr) {
          skipSpaces(scnr);
          eat(scnr, `'`);
          let ch = "";
          let literal = "";
          while (ch = takeChar(scnr, isLiteral2)) {
            if (ch === "\\") {
              literal += readEscapeSequence(scnr);
            } else {
              literal += ch;
            }
          }
          const current = scnr.currentChar();
          if (current === CHAR_LF || current === EOF) {
            emitError(CompileErrorCodes.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER, currentPosition(), 0);
            if (current === CHAR_LF) {
              scnr.next();
              eat(scnr, `'`);
            }
            return literal;
          }
          eat(scnr, `'`);
          return literal;
        }
        function readEscapeSequence(scnr) {
          const ch = scnr.currentChar();
          switch (ch) {
            case "\\":
            case `'`:
              scnr.next();
              return `\\${ch}`;
            case "u":
              return readUnicodeEscapeSequence(scnr, ch, 4);
            case "U":
              return readUnicodeEscapeSequence(scnr, ch, 6);
            default:
              emitError(CompileErrorCodes.UNKNOWN_ESCAPE_SEQUENCE, currentPosition(), 0, ch);
              return "";
          }
        }
        function readUnicodeEscapeSequence(scnr, unicode, digits) {
          eat(scnr, unicode);
          let sequence = "";
          for (let i = 0; i < digits; i++) {
            const ch = takeHexDigit(scnr);
            if (!ch) {
              emitError(CompileErrorCodes.INVALID_UNICODE_ESCAPE_SEQUENCE, currentPosition(), 0, `\\${unicode}${sequence}${scnr.currentChar()}`);
              break;
            }
            sequence += ch;
          }
          return `\\${unicode}${sequence}`;
        }
        function isInvalidIdentifier(ch) {
          return ch !== "{" && ch !== "}" && ch !== CHAR_SP && ch !== CHAR_LF;
        }
        function readInvalidIdentifier(scnr) {
          skipSpaces(scnr);
          let ch = "";
          let identifiers = "";
          while (ch = takeChar(scnr, isInvalidIdentifier)) {
            identifiers += ch;
          }
          return identifiers;
        }
        function readLinkedModifier(scnr) {
          let ch = "";
          let name = "";
          while (ch = takeIdentifierChar(scnr)) {
            name += ch;
          }
          return name;
        }
        function readLinkedRefer(scnr) {
          const fn = (detect2 = false, buf) => {
            const ch = scnr.currentChar();
            if (ch === "{" || ch === "%" || ch === "@" || ch === "|" || ch === "(" || ch === ")" || !ch) {
              return buf;
            } else if (ch === CHAR_SP) {
              return buf;
            } else if (ch === CHAR_LF || ch === DOT) {
              buf += ch;
              scnr.next();
              return fn(detect2, buf);
            } else {
              buf += ch;
              scnr.next();
              return fn(true, buf);
            }
          };
          return fn(false, "");
        }
        function readPlural(scnr) {
          skipSpaces(scnr);
          const plural = eat(
            scnr,
            "|"
            /* TokenChars.Pipe */
          );
          skipSpaces(scnr);
          return plural;
        }
        function readTokenInPlaceholder(scnr, context2) {
          let token = null;
          const ch = scnr.currentChar();
          switch (ch) {
            case "{":
              if (context2.braceNest >= 1) {
                emitError(CompileErrorCodes.NOT_ALLOW_NEST_PLACEHOLDER, currentPosition(), 0);
              }
              scnr.next();
              token = getToken(
                context2,
                2,
                "{"
                /* TokenChars.BraceLeft */
              );
              skipSpaces(scnr);
              context2.braceNest++;
              return token;
            case "}":
              if (context2.braceNest > 0 && context2.currentType === 2) {
                emitError(CompileErrorCodes.EMPTY_PLACEHOLDER, currentPosition(), 0);
              }
              scnr.next();
              token = getToken(
                context2,
                3,
                "}"
                /* TokenChars.BraceRight */
              );
              context2.braceNest--;
              context2.braceNest > 0 && skipSpaces(scnr);
              if (context2.inLinked && context2.braceNest === 0) {
                context2.inLinked = false;
              }
              return token;
            case "@":
              if (context2.braceNest > 0) {
                emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
              }
              token = readTokenInLinked(scnr, context2) || getEndToken(context2);
              context2.braceNest = 0;
              return token;
            default: {
              let validNamedIdentifier = true;
              let validListIdentifier = true;
              let validLiteral = true;
              if (isPluralStart(scnr)) {
                if (context2.braceNest > 0) {
                  emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
                }
                token = getToken(context2, 1, readPlural(scnr));
                context2.braceNest = 0;
                context2.inLinked = false;
                return token;
              }
              if (context2.braceNest > 0 && (context2.currentType === 5 || context2.currentType === 6 || context2.currentType === 7)) {
                emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
                context2.braceNest = 0;
                return readToken(scnr, context2);
              }
              if (validNamedIdentifier = isNamedIdentifierStart(scnr, context2)) {
                token = getToken(context2, 5, readNamedIdentifier(scnr));
                skipSpaces(scnr);
                return token;
              }
              if (validListIdentifier = isListIdentifierStart(scnr, context2)) {
                token = getToken(context2, 6, readListIdentifier(scnr));
                skipSpaces(scnr);
                return token;
              }
              if (validLiteral = isLiteralStart(scnr, context2)) {
                token = getToken(context2, 7, readLiteral(scnr));
                skipSpaces(scnr);
                return token;
              }
              if (!validNamedIdentifier && !validListIdentifier && !validLiteral) {
                token = getToken(context2, 13, readInvalidIdentifier(scnr));
                emitError(CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER, currentPosition(), 0, token.value);
                skipSpaces(scnr);
                return token;
              }
              break;
            }
          }
          return token;
        }
        function readTokenInLinked(scnr, context2) {
          const { currentType } = context2;
          let token = null;
          const ch = scnr.currentChar();
          if ((currentType === 8 || currentType === 9 || currentType === 12 || currentType === 10) && (ch === CHAR_LF || ch === CHAR_SP)) {
            emitError(CompileErrorCodes.INVALID_LINKED_FORMAT, currentPosition(), 0);
          }
          switch (ch) {
            case "@":
              scnr.next();
              token = getToken(
                context2,
                8,
                "@"
                /* TokenChars.LinkedAlias */
              );
              context2.inLinked = true;
              return token;
            case ".":
              skipSpaces(scnr);
              scnr.next();
              return getToken(
                context2,
                9,
                "."
                /* TokenChars.LinkedDot */
              );
            case ":":
              skipSpaces(scnr);
              scnr.next();
              return getToken(
                context2,
                10,
                ":"
                /* TokenChars.LinkedDelimiter */
              );
            default:
              if (isPluralStart(scnr)) {
                token = getToken(context2, 1, readPlural(scnr));
                context2.braceNest = 0;
                context2.inLinked = false;
                return token;
              }
              if (isLinkedDotStart(scnr, context2) || isLinkedDelimiterStart(scnr, context2)) {
                skipSpaces(scnr);
                return readTokenInLinked(scnr, context2);
              }
              if (isLinkedModifierStart(scnr, context2)) {
                skipSpaces(scnr);
                return getToken(context2, 12, readLinkedModifier(scnr));
              }
              if (isLinkedReferStart(scnr, context2)) {
                skipSpaces(scnr);
                if (ch === "{") {
                  return readTokenInPlaceholder(scnr, context2) || token;
                } else {
                  return getToken(context2, 11, readLinkedRefer(scnr));
                }
              }
              if (currentType === 8) {
                emitError(CompileErrorCodes.INVALID_LINKED_FORMAT, currentPosition(), 0);
              }
              context2.braceNest = 0;
              context2.inLinked = false;
              return readToken(scnr, context2);
          }
        }
        function readToken(scnr, context2) {
          let token = {
            type: 14
            /* TokenTypes.EOF */
          };
          if (context2.braceNest > 0) {
            return readTokenInPlaceholder(scnr, context2) || getEndToken(context2);
          }
          if (context2.inLinked) {
            return readTokenInLinked(scnr, context2) || getEndToken(context2);
          }
          const ch = scnr.currentChar();
          switch (ch) {
            case "{":
              return readTokenInPlaceholder(scnr, context2) || getEndToken(context2);
            case "}":
              emitError(CompileErrorCodes.UNBALANCED_CLOSING_BRACE, currentPosition(), 0);
              scnr.next();
              return getToken(
                context2,
                3,
                "}"
                /* TokenChars.BraceRight */
              );
            case "@":
              return readTokenInLinked(scnr, context2) || getEndToken(context2);
            default: {
              if (isPluralStart(scnr)) {
                token = getToken(context2, 1, readPlural(scnr));
                context2.braceNest = 0;
                context2.inLinked = false;
                return token;
              }
              const { isModulo, hasSpace } = detectModuloStart(scnr);
              if (isModulo) {
                return hasSpace ? getToken(context2, 0, readText(scnr)) : getToken(context2, 4, readModulo(scnr));
              }
              if (isTextStart(scnr)) {
                return getToken(context2, 0, readText(scnr));
              }
              break;
            }
          }
          return token;
        }
        function nextToken() {
          const { currentType, offset, startLoc, endLoc } = _context;
          _context.lastType = currentType;
          _context.lastOffset = offset;
          _context.lastStartLoc = startLoc;
          _context.lastEndLoc = endLoc;
          _context.offset = currentOffset();
          _context.startLoc = currentPosition();
          if (_scnr.currentChar() === EOF) {
            return getToken(
              _context,
              14
              /* TokenTypes.EOF */
            );
          }
          return readToken(_scnr, _context);
        }
        return {
          nextToken,
          currentOffset,
          currentPosition,
          context
        };
      }
      const ERROR_DOMAIN$2 = "parser";
      const KNOWN_ESCAPES = /(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;
      function fromEscapeSequence(match2, codePoint4, codePoint6) {
        switch (match2) {
          case `\\\\`:
            return `\\`;
          case `\\'`:
            return `'`;
          default: {
            const codePoint = parseInt(codePoint4 || codePoint6, 16);
            if (codePoint <= 55295 || codePoint >= 57344) {
              return String.fromCodePoint(codePoint);
            }
            return "�";
          }
        }
      }
      function createParser(options = {}) {
        const location2 = options.location !== false;
        const { onError, onWarn } = options;
        function emitError(tokenzer, code2, start, offset, ...args) {
          const end = tokenzer.currentPosition();
          end.offset += offset;
          end.column += offset;
          if (onError) {
            const loc = location2 ? createLocation(start, end) : null;
            const err = createCompileError(code2, loc, {
              domain: ERROR_DOMAIN$2,
              args
            });
            onError(err);
          }
        }
        function emitWarn(tokenzer, code2, start, offset, ...args) {
          const end = tokenzer.currentPosition();
          end.offset += offset;
          end.column += offset;
          if (onWarn) {
            const loc = location2 ? createLocation(start, end) : null;
            onWarn(createCompileWarn(code2, loc, args));
          }
        }
        function startNode(type, offset, loc) {
          const node = { type };
          if (location2) {
            node.start = offset;
            node.end = offset;
            node.loc = { start: loc, end: loc };
          }
          return node;
        }
        function endNode(node, offset, pos, type) {
          if (type) {
            node.type = type;
          }
          if (location2) {
            node.end = offset;
            if (node.loc) {
              node.loc.end = pos;
            }
          }
        }
        function parseText(tokenizer, value) {
          const context = tokenizer.context();
          const node = startNode(3, context.offset, context.startLoc);
          node.value = value;
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
        }
        function parseList(tokenizer, index) {
          const context = tokenizer.context();
          const { lastOffset: offset, lastStartLoc: loc } = context;
          const node = startNode(5, offset, loc);
          node.index = parseInt(index, 10);
          tokenizer.nextToken();
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
        }
        function parseNamed(tokenizer, key, modulo) {
          const context = tokenizer.context();
          const { lastOffset: offset, lastStartLoc: loc } = context;
          const node = startNode(4, offset, loc);
          node.key = key;
          if (modulo === true) {
            node.modulo = true;
          }
          tokenizer.nextToken();
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
        }
        function parseLiteral(tokenizer, value) {
          const context = tokenizer.context();
          const { lastOffset: offset, lastStartLoc: loc } = context;
          const node = startNode(9, offset, loc);
          node.value = value.replace(KNOWN_ESCAPES, fromEscapeSequence);
          tokenizer.nextToken();
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
        }
        function parseLinkedModifier(tokenizer) {
          const token = tokenizer.nextToken();
          const context = tokenizer.context();
          const { lastOffset: offset, lastStartLoc: loc } = context;
          const node = startNode(8, offset, loc);
          if (token.type !== 12) {
            emitError(tokenizer, CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_MODIFIER, context.lastStartLoc, 0);
            node.value = "";
            endNode(node, offset, loc);
            return {
              nextConsumeToken: token,
              node
            };
          }
          if (token.value == null) {
            emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
          }
          node.value = token.value || "";
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return {
            node
          };
        }
        function parseLinkedKey(tokenizer, value) {
          const context = tokenizer.context();
          const node = startNode(7, context.offset, context.startLoc);
          node.value = value;
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
        }
        function parseLinked(tokenizer) {
          const context = tokenizer.context();
          const linkedNode = startNode(6, context.offset, context.startLoc);
          let token = tokenizer.nextToken();
          if (token.type === 9) {
            const parsed = parseLinkedModifier(tokenizer);
            linkedNode.modifier = parsed.node;
            token = parsed.nextConsumeToken || tokenizer.nextToken();
          }
          if (token.type !== 10) {
            emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
          }
          token = tokenizer.nextToken();
          if (token.type === 2) {
            token = tokenizer.nextToken();
          }
          switch (token.type) {
            case 11:
              if (token.value == null) {
                emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
              }
              linkedNode.key = parseLinkedKey(tokenizer, token.value || "");
              break;
            case 5:
              if (token.value == null) {
                emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
              }
              linkedNode.key = parseNamed(tokenizer, token.value || "");
              break;
            case 6:
              if (token.value == null) {
                emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
              }
              linkedNode.key = parseList(tokenizer, token.value || "");
              break;
            case 7:
              if (token.value == null) {
                emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
              }
              linkedNode.key = parseLiteral(tokenizer, token.value || "");
              break;
            default: {
              emitError(tokenizer, CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_KEY, context.lastStartLoc, 0);
              const nextContext = tokenizer.context();
              const emptyLinkedKeyNode = startNode(7, nextContext.offset, nextContext.startLoc);
              emptyLinkedKeyNode.value = "";
              endNode(emptyLinkedKeyNode, nextContext.offset, nextContext.startLoc);
              linkedNode.key = emptyLinkedKeyNode;
              endNode(linkedNode, nextContext.offset, nextContext.startLoc);
              return {
                nextConsumeToken: token,
                node: linkedNode
              };
            }
          }
          endNode(linkedNode, tokenizer.currentOffset(), tokenizer.currentPosition());
          return {
            node: linkedNode
          };
        }
        function parseMessage(tokenizer) {
          const context = tokenizer.context();
          const startOffset = context.currentType === 1 ? tokenizer.currentOffset() : context.offset;
          const startLoc = context.currentType === 1 ? context.endLoc : context.startLoc;
          const node = startNode(2, startOffset, startLoc);
          node.items = [];
          let nextToken = null;
          let modulo = null;
          do {
            const token = nextToken || tokenizer.nextToken();
            nextToken = null;
            switch (token.type) {
              case 0:
                if (token.value == null) {
                  emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                }
                node.items.push(parseText(tokenizer, token.value || ""));
                break;
              case 6:
                if (token.value == null) {
                  emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                }
                node.items.push(parseList(tokenizer, token.value || ""));
                break;
              case 4:
                modulo = true;
                break;
              case 5:
                if (token.value == null) {
                  emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                }
                node.items.push(parseNamed(tokenizer, token.value || "", !!modulo));
                if (modulo) {
                  emitWarn(tokenizer, CompileWarnCodes.USE_MODULO_SYNTAX, context.lastStartLoc, 0, getTokenCaption(token));
                  modulo = null;
                }
                break;
              case 7:
                if (token.value == null) {
                  emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                }
                node.items.push(parseLiteral(tokenizer, token.value || ""));
                break;
              case 8: {
                const parsed = parseLinked(tokenizer);
                node.items.push(parsed.node);
                nextToken = parsed.nextConsumeToken || null;
                break;
              }
            }
          } while (context.currentType !== 14 && context.currentType !== 1);
          const endOffset = context.currentType === 1 ? context.lastOffset : tokenizer.currentOffset();
          const endLoc = context.currentType === 1 ? context.lastEndLoc : tokenizer.currentPosition();
          endNode(node, endOffset, endLoc);
          return node;
        }
        function parsePlural(tokenizer, offset, loc, msgNode) {
          const context = tokenizer.context();
          let hasEmptyMessage = msgNode.items.length === 0;
          const node = startNode(1, offset, loc);
          node.cases = [];
          node.cases.push(msgNode);
          do {
            const msg = parseMessage(tokenizer);
            if (!hasEmptyMessage) {
              hasEmptyMessage = msg.items.length === 0;
            }
            node.cases.push(msg);
          } while (context.currentType !== 14);
          if (hasEmptyMessage) {
            emitError(tokenizer, CompileErrorCodes.MUST_HAVE_MESSAGES_IN_PLURAL, loc, 0);
          }
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
        }
        function parseResource(tokenizer) {
          const context = tokenizer.context();
          const { offset, startLoc } = context;
          const msgNode = parseMessage(tokenizer);
          if (context.currentType === 14) {
            return msgNode;
          } else {
            return parsePlural(tokenizer, offset, startLoc, msgNode);
          }
        }
        function parse2(source) {
          const tokenizer = createTokenizer(source, assign({}, options));
          const context = tokenizer.context();
          const node = startNode(0, context.offset, context.startLoc);
          if (location2 && node.loc) {
            node.loc.source = source;
          }
          node.body = parseResource(tokenizer);
          if (options.onCacheKey) {
            node.cacheKey = options.onCacheKey(source);
          }
          if (context.currentType !== 14) {
            emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, source[context.offset] || "");
          }
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
        }
        return { parse: parse2 };
      }
      function getTokenCaption(token) {
        if (token.type === 14) {
          return "EOF";
        }
        const name = (token.value || "").replace(/\r?\n/gu, "\\n");
        return name.length > 10 ? name.slice(0, 9) + "…" : name;
      }
      function createTransformer(ast, options = {}) {
        const _context = {
          ast,
          helpers: /* @__PURE__ */ new Set()
        };
        const context = () => _context;
        const helper = (name) => {
          _context.helpers.add(name);
          return name;
        };
        return { context, helper };
      }
      function traverseNodes(nodes, transformer) {
        for (let i = 0; i < nodes.length; i++) {
          traverseNode(nodes[i], transformer);
        }
      }
      function traverseNode(node, transformer) {
        switch (node.type) {
          case 1:
            traverseNodes(node.cases, transformer);
            transformer.helper(
              "plural"
              /* HelperNameMap.PLURAL */
            );
            break;
          case 2:
            traverseNodes(node.items, transformer);
            break;
          case 6: {
            const linked = node;
            traverseNode(linked.key, transformer);
            transformer.helper(
              "linked"
              /* HelperNameMap.LINKED */
            );
            transformer.helper(
              "type"
              /* HelperNameMap.TYPE */
            );
            break;
          }
          case 5:
            transformer.helper(
              "interpolate"
              /* HelperNameMap.INTERPOLATE */
            );
            transformer.helper(
              "list"
              /* HelperNameMap.LIST */
            );
            break;
          case 4:
            transformer.helper(
              "interpolate"
              /* HelperNameMap.INTERPOLATE */
            );
            transformer.helper(
              "named"
              /* HelperNameMap.NAMED */
            );
            break;
        }
      }
      function transform(ast, options = {}) {
        const transformer = createTransformer(ast);
        transformer.helper(
          "normalize"
          /* HelperNameMap.NORMALIZE */
        );
        ast.body && traverseNode(ast.body, transformer);
        const context = transformer.context();
        ast.helpers = Array.from(context.helpers);
      }
      function optimize(ast) {
        const body = ast.body;
        if (body.type === 2) {
          optimizeMessageNode(body);
        } else {
          body.cases.forEach((c) => optimizeMessageNode(c));
        }
        return ast;
      }
      function optimizeMessageNode(message) {
        if (message.items.length === 1) {
          const item = message.items[0];
          if (item.type === 3 || item.type === 9) {
            message.static = item.value;
            delete item.value;
          }
        } else {
          const values2 = [];
          for (let i = 0; i < message.items.length; i++) {
            const item = message.items[i];
            if (!(item.type === 3 || item.type === 9)) {
              break;
            }
            if (item.value == null) {
              break;
            }
            values2.push(item.value);
          }
          if (values2.length === message.items.length) {
            message.static = join(values2);
            for (let i = 0; i < message.items.length; i++) {
              const item = message.items[i];
              if (item.type === 3 || item.type === 9) {
                delete item.value;
              }
            }
          }
        }
      }
      const ERROR_DOMAIN$1 = "minifier";
      function minify(node) {
        node.t = node.type;
        switch (node.type) {
          case 0: {
            const resource2 = node;
            minify(resource2.body);
            resource2.b = resource2.body;
            delete resource2.body;
            break;
          }
          case 1: {
            const plural = node;
            const cases = plural.cases;
            for (let i = 0; i < cases.length; i++) {
              minify(cases[i]);
            }
            plural.c = cases;
            delete plural.cases;
            break;
          }
          case 2: {
            const message = node;
            const items = message.items;
            for (let i = 0; i < items.length; i++) {
              minify(items[i]);
            }
            message.i = items;
            delete message.items;
            if (message.static) {
              message.s = message.static;
              delete message.static;
            }
            break;
          }
          case 3:
          case 9:
          case 8:
          case 7: {
            const valueNode = node;
            if (valueNode.value) {
              valueNode.v = valueNode.value;
              delete valueNode.value;
            }
            break;
          }
          case 6: {
            const linked = node;
            minify(linked.key);
            linked.k = linked.key;
            delete linked.key;
            if (linked.modifier) {
              minify(linked.modifier);
              linked.m = linked.modifier;
              delete linked.modifier;
            }
            break;
          }
          case 5: {
            const list = node;
            list.i = list.index;
            delete list.index;
            break;
          }
          case 4: {
            const named = node;
            named.k = named.key;
            delete named.key;
            break;
          }
          default: {
            throw createCompileError(CompileErrorCodes.UNHANDLED_MINIFIER_NODE_TYPE, null, {
              domain: ERROR_DOMAIN$1,
              args: [node.type]
            });
          }
        }
        delete node.type;
      }
      const ERROR_DOMAIN = "parser";
      function createCodeGenerator(ast, options) {
        const { sourceMap, filename, breakLineCode, needIndent: _needIndent } = options;
        const location2 = options.location !== false;
        const _context = {
          filename,
          code: "",
          column: 1,
          line: 1,
          offset: 0,
          map: void 0,
          breakLineCode,
          needIndent: _needIndent,
          indentLevel: 0
        };
        if (location2 && ast.loc) {
          _context.source = ast.loc.source;
        }
        const context = () => _context;
        function push(code2, node) {
          _context.code += code2;
        }
        function _newline(n, withBreakLine = true) {
          const _breakLineCode = withBreakLine ? breakLineCode : "";
          push(_needIndent ? _breakLineCode + `  `.repeat(n) : _breakLineCode);
        }
        function indent(withNewLine = true) {
          const level = ++_context.indentLevel;
          withNewLine && _newline(level);
        }
        function deindent(withNewLine = true) {
          const level = --_context.indentLevel;
          withNewLine && _newline(level);
        }
        function newline() {
          _newline(_context.indentLevel);
        }
        const helper = (key) => `_${key}`;
        const needIndent = () => _context.needIndent;
        return {
          context,
          push,
          indent,
          deindent,
          newline,
          helper,
          needIndent
        };
      }
      function generateLinkedNode(generator, node) {
        const { helper } = generator;
        generator.push(`${helper(
        "linked"
        /* HelperNameMap.LINKED */
      )}(`);
        generateNode(generator, node.key);
        if (node.modifier) {
          generator.push(`, `);
          generateNode(generator, node.modifier);
          generator.push(`, _type`);
        } else {
          generator.push(`, undefined, _type`);
        }
        generator.push(`)`);
      }
      function generateMessageNode(generator, node) {
        const { helper, needIndent } = generator;
        generator.push(`${helper(
        "normalize"
        /* HelperNameMap.NORMALIZE */
      )}([`);
        generator.indent(needIndent());
        const length = node.items.length;
        for (let i = 0; i < length; i++) {
          generateNode(generator, node.items[i]);
          if (i === length - 1) {
            break;
          }
          generator.push(", ");
        }
        generator.deindent(needIndent());
        generator.push("])");
      }
      function generatePluralNode(generator, node) {
        const { helper, needIndent } = generator;
        if (node.cases.length > 1) {
          generator.push(`${helper(
          "plural"
          /* HelperNameMap.PLURAL */
        )}([`);
          generator.indent(needIndent());
          const length = node.cases.length;
          for (let i = 0; i < length; i++) {
            generateNode(generator, node.cases[i]);
            if (i === length - 1) {
              break;
            }
            generator.push(", ");
          }
          generator.deindent(needIndent());
          generator.push(`])`);
        }
      }
      function generateResource(generator, node) {
        if (node.body) {
          generateNode(generator, node.body);
        } else {
          generator.push("null");
        }
      }
      function generateNode(generator, node) {
        const { helper } = generator;
        switch (node.type) {
          case 0:
            generateResource(generator, node);
            break;
          case 1:
            generatePluralNode(generator, node);
            break;
          case 2:
            generateMessageNode(generator, node);
            break;
          case 6:
            generateLinkedNode(generator, node);
            break;
          case 8:
            generator.push(JSON.stringify(node.value), node);
            break;
          case 7:
            generator.push(JSON.stringify(node.value), node);
            break;
          case 5:
            generator.push(`${helper(
            "interpolate"
            /* HelperNameMap.INTERPOLATE */
          )}(${helper(
            "list"
            /* HelperNameMap.LIST */
          )}(${node.index}))`, node);
            break;
          case 4:
            generator.push(`${helper(
            "interpolate"
            /* HelperNameMap.INTERPOLATE */
          )}(${helper(
            "named"
            /* HelperNameMap.NAMED */
          )}(${JSON.stringify(node.key)}))`, node);
            break;
          case 9:
            generator.push(JSON.stringify(node.value), node);
            break;
          case 3:
            generator.push(JSON.stringify(node.value), node);
            break;
          default: {
            throw createCompileError(CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE, null, {
              domain: ERROR_DOMAIN,
              args: [node.type]
            });
          }
        }
      }
      const generate = (ast, options = {}) => {
        const mode = isString(options.mode) ? options.mode : "normal";
        const filename = isString(options.filename) ? options.filename : "message.intl";
        const sourceMap = !!options.sourceMap;
        const breakLineCode = options.breakLineCode != null ? options.breakLineCode : mode === "arrow" ? ";" : "\n";
        const needIndent = options.needIndent ? options.needIndent : mode !== "arrow";
        const helpers = ast.helpers || [];
        const generator = createCodeGenerator(ast, {
          mode,
          filename,
          sourceMap,
          breakLineCode,
          needIndent
        });
        generator.push(mode === "normal" ? `function __msg__ (ctx) {` : `(ctx) => {`);
        generator.indent(needIndent);
        if (helpers.length > 0) {
          generator.push(`const { ${join(helpers.map((s) => `${s}: _${s}`), ", ")} } = ctx`);
          generator.newline();
        }
        generator.push(`return `);
        generateNode(generator, ast);
        generator.deindent(needIndent);
        generator.push(`}`);
        delete ast.helpers;
        const { code: code2, map: map2 } = generator.context();
        return {
          ast,
          code: code2,
          map: map2 ? map2.toJSON() : void 0
          // eslint-disable-line @typescript-eslint/no-explicit-any
        };
      };
      function baseCompile$1(source, options = {}) {
        const assignedOptions = assign({}, options);
        const jit = !!assignedOptions.jit;
        const enalbeMinify = !!assignedOptions.minify;
        const enambeOptimize = assignedOptions.optimize == null ? true : assignedOptions.optimize;
        const parser2 = createParser(assignedOptions);
        const ast = parser2.parse(source);
        if (!jit) {
          transform(ast, assignedOptions);
          return generate(ast, assignedOptions);
        } else {
          enambeOptimize && optimize(ast);
          enalbeMinify && minify(ast);
          return { ast, code: "" };
        }
      }
      /*!
        * core-base v9.12.1
        * (c) 2024 kazuya kawaguchi
        * Released under the MIT License.
        */
      function initFeatureFlags$1() {
        if (typeof __INTLIFY_PROD_DEVTOOLS__ !== "boolean") {
          getGlobalThis().__INTLIFY_PROD_DEVTOOLS__ = false;
        }
      }
      const pathStateMachine = [];
      pathStateMachine[
        0
        /* States.BEFORE_PATH */
      ] = {
        [
          "w"
          /* PathCharTypes.WORKSPACE */
        ]: [
          0
          /* States.BEFORE_PATH */
        ],
        [
          "i"
          /* PathCharTypes.IDENT */
        ]: [
          3,
          0
          /* Actions.APPEND */
        ],
        [
          "["
          /* PathCharTypes.LEFT_BRACKET */
        ]: [
          4
          /* States.IN_SUB_PATH */
        ],
        [
          "o"
          /* PathCharTypes.END_OF_FAIL */
        ]: [
          7
          /* States.AFTER_PATH */
        ]
      };
      pathStateMachine[
        1
        /* States.IN_PATH */
      ] = {
        [
          "w"
          /* PathCharTypes.WORKSPACE */
        ]: [
          1
          /* States.IN_PATH */
        ],
        [
          "."
          /* PathCharTypes.DOT */
        ]: [
          2
          /* States.BEFORE_IDENT */
        ],
        [
          "["
          /* PathCharTypes.LEFT_BRACKET */
        ]: [
          4
          /* States.IN_SUB_PATH */
        ],
        [
          "o"
          /* PathCharTypes.END_OF_FAIL */
        ]: [
          7
          /* States.AFTER_PATH */
        ]
      };
      pathStateMachine[
        2
        /* States.BEFORE_IDENT */
      ] = {
        [
          "w"
          /* PathCharTypes.WORKSPACE */
        ]: [
          2
          /* States.BEFORE_IDENT */
        ],
        [
          "i"
          /* PathCharTypes.IDENT */
        ]: [
          3,
          0
          /* Actions.APPEND */
        ],
        [
          "0"
          /* PathCharTypes.ZERO */
        ]: [
          3,
          0
          /* Actions.APPEND */
        ]
      };
      pathStateMachine[
        3
        /* States.IN_IDENT */
      ] = {
        [
          "i"
          /* PathCharTypes.IDENT */
        ]: [
          3,
          0
          /* Actions.APPEND */
        ],
        [
          "0"
          /* PathCharTypes.ZERO */
        ]: [
          3,
          0
          /* Actions.APPEND */
        ],
        [
          "w"
          /* PathCharTypes.WORKSPACE */
        ]: [
          1,
          1
          /* Actions.PUSH */
        ],
        [
          "."
          /* PathCharTypes.DOT */
        ]: [
          2,
          1
          /* Actions.PUSH */
        ],
        [
          "["
          /* PathCharTypes.LEFT_BRACKET */
        ]: [
          4,
          1
          /* Actions.PUSH */
        ],
        [
          "o"
          /* PathCharTypes.END_OF_FAIL */
        ]: [
          7,
          1
          /* Actions.PUSH */
        ]
      };
      pathStateMachine[
        4
        /* States.IN_SUB_PATH */
      ] = {
        [
          "'"
          /* PathCharTypes.SINGLE_QUOTE */
        ]: [
          5,
          0
          /* Actions.APPEND */
        ],
        [
          '"'
          /* PathCharTypes.DOUBLE_QUOTE */
        ]: [
          6,
          0
          /* Actions.APPEND */
        ],
        [
          "["
          /* PathCharTypes.LEFT_BRACKET */
        ]: [
          4,
          2
          /* Actions.INC_SUB_PATH_DEPTH */
        ],
        [
          "]"
          /* PathCharTypes.RIGHT_BRACKET */
        ]: [
          1,
          3
          /* Actions.PUSH_SUB_PATH */
        ],
        [
          "o"
          /* PathCharTypes.END_OF_FAIL */
        ]: 8,
        [
          "l"
          /* PathCharTypes.ELSE */
        ]: [
          4,
          0
          /* Actions.APPEND */
        ]
      };
      pathStateMachine[
        5
        /* States.IN_SINGLE_QUOTE */
      ] = {
        [
          "'"
          /* PathCharTypes.SINGLE_QUOTE */
        ]: [
          4,
          0
          /* Actions.APPEND */
        ],
        [
          "o"
          /* PathCharTypes.END_OF_FAIL */
        ]: 8,
        [
          "l"
          /* PathCharTypes.ELSE */
        ]: [
          5,
          0
          /* Actions.APPEND */
        ]
      };
      pathStateMachine[
        6
        /* States.IN_DOUBLE_QUOTE */
      ] = {
        [
          '"'
          /* PathCharTypes.DOUBLE_QUOTE */
        ]: [
          4,
          0
          /* Actions.APPEND */
        ],
        [
          "o"
          /* PathCharTypes.END_OF_FAIL */
        ]: 8,
        [
          "l"
          /* PathCharTypes.ELSE */
        ]: [
          6,
          0
          /* Actions.APPEND */
        ]
      };
      const literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
      function isLiteral(exp) {
        return literalValueRE.test(exp);
      }
      function stripQuotes(str) {
        const a = str.charCodeAt(0);
        const b = str.charCodeAt(str.length - 1);
        return a === b && (a === 34 || a === 39) ? str.slice(1, -1) : str;
      }
      function getPathCharType(ch) {
        if (ch === void 0 || ch === null) {
          return "o";
        }
        const code2 = ch.charCodeAt(0);
        switch (code2) {
          case 91:
          case 93:
          case 46:
          case 34:
          case 39:
            return ch;
          case 95:
          case 36:
          case 45:
            return "i";
          case 9:
          case 10:
          case 13:
          case 160:
          case 65279:
          case 8232:
          case 8233:
            return "w";
        }
        return "i";
      }
      function formatSubPath(path) {
        const trimmed = path.trim();
        if (path.charAt(0) === "0" && isNaN(parseInt(path))) {
          return false;
        }
        return isLiteral(trimmed) ? stripQuotes(trimmed) : "*" + trimmed;
      }
      function parse(path) {
        const keys2 = [];
        let index = -1;
        let mode = 0;
        let subPathDepth = 0;
        let c;
        let key;
        let newChar;
        let type;
        let transition;
        let action;
        let typeMap;
        const actions = [];
        actions[
          0
          /* Actions.APPEND */
        ] = () => {
          if (key === void 0) {
            key = newChar;
          } else {
            key += newChar;
          }
        };
        actions[
          1
          /* Actions.PUSH */
        ] = () => {
          if (key !== void 0) {
            keys2.push(key);
            key = void 0;
          }
        };
        actions[
          2
          /* Actions.INC_SUB_PATH_DEPTH */
        ] = () => {
          actions[
            0
            /* Actions.APPEND */
          ]();
          subPathDepth++;
        };
        actions[
          3
          /* Actions.PUSH_SUB_PATH */
        ] = () => {
          if (subPathDepth > 0) {
            subPathDepth--;
            mode = 4;
            actions[
              0
              /* Actions.APPEND */
            ]();
          } else {
            subPathDepth = 0;
            if (key === void 0) {
              return false;
            }
            key = formatSubPath(key);
            if (key === false) {
              return false;
            } else {
              actions[
                1
                /* Actions.PUSH */
              ]();
            }
          }
        };
        function maybeUnescapeQuote() {
          const nextChar = path[index + 1];
          if (mode === 5 && nextChar === "'" || mode === 6 && nextChar === '"') {
            index++;
            newChar = "\\" + nextChar;
            actions[
              0
              /* Actions.APPEND */
            ]();
            return true;
          }
        }
        while (mode !== null) {
          index++;
          c = path[index];
          if (c === "\\" && maybeUnescapeQuote()) {
            continue;
          }
          type = getPathCharType(c);
          typeMap = pathStateMachine[mode];
          transition = typeMap[type] || typeMap[
            "l"
            /* PathCharTypes.ELSE */
          ] || 8;
          if (transition === 8) {
            return;
          }
          mode = transition[0];
          if (transition[1] !== void 0) {
            action = actions[transition[1]];
            if (action) {
              newChar = c;
              if (action() === false) {
                return;
              }
            }
          }
          if (mode === 7) {
            return keys2;
          }
        }
      }
      const cache = /* @__PURE__ */ new Map();
      function resolveWithKeyValue(obj, path) {
        return isObject$3(obj) ? obj[path] : null;
      }
      function resolveValue(obj, path) {
        if (!isObject$3(obj)) {
          return null;
        }
        let hit = cache.get(path);
        if (!hit) {
          hit = parse(path);
          if (hit) {
            cache.set(path, hit);
          }
        }
        if (!hit) {
          return null;
        }
        const len = hit.length;
        let last2 = obj;
        let i = 0;
        while (i < len) {
          const val = last2[hit[i]];
          if (val === void 0) {
            return null;
          }
          if (isFunction(last2)) {
            return null;
          }
          last2 = val;
          i++;
        }
        return last2;
      }
      const DEFAULT_MODIFIER = (str) => str;
      const DEFAULT_MESSAGE = (ctx) => "";
      const DEFAULT_MESSAGE_DATA_TYPE = "text";
      const DEFAULT_NORMALIZE = (values2) => values2.length === 0 ? "" : join$1(values2);
      const DEFAULT_INTERPOLATE = toDisplayString;
      function pluralDefault(choice, choicesLength) {
        choice = Math.abs(choice);
        if (choicesLength === 2) {
          return choice ? choice > 1 ? 1 : 0 : 1;
        }
        return choice ? Math.min(choice, 2) : 0;
      }
      function getPluralIndex(options) {
        const index = isNumber(options.pluralIndex) ? options.pluralIndex : -1;
        return options.named && (isNumber(options.named.count) || isNumber(options.named.n)) ? isNumber(options.named.count) ? options.named.count : isNumber(options.named.n) ? options.named.n : index : index;
      }
      function normalizeNamed(pluralIndex, props) {
        if (!props.count) {
          props.count = pluralIndex;
        }
        if (!props.n) {
          props.n = pluralIndex;
        }
      }
      function createMessageContext(options = {}) {
        const locale = options.locale;
        const pluralIndex = getPluralIndex(options);
        const pluralRule = isObject$3(options.pluralRules) && isString$1(locale) && isFunction(options.pluralRules[locale]) ? options.pluralRules[locale] : pluralDefault;
        const orgPluralRule = isObject$3(options.pluralRules) && isString$1(locale) && isFunction(options.pluralRules[locale]) ? pluralDefault : void 0;
        const plural = (messages) => {
          return messages[pluralRule(pluralIndex, messages.length, orgPluralRule)];
        };
        const _list = options.list || [];
        const list = (index) => _list[index];
        const _named = options.named || {};
        isNumber(options.pluralIndex) && normalizeNamed(pluralIndex, _named);
        const named = (key) => _named[key];
        function message(key) {
          const msg = isFunction(options.messages) ? options.messages(key) : isObject$3(options.messages) ? options.messages[key] : false;
          return !msg ? options.parent ? options.parent.message(key) : DEFAULT_MESSAGE : msg;
        }
        const _modifier = (name) => options.modifiers ? options.modifiers[name] : DEFAULT_MODIFIER;
        const normalize = isPlainObject(options.processor) && isFunction(options.processor.normalize) ? options.processor.normalize : DEFAULT_NORMALIZE;
        const interpolate = isPlainObject(options.processor) && isFunction(options.processor.interpolate) ? options.processor.interpolate : DEFAULT_INTERPOLATE;
        const type = isPlainObject(options.processor) && isString$1(options.processor.type) ? options.processor.type : DEFAULT_MESSAGE_DATA_TYPE;
        const linked = (key, ...args) => {
          const [arg1, arg2] = args;
          let type2 = "text";
          let modifier = "";
          if (args.length === 1) {
            if (isObject$3(arg1)) {
              modifier = arg1.modifier || modifier;
              type2 = arg1.type || type2;
            } else if (isString$1(arg1)) {
              modifier = arg1 || modifier;
            }
          } else if (args.length === 2) {
            if (isString$1(arg1)) {
              modifier = arg1 || modifier;
            }
            if (isString$1(arg2)) {
              type2 = arg2 || type2;
            }
          }
          const ret = message(key)(ctx);
          const msg = (
            // The message in vnode resolved with linked are returned as an array by processor.nomalize
            type2 === "vnode" && isArray(ret) && modifier ? ret[0] : ret
          );
          return modifier ? _modifier(modifier)(msg, type2) : msg;
        };
        const ctx = {
          [
            "list"
            /* HelperNameMap.LIST */
          ]: list,
          [
            "named"
            /* HelperNameMap.NAMED */
          ]: named,
          [
            "plural"
            /* HelperNameMap.PLURAL */
          ]: plural,
          [
            "linked"
            /* HelperNameMap.LINKED */
          ]: linked,
          [
            "message"
            /* HelperNameMap.MESSAGE */
          ]: message,
          [
            "type"
            /* HelperNameMap.TYPE */
          ]: type,
          [
            "interpolate"
            /* HelperNameMap.INTERPOLATE */
          ]: interpolate,
          [
            "normalize"
            /* HelperNameMap.NORMALIZE */
          ]: normalize,
          [
            "values"
            /* HelperNameMap.VALUES */
          ]: assign$1({}, _list, _named)
        };
        return ctx;
      }
      let devtools = null;
      function setDevToolsHook(hook) {
        devtools = hook;
      }
      function initI18nDevTools(i18n2, version, meta) {
        devtools && devtools.emit("i18n:init", {
          timestamp: Date.now(),
          i18n: i18n2,
          version,
          meta
        });
      }
      const translateDevTools = /* @__PURE__ */ createDevToolsHook(
        "function:translate"
        /* IntlifyDevToolsHooks.FunctionTranslate */
      );
      function createDevToolsHook(hook) {
        return (payloads) => devtools && devtools.emit(hook, payloads);
      }
      const code$1$1 = CompileWarnCodes.__EXTEND_POINT__;
      const inc$1$1 = incrementer(code$1$1);
      const CoreWarnCodes = {
        NOT_FOUND_KEY: code$1$1,
        // 2
        FALLBACK_TO_TRANSLATE: inc$1$1(),
        // 3
        CANNOT_FORMAT_NUMBER: inc$1$1(),
        // 4
        FALLBACK_TO_NUMBER_FORMAT: inc$1$1(),
        // 5
        CANNOT_FORMAT_DATE: inc$1$1(),
        // 6
        FALLBACK_TO_DATE_FORMAT: inc$1$1(),
        // 7
        EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER: inc$1$1(),
        // 8
        __EXTEND_POINT__: inc$1$1()
        // 9
      };
      const code$2 = CompileErrorCodes.__EXTEND_POINT__;
      const inc$2 = incrementer(code$2);
      const CoreErrorCodes = {
        INVALID_ARGUMENT: code$2,
        // 17
        INVALID_DATE_ARGUMENT: inc$2(),
        // 18
        INVALID_ISO_DATE_ARGUMENT: inc$2(),
        // 19
        NOT_SUPPORT_NON_STRING_MESSAGE: inc$2(),
        // 20
        NOT_SUPPORT_LOCALE_PROMISE_VALUE: inc$2(),
        // 21
        NOT_SUPPORT_LOCALE_ASYNC_FUNCTION: inc$2(),
        // 22
        NOT_SUPPORT_LOCALE_TYPE: inc$2(),
        // 23
        __EXTEND_POINT__: inc$2()
        // 24
      };
      function createCoreError(code2) {
        return createCompileError(code2, null, void 0);
      }
      function getLocale(context, options) {
        return options.locale != null ? resolveLocale(options.locale) : resolveLocale(context.locale);
      }
      let _resolveLocale;
      function resolveLocale(locale) {
        if (isString$1(locale)) {
          return locale;
        } else {
          if (isFunction(locale)) {
            if (locale.resolvedOnce && _resolveLocale != null) {
              return _resolveLocale;
            } else if (locale.constructor.name === "Function") {
              const resolve = locale();
              if (isPromise(resolve)) {
                throw createCoreError(CoreErrorCodes.NOT_SUPPORT_LOCALE_PROMISE_VALUE);
              }
              return _resolveLocale = resolve;
            } else {
              throw createCoreError(CoreErrorCodes.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION);
            }
          } else {
            throw createCoreError(CoreErrorCodes.NOT_SUPPORT_LOCALE_TYPE);
          }
        }
      }
      function fallbackWithSimple(ctx, fallback, start) {
        return [.../* @__PURE__ */ new Set([
          start,
          ...isArray(fallback) ? fallback : isObject$3(fallback) ? Object.keys(fallback) : isString$1(fallback) ? [fallback] : [start]
        ])];
      }
      function fallbackWithLocaleChain(ctx, fallback, start) {
        const startLocale = isString$1(start) ? start : DEFAULT_LOCALE;
        const context = ctx;
        if (!context.__localeChainCache) {
          context.__localeChainCache = /* @__PURE__ */ new Map();
        }
        let chain = context.__localeChainCache.get(startLocale);
        if (!chain) {
          chain = [];
          let block = [start];
          while (isArray(block)) {
            block = appendBlockToChain(chain, block, fallback);
          }
          const defaults = isArray(fallback) || !isPlainObject(fallback) ? fallback : fallback["default"] ? fallback["default"] : null;
          block = isString$1(defaults) ? [defaults] : defaults;
          if (isArray(block)) {
            appendBlockToChain(chain, block, false);
          }
          context.__localeChainCache.set(startLocale, chain);
        }
        return chain;
      }
      function appendBlockToChain(chain, block, blocks) {
        let follow = true;
        for (let i = 0; i < block.length && isBoolean(follow); i++) {
          const locale = block[i];
          if (isString$1(locale)) {
            follow = appendLocaleToChain(chain, block[i], blocks);
          }
        }
        return follow;
      }
      function appendLocaleToChain(chain, locale, blocks) {
        let follow;
        const tokens = locale.split("-");
        do {
          const target = tokens.join("-");
          follow = appendItemToChain(chain, target, blocks);
          tokens.splice(-1, 1);
        } while (tokens.length && follow === true);
        return follow;
      }
      function appendItemToChain(chain, target, blocks) {
        let follow = false;
        if (!chain.includes(target)) {
          follow = true;
          if (target) {
            follow = target[target.length - 1] !== "!";
            const locale = target.replace(/!/g, "");
            chain.push(locale);
            if ((isArray(blocks) || isPlainObject(blocks)) && blocks[locale]) {
              follow = blocks[locale];
            }
          }
        }
        return follow;
      }
      const VERSION$1 = "9.12.1";
      const NOT_REOSLVED = -1;
      const DEFAULT_LOCALE = "en-US";
      const MISSING_RESOLVE_VALUE = "";
      const capitalize = (str) => `${str.charAt(0).toLocaleUpperCase()}${str.substr(1)}`;
      function getDefaultLinkedModifiers() {
        return {
          upper: (val, type) => {
            return type === "text" && isString$1(val) ? val.toUpperCase() : type === "vnode" && isObject$3(val) && "__v_isVNode" in val ? val.children.toUpperCase() : val;
          },
          lower: (val, type) => {
            return type === "text" && isString$1(val) ? val.toLowerCase() : type === "vnode" && isObject$3(val) && "__v_isVNode" in val ? val.children.toLowerCase() : val;
          },
          capitalize: (val, type) => {
            return type === "text" && isString$1(val) ? capitalize(val) : type === "vnode" && isObject$3(val) && "__v_isVNode" in val ? capitalize(val.children) : val;
          }
        };
      }
      let _compiler;
      function registerMessageCompiler(compiler) {
        _compiler = compiler;
      }
      let _resolver;
      function registerMessageResolver(resolver) {
        _resolver = resolver;
      }
      let _fallbacker;
      function registerLocaleFallbacker(fallbacker) {
        _fallbacker = fallbacker;
      }
      let _additionalMeta = null;
      const setAdditionalMeta = /* @__NO_SIDE_EFFECTS__ */ (meta) => {
        _additionalMeta = meta;
      };
      const getAdditionalMeta = /* @__NO_SIDE_EFFECTS__ */ () => _additionalMeta;
      let _fallbackContext = null;
      const setFallbackContext = (context) => {
        _fallbackContext = context;
      };
      const getFallbackContext = () => _fallbackContext;
      let _cid = 0;
      function createCoreContext(options = {}) {
        const onWarn = isFunction(options.onWarn) ? options.onWarn : warn;
        const version = isString$1(options.version) ? options.version : VERSION$1;
        const locale = isString$1(options.locale) || isFunction(options.locale) ? options.locale : DEFAULT_LOCALE;
        const _locale = isFunction(locale) ? DEFAULT_LOCALE : locale;
        const fallbackLocale = isArray(options.fallbackLocale) || isPlainObject(options.fallbackLocale) || isString$1(options.fallbackLocale) || options.fallbackLocale === false ? options.fallbackLocale : _locale;
        const messages = isPlainObject(options.messages) ? options.messages : { [_locale]: {} };
        const datetimeFormats = isPlainObject(options.datetimeFormats) ? options.datetimeFormats : { [_locale]: {} };
        const numberFormats = isPlainObject(options.numberFormats) ? options.numberFormats : { [_locale]: {} };
        const modifiers = assign$1({}, options.modifiers || {}, getDefaultLinkedModifiers());
        const pluralRules = options.pluralRules || {};
        const missing = isFunction(options.missing) ? options.missing : null;
        const missingWarn = isBoolean(options.missingWarn) || isRegExp(options.missingWarn) ? options.missingWarn : true;
        const fallbackWarn = isBoolean(options.fallbackWarn) || isRegExp(options.fallbackWarn) ? options.fallbackWarn : true;
        const fallbackFormat = !!options.fallbackFormat;
        const unresolving = !!options.unresolving;
        const postTranslation = isFunction(options.postTranslation) ? options.postTranslation : null;
        const processor = isPlainObject(options.processor) ? options.processor : null;
        const warnHtmlMessage = isBoolean(options.warnHtmlMessage) ? options.warnHtmlMessage : true;
        const escapeParameter = !!options.escapeParameter;
        const messageCompiler = isFunction(options.messageCompiler) ? options.messageCompiler : _compiler;
        const messageResolver = isFunction(options.messageResolver) ? options.messageResolver : _resolver || resolveWithKeyValue;
        const localeFallbacker = isFunction(options.localeFallbacker) ? options.localeFallbacker : _fallbacker || fallbackWithSimple;
        const fallbackContext = isObject$3(options.fallbackContext) ? options.fallbackContext : void 0;
        const internalOptions = options;
        const __datetimeFormatters = isObject$3(internalOptions.__datetimeFormatters) ? internalOptions.__datetimeFormatters : /* @__PURE__ */ new Map();
        const __numberFormatters = isObject$3(internalOptions.__numberFormatters) ? internalOptions.__numberFormatters : /* @__PURE__ */ new Map();
        const __meta = isObject$3(internalOptions.__meta) ? internalOptions.__meta : {};
        _cid++;
        const context = {
          version,
          cid: _cid,
          locale,
          fallbackLocale,
          messages,
          modifiers,
          pluralRules,
          missing,
          missingWarn,
          fallbackWarn,
          fallbackFormat,
          unresolving,
          postTranslation,
          processor,
          warnHtmlMessage,
          escapeParameter,
          messageCompiler,
          messageResolver,
          localeFallbacker,
          fallbackContext,
          onWarn,
          __meta
        };
        {
          context.datetimeFormats = datetimeFormats;
          context.numberFormats = numberFormats;
          context.__datetimeFormatters = __datetimeFormatters;
          context.__numberFormatters = __numberFormatters;
        }
        if (__INTLIFY_PROD_DEVTOOLS__) {
          initI18nDevTools(context, version, __meta);
        }
        return context;
      }
      function handleMissing(context, key, locale, missingWarn, type) {
        const { missing, onWarn } = context;
        if (missing !== null) {
          const ret = missing(context, locale, key, type);
          return isString$1(ret) ? ret : key;
        } else {
          return key;
        }
      }
      function updateFallbackLocale(ctx, locale, fallback) {
        const context = ctx;
        context.__localeChainCache = /* @__PURE__ */ new Map();
        ctx.localeFallbacker(ctx, fallback, locale);
      }
      function format(ast) {
        const msg = (ctx) => formatParts(ctx, ast);
        return msg;
      }
      function formatParts(ctx, ast) {
        const body = ast.b || ast.body;
        if ((body.t || body.type) === 1) {
          const plural = body;
          const cases = plural.c || plural.cases;
          return ctx.plural(cases.reduce((messages, c) => [
            ...messages,
            formatMessageParts(ctx, c)
          ], []));
        } else {
          return formatMessageParts(ctx, body);
        }
      }
      function formatMessageParts(ctx, node) {
        const _static = node.s || node.static;
        if (_static) {
          return ctx.type === "text" ? _static : ctx.normalize([_static]);
        } else {
          const messages = (node.i || node.items).reduce((acm, c) => [...acm, formatMessagePart(ctx, c)], []);
          return ctx.normalize(messages);
        }
      }
      function formatMessagePart(ctx, node) {
        const type = node.t || node.type;
        switch (type) {
          case 3: {
            const text = node;
            return text.v || text.value;
          }
          case 9: {
            const literal = node;
            return literal.v || literal.value;
          }
          case 4: {
            const named = node;
            return ctx.interpolate(ctx.named(named.k || named.key));
          }
          case 5: {
            const list = node;
            return ctx.interpolate(ctx.list(list.i != null ? list.i : list.index));
          }
          case 6: {
            const linked = node;
            const modifier = linked.m || linked.modifier;
            return ctx.linked(formatMessagePart(ctx, linked.k || linked.key), modifier ? formatMessagePart(ctx, modifier) : void 0, ctx.type);
          }
          case 7: {
            const linkedKey = node;
            return linkedKey.v || linkedKey.value;
          }
          case 8: {
            const linkedModifier = node;
            return linkedModifier.v || linkedModifier.value;
          }
          default:
            throw new Error(`unhandled node type on format message part: ${type}`);
        }
      }
      const defaultOnCacheKey = (message) => message;
      let compileCache = /* @__PURE__ */ Object.create(null);
      const isMessageAST = (val) => isObject$3(val) && (val.t === 0 || val.type === 0) && ("b" in val || "body" in val);
      function baseCompile(message, options = {}) {
        let detectError = false;
        const onError = options.onError || defaultOnError;
        options.onError = (err) => {
          detectError = true;
          onError(err);
        };
        return { ...baseCompile$1(message, options), detectError };
      }
      function compile(message, context) {
        if (isString$1(message)) {
          isBoolean(context.warnHtmlMessage) ? context.warnHtmlMessage : true;
          const onCacheKey = context.onCacheKey || defaultOnCacheKey;
          const cacheKey = onCacheKey(message);
          const cached = compileCache[cacheKey];
          if (cached) {
            return cached;
          }
          const { ast, detectError } = baseCompile(message, {
            ...context,
            location: false,
            jit: true
          });
          const msg = format(ast);
          return !detectError ? compileCache[cacheKey] = msg : msg;
        } else {
          const cacheKey = message.cacheKey;
          if (cacheKey) {
            const cached = compileCache[cacheKey];
            if (cached) {
              return cached;
            }
            return compileCache[cacheKey] = format(message);
          } else {
            return format(message);
          }
        }
      }
      const NOOP_MESSAGE_FUNCTION = () => "";
      const isMessageFunction = (val) => isFunction(val);
      function translate(context, ...args) {
        const { fallbackFormat, postTranslation, unresolving, messageCompiler, fallbackLocale, messages } = context;
        const [key, options] = parseTranslateArgs(...args);
        const missingWarn = isBoolean(options.missingWarn) ? options.missingWarn : context.missingWarn;
        const fallbackWarn = isBoolean(options.fallbackWarn) ? options.fallbackWarn : context.fallbackWarn;
        const escapeParameter = isBoolean(options.escapeParameter) ? options.escapeParameter : context.escapeParameter;
        const resolvedMessage = !!options.resolvedMessage;
        const defaultMsgOrKey = isString$1(options.default) || isBoolean(options.default) ? !isBoolean(options.default) ? options.default : !messageCompiler ? () => key : key : fallbackFormat ? !messageCompiler ? () => key : key : "";
        const enableDefaultMsg = fallbackFormat || defaultMsgOrKey !== "";
        const locale = getLocale(context, options);
        escapeParameter && escapeParams(options);
        let [formatScope, targetLocale, message] = !resolvedMessage ? resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn) : [
          key,
          locale,
          messages[locale] || {}
        ];
        let format2 = formatScope;
        let cacheBaseKey = key;
        if (!resolvedMessage && !(isString$1(format2) || isMessageAST(format2) || isMessageFunction(format2))) {
          if (enableDefaultMsg) {
            format2 = defaultMsgOrKey;
            cacheBaseKey = format2;
          }
        }
        if (!resolvedMessage && (!(isString$1(format2) || isMessageAST(format2) || isMessageFunction(format2)) || !isString$1(targetLocale))) {
          return unresolving ? NOT_REOSLVED : key;
        }
        let occurred = false;
        const onError = () => {
          occurred = true;
        };
        const msg = !isMessageFunction(format2) ? compileMessageFormat(context, key, targetLocale, format2, cacheBaseKey, onError) : format2;
        if (occurred) {
          return format2;
        }
        const ctxOptions = getMessageContextOptions(context, targetLocale, message, options);
        const msgContext = createMessageContext(ctxOptions);
        const messaged = evaluateMessage(context, msg, msgContext);
        const ret = postTranslation ? postTranslation(messaged, key) : messaged;
        if (__INTLIFY_PROD_DEVTOOLS__) {
          const payloads = {
            timestamp: Date.now(),
            key: isString$1(key) ? key : isMessageFunction(format2) ? format2.key : "",
            locale: targetLocale || (isMessageFunction(format2) ? format2.locale : ""),
            format: isString$1(format2) ? format2 : isMessageFunction(format2) ? format2.source : "",
            message: ret
          };
          payloads.meta = assign$1({}, context.__meta, /* @__PURE__ */ getAdditionalMeta() || {});
          translateDevTools(payloads);
        }
        return ret;
      }
      function escapeParams(options) {
        if (isArray(options.list)) {
          options.list = options.list.map((item) => isString$1(item) ? escapeHtml(item) : item);
        } else if (isObject$3(options.named)) {
          Object.keys(options.named).forEach((key) => {
            if (isString$1(options.named[key])) {
              options.named[key] = escapeHtml(options.named[key]);
            }
          });
        }
      }
      function resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn) {
        const { messages, onWarn, messageResolver: resolveValue2, localeFallbacker } = context;
        const locales = localeFallbacker(context, fallbackLocale, locale);
        let message = {};
        let targetLocale;
        let format2 = null;
        const type = "translate";
        for (let i = 0; i < locales.length; i++) {
          targetLocale = locales[i];
          message = messages[targetLocale] || {};
          if ((format2 = resolveValue2(message, key)) === null) {
            format2 = message[key];
          }
          if (isString$1(format2) || isMessageAST(format2) || isMessageFunction(format2)) {
            break;
          }
          const missingRet = handleMissing(
            context,
            // eslint-disable-line @typescript-eslint/no-explicit-any
            key,
            targetLocale,
            missingWarn,
            type
          );
          if (missingRet !== key) {
            format2 = missingRet;
          }
        }
        return [format2, targetLocale, message];
      }
      function compileMessageFormat(context, key, targetLocale, format2, cacheBaseKey, onError) {
        const { messageCompiler, warnHtmlMessage } = context;
        if (isMessageFunction(format2)) {
          const msg2 = format2;
          msg2.locale = msg2.locale || targetLocale;
          msg2.key = msg2.key || key;
          return msg2;
        }
        if (messageCompiler == null) {
          const msg2 = () => format2;
          msg2.locale = targetLocale;
          msg2.key = key;
          return msg2;
        }
        const msg = messageCompiler(format2, getCompileContext(context, targetLocale, cacheBaseKey, format2, warnHtmlMessage, onError));
        msg.locale = targetLocale;
        msg.key = key;
        msg.source = format2;
        return msg;
      }
      function evaluateMessage(context, msg, msgCtx) {
        const messaged = msg(msgCtx);
        return messaged;
      }
      function parseTranslateArgs(...args) {
        const [arg1, arg2, arg3] = args;
        const options = {};
        if (!isString$1(arg1) && !isNumber(arg1) && !isMessageFunction(arg1) && !isMessageAST(arg1)) {
          throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
        }
        const key = isNumber(arg1) ? String(arg1) : isMessageFunction(arg1) ? arg1 : arg1;
        if (isNumber(arg2)) {
          options.plural = arg2;
        } else if (isString$1(arg2)) {
          options.default = arg2;
        } else if (isPlainObject(arg2) && !isEmptyObject(arg2)) {
          options.named = arg2;
        } else if (isArray(arg2)) {
          options.list = arg2;
        }
        if (isNumber(arg3)) {
          options.plural = arg3;
        } else if (isString$1(arg3)) {
          options.default = arg3;
        } else if (isPlainObject(arg3)) {
          assign$1(options, arg3);
        }
        return [key, options];
      }
      function getCompileContext(context, locale, key, source, warnHtmlMessage, onError) {
        return {
          locale,
          key,
          warnHtmlMessage,
          onError: (err) => {
            onError && onError(err);
            {
              throw err;
            }
          },
          onCacheKey: (source2) => generateFormatCacheKey(locale, key, source2)
        };
      }
      function getMessageContextOptions(context, locale, message, options) {
        const { modifiers, pluralRules, messageResolver: resolveValue2, fallbackLocale, fallbackWarn, missingWarn, fallbackContext } = context;
        const resolveMessage = (key) => {
          let val = resolveValue2(message, key);
          if (val == null && fallbackContext) {
            const [, , message2] = resolveMessageFormat(fallbackContext, key, locale, fallbackLocale, fallbackWarn, missingWarn);
            val = resolveValue2(message2, key);
          }
          if (isString$1(val) || isMessageAST(val)) {
            let occurred = false;
            const onError = () => {
              occurred = true;
            };
            const msg = compileMessageFormat(context, key, locale, val, key, onError);
            return !occurred ? msg : NOOP_MESSAGE_FUNCTION;
          } else if (isMessageFunction(val)) {
            return val;
          } else {
            return NOOP_MESSAGE_FUNCTION;
          }
        };
        const ctxOptions = {
          locale,
          modifiers,
          pluralRules,
          messages: resolveMessage
        };
        if (context.processor) {
          ctxOptions.processor = context.processor;
        }
        if (options.list) {
          ctxOptions.list = options.list;
        }
        if (options.named) {
          ctxOptions.named = options.named;
        }
        if (isNumber(options.plural)) {
          ctxOptions.pluralIndex = options.plural;
        }
        return ctxOptions;
      }
      function datetime(context, ...args) {
        const { datetimeFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
        const { __datetimeFormatters } = context;
        const [key, value, options, overrides] = parseDateTimeArgs(...args);
        const missingWarn = isBoolean(options.missingWarn) ? options.missingWarn : context.missingWarn;
        isBoolean(options.fallbackWarn) ? options.fallbackWarn : context.fallbackWarn;
        const part = !!options.part;
        const locale = getLocale(context, options);
        const locales = localeFallbacker(
          context,
          // eslint-disable-line @typescript-eslint/no-explicit-any
          fallbackLocale,
          locale
        );
        if (!isString$1(key) || key === "") {
          return new Intl.DateTimeFormat(locale, overrides).format(value);
        }
        let datetimeFormat = {};
        let targetLocale;
        let format2 = null;
        const type = "datetime format";
        for (let i = 0; i < locales.length; i++) {
          targetLocale = locales[i];
          datetimeFormat = datetimeFormats[targetLocale] || {};
          format2 = datetimeFormat[key];
          if (isPlainObject(format2))
            break;
          handleMissing(context, key, targetLocale, missingWarn, type);
        }
        if (!isPlainObject(format2) || !isString$1(targetLocale)) {
          return unresolving ? NOT_REOSLVED : key;
        }
        let id = `${targetLocale}__${key}`;
        if (!isEmptyObject(overrides)) {
          id = `${id}__${JSON.stringify(overrides)}`;
        }
        let formatter = __datetimeFormatters.get(id);
        if (!formatter) {
          formatter = new Intl.DateTimeFormat(targetLocale, assign$1({}, format2, overrides));
          __datetimeFormatters.set(id, formatter);
        }
        return !part ? formatter.format(value) : formatter.formatToParts(value);
      }
      const DATETIME_FORMAT_OPTIONS_KEYS = [
        "localeMatcher",
        "weekday",
        "era",
        "year",
        "month",
        "day",
        "hour",
        "minute",
        "second",
        "timeZoneName",
        "formatMatcher",
        "hour12",
        "timeZone",
        "dateStyle",
        "timeStyle",
        "calendar",
        "dayPeriod",
        "numberingSystem",
        "hourCycle",
        "fractionalSecondDigits"
      ];
      function parseDateTimeArgs(...args) {
        const [arg1, arg2, arg3, arg4] = args;
        const options = {};
        let overrides = {};
        let value;
        if (isString$1(arg1)) {
          const matches = arg1.match(/(\d{4}-\d{2}-\d{2})(T|\s)?(.*)/);
          if (!matches) {
            throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
          }
          const dateTime = matches[3] ? matches[3].trim().startsWith("T") ? `${matches[1].trim()}${matches[3].trim()}` : `${matches[1].trim()}T${matches[3].trim()}` : matches[1].trim();
          value = new Date(dateTime);
          try {
            value.toISOString();
          } catch (e) {
            throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
          }
        } else if (isDate(arg1)) {
          if (isNaN(arg1.getTime())) {
            throw createCoreError(CoreErrorCodes.INVALID_DATE_ARGUMENT);
          }
          value = arg1;
        } else if (isNumber(arg1)) {
          value = arg1;
        } else {
          throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
        }
        if (isString$1(arg2)) {
          options.key = arg2;
        } else if (isPlainObject(arg2)) {
          Object.keys(arg2).forEach((key) => {
            if (DATETIME_FORMAT_OPTIONS_KEYS.includes(key)) {
              overrides[key] = arg2[key];
            } else {
              options[key] = arg2[key];
            }
          });
        }
        if (isString$1(arg3)) {
          options.locale = arg3;
        } else if (isPlainObject(arg3)) {
          overrides = arg3;
        }
        if (isPlainObject(arg4)) {
          overrides = arg4;
        }
        return [options.key || "", value, options, overrides];
      }
      function clearDateTimeFormat(ctx, locale, format2) {
        const context = ctx;
        for (const key in format2) {
          const id = `${locale}__${key}`;
          if (!context.__datetimeFormatters.has(id)) {
            continue;
          }
          context.__datetimeFormatters.delete(id);
        }
      }
      function number(context, ...args) {
        const { numberFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
        const { __numberFormatters } = context;
        const [key, value, options, overrides] = parseNumberArgs(...args);
        const missingWarn = isBoolean(options.missingWarn) ? options.missingWarn : context.missingWarn;
        isBoolean(options.fallbackWarn) ? options.fallbackWarn : context.fallbackWarn;
        const part = !!options.part;
        const locale = getLocale(context, options);
        const locales = localeFallbacker(
          context,
          // eslint-disable-line @typescript-eslint/no-explicit-any
          fallbackLocale,
          locale
        );
        if (!isString$1(key) || key === "") {
          return new Intl.NumberFormat(locale, overrides).format(value);
        }
        let numberFormat = {};
        let targetLocale;
        let format2 = null;
        const type = "number format";
        for (let i = 0; i < locales.length; i++) {
          targetLocale = locales[i];
          numberFormat = numberFormats[targetLocale] || {};
          format2 = numberFormat[key];
          if (isPlainObject(format2))
            break;
          handleMissing(context, key, targetLocale, missingWarn, type);
        }
        if (!isPlainObject(format2) || !isString$1(targetLocale)) {
          return unresolving ? NOT_REOSLVED : key;
        }
        let id = `${targetLocale}__${key}`;
        if (!isEmptyObject(overrides)) {
          id = `${id}__${JSON.stringify(overrides)}`;
        }
        let formatter = __numberFormatters.get(id);
        if (!formatter) {
          formatter = new Intl.NumberFormat(targetLocale, assign$1({}, format2, overrides));
          __numberFormatters.set(id, formatter);
        }
        return !part ? formatter.format(value) : formatter.formatToParts(value);
      }
      const NUMBER_FORMAT_OPTIONS_KEYS = [
        "localeMatcher",
        "style",
        "currency",
        "currencyDisplay",
        "currencySign",
        "useGrouping",
        "minimumIntegerDigits",
        "minimumFractionDigits",
        "maximumFractionDigits",
        "minimumSignificantDigits",
        "maximumSignificantDigits",
        "compactDisplay",
        "notation",
        "signDisplay",
        "unit",
        "unitDisplay",
        "roundingMode",
        "roundingPriority",
        "roundingIncrement",
        "trailingZeroDisplay"
      ];
      function parseNumberArgs(...args) {
        const [arg1, arg2, arg3, arg4] = args;
        const options = {};
        let overrides = {};
        if (!isNumber(arg1)) {
          throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
        }
        const value = arg1;
        if (isString$1(arg2)) {
          options.key = arg2;
        } else if (isPlainObject(arg2)) {
          Object.keys(arg2).forEach((key) => {
            if (NUMBER_FORMAT_OPTIONS_KEYS.includes(key)) {
              overrides[key] = arg2[key];
            } else {
              options[key] = arg2[key];
            }
          });
        }
        if (isString$1(arg3)) {
          options.locale = arg3;
        } else if (isPlainObject(arg3)) {
          overrides = arg3;
        }
        if (isPlainObject(arg4)) {
          overrides = arg4;
        }
        return [options.key || "", value, options, overrides];
      }
      function clearNumberFormat(ctx, locale, format2) {
        const context = ctx;
        for (const key in format2) {
          const id = `${locale}__${key}`;
          if (!context.__numberFormatters.has(id)) {
            continue;
          }
          context.__numberFormatters.delete(id);
        }
      }
      {
        initFeatureFlags$1();
      }
      /*!
        * vue-i18n v9.12.1
        * (c) 2024 kazuya kawaguchi
        * Released under the MIT License.
        */
      const VERSION = "9.12.1";
      function initFeatureFlags() {
        if (typeof __INTLIFY_PROD_DEVTOOLS__ !== "boolean") {
          getGlobalThis().__INTLIFY_PROD_DEVTOOLS__ = false;
        }
      }
      const code$1 = CoreWarnCodes.__EXTEND_POINT__;
      const inc$1 = incrementer(code$1);
      ({
        FALLBACK_TO_ROOT: code$1,
        // 9
        NOT_SUPPORTED_PRESERVE: inc$1(),
        // 10
        NOT_SUPPORTED_FORMATTER: inc$1(),
        // 11
        NOT_SUPPORTED_PRESERVE_DIRECTIVE: inc$1(),
        // 12
        NOT_SUPPORTED_GET_CHOICE_INDEX: inc$1(),
        // 13
        COMPONENT_NAME_LEGACY_COMPATIBLE: inc$1(),
        // 14
        NOT_FOUND_PARENT_SCOPE: inc$1(),
        // 15
        IGNORE_OBJ_FLATTEN: inc$1(),
        // 16
        NOTICE_DROP_ALLOW_COMPOSITION: inc$1(),
        // 17
        NOTICE_DROP_TRANSLATE_EXIST_COMPATIBLE_FLAG: inc$1()
        // 18
      });
      const code = CoreErrorCodes.__EXTEND_POINT__;
      const inc = incrementer(code);
      const I18nErrorCodes = {
        // composer module errors
        UNEXPECTED_RETURN_TYPE: code,
        // 24
        // legacy module errors
        INVALID_ARGUMENT: inc(),
        // 25
        // i18n module errors
        MUST_BE_CALL_SETUP_TOP: inc(),
        // 26
        NOT_INSTALLED: inc(),
        // 27
        NOT_AVAILABLE_IN_LEGACY_MODE: inc(),
        // 28
        // directive module errors
        REQUIRED_VALUE: inc(),
        // 29
        INVALID_VALUE: inc(),
        // 30
        // vue-devtools errors
        CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN: inc(),
        // 31
        NOT_INSTALLED_WITH_PROVIDE: inc(),
        // 32
        // unexpected error
        UNEXPECTED_ERROR: inc(),
        // 33
        // not compatible legacy vue-i18n constructor
        NOT_COMPATIBLE_LEGACY_VUE_I18N: inc(),
        // 34
        // bridge support vue 2.x only
        BRIDGE_SUPPORT_VUE_2_ONLY: inc(),
        // 35
        // need to define `i18n` option in `allowComposition: true` and `useScope: 'local' at `useI18n``
        MUST_DEFINE_I18N_OPTION_IN_ALLOW_COMPOSITION: inc(),
        // 36
        // Not available Compostion API in Legacy API mode. Please make sure that the legacy API mode is working properly
        NOT_AVAILABLE_COMPOSITION_IN_LEGACY: inc(),
        // 37
        // for enhancement
        __EXTEND_POINT__: inc()
        // 38
      };
      function createI18nError(code2, ...args) {
        return createCompileError(code2, null, void 0);
      }
      const TranslateVNodeSymbol = /* @__PURE__ */ makeSymbol("__translateVNode");
      const DatetimePartsSymbol = /* @__PURE__ */ makeSymbol("__datetimeParts");
      const NumberPartsSymbol = /* @__PURE__ */ makeSymbol("__numberParts");
      const SetPluralRulesSymbol = makeSymbol("__setPluralRules");
      const InejctWithOptionSymbol = /* @__PURE__ */ makeSymbol("__injectWithOption");
      const DisposeSymbol = /* @__PURE__ */ makeSymbol("__dispose");
      function handleFlatJson(obj) {
        if (!isObject$3(obj)) {
          return obj;
        }
        for (const key in obj) {
          if (!hasOwn(obj, key)) {
            continue;
          }
          if (!key.includes(".")) {
            if (isObject$3(obj[key])) {
              handleFlatJson(obj[key]);
            }
          } else {
            const subKeys = key.split(".");
            const lastIndex = subKeys.length - 1;
            let currentObj = obj;
            let hasStringValue = false;
            for (let i = 0; i < lastIndex; i++) {
              if (!(subKeys[i] in currentObj)) {
                currentObj[subKeys[i]] = {};
              }
              if (!isObject$3(currentObj[subKeys[i]])) {
                hasStringValue = true;
                break;
              }
              currentObj = currentObj[subKeys[i]];
            }
            if (!hasStringValue) {
              currentObj[subKeys[lastIndex]] = obj[key];
              delete obj[key];
            }
            if (isObject$3(currentObj[subKeys[lastIndex]])) {
              handleFlatJson(currentObj[subKeys[lastIndex]]);
            }
          }
        }
        return obj;
      }
      function getLocaleMessages(locale, options) {
        const { messages, __i18n, messageResolver, flatJson } = options;
        const ret = isPlainObject(messages) ? messages : isArray(__i18n) ? {} : { [locale]: {} };
        if (isArray(__i18n)) {
          __i18n.forEach((custom) => {
            if ("locale" in custom && "resource" in custom) {
              const { locale: locale2, resource: resource2 } = custom;
              if (locale2) {
                ret[locale2] = ret[locale2] || {};
                deepCopy(resource2, ret[locale2]);
              } else {
                deepCopy(resource2, ret);
              }
            } else {
              isString$1(custom) && deepCopy(JSON.parse(custom), ret);
            }
          });
        }
        if (messageResolver == null && flatJson) {
          for (const key in ret) {
            if (hasOwn(ret, key)) {
              handleFlatJson(ret[key]);
            }
          }
        }
        return ret;
      }
      function getComponentOptions(instance) {
        return instance.type;
      }
      function adjustI18nResources(gl, options, componentOptions) {
        let messages = isObject$3(options.messages) ? options.messages : {};
        if ("__i18nGlobal" in componentOptions) {
          messages = getLocaleMessages(gl.locale.value, {
            messages,
            __i18n: componentOptions.__i18nGlobal
          });
        }
        const locales = Object.keys(messages);
        if (locales.length) {
          locales.forEach((locale) => {
            gl.mergeLocaleMessage(locale, messages[locale]);
          });
        }
        {
          if (isObject$3(options.datetimeFormats)) {
            const locales2 = Object.keys(options.datetimeFormats);
            if (locales2.length) {
              locales2.forEach((locale) => {
                gl.mergeDateTimeFormat(locale, options.datetimeFormats[locale]);
              });
            }
          }
          if (isObject$3(options.numberFormats)) {
            const locales2 = Object.keys(options.numberFormats);
            if (locales2.length) {
              locales2.forEach((locale) => {
                gl.mergeNumberFormat(locale, options.numberFormats[locale]);
              });
            }
          }
        }
      }
      function createTextNode(key) {
        return vue.createVNode(vue.Text, null, key, 0);
      }
      const DEVTOOLS_META = "__INTLIFY_META__";
      const NOOP_RETURN_ARRAY = () => [];
      const NOOP_RETURN_FALSE = () => false;
      let composerID = 0;
      function defineCoreMissingHandler(missing) {
        return (ctx, locale, key, type) => {
          return missing(locale, key, vue.getCurrentInstance() || void 0, type);
        };
      }
      const getMetaInfo = /* @__NO_SIDE_EFFECTS__ */ () => {
        const instance = vue.getCurrentInstance();
        let meta = null;
        return instance && (meta = getComponentOptions(instance)[DEVTOOLS_META]) ? { [DEVTOOLS_META]: meta } : null;
      };
      function createComposer(options = {}, VueI18nLegacy) {
        const { __root, __injectWithOption } = options;
        const _isGlobal = __root === void 0;
        const flatJson = options.flatJson;
        const _ref = inBrowser ? vue.ref : vue.shallowRef;
        const translateExistCompatible = !!options.translateExistCompatible;
        let _inheritLocale = isBoolean(options.inheritLocale) ? options.inheritLocale : true;
        const _locale = _ref(
          // prettier-ignore
          __root && _inheritLocale ? __root.locale.value : isString$1(options.locale) ? options.locale : DEFAULT_LOCALE
        );
        const _fallbackLocale = _ref(
          // prettier-ignore
          __root && _inheritLocale ? __root.fallbackLocale.value : isString$1(options.fallbackLocale) || isArray(options.fallbackLocale) || isPlainObject(options.fallbackLocale) || options.fallbackLocale === false ? options.fallbackLocale : _locale.value
        );
        const _messages = _ref(getLocaleMessages(_locale.value, options));
        const _datetimeFormats = _ref(isPlainObject(options.datetimeFormats) ? options.datetimeFormats : { [_locale.value]: {} });
        const _numberFormats = _ref(isPlainObject(options.numberFormats) ? options.numberFormats : { [_locale.value]: {} });
        let _missingWarn = __root ? __root.missingWarn : isBoolean(options.missingWarn) || isRegExp(options.missingWarn) ? options.missingWarn : true;
        let _fallbackWarn = __root ? __root.fallbackWarn : isBoolean(options.fallbackWarn) || isRegExp(options.fallbackWarn) ? options.fallbackWarn : true;
        let _fallbackRoot = __root ? __root.fallbackRoot : isBoolean(options.fallbackRoot) ? options.fallbackRoot : true;
        let _fallbackFormat = !!options.fallbackFormat;
        let _missing = isFunction(options.missing) ? options.missing : null;
        let _runtimeMissing = isFunction(options.missing) ? defineCoreMissingHandler(options.missing) : null;
        let _postTranslation = isFunction(options.postTranslation) ? options.postTranslation : null;
        let _warnHtmlMessage = __root ? __root.warnHtmlMessage : isBoolean(options.warnHtmlMessage) ? options.warnHtmlMessage : true;
        let _escapeParameter = !!options.escapeParameter;
        const _modifiers = __root ? __root.modifiers : isPlainObject(options.modifiers) ? options.modifiers : {};
        let _pluralRules = options.pluralRules || __root && __root.pluralRules;
        let _context;
        const getCoreContext = () => {
          _isGlobal && setFallbackContext(null);
          const ctxOptions = {
            version: VERSION,
            locale: _locale.value,
            fallbackLocale: _fallbackLocale.value,
            messages: _messages.value,
            modifiers: _modifiers,
            pluralRules: _pluralRules,
            missing: _runtimeMissing === null ? void 0 : _runtimeMissing,
            missingWarn: _missingWarn,
            fallbackWarn: _fallbackWarn,
            fallbackFormat: _fallbackFormat,
            unresolving: true,
            postTranslation: _postTranslation === null ? void 0 : _postTranslation,
            warnHtmlMessage: _warnHtmlMessage,
            escapeParameter: _escapeParameter,
            messageResolver: options.messageResolver,
            messageCompiler: options.messageCompiler,
            __meta: { framework: "vue" }
          };
          {
            ctxOptions.datetimeFormats = _datetimeFormats.value;
            ctxOptions.numberFormats = _numberFormats.value;
            ctxOptions.__datetimeFormatters = isPlainObject(_context) ? _context.__datetimeFormatters : void 0;
            ctxOptions.__numberFormatters = isPlainObject(_context) ? _context.__numberFormatters : void 0;
          }
          const ctx = createCoreContext(ctxOptions);
          _isGlobal && setFallbackContext(ctx);
          return ctx;
        };
        _context = getCoreContext();
        updateFallbackLocale(_context, _locale.value, _fallbackLocale.value);
        function trackReactivityValues() {
          return [
            _locale.value,
            _fallbackLocale.value,
            _messages.value,
            _datetimeFormats.value,
            _numberFormats.value
          ];
        }
        const locale = vue.computed({
          get: () => _locale.value,
          set: (val) => {
            _locale.value = val;
            _context.locale = _locale.value;
          }
        });
        const fallbackLocale = vue.computed({
          get: () => _fallbackLocale.value,
          set: (val) => {
            _fallbackLocale.value = val;
            _context.fallbackLocale = _fallbackLocale.value;
            updateFallbackLocale(_context, _locale.value, val);
          }
        });
        const messages = vue.computed(() => _messages.value);
        const datetimeFormats = /* @__PURE__ */ vue.computed(() => _datetimeFormats.value);
        const numberFormats = /* @__PURE__ */ vue.computed(() => _numberFormats.value);
        function getPostTranslationHandler() {
          return isFunction(_postTranslation) ? _postTranslation : null;
        }
        function setPostTranslationHandler(handler) {
          _postTranslation = handler;
          _context.postTranslation = handler;
        }
        function getMissingHandler() {
          return _missing;
        }
        function setMissingHandler(handler) {
          if (handler !== null) {
            _runtimeMissing = defineCoreMissingHandler(handler);
          }
          _missing = handler;
          _context.missing = _runtimeMissing;
        }
        const wrapWithDeps = (fn, argumentParser, warnType, fallbackSuccess, fallbackFail, successCondition) => {
          trackReactivityValues();
          let ret;
          try {
            if (__INTLIFY_PROD_DEVTOOLS__) {
              /* @__PURE__ */ setAdditionalMeta(/* @__PURE__ */ getMetaInfo());
            }
            if (!_isGlobal) {
              _context.fallbackContext = __root ? getFallbackContext() : void 0;
            }
            ret = fn(_context);
          } finally {
            if (__INTLIFY_PROD_DEVTOOLS__)
              ;
            if (!_isGlobal) {
              _context.fallbackContext = void 0;
            }
          }
          if (warnType !== "translate exists" && // for not `te` (e.g `t`)
          isNumber(ret) && ret === NOT_REOSLVED || warnType === "translate exists" && !ret) {
            const [key, arg2] = argumentParser();
            return __root && _fallbackRoot ? fallbackSuccess(__root) : fallbackFail(key);
          } else if (successCondition(ret)) {
            return ret;
          } else {
            throw createI18nError(I18nErrorCodes.UNEXPECTED_RETURN_TYPE);
          }
        };
        function t2(...args) {
          return wrapWithDeps((context) => Reflect.apply(translate, null, [context, ...args]), () => parseTranslateArgs(...args), "translate", (root2) => Reflect.apply(root2.t, root2, [...args]), (key) => key, (val) => isString$1(val));
        }
        function rt(...args) {
          const [arg1, arg2, arg3] = args;
          if (arg3 && !isObject$3(arg3)) {
            throw createI18nError(I18nErrorCodes.INVALID_ARGUMENT);
          }
          return t2(...[arg1, arg2, assign$1({ resolvedMessage: true }, arg3 || {})]);
        }
        function d(...args) {
          return wrapWithDeps((context) => Reflect.apply(datetime, null, [context, ...args]), () => parseDateTimeArgs(...args), "datetime format", (root2) => Reflect.apply(root2.d, root2, [...args]), () => MISSING_RESOLVE_VALUE, (val) => isString$1(val));
        }
        function n(...args) {
          return wrapWithDeps((context) => Reflect.apply(number, null, [context, ...args]), () => parseNumberArgs(...args), "number format", (root2) => Reflect.apply(root2.n, root2, [...args]), () => MISSING_RESOLVE_VALUE, (val) => isString$1(val));
        }
        function normalize(values2) {
          return values2.map((val) => isString$1(val) || isNumber(val) || isBoolean(val) ? createTextNode(String(val)) : val);
        }
        const interpolate = (val) => val;
        const processor = {
          normalize,
          interpolate,
          type: "vnode"
        };
        function translateVNode(...args) {
          return wrapWithDeps(
            (context) => {
              let ret;
              const _context2 = context;
              try {
                _context2.processor = processor;
                ret = Reflect.apply(translate, null, [_context2, ...args]);
              } finally {
                _context2.processor = null;
              }
              return ret;
            },
            () => parseTranslateArgs(...args),
            "translate",
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            (root2) => root2[TranslateVNodeSymbol](...args),
            (key) => [createTextNode(key)],
            (val) => isArray(val)
          );
        }
        function numberParts(...args) {
          return wrapWithDeps(
            (context) => Reflect.apply(number, null, [context, ...args]),
            () => parseNumberArgs(...args),
            "number format",
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            (root2) => root2[NumberPartsSymbol](...args),
            NOOP_RETURN_ARRAY,
            (val) => isString$1(val) || isArray(val)
          );
        }
        function datetimeParts(...args) {
          return wrapWithDeps(
            (context) => Reflect.apply(datetime, null, [context, ...args]),
            () => parseDateTimeArgs(...args),
            "datetime format",
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            (root2) => root2[DatetimePartsSymbol](...args),
            NOOP_RETURN_ARRAY,
            (val) => isString$1(val) || isArray(val)
          );
        }
        function setPluralRules(rules) {
          _pluralRules = rules;
          _context.pluralRules = _pluralRules;
        }
        function te(key, locale2) {
          return wrapWithDeps(() => {
            if (!key) {
              return false;
            }
            const targetLocale = isString$1(locale2) ? locale2 : _locale.value;
            const message = getLocaleMessage(targetLocale);
            const resolved = _context.messageResolver(message, key);
            return !translateExistCompatible ? isMessageAST(resolved) || isMessageFunction(resolved) || isString$1(resolved) : resolved != null;
          }, () => [key], "translate exists", (root2) => {
            return Reflect.apply(root2.te, root2, [key, locale2]);
          }, NOOP_RETURN_FALSE, (val) => isBoolean(val));
        }
        function resolveMessages(key) {
          let messages2 = null;
          const locales = fallbackWithLocaleChain(_context, _fallbackLocale.value, _locale.value);
          for (let i = 0; i < locales.length; i++) {
            const targetLocaleMessages = _messages.value[locales[i]] || {};
            const messageValue = _context.messageResolver(targetLocaleMessages, key);
            if (messageValue != null) {
              messages2 = messageValue;
              break;
            }
          }
          return messages2;
        }
        function tm(key) {
          const messages2 = resolveMessages(key);
          return messages2 != null ? messages2 : __root ? __root.tm(key) || {} : {};
        }
        function getLocaleMessage(locale2) {
          return _messages.value[locale2] || {};
        }
        function setLocaleMessage(locale2, message) {
          if (flatJson) {
            const _message = { [locale2]: message };
            for (const key in _message) {
              if (hasOwn(_message, key)) {
                handleFlatJson(_message[key]);
              }
            }
            message = _message[locale2];
          }
          _messages.value[locale2] = message;
          _context.messages = _messages.value;
        }
        function mergeLocaleMessage(locale2, message) {
          _messages.value[locale2] = _messages.value[locale2] || {};
          const _message = { [locale2]: message };
          if (flatJson) {
            for (const key in _message) {
              if (hasOwn(_message, key)) {
                handleFlatJson(_message[key]);
              }
            }
          }
          message = _message[locale2];
          deepCopy(message, _messages.value[locale2]);
          _context.messages = _messages.value;
        }
        function getDateTimeFormat(locale2) {
          return _datetimeFormats.value[locale2] || {};
        }
        function setDateTimeFormat(locale2, format2) {
          _datetimeFormats.value[locale2] = format2;
          _context.datetimeFormats = _datetimeFormats.value;
          clearDateTimeFormat(_context, locale2, format2);
        }
        function mergeDateTimeFormat(locale2, format2) {
          _datetimeFormats.value[locale2] = assign$1(_datetimeFormats.value[locale2] || {}, format2);
          _context.datetimeFormats = _datetimeFormats.value;
          clearDateTimeFormat(_context, locale2, format2);
        }
        function getNumberFormat(locale2) {
          return _numberFormats.value[locale2] || {};
        }
        function setNumberFormat(locale2, format2) {
          _numberFormats.value[locale2] = format2;
          _context.numberFormats = _numberFormats.value;
          clearNumberFormat(_context, locale2, format2);
        }
        function mergeNumberFormat(locale2, format2) {
          _numberFormats.value[locale2] = assign$1(_numberFormats.value[locale2] || {}, format2);
          _context.numberFormats = _numberFormats.value;
          clearNumberFormat(_context, locale2, format2);
        }
        composerID++;
        if (__root && inBrowser) {
          vue.watch(__root.locale, (val) => {
            if (_inheritLocale) {
              _locale.value = val;
              _context.locale = val;
              updateFallbackLocale(_context, _locale.value, _fallbackLocale.value);
            }
          });
          vue.watch(__root.fallbackLocale, (val) => {
            if (_inheritLocale) {
              _fallbackLocale.value = val;
              _context.fallbackLocale = val;
              updateFallbackLocale(_context, _locale.value, _fallbackLocale.value);
            }
          });
        }
        const composer = {
          id: composerID,
          locale,
          fallbackLocale,
          get inheritLocale() {
            return _inheritLocale;
          },
          set inheritLocale(val) {
            _inheritLocale = val;
            if (val && __root) {
              _locale.value = __root.locale.value;
              _fallbackLocale.value = __root.fallbackLocale.value;
              updateFallbackLocale(_context, _locale.value, _fallbackLocale.value);
            }
          },
          get availableLocales() {
            return Object.keys(_messages.value).sort();
          },
          messages,
          get modifiers() {
            return _modifiers;
          },
          get pluralRules() {
            return _pluralRules || {};
          },
          get isGlobal() {
            return _isGlobal;
          },
          get missingWarn() {
            return _missingWarn;
          },
          set missingWarn(val) {
            _missingWarn = val;
            _context.missingWarn = _missingWarn;
          },
          get fallbackWarn() {
            return _fallbackWarn;
          },
          set fallbackWarn(val) {
            _fallbackWarn = val;
            _context.fallbackWarn = _fallbackWarn;
          },
          get fallbackRoot() {
            return _fallbackRoot;
          },
          set fallbackRoot(val) {
            _fallbackRoot = val;
          },
          get fallbackFormat() {
            return _fallbackFormat;
          },
          set fallbackFormat(val) {
            _fallbackFormat = val;
            _context.fallbackFormat = _fallbackFormat;
          },
          get warnHtmlMessage() {
            return _warnHtmlMessage;
          },
          set warnHtmlMessage(val) {
            _warnHtmlMessage = val;
            _context.warnHtmlMessage = val;
          },
          get escapeParameter() {
            return _escapeParameter;
          },
          set escapeParameter(val) {
            _escapeParameter = val;
            _context.escapeParameter = val;
          },
          t: t2,
          getLocaleMessage,
          setLocaleMessage,
          mergeLocaleMessage,
          getPostTranslationHandler,
          setPostTranslationHandler,
          getMissingHandler,
          setMissingHandler,
          [SetPluralRulesSymbol]: setPluralRules
        };
        {
          composer.datetimeFormats = datetimeFormats;
          composer.numberFormats = numberFormats;
          composer.rt = rt;
          composer.te = te;
          composer.tm = tm;
          composer.d = d;
          composer.n = n;
          composer.getDateTimeFormat = getDateTimeFormat;
          composer.setDateTimeFormat = setDateTimeFormat;
          composer.mergeDateTimeFormat = mergeDateTimeFormat;
          composer.getNumberFormat = getNumberFormat;
          composer.setNumberFormat = setNumberFormat;
          composer.mergeNumberFormat = mergeNumberFormat;
          composer[InejctWithOptionSymbol] = __injectWithOption;
          composer[TranslateVNodeSymbol] = translateVNode;
          composer[DatetimePartsSymbol] = datetimeParts;
          composer[NumberPartsSymbol] = numberParts;
        }
        return composer;
      }
      const baseFormatProps = {
        tag: {
          type: [String, Object]
        },
        locale: {
          type: String
        },
        scope: {
          type: String,
          // NOTE: avoid https://github.com/microsoft/rushstack/issues/1050
          validator: (val) => val === "parent" || val === "global",
          default: "parent"
          /* ComponentI18nScope */
        },
        i18n: {
          type: Object
        }
      };
      function getInterpolateArg({ slots }, keys2) {
        if (keys2.length === 1 && keys2[0] === "default") {
          const ret = slots.default ? slots.default() : [];
          return ret.reduce((slot, current) => {
            return [
              ...slot,
              // prettier-ignore
              ...current.type === vue.Fragment ? current.children : [current]
            ];
          }, []);
        } else {
          return keys2.reduce((arg, key) => {
            const slot = slots[key];
            if (slot) {
              arg[key] = slot();
            }
            return arg;
          }, {});
        }
      }
      function getFragmentableTag(tag) {
        return vue.Fragment;
      }
      const TranslationImpl = /* @__PURE__ */ vue.defineComponent({
        /* eslint-disable */
        name: "i18n-t",
        props: assign$1({
          keypath: {
            type: String,
            required: true
          },
          plural: {
            type: [Number, String],
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            validator: (val) => isNumber(val) || !isNaN(val)
          }
        }, baseFormatProps),
        /* eslint-enable */
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        setup(props, context) {
          const { slots, attrs } = context;
          const i18n2 = props.i18n || useI18n({
            useScope: props.scope,
            __useComponent: true
          });
          return () => {
            const keys2 = Object.keys(slots).filter((key) => key !== "_");
            const options = {};
            if (props.locale) {
              options.locale = props.locale;
            }
            if (props.plural !== void 0) {
              options.plural = isString$1(props.plural) ? +props.plural : props.plural;
            }
            const arg = getInterpolateArg(context, keys2);
            const children = i18n2[TranslateVNodeSymbol](props.keypath, arg, options);
            const assignedAttrs = assign$1({}, attrs);
            const tag = isString$1(props.tag) || isObject$3(props.tag) ? props.tag : getFragmentableTag();
            return vue.h(tag, assignedAttrs, children);
          };
        }
      });
      const Translation = TranslationImpl;
      function isVNode(target) {
        return isArray(target) && !isString$1(target[0]);
      }
      function renderFormatter(props, context, slotKeys, partFormatter) {
        const { slots, attrs } = context;
        return () => {
          const options = { part: true };
          let overrides = {};
          if (props.locale) {
            options.locale = props.locale;
          }
          if (isString$1(props.format)) {
            options.key = props.format;
          } else if (isObject$3(props.format)) {
            if (isString$1(props.format.key)) {
              options.key = props.format.key;
            }
            overrides = Object.keys(props.format).reduce((options2, prop) => {
              return slotKeys.includes(prop) ? assign$1({}, options2, { [prop]: props.format[prop] }) : options2;
            }, {});
          }
          const parts = partFormatter(...[props.value, options, overrides]);
          let children = [options.key];
          if (isArray(parts)) {
            children = parts.map((part, index) => {
              const slot = slots[part.type];
              const node = slot ? slot({ [part.type]: part.value, index, parts }) : [part.value];
              if (isVNode(node)) {
                node[0].key = `${part.type}-${index}`;
              }
              return node;
            });
          } else if (isString$1(parts)) {
            children = [parts];
          }
          const assignedAttrs = assign$1({}, attrs);
          const tag = isString$1(props.tag) || isObject$3(props.tag) ? props.tag : getFragmentableTag();
          return vue.h(tag, assignedAttrs, children);
        };
      }
      const NumberFormatImpl = /* @__PURE__ */ vue.defineComponent({
        /* eslint-disable */
        name: "i18n-n",
        props: assign$1({
          value: {
            type: Number,
            required: true
          },
          format: {
            type: [String, Object]
          }
        }, baseFormatProps),
        /* eslint-enable */
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        setup(props, context) {
          const i18n2 = props.i18n || useI18n({
            useScope: props.scope,
            __useComponent: true
          });
          return renderFormatter(props, context, NUMBER_FORMAT_OPTIONS_KEYS, (...args) => (
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            i18n2[NumberPartsSymbol](...args)
          ));
        }
      });
      const NumberFormat = NumberFormatImpl;
      const DatetimeFormatImpl = /* @__PURE__ */ vue.defineComponent({
        /* eslint-disable */
        name: "i18n-d",
        props: assign$1({
          value: {
            type: [Number, Date],
            required: true
          },
          format: {
            type: [String, Object]
          }
        }, baseFormatProps),
        /* eslint-enable */
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        setup(props, context) {
          const i18n2 = props.i18n || useI18n({
            useScope: props.scope,
            __useComponent: true
          });
          return renderFormatter(props, context, DATETIME_FORMAT_OPTIONS_KEYS, (...args) => (
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            i18n2[DatetimePartsSymbol](...args)
          ));
        }
      });
      const DatetimeFormat = DatetimeFormatImpl;
      function getComposer$2(i18n2, instance) {
        const i18nInternal = i18n2;
        if (i18n2.mode === "composition") {
          return i18nInternal.__getInstance(instance) || i18n2.global;
        } else {
          const vueI18n = i18nInternal.__getInstance(instance);
          return vueI18n != null ? vueI18n.__composer : i18n2.global.__composer;
        }
      }
      function vTDirective(i18n2) {
        const _process = (binding) => {
          const { instance, modifiers, value } = binding;
          if (!instance || !instance.$) {
            throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR);
          }
          const composer = getComposer$2(i18n2, instance.$);
          const parsedValue = parseValue(value);
          return [
            Reflect.apply(composer.t, composer, [...makeParams(parsedValue)]),
            composer
          ];
        };
        const register = (el, binding) => {
          const [textContent, composer] = _process(binding);
          if (inBrowser && i18n2.global === composer) {
            el.__i18nWatcher = vue.watch(composer.locale, () => {
              binding.instance && binding.instance.$forceUpdate();
            });
          }
          el.__composer = composer;
          el.textContent = textContent;
        };
        const unregister = (el) => {
          if (inBrowser && el.__i18nWatcher) {
            el.__i18nWatcher();
            el.__i18nWatcher = void 0;
            delete el.__i18nWatcher;
          }
          if (el.__composer) {
            el.__composer = void 0;
            delete el.__composer;
          }
        };
        const update = (el, { value }) => {
          if (el.__composer) {
            const composer = el.__composer;
            const parsedValue = parseValue(value);
            el.textContent = Reflect.apply(composer.t, composer, [
              ...makeParams(parsedValue)
            ]);
          }
        };
        const getSSRProps = (binding) => {
          const [textContent] = _process(binding);
          return { textContent };
        };
        return {
          created: register,
          unmounted: unregister,
          beforeUpdate: update,
          getSSRProps
        };
      }
      function parseValue(value) {
        if (isString$1(value)) {
          return { path: value };
        } else if (isPlainObject(value)) {
          if (!("path" in value)) {
            throw createI18nError(I18nErrorCodes.REQUIRED_VALUE, "path");
          }
          return value;
        } else {
          throw createI18nError(I18nErrorCodes.INVALID_VALUE);
        }
      }
      function makeParams(value) {
        const { path, locale, args, choice, plural } = value;
        const options = {};
        const named = args || {};
        if (isString$1(locale)) {
          options.locale = locale;
        }
        if (isNumber(choice)) {
          options.plural = choice;
        }
        if (isNumber(plural)) {
          options.plural = plural;
        }
        return [path, named, options];
      }
      function apply(app, i18n2, ...options) {
        const pluginOptions = isPlainObject(options[0]) ? options[0] : {};
        const useI18nComponentName = !!pluginOptions.useI18nComponentName;
        const globalInstall = isBoolean(pluginOptions.globalInstall) ? pluginOptions.globalInstall : true;
        if (globalInstall) {
          [!useI18nComponentName ? Translation.name : "i18n", "I18nT"].forEach((name) => app.component(name, Translation));
          [NumberFormat.name, "I18nN"].forEach((name) => app.component(name, NumberFormat));
          [DatetimeFormat.name, "I18nD"].forEach((name) => app.component(name, DatetimeFormat));
        }
        {
          app.directive("t", vTDirective(i18n2));
        }
      }
      const I18nInjectionKey = /* @__PURE__ */ makeSymbol("global-vue-i18n");
      function createI18n(options = {}, VueI18nLegacy) {
        const __globalInjection = isBoolean(options.globalInjection) ? options.globalInjection : true;
        const __allowComposition = true;
        const __instances = /* @__PURE__ */ new Map();
        const [globalScope, __global] = createGlobal(options);
        const symbol = /* @__PURE__ */ makeSymbol("");
        function __getInstance(component) {
          return __instances.get(component) || null;
        }
        function __setInstance(component, instance) {
          __instances.set(component, instance);
        }
        function __deleteInstance(component) {
          __instances.delete(component);
        }
        {
          const i18n2 = {
            // mode
            get mode() {
              return "composition";
            },
            // allowComposition
            get allowComposition() {
              return __allowComposition;
            },
            // install plugin
            async install(app, ...options2) {
              app.__VUE_I18N_SYMBOL__ = symbol;
              app.provide(app.__VUE_I18N_SYMBOL__, i18n2);
              if (isPlainObject(options2[0])) {
                const opts = options2[0];
                i18n2.__composerExtend = opts.__composerExtend;
                i18n2.__vueI18nExtend = opts.__vueI18nExtend;
              }
              let globalReleaseHandler = null;
              if (__globalInjection) {
                globalReleaseHandler = injectGlobalFields(app, i18n2.global);
              }
              {
                apply(app, i18n2, ...options2);
              }
              const unmountApp = app.unmount;
              app.unmount = () => {
                globalReleaseHandler && globalReleaseHandler();
                i18n2.dispose();
                unmountApp();
              };
            },
            // global accessor
            get global() {
              return __global;
            },
            dispose() {
              globalScope.stop();
            },
            // @internal
            __instances,
            // @internal
            __getInstance,
            // @internal
            __setInstance,
            // @internal
            __deleteInstance
          };
          return i18n2;
        }
      }
      function useI18n(options = {}) {
        const instance = vue.getCurrentInstance();
        if (instance == null) {
          throw createI18nError(I18nErrorCodes.MUST_BE_CALL_SETUP_TOP);
        }
        if (!instance.isCE && instance.appContext.app != null && !instance.appContext.app.__VUE_I18N_SYMBOL__) {
          throw createI18nError(I18nErrorCodes.NOT_INSTALLED);
        }
        const i18n2 = getI18nInstance(instance);
        const gl = getGlobalComposer(i18n2);
        const componentOptions = getComponentOptions(instance);
        const scope = getScope(options, componentOptions);
        if (scope === "global") {
          adjustI18nResources(gl, options, componentOptions);
          return gl;
        }
        if (scope === "parent") {
          let composer2 = getComposer(i18n2, instance, options.__useComponent);
          if (composer2 == null) {
            composer2 = gl;
          }
          return composer2;
        }
        const i18nInternal = i18n2;
        let composer = i18nInternal.__getInstance(instance);
        if (composer == null) {
          const composerOptions = assign$1({}, options);
          if ("__i18n" in componentOptions) {
            composerOptions.__i18n = componentOptions.__i18n;
          }
          if (gl) {
            composerOptions.__root = gl;
          }
          composer = createComposer(composerOptions);
          if (i18nInternal.__composerExtend) {
            composer[DisposeSymbol] = i18nInternal.__composerExtend(composer);
          }
          setupLifeCycle(i18nInternal, instance, composer);
          i18nInternal.__setInstance(instance, composer);
        }
        return composer;
      }
      function createGlobal(options, legacyMode, VueI18nLegacy) {
        const scope = vue.effectScope();
        {
          const obj = scope.run(() => createComposer(options));
          if (obj == null) {
            throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR);
          }
          return [scope, obj];
        }
      }
      function getI18nInstance(instance) {
        {
          const i18n2 = vue.inject(!instance.isCE ? instance.appContext.app.__VUE_I18N_SYMBOL__ : I18nInjectionKey);
          if (!i18n2) {
            throw createI18nError(!instance.isCE ? I18nErrorCodes.UNEXPECTED_ERROR : I18nErrorCodes.NOT_INSTALLED_WITH_PROVIDE);
          }
          return i18n2;
        }
      }
      function getScope(options, componentOptions) {
        return isEmptyObject(options) ? "__i18n" in componentOptions ? "local" : "global" : !options.useScope ? "local" : options.useScope;
      }
      function getGlobalComposer(i18n2) {
        return i18n2.mode === "composition" ? i18n2.global : i18n2.global.__composer;
      }
      function getComposer(i18n2, target, useComponent = false) {
        let composer = null;
        const root2 = target.root;
        let current = getParentComponentInstance(target, useComponent);
        while (current != null) {
          const i18nInternal = i18n2;
          if (i18n2.mode === "composition") {
            composer = i18nInternal.__getInstance(current);
          }
          if (composer != null) {
            break;
          }
          if (root2 === current) {
            break;
          }
          current = current.parent;
        }
        return composer;
      }
      function getParentComponentInstance(target, useComponent = false) {
        if (target == null) {
          return null;
        }
        {
          return !useComponent ? target.parent : target.vnode.ctx || target.parent;
        }
      }
      function setupLifeCycle(i18n2, target, composer) {
        {
          vue.onMounted(() => {
          }, target);
          vue.onUnmounted(() => {
            const _composer = composer;
            i18n2.__deleteInstance(target);
            const dispose = _composer[DisposeSymbol];
            if (dispose) {
              dispose();
              delete _composer[DisposeSymbol];
            }
          }, target);
        }
      }
      const globalExportProps = [
        "locale",
        "fallbackLocale",
        "availableLocales"
      ];
      const globalExportMethods = ["t", "rt", "d", "n", "tm", "te"];
      function injectGlobalFields(app, composer) {
        const i18n2 = /* @__PURE__ */ Object.create(null);
        globalExportProps.forEach((prop) => {
          const desc = Object.getOwnPropertyDescriptor(composer, prop);
          if (!desc) {
            throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR);
          }
          const wrap2 = vue.isRef(desc.value) ? {
            get() {
              return desc.value.value;
            },
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            set(val) {
              desc.value.value = val;
            }
          } : {
            get() {
              return desc.get && desc.get();
            }
          };
          Object.defineProperty(i18n2, prop, wrap2);
        });
        app.config.globalProperties.$i18n = i18n2;
        globalExportMethods.forEach((method) => {
          const desc = Object.getOwnPropertyDescriptor(composer, method);
          if (!desc || !desc.value) {
            throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR);
          }
          Object.defineProperty(app.config.globalProperties, `$${method}`, desc);
        });
        const dispose = () => {
          delete app.config.globalProperties.$i18n;
          globalExportMethods.forEach((method) => {
            delete app.config.globalProperties[`$${method}`];
          });
        };
        return dispose;
      }
      {
        initFeatureFlags();
      }
      {
        registerMessageCompiler(compile);
      }
      registerMessageResolver(resolveValue);
      registerLocaleFallbacker(fallbackWithLocaleChain);
      if (__INTLIFY_PROD_DEVTOOLS__) {
        const target = getGlobalThis();
        target.__INTLIFY__ = true;
        setDevToolsHook(target.__INTLIFY_DEVTOOLS_GLOBAL_HOOK__);
      }
      const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
        __name: "ConfirmPopup",
        emits: ["confirm"],
        setup(__props, { emit: __emit }) {
          const emit = __emit;
          const { t: t2 } = useI18n();
          return (_ctx, _cache) => {
            return vue.openBlock(), vue.createBlock(vue.unref(elementPlus.ElPopconfirm), {
              title: vue.unref(t2)("confirmPopup.title"),
              "confirm-button-text": vue.unref(t2)("confirmPopup.yes"),
              "cancel-button-text": vue.unref(t2)("confirmPopup.no"),
              placement: "top",
              onConfirm: _cache[0] || (_cache[0] = (...args) => emit("confirm", ...args))
            }, {
              reference: vue.withCtx(() => [
                vue.renderSlot(_ctx.$slots, "default")
              ]),
              _: 3
            }, 8, ["title", "confirm-button-text", "cancel-button-text"]);
          };
        }
      });
      var FileSaver_min = { exports: {} };
      (function(module2, exports2) {
        (function(a, b) {
          b();
        })(commonjsGlobal, function() {
          function b(a2, b2) {
            return "undefined" == typeof b2 ? b2 = { autoBom: false } : "object" != typeof b2 && (console.warn("Deprecated: Expected third argument to be a object"), b2 = { autoBom: !b2 }), b2.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a2.type) ? new Blob(["\uFEFF", a2], { type: a2.type }) : a2;
          }
          function c(a2, b2, c2) {
            var d2 = new XMLHttpRequest();
            d2.open("GET", a2), d2.responseType = "blob", d2.onload = function() {
              g(d2.response, b2, c2);
            }, d2.onerror = function() {
              console.error("could not download file");
            }, d2.send();
          }
          function d(a2) {
            var b2 = new XMLHttpRequest();
            b2.open("HEAD", a2, false);
            try {
              b2.send();
            } catch (a3) {
            }
            return 200 <= b2.status && 299 >= b2.status;
          }
          function e(a2) {
            try {
              a2.dispatchEvent(new MouseEvent("click"));
            } catch (c2) {
              var b2 = document.createEvent("MouseEvents");
              b2.initMouseEvent("click", true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null), a2.dispatchEvent(b2);
            }
          }
          var f = "object" == typeof window && window.window === window ? window : "object" == typeof self && self.self === self ? self : "object" == typeof commonjsGlobal && commonjsGlobal.global === commonjsGlobal ? commonjsGlobal : void 0, a = f.navigator && /Macintosh/.test(navigator.userAgent) && /AppleWebKit/.test(navigator.userAgent) && !/Safari/.test(navigator.userAgent), g = f.saveAs || ("object" != typeof window || window !== f ? function() {
          } : "download" in HTMLAnchorElement.prototype && !a ? function(b2, g2, h2) {
            var i = f.URL || f.webkitURL, j = document.createElement("a");
            g2 = g2 || b2.name || "download", j.download = g2, j.rel = "noopener", "string" == typeof b2 ? (j.href = b2, j.origin === location.origin ? e(j) : d(j.href) ? c(b2, g2, h2) : e(j, j.target = "_blank")) : (j.href = i.createObjectURL(b2), setTimeout(function() {
              i.revokeObjectURL(j.href);
            }, 4e4), setTimeout(function() {
              e(j);
            }, 0));
          } : "msSaveOrOpenBlob" in navigator ? function(f2, g2, h2) {
            if (g2 = g2 || f2.name || "download", "string" != typeof f2)
              navigator.msSaveOrOpenBlob(b(f2, h2), g2);
            else if (d(f2))
              c(f2, g2, h2);
            else {
              var i = document.createElement("a");
              i.href = f2, i.target = "_blank", setTimeout(function() {
                e(i);
              });
            }
          } : function(b2, d2, e2, g2) {
            if (g2 = g2 || open("", "_blank"), g2 && (g2.document.title = g2.document.body.innerText = "downloading..."), "string" == typeof b2)
              return c(b2, d2, e2);
            var h2 = "application/octet-stream" === b2.type, i = /constructor/i.test(f.HTMLElement) || f.safari, j = /CriOS\/[\d]+/.test(navigator.userAgent);
            if ((j || h2 && i || a) && "undefined" != typeof FileReader) {
              var k = new FileReader();
              k.onloadend = function() {
                var a2 = k.result;
                a2 = j ? a2 : a2.replace(/^data:[^;]*;/, "data:attachment/file;"), g2 ? g2.location.href = a2 : location = a2, g2 = null;
              }, k.readAsDataURL(b2);
            } else {
              var l = f.URL || f.webkitURL, m = l.createObjectURL(b2);
              g2 ? g2.location = m : location.href = m, g2 = null, setTimeout(function() {
                l.revokeObjectURL(m);
              }, 4e4);
            }
          });
          f.saveAs = g.saveAs = g, module2.exports = g;
        });
      })(FileSaver_min);
      var FileSaver_minExports = FileSaver_min.exports;
      function commonjsRequire(path) {
        throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
      }
      var localforage$1 = { exports: {} };
      /*!
          localForage -- Offline Storage, Improved
          Version 1.10.0
          https://localforage.github.io/localForage
          (c) 2013-2017 Mozilla, Apache License 2.0
      */
      (function(module2, exports2) {
        (function(f) {
          {
            module2.exports = f();
          }
        })(function() {
          return function e(t2, n, r) {
            function s(o2, u) {
              if (!n[o2]) {
                if (!t2[o2]) {
                  var a = typeof commonjsRequire == "function" && commonjsRequire;
                  if (!u && a)
                    return a(o2, true);
                  if (i)
                    return i(o2, true);
                  var f = new Error("Cannot find module '" + o2 + "'");
                  throw f.code = "MODULE_NOT_FOUND", f;
                }
                var l = n[o2] = { exports: {} };
                t2[o2][0].call(l.exports, function(e2) {
                  var n2 = t2[o2][1][e2];
                  return s(n2 ? n2 : e2);
                }, l, l.exports, e, t2, n, r);
              }
              return n[o2].exports;
            }
            var i = typeof commonjsRequire == "function" && commonjsRequire;
            for (var o = 0; o < r.length; o++)
              s(r[o]);
            return s;
          }({ 1: [function(_dereq_, module3, exports3) {
            (function(global2) {
              var Mutation = global2.MutationObserver || global2.WebKitMutationObserver;
              var scheduleDrain;
              {
                if (Mutation) {
                  var called = 0;
                  var observer = new Mutation(nextTick2);
                  var element = global2.document.createTextNode("");
                  observer.observe(element, {
                    characterData: true
                  });
                  scheduleDrain = function() {
                    element.data = called = ++called % 2;
                  };
                } else if (!global2.setImmediate && typeof global2.MessageChannel !== "undefined") {
                  var channel = new global2.MessageChannel();
                  channel.port1.onmessage = nextTick2;
                  scheduleDrain = function() {
                    channel.port2.postMessage(0);
                  };
                } else if ("document" in global2 && "onreadystatechange" in global2.document.createElement("script")) {
                  scheduleDrain = function() {
                    var scriptEl = global2.document.createElement("script");
                    scriptEl.onreadystatechange = function() {
                      nextTick2();
                      scriptEl.onreadystatechange = null;
                      scriptEl.parentNode.removeChild(scriptEl);
                      scriptEl = null;
                    };
                    global2.document.documentElement.appendChild(scriptEl);
                  };
                } else {
                  scheduleDrain = function() {
                    setTimeout(nextTick2, 0);
                  };
                }
              }
              var draining;
              var queue = [];
              function nextTick2() {
                draining = true;
                var i, oldQueue;
                var len = queue.length;
                while (len) {
                  oldQueue = queue;
                  queue = [];
                  i = -1;
                  while (++i < len) {
                    oldQueue[i]();
                  }
                  len = queue.length;
                }
                draining = false;
              }
              module3.exports = immediate;
              function immediate(task) {
                if (queue.push(task) === 1 && !draining) {
                  scheduleDrain();
                }
              }
            }).call(this, typeof commonjsGlobal !== "undefined" ? commonjsGlobal : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {});
          }, {}], 2: [function(_dereq_, module3, exports3) {
            var immediate = _dereq_(1);
            function INTERNAL() {
            }
            var handlers2 = {};
            var REJECTED = ["REJECTED"];
            var FULFILLED = ["FULFILLED"];
            var PENDING = ["PENDING"];
            module3.exports = Promise2;
            function Promise2(resolver) {
              if (typeof resolver !== "function") {
                throw new TypeError("resolver must be a function");
              }
              this.state = PENDING;
              this.queue = [];
              this.outcome = void 0;
              if (resolver !== INTERNAL) {
                safelyResolveThenable(this, resolver);
              }
            }
            Promise2.prototype["catch"] = function(onRejected) {
              return this.then(null, onRejected);
            };
            Promise2.prototype.then = function(onFulfilled, onRejected) {
              if (typeof onFulfilled !== "function" && this.state === FULFILLED || typeof onRejected !== "function" && this.state === REJECTED) {
                return this;
              }
              var promise = new this.constructor(INTERNAL);
              if (this.state !== PENDING) {
                var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
                unwrap(promise, resolver, this.outcome);
              } else {
                this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
              }
              return promise;
            };
            function QueueItem(promise, onFulfilled, onRejected) {
              this.promise = promise;
              if (typeof onFulfilled === "function") {
                this.onFulfilled = onFulfilled;
                this.callFulfilled = this.otherCallFulfilled;
              }
              if (typeof onRejected === "function") {
                this.onRejected = onRejected;
                this.callRejected = this.otherCallRejected;
              }
            }
            QueueItem.prototype.callFulfilled = function(value) {
              handlers2.resolve(this.promise, value);
            };
            QueueItem.prototype.otherCallFulfilled = function(value) {
              unwrap(this.promise, this.onFulfilled, value);
            };
            QueueItem.prototype.callRejected = function(value) {
              handlers2.reject(this.promise, value);
            };
            QueueItem.prototype.otherCallRejected = function(value) {
              unwrap(this.promise, this.onRejected, value);
            };
            function unwrap(promise, func, value) {
              immediate(function() {
                var returnValue;
                try {
                  returnValue = func(value);
                } catch (e) {
                  return handlers2.reject(promise, e);
                }
                if (returnValue === promise) {
                  handlers2.reject(promise, new TypeError("Cannot resolve promise with itself"));
                } else {
                  handlers2.resolve(promise, returnValue);
                }
              });
            }
            handlers2.resolve = function(self2, value) {
              var result = tryCatch(getThen, value);
              if (result.status === "error") {
                return handlers2.reject(self2, result.value);
              }
              var thenable = result.value;
              if (thenable) {
                safelyResolveThenable(self2, thenable);
              } else {
                self2.state = FULFILLED;
                self2.outcome = value;
                var i = -1;
                var len = self2.queue.length;
                while (++i < len) {
                  self2.queue[i].callFulfilled(value);
                }
              }
              return self2;
            };
            handlers2.reject = function(self2, error) {
              self2.state = REJECTED;
              self2.outcome = error;
              var i = -1;
              var len = self2.queue.length;
              while (++i < len) {
                self2.queue[i].callRejected(error);
              }
              return self2;
            };
            function getThen(obj) {
              var then = obj && obj.then;
              if (obj && (typeof obj === "object" || typeof obj === "function") && typeof then === "function") {
                return function appyThen() {
                  then.apply(obj, arguments);
                };
              }
            }
            function safelyResolveThenable(self2, thenable) {
              var called = false;
              function onError(value) {
                if (called) {
                  return;
                }
                called = true;
                handlers2.reject(self2, value);
              }
              function onSuccess(value) {
                if (called) {
                  return;
                }
                called = true;
                handlers2.resolve(self2, value);
              }
              function tryToUnwrap() {
                thenable(onSuccess, onError);
              }
              var result = tryCatch(tryToUnwrap);
              if (result.status === "error") {
                onError(result.value);
              }
            }
            function tryCatch(func, value) {
              var out = {};
              try {
                out.value = func(value);
                out.status = "success";
              } catch (e) {
                out.status = "error";
                out.value = e;
              }
              return out;
            }
            Promise2.resolve = resolve;
            function resolve(value) {
              if (value instanceof this) {
                return value;
              }
              return handlers2.resolve(new this(INTERNAL), value);
            }
            Promise2.reject = reject;
            function reject(reason) {
              var promise = new this(INTERNAL);
              return handlers2.reject(promise, reason);
            }
            Promise2.all = all;
            function all(iterable) {
              var self2 = this;
              if (Object.prototype.toString.call(iterable) !== "[object Array]") {
                return this.reject(new TypeError("must be an array"));
              }
              var len = iterable.length;
              var called = false;
              if (!len) {
                return this.resolve([]);
              }
              var values2 = new Array(len);
              var resolved = 0;
              var i = -1;
              var promise = new this(INTERNAL);
              while (++i < len) {
                allResolver(iterable[i], i);
              }
              return promise;
              function allResolver(value, i2) {
                self2.resolve(value).then(resolveFromAll, function(error) {
                  if (!called) {
                    called = true;
                    handlers2.reject(promise, error);
                  }
                });
                function resolveFromAll(outValue) {
                  values2[i2] = outValue;
                  if (++resolved === len && !called) {
                    called = true;
                    handlers2.resolve(promise, values2);
                  }
                }
              }
            }
            Promise2.race = race;
            function race(iterable) {
              var self2 = this;
              if (Object.prototype.toString.call(iterable) !== "[object Array]") {
                return this.reject(new TypeError("must be an array"));
              }
              var len = iterable.length;
              var called = false;
              if (!len) {
                return this.resolve([]);
              }
              var i = -1;
              var promise = new this(INTERNAL);
              while (++i < len) {
                resolver(iterable[i]);
              }
              return promise;
              function resolver(value) {
                self2.resolve(value).then(function(response) {
                  if (!called) {
                    called = true;
                    handlers2.resolve(promise, response);
                  }
                }, function(error) {
                  if (!called) {
                    called = true;
                    handlers2.reject(promise, error);
                  }
                });
              }
            }
          }, { "1": 1 }], 3: [function(_dereq_, module3, exports3) {
            (function(global2) {
              if (typeof global2.Promise !== "function") {
                global2.Promise = _dereq_(2);
              }
            }).call(this, typeof commonjsGlobal !== "undefined" ? commonjsGlobal : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {});
          }, { "2": 2 }], 4: [function(_dereq_, module3, exports3) {
            var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
              return typeof obj;
            } : function(obj) {
              return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
            };
            function _classCallCheck(instance, Constructor) {
              if (!(instance instanceof Constructor)) {
                throw new TypeError("Cannot call a class as a function");
              }
            }
            function getIDB() {
              try {
                if (typeof indexedDB !== "undefined") {
                  return indexedDB;
                }
                if (typeof webkitIndexedDB !== "undefined") {
                  return webkitIndexedDB;
                }
                if (typeof mozIndexedDB !== "undefined") {
                  return mozIndexedDB;
                }
                if (typeof OIndexedDB !== "undefined") {
                  return OIndexedDB;
                }
                if (typeof msIndexedDB !== "undefined") {
                  return msIndexedDB;
                }
              } catch (e) {
                return;
              }
            }
            var idb = getIDB();
            function isIndexedDBValid() {
              try {
                if (!idb || !idb.open) {
                  return false;
                }
                var isSafari = typeof openDatabase !== "undefined" && /(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent) && !/BlackBerry/.test(navigator.platform);
                var hasFetch = typeof fetch === "function" && fetch.toString().indexOf("[native code") !== -1;
                return (!isSafari || hasFetch) && typeof indexedDB !== "undefined" && // some outdated implementations of IDB that appear on Samsung
                // and HTC Android devices <4.4 are missing IDBKeyRange
                // See: https://github.com/mozilla/localForage/issues/128
                // See: https://github.com/mozilla/localForage/issues/272
                typeof IDBKeyRange !== "undefined";
              } catch (e) {
                return false;
              }
            }
            function createBlob(parts, properties) {
              parts = parts || [];
              properties = properties || {};
              try {
                return new Blob(parts, properties);
              } catch (e) {
                if (e.name !== "TypeError") {
                  throw e;
                }
                var Builder = typeof BlobBuilder !== "undefined" ? BlobBuilder : typeof MSBlobBuilder !== "undefined" ? MSBlobBuilder : typeof MozBlobBuilder !== "undefined" ? MozBlobBuilder : WebKitBlobBuilder;
                var builder = new Builder();
                for (var i = 0; i < parts.length; i += 1) {
                  builder.append(parts[i]);
                }
                return builder.getBlob(properties.type);
              }
            }
            if (typeof Promise === "undefined") {
              _dereq_(3);
            }
            var Promise$12 = Promise;
            function executeCallback2(promise, callback) {
              if (callback) {
                promise.then(function(result) {
                  callback(null, result);
                }, function(error) {
                  callback(error);
                });
              }
            }
            function executeTwoCallbacks(promise, callback, errorCallback) {
              if (typeof callback === "function") {
                promise.then(callback);
              }
              if (typeof errorCallback === "function") {
                promise["catch"](errorCallback);
              }
            }
            function normalizeKey(key2) {
              if (typeof key2 !== "string") {
                console.warn(key2 + " used as a key, but it is not a string.");
                key2 = String(key2);
              }
              return key2;
            }
            function getCallback() {
              if (arguments.length && typeof arguments[arguments.length - 1] === "function") {
                return arguments[arguments.length - 1];
              }
            }
            var DETECT_BLOB_SUPPORT_STORE = "local-forage-detect-blob-support";
            var supportsBlobs = void 0;
            var dbContexts = {};
            var toString2 = Object.prototype.toString;
            var READ_ONLY = "readonly";
            var READ_WRITE = "readwrite";
            function _binStringToArrayBuffer(bin) {
              var length2 = bin.length;
              var buf = new ArrayBuffer(length2);
              var arr = new Uint8Array(buf);
              for (var i = 0; i < length2; i++) {
                arr[i] = bin.charCodeAt(i);
              }
              return buf;
            }
            function _checkBlobSupportWithoutCaching(idb2) {
              return new Promise$12(function(resolve) {
                var txn = idb2.transaction(DETECT_BLOB_SUPPORT_STORE, READ_WRITE);
                var blob2 = createBlob([""]);
                txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob2, "key");
                txn.onabort = function(e) {
                  e.preventDefault();
                  e.stopPropagation();
                  resolve(false);
                };
                txn.oncomplete = function() {
                  var matchedChrome = navigator.userAgent.match(/Chrome\/(\d+)/);
                  var matchedEdge = navigator.userAgent.match(/Edge\//);
                  resolve(matchedEdge || !matchedChrome || parseInt(matchedChrome[1], 10) >= 43);
                };
              })["catch"](function() {
                return false;
              });
            }
            function _checkBlobSupport(idb2) {
              if (typeof supportsBlobs === "boolean") {
                return Promise$12.resolve(supportsBlobs);
              }
              return _checkBlobSupportWithoutCaching(idb2).then(function(value) {
                supportsBlobs = value;
                return supportsBlobs;
              });
            }
            function _deferReadiness(dbInfo) {
              var dbContext = dbContexts[dbInfo.name];
              var deferredOperation = {};
              deferredOperation.promise = new Promise$12(function(resolve, reject) {
                deferredOperation.resolve = resolve;
                deferredOperation.reject = reject;
              });
              dbContext.deferredOperations.push(deferredOperation);
              if (!dbContext.dbReady) {
                dbContext.dbReady = deferredOperation.promise;
              } else {
                dbContext.dbReady = dbContext.dbReady.then(function() {
                  return deferredOperation.promise;
                });
              }
            }
            function _advanceReadiness(dbInfo) {
              var dbContext = dbContexts[dbInfo.name];
              var deferredOperation = dbContext.deferredOperations.pop();
              if (deferredOperation) {
                deferredOperation.resolve();
                return deferredOperation.promise;
              }
            }
            function _rejectReadiness(dbInfo, err) {
              var dbContext = dbContexts[dbInfo.name];
              var deferredOperation = dbContext.deferredOperations.pop();
              if (deferredOperation) {
                deferredOperation.reject(err);
                return deferredOperation.promise;
              }
            }
            function _getConnection(dbInfo, upgradeNeeded) {
              return new Promise$12(function(resolve, reject) {
                dbContexts[dbInfo.name] = dbContexts[dbInfo.name] || createDbContext();
                if (dbInfo.db) {
                  if (upgradeNeeded) {
                    _deferReadiness(dbInfo);
                    dbInfo.db.close();
                  } else {
                    return resolve(dbInfo.db);
                  }
                }
                var dbArgs = [dbInfo.name];
                if (upgradeNeeded) {
                  dbArgs.push(dbInfo.version);
                }
                var openreq = idb.open.apply(idb, dbArgs);
                if (upgradeNeeded) {
                  openreq.onupgradeneeded = function(e) {
                    var db = openreq.result;
                    try {
                      db.createObjectStore(dbInfo.storeName);
                      if (e.oldVersion <= 1) {
                        db.createObjectStore(DETECT_BLOB_SUPPORT_STORE);
                      }
                    } catch (ex) {
                      if (ex.name === "ConstraintError") {
                        console.warn('The database "' + dbInfo.name + '" has been upgraded from version ' + e.oldVersion + " to version " + e.newVersion + ', but the storage "' + dbInfo.storeName + '" already exists.');
                      } else {
                        throw ex;
                      }
                    }
                  };
                }
                openreq.onerror = function(e) {
                  e.preventDefault();
                  reject(openreq.error);
                };
                openreq.onsuccess = function() {
                  var db = openreq.result;
                  db.onversionchange = function(e) {
                    e.target.close();
                  };
                  resolve(db);
                  _advanceReadiness(dbInfo);
                };
              });
            }
            function _getOriginalConnection(dbInfo) {
              return _getConnection(dbInfo, false);
            }
            function _getUpgradedConnection(dbInfo) {
              return _getConnection(dbInfo, true);
            }
            function _isUpgradeNeeded(dbInfo, defaultVersion) {
              if (!dbInfo.db) {
                return true;
              }
              var isNewStore = !dbInfo.db.objectStoreNames.contains(dbInfo.storeName);
              var isDowngrade = dbInfo.version < dbInfo.db.version;
              var isUpgrade = dbInfo.version > dbInfo.db.version;
              if (isDowngrade) {
                if (dbInfo.version !== defaultVersion) {
                  console.warn('The database "' + dbInfo.name + `" can't be downgraded from version ` + dbInfo.db.version + " to version " + dbInfo.version + ".");
                }
                dbInfo.version = dbInfo.db.version;
              }
              if (isUpgrade || isNewStore) {
                if (isNewStore) {
                  var incVersion = dbInfo.db.version + 1;
                  if (incVersion > dbInfo.version) {
                    dbInfo.version = incVersion;
                  }
                }
                return true;
              }
              return false;
            }
            function _encodeBlob(blob2) {
              return new Promise$12(function(resolve, reject) {
                var reader = new FileReader();
                reader.onerror = reject;
                reader.onloadend = function(e) {
                  var base64 = btoa(e.target.result || "");
                  resolve({
                    __local_forage_encoded_blob: true,
                    data: base64,
                    type: blob2.type
                  });
                };
                reader.readAsBinaryString(blob2);
              });
            }
            function _decodeBlob(encodedBlob) {
              var arrayBuff = _binStringToArrayBuffer(atob(encodedBlob.data));
              return createBlob([arrayBuff], { type: encodedBlob.type });
            }
            function _isEncodedBlob(value) {
              return value && value.__local_forage_encoded_blob;
            }
            function _fullyReady(callback) {
              var self2 = this;
              var promise = self2._initReady().then(function() {
                var dbContext = dbContexts[self2._dbInfo.name];
                if (dbContext && dbContext.dbReady) {
                  return dbContext.dbReady;
                }
              });
              executeTwoCallbacks(promise, callback, callback);
              return promise;
            }
            function _tryReconnect(dbInfo) {
              _deferReadiness(dbInfo);
              var dbContext = dbContexts[dbInfo.name];
              var forages = dbContext.forages;
              for (var i = 0; i < forages.length; i++) {
                var forage = forages[i];
                if (forage._dbInfo.db) {
                  forage._dbInfo.db.close();
                  forage._dbInfo.db = null;
                }
              }
              dbInfo.db = null;
              return _getOriginalConnection(dbInfo).then(function(db) {
                dbInfo.db = db;
                if (_isUpgradeNeeded(dbInfo)) {
                  return _getUpgradedConnection(dbInfo);
                }
                return db;
              }).then(function(db) {
                dbInfo.db = dbContext.db = db;
                for (var i2 = 0; i2 < forages.length; i2++) {
                  forages[i2]._dbInfo.db = db;
                }
              })["catch"](function(err) {
                _rejectReadiness(dbInfo, err);
                throw err;
              });
            }
            function createTransaction(dbInfo, mode, callback, retries) {
              if (retries === void 0) {
                retries = 1;
              }
              try {
                var tx = dbInfo.db.transaction(dbInfo.storeName, mode);
                callback(null, tx);
              } catch (err) {
                if (retries > 0 && (!dbInfo.db || err.name === "InvalidStateError" || err.name === "NotFoundError")) {
                  return Promise$12.resolve().then(function() {
                    if (!dbInfo.db || err.name === "NotFoundError" && !dbInfo.db.objectStoreNames.contains(dbInfo.storeName) && dbInfo.version <= dbInfo.db.version) {
                      if (dbInfo.db) {
                        dbInfo.version = dbInfo.db.version + 1;
                      }
                      return _getUpgradedConnection(dbInfo);
                    }
                  }).then(function() {
                    return _tryReconnect(dbInfo).then(function() {
                      createTransaction(dbInfo, mode, callback, retries - 1);
                    });
                  })["catch"](callback);
                }
                callback(err);
              }
            }
            function createDbContext() {
              return {
                // Running localForages sharing a database.
                forages: [],
                // Shared database.
                db: null,
                // Database readiness (promise).
                dbReady: null,
                // Deferred operations on the database.
                deferredOperations: []
              };
            }
            function _initStorage(options) {
              var self2 = this;
              var dbInfo = {
                db: null
              };
              if (options) {
                for (var i in options) {
                  dbInfo[i] = options[i];
                }
              }
              var dbContext = dbContexts[dbInfo.name];
              if (!dbContext) {
                dbContext = createDbContext();
                dbContexts[dbInfo.name] = dbContext;
              }
              dbContext.forages.push(self2);
              if (!self2._initReady) {
                self2._initReady = self2.ready;
                self2.ready = _fullyReady;
              }
              var initPromises = [];
              function ignoreErrors() {
                return Promise$12.resolve();
              }
              for (var j = 0; j < dbContext.forages.length; j++) {
                var forage = dbContext.forages[j];
                if (forage !== self2) {
                  initPromises.push(forage._initReady()["catch"](ignoreErrors));
                }
              }
              var forages = dbContext.forages.slice(0);
              return Promise$12.all(initPromises).then(function() {
                dbInfo.db = dbContext.db;
                return _getOriginalConnection(dbInfo);
              }).then(function(db) {
                dbInfo.db = db;
                if (_isUpgradeNeeded(dbInfo, self2._defaultConfig.version)) {
                  return _getUpgradedConnection(dbInfo);
                }
                return db;
              }).then(function(db) {
                dbInfo.db = dbContext.db = db;
                self2._dbInfo = dbInfo;
                for (var k = 0; k < forages.length; k++) {
                  var forage2 = forages[k];
                  if (forage2 !== self2) {
                    forage2._dbInfo.db = dbInfo.db;
                    forage2._dbInfo.version = dbInfo.version;
                  }
                }
              });
            }
            function getItem(key2, callback) {
              var self2 = this;
              key2 = normalizeKey(key2);
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  createTransaction(self2._dbInfo, READ_ONLY, function(err, transaction) {
                    if (err) {
                      return reject(err);
                    }
                    try {
                      var store = transaction.objectStore(self2._dbInfo.storeName);
                      var req = store.get(key2);
                      req.onsuccess = function() {
                        var value = req.result;
                        if (value === void 0) {
                          value = null;
                        }
                        if (_isEncodedBlob(value)) {
                          value = _decodeBlob(value);
                        }
                        resolve(value);
                      };
                      req.onerror = function() {
                        reject(req.error);
                      };
                    } catch (e) {
                      reject(e);
                    }
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function iterate(iterator, callback) {
              var self2 = this;
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  createTransaction(self2._dbInfo, READ_ONLY, function(err, transaction) {
                    if (err) {
                      return reject(err);
                    }
                    try {
                      var store = transaction.objectStore(self2._dbInfo.storeName);
                      var req = store.openCursor();
                      var iterationNumber = 1;
                      req.onsuccess = function() {
                        var cursor = req.result;
                        if (cursor) {
                          var value = cursor.value;
                          if (_isEncodedBlob(value)) {
                            value = _decodeBlob(value);
                          }
                          var result = iterator(value, cursor.key, iterationNumber++);
                          if (result !== void 0) {
                            resolve(result);
                          } else {
                            cursor["continue"]();
                          }
                        } else {
                          resolve();
                        }
                      };
                      req.onerror = function() {
                        reject(req.error);
                      };
                    } catch (e) {
                      reject(e);
                    }
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function setItem(key2, value, callback) {
              var self2 = this;
              key2 = normalizeKey(key2);
              var promise = new Promise$12(function(resolve, reject) {
                var dbInfo;
                self2.ready().then(function() {
                  dbInfo = self2._dbInfo;
                  if (toString2.call(value) === "[object Blob]") {
                    return _checkBlobSupport(dbInfo.db).then(function(blobSupport) {
                      if (blobSupport) {
                        return value;
                      }
                      return _encodeBlob(value);
                    });
                  }
                  return value;
                }).then(function(value2) {
                  createTransaction(self2._dbInfo, READ_WRITE, function(err, transaction) {
                    if (err) {
                      return reject(err);
                    }
                    try {
                      var store = transaction.objectStore(self2._dbInfo.storeName);
                      if (value2 === null) {
                        value2 = void 0;
                      }
                      var req = store.put(value2, key2);
                      transaction.oncomplete = function() {
                        if (value2 === void 0) {
                          value2 = null;
                        }
                        resolve(value2);
                      };
                      transaction.onabort = transaction.onerror = function() {
                        var err2 = req.error ? req.error : req.transaction.error;
                        reject(err2);
                      };
                    } catch (e) {
                      reject(e);
                    }
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function removeItem(key2, callback) {
              var self2 = this;
              key2 = normalizeKey(key2);
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  createTransaction(self2._dbInfo, READ_WRITE, function(err, transaction) {
                    if (err) {
                      return reject(err);
                    }
                    try {
                      var store = transaction.objectStore(self2._dbInfo.storeName);
                      var req = store["delete"](key2);
                      transaction.oncomplete = function() {
                        resolve();
                      };
                      transaction.onerror = function() {
                        reject(req.error);
                      };
                      transaction.onabort = function() {
                        var err2 = req.error ? req.error : req.transaction.error;
                        reject(err2);
                      };
                    } catch (e) {
                      reject(e);
                    }
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function clear(callback) {
              var self2 = this;
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  createTransaction(self2._dbInfo, READ_WRITE, function(err, transaction) {
                    if (err) {
                      return reject(err);
                    }
                    try {
                      var store = transaction.objectStore(self2._dbInfo.storeName);
                      var req = store.clear();
                      transaction.oncomplete = function() {
                        resolve();
                      };
                      transaction.onabort = transaction.onerror = function() {
                        var err2 = req.error ? req.error : req.transaction.error;
                        reject(err2);
                      };
                    } catch (e) {
                      reject(e);
                    }
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function length(callback) {
              var self2 = this;
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  createTransaction(self2._dbInfo, READ_ONLY, function(err, transaction) {
                    if (err) {
                      return reject(err);
                    }
                    try {
                      var store = transaction.objectStore(self2._dbInfo.storeName);
                      var req = store.count();
                      req.onsuccess = function() {
                        resolve(req.result);
                      };
                      req.onerror = function() {
                        reject(req.error);
                      };
                    } catch (e) {
                      reject(e);
                    }
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function key(n, callback) {
              var self2 = this;
              var promise = new Promise$12(function(resolve, reject) {
                if (n < 0) {
                  resolve(null);
                  return;
                }
                self2.ready().then(function() {
                  createTransaction(self2._dbInfo, READ_ONLY, function(err, transaction) {
                    if (err) {
                      return reject(err);
                    }
                    try {
                      var store = transaction.objectStore(self2._dbInfo.storeName);
                      var advanced = false;
                      var req = store.openKeyCursor();
                      req.onsuccess = function() {
                        var cursor = req.result;
                        if (!cursor) {
                          resolve(null);
                          return;
                        }
                        if (n === 0) {
                          resolve(cursor.key);
                        } else {
                          if (!advanced) {
                            advanced = true;
                            cursor.advance(n);
                          } else {
                            resolve(cursor.key);
                          }
                        }
                      };
                      req.onerror = function() {
                        reject(req.error);
                      };
                    } catch (e) {
                      reject(e);
                    }
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function keys2(callback) {
              var self2 = this;
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  createTransaction(self2._dbInfo, READ_ONLY, function(err, transaction) {
                    if (err) {
                      return reject(err);
                    }
                    try {
                      var store = transaction.objectStore(self2._dbInfo.storeName);
                      var req = store.openKeyCursor();
                      var keys3 = [];
                      req.onsuccess = function() {
                        var cursor = req.result;
                        if (!cursor) {
                          resolve(keys3);
                          return;
                        }
                        keys3.push(cursor.key);
                        cursor["continue"]();
                      };
                      req.onerror = function() {
                        reject(req.error);
                      };
                    } catch (e) {
                      reject(e);
                    }
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function dropInstance(options, callback) {
              callback = getCallback.apply(this, arguments);
              var currentConfig = this.config();
              options = typeof options !== "function" && options || {};
              if (!options.name) {
                options.name = options.name || currentConfig.name;
                options.storeName = options.storeName || currentConfig.storeName;
              }
              var self2 = this;
              var promise;
              if (!options.name) {
                promise = Promise$12.reject("Invalid arguments");
              } else {
                var isCurrentDb = options.name === currentConfig.name && self2._dbInfo.db;
                var dbPromise = isCurrentDb ? Promise$12.resolve(self2._dbInfo.db) : _getOriginalConnection(options).then(function(db) {
                  var dbContext = dbContexts[options.name];
                  var forages = dbContext.forages;
                  dbContext.db = db;
                  for (var i = 0; i < forages.length; i++) {
                    forages[i]._dbInfo.db = db;
                  }
                  return db;
                });
                if (!options.storeName) {
                  promise = dbPromise.then(function(db) {
                    _deferReadiness(options);
                    var dbContext = dbContexts[options.name];
                    var forages = dbContext.forages;
                    db.close();
                    for (var i = 0; i < forages.length; i++) {
                      var forage = forages[i];
                      forage._dbInfo.db = null;
                    }
                    var dropDBPromise = new Promise$12(function(resolve, reject) {
                      var req = idb.deleteDatabase(options.name);
                      req.onerror = function() {
                        var db2 = req.result;
                        if (db2) {
                          db2.close();
                        }
                        reject(req.error);
                      };
                      req.onblocked = function() {
                        console.warn('dropInstance blocked for database "' + options.name + '" until all open connections are closed');
                      };
                      req.onsuccess = function() {
                        var db2 = req.result;
                        if (db2) {
                          db2.close();
                        }
                        resolve(db2);
                      };
                    });
                    return dropDBPromise.then(function(db2) {
                      dbContext.db = db2;
                      for (var i2 = 0; i2 < forages.length; i2++) {
                        var _forage = forages[i2];
                        _advanceReadiness(_forage._dbInfo);
                      }
                    })["catch"](function(err) {
                      (_rejectReadiness(options, err) || Promise$12.resolve())["catch"](function() {
                      });
                      throw err;
                    });
                  });
                } else {
                  promise = dbPromise.then(function(db) {
                    if (!db.objectStoreNames.contains(options.storeName)) {
                      return;
                    }
                    var newVersion = db.version + 1;
                    _deferReadiness(options);
                    var dbContext = dbContexts[options.name];
                    var forages = dbContext.forages;
                    db.close();
                    for (var i = 0; i < forages.length; i++) {
                      var forage = forages[i];
                      forage._dbInfo.db = null;
                      forage._dbInfo.version = newVersion;
                    }
                    var dropObjectPromise = new Promise$12(function(resolve, reject) {
                      var req = idb.open(options.name, newVersion);
                      req.onerror = function(err) {
                        var db2 = req.result;
                        db2.close();
                        reject(err);
                      };
                      req.onupgradeneeded = function() {
                        var db2 = req.result;
                        db2.deleteObjectStore(options.storeName);
                      };
                      req.onsuccess = function() {
                        var db2 = req.result;
                        db2.close();
                        resolve(db2);
                      };
                    });
                    return dropObjectPromise.then(function(db2) {
                      dbContext.db = db2;
                      for (var j = 0; j < forages.length; j++) {
                        var _forage2 = forages[j];
                        _forage2._dbInfo.db = db2;
                        _advanceReadiness(_forage2._dbInfo);
                      }
                    })["catch"](function(err) {
                      (_rejectReadiness(options, err) || Promise$12.resolve())["catch"](function() {
                      });
                      throw err;
                    });
                  });
                }
              }
              executeCallback2(promise, callback);
              return promise;
            }
            var asyncStorage = {
              _driver: "asyncStorage",
              _initStorage,
              _support: isIndexedDBValid(),
              iterate,
              getItem,
              setItem,
              removeItem,
              clear,
              length,
              key,
              keys: keys2,
              dropInstance
            };
            function isWebSQLValid() {
              return typeof openDatabase === "function";
            }
            var BASE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
            var BLOB_TYPE_PREFIX = "~~local_forage_type~";
            var BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;
            var SERIALIZED_MARKER = "__lfsc__:";
            var SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;
            var TYPE_ARRAYBUFFER = "arbf";
            var TYPE_BLOB = "blob";
            var TYPE_INT8ARRAY = "si08";
            var TYPE_UINT8ARRAY = "ui08";
            var TYPE_UINT8CLAMPEDARRAY = "uic8";
            var TYPE_INT16ARRAY = "si16";
            var TYPE_INT32ARRAY = "si32";
            var TYPE_UINT16ARRAY = "ur16";
            var TYPE_UINT32ARRAY = "ui32";
            var TYPE_FLOAT32ARRAY = "fl32";
            var TYPE_FLOAT64ARRAY = "fl64";
            var TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH + TYPE_ARRAYBUFFER.length;
            var toString$12 = Object.prototype.toString;
            function stringToBuffer(serializedString) {
              var bufferLength = serializedString.length * 0.75;
              var len = serializedString.length;
              var i;
              var p = 0;
              var encoded1, encoded2, encoded3, encoded4;
              if (serializedString[serializedString.length - 1] === "=") {
                bufferLength--;
                if (serializedString[serializedString.length - 2] === "=") {
                  bufferLength--;
                }
              }
              var buffer = new ArrayBuffer(bufferLength);
              var bytes = new Uint8Array(buffer);
              for (i = 0; i < len; i += 4) {
                encoded1 = BASE_CHARS.indexOf(serializedString[i]);
                encoded2 = BASE_CHARS.indexOf(serializedString[i + 1]);
                encoded3 = BASE_CHARS.indexOf(serializedString[i + 2]);
                encoded4 = BASE_CHARS.indexOf(serializedString[i + 3]);
                bytes[p++] = encoded1 << 2 | encoded2 >> 4;
                bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;
                bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;
              }
              return buffer;
            }
            function bufferToString(buffer) {
              var bytes = new Uint8Array(buffer);
              var base64String = "";
              var i;
              for (i = 0; i < bytes.length; i += 3) {
                base64String += BASE_CHARS[bytes[i] >> 2];
                base64String += BASE_CHARS[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];
                base64String += BASE_CHARS[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];
                base64String += BASE_CHARS[bytes[i + 2] & 63];
              }
              if (bytes.length % 3 === 2) {
                base64String = base64String.substring(0, base64String.length - 1) + "=";
              } else if (bytes.length % 3 === 1) {
                base64String = base64String.substring(0, base64String.length - 2) + "==";
              }
              return base64String;
            }
            function serialize(value, callback) {
              var valueType = "";
              if (value) {
                valueType = toString$12.call(value);
              }
              if (value && (valueType === "[object ArrayBuffer]" || value.buffer && toString$12.call(value.buffer) === "[object ArrayBuffer]")) {
                var buffer;
                var marker = SERIALIZED_MARKER;
                if (value instanceof ArrayBuffer) {
                  buffer = value;
                  marker += TYPE_ARRAYBUFFER;
                } else {
                  buffer = value.buffer;
                  if (valueType === "[object Int8Array]") {
                    marker += TYPE_INT8ARRAY;
                  } else if (valueType === "[object Uint8Array]") {
                    marker += TYPE_UINT8ARRAY;
                  } else if (valueType === "[object Uint8ClampedArray]") {
                    marker += TYPE_UINT8CLAMPEDARRAY;
                  } else if (valueType === "[object Int16Array]") {
                    marker += TYPE_INT16ARRAY;
                  } else if (valueType === "[object Uint16Array]") {
                    marker += TYPE_UINT16ARRAY;
                  } else if (valueType === "[object Int32Array]") {
                    marker += TYPE_INT32ARRAY;
                  } else if (valueType === "[object Uint32Array]") {
                    marker += TYPE_UINT32ARRAY;
                  } else if (valueType === "[object Float32Array]") {
                    marker += TYPE_FLOAT32ARRAY;
                  } else if (valueType === "[object Float64Array]") {
                    marker += TYPE_FLOAT64ARRAY;
                  } else {
                    callback(new Error("Failed to get type for BinaryArray"));
                  }
                }
                callback(marker + bufferToString(buffer));
              } else if (valueType === "[object Blob]") {
                var fileReader = new FileReader();
                fileReader.onload = function() {
                  var str = BLOB_TYPE_PREFIX + value.type + "~" + bufferToString(this.result);
                  callback(SERIALIZED_MARKER + TYPE_BLOB + str);
                };
                fileReader.readAsArrayBuffer(value);
              } else {
                try {
                  callback(JSON.stringify(value));
                } catch (e) {
                  console.error("Couldn't convert value into a JSON string: ", value);
                  callback(null, e);
                }
              }
            }
            function deserialize(value) {
              if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {
                return JSON.parse(value);
              }
              var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);
              var type = value.substring(SERIALIZED_MARKER_LENGTH, TYPE_SERIALIZED_MARKER_LENGTH);
              var blobType;
              if (type === TYPE_BLOB && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {
                var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);
                blobType = matcher[1];
                serializedString = serializedString.substring(matcher[0].length);
              }
              var buffer = stringToBuffer(serializedString);
              switch (type) {
                case TYPE_ARRAYBUFFER:
                  return buffer;
                case TYPE_BLOB:
                  return createBlob([buffer], { type: blobType });
                case TYPE_INT8ARRAY:
                  return new Int8Array(buffer);
                case TYPE_UINT8ARRAY:
                  return new Uint8Array(buffer);
                case TYPE_UINT8CLAMPEDARRAY:
                  return new Uint8ClampedArray(buffer);
                case TYPE_INT16ARRAY:
                  return new Int16Array(buffer);
                case TYPE_UINT16ARRAY:
                  return new Uint16Array(buffer);
                case TYPE_INT32ARRAY:
                  return new Int32Array(buffer);
                case TYPE_UINT32ARRAY:
                  return new Uint32Array(buffer);
                case TYPE_FLOAT32ARRAY:
                  return new Float32Array(buffer);
                case TYPE_FLOAT64ARRAY:
                  return new Float64Array(buffer);
                default:
                  throw new Error("Unkown type: " + type);
              }
            }
            var localforageSerializer = {
              serialize,
              deserialize,
              stringToBuffer,
              bufferToString
            };
            function createDbTable(t2, dbInfo, callback, errorCallback) {
              t2.executeSql("CREATE TABLE IF NOT EXISTS " + dbInfo.storeName + " (id INTEGER PRIMARY KEY, key unique, value)", [], callback, errorCallback);
            }
            function _initStorage$1(options) {
              var self2 = this;
              var dbInfo = {
                db: null
              };
              if (options) {
                for (var i in options) {
                  dbInfo[i] = typeof options[i] !== "string" ? options[i].toString() : options[i];
                }
              }
              var dbInfoPromise = new Promise$12(function(resolve, reject) {
                try {
                  dbInfo.db = openDatabase(dbInfo.name, String(dbInfo.version), dbInfo.description, dbInfo.size);
                } catch (e) {
                  return reject(e);
                }
                dbInfo.db.transaction(function(t2) {
                  createDbTable(t2, dbInfo, function() {
                    self2._dbInfo = dbInfo;
                    resolve();
                  }, function(t3, error) {
                    reject(error);
                  });
                }, reject);
              });
              dbInfo.serializer = localforageSerializer;
              return dbInfoPromise;
            }
            function tryExecuteSql(t2, dbInfo, sqlStatement, args, callback, errorCallback) {
              t2.executeSql(sqlStatement, args, callback, function(t3, error) {
                if (error.code === error.SYNTAX_ERR) {
                  t3.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name = ?", [dbInfo.storeName], function(t4, results) {
                    if (!results.rows.length) {
                      createDbTable(t4, dbInfo, function() {
                        t4.executeSql(sqlStatement, args, callback, errorCallback);
                      }, errorCallback);
                    } else {
                      errorCallback(t4, error);
                    }
                  }, errorCallback);
                } else {
                  errorCallback(t3, error);
                }
              }, errorCallback);
            }
            function getItem$1(key2, callback) {
              var self2 = this;
              key2 = normalizeKey(key2);
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  var dbInfo = self2._dbInfo;
                  dbInfo.db.transaction(function(t2) {
                    tryExecuteSql(t2, dbInfo, "SELECT * FROM " + dbInfo.storeName + " WHERE key = ? LIMIT 1", [key2], function(t3, results) {
                      var result = results.rows.length ? results.rows.item(0).value : null;
                      if (result) {
                        result = dbInfo.serializer.deserialize(result);
                      }
                      resolve(result);
                    }, function(t3, error) {
                      reject(error);
                    });
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function iterate$1(iterator, callback) {
              var self2 = this;
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  var dbInfo = self2._dbInfo;
                  dbInfo.db.transaction(function(t2) {
                    tryExecuteSql(t2, dbInfo, "SELECT * FROM " + dbInfo.storeName, [], function(t3, results) {
                      var rows = results.rows;
                      var length2 = rows.length;
                      for (var i = 0; i < length2; i++) {
                        var item = rows.item(i);
                        var result = item.value;
                        if (result) {
                          result = dbInfo.serializer.deserialize(result);
                        }
                        result = iterator(result, item.key, i + 1);
                        if (result !== void 0) {
                          resolve(result);
                          return;
                        }
                      }
                      resolve();
                    }, function(t3, error) {
                      reject(error);
                    });
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function _setItem(key2, value, callback, retriesLeft) {
              var self2 = this;
              key2 = normalizeKey(key2);
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  if (value === void 0) {
                    value = null;
                  }
                  var originalValue = value;
                  var dbInfo = self2._dbInfo;
                  dbInfo.serializer.serialize(value, function(value2, error) {
                    if (error) {
                      reject(error);
                    } else {
                      dbInfo.db.transaction(function(t2) {
                        tryExecuteSql(t2, dbInfo, "INSERT OR REPLACE INTO " + dbInfo.storeName + " (key, value) VALUES (?, ?)", [key2, value2], function() {
                          resolve(originalValue);
                        }, function(t3, error2) {
                          reject(error2);
                        });
                      }, function(sqlError) {
                        if (sqlError.code === sqlError.QUOTA_ERR) {
                          if (retriesLeft > 0) {
                            resolve(_setItem.apply(self2, [key2, originalValue, callback, retriesLeft - 1]));
                            return;
                          }
                          reject(sqlError);
                        }
                      });
                    }
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function setItem$1(key2, value, callback) {
              return _setItem.apply(this, [key2, value, callback, 1]);
            }
            function removeItem$1(key2, callback) {
              var self2 = this;
              key2 = normalizeKey(key2);
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  var dbInfo = self2._dbInfo;
                  dbInfo.db.transaction(function(t2) {
                    tryExecuteSql(t2, dbInfo, "DELETE FROM " + dbInfo.storeName + " WHERE key = ?", [key2], function() {
                      resolve();
                    }, function(t3, error) {
                      reject(error);
                    });
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function clear$1(callback) {
              var self2 = this;
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  var dbInfo = self2._dbInfo;
                  dbInfo.db.transaction(function(t2) {
                    tryExecuteSql(t2, dbInfo, "DELETE FROM " + dbInfo.storeName, [], function() {
                      resolve();
                    }, function(t3, error) {
                      reject(error);
                    });
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function length$1(callback) {
              var self2 = this;
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  var dbInfo = self2._dbInfo;
                  dbInfo.db.transaction(function(t2) {
                    tryExecuteSql(t2, dbInfo, "SELECT COUNT(key) as c FROM " + dbInfo.storeName, [], function(t3, results) {
                      var result = results.rows.item(0).c;
                      resolve(result);
                    }, function(t3, error) {
                      reject(error);
                    });
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function key$1(n, callback) {
              var self2 = this;
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  var dbInfo = self2._dbInfo;
                  dbInfo.db.transaction(function(t2) {
                    tryExecuteSql(t2, dbInfo, "SELECT key FROM " + dbInfo.storeName + " WHERE id = ? LIMIT 1", [n + 1], function(t3, results) {
                      var result = results.rows.length ? results.rows.item(0).key : null;
                      resolve(result);
                    }, function(t3, error) {
                      reject(error);
                    });
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function keys$1(callback) {
              var self2 = this;
              var promise = new Promise$12(function(resolve, reject) {
                self2.ready().then(function() {
                  var dbInfo = self2._dbInfo;
                  dbInfo.db.transaction(function(t2) {
                    tryExecuteSql(t2, dbInfo, "SELECT key FROM " + dbInfo.storeName, [], function(t3, results) {
                      var keys3 = [];
                      for (var i = 0; i < results.rows.length; i++) {
                        keys3.push(results.rows.item(i).key);
                      }
                      resolve(keys3);
                    }, function(t3, error) {
                      reject(error);
                    });
                  });
                })["catch"](reject);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function getAllStoreNames(db) {
              return new Promise$12(function(resolve, reject) {
                db.transaction(function(t2) {
                  t2.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'", [], function(t3, results) {
                    var storeNames = [];
                    for (var i = 0; i < results.rows.length; i++) {
                      storeNames.push(results.rows.item(i).name);
                    }
                    resolve({
                      db,
                      storeNames
                    });
                  }, function(t3, error) {
                    reject(error);
                  });
                }, function(sqlError) {
                  reject(sqlError);
                });
              });
            }
            function dropInstance$1(options, callback) {
              callback = getCallback.apply(this, arguments);
              var currentConfig = this.config();
              options = typeof options !== "function" && options || {};
              if (!options.name) {
                options.name = options.name || currentConfig.name;
                options.storeName = options.storeName || currentConfig.storeName;
              }
              var self2 = this;
              var promise;
              if (!options.name) {
                promise = Promise$12.reject("Invalid arguments");
              } else {
                promise = new Promise$12(function(resolve) {
                  var db;
                  if (options.name === currentConfig.name) {
                    db = self2._dbInfo.db;
                  } else {
                    db = openDatabase(options.name, "", "", 0);
                  }
                  if (!options.storeName) {
                    resolve(getAllStoreNames(db));
                  } else {
                    resolve({
                      db,
                      storeNames: [options.storeName]
                    });
                  }
                }).then(function(operationInfo) {
                  return new Promise$12(function(resolve, reject) {
                    operationInfo.db.transaction(function(t2) {
                      function dropTable(storeName) {
                        return new Promise$12(function(resolve2, reject2) {
                          t2.executeSql("DROP TABLE IF EXISTS " + storeName, [], function() {
                            resolve2();
                          }, function(t3, error) {
                            reject2(error);
                          });
                        });
                      }
                      var operations = [];
                      for (var i = 0, len = operationInfo.storeNames.length; i < len; i++) {
                        operations.push(dropTable(operationInfo.storeNames[i]));
                      }
                      Promise$12.all(operations).then(function() {
                        resolve();
                      })["catch"](function(e) {
                        reject(e);
                      });
                    }, function(sqlError) {
                      reject(sqlError);
                    });
                  });
                });
              }
              executeCallback2(promise, callback);
              return promise;
            }
            var webSQLStorage = {
              _driver: "webSQLStorage",
              _initStorage: _initStorage$1,
              _support: isWebSQLValid(),
              iterate: iterate$1,
              getItem: getItem$1,
              setItem: setItem$1,
              removeItem: removeItem$1,
              clear: clear$1,
              length: length$1,
              key: key$1,
              keys: keys$1,
              dropInstance: dropInstance$1
            };
            function isLocalStorageValid() {
              try {
                return typeof localStorage !== "undefined" && "setItem" in localStorage && // in IE8 typeof localStorage.setItem === 'object'
                !!localStorage.setItem;
              } catch (e) {
                return false;
              }
            }
            function _getKeyPrefix(options, defaultConfig) {
              var keyPrefix = options.name + "/";
              if (options.storeName !== defaultConfig.storeName) {
                keyPrefix += options.storeName + "/";
              }
              return keyPrefix;
            }
            function checkIfLocalStorageThrows() {
              var localStorageTestKey = "_localforage_support_test";
              try {
                localStorage.setItem(localStorageTestKey, true);
                localStorage.removeItem(localStorageTestKey);
                return false;
              } catch (e) {
                return true;
              }
            }
            function _isLocalStorageUsable() {
              return !checkIfLocalStorageThrows() || localStorage.length > 0;
            }
            function _initStorage$2(options) {
              var self2 = this;
              var dbInfo = {};
              if (options) {
                for (var i in options) {
                  dbInfo[i] = options[i];
                }
              }
              dbInfo.keyPrefix = _getKeyPrefix(options, self2._defaultConfig);
              if (!_isLocalStorageUsable()) {
                return Promise$12.reject();
              }
              self2._dbInfo = dbInfo;
              dbInfo.serializer = localforageSerializer;
              return Promise$12.resolve();
            }
            function clear$2(callback) {
              var self2 = this;
              var promise = self2.ready().then(function() {
                var keyPrefix = self2._dbInfo.keyPrefix;
                for (var i = localStorage.length - 1; i >= 0; i--) {
                  var key2 = localStorage.key(i);
                  if (key2.indexOf(keyPrefix) === 0) {
                    localStorage.removeItem(key2);
                  }
                }
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function getItem$2(key2, callback) {
              var self2 = this;
              key2 = normalizeKey(key2);
              var promise = self2.ready().then(function() {
                var dbInfo = self2._dbInfo;
                var result = localStorage.getItem(dbInfo.keyPrefix + key2);
                if (result) {
                  result = dbInfo.serializer.deserialize(result);
                }
                return result;
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function iterate$2(iterator, callback) {
              var self2 = this;
              var promise = self2.ready().then(function() {
                var dbInfo = self2._dbInfo;
                var keyPrefix = dbInfo.keyPrefix;
                var keyPrefixLength = keyPrefix.length;
                var length2 = localStorage.length;
                var iterationNumber = 1;
                for (var i = 0; i < length2; i++) {
                  var key2 = localStorage.key(i);
                  if (key2.indexOf(keyPrefix) !== 0) {
                    continue;
                  }
                  var value = localStorage.getItem(key2);
                  if (value) {
                    value = dbInfo.serializer.deserialize(value);
                  }
                  value = iterator(value, key2.substring(keyPrefixLength), iterationNumber++);
                  if (value !== void 0) {
                    return value;
                  }
                }
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function key$2(n, callback) {
              var self2 = this;
              var promise = self2.ready().then(function() {
                var dbInfo = self2._dbInfo;
                var result;
                try {
                  result = localStorage.key(n);
                } catch (error) {
                  result = null;
                }
                if (result) {
                  result = result.substring(dbInfo.keyPrefix.length);
                }
                return result;
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function keys$2(callback) {
              var self2 = this;
              var promise = self2.ready().then(function() {
                var dbInfo = self2._dbInfo;
                var length2 = localStorage.length;
                var keys3 = [];
                for (var i = 0; i < length2; i++) {
                  var itemKey = localStorage.key(i);
                  if (itemKey.indexOf(dbInfo.keyPrefix) === 0) {
                    keys3.push(itemKey.substring(dbInfo.keyPrefix.length));
                  }
                }
                return keys3;
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function length$2(callback) {
              var self2 = this;
              var promise = self2.keys().then(function(keys3) {
                return keys3.length;
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function removeItem$2(key2, callback) {
              var self2 = this;
              key2 = normalizeKey(key2);
              var promise = self2.ready().then(function() {
                var dbInfo = self2._dbInfo;
                localStorage.removeItem(dbInfo.keyPrefix + key2);
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function setItem$2(key2, value, callback) {
              var self2 = this;
              key2 = normalizeKey(key2);
              var promise = self2.ready().then(function() {
                if (value === void 0) {
                  value = null;
                }
                var originalValue = value;
                return new Promise$12(function(resolve, reject) {
                  var dbInfo = self2._dbInfo;
                  dbInfo.serializer.serialize(value, function(value2, error) {
                    if (error) {
                      reject(error);
                    } else {
                      try {
                        localStorage.setItem(dbInfo.keyPrefix + key2, value2);
                        resolve(originalValue);
                      } catch (e) {
                        if (e.name === "QuotaExceededError" || e.name === "NS_ERROR_DOM_QUOTA_REACHED") {
                          reject(e);
                        }
                        reject(e);
                      }
                    }
                  });
                });
              });
              executeCallback2(promise, callback);
              return promise;
            }
            function dropInstance$2(options, callback) {
              callback = getCallback.apply(this, arguments);
              options = typeof options !== "function" && options || {};
              if (!options.name) {
                var currentConfig = this.config();
                options.name = options.name || currentConfig.name;
                options.storeName = options.storeName || currentConfig.storeName;
              }
              var self2 = this;
              var promise;
              if (!options.name) {
                promise = Promise$12.reject("Invalid arguments");
              } else {
                promise = new Promise$12(function(resolve) {
                  if (!options.storeName) {
                    resolve(options.name + "/");
                  } else {
                    resolve(_getKeyPrefix(options, self2._defaultConfig));
                  }
                }).then(function(keyPrefix) {
                  for (var i = localStorage.length - 1; i >= 0; i--) {
                    var key2 = localStorage.key(i);
                    if (key2.indexOf(keyPrefix) === 0) {
                      localStorage.removeItem(key2);
                    }
                  }
                });
              }
              executeCallback2(promise, callback);
              return promise;
            }
            var localStorageWrapper = {
              _driver: "localStorageWrapper",
              _initStorage: _initStorage$2,
              _support: isLocalStorageValid(),
              iterate: iterate$2,
              getItem: getItem$2,
              setItem: setItem$2,
              removeItem: removeItem$2,
              clear: clear$2,
              length: length$2,
              key: key$2,
              keys: keys$2,
              dropInstance: dropInstance$2
            };
            var sameValue = function sameValue2(x, y) {
              return x === y || typeof x === "number" && typeof y === "number" && isNaN(x) && isNaN(y);
            };
            var includes = function includes2(array, searchElement) {
              var len = array.length;
              var i = 0;
              while (i < len) {
                if (sameValue(array[i], searchElement)) {
                  return true;
                }
                i++;
              }
              return false;
            };
            var isArray2 = Array.isArray || function(arg) {
              return Object.prototype.toString.call(arg) === "[object Array]";
            };
            var DefinedDrivers = {};
            var DriverSupport = {};
            var DefaultDrivers = {
              INDEXEDDB: asyncStorage,
              WEBSQL: webSQLStorage,
              LOCALSTORAGE: localStorageWrapper
            };
            var DefaultDriverOrder = [DefaultDrivers.INDEXEDDB._driver, DefaultDrivers.WEBSQL._driver, DefaultDrivers.LOCALSTORAGE._driver];
            var OptionalDriverMethods = ["dropInstance"];
            var LibraryMethods = ["clear", "getItem", "iterate", "key", "keys", "length", "removeItem", "setItem"].concat(OptionalDriverMethods);
            var DefaultConfig = {
              description: "",
              driver: DefaultDriverOrder.slice(),
              name: "localforage",
              // Default DB size is _JUST UNDER_ 5MB, as it's the highest size
              // we can use without a prompt.
              size: 4980736,
              storeName: "keyvaluepairs",
              version: 1
            };
            function callWhenReady(localForageInstance, libraryMethod) {
              localForageInstance[libraryMethod] = function() {
                var _args = arguments;
                return localForageInstance.ready().then(function() {
                  return localForageInstance[libraryMethod].apply(localForageInstance, _args);
                });
              };
            }
            function extend() {
              for (var i = 1; i < arguments.length; i++) {
                var arg = arguments[i];
                if (arg) {
                  for (var _key in arg) {
                    if (arg.hasOwnProperty(_key)) {
                      if (isArray2(arg[_key])) {
                        arguments[0][_key] = arg[_key].slice();
                      } else {
                        arguments[0][_key] = arg[_key];
                      }
                    }
                  }
                }
              }
              return arguments[0];
            }
            var LocalForage = function() {
              function LocalForage2(options) {
                _classCallCheck(this, LocalForage2);
                for (var driverTypeKey in DefaultDrivers) {
                  if (DefaultDrivers.hasOwnProperty(driverTypeKey)) {
                    var driver = DefaultDrivers[driverTypeKey];
                    var driverName = driver._driver;
                    this[driverTypeKey] = driverName;
                    if (!DefinedDrivers[driverName]) {
                      this.defineDriver(driver);
                    }
                  }
                }
                this._defaultConfig = extend({}, DefaultConfig);
                this._config = extend({}, this._defaultConfig, options);
                this._driverSet = null;
                this._initDriver = null;
                this._ready = false;
                this._dbInfo = null;
                this._wrapLibraryMethodsWithReady();
                this.setDriver(this._config.driver)["catch"](function() {
                });
              }
              LocalForage2.prototype.config = function config(options) {
                if ((typeof options === "undefined" ? "undefined" : _typeof(options)) === "object") {
                  if (this._ready) {
                    return new Error("Can't call config() after localforage has been used.");
                  }
                  for (var i in options) {
                    if (i === "storeName") {
                      options[i] = options[i].replace(/\W/g, "_");
                    }
                    if (i === "version" && typeof options[i] !== "number") {
                      return new Error("Database version must be a number.");
                    }
                    this._config[i] = options[i];
                  }
                  if ("driver" in options && options.driver) {
                    return this.setDriver(this._config.driver);
                  }
                  return true;
                } else if (typeof options === "string") {
                  return this._config[options];
                } else {
                  return this._config;
                }
              };
              LocalForage2.prototype.defineDriver = function defineDriver(driverObject, callback, errorCallback) {
                var promise = new Promise$12(function(resolve, reject) {
                  try {
                    var driverName = driverObject._driver;
                    var complianceError = new Error("Custom driver not compliant; see https://mozilla.github.io/localForage/#definedriver");
                    if (!driverObject._driver) {
                      reject(complianceError);
                      return;
                    }
                    var driverMethods = LibraryMethods.concat("_initStorage");
                    for (var i = 0, len = driverMethods.length; i < len; i++) {
                      var driverMethodName = driverMethods[i];
                      var isRequired = !includes(OptionalDriverMethods, driverMethodName);
                      if ((isRequired || driverObject[driverMethodName]) && typeof driverObject[driverMethodName] !== "function") {
                        reject(complianceError);
                        return;
                      }
                    }
                    var configureMissingMethods = function configureMissingMethods2() {
                      var methodNotImplementedFactory = function methodNotImplementedFactory2(methodName) {
                        return function() {
                          var error = new Error("Method " + methodName + " is not implemented by the current driver");
                          var promise2 = Promise$12.reject(error);
                          executeCallback2(promise2, arguments[arguments.length - 1]);
                          return promise2;
                        };
                      };
                      for (var _i = 0, _len = OptionalDriverMethods.length; _i < _len; _i++) {
                        var optionalDriverMethod = OptionalDriverMethods[_i];
                        if (!driverObject[optionalDriverMethod]) {
                          driverObject[optionalDriverMethod] = methodNotImplementedFactory(optionalDriverMethod);
                        }
                      }
                    };
                    configureMissingMethods();
                    var setDriverSupport = function setDriverSupport2(support) {
                      if (DefinedDrivers[driverName]) {
                        console.info("Redefining LocalForage driver: " + driverName);
                      }
                      DefinedDrivers[driverName] = driverObject;
                      DriverSupport[driverName] = support;
                      resolve();
                    };
                    if ("_support" in driverObject) {
                      if (driverObject._support && typeof driverObject._support === "function") {
                        driverObject._support().then(setDriverSupport, reject);
                      } else {
                        setDriverSupport(!!driverObject._support);
                      }
                    } else {
                      setDriverSupport(true);
                    }
                  } catch (e) {
                    reject(e);
                  }
                });
                executeTwoCallbacks(promise, callback, errorCallback);
                return promise;
              };
              LocalForage2.prototype.driver = function driver() {
                return this._driver || null;
              };
              LocalForage2.prototype.getDriver = function getDriver(driverName, callback, errorCallback) {
                var getDriverPromise = DefinedDrivers[driverName] ? Promise$12.resolve(DefinedDrivers[driverName]) : Promise$12.reject(new Error("Driver not found."));
                executeTwoCallbacks(getDriverPromise, callback, errorCallback);
                return getDriverPromise;
              };
              LocalForage2.prototype.getSerializer = function getSerializer(callback) {
                var serializerPromise = Promise$12.resolve(localforageSerializer);
                executeTwoCallbacks(serializerPromise, callback);
                return serializerPromise;
              };
              LocalForage2.prototype.ready = function ready(callback) {
                var self2 = this;
                var promise = self2._driverSet.then(function() {
                  if (self2._ready === null) {
                    self2._ready = self2._initDriver();
                  }
                  return self2._ready;
                });
                executeTwoCallbacks(promise, callback, callback);
                return promise;
              };
              LocalForage2.prototype.setDriver = function setDriver(drivers, callback, errorCallback) {
                var self2 = this;
                if (!isArray2(drivers)) {
                  drivers = [drivers];
                }
                var supportedDrivers = this._getSupportedDrivers(drivers);
                function setDriverToConfig() {
                  self2._config.driver = self2.driver();
                }
                function extendSelfWithDriver(driver) {
                  self2._extend(driver);
                  setDriverToConfig();
                  self2._ready = self2._initStorage(self2._config);
                  return self2._ready;
                }
                function initDriver(supportedDrivers2) {
                  return function() {
                    var currentDriverIndex = 0;
                    function driverPromiseLoop() {
                      while (currentDriverIndex < supportedDrivers2.length) {
                        var driverName = supportedDrivers2[currentDriverIndex];
                        currentDriverIndex++;
                        self2._dbInfo = null;
                        self2._ready = null;
                        return self2.getDriver(driverName).then(extendSelfWithDriver)["catch"](driverPromiseLoop);
                      }
                      setDriverToConfig();
                      var error = new Error("No available storage method found.");
                      self2._driverSet = Promise$12.reject(error);
                      return self2._driverSet;
                    }
                    return driverPromiseLoop();
                  };
                }
                var oldDriverSetDone = this._driverSet !== null ? this._driverSet["catch"](function() {
                  return Promise$12.resolve();
                }) : Promise$12.resolve();
                this._driverSet = oldDriverSetDone.then(function() {
                  var driverName = supportedDrivers[0];
                  self2._dbInfo = null;
                  self2._ready = null;
                  return self2.getDriver(driverName).then(function(driver) {
                    self2._driver = driver._driver;
                    setDriverToConfig();
                    self2._wrapLibraryMethodsWithReady();
                    self2._initDriver = initDriver(supportedDrivers);
                  });
                })["catch"](function() {
                  setDriverToConfig();
                  var error = new Error("No available storage method found.");
                  self2._driverSet = Promise$12.reject(error);
                  return self2._driverSet;
                });
                executeTwoCallbacks(this._driverSet, callback, errorCallback);
                return this._driverSet;
              };
              LocalForage2.prototype.supports = function supports(driverName) {
                return !!DriverSupport[driverName];
              };
              LocalForage2.prototype._extend = function _extend(libraryMethodsAndProperties) {
                extend(this, libraryMethodsAndProperties);
              };
              LocalForage2.prototype._getSupportedDrivers = function _getSupportedDrivers(drivers) {
                var supportedDrivers = [];
                for (var i = 0, len = drivers.length; i < len; i++) {
                  var driverName = drivers[i];
                  if (this.supports(driverName)) {
                    supportedDrivers.push(driverName);
                  }
                }
                return supportedDrivers;
              };
              LocalForage2.prototype._wrapLibraryMethodsWithReady = function _wrapLibraryMethodsWithReady() {
                for (var i = 0, len = LibraryMethods.length; i < len; i++) {
                  callWhenReady(this, LibraryMethods[i]);
                }
              };
              LocalForage2.prototype.createInstance = function createInstance(options) {
                return new LocalForage2(options);
              };
              return LocalForage2;
            }();
            var localforage_js = new LocalForage();
            module3.exports = localforage_js;
          }, { "3": 3 }] }, {}, [4])(4);
        });
      })(localforage$1);
      var localforageExports = localforage$1.exports;
      const localforage = /* @__PURE__ */ getDefaultExportFromCjs(localforageExports);
      function getSerializerPromise(localForageInstance) {
        if (getSerializerPromise.result) {
          return getSerializerPromise.result;
        }
        if (!localForageInstance || typeof localForageInstance.getSerializer !== "function") {
          return Promise.reject(new Error("localforage.getSerializer() was not available! localforage v1.4+ is required!"));
        }
        getSerializerPromise.result = localForageInstance.getSerializer();
        return getSerializerPromise.result;
      }
      function executeCallback(promise, callback) {
        if (callback) {
          promise.then(function(result) {
            callback(null, result);
          }, function(error) {
            callback(error);
          });
        }
      }
      function forEachItem(items, keyFn, valueFn, loopFn) {
        function ensurePropGetterMethod(propFn, defaultPropName) {
          var propName = propFn || defaultPropName;
          if ((!propFn || typeof propFn !== "function") && typeof propName === "string") {
            propFn = function propFn2(item2) {
              return item2[propName];
            };
          }
          return propFn;
        }
        var result = [];
        if (Object.prototype.toString.call(items) === "[object Array]") {
          keyFn = ensurePropGetterMethod(keyFn, "key");
          valueFn = ensurePropGetterMethod(valueFn, "value");
          for (var i = 0, len = items.length; i < len; i++) {
            var item = items[i];
            result.push(loopFn(keyFn(item), valueFn(item)));
          }
        } else {
          for (var prop in items) {
            if (items.hasOwnProperty(prop)) {
              result.push(loopFn(prop, items[prop]));
            }
          }
        }
        return result;
      }
      function setItemsIndexedDB(items, keyFn, valueFn, callback) {
        var localforageInstance = this;
        var promise = localforageInstance.ready().then(function() {
          return new Promise(function(resolve, reject) {
            var dbInfo = localforageInstance._dbInfo;
            var transaction = dbInfo.db.transaction(dbInfo.storeName, "readwrite");
            var store = transaction.objectStore(dbInfo.storeName);
            var lastError;
            transaction.oncomplete = function() {
              resolve(items);
            };
            transaction.onabort = transaction.onerror = function(event) {
              reject(lastError || event.target);
            };
            function requestOnError(evt) {
              var request2 = evt.target || this;
              lastError = request2.error || request2.transaction.error;
              reject(lastError);
            }
            forEachItem(items, keyFn, valueFn, function(key, value) {
              if (value === null) {
                value = void 0;
              }
              var request2 = store.put(value, key);
              request2.onerror = requestOnError;
            });
          });
        });
        executeCallback(promise, callback);
        return promise;
      }
      function setItemsWebsql(items, keyFn, valueFn, callback) {
        var localforageInstance = this;
        var promise = new Promise(function(resolve, reject) {
          localforageInstance.ready().then(function() {
            return getSerializerPromise(localforageInstance);
          }).then(function(serializer) {
            var dbInfo = localforageInstance._dbInfo;
            dbInfo.db.transaction(
              function(t2) {
                var query = "INSERT OR REPLACE INTO " + dbInfo.storeName + " (key, value) VALUES (?, ?)";
                var itemPromises = forEachItem(items, keyFn, valueFn, function(key, value) {
                  return new Promise(function(resolve2, reject2) {
                    serializer.serialize(value, function(value2, error) {
                      if (error) {
                        reject2(error);
                      } else {
                        t2.executeSql(query, [key, value2], function() {
                          resolve2();
                        }, function(t3, error2) {
                          reject2(error2);
                        });
                      }
                    });
                  });
                });
                Promise.all(itemPromises).then(function() {
                  resolve(items);
                }, reject);
              },
              function(sqlError) {
                reject(sqlError);
              }
              /*, function() {
                 if (resolving) {
                     resolve(items);
                 }
              }*/
            );
          }).catch(reject);
        });
        executeCallback(promise, callback);
        return promise;
      }
      function setItemsGeneric(items, keyFn, valueFn, callback) {
        var localforageInstance = this;
        var itemPromises = forEachItem(items, keyFn, valueFn, function(key, value) {
          return localforageInstance.setItem(key, value);
        });
        var promise = Promise.all(itemPromises);
        executeCallback(promise, callback);
        return promise;
      }
      function localforageSetItems(items, keyFn, valueFn, callback) {
        var localforageInstance = this;
        var currentDriver = localforageInstance.driver();
        if (currentDriver === localforageInstance.INDEXEDDB) {
          return setItemsIndexedDB.call(localforageInstance, items, keyFn, valueFn, callback);
        } else if (currentDriver === localforageInstance.WEBSQL) {
          return setItemsWebsql.call(localforageInstance, items, keyFn, valueFn, callback);
        } else {
          return setItemsGeneric.call(localforageInstance, items, keyFn, valueFn, callback);
        }
      }
      function extendPrototype(localforage$$1) {
        var localforagePrototype = Object.getPrototypeOf(localforage$$1);
        if (localforagePrototype) {
          localforagePrototype.setItems = localforageSetItems;
          localforagePrototype.setItems.indexedDB = function() {
            return setItemsIndexedDB.apply(this, arguments);
          };
          localforagePrototype.setItems.websql = function() {
            return setItemsWebsql.apply(this, arguments);
          };
          localforagePrototype.setItems.generic = function() {
            return setItemsGeneric.apply(this, arguments);
          };
        }
      }
      extendPrototype(localforage);
      var md5$1 = { exports: {} };
      var crypt = { exports: {} };
      (function() {
        var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", crypt$1 = {
          // Bit-wise rotation left
          rotl: function(n, b) {
            return n << b | n >>> 32 - b;
          },
          // Bit-wise rotation right
          rotr: function(n, b) {
            return n << 32 - b | n >>> b;
          },
          // Swap big-endian to little-endian and vice versa
          endian: function(n) {
            if (n.constructor == Number) {
              return crypt$1.rotl(n, 8) & 16711935 | crypt$1.rotl(n, 24) & 4278255360;
            }
            for (var i = 0; i < n.length; i++)
              n[i] = crypt$1.endian(n[i]);
            return n;
          },
          // Generate an array of any length of random bytes
          randomBytes: function(n) {
            for (var bytes = []; n > 0; n--)
              bytes.push(Math.floor(Math.random() * 256));
            return bytes;
          },
          // Convert a byte array to big-endian 32-bit words
          bytesToWords: function(bytes) {
            for (var words2 = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
              words2[b >>> 5] |= bytes[i] << 24 - b % 32;
            return words2;
          },
          // Convert big-endian 32-bit words to a byte array
          wordsToBytes: function(words2) {
            for (var bytes = [], b = 0; b < words2.length * 32; b += 8)
              bytes.push(words2[b >>> 5] >>> 24 - b % 32 & 255);
            return bytes;
          },
          // Convert a byte array to a hex string
          bytesToHex: function(bytes) {
            for (var hex = [], i = 0; i < bytes.length; i++) {
              hex.push((bytes[i] >>> 4).toString(16));
              hex.push((bytes[i] & 15).toString(16));
            }
            return hex.join("");
          },
          // Convert a hex string to a byte array
          hexToBytes: function(hex) {
            for (var bytes = [], c = 0; c < hex.length; c += 2)
              bytes.push(parseInt(hex.substr(c, 2), 16));
            return bytes;
          },
          // Convert a byte array to a base-64 string
          bytesToBase64: function(bytes) {
            for (var base64 = [], i = 0; i < bytes.length; i += 3) {
              var triplet = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
              for (var j = 0; j < 4; j++)
                if (i * 8 + j * 6 <= bytes.length * 8)
                  base64.push(base64map.charAt(triplet >>> 6 * (3 - j) & 63));
                else
                  base64.push("=");
            }
            return base64.join("");
          },
          // Convert a base-64 string to a byte array
          base64ToBytes: function(base64) {
            base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
            for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) {
              if (imod4 == 0)
                continue;
              bytes.push((base64map.indexOf(base64.charAt(i - 1)) & Math.pow(2, -2 * imod4 + 8) - 1) << imod4 * 2 | base64map.indexOf(base64.charAt(i)) >>> 6 - imod4 * 2);
            }
            return bytes;
          }
        };
        crypt.exports = crypt$1;
      })();
      var cryptExports = crypt.exports;
      var charenc = {
        // UTF-8 encoding
        utf8: {
          // Convert a string to a byte array
          stringToBytes: function(str) {
            return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
          },
          // Convert a byte array to a string
          bytesToString: function(bytes) {
            return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
          }
        },
        // Binary encoding
        bin: {
          // Convert a string to a byte array
          stringToBytes: function(str) {
            for (var bytes = [], i = 0; i < str.length; i++)
              bytes.push(str.charCodeAt(i) & 255);
            return bytes;
          },
          // Convert a byte array to a string
          bytesToString: function(bytes) {
            for (var str = [], i = 0; i < bytes.length; i++)
              str.push(String.fromCharCode(bytes[i]));
            return str.join("");
          }
        }
      };
      var charenc_1 = charenc;
      /*!
       * Determine if an object is a Buffer
       *
       * @author   Feross Aboukhadijeh <https://feross.org>
       * @license  MIT
       */
      var isBuffer_1 = function(obj) {
        return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer);
      };
      function isBuffer(obj) {
        return !!obj.constructor && typeof obj.constructor.isBuffer === "function" && obj.constructor.isBuffer(obj);
      }
      function isSlowBuffer(obj) {
        return typeof obj.readFloatLE === "function" && typeof obj.slice === "function" && isBuffer(obj.slice(0, 0));
      }
      (function() {
        var crypt2 = cryptExports, utf8 = charenc_1.utf8, isBuffer2 = isBuffer_1, bin = charenc_1.bin, md52 = function(message, options) {
          if (message.constructor == String)
            if (options && options.encoding === "binary")
              message = bin.stringToBytes(message);
            else
              message = utf8.stringToBytes(message);
          else if (isBuffer2(message))
            message = Array.prototype.slice.call(message, 0);
          else if (!Array.isArray(message) && message.constructor !== Uint8Array)
            message = message.toString();
          var m = crypt2.bytesToWords(message), l = message.length * 8, a = 1732584193, b = -271733879, c = -1732584194, d = 271733878;
          for (var i = 0; i < m.length; i++) {
            m[i] = (m[i] << 8 | m[i] >>> 24) & 16711935 | (m[i] << 24 | m[i] >>> 8) & 4278255360;
          }
          m[l >>> 5] |= 128 << l % 32;
          m[(l + 64 >>> 9 << 4) + 14] = l;
          var FF = md52._ff, GG = md52._gg, HH = md52._hh, II = md52._ii;
          for (var i = 0; i < m.length; i += 16) {
            var aa = a, bb = b, cc = c, dd = d;
            a = FF(a, b, c, d, m[i + 0], 7, -680876936);
            d = FF(d, a, b, c, m[i + 1], 12, -389564586);
            c = FF(c, d, a, b, m[i + 2], 17, 606105819);
            b = FF(b, c, d, a, m[i + 3], 22, -1044525330);
            a = FF(a, b, c, d, m[i + 4], 7, -176418897);
            d = FF(d, a, b, c, m[i + 5], 12, 1200080426);
            c = FF(c, d, a, b, m[i + 6], 17, -1473231341);
            b = FF(b, c, d, a, m[i + 7], 22, -45705983);
            a = FF(a, b, c, d, m[i + 8], 7, 1770035416);
            d = FF(d, a, b, c, m[i + 9], 12, -1958414417);
            c = FF(c, d, a, b, m[i + 10], 17, -42063);
            b = FF(b, c, d, a, m[i + 11], 22, -1990404162);
            a = FF(a, b, c, d, m[i + 12], 7, 1804603682);
            d = FF(d, a, b, c, m[i + 13], 12, -40341101);
            c = FF(c, d, a, b, m[i + 14], 17, -1502002290);
            b = FF(b, c, d, a, m[i + 15], 22, 1236535329);
            a = GG(a, b, c, d, m[i + 1], 5, -165796510);
            d = GG(d, a, b, c, m[i + 6], 9, -1069501632);
            c = GG(c, d, a, b, m[i + 11], 14, 643717713);
            b = GG(b, c, d, a, m[i + 0], 20, -373897302);
            a = GG(a, b, c, d, m[i + 5], 5, -701558691);
            d = GG(d, a, b, c, m[i + 10], 9, 38016083);
            c = GG(c, d, a, b, m[i + 15], 14, -660478335);
            b = GG(b, c, d, a, m[i + 4], 20, -405537848);
            a = GG(a, b, c, d, m[i + 9], 5, 568446438);
            d = GG(d, a, b, c, m[i + 14], 9, -1019803690);
            c = GG(c, d, a, b, m[i + 3], 14, -187363961);
            b = GG(b, c, d, a, m[i + 8], 20, 1163531501);
            a = GG(a, b, c, d, m[i + 13], 5, -1444681467);
            d = GG(d, a, b, c, m[i + 2], 9, -51403784);
            c = GG(c, d, a, b, m[i + 7], 14, 1735328473);
            b = GG(b, c, d, a, m[i + 12], 20, -1926607734);
            a = HH(a, b, c, d, m[i + 5], 4, -378558);
            d = HH(d, a, b, c, m[i + 8], 11, -2022574463);
            c = HH(c, d, a, b, m[i + 11], 16, 1839030562);
            b = HH(b, c, d, a, m[i + 14], 23, -35309556);
            a = HH(a, b, c, d, m[i + 1], 4, -1530992060);
            d = HH(d, a, b, c, m[i + 4], 11, 1272893353);
            c = HH(c, d, a, b, m[i + 7], 16, -155497632);
            b = HH(b, c, d, a, m[i + 10], 23, -1094730640);
            a = HH(a, b, c, d, m[i + 13], 4, 681279174);
            d = HH(d, a, b, c, m[i + 0], 11, -358537222);
            c = HH(c, d, a, b, m[i + 3], 16, -722521979);
            b = HH(b, c, d, a, m[i + 6], 23, 76029189);
            a = HH(a, b, c, d, m[i + 9], 4, -640364487);
            d = HH(d, a, b, c, m[i + 12], 11, -421815835);
            c = HH(c, d, a, b, m[i + 15], 16, 530742520);
            b = HH(b, c, d, a, m[i + 2], 23, -995338651);
            a = II(a, b, c, d, m[i + 0], 6, -198630844);
            d = II(d, a, b, c, m[i + 7], 10, 1126891415);
            c = II(c, d, a, b, m[i + 14], 15, -1416354905);
            b = II(b, c, d, a, m[i + 5], 21, -57434055);
            a = II(a, b, c, d, m[i + 12], 6, 1700485571);
            d = II(d, a, b, c, m[i + 3], 10, -1894986606);
            c = II(c, d, a, b, m[i + 10], 15, -1051523);
            b = II(b, c, d, a, m[i + 1], 21, -2054922799);
            a = II(a, b, c, d, m[i + 8], 6, 1873313359);
            d = II(d, a, b, c, m[i + 15], 10, -30611744);
            c = II(c, d, a, b, m[i + 6], 15, -1560198380);
            b = II(b, c, d, a, m[i + 13], 21, 1309151649);
            a = II(a, b, c, d, m[i + 4], 6, -145523070);
            d = II(d, a, b, c, m[i + 11], 10, -1120210379);
            c = II(c, d, a, b, m[i + 2], 15, 718787259);
            b = II(b, c, d, a, m[i + 9], 21, -343485551);
            a = a + aa >>> 0;
            b = b + bb >>> 0;
            c = c + cc >>> 0;
            d = d + dd >>> 0;
          }
          return crypt2.endian([a, b, c, d]);
        };
        md52._ff = function(a, b, c, d, x, s, t2) {
          var n = a + (b & c | ~b & d) + (x >>> 0) + t2;
          return (n << s | n >>> 32 - s) + b;
        };
        md52._gg = function(a, b, c, d, x, s, t2) {
          var n = a + (b & d | c & ~d) + (x >>> 0) + t2;
          return (n << s | n >>> 32 - s) + b;
        };
        md52._hh = function(a, b, c, d, x, s, t2) {
          var n = a + (b ^ c ^ d) + (x >>> 0) + t2;
          return (n << s | n >>> 32 - s) + b;
        };
        md52._ii = function(a, b, c, d, x, s, t2) {
          var n = a + (c ^ (b | ~d)) + (x >>> 0) + t2;
          return (n << s | n >>> 32 - s) + b;
        };
        md52._blocksize = 16;
        md52._digestsize = 16;
        md5$1.exports = function(message, options) {
          if (message === void 0 || message === null)
            throw new Error("Illegal argument " + message);
          var digestbytes = crypt2.wordsToBytes(md52(message, options));
          return options && options.asBytes ? digestbytes : options && options.asString ? bin.bytesToString(digestbytes) : crypt2.bytesToHex(digestbytes);
        };
      })();
      var md5Exports = md5$1.exports;
      const md5 = /* @__PURE__ */ getDefaultExportFromCjs(md5Exports);
      const dateTimeFormatter = new Intl.DateTimeFormat(void 0, {
        year: "numeric",
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        hour12: false
      });
      (function detectScriptRel() {
        const relList = typeof document !== "undefined" && document.createElement("link").relList;
        return relList && relList.supports && relList.supports("modulepreload") ? "modulepreload" : "preload";
      })();
      /**
       * @license
       * Copyright 2019 Google LLC
       * SPDX-License-Identifier: Apache-2.0
       */
      const proxyMarker = Symbol("Comlink.proxy");
      const createEndpoint = Symbol("Comlink.endpoint");
      const releaseProxy = Symbol("Comlink.releaseProxy");
      const finalizer = Symbol("Comlink.finalizer");
      const throwMarker = Symbol("Comlink.thrown");
      const isObject$1 = (val) => typeof val === "object" && val !== null || typeof val === "function";
      const proxyTransferHandler = {
        canHandle: (val) => isObject$1(val) && val[proxyMarker],
        serialize(obj) {
          const { port1, port2 } = new MessageChannel();
          expose(obj, port1);
          return [port2, [port2]];
        },
        deserialize(port) {
          port.start();
          return wrap(port);
        }
      };
      const throwTransferHandler = {
        canHandle: (value) => isObject$1(value) && throwMarker in value,
        serialize({ value }) {
          let serialized;
          if (value instanceof Error) {
            serialized = {
              isError: true,
              value: {
                message: value.message,
                name: value.name,
                stack: value.stack
              }
            };
          } else {
            serialized = { isError: false, value };
          }
          return [serialized, []];
        },
        deserialize(serialized) {
          if (serialized.isError) {
            throw Object.assign(new Error(serialized.value.message), serialized.value);
          }
          throw serialized.value;
        }
      };
      const transferHandlers = /* @__PURE__ */ new Map([
        ["proxy", proxyTransferHandler],
        ["throw", throwTransferHandler]
      ]);
      function isAllowedOrigin(allowedOrigins, origin) {
        for (const allowedOrigin of allowedOrigins) {
          if (origin === allowedOrigin || allowedOrigin === "*") {
            return true;
          }
          if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {
            return true;
          }
        }
        return false;
      }
      function expose(obj, ep = globalThis, allowedOrigins = ["*"]) {
        ep.addEventListener("message", function callback(ev) {
          if (!ev || !ev.data) {
            return;
          }
          if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
            console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);
            return;
          }
          const { id, type, path } = Object.assign({ path: [] }, ev.data);
          const argumentList = (ev.data.argumentList || []).map(fromWireValue);
          let returnValue;
          try {
            const parent = path.slice(0, -1).reduce((obj2, prop) => obj2[prop], obj);
            const rawValue = path.reduce((obj2, prop) => obj2[prop], obj);
            switch (type) {
              case "GET":
                {
                  returnValue = rawValue;
                }
                break;
              case "SET":
                {
                  parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
                  returnValue = true;
                }
                break;
              case "APPLY":
                {
                  returnValue = rawValue.apply(parent, argumentList);
                }
                break;
              case "CONSTRUCT":
                {
                  const value = new rawValue(...argumentList);
                  returnValue = proxy(value);
                }
                break;
              case "ENDPOINT":
                {
                  const { port1, port2 } = new MessageChannel();
                  expose(obj, port2);
                  returnValue = transfer(port1, [port1]);
                }
                break;
              case "RELEASE":
                {
                  returnValue = void 0;
                }
                break;
              default:
                return;
            }
          } catch (value) {
            returnValue = { value, [throwMarker]: 0 };
          }
          Promise.resolve(returnValue).catch((value) => {
            return { value, [throwMarker]: 0 };
          }).then((returnValue2) => {
            const [wireValue, transferables] = toWireValue(returnValue2);
            ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
            if (type === "RELEASE") {
              ep.removeEventListener("message", callback);
              closeEndPoint(ep);
              if (finalizer in obj && typeof obj[finalizer] === "function") {
                obj[finalizer]();
              }
            }
          }).catch((error) => {
            const [wireValue, transferables] = toWireValue({
              value: new TypeError("Unserializable return value"),
              [throwMarker]: 0
            });
            ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
          });
        });
        if (ep.start) {
          ep.start();
        }
      }
      function isMessagePort(endpoint) {
        return endpoint.constructor.name === "MessagePort";
      }
      function closeEndPoint(endpoint) {
        if (isMessagePort(endpoint))
          endpoint.close();
      }
      function wrap(ep, target) {
        return createProxy(ep, [], target);
      }
      function throwIfProxyReleased(isReleased) {
        if (isReleased) {
          throw new Error("Proxy has been released and is not useable");
        }
      }
      function releaseEndpoint(ep) {
        return requestResponseMessage(ep, {
          type: "RELEASE"
        }).then(() => {
          closeEndPoint(ep);
        });
      }
      const proxyCounter = /* @__PURE__ */ new WeakMap();
      const proxyFinalizers = "FinalizationRegistry" in globalThis && new FinalizationRegistry((ep) => {
        const newCount = (proxyCounter.get(ep) || 0) - 1;
        proxyCounter.set(ep, newCount);
        if (newCount === 0) {
          releaseEndpoint(ep);
        }
      });
      function registerProxy(proxy2, ep) {
        const newCount = (proxyCounter.get(ep) || 0) + 1;
        proxyCounter.set(ep, newCount);
        if (proxyFinalizers) {
          proxyFinalizers.register(proxy2, ep, proxy2);
        }
      }
      function unregisterProxy(proxy2) {
        if (proxyFinalizers) {
          proxyFinalizers.unregister(proxy2);
        }
      }
      function createProxy(ep, path = [], target = function() {
      }) {
        let isProxyReleased = false;
        const proxy2 = new Proxy(target, {
          get(_target, prop) {
            throwIfProxyReleased(isProxyReleased);
            if (prop === releaseProxy) {
              return () => {
                unregisterProxy(proxy2);
                releaseEndpoint(ep);
                isProxyReleased = true;
              };
            }
            if (prop === "then") {
              if (path.length === 0) {
                return { then: () => proxy2 };
              }
              const r = requestResponseMessage(ep, {
                type: "GET",
                path: path.map((p) => p.toString())
              }).then(fromWireValue);
              return r.then.bind(r);
            }
            return createProxy(ep, [...path, prop]);
          },
          set(_target, prop, rawValue) {
            throwIfProxyReleased(isProxyReleased);
            const [value, transferables] = toWireValue(rawValue);
            return requestResponseMessage(ep, {
              type: "SET",
              path: [...path, prop].map((p) => p.toString()),
              value
            }, transferables).then(fromWireValue);
          },
          apply(_target, _thisArg, rawArgumentList) {
            throwIfProxyReleased(isProxyReleased);
            const last2 = path[path.length - 1];
            if (last2 === createEndpoint) {
              return requestResponseMessage(ep, {
                type: "ENDPOINT"
              }).then(fromWireValue);
            }
            if (last2 === "bind") {
              return createProxy(ep, path.slice(0, -1));
            }
            const [argumentList, transferables] = processArguments(rawArgumentList);
            return requestResponseMessage(ep, {
              type: "APPLY",
              path: path.map((p) => p.toString()),
              argumentList
            }, transferables).then(fromWireValue);
          },
          construct(_target, rawArgumentList) {
            throwIfProxyReleased(isProxyReleased);
            const [argumentList, transferables] = processArguments(rawArgumentList);
            return requestResponseMessage(ep, {
              type: "CONSTRUCT",
              path: path.map((p) => p.toString()),
              argumentList
            }, transferables).then(fromWireValue);
          }
        });
        registerProxy(proxy2, ep);
        return proxy2;
      }
      function myFlat(arr) {
        return Array.prototype.concat.apply([], arr);
      }
      function processArguments(argumentList) {
        const processed = argumentList.map(toWireValue);
        return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
      }
      const transferCache = /* @__PURE__ */ new WeakMap();
      function transfer(obj, transfers) {
        transferCache.set(obj, transfers);
        return obj;
      }
      function proxy(obj) {
        return Object.assign(obj, { [proxyMarker]: true });
      }
      function toWireValue(value) {
        for (const [name, handler] of transferHandlers) {
          if (handler.canHandle(value)) {
            const [serializedValue, transferables] = handler.serialize(value);
            return [
              {
                type: "HANDLER",
                name,
                value: serializedValue
              },
              transferables
            ];
          }
        }
        return [
          {
            type: "RAW",
            value
          },
          transferCache.get(value) || []
        ];
      }
      function fromWireValue(value) {
        switch (value.type) {
          case "HANDLER":
            return transferHandlers.get(value.name).deserialize(value.value);
          case "RAW":
            return value.value;
        }
      }
      function requestResponseMessage(ep, msg, transfers) {
        return new Promise((resolve) => {
          const id = generateUUID();
          ep.addEventListener("message", function l(ev) {
            if (!ev.data || !ev.data.id || ev.data.id !== id) {
              return;
            }
            ep.removeEventListener("message", l);
            resolve(ev.data);
          });
          if (ep.start) {
            ep.start();
          }
          ep.postMessage(Object.assign({ id }, msg), transfers);
        });
      }
      function generateUUID() {
        return new Array(4).fill(0).map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16)).join("-");
      }
      const encodedJs = "dmFyIF9fZGVmUHJvcCA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTsKdmFyIF9fZGVmTm9ybWFsUHJvcCA9IChvYmosIGtleSwgdmFsdWUpID0+IGtleSBpbiBvYmogPyBfX2RlZlByb3Aob2JqLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlLCB3cml0YWJsZTogdHJ1ZSwgdmFsdWUgfSkgOiBvYmpba2V5XSA9IHZhbHVlOwp2YXIgX19wdWJsaWNGaWVsZCA9IChvYmosIGtleSwgdmFsdWUpID0+IHsKICBfX2RlZk5vcm1hbFByb3Aob2JqLCB0eXBlb2Yga2V5ICE9PSAic3ltYm9sIiA/IGtleSArICIiIDoga2V5LCB2YWx1ZSk7CiAgcmV0dXJuIHZhbHVlOwp9OwooZnVuY3Rpb24oKSB7CiAgInVzZSBzdHJpY3QiOwogIHZhciBjb21tb25qc0dsb2JhbCA9IHR5cGVvZiBnbG9iYWxUaGlzICE9PSAidW5kZWZpbmVkIiA/IGdsb2JhbFRoaXMgOiB0eXBlb2Ygd2luZG93ICE9PSAidW5kZWZpbmVkIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09ICJ1bmRlZmluZWQiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09ICJ1bmRlZmluZWQiID8gc2VsZiA6IHt9OwogIGZ1bmN0aW9uIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzKHgpIHsKICAgIHJldHVybiB4ICYmIHguX19lc01vZHVsZSAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoeCwgImRlZmF1bHQiKSA/IHhbImRlZmF1bHQiXSA6IHg7CiAgfQogIGZ1bmN0aW9uIGNvbW1vbmpzUmVxdWlyZShwYXRoKSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvdWxkIG5vdCBkeW5hbWljYWxseSByZXF1aXJlICInICsgcGF0aCArICciLiBQbGVhc2UgY29uZmlndXJlIHRoZSBkeW5hbWljUmVxdWlyZVRhcmdldHMgb3IvYW5kIGlnbm9yZUR5bmFtaWNSZXF1aXJlcyBvcHRpb24gb2YgQHJvbGx1cC9wbHVnaW4tY29tbW9uanMgYXBwcm9wcmlhdGVseSBmb3IgdGhpcyByZXF1aXJlIGNhbGwgdG8gd29yay4nKTsKICB9CiAgdmFyIGpzemlwX21pbiA9IHsgZXhwb3J0czoge30gfTsKICAvKiEKICAKICAJSlNaaXAgdjMuMTAuMSAtIEEgSmF2YVNjcmlwdCBjbGFzcyBmb3IgZ2VuZXJhdGluZyBhbmQgcmVhZGluZyB6aXAgZmlsZXMKICAJPGh0dHA6Ly9zdHVhcnRrLmNvbS9qc3ppcD4KICAKICAJKGMpIDIwMDktMjAxNiBTdHVhcnQgS25pZ2h0bGV5IDxzdHVhcnQgW2F0XSBzdHVhcnRrLmNvbT4KICAJRHVhbCBsaWNlbmNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2Ugb3IgR1BMdjMuIFNlZSBodHRwczovL3Jhdy5naXRodWIuY29tL1N0dWsvanN6aXAvbWFpbi9MSUNFTlNFLm1hcmtkb3duLgogIAogIAlKU1ppcCB1c2VzIHRoZSBsaWJyYXJ5IHBha28gcmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIDoKICAJaHR0cHM6Ly9naXRodWIuY29tL25vZGVjYS9wYWtvL2Jsb2IvbWFpbi9MSUNFTlNFCiAgCSovCiAgKGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cykgewogICAgIWZ1bmN0aW9uKGUpIHsKICAgICAgbW9kdWxlLmV4cG9ydHMgPSBlKCk7CiAgICB9KGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gZnVuY3Rpb24gcyhhLCBvLCBoKSB7CiAgICAgICAgZnVuY3Rpb24gdShyLCBlMikgewogICAgICAgICAgaWYgKCFvW3JdKSB7CiAgICAgICAgICAgIGlmICghYVtyXSkgewogICAgICAgICAgICAgIHZhciB0ID0gImZ1bmN0aW9uIiA9PSB0eXBlb2YgY29tbW9uanNSZXF1aXJlICYmIGNvbW1vbmpzUmVxdWlyZTsKICAgICAgICAgICAgICBpZiAoIWUyICYmIHQpCiAgICAgICAgICAgICAgICByZXR1cm4gdChyLCB0cnVlKTsKICAgICAgICAgICAgICBpZiAobCkKICAgICAgICAgICAgICAgIHJldHVybiBsKHIsIHRydWUpOwogICAgICAgICAgICAgIHZhciBuID0gbmV3IEVycm9yKCJDYW5ub3QgZmluZCBtb2R1bGUgJyIgKyByICsgIiciKTsKICAgICAgICAgICAgICB0aHJvdyBuLmNvZGUgPSAiTU9EVUxFX05PVF9GT1VORCIsIG47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGkgPSBvW3JdID0geyBleHBvcnRzOiB7fSB9OwogICAgICAgICAgICBhW3JdWzBdLmNhbGwoaS5leHBvcnRzLCBmdW5jdGlvbihlMykgewogICAgICAgICAgICAgIHZhciB0MiA9IGFbcl1bMV1bZTNdOwogICAgICAgICAgICAgIHJldHVybiB1KHQyIHx8IGUzKTsKICAgICAgICAgICAgfSwgaSwgaS5leHBvcnRzLCBzLCBhLCBvLCBoKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBvW3JdLmV4cG9ydHM7CiAgICAgICAgfQogICAgICAgIGZvciAodmFyIGwgPSAiZnVuY3Rpb24iID09IHR5cGVvZiBjb21tb25qc1JlcXVpcmUgJiYgY29tbW9uanNSZXF1aXJlLCBlID0gMDsgZSA8IGgubGVuZ3RoOyBlKyspCiAgICAgICAgICB1KGhbZV0pOwogICAgICAgIHJldHVybiB1OwogICAgICB9KHsgMTogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgZCA9IGUoIi4vdXRpbHMiKSwgYyA9IGUoIi4vc3VwcG9ydCIpLCBwID0gIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky89IjsKICAgICAgICByLmVuY29kZSA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICBmb3IgKHZhciB0MiwgcjIsIG4sIGksIHMsIGEsIG8sIGggPSBbXSwgdSA9IDAsIGwgPSBlMi5sZW5ndGgsIGYgPSBsLCBjMiA9ICJzdHJpbmciICE9PSBkLmdldFR5cGVPZihlMik7IHUgPCBlMi5sZW5ndGg7ICkKICAgICAgICAgICAgZiA9IGwgLSB1LCBuID0gYzIgPyAodDIgPSBlMlt1KytdLCByMiA9IHUgPCBsID8gZTJbdSsrXSA6IDAsIHUgPCBsID8gZTJbdSsrXSA6IDApIDogKHQyID0gZTIuY2hhckNvZGVBdCh1KyspLCByMiA9IHUgPCBsID8gZTIuY2hhckNvZGVBdCh1KyspIDogMCwgdSA8IGwgPyBlMi5jaGFyQ29kZUF0KHUrKykgOiAwKSwgaSA9IHQyID4+IDIsIHMgPSAoMyAmIHQyKSA8PCA0IHwgcjIgPj4gNCwgYSA9IDEgPCBmID8gKDE1ICYgcjIpIDw8IDIgfCBuID4+IDYgOiA2NCwgbyA9IDIgPCBmID8gNjMgJiBuIDogNjQsIGgucHVzaChwLmNoYXJBdChpKSArIHAuY2hhckF0KHMpICsgcC5jaGFyQXQoYSkgKyBwLmNoYXJBdChvKSk7CiAgICAgICAgICByZXR1cm4gaC5qb2luKCIiKTsKICAgICAgICB9LCByLmRlY29kZSA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB2YXIgdDIsIHIyLCBuLCBpLCBzLCBhLCBvID0gMCwgaCA9IDAsIHUgPSAiZGF0YToiOwogICAgICAgICAgaWYgKGUyLnN1YnN0cigwLCB1Lmxlbmd0aCkgPT09IHUpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiSW52YWxpZCBiYXNlNjQgaW5wdXQsIGl0IGxvb2tzIGxpa2UgYSBkYXRhIHVybC4iKTsKICAgICAgICAgIHZhciBsLCBmID0gMyAqIChlMiA9IGUyLnJlcGxhY2UoL1teQS1aYS16MC05Ky89XS9nLCAiIikpLmxlbmd0aCAvIDQ7CiAgICAgICAgICBpZiAoZTIuY2hhckF0KGUyLmxlbmd0aCAtIDEpID09PSBwLmNoYXJBdCg2NCkgJiYgZi0tLCBlMi5jaGFyQXQoZTIubGVuZ3RoIC0gMikgPT09IHAuY2hhckF0KDY0KSAmJiBmLS0sIGYgJSAxICE9IDApCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiSW52YWxpZCBiYXNlNjQgaW5wdXQsIGJhZCBjb250ZW50IGxlbmd0aC4iKTsKICAgICAgICAgIGZvciAobCA9IGMudWludDhhcnJheSA/IG5ldyBVaW50OEFycmF5KDAgfCBmKSA6IG5ldyBBcnJheSgwIHwgZik7IG8gPCBlMi5sZW5ndGg7ICkKICAgICAgICAgICAgdDIgPSBwLmluZGV4T2YoZTIuY2hhckF0KG8rKykpIDw8IDIgfCAoaSA9IHAuaW5kZXhPZihlMi5jaGFyQXQobysrKSkpID4+IDQsIHIyID0gKDE1ICYgaSkgPDwgNCB8IChzID0gcC5pbmRleE9mKGUyLmNoYXJBdChvKyspKSkgPj4gMiwgbiA9ICgzICYgcykgPDwgNiB8IChhID0gcC5pbmRleE9mKGUyLmNoYXJBdChvKyspKSksIGxbaCsrXSA9IHQyLCA2NCAhPT0gcyAmJiAobFtoKytdID0gcjIpLCA2NCAhPT0gYSAmJiAobFtoKytdID0gbik7CiAgICAgICAgICByZXR1cm4gbDsKICAgICAgICB9OwogICAgICB9LCB7ICIuL3N1cHBvcnQiOiAzMCwgIi4vdXRpbHMiOiAzMiB9XSwgMjogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgbiA9IGUoIi4vZXh0ZXJuYWwiKSwgaSA9IGUoIi4vc3RyZWFtL0RhdGFXb3JrZXIiKSwgcyA9IGUoIi4vc3RyZWFtL0NyYzMyUHJvYmUiKSwgYSA9IGUoIi4vc3RyZWFtL0RhdGFMZW5ndGhQcm9iZSIpOwogICAgICAgIGZ1bmN0aW9uIG8oZTIsIHQyLCByMiwgbjIsIGkyKSB7CiAgICAgICAgICB0aGlzLmNvbXByZXNzZWRTaXplID0gZTIsIHRoaXMudW5jb21wcmVzc2VkU2l6ZSA9IHQyLCB0aGlzLmNyYzMyID0gcjIsIHRoaXMuY29tcHJlc3Npb24gPSBuMiwgdGhpcy5jb21wcmVzc2VkQ29udGVudCA9IGkyOwogICAgICAgIH0KICAgICAgICBvLnByb3RvdHlwZSA9IHsgZ2V0Q29udGVudFdvcmtlcjogZnVuY3Rpb24oKSB7CiAgICAgICAgICB2YXIgZTIgPSBuZXcgaShuLlByb21pc2UucmVzb2x2ZSh0aGlzLmNvbXByZXNzZWRDb250ZW50KSkucGlwZSh0aGlzLmNvbXByZXNzaW9uLnVuY29tcHJlc3NXb3JrZXIoKSkucGlwZShuZXcgYSgiZGF0YV9sZW5ndGgiKSksIHQyID0gdGhpczsKICAgICAgICAgIHJldHVybiBlMi5vbigiZW5kIiwgZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIGlmICh0aGlzLnN0cmVhbUluZm8uZGF0YV9sZW5ndGggIT09IHQyLnVuY29tcHJlc3NlZFNpemUpCiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJCdWcgOiB1bmNvbXByZXNzZWQgZGF0YSBzaXplIG1pc21hdGNoIik7CiAgICAgICAgICB9KSwgZTI7CiAgICAgICAgfSwgZ2V0Q29tcHJlc3NlZFdvcmtlcjogZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gbmV3IGkobi5Qcm9taXNlLnJlc29sdmUodGhpcy5jb21wcmVzc2VkQ29udGVudCkpLndpdGhTdHJlYW1JbmZvKCJjb21wcmVzc2VkU2l6ZSIsIHRoaXMuY29tcHJlc3NlZFNpemUpLndpdGhTdHJlYW1JbmZvKCJ1bmNvbXByZXNzZWRTaXplIiwgdGhpcy51bmNvbXByZXNzZWRTaXplKS53aXRoU3RyZWFtSW5mbygiY3JjMzIiLCB0aGlzLmNyYzMyKS53aXRoU3RyZWFtSW5mbygiY29tcHJlc3Npb24iLCB0aGlzLmNvbXByZXNzaW9uKTsKICAgICAgICB9IH0sIG8uY3JlYXRlV29ya2VyRnJvbSA9IGZ1bmN0aW9uKGUyLCB0MiwgcjIpIHsKICAgICAgICAgIHJldHVybiBlMi5waXBlKG5ldyBzKCkpLnBpcGUobmV3IGEoInVuY29tcHJlc3NlZFNpemUiKSkucGlwZSh0Mi5jb21wcmVzc1dvcmtlcihyMikpLnBpcGUobmV3IGEoImNvbXByZXNzZWRTaXplIikpLndpdGhTdHJlYW1JbmZvKCJjb21wcmVzc2lvbiIsIHQyKTsKICAgICAgICB9LCB0LmV4cG9ydHMgPSBvOwogICAgICB9LCB7ICIuL2V4dGVybmFsIjogNiwgIi4vc3RyZWFtL0NyYzMyUHJvYmUiOiAyNSwgIi4vc3RyZWFtL0RhdGFMZW5ndGhQcm9iZSI6IDI2LCAiLi9zdHJlYW0vRGF0YVdvcmtlciI6IDI3IH1dLCAzOiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBuID0gZSgiLi9zdHJlYW0vR2VuZXJpY1dvcmtlciIpOwogICAgICAgIHIuU1RPUkUgPSB7IG1hZ2ljOiAiXDBcMCIsIGNvbXByZXNzV29ya2VyOiBmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiBuZXcgbigiU1RPUkUgY29tcHJlc3Npb24iKTsKICAgICAgICB9LCB1bmNvbXByZXNzV29ya2VyOiBmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiBuZXcgbigiU1RPUkUgZGVjb21wcmVzc2lvbiIpOwogICAgICAgIH0gfSwgci5ERUZMQVRFID0gZSgiLi9mbGF0ZSIpOwogICAgICB9LCB7ICIuL2ZsYXRlIjogNywgIi4vc3RyZWFtL0dlbmVyaWNXb3JrZXIiOiAyOCB9XSwgNDogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgbiA9IGUoIi4vdXRpbHMiKTsKICAgICAgICB2YXIgbyA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgZm9yICh2YXIgZTIsIHQyID0gW10sIHIyID0gMDsgcjIgPCAyNTY7IHIyKyspIHsKICAgICAgICAgICAgZTIgPSByMjsKICAgICAgICAgICAgZm9yICh2YXIgbjIgPSAwOyBuMiA8IDg7IG4yKyspCiAgICAgICAgICAgICAgZTIgPSAxICYgZTIgPyAzOTg4MjkyMzg0IF4gZTIgPj4+IDEgOiBlMiA+Pj4gMTsKICAgICAgICAgICAgdDJbcjJdID0gZTI7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdDI7CiAgICAgICAgfSgpOwogICAgICAgIHQuZXhwb3J0cyA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgcmV0dXJuIHZvaWQgMCAhPT0gZTIgJiYgZTIubGVuZ3RoID8gInN0cmluZyIgIT09IG4uZ2V0VHlwZU9mKGUyKSA/IGZ1bmN0aW9uKGUzLCB0MywgcjIsIG4yKSB7CiAgICAgICAgICAgIHZhciBpID0gbywgcyA9IG4yICsgcjI7CiAgICAgICAgICAgIGUzIF49IC0xOwogICAgICAgICAgICBmb3IgKHZhciBhID0gbjI7IGEgPCBzOyBhKyspCiAgICAgICAgICAgICAgZTMgPSBlMyA+Pj4gOCBeIGlbMjU1ICYgKGUzIF4gdDNbYV0pXTsKICAgICAgICAgICAgcmV0dXJuIC0xIF4gZTM7CiAgICAgICAgICB9KDAgfCB0MiwgZTIsIGUyLmxlbmd0aCwgMCkgOiBmdW5jdGlvbihlMywgdDMsIHIyLCBuMikgewogICAgICAgICAgICB2YXIgaSA9IG8sIHMgPSBuMiArIHIyOwogICAgICAgICAgICBlMyBePSAtMTsKICAgICAgICAgICAgZm9yICh2YXIgYSA9IG4yOyBhIDwgczsgYSsrKQogICAgICAgICAgICAgIGUzID0gZTMgPj4+IDggXiBpWzI1NSAmIChlMyBeIHQzLmNoYXJDb2RlQXQoYSkpXTsKICAgICAgICAgICAgcmV0dXJuIC0xIF4gZTM7CiAgICAgICAgICB9KDAgfCB0MiwgZTIsIGUyLmxlbmd0aCwgMCkgOiAwOwogICAgICAgIH07CiAgICAgIH0sIHsgIi4vdXRpbHMiOiAzMiB9XSwgNTogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICByLmJhc2U2NCA9IGZhbHNlLCByLmJpbmFyeSA9IGZhbHNlLCByLmRpciA9IGZhbHNlLCByLmNyZWF0ZUZvbGRlcnMgPSB0cnVlLCByLmRhdGUgPSBudWxsLCByLmNvbXByZXNzaW9uID0gbnVsbCwgci5jb21wcmVzc2lvbk9wdGlvbnMgPSBudWxsLCByLmNvbW1lbnQgPSBudWxsLCByLnVuaXhQZXJtaXNzaW9ucyA9IG51bGwsIHIuZG9zUGVybWlzc2lvbnMgPSBudWxsOwogICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIG4gPSBudWxsOwogICAgICAgIG4gPSAidW5kZWZpbmVkIiAhPSB0eXBlb2YgUHJvbWlzZSA/IFByb21pc2UgOiBlKCJsaWUiKSwgdC5leHBvcnRzID0geyBQcm9taXNlOiBuIH07CiAgICAgIH0sIHsgbGllOiAzNyB9XSwgNzogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgbiA9ICJ1bmRlZmluZWQiICE9IHR5cGVvZiBVaW50OEFycmF5ICYmICJ1bmRlZmluZWQiICE9IHR5cGVvZiBVaW50MTZBcnJheSAmJiAidW5kZWZpbmVkIiAhPSB0eXBlb2YgVWludDMyQXJyYXksIGkgPSBlKCJwYWtvIiksIHMgPSBlKCIuL3V0aWxzIiksIGEgPSBlKCIuL3N0cmVhbS9HZW5lcmljV29ya2VyIiksIG8gPSBuID8gInVpbnQ4YXJyYXkiIDogImFycmF5IjsKICAgICAgICBmdW5jdGlvbiBoKGUyLCB0MikgewogICAgICAgICAgYS5jYWxsKHRoaXMsICJGbGF0ZVdvcmtlci8iICsgZTIpLCB0aGlzLl9wYWtvID0gbnVsbCwgdGhpcy5fcGFrb0FjdGlvbiA9IGUyLCB0aGlzLl9wYWtvT3B0aW9ucyA9IHQyLCB0aGlzLm1ldGEgPSB7fTsKICAgICAgICB9CiAgICAgICAgci5tYWdpYyA9ICJcYlwwIiwgcy5pbmhlcml0cyhoLCBhKSwgaC5wcm90b3R5cGUucHJvY2Vzc0NodW5rID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHRoaXMubWV0YSA9IGUyLm1ldGEsIG51bGwgPT09IHRoaXMuX3Bha28gJiYgdGhpcy5fY3JlYXRlUGFrbygpLCB0aGlzLl9wYWtvLnB1c2gocy50cmFuc2Zvcm1UbyhvLCBlMi5kYXRhKSwgZmFsc2UpOwogICAgICAgIH0sIGgucHJvdG90eXBlLmZsdXNoID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICBhLnByb3RvdHlwZS5mbHVzaC5jYWxsKHRoaXMpLCBudWxsID09PSB0aGlzLl9wYWtvICYmIHRoaXMuX2NyZWF0ZVBha28oKSwgdGhpcy5fcGFrby5wdXNoKFtdLCB0cnVlKTsKICAgICAgICB9LCBoLnByb3RvdHlwZS5jbGVhblVwID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICBhLnByb3RvdHlwZS5jbGVhblVwLmNhbGwodGhpcyksIHRoaXMuX3Bha28gPSBudWxsOwogICAgICAgIH0sIGgucHJvdG90eXBlLl9jcmVhdGVQYWtvID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLl9wYWtvID0gbmV3IGlbdGhpcy5fcGFrb0FjdGlvbl0oeyByYXc6IHRydWUsIGxldmVsOiB0aGlzLl9wYWtvT3B0aW9ucy5sZXZlbCB8fCAtMSB9KTsKICAgICAgICAgIHZhciB0MiA9IHRoaXM7CiAgICAgICAgICB0aGlzLl9wYWtvLm9uRGF0YSA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICAgIHQyLnB1c2goeyBkYXRhOiBlMiwgbWV0YTogdDIubWV0YSB9KTsKICAgICAgICAgIH07CiAgICAgICAgfSwgci5jb21wcmVzc1dvcmtlciA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICByZXR1cm4gbmV3IGgoIkRlZmxhdGUiLCBlMik7CiAgICAgICAgfSwgci51bmNvbXByZXNzV29ya2VyID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gbmV3IGgoIkluZmxhdGUiLCB7fSk7CiAgICAgICAgfTsKICAgICAgfSwgeyAiLi9zdHJlYW0vR2VuZXJpY1dvcmtlciI6IDI4LCAiLi91dGlscyI6IDMyLCBwYWtvOiAzOCB9XSwgODogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICBmdW5jdGlvbiBBKGUyLCB0MikgewogICAgICAgICAgdmFyIHIyLCBuMiA9ICIiOwogICAgICAgICAgZm9yIChyMiA9IDA7IHIyIDwgdDI7IHIyKyspCiAgICAgICAgICAgIG4yICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMjU1ICYgZTIpLCBlMiA+Pj49IDg7CiAgICAgICAgICByZXR1cm4gbjI7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIG4oZTIsIHQyLCByMiwgbjIsIGkyLCBzMikgewogICAgICAgICAgdmFyIGEsIG8sIGggPSBlMi5maWxlLCB1ID0gZTIuY29tcHJlc3Npb24sIGwgPSBzMiAhPT0gTy51dGY4ZW5jb2RlLCBmID0gSS50cmFuc2Zvcm1Ubygic3RyaW5nIiwgczIoaC5uYW1lKSksIGMgPSBJLnRyYW5zZm9ybVRvKCJzdHJpbmciLCBPLnV0ZjhlbmNvZGUoaC5uYW1lKSksIGQgPSBoLmNvbW1lbnQsIHAgPSBJLnRyYW5zZm9ybVRvKCJzdHJpbmciLCBzMihkKSksIG0gPSBJLnRyYW5zZm9ybVRvKCJzdHJpbmciLCBPLnV0ZjhlbmNvZGUoZCkpLCBfID0gYy5sZW5ndGggIT09IGgubmFtZS5sZW5ndGgsIGcgPSBtLmxlbmd0aCAhPT0gZC5sZW5ndGgsIGIgPSAiIiwgdiA9ICIiLCB5ID0gIiIsIHcgPSBoLmRpciwgayA9IGguZGF0ZSwgeCA9IHsgY3JjMzI6IDAsIGNvbXByZXNzZWRTaXplOiAwLCB1bmNvbXByZXNzZWRTaXplOiAwIH07CiAgICAgICAgICB0MiAmJiAhcjIgfHwgKHguY3JjMzIgPSBlMi5jcmMzMiwgeC5jb21wcmVzc2VkU2l6ZSA9IGUyLmNvbXByZXNzZWRTaXplLCB4LnVuY29tcHJlc3NlZFNpemUgPSBlMi51bmNvbXByZXNzZWRTaXplKTsKICAgICAgICAgIHZhciBTID0gMDsKICAgICAgICAgIHQyICYmIChTIHw9IDgpLCBsIHx8ICFfICYmICFnIHx8IChTIHw9IDIwNDgpOwogICAgICAgICAgdmFyIHogPSAwLCBDID0gMDsKICAgICAgICAgIHcgJiYgKHogfD0gMTYpLCAiVU5JWCIgPT09IGkyID8gKEMgPSA3OTgsIHogfD0gZnVuY3Rpb24oZTMsIHQzKSB7CiAgICAgICAgICAgIHZhciByMyA9IGUzOwogICAgICAgICAgICByZXR1cm4gZTMgfHwgKHIzID0gdDMgPyAxNjg5MyA6IDMzMjA0KSwgKDY1NTM1ICYgcjMpIDw8IDE2OwogICAgICAgICAgfShoLnVuaXhQZXJtaXNzaW9ucywgdykpIDogKEMgPSAyMCwgeiB8PSBmdW5jdGlvbihlMykgewogICAgICAgICAgICByZXR1cm4gNjMgJiAoZTMgfHwgMCk7CiAgICAgICAgICB9KGguZG9zUGVybWlzc2lvbnMpKSwgYSA9IGsuZ2V0VVRDSG91cnMoKSwgYSA8PD0gNiwgYSB8PSBrLmdldFVUQ01pbnV0ZXMoKSwgYSA8PD0gNSwgYSB8PSBrLmdldFVUQ1NlY29uZHMoKSAvIDIsIG8gPSBrLmdldFVUQ0Z1bGxZZWFyKCkgLSAxOTgwLCBvIDw8PSA0LCBvIHw9IGsuZ2V0VVRDTW9udGgoKSArIDEsIG8gPDw9IDUsIG8gfD0gay5nZXRVVENEYXRlKCksIF8gJiYgKHYgPSBBKDEsIDEpICsgQShCKGYpLCA0KSArIGMsIGIgKz0gInVwIiArIEEodi5sZW5ndGgsIDIpICsgdiksIGcgJiYgKHkgPSBBKDEsIDEpICsgQShCKHApLCA0KSArIG0sIGIgKz0gInVjIiArIEEoeS5sZW5ndGgsIDIpICsgeSk7CiAgICAgICAgICB2YXIgRSA9ICIiOwogICAgICAgICAgcmV0dXJuIEUgKz0gIlxuXDAiLCBFICs9IEEoUywgMiksIEUgKz0gdS5tYWdpYywgRSArPSBBKGEsIDIpLCBFICs9IEEobywgMiksIEUgKz0gQSh4LmNyYzMyLCA0KSwgRSArPSBBKHguY29tcHJlc3NlZFNpemUsIDQpLCBFICs9IEEoeC51bmNvbXByZXNzZWRTaXplLCA0KSwgRSArPSBBKGYubGVuZ3RoLCAyKSwgRSArPSBBKGIubGVuZ3RoLCAyKSwgeyBmaWxlUmVjb3JkOiBSLkxPQ0FMX0ZJTEVfSEVBREVSICsgRSArIGYgKyBiLCBkaXJSZWNvcmQ6IFIuQ0VOVFJBTF9GSUxFX0hFQURFUiArIEEoQywgMikgKyBFICsgQShwLmxlbmd0aCwgMikgKyAiXDBcMFwwXDAiICsgQSh6LCA0KSArIEEobjIsIDQpICsgZiArIGIgKyBwIH07CiAgICAgICAgfQogICAgICAgIHZhciBJID0gZSgiLi4vdXRpbHMiKSwgaSA9IGUoIi4uL3N0cmVhbS9HZW5lcmljV29ya2VyIiksIE8gPSBlKCIuLi91dGY4IiksIEIgPSBlKCIuLi9jcmMzMiIpLCBSID0gZSgiLi4vc2lnbmF0dXJlIik7CiAgICAgICAgZnVuY3Rpb24gcyhlMiwgdDIsIHIyLCBuMikgewogICAgICAgICAgaS5jYWxsKHRoaXMsICJaaXBGaWxlV29ya2VyIiksIHRoaXMuYnl0ZXNXcml0dGVuID0gMCwgdGhpcy56aXBDb21tZW50ID0gdDIsIHRoaXMuemlwUGxhdGZvcm0gPSByMiwgdGhpcy5lbmNvZGVGaWxlTmFtZSA9IG4yLCB0aGlzLnN0cmVhbUZpbGVzID0gZTIsIHRoaXMuYWNjdW11bGF0ZSA9IGZhbHNlLCB0aGlzLmNvbnRlbnRCdWZmZXIgPSBbXSwgdGhpcy5kaXJSZWNvcmRzID0gW10sIHRoaXMuY3VycmVudFNvdXJjZU9mZnNldCA9IDAsIHRoaXMuZW50cmllc0NvdW50ID0gMCwgdGhpcy5jdXJyZW50RmlsZSA9IG51bGwsIHRoaXMuX3NvdXJjZXMgPSBbXTsKICAgICAgICB9CiAgICAgICAgSS5pbmhlcml0cyhzLCBpKSwgcy5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB2YXIgdDIgPSBlMi5tZXRhLnBlcmNlbnQgfHwgMCwgcjIgPSB0aGlzLmVudHJpZXNDb3VudCwgbjIgPSB0aGlzLl9zb3VyY2VzLmxlbmd0aDsKICAgICAgICAgIHRoaXMuYWNjdW11bGF0ZSA/IHRoaXMuY29udGVudEJ1ZmZlci5wdXNoKGUyKSA6ICh0aGlzLmJ5dGVzV3JpdHRlbiArPSBlMi5kYXRhLmxlbmd0aCwgaS5wcm90b3R5cGUucHVzaC5jYWxsKHRoaXMsIHsgZGF0YTogZTIuZGF0YSwgbWV0YTogeyBjdXJyZW50RmlsZTogdGhpcy5jdXJyZW50RmlsZSwgcGVyY2VudDogcjIgPyAodDIgKyAxMDAgKiAocjIgLSBuMiAtIDEpKSAvIHIyIDogMTAwIH0gfSkpOwogICAgICAgIH0sIHMucHJvdG90eXBlLm9wZW5lZFNvdXJjZSA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB0aGlzLmN1cnJlbnRTb3VyY2VPZmZzZXQgPSB0aGlzLmJ5dGVzV3JpdHRlbiwgdGhpcy5jdXJyZW50RmlsZSA9IGUyLmZpbGUubmFtZTsKICAgICAgICAgIHZhciB0MiA9IHRoaXMuc3RyZWFtRmlsZXMgJiYgIWUyLmZpbGUuZGlyOwogICAgICAgICAgaWYgKHQyKSB7CiAgICAgICAgICAgIHZhciByMiA9IG4oZTIsIHQyLCBmYWxzZSwgdGhpcy5jdXJyZW50U291cmNlT2Zmc2V0LCB0aGlzLnppcFBsYXRmb3JtLCB0aGlzLmVuY29kZUZpbGVOYW1lKTsKICAgICAgICAgICAgdGhpcy5wdXNoKHsgZGF0YTogcjIuZmlsZVJlY29yZCwgbWV0YTogeyBwZXJjZW50OiAwIH0gfSk7CiAgICAgICAgICB9IGVsc2UKICAgICAgICAgICAgdGhpcy5hY2N1bXVsYXRlID0gdHJ1ZTsKICAgICAgICB9LCBzLnByb3RvdHlwZS5jbG9zZWRTb3VyY2UgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgdGhpcy5hY2N1bXVsYXRlID0gZmFsc2U7CiAgICAgICAgICB2YXIgdDIgPSB0aGlzLnN0cmVhbUZpbGVzICYmICFlMi5maWxlLmRpciwgcjIgPSBuKGUyLCB0MiwgdHJ1ZSwgdGhpcy5jdXJyZW50U291cmNlT2Zmc2V0LCB0aGlzLnppcFBsYXRmb3JtLCB0aGlzLmVuY29kZUZpbGVOYW1lKTsKICAgICAgICAgIGlmICh0aGlzLmRpclJlY29yZHMucHVzaChyMi5kaXJSZWNvcmQpLCB0MikKICAgICAgICAgICAgdGhpcy5wdXNoKHsgZGF0YTogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICByZXR1cm4gUi5EQVRBX0RFU0NSSVBUT1IgKyBBKGUzLmNyYzMyLCA0KSArIEEoZTMuY29tcHJlc3NlZFNpemUsIDQpICsgQShlMy51bmNvbXByZXNzZWRTaXplLCA0KTsKICAgICAgICAgICAgfShlMiksIG1ldGE6IHsgcGVyY2VudDogMTAwIH0gfSk7CiAgICAgICAgICBlbHNlCiAgICAgICAgICAgIGZvciAodGhpcy5wdXNoKHsgZGF0YTogcjIuZmlsZVJlY29yZCwgbWV0YTogeyBwZXJjZW50OiAwIH0gfSk7IHRoaXMuY29udGVudEJ1ZmZlci5sZW5ndGg7ICkKICAgICAgICAgICAgICB0aGlzLnB1c2godGhpcy5jb250ZW50QnVmZmVyLnNoaWZ0KCkpOwogICAgICAgICAgdGhpcy5jdXJyZW50RmlsZSA9IG51bGw7CiAgICAgICAgfSwgcy5wcm90b3R5cGUuZmx1c2ggPSBmdW5jdGlvbigpIHsKICAgICAgICAgIGZvciAodmFyIGUyID0gdGhpcy5ieXRlc1dyaXR0ZW4sIHQyID0gMDsgdDIgPCB0aGlzLmRpclJlY29yZHMubGVuZ3RoOyB0MisrKQogICAgICAgICAgICB0aGlzLnB1c2goeyBkYXRhOiB0aGlzLmRpclJlY29yZHNbdDJdLCBtZXRhOiB7IHBlcmNlbnQ6IDEwMCB9IH0pOwogICAgICAgICAgdmFyIHIyID0gdGhpcy5ieXRlc1dyaXR0ZW4gLSBlMiwgbjIgPSBmdW5jdGlvbihlMywgdDMsIHIzLCBuMywgaTIpIHsKICAgICAgICAgICAgdmFyIHMyID0gSS50cmFuc2Zvcm1Ubygic3RyaW5nIiwgaTIobjMpKTsKICAgICAgICAgICAgcmV0dXJuIFIuQ0VOVFJBTF9ESVJFQ1RPUllfRU5EICsgIlwwXDBcMFwwIiArIEEoZTMsIDIpICsgQShlMywgMikgKyBBKHQzLCA0KSArIEEocjMsIDQpICsgQShzMi5sZW5ndGgsIDIpICsgczI7CiAgICAgICAgICB9KHRoaXMuZGlyUmVjb3Jkcy5sZW5ndGgsIHIyLCBlMiwgdGhpcy56aXBDb21tZW50LCB0aGlzLmVuY29kZUZpbGVOYW1lKTsKICAgICAgICAgIHRoaXMucHVzaCh7IGRhdGE6IG4yLCBtZXRhOiB7IHBlcmNlbnQ6IDEwMCB9IH0pOwogICAgICAgIH0sIHMucHJvdG90eXBlLnByZXBhcmVOZXh0U291cmNlID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLnByZXZpb3VzID0gdGhpcy5fc291cmNlcy5zaGlmdCgpLCB0aGlzLm9wZW5lZFNvdXJjZSh0aGlzLnByZXZpb3VzLnN0cmVhbUluZm8pLCB0aGlzLmlzUGF1c2VkID8gdGhpcy5wcmV2aW91cy5wYXVzZSgpIDogdGhpcy5wcmV2aW91cy5yZXN1bWUoKTsKICAgICAgICB9LCBzLnByb3RvdHlwZS5yZWdpc3RlclByZXZpb3VzID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHRoaXMuX3NvdXJjZXMucHVzaChlMik7CiAgICAgICAgICB2YXIgdDIgPSB0aGlzOwogICAgICAgICAgcmV0dXJuIGUyLm9uKCJkYXRhIiwgZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgdDIucHJvY2Vzc0NodW5rKGUzKTsKICAgICAgICAgIH0pLCBlMi5vbigiZW5kIiwgZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHQyLmNsb3NlZFNvdXJjZSh0Mi5wcmV2aW91cy5zdHJlYW1JbmZvKSwgdDIuX3NvdXJjZXMubGVuZ3RoID8gdDIucHJlcGFyZU5leHRTb3VyY2UoKSA6IHQyLmVuZCgpOwogICAgICAgICAgfSksIGUyLm9uKCJlcnJvciIsIGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIHQyLmVycm9yKGUzKTsKICAgICAgICAgIH0pLCB0aGlzOwogICAgICAgIH0sIHMucHJvdG90eXBlLnJlc3VtZSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgcmV0dXJuICEhaS5wcm90b3R5cGUucmVzdW1lLmNhbGwodGhpcykgJiYgKCF0aGlzLnByZXZpb3VzICYmIHRoaXMuX3NvdXJjZXMubGVuZ3RoID8gKHRoaXMucHJlcGFyZU5leHRTb3VyY2UoKSwgdHJ1ZSkgOiB0aGlzLnByZXZpb3VzIHx8IHRoaXMuX3NvdXJjZXMubGVuZ3RoIHx8IHRoaXMuZ2VuZXJhdGVkRXJyb3IgPyB2b2lkIDAgOiAodGhpcy5lbmQoKSwgdHJ1ZSkpOwogICAgICAgIH0sIHMucHJvdG90eXBlLmVycm9yID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHZhciB0MiA9IHRoaXMuX3NvdXJjZXM7CiAgICAgICAgICBpZiAoIWkucHJvdG90eXBlLmVycm9yLmNhbGwodGhpcywgZTIpKQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICBmb3IgKHZhciByMiA9IDA7IHIyIDwgdDIubGVuZ3RoOyByMisrKQogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIHQyW3IyXS5lcnJvcihlMik7CiAgICAgICAgICAgIH0gY2F0Y2ggKGUzKSB7CiAgICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0sIHMucHJvdG90eXBlLmxvY2sgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIGkucHJvdG90eXBlLmxvY2suY2FsbCh0aGlzKTsKICAgICAgICAgIGZvciAodmFyIGUyID0gdGhpcy5fc291cmNlcywgdDIgPSAwOyB0MiA8IGUyLmxlbmd0aDsgdDIrKykKICAgICAgICAgICAgZTJbdDJdLmxvY2soKTsKICAgICAgICB9LCB0LmV4cG9ydHMgPSBzOwogICAgICB9LCB7ICIuLi9jcmMzMiI6IDQsICIuLi9zaWduYXR1cmUiOiAyMywgIi4uL3N0cmVhbS9HZW5lcmljV29ya2VyIjogMjgsICIuLi91dGY4IjogMzEsICIuLi91dGlscyI6IDMyIH1dLCA5OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciB1ID0gZSgiLi4vY29tcHJlc3Npb25zIiksIG4gPSBlKCIuL1ppcEZpbGVXb3JrZXIiKTsKICAgICAgICByLmdlbmVyYXRlV29ya2VyID0gZnVuY3Rpb24oZTIsIGEsIHQyKSB7CiAgICAgICAgICB2YXIgbyA9IG5ldyBuKGEuc3RyZWFtRmlsZXMsIHQyLCBhLnBsYXRmb3JtLCBhLmVuY29kZUZpbGVOYW1lKSwgaCA9IDA7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBlMi5mb3JFYWNoKGZ1bmN0aW9uKGUzLCB0MykgewogICAgICAgICAgICAgIGgrKzsKICAgICAgICAgICAgICB2YXIgcjIgPSBmdW5jdGlvbihlNCwgdDQpIHsKICAgICAgICAgICAgICAgIHZhciByMyA9IGU0IHx8IHQ0LCBuMyA9IHVbcjNdOwogICAgICAgICAgICAgICAgaWYgKCFuMykKICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHIzICsgIiBpcyBub3QgYSB2YWxpZCBjb21wcmVzc2lvbiBtZXRob2QgISIpOwogICAgICAgICAgICAgICAgcmV0dXJuIG4zOwogICAgICAgICAgICAgIH0odDMub3B0aW9ucy5jb21wcmVzc2lvbiwgYS5jb21wcmVzc2lvbiksIG4yID0gdDMub3B0aW9ucy5jb21wcmVzc2lvbk9wdGlvbnMgfHwgYS5jb21wcmVzc2lvbk9wdGlvbnMgfHwge30sIGkgPSB0My5kaXIsIHMgPSB0My5kYXRlOwogICAgICAgICAgICAgIHQzLl9jb21wcmVzc1dvcmtlcihyMiwgbjIpLndpdGhTdHJlYW1JbmZvKCJmaWxlIiwgeyBuYW1lOiBlMywgZGlyOiBpLCBkYXRlOiBzLCBjb21tZW50OiB0My5jb21tZW50IHx8ICIiLCB1bml4UGVybWlzc2lvbnM6IHQzLnVuaXhQZXJtaXNzaW9ucywgZG9zUGVybWlzc2lvbnM6IHQzLmRvc1Blcm1pc3Npb25zIH0pLnBpcGUobyk7CiAgICAgICAgICAgIH0pLCBvLmVudHJpZXNDb3VudCA9IGg7CiAgICAgICAgICB9IGNhdGNoIChlMykgewogICAgICAgICAgICBvLmVycm9yKGUzKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBvOwogICAgICAgIH07CiAgICAgIH0sIHsgIi4uL2NvbXByZXNzaW9ucyI6IDMsICIuL1ppcEZpbGVXb3JrZXIiOiA4IH1dLCAxMDogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICBmdW5jdGlvbiBuKCkgewogICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIG4pKQogICAgICAgICAgICByZXR1cm4gbmV3IG4oKTsKICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlRoZSBjb25zdHJ1Y3RvciB3aXRoIHBhcmFtZXRlcnMgaGFzIGJlZW4gcmVtb3ZlZCBpbiBKU1ppcCAzLjAsIHBsZWFzZSBjaGVjayB0aGUgdXBncmFkZSBndWlkZS4iKTsKICAgICAgICAgIHRoaXMuZmlsZXMgPSAvKiBAX19QVVJFX18gKi8gT2JqZWN0LmNyZWF0ZShudWxsKSwgdGhpcy5jb21tZW50ID0gbnVsbCwgdGhpcy5yb290ID0gIiIsIHRoaXMuY2xvbmUgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgdmFyIGUyID0gbmV3IG4oKTsKICAgICAgICAgICAgZm9yICh2YXIgdDIgaW4gdGhpcykKICAgICAgICAgICAgICAiZnVuY3Rpb24iICE9IHR5cGVvZiB0aGlzW3QyXSAmJiAoZTJbdDJdID0gdGhpc1t0Ml0pOwogICAgICAgICAgICByZXR1cm4gZTI7CiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICAobi5wcm90b3R5cGUgPSBlKCIuL29iamVjdCIpKS5sb2FkQXN5bmMgPSBlKCIuL2xvYWQiKSwgbi5zdXBwb3J0ID0gZSgiLi9zdXBwb3J0IiksIG4uZGVmYXVsdHMgPSBlKCIuL2RlZmF1bHRzIiksIG4udmVyc2lvbiA9ICIzLjEwLjEiLCBuLmxvYWRBc3luYyA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgcmV0dXJuIG5ldyBuKCkubG9hZEFzeW5jKGUyLCB0Mik7CiAgICAgICAgfSwgbi5leHRlcm5hbCA9IGUoIi4vZXh0ZXJuYWwiKSwgdC5leHBvcnRzID0gbjsKICAgICAgfSwgeyAiLi9kZWZhdWx0cyI6IDUsICIuL2V4dGVybmFsIjogNiwgIi4vbG9hZCI6IDExLCAiLi9vYmplY3QiOiAxNSwgIi4vc3VwcG9ydCI6IDMwIH1dLCAxMTogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgdSA9IGUoIi4vdXRpbHMiKSwgaSA9IGUoIi4vZXh0ZXJuYWwiKSwgbiA9IGUoIi4vdXRmOCIpLCBzID0gZSgiLi96aXBFbnRyaWVzIiksIGEgPSBlKCIuL3N0cmVhbS9DcmMzMlByb2JlIiksIGwgPSBlKCIuL25vZGVqc1V0aWxzIik7CiAgICAgICAgZnVuY3Rpb24gZihuMikgewogICAgICAgICAgcmV0dXJuIG5ldyBpLlByb21pc2UoZnVuY3Rpb24oZTIsIHQyKSB7CiAgICAgICAgICAgIHZhciByMiA9IG4yLmRlY29tcHJlc3NlZC5nZXRDb250ZW50V29ya2VyKCkucGlwZShuZXcgYSgpKTsKICAgICAgICAgICAgcjIub24oImVycm9yIiwgZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICB0MihlMyk7CiAgICAgICAgICAgIH0pLm9uKCJlbmQiLCBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICByMi5zdHJlYW1JbmZvLmNyYzMyICE9PSBuMi5kZWNvbXByZXNzZWQuY3JjMzIgPyB0MihuZXcgRXJyb3IoIkNvcnJ1cHRlZCB6aXAgOiBDUkMzMiBtaXNtYXRjaCIpKSA6IGUyKCk7CiAgICAgICAgICAgIH0pLnJlc3VtZSgpOwogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHQuZXhwb3J0cyA9IGZ1bmN0aW9uKGUyLCBvKSB7CiAgICAgICAgICB2YXIgaCA9IHRoaXM7CiAgICAgICAgICByZXR1cm4gbyA9IHUuZXh0ZW5kKG8gfHwge30sIHsgYmFzZTY0OiBmYWxzZSwgY2hlY2tDUkMzMjogZmFsc2UsIG9wdGltaXplZEJpbmFyeVN0cmluZzogZmFsc2UsIGNyZWF0ZUZvbGRlcnM6IGZhbHNlLCBkZWNvZGVGaWxlTmFtZTogbi51dGY4ZGVjb2RlIH0pLCBsLmlzTm9kZSAmJiBsLmlzU3RyZWFtKGUyKSA/IGkuUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCJKU1ppcCBjYW4ndCBhY2NlcHQgYSBzdHJlYW0gd2hlbiBsb2FkaW5nIGEgemlwIGZpbGUuIikpIDogdS5wcmVwYXJlQ29udGVudCgidGhlIGxvYWRlZCB6aXAgZmlsZSIsIGUyLCB0cnVlLCBvLm9wdGltaXplZEJpbmFyeVN0cmluZywgby5iYXNlNjQpLnRoZW4oZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgdmFyIHQyID0gbmV3IHMobyk7CiAgICAgICAgICAgIHJldHVybiB0Mi5sb2FkKGUzKSwgdDI7CiAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIHZhciB0MiA9IFtpLlByb21pc2UucmVzb2x2ZShlMyldLCByMiA9IGUzLmZpbGVzOwogICAgICAgICAgICBpZiAoby5jaGVja0NSQzMyKQogICAgICAgICAgICAgIGZvciAodmFyIG4yID0gMDsgbjIgPCByMi5sZW5ndGg7IG4yKyspCiAgICAgICAgICAgICAgICB0Mi5wdXNoKGYocjJbbjJdKSk7CiAgICAgICAgICAgIHJldHVybiBpLlByb21pc2UuYWxsKHQyKTsKICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgZm9yICh2YXIgdDIgPSBlMy5zaGlmdCgpLCByMiA9IHQyLmZpbGVzLCBuMiA9IDA7IG4yIDwgcjIubGVuZ3RoOyBuMisrKSB7CiAgICAgICAgICAgICAgdmFyIGkyID0gcjJbbjJdLCBzMiA9IGkyLmZpbGVOYW1lU3RyLCBhMiA9IHUucmVzb2x2ZShpMi5maWxlTmFtZVN0cik7CiAgICAgICAgICAgICAgaC5maWxlKGEyLCBpMi5kZWNvbXByZXNzZWQsIHsgYmluYXJ5OiB0cnVlLCBvcHRpbWl6ZWRCaW5hcnlTdHJpbmc6IHRydWUsIGRhdGU6IGkyLmRhdGUsIGRpcjogaTIuZGlyLCBjb21tZW50OiBpMi5maWxlQ29tbWVudFN0ci5sZW5ndGggPyBpMi5maWxlQ29tbWVudFN0ciA6IG51bGwsIHVuaXhQZXJtaXNzaW9uczogaTIudW5peFBlcm1pc3Npb25zLCBkb3NQZXJtaXNzaW9uczogaTIuZG9zUGVybWlzc2lvbnMsIGNyZWF0ZUZvbGRlcnM6IG8uY3JlYXRlRm9sZGVycyB9KSwgaTIuZGlyIHx8IChoLmZpbGUoYTIpLnVuc2FmZU9yaWdpbmFsTmFtZSA9IHMyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gdDIuemlwQ29tbWVudC5sZW5ndGggJiYgKGguY29tbWVudCA9IHQyLnppcENvbW1lbnQpLCBoOwogICAgICAgICAgfSk7CiAgICAgICAgfTsKICAgICAgfSwgeyAiLi9leHRlcm5hbCI6IDYsICIuL25vZGVqc1V0aWxzIjogMTQsICIuL3N0cmVhbS9DcmMzMlByb2JlIjogMjUsICIuL3V0ZjgiOiAzMSwgIi4vdXRpbHMiOiAzMiwgIi4vemlwRW50cmllcyI6IDMzIH1dLCAxMjogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgbiA9IGUoIi4uL3V0aWxzIiksIGkgPSBlKCIuLi9zdHJlYW0vR2VuZXJpY1dvcmtlciIpOwogICAgICAgIGZ1bmN0aW9uIHMoZTIsIHQyKSB7CiAgICAgICAgICBpLmNhbGwodGhpcywgIk5vZGVqcyBzdHJlYW0gaW5wdXQgYWRhcHRlciBmb3IgIiArIGUyKSwgdGhpcy5fdXBzdHJlYW1FbmRlZCA9IGZhbHNlLCB0aGlzLl9iaW5kU3RyZWFtKHQyKTsKICAgICAgICB9CiAgICAgICAgbi5pbmhlcml0cyhzLCBpKSwgcy5wcm90b3R5cGUuX2JpbmRTdHJlYW0gPSBmdW5jdGlvbihlMikgewogICAgICAgICAgdmFyIHQyID0gdGhpczsKICAgICAgICAgICh0aGlzLl9zdHJlYW0gPSBlMikucGF1c2UoKSwgZTIub24oImRhdGEiLCBmdW5jdGlvbihlMykgewogICAgICAgICAgICB0Mi5wdXNoKHsgZGF0YTogZTMsIG1ldGE6IHsgcGVyY2VudDogMCB9IH0pOwogICAgICAgICAgfSkub24oImVycm9yIiwgZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgdDIuaXNQYXVzZWQgPyB0aGlzLmdlbmVyYXRlZEVycm9yID0gZTMgOiB0Mi5lcnJvcihlMyk7CiAgICAgICAgICB9KS5vbigiZW5kIiwgZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIHQyLmlzUGF1c2VkID8gdDIuX3Vwc3RyZWFtRW5kZWQgPSB0cnVlIDogdDIuZW5kKCk7CiAgICAgICAgICB9KTsKICAgICAgICB9LCBzLnByb3RvdHlwZS5wYXVzZSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgcmV0dXJuICEhaS5wcm90b3R5cGUucGF1c2UuY2FsbCh0aGlzKSAmJiAodGhpcy5fc3RyZWFtLnBhdXNlKCksIHRydWUpOwogICAgICAgIH0sIHMucHJvdG90eXBlLnJlc3VtZSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgcmV0dXJuICEhaS5wcm90b3R5cGUucmVzdW1lLmNhbGwodGhpcykgJiYgKHRoaXMuX3Vwc3RyZWFtRW5kZWQgPyB0aGlzLmVuZCgpIDogdGhpcy5fc3RyZWFtLnJlc3VtZSgpLCB0cnVlKTsKICAgICAgICB9LCB0LmV4cG9ydHMgPSBzOwogICAgICB9LCB7ICIuLi9zdHJlYW0vR2VuZXJpY1dvcmtlciI6IDI4LCAiLi4vdXRpbHMiOiAzMiB9XSwgMTM6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIGkgPSBlKCJyZWFkYWJsZS1zdHJlYW0iKS5SZWFkYWJsZTsKICAgICAgICBmdW5jdGlvbiBuKGUyLCB0MiwgcjIpIHsKICAgICAgICAgIGkuY2FsbCh0aGlzLCB0MiksIHRoaXMuX2hlbHBlciA9IGUyOwogICAgICAgICAgdmFyIG4yID0gdGhpczsKICAgICAgICAgIGUyLm9uKCJkYXRhIiwgZnVuY3Rpb24oZTMsIHQzKSB7CiAgICAgICAgICAgIG4yLnB1c2goZTMpIHx8IG4yLl9oZWxwZXIucGF1c2UoKSwgcjIgJiYgcjIodDMpOwogICAgICAgICAgfSkub24oImVycm9yIiwgZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgbjIuZW1pdCgiZXJyb3IiLCBlMyk7CiAgICAgICAgICB9KS5vbigiZW5kIiwgZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIG4yLnB1c2gobnVsbCk7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgZSgiLi4vdXRpbHMiKS5pbmhlcml0cyhuLCBpKSwgbi5wcm90b3R5cGUuX3JlYWQgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMuX2hlbHBlci5yZXN1bWUoKTsKICAgICAgICB9LCB0LmV4cG9ydHMgPSBuOwogICAgICB9LCB7ICIuLi91dGlscyI6IDMyLCAicmVhZGFibGUtc3RyZWFtIjogMTYgfV0sIDE0OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHQuZXhwb3J0cyA9IHsgaXNOb2RlOiAidW5kZWZpbmVkIiAhPSB0eXBlb2YgQnVmZmVyLCBuZXdCdWZmZXJGcm9tOiBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIGlmIChCdWZmZXIuZnJvbSAmJiBCdWZmZXIuZnJvbSAhPT0gVWludDhBcnJheS5mcm9tKQogICAgICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oZTIsIHQyKTsKICAgICAgICAgIGlmICgibnVtYmVyIiA9PSB0eXBlb2YgZTIpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlICJkYXRhIiBhcmd1bWVudCBtdXN0IG5vdCBiZSBhIG51bWJlcicpOwogICAgICAgICAgcmV0dXJuIG5ldyBCdWZmZXIoZTIsIHQyKTsKICAgICAgICB9LCBhbGxvY0J1ZmZlcjogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGlmIChCdWZmZXIuYWxsb2MpCiAgICAgICAgICAgIHJldHVybiBCdWZmZXIuYWxsb2MoZTIpOwogICAgICAgICAgdmFyIHQyID0gbmV3IEJ1ZmZlcihlMik7CiAgICAgICAgICByZXR1cm4gdDIuZmlsbCgwKSwgdDI7CiAgICAgICAgfSwgaXNCdWZmZXI6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICByZXR1cm4gQnVmZmVyLmlzQnVmZmVyKGUyKTsKICAgICAgICB9LCBpc1N0cmVhbTogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiBlMiAmJiAiZnVuY3Rpb24iID09IHR5cGVvZiBlMi5vbiAmJiAiZnVuY3Rpb24iID09IHR5cGVvZiBlMi5wYXVzZSAmJiAiZnVuY3Rpb24iID09IHR5cGVvZiBlMi5yZXN1bWU7CiAgICAgICAgfSB9OwogICAgICB9LCB7fV0sIDE1OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIGZ1bmN0aW9uIHMoZTIsIHQyLCByMikgewogICAgICAgICAgdmFyIG4yLCBpMiA9IHUuZ2V0VHlwZU9mKHQyKSwgczIgPSB1LmV4dGVuZChyMiB8fCB7fSwgZik7CiAgICAgICAgICBzMi5kYXRlID0gczIuZGF0ZSB8fCAvKiBAX19QVVJFX18gKi8gbmV3IERhdGUoKSwgbnVsbCAhPT0gczIuY29tcHJlc3Npb24gJiYgKHMyLmNvbXByZXNzaW9uID0gczIuY29tcHJlc3Npb24udG9VcHBlckNhc2UoKSksICJzdHJpbmciID09IHR5cGVvZiBzMi51bml4UGVybWlzc2lvbnMgJiYgKHMyLnVuaXhQZXJtaXNzaW9ucyA9IHBhcnNlSW50KHMyLnVuaXhQZXJtaXNzaW9ucywgOCkpLCBzMi51bml4UGVybWlzc2lvbnMgJiYgMTYzODQgJiBzMi51bml4UGVybWlzc2lvbnMgJiYgKHMyLmRpciA9IHRydWUpLCBzMi5kb3NQZXJtaXNzaW9ucyAmJiAxNiAmIHMyLmRvc1Blcm1pc3Npb25zICYmIChzMi5kaXIgPSB0cnVlKSwgczIuZGlyICYmIChlMiA9IGcoZTIpKSwgczIuY3JlYXRlRm9sZGVycyAmJiAobjIgPSBfKGUyKSkgJiYgYi5jYWxsKHRoaXMsIG4yLCB0cnVlKTsKICAgICAgICAgIHZhciBhMiA9ICJzdHJpbmciID09PSBpMiAmJiBmYWxzZSA9PT0gczIuYmluYXJ5ICYmIGZhbHNlID09PSBzMi5iYXNlNjQ7CiAgICAgICAgICByMiAmJiB2b2lkIDAgIT09IHIyLmJpbmFyeSB8fCAoczIuYmluYXJ5ID0gIWEyKSwgKHQyIGluc3RhbmNlb2YgYyAmJiAwID09PSB0Mi51bmNvbXByZXNzZWRTaXplIHx8IHMyLmRpciB8fCAhdDIgfHwgMCA9PT0gdDIubGVuZ3RoKSAmJiAoczIuYmFzZTY0ID0gZmFsc2UsIHMyLmJpbmFyeSA9IHRydWUsIHQyID0gIiIsIHMyLmNvbXByZXNzaW9uID0gIlNUT1JFIiwgaTIgPSAic3RyaW5nIik7CiAgICAgICAgICB2YXIgbzIgPSBudWxsOwogICAgICAgICAgbzIgPSB0MiBpbnN0YW5jZW9mIGMgfHwgdDIgaW5zdGFuY2VvZiBsID8gdDIgOiBwLmlzTm9kZSAmJiBwLmlzU3RyZWFtKHQyKSA/IG5ldyBtKGUyLCB0MikgOiB1LnByZXBhcmVDb250ZW50KGUyLCB0MiwgczIuYmluYXJ5LCBzMi5vcHRpbWl6ZWRCaW5hcnlTdHJpbmcsIHMyLmJhc2U2NCk7CiAgICAgICAgICB2YXIgaDIgPSBuZXcgZChlMiwgbzIsIHMyKTsKICAgICAgICAgIHRoaXMuZmlsZXNbZTJdID0gaDI7CiAgICAgICAgfQogICAgICAgIHZhciBpID0gZSgiLi91dGY4IiksIHUgPSBlKCIuL3V0aWxzIiksIGwgPSBlKCIuL3N0cmVhbS9HZW5lcmljV29ya2VyIiksIGEgPSBlKCIuL3N0cmVhbS9TdHJlYW1IZWxwZXIiKSwgZiA9IGUoIi4vZGVmYXVsdHMiKSwgYyA9IGUoIi4vY29tcHJlc3NlZE9iamVjdCIpLCBkID0gZSgiLi96aXBPYmplY3QiKSwgbyA9IGUoIi4vZ2VuZXJhdGUiKSwgcCA9IGUoIi4vbm9kZWpzVXRpbHMiKSwgbSA9IGUoIi4vbm9kZWpzL05vZGVqc1N0cmVhbUlucHV0QWRhcHRlciIpLCBfID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgICIvIiA9PT0gZTIuc2xpY2UoLTEpICYmIChlMiA9IGUyLnN1YnN0cmluZygwLCBlMi5sZW5ndGggLSAxKSk7CiAgICAgICAgICB2YXIgdDIgPSBlMi5sYXN0SW5kZXhPZigiLyIpOwogICAgICAgICAgcmV0dXJuIDAgPCB0MiA/IGUyLnN1YnN0cmluZygwLCB0MikgOiAiIjsKICAgICAgICB9LCBnID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiAiLyIgIT09IGUyLnNsaWNlKC0xKSAmJiAoZTIgKz0gIi8iKSwgZTI7CiAgICAgICAgfSwgYiA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgcmV0dXJuIHQyID0gdm9pZCAwICE9PSB0MiA/IHQyIDogZi5jcmVhdGVGb2xkZXJzLCBlMiA9IGcoZTIpLCB0aGlzLmZpbGVzW2UyXSB8fCBzLmNhbGwodGhpcywgZTIsIG51bGwsIHsgZGlyOiB0cnVlLCBjcmVhdGVGb2xkZXJzOiB0MiB9KSwgdGhpcy5maWxlc1tlMl07CiAgICAgICAgfTsKICAgICAgICBmdW5jdGlvbiBoKGUyKSB7CiAgICAgICAgICByZXR1cm4gIltvYmplY3QgUmVnRXhwXSIgPT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChlMik7CiAgICAgICAgfQogICAgICAgIHZhciBuID0geyBsb2FkOiBmdW5jdGlvbigpIHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiVGhpcyBtZXRob2QgaGFzIGJlZW4gcmVtb3ZlZCBpbiBKU1ppcCAzLjAsIHBsZWFzZSBjaGVjayB0aGUgdXBncmFkZSBndWlkZS4iKTsKICAgICAgICB9LCBmb3JFYWNoOiBmdW5jdGlvbihlMikgewogICAgICAgICAgdmFyIHQyLCByMiwgbjI7CiAgICAgICAgICBmb3IgKHQyIGluIHRoaXMuZmlsZXMpCiAgICAgICAgICAgIG4yID0gdGhpcy5maWxlc1t0Ml0sIChyMiA9IHQyLnNsaWNlKHRoaXMucm9vdC5sZW5ndGgsIHQyLmxlbmd0aCkpICYmIHQyLnNsaWNlKDAsIHRoaXMucm9vdC5sZW5ndGgpID09PSB0aGlzLnJvb3QgJiYgZTIocjIsIG4yKTsKICAgICAgICB9LCBmaWx0ZXI6IGZ1bmN0aW9uKHIyKSB7CiAgICAgICAgICB2YXIgbjIgPSBbXTsKICAgICAgICAgIHJldHVybiB0aGlzLmZvckVhY2goZnVuY3Rpb24oZTIsIHQyKSB7CiAgICAgICAgICAgIHIyKGUyLCB0MikgJiYgbjIucHVzaCh0Mik7CiAgICAgICAgICB9KSwgbjI7CiAgICAgICAgfSwgZmlsZTogZnVuY3Rpb24oZTIsIHQyLCByMikgewogICAgICAgICAgaWYgKDEgIT09IGFyZ3VtZW50cy5sZW5ndGgpCiAgICAgICAgICAgIHJldHVybiBlMiA9IHRoaXMucm9vdCArIGUyLCBzLmNhbGwodGhpcywgZTIsIHQyLCByMiksIHRoaXM7CiAgICAgICAgICBpZiAoaChlMikpIHsKICAgICAgICAgICAgdmFyIG4yID0gZTI7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbHRlcihmdW5jdGlvbihlMywgdDMpIHsKICAgICAgICAgICAgICByZXR1cm4gIXQzLmRpciAmJiBuMi50ZXN0KGUzKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgaTIgPSB0aGlzLmZpbGVzW3RoaXMucm9vdCArIGUyXTsKICAgICAgICAgIHJldHVybiBpMiAmJiAhaTIuZGlyID8gaTIgOiBudWxsOwogICAgICAgIH0sIGZvbGRlcjogZnVuY3Rpb24ocjIpIHsKICAgICAgICAgIGlmICghcjIpCiAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgaWYgKGgocjIpKQogICAgICAgICAgICByZXR1cm4gdGhpcy5maWx0ZXIoZnVuY3Rpb24oZTMsIHQzKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHQzLmRpciAmJiByMi50ZXN0KGUzKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB2YXIgZTIgPSB0aGlzLnJvb3QgKyByMiwgdDIgPSBiLmNhbGwodGhpcywgZTIpLCBuMiA9IHRoaXMuY2xvbmUoKTsKICAgICAgICAgIHJldHVybiBuMi5yb290ID0gdDIubmFtZSwgbjI7CiAgICAgICAgfSwgcmVtb3ZlOiBmdW5jdGlvbihyMikgewogICAgICAgICAgcjIgPSB0aGlzLnJvb3QgKyByMjsKICAgICAgICAgIHZhciBlMiA9IHRoaXMuZmlsZXNbcjJdOwogICAgICAgICAgaWYgKGUyIHx8ICgiLyIgIT09IHIyLnNsaWNlKC0xKSAmJiAocjIgKz0gIi8iKSwgZTIgPSB0aGlzLmZpbGVzW3IyXSksIGUyICYmICFlMi5kaXIpCiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmZpbGVzW3IyXTsKICAgICAgICAgIGVsc2UKICAgICAgICAgICAgZm9yICh2YXIgdDIgPSB0aGlzLmZpbHRlcihmdW5jdGlvbihlMywgdDMpIHsKICAgICAgICAgICAgICByZXR1cm4gdDMubmFtZS5zbGljZSgwLCByMi5sZW5ndGgpID09PSByMjsKICAgICAgICAgICAgfSksIG4yID0gMDsgbjIgPCB0Mi5sZW5ndGg7IG4yKyspCiAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuZmlsZXNbdDJbbjJdLm5hbWVdOwogICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgfSwgZ2VuZXJhdGU6IGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJUaGlzIG1ldGhvZCBoYXMgYmVlbiByZW1vdmVkIGluIEpTWmlwIDMuMCwgcGxlYXNlIGNoZWNrIHRoZSB1cGdyYWRlIGd1aWRlLiIpOwogICAgICAgIH0sIGdlbmVyYXRlSW50ZXJuYWxTdHJlYW06IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB2YXIgdDIsIHIyID0ge307CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBpZiAoKHIyID0gdS5leHRlbmQoZTIgfHwge30sIHsgc3RyZWFtRmlsZXM6IGZhbHNlLCBjb21wcmVzc2lvbjogIlNUT1JFIiwgY29tcHJlc3Npb25PcHRpb25zOiBudWxsLCB0eXBlOiAiIiwgcGxhdGZvcm06ICJET1MiLCBjb21tZW50OiBudWxsLCBtaW1lVHlwZTogImFwcGxpY2F0aW9uL3ppcCIsIGVuY29kZUZpbGVOYW1lOiBpLnV0ZjhlbmNvZGUgfSkpLnR5cGUgPSByMi50eXBlLnRvTG93ZXJDYXNlKCksIHIyLmNvbXByZXNzaW9uID0gcjIuY29tcHJlc3Npb24udG9VcHBlckNhc2UoKSwgImJpbmFyeXN0cmluZyIgPT09IHIyLnR5cGUgJiYgKHIyLnR5cGUgPSAic3RyaW5nIiksICFyMi50eXBlKQogICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiTm8gb3V0cHV0IHR5cGUgc3BlY2lmaWVkLiIpOwogICAgICAgICAgICB1LmNoZWNrU3VwcG9ydChyMi50eXBlKSwgImRhcndpbiIgIT09IHIyLnBsYXRmb3JtICYmICJmcmVlYnNkIiAhPT0gcjIucGxhdGZvcm0gJiYgImxpbnV4IiAhPT0gcjIucGxhdGZvcm0gJiYgInN1bm9zIiAhPT0gcjIucGxhdGZvcm0gfHwgKHIyLnBsYXRmb3JtID0gIlVOSVgiKSwgIndpbjMyIiA9PT0gcjIucGxhdGZvcm0gJiYgKHIyLnBsYXRmb3JtID0gIkRPUyIpOwogICAgICAgICAgICB2YXIgbjIgPSByMi5jb21tZW50IHx8IHRoaXMuY29tbWVudCB8fCAiIjsKICAgICAgICAgICAgdDIgPSBvLmdlbmVyYXRlV29ya2VyKHRoaXMsIHIyLCBuMik7CiAgICAgICAgICB9IGNhdGNoIChlMykgewogICAgICAgICAgICAodDIgPSBuZXcgbCgiZXJyb3IiKSkuZXJyb3IoZTMpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG5ldyBhKHQyLCByMi50eXBlIHx8ICJzdHJpbmciLCByMi5taW1lVHlwZSk7CiAgICAgICAgfSwgZ2VuZXJhdGVBc3luYzogZnVuY3Rpb24oZTIsIHQyKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5nZW5lcmF0ZUludGVybmFsU3RyZWFtKGUyKS5hY2N1bXVsYXRlKHQyKTsKICAgICAgICB9LCBnZW5lcmF0ZU5vZGVTdHJlYW06IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgcmV0dXJuIChlMiA9IGUyIHx8IHt9KS50eXBlIHx8IChlMi50eXBlID0gIm5vZGVidWZmZXIiKSwgdGhpcy5nZW5lcmF0ZUludGVybmFsU3RyZWFtKGUyKS50b05vZGVqc1N0cmVhbSh0Mik7CiAgICAgICAgfSB9OwogICAgICAgIHQuZXhwb3J0cyA9IG47CiAgICAgIH0sIHsgIi4vY29tcHJlc3NlZE9iamVjdCI6IDIsICIuL2RlZmF1bHRzIjogNSwgIi4vZ2VuZXJhdGUiOiA5LCAiLi9ub2RlanMvTm9kZWpzU3RyZWFtSW5wdXRBZGFwdGVyIjogMTIsICIuL25vZGVqc1V0aWxzIjogMTQsICIuL3N0cmVhbS9HZW5lcmljV29ya2VyIjogMjgsICIuL3N0cmVhbS9TdHJlYW1IZWxwZXIiOiAyOSwgIi4vdXRmOCI6IDMxLCAiLi91dGlscyI6IDMyLCAiLi96aXBPYmplY3QiOiAzNSB9XSwgMTY6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdC5leHBvcnRzID0gZSgic3RyZWFtIik7CiAgICAgIH0sIHsgc3RyZWFtOiB2b2lkIDAgfV0sIDE3OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBuID0gZSgiLi9EYXRhUmVhZGVyIik7CiAgICAgICAgZnVuY3Rpb24gaShlMikgewogICAgICAgICAgbi5jYWxsKHRoaXMsIGUyKTsKICAgICAgICAgIGZvciAodmFyIHQyID0gMDsgdDIgPCB0aGlzLmRhdGEubGVuZ3RoOyB0MisrKQogICAgICAgICAgICBlMlt0Ml0gPSAyNTUgJiBlMlt0Ml07CiAgICAgICAgfQogICAgICAgIGUoIi4uL3V0aWxzIikuaW5oZXJpdHMoaSwgbiksIGkucHJvdG90eXBlLmJ5dGVBdCA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5kYXRhW3RoaXMuemVybyArIGUyXTsKICAgICAgICB9LCBpLnByb3RvdHlwZS5sYXN0SW5kZXhPZlNpZ25hdHVyZSA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICBmb3IgKHZhciB0MiA9IGUyLmNoYXJDb2RlQXQoMCksIHIyID0gZTIuY2hhckNvZGVBdCgxKSwgbjIgPSBlMi5jaGFyQ29kZUF0KDIpLCBpMiA9IGUyLmNoYXJDb2RlQXQoMyksIHMgPSB0aGlzLmxlbmd0aCAtIDQ7IDAgPD0gczsgLS1zKQogICAgICAgICAgICBpZiAodGhpcy5kYXRhW3NdID09PSB0MiAmJiB0aGlzLmRhdGFbcyArIDFdID09PSByMiAmJiB0aGlzLmRhdGFbcyArIDJdID09PSBuMiAmJiB0aGlzLmRhdGFbcyArIDNdID09PSBpMikKICAgICAgICAgICAgICByZXR1cm4gcyAtIHRoaXMuemVybzsKICAgICAgICAgIHJldHVybiAtMTsKICAgICAgICB9LCBpLnByb3RvdHlwZS5yZWFkQW5kQ2hlY2tTaWduYXR1cmUgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgdmFyIHQyID0gZTIuY2hhckNvZGVBdCgwKSwgcjIgPSBlMi5jaGFyQ29kZUF0KDEpLCBuMiA9IGUyLmNoYXJDb2RlQXQoMiksIGkyID0gZTIuY2hhckNvZGVBdCgzKSwgcyA9IHRoaXMucmVhZERhdGEoNCk7CiAgICAgICAgICByZXR1cm4gdDIgPT09IHNbMF0gJiYgcjIgPT09IHNbMV0gJiYgbjIgPT09IHNbMl0gJiYgaTIgPT09IHNbM107CiAgICAgICAgfSwgaS5wcm90b3R5cGUucmVhZERhdGEgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgaWYgKHRoaXMuY2hlY2tPZmZzZXQoZTIpLCAwID09PSBlMikKICAgICAgICAgICAgcmV0dXJuIFtdOwogICAgICAgICAgdmFyIHQyID0gdGhpcy5kYXRhLnNsaWNlKHRoaXMuemVybyArIHRoaXMuaW5kZXgsIHRoaXMuemVybyArIHRoaXMuaW5kZXggKyBlMik7CiAgICAgICAgICByZXR1cm4gdGhpcy5pbmRleCArPSBlMiwgdDI7CiAgICAgICAgfSwgdC5leHBvcnRzID0gaTsKICAgICAgfSwgeyAiLi4vdXRpbHMiOiAzMiwgIi4vRGF0YVJlYWRlciI6IDE4IH1dLCAxODogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgbiA9IGUoIi4uL3V0aWxzIik7CiAgICAgICAgZnVuY3Rpb24gaShlMikgewogICAgICAgICAgdGhpcy5kYXRhID0gZTIsIHRoaXMubGVuZ3RoID0gZTIubGVuZ3RoLCB0aGlzLmluZGV4ID0gMCwgdGhpcy56ZXJvID0gMDsKICAgICAgICB9CiAgICAgICAgaS5wcm90b3R5cGUgPSB7IGNoZWNrT2Zmc2V0OiBmdW5jdGlvbihlMikgewogICAgICAgICAgdGhpcy5jaGVja0luZGV4KHRoaXMuaW5kZXggKyBlMik7CiAgICAgICAgfSwgY2hlY2tJbmRleDogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGlmICh0aGlzLmxlbmd0aCA8IHRoaXMuemVybyArIGUyIHx8IGUyIDwgMCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJFbmQgb2YgZGF0YSByZWFjaGVkIChkYXRhIGxlbmd0aCA9ICIgKyB0aGlzLmxlbmd0aCArICIsIGFza2VkIGluZGV4ID0gIiArIGUyICsgIikuIENvcnJ1cHRlZCB6aXAgPyIpOwogICAgICAgIH0sIHNldEluZGV4OiBmdW5jdGlvbihlMikgewogICAgICAgICAgdGhpcy5jaGVja0luZGV4KGUyKSwgdGhpcy5pbmRleCA9IGUyOwogICAgICAgIH0sIHNraXA6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB0aGlzLnNldEluZGV4KHRoaXMuaW5kZXggKyBlMik7CiAgICAgICAgfSwgYnl0ZUF0OiBmdW5jdGlvbigpIHsKICAgICAgICB9LCByZWFkSW50OiBmdW5jdGlvbihlMikgewogICAgICAgICAgdmFyIHQyLCByMiA9IDA7CiAgICAgICAgICBmb3IgKHRoaXMuY2hlY2tPZmZzZXQoZTIpLCB0MiA9IHRoaXMuaW5kZXggKyBlMiAtIDE7IHQyID49IHRoaXMuaW5kZXg7IHQyLS0pCiAgICAgICAgICAgIHIyID0gKHIyIDw8IDgpICsgdGhpcy5ieXRlQXQodDIpOwogICAgICAgICAgcmV0dXJuIHRoaXMuaW5kZXggKz0gZTIsIHIyOwogICAgICAgIH0sIHJlYWRTdHJpbmc6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICByZXR1cm4gbi50cmFuc2Zvcm1Ubygic3RyaW5nIiwgdGhpcy5yZWFkRGF0YShlMikpOwogICAgICAgIH0sIHJlYWREYXRhOiBmdW5jdGlvbigpIHsKICAgICAgICB9LCBsYXN0SW5kZXhPZlNpZ25hdHVyZTogZnVuY3Rpb24oKSB7CiAgICAgICAgfSwgcmVhZEFuZENoZWNrU2lnbmF0dXJlOiBmdW5jdGlvbigpIHsKICAgICAgICB9LCByZWFkRGF0ZTogZnVuY3Rpb24oKSB7CiAgICAgICAgICB2YXIgZTIgPSB0aGlzLnJlYWRJbnQoNCk7CiAgICAgICAgICByZXR1cm4gbmV3IERhdGUoRGF0ZS5VVEMoMTk4MCArIChlMiA+PiAyNSAmIDEyNyksIChlMiA+PiAyMSAmIDE1KSAtIDEsIGUyID4+IDE2ICYgMzEsIGUyID4+IDExICYgMzEsIGUyID4+IDUgJiA2MywgKDMxICYgZTIpIDw8IDEpKTsKICAgICAgICB9IH0sIHQuZXhwb3J0cyA9IGk7CiAgICAgIH0sIHsgIi4uL3V0aWxzIjogMzIgfV0sIDE5OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBuID0gZSgiLi9VaW50OEFycmF5UmVhZGVyIik7CiAgICAgICAgZnVuY3Rpb24gaShlMikgewogICAgICAgICAgbi5jYWxsKHRoaXMsIGUyKTsKICAgICAgICB9CiAgICAgICAgZSgiLi4vdXRpbHMiKS5pbmhlcml0cyhpLCBuKSwgaS5wcm90b3R5cGUucmVhZERhdGEgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgdGhpcy5jaGVja09mZnNldChlMik7CiAgICAgICAgICB2YXIgdDIgPSB0aGlzLmRhdGEuc2xpY2UodGhpcy56ZXJvICsgdGhpcy5pbmRleCwgdGhpcy56ZXJvICsgdGhpcy5pbmRleCArIGUyKTsKICAgICAgICAgIHJldHVybiB0aGlzLmluZGV4ICs9IGUyLCB0MjsKICAgICAgICB9LCB0LmV4cG9ydHMgPSBpOwogICAgICB9LCB7ICIuLi91dGlscyI6IDMyLCAiLi9VaW50OEFycmF5UmVhZGVyIjogMjEgfV0sIDIwOiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBuID0gZSgiLi9EYXRhUmVhZGVyIik7CiAgICAgICAgZnVuY3Rpb24gaShlMikgewogICAgICAgICAgbi5jYWxsKHRoaXMsIGUyKTsKICAgICAgICB9CiAgICAgICAgZSgiLi4vdXRpbHMiKS5pbmhlcml0cyhpLCBuKSwgaS5wcm90b3R5cGUuYnl0ZUF0ID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmRhdGEuY2hhckNvZGVBdCh0aGlzLnplcm8gKyBlMik7CiAgICAgICAgfSwgaS5wcm90b3R5cGUubGFzdEluZGV4T2ZTaWduYXR1cmUgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIHRoaXMuZGF0YS5sYXN0SW5kZXhPZihlMikgLSB0aGlzLnplcm87CiAgICAgICAgfSwgaS5wcm90b3R5cGUucmVhZEFuZENoZWNrU2lnbmF0dXJlID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiBlMiA9PT0gdGhpcy5yZWFkRGF0YSg0KTsKICAgICAgICB9LCBpLnByb3RvdHlwZS5yZWFkRGF0YSA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB0aGlzLmNoZWNrT2Zmc2V0KGUyKTsKICAgICAgICAgIHZhciB0MiA9IHRoaXMuZGF0YS5zbGljZSh0aGlzLnplcm8gKyB0aGlzLmluZGV4LCB0aGlzLnplcm8gKyB0aGlzLmluZGV4ICsgZTIpOwogICAgICAgICAgcmV0dXJuIHRoaXMuaW5kZXggKz0gZTIsIHQyOwogICAgICAgIH0sIHQuZXhwb3J0cyA9IGk7CiAgICAgIH0sIHsgIi4uL3V0aWxzIjogMzIsICIuL0RhdGFSZWFkZXIiOiAxOCB9XSwgMjE6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIG4gPSBlKCIuL0FycmF5UmVhZGVyIik7CiAgICAgICAgZnVuY3Rpb24gaShlMikgewogICAgICAgICAgbi5jYWxsKHRoaXMsIGUyKTsKICAgICAgICB9CiAgICAgICAgZSgiLi4vdXRpbHMiKS5pbmhlcml0cyhpLCBuKSwgaS5wcm90b3R5cGUucmVhZERhdGEgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgaWYgKHRoaXMuY2hlY2tPZmZzZXQoZTIpLCAwID09PSBlMikKICAgICAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KDApOwogICAgICAgICAgdmFyIHQyID0gdGhpcy5kYXRhLnN1YmFycmF5KHRoaXMuemVybyArIHRoaXMuaW5kZXgsIHRoaXMuemVybyArIHRoaXMuaW5kZXggKyBlMik7CiAgICAgICAgICByZXR1cm4gdGhpcy5pbmRleCArPSBlMiwgdDI7CiAgICAgICAgfSwgdC5leHBvcnRzID0gaTsKICAgICAgfSwgeyAiLi4vdXRpbHMiOiAzMiwgIi4vQXJyYXlSZWFkZXIiOiAxNyB9XSwgMjI6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIG4gPSBlKCIuLi91dGlscyIpLCBpID0gZSgiLi4vc3VwcG9ydCIpLCBzID0gZSgiLi9BcnJheVJlYWRlciIpLCBhID0gZSgiLi9TdHJpbmdSZWFkZXIiKSwgbyA9IGUoIi4vTm9kZUJ1ZmZlclJlYWRlciIpLCBoID0gZSgiLi9VaW50OEFycmF5UmVhZGVyIik7CiAgICAgICAgdC5leHBvcnRzID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHZhciB0MiA9IG4uZ2V0VHlwZU9mKGUyKTsKICAgICAgICAgIHJldHVybiBuLmNoZWNrU3VwcG9ydCh0MiksICJzdHJpbmciICE9PSB0MiB8fCBpLnVpbnQ4YXJyYXkgPyAibm9kZWJ1ZmZlciIgPT09IHQyID8gbmV3IG8oZTIpIDogaS51aW50OGFycmF5ID8gbmV3IGgobi50cmFuc2Zvcm1UbygidWludDhhcnJheSIsIGUyKSkgOiBuZXcgcyhuLnRyYW5zZm9ybVRvKCJhcnJheSIsIGUyKSkgOiBuZXcgYShlMik7CiAgICAgICAgfTsKICAgICAgfSwgeyAiLi4vc3VwcG9ydCI6IDMwLCAiLi4vdXRpbHMiOiAzMiwgIi4vQXJyYXlSZWFkZXIiOiAxNywgIi4vTm9kZUJ1ZmZlclJlYWRlciI6IDE5LCAiLi9TdHJpbmdSZWFkZXIiOiAyMCwgIi4vVWludDhBcnJheVJlYWRlciI6IDIxIH1dLCAyMzogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICByLkxPQ0FMX0ZJTEVfSEVBREVSID0gIlBLAwQiLCByLkNFTlRSQUxfRklMRV9IRUFERVIgPSAiUEsBAiIsIHIuQ0VOVFJBTF9ESVJFQ1RPUllfRU5EID0gIlBLBQYiLCByLlpJUDY0X0NFTlRSQUxfRElSRUNUT1JZX0xPQ0FUT1IgPSAiUEsGXHgwNyIsIHIuWklQNjRfQ0VOVFJBTF9ESVJFQ1RPUllfRU5EID0gIlBLBgYiLCByLkRBVEFfREVTQ1JJUFRPUiA9ICJQS1x4MDdcYiI7CiAgICAgIH0sIHt9XSwgMjQ6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIG4gPSBlKCIuL0dlbmVyaWNXb3JrZXIiKSwgaSA9IGUoIi4uL3V0aWxzIik7CiAgICAgICAgZnVuY3Rpb24gcyhlMikgewogICAgICAgICAgbi5jYWxsKHRoaXMsICJDb252ZXJ0V29ya2VyIHRvICIgKyBlMiksIHRoaXMuZGVzdFR5cGUgPSBlMjsKICAgICAgICB9CiAgICAgICAgaS5pbmhlcml0cyhzLCBuKSwgcy5wcm90b3R5cGUucHJvY2Vzc0NodW5rID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHRoaXMucHVzaCh7IGRhdGE6IGkudHJhbnNmb3JtVG8odGhpcy5kZXN0VHlwZSwgZTIuZGF0YSksIG1ldGE6IGUyLm1ldGEgfSk7CiAgICAgICAgfSwgdC5leHBvcnRzID0gczsKICAgICAgfSwgeyAiLi4vdXRpbHMiOiAzMiwgIi4vR2VuZXJpY1dvcmtlciI6IDI4IH1dLCAyNTogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgbiA9IGUoIi4vR2VuZXJpY1dvcmtlciIpLCBpID0gZSgiLi4vY3JjMzIiKTsKICAgICAgICBmdW5jdGlvbiBzKCkgewogICAgICAgICAgbi5jYWxsKHRoaXMsICJDcmMzMlByb2JlIiksIHRoaXMud2l0aFN0cmVhbUluZm8oImNyYzMyIiwgMCk7CiAgICAgICAgfQogICAgICAgIGUoIi4uL3V0aWxzIikuaW5oZXJpdHMocywgbiksIHMucHJvdG90eXBlLnByb2Nlc3NDaHVuayA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB0aGlzLnN0cmVhbUluZm8uY3JjMzIgPSBpKGUyLmRhdGEsIHRoaXMuc3RyZWFtSW5mby5jcmMzMiB8fCAwKSwgdGhpcy5wdXNoKGUyKTsKICAgICAgICB9LCB0LmV4cG9ydHMgPSBzOwogICAgICB9LCB7ICIuLi9jcmMzMiI6IDQsICIuLi91dGlscyI6IDMyLCAiLi9HZW5lcmljV29ya2VyIjogMjggfV0sIDI2OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBuID0gZSgiLi4vdXRpbHMiKSwgaSA9IGUoIi4vR2VuZXJpY1dvcmtlciIpOwogICAgICAgIGZ1bmN0aW9uIHMoZTIpIHsKICAgICAgICAgIGkuY2FsbCh0aGlzLCAiRGF0YUxlbmd0aFByb2JlIGZvciAiICsgZTIpLCB0aGlzLnByb3BOYW1lID0gZTIsIHRoaXMud2l0aFN0cmVhbUluZm8oZTIsIDApOwogICAgICAgIH0KICAgICAgICBuLmluaGVyaXRzKHMsIGkpLCBzLnByb3RvdHlwZS5wcm9jZXNzQ2h1bmsgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgaWYgKGUyKSB7CiAgICAgICAgICAgIHZhciB0MiA9IHRoaXMuc3RyZWFtSW5mb1t0aGlzLnByb3BOYW1lXSB8fCAwOwogICAgICAgICAgICB0aGlzLnN0cmVhbUluZm9bdGhpcy5wcm9wTmFtZV0gPSB0MiArIGUyLmRhdGEubGVuZ3RoOwogICAgICAgICAgfQogICAgICAgICAgaS5wcm90b3R5cGUucHJvY2Vzc0NodW5rLmNhbGwodGhpcywgZTIpOwogICAgICAgIH0sIHQuZXhwb3J0cyA9IHM7CiAgICAgIH0sIHsgIi4uL3V0aWxzIjogMzIsICIuL0dlbmVyaWNXb3JrZXIiOiAyOCB9XSwgMjc6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIG4gPSBlKCIuLi91dGlscyIpLCBpID0gZSgiLi9HZW5lcmljV29ya2VyIik7CiAgICAgICAgZnVuY3Rpb24gcyhlMikgewogICAgICAgICAgaS5jYWxsKHRoaXMsICJEYXRhV29ya2VyIik7CiAgICAgICAgICB2YXIgdDIgPSB0aGlzOwogICAgICAgICAgdGhpcy5kYXRhSXNSZWFkeSA9IGZhbHNlLCB0aGlzLmluZGV4ID0gMCwgdGhpcy5tYXggPSAwLCB0aGlzLmRhdGEgPSBudWxsLCB0aGlzLnR5cGUgPSAiIiwgdGhpcy5fdGlja1NjaGVkdWxlZCA9IGZhbHNlLCBlMi50aGVuKGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIHQyLmRhdGFJc1JlYWR5ID0gdHJ1ZSwgdDIuZGF0YSA9IGUzLCB0Mi5tYXggPSBlMyAmJiBlMy5sZW5ndGggfHwgMCwgdDIudHlwZSA9IG4uZ2V0VHlwZU9mKGUzKSwgdDIuaXNQYXVzZWQgfHwgdDIuX3RpY2tBbmRSZXBlYXQoKTsKICAgICAgICAgIH0sIGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIHQyLmVycm9yKGUzKTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBuLmluaGVyaXRzKHMsIGkpLCBzLnByb3RvdHlwZS5jbGVhblVwID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICBpLnByb3RvdHlwZS5jbGVhblVwLmNhbGwodGhpcyksIHRoaXMuZGF0YSA9IG51bGw7CiAgICAgICAgfSwgcy5wcm90b3R5cGUucmVzdW1lID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gISFpLnByb3RvdHlwZS5yZXN1bWUuY2FsbCh0aGlzKSAmJiAoIXRoaXMuX3RpY2tTY2hlZHVsZWQgJiYgdGhpcy5kYXRhSXNSZWFkeSAmJiAodGhpcy5fdGlja1NjaGVkdWxlZCA9IHRydWUsIG4uZGVsYXkodGhpcy5fdGlja0FuZFJlcGVhdCwgW10sIHRoaXMpKSwgdHJ1ZSk7CiAgICAgICAgfSwgcy5wcm90b3R5cGUuX3RpY2tBbmRSZXBlYXQgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMuX3RpY2tTY2hlZHVsZWQgPSBmYWxzZSwgdGhpcy5pc1BhdXNlZCB8fCB0aGlzLmlzRmluaXNoZWQgfHwgKHRoaXMuX3RpY2soKSwgdGhpcy5pc0ZpbmlzaGVkIHx8IChuLmRlbGF5KHRoaXMuX3RpY2tBbmRSZXBlYXQsIFtdLCB0aGlzKSwgdGhpcy5fdGlja1NjaGVkdWxlZCA9IHRydWUpKTsKICAgICAgICB9LCBzLnByb3RvdHlwZS5fdGljayA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgaWYgKHRoaXMuaXNQYXVzZWQgfHwgdGhpcy5pc0ZpbmlzaGVkKQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB2YXIgZTIgPSBudWxsLCB0MiA9IE1hdGgubWluKHRoaXMubWF4LCB0aGlzLmluZGV4ICsgMTYzODQpOwogICAgICAgICAgaWYgKHRoaXMuaW5kZXggPj0gdGhpcy5tYXgpCiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuZCgpOwogICAgICAgICAgc3dpdGNoICh0aGlzLnR5cGUpIHsKICAgICAgICAgICAgY2FzZSAic3RyaW5nIjoKICAgICAgICAgICAgICBlMiA9IHRoaXMuZGF0YS5zdWJzdHJpbmcodGhpcy5pbmRleCwgdDIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJ1aW50OGFycmF5IjoKICAgICAgICAgICAgICBlMiA9IHRoaXMuZGF0YS5zdWJhcnJheSh0aGlzLmluZGV4LCB0Mik7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImFycmF5IjoKICAgICAgICAgICAgY2FzZSAibm9kZWJ1ZmZlciI6CiAgICAgICAgICAgICAgZTIgPSB0aGlzLmRhdGEuc2xpY2UodGhpcy5pbmRleCwgdDIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHRoaXMuaW5kZXggPSB0MiwgdGhpcy5wdXNoKHsgZGF0YTogZTIsIG1ldGE6IHsgcGVyY2VudDogdGhpcy5tYXggPyB0aGlzLmluZGV4IC8gdGhpcy5tYXggKiAxMDAgOiAwIH0gfSk7CiAgICAgICAgfSwgdC5leHBvcnRzID0gczsKICAgICAgfSwgeyAiLi4vdXRpbHMiOiAzMiwgIi4vR2VuZXJpY1dvcmtlciI6IDI4IH1dLCAyODogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICBmdW5jdGlvbiBuKGUyKSB7CiAgICAgICAgICB0aGlzLm5hbWUgPSBlMiB8fCAiZGVmYXVsdCIsIHRoaXMuc3RyZWFtSW5mbyA9IHt9LCB0aGlzLmdlbmVyYXRlZEVycm9yID0gbnVsbCwgdGhpcy5leHRyYVN0cmVhbUluZm8gPSB7fSwgdGhpcy5pc1BhdXNlZCA9IHRydWUsIHRoaXMuaXNGaW5pc2hlZCA9IGZhbHNlLCB0aGlzLmlzTG9ja2VkID0gZmFsc2UsIHRoaXMuX2xpc3RlbmVycyA9IHsgZGF0YTogW10sIGVuZDogW10sIGVycm9yOiBbXSB9LCB0aGlzLnByZXZpb3VzID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgbi5wcm90b3R5cGUgPSB7IHB1c2g6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB0aGlzLmVtaXQoImRhdGEiLCBlMik7CiAgICAgICAgfSwgZW5kOiBmdW5jdGlvbigpIHsKICAgICAgICAgIGlmICh0aGlzLmlzRmluaXNoZWQpCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIHRoaXMuZmx1c2goKTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHRoaXMuZW1pdCgiZW5kIiksIHRoaXMuY2xlYW5VcCgpLCB0aGlzLmlzRmluaXNoZWQgPSB0cnVlOwogICAgICAgICAgfSBjYXRjaCAoZTIpIHsKICAgICAgICAgICAgdGhpcy5lbWl0KCJlcnJvciIsIGUyKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0sIGVycm9yOiBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuICF0aGlzLmlzRmluaXNoZWQgJiYgKHRoaXMuaXNQYXVzZWQgPyB0aGlzLmdlbmVyYXRlZEVycm9yID0gZTIgOiAodGhpcy5pc0ZpbmlzaGVkID0gdHJ1ZSwgdGhpcy5lbWl0KCJlcnJvciIsIGUyKSwgdGhpcy5wcmV2aW91cyAmJiB0aGlzLnByZXZpb3VzLmVycm9yKGUyKSwgdGhpcy5jbGVhblVwKCkpLCB0cnVlKTsKICAgICAgICB9LCBvbjogZnVuY3Rpb24oZTIsIHQyKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fbGlzdGVuZXJzW2UyXS5wdXNoKHQyKSwgdGhpczsKICAgICAgICB9LCBjbGVhblVwOiBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMuc3RyZWFtSW5mbyA9IHRoaXMuZ2VuZXJhdGVkRXJyb3IgPSB0aGlzLmV4dHJhU3RyZWFtSW5mbyA9IG51bGwsIHRoaXMuX2xpc3RlbmVycyA9IFtdOwogICAgICAgIH0sIGVtaXQ6IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgaWYgKHRoaXMuX2xpc3RlbmVyc1tlMl0pCiAgICAgICAgICAgIGZvciAodmFyIHIyID0gMDsgcjIgPCB0aGlzLl9saXN0ZW5lcnNbZTJdLmxlbmd0aDsgcjIrKykKICAgICAgICAgICAgICB0aGlzLl9saXN0ZW5lcnNbZTJdW3IyXS5jYWxsKHRoaXMsIHQyKTsKICAgICAgICB9LCBwaXBlOiBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIGUyLnJlZ2lzdGVyUHJldmlvdXModGhpcyk7CiAgICAgICAgfSwgcmVnaXN0ZXJQcmV2aW91czogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGlmICh0aGlzLmlzTG9ja2VkKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlRoZSBzdHJlYW0gJyIgKyB0aGlzICsgIicgaGFzIGFscmVhZHkgYmVlbiB1c2VkLiIpOwogICAgICAgICAgdGhpcy5zdHJlYW1JbmZvID0gZTIuc3RyZWFtSW5mbywgdGhpcy5tZXJnZVN0cmVhbUluZm8oKSwgdGhpcy5wcmV2aW91cyA9IGUyOwogICAgICAgICAgdmFyIHQyID0gdGhpczsKICAgICAgICAgIHJldHVybiBlMi5vbigiZGF0YSIsIGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIHQyLnByb2Nlc3NDaHVuayhlMyk7CiAgICAgICAgICB9KSwgZTIub24oImVuZCIsIGZ1bmN0aW9uKCkgewogICAgICAgICAgICB0Mi5lbmQoKTsKICAgICAgICAgIH0pLCBlMi5vbigiZXJyb3IiLCBmdW5jdGlvbihlMykgewogICAgICAgICAgICB0Mi5lcnJvcihlMyk7CiAgICAgICAgICB9KSwgdGhpczsKICAgICAgICB9LCBwYXVzZTogZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gIXRoaXMuaXNQYXVzZWQgJiYgIXRoaXMuaXNGaW5pc2hlZCAmJiAodGhpcy5pc1BhdXNlZCA9IHRydWUsIHRoaXMucHJldmlvdXMgJiYgdGhpcy5wcmV2aW91cy5wYXVzZSgpLCB0cnVlKTsKICAgICAgICB9LCByZXN1bWU6IGZ1bmN0aW9uKCkgewogICAgICAgICAgaWYgKCF0aGlzLmlzUGF1c2VkIHx8IHRoaXMuaXNGaW5pc2hlZCkKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgdmFyIGUyID0gdGhpcy5pc1BhdXNlZCA9IGZhbHNlOwogICAgICAgICAgcmV0dXJuIHRoaXMuZ2VuZXJhdGVkRXJyb3IgJiYgKHRoaXMuZXJyb3IodGhpcy5nZW5lcmF0ZWRFcnJvciksIGUyID0gdHJ1ZSksIHRoaXMucHJldmlvdXMgJiYgdGhpcy5wcmV2aW91cy5yZXN1bWUoKSwgIWUyOwogICAgICAgIH0sIGZsdXNoOiBmdW5jdGlvbigpIHsKICAgICAgICB9LCBwcm9jZXNzQ2h1bms6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB0aGlzLnB1c2goZTIpOwogICAgICAgIH0sIHdpdGhTdHJlYW1JbmZvOiBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmV4dHJhU3RyZWFtSW5mb1tlMl0gPSB0MiwgdGhpcy5tZXJnZVN0cmVhbUluZm8oKSwgdGhpczsKICAgICAgICB9LCBtZXJnZVN0cmVhbUluZm86IGZ1bmN0aW9uKCkgewogICAgICAgICAgZm9yICh2YXIgZTIgaW4gdGhpcy5leHRyYVN0cmVhbUluZm8pCiAgICAgICAgICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmV4dHJhU3RyZWFtSW5mbywgZTIpICYmICh0aGlzLnN0cmVhbUluZm9bZTJdID0gdGhpcy5leHRyYVN0cmVhbUluZm9bZTJdKTsKICAgICAgICB9LCBsb2NrOiBmdW5jdGlvbigpIHsKICAgICAgICAgIGlmICh0aGlzLmlzTG9ja2VkKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlRoZSBzdHJlYW0gJyIgKyB0aGlzICsgIicgaGFzIGFscmVhZHkgYmVlbiB1c2VkLiIpOwogICAgICAgICAgdGhpcy5pc0xvY2tlZCA9IHRydWUsIHRoaXMucHJldmlvdXMgJiYgdGhpcy5wcmV2aW91cy5sb2NrKCk7CiAgICAgICAgfSwgdG9TdHJpbmc6IGZ1bmN0aW9uKCkgewogICAgICAgICAgdmFyIGUyID0gIldvcmtlciAiICsgdGhpcy5uYW1lOwogICAgICAgICAgcmV0dXJuIHRoaXMucHJldmlvdXMgPyB0aGlzLnByZXZpb3VzICsgIiAtPiAiICsgZTIgOiBlMjsKICAgICAgICB9IH0sIHQuZXhwb3J0cyA9IG47CiAgICAgIH0sIHt9XSwgMjk6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIGggPSBlKCIuLi91dGlscyIpLCBpID0gZSgiLi9Db252ZXJ0V29ya2VyIiksIHMgPSBlKCIuL0dlbmVyaWNXb3JrZXIiKSwgdSA9IGUoIi4uL2Jhc2U2NCIpLCBuID0gZSgiLi4vc3VwcG9ydCIpLCBhID0gZSgiLi4vZXh0ZXJuYWwiKSwgbyA9IG51bGw7CiAgICAgICAgaWYgKG4ubm9kZXN0cmVhbSkKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIG8gPSBlKCIuLi9ub2RlanMvTm9kZWpzU3RyZWFtT3V0cHV0QWRhcHRlciIpOwogICAgICAgICAgfSBjYXRjaCAoZTIpIHsKICAgICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBsKGUyLCBvMikgewogICAgICAgICAgcmV0dXJuIG5ldyBhLlByb21pc2UoZnVuY3Rpb24odDIsIHIyKSB7CiAgICAgICAgICAgIHZhciBuMiA9IFtdLCBpMiA9IGUyLl9pbnRlcm5hbFR5cGUsIHMyID0gZTIuX291dHB1dFR5cGUsIGEyID0gZTIuX21pbWVUeXBlOwogICAgICAgICAgICBlMi5vbigiZGF0YSIsIGZ1bmN0aW9uKGUzLCB0MykgewogICAgICAgICAgICAgIG4yLnB1c2goZTMpLCBvMiAmJiBvMih0Myk7CiAgICAgICAgICAgIH0pLm9uKCJlcnJvciIsIGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgbjIgPSBbXSwgcjIoZTMpOwogICAgICAgICAgICB9KS5vbigiZW5kIiwgZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHZhciBlMyA9IGZ1bmN0aW9uKGU0LCB0MywgcjMpIHsKICAgICAgICAgICAgICAgICAgc3dpdGNoIChlNCkgewogICAgICAgICAgICAgICAgICAgIGNhc2UgImJsb2IiOgogICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGgubmV3QmxvYihoLnRyYW5zZm9ybVRvKCJhcnJheWJ1ZmZlciIsIHQzKSwgcjMpOwogICAgICAgICAgICAgICAgICAgIGNhc2UgImJhc2U2NCI6CiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdS5lbmNvZGUodDMpOwogICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaC50cmFuc2Zvcm1UbyhlNCwgdDMpOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KHMyLCBmdW5jdGlvbihlNCwgdDMpIHsKICAgICAgICAgICAgICAgICAgdmFyIHIzLCBuMyA9IDAsIGkzID0gbnVsbCwgczMgPSAwOwogICAgICAgICAgICAgICAgICBmb3IgKHIzID0gMDsgcjMgPCB0My5sZW5ndGg7IHIzKyspCiAgICAgICAgICAgICAgICAgICAgczMgKz0gdDNbcjNdLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgc3dpdGNoIChlNCkgewogICAgICAgICAgICAgICAgICAgIGNhc2UgInN0cmluZyI6CiAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdDMuam9pbigiIik7CiAgICAgICAgICAgICAgICAgICAgY2FzZSAiYXJyYXkiOgogICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5jb25jYXQuYXBwbHkoW10sIHQzKTsKICAgICAgICAgICAgICAgICAgICBjYXNlICJ1aW50OGFycmF5IjoKICAgICAgICAgICAgICAgICAgICAgIGZvciAoaTMgPSBuZXcgVWludDhBcnJheShzMyksIHIzID0gMDsgcjMgPCB0My5sZW5ndGg7IHIzKyspCiAgICAgICAgICAgICAgICAgICAgICAgIGkzLnNldCh0M1tyM10sIG4zKSwgbjMgKz0gdDNbcjNdLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpMzsKICAgICAgICAgICAgICAgICAgICBjYXNlICJub2RlYnVmZmVyIjoKICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBCdWZmZXIuY29uY2F0KHQzKTsKICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJjb25jYXQgOiB1bnN1cHBvcnRlZCB0eXBlICciICsgZTQgKyAiJyIpOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KGkyLCBuMiksIGEyKTsKICAgICAgICAgICAgICAgIHQyKGUzKTsKICAgICAgICAgICAgICB9IGNhdGNoIChlNCkgewogICAgICAgICAgICAgICAgcjIoZTQpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBuMiA9IFtdOwogICAgICAgICAgICB9KS5yZXN1bWUoKTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBmKGUyLCB0MiwgcjIpIHsKICAgICAgICAgIHZhciBuMiA9IHQyOwogICAgICAgICAgc3dpdGNoICh0MikgewogICAgICAgICAgICBjYXNlICJibG9iIjoKICAgICAgICAgICAgY2FzZSAiYXJyYXlidWZmZXIiOgogICAgICAgICAgICAgIG4yID0gInVpbnQ4YXJyYXkiOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJiYXNlNjQiOgogICAgICAgICAgICAgIG4yID0gInN0cmluZyI7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICB0aGlzLl9pbnRlcm5hbFR5cGUgPSBuMiwgdGhpcy5fb3V0cHV0VHlwZSA9IHQyLCB0aGlzLl9taW1lVHlwZSA9IHIyLCBoLmNoZWNrU3VwcG9ydChuMiksIHRoaXMuX3dvcmtlciA9IGUyLnBpcGUobmV3IGkobjIpKSwgZTIubG9jaygpOwogICAgICAgICAgfSBjYXRjaCAoZTMpIHsKICAgICAgICAgICAgdGhpcy5fd29ya2VyID0gbmV3IHMoImVycm9yIiksIHRoaXMuX3dvcmtlci5lcnJvcihlMyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGYucHJvdG90eXBlID0geyBhY2N1bXVsYXRlOiBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIGwodGhpcywgZTIpOwogICAgICAgIH0sIG9uOiBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiA9IHRoaXM7CiAgICAgICAgICByZXR1cm4gImRhdGEiID09PSBlMiA/IHRoaXMuX3dvcmtlci5vbihlMiwgZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgdDIuY2FsbChyMiwgZTMuZGF0YSwgZTMubWV0YSk7CiAgICAgICAgICB9KSA6IHRoaXMuX3dvcmtlci5vbihlMiwgZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIGguZGVsYXkodDIsIGFyZ3VtZW50cywgcjIpOwogICAgICAgICAgfSksIHRoaXM7CiAgICAgICAgfSwgcmVzdW1lOiBmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiBoLmRlbGF5KHRoaXMuX3dvcmtlci5yZXN1bWUsIFtdLCB0aGlzLl93b3JrZXIpLCB0aGlzOwogICAgICAgIH0sIHBhdXNlOiBmdW5jdGlvbigpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl93b3JrZXIucGF1c2UoKSwgdGhpczsKICAgICAgICB9LCB0b05vZGVqc1N0cmVhbTogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGlmIChoLmNoZWNrU3VwcG9ydCgibm9kZXN0cmVhbSIpLCAibm9kZWJ1ZmZlciIgIT09IHRoaXMuX291dHB1dFR5cGUpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLl9vdXRwdXRUeXBlICsgIiBpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoaXMgbWV0aG9kIik7CiAgICAgICAgICByZXR1cm4gbmV3IG8odGhpcywgeyBvYmplY3RNb2RlOiAibm9kZWJ1ZmZlciIgIT09IHRoaXMuX291dHB1dFR5cGUgfSwgZTIpOwogICAgICAgIH0gfSwgdC5leHBvcnRzID0gZjsKICAgICAgfSwgeyAiLi4vYmFzZTY0IjogMSwgIi4uL2V4dGVybmFsIjogNiwgIi4uL25vZGVqcy9Ob2RlanNTdHJlYW1PdXRwdXRBZGFwdGVyIjogMTMsICIuLi9zdXBwb3J0IjogMzAsICIuLi91dGlscyI6IDMyLCAiLi9Db252ZXJ0V29ya2VyIjogMjQsICIuL0dlbmVyaWNXb3JrZXIiOiAyOCB9XSwgMzA6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgaWYgKHIuYmFzZTY0ID0gdHJ1ZSwgci5hcnJheSA9IHRydWUsIHIuc3RyaW5nID0gdHJ1ZSwgci5hcnJheWJ1ZmZlciA9ICJ1bmRlZmluZWQiICE9IHR5cGVvZiBBcnJheUJ1ZmZlciAmJiAidW5kZWZpbmVkIiAhPSB0eXBlb2YgVWludDhBcnJheSwgci5ub2RlYnVmZmVyID0gInVuZGVmaW5lZCIgIT0gdHlwZW9mIEJ1ZmZlciwgci51aW50OGFycmF5ID0gInVuZGVmaW5lZCIgIT0gdHlwZW9mIFVpbnQ4QXJyYXksICJ1bmRlZmluZWQiID09IHR5cGVvZiBBcnJheUJ1ZmZlcikKICAgICAgICAgIHIuYmxvYiA9IGZhbHNlOwogICAgICAgIGVsc2UgewogICAgICAgICAgdmFyIG4gPSBuZXcgQXJyYXlCdWZmZXIoMCk7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICByLmJsb2IgPSAwID09PSBuZXcgQmxvYihbbl0sIHsgdHlwZTogImFwcGxpY2F0aW9uL3ppcCIgfSkuc2l6ZTsKICAgICAgICAgIH0gY2F0Y2ggKGUyKSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgdmFyIGkgPSBuZXcgKHNlbGYuQmxvYkJ1aWxkZXIgfHwgc2VsZi5XZWJLaXRCbG9iQnVpbGRlciB8fCBzZWxmLk1vekJsb2JCdWlsZGVyIHx8IHNlbGYuTVNCbG9iQnVpbGRlcikoKTsKICAgICAgICAgICAgICBpLmFwcGVuZChuKSwgci5ibG9iID0gMCA9PT0gaS5nZXRCbG9iKCJhcHBsaWNhdGlvbi96aXAiKS5zaXplOwogICAgICAgICAgICB9IGNhdGNoIChlMykgewogICAgICAgICAgICAgIHIuYmxvYiA9IGZhbHNlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICByLm5vZGVzdHJlYW0gPSAhIWUoInJlYWRhYmxlLXN0cmVhbSIpLlJlYWRhYmxlOwogICAgICAgIH0gY2F0Y2ggKGUyKSB7CiAgICAgICAgICByLm5vZGVzdHJlYW0gPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0sIHsgInJlYWRhYmxlLXN0cmVhbSI6IDE2IH1dLCAzMTogW2Z1bmN0aW9uKGUsIHQsIHMpIHsKICAgICAgICBmb3IgKHZhciBvID0gZSgiLi91dGlscyIpLCBoID0gZSgiLi9zdXBwb3J0IiksIHIgPSBlKCIuL25vZGVqc1V0aWxzIiksIG4gPSBlKCIuL3N0cmVhbS9HZW5lcmljV29ya2VyIiksIHUgPSBuZXcgQXJyYXkoMjU2KSwgaSA9IDA7IGkgPCAyNTY7IGkrKykKICAgICAgICAgIHVbaV0gPSAyNTIgPD0gaSA/IDYgOiAyNDggPD0gaSA/IDUgOiAyNDAgPD0gaSA/IDQgOiAyMjQgPD0gaSA/IDMgOiAxOTIgPD0gaSA/IDIgOiAxOwogICAgICAgIHVbMjU0XSA9IHVbMjU0XSA9IDE7CiAgICAgICAgZnVuY3Rpb24gYSgpIHsKICAgICAgICAgIG4uY2FsbCh0aGlzLCAidXRmLTggZGVjb2RlIiksIHRoaXMubGVmdE92ZXIgPSBudWxsOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBsKCkgewogICAgICAgICAgbi5jYWxsKHRoaXMsICJ1dGYtOCBlbmNvZGUiKTsKICAgICAgICB9CiAgICAgICAgcy51dGY4ZW5jb2RlID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiBoLm5vZGVidWZmZXIgPyByLm5ld0J1ZmZlckZyb20oZTIsICJ1dGYtOCIpIDogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgdmFyIHQyLCByMiwgbjIsIGkyLCBzMiwgYTIgPSBlMy5sZW5ndGgsIG8yID0gMDsKICAgICAgICAgICAgZm9yIChpMiA9IDA7IGkyIDwgYTI7IGkyKyspCiAgICAgICAgICAgICAgNTUyOTYgPT0gKDY0NTEyICYgKHIyID0gZTMuY2hhckNvZGVBdChpMikpKSAmJiBpMiArIDEgPCBhMiAmJiA1NjMyMCA9PSAoNjQ1MTIgJiAobjIgPSBlMy5jaGFyQ29kZUF0KGkyICsgMSkpKSAmJiAocjIgPSA2NTUzNiArIChyMiAtIDU1Mjk2IDw8IDEwKSArIChuMiAtIDU2MzIwKSwgaTIrKyksIG8yICs9IHIyIDwgMTI4ID8gMSA6IHIyIDwgMjA0OCA/IDIgOiByMiA8IDY1NTM2ID8gMyA6IDQ7CiAgICAgICAgICAgIGZvciAodDIgPSBoLnVpbnQ4YXJyYXkgPyBuZXcgVWludDhBcnJheShvMikgOiBuZXcgQXJyYXkobzIpLCBpMiA9IHMyID0gMDsgczIgPCBvMjsgaTIrKykKICAgICAgICAgICAgICA1NTI5NiA9PSAoNjQ1MTIgJiAocjIgPSBlMy5jaGFyQ29kZUF0KGkyKSkpICYmIGkyICsgMSA8IGEyICYmIDU2MzIwID09ICg2NDUxMiAmIChuMiA9IGUzLmNoYXJDb2RlQXQoaTIgKyAxKSkpICYmIChyMiA9IDY1NTM2ICsgKHIyIC0gNTUyOTYgPDwgMTApICsgKG4yIC0gNTYzMjApLCBpMisrKSwgcjIgPCAxMjggPyB0MltzMisrXSA9IHIyIDogKHIyIDwgMjA0OCA/IHQyW3MyKytdID0gMTkyIHwgcjIgPj4+IDYgOiAocjIgPCA2NTUzNiA/IHQyW3MyKytdID0gMjI0IHwgcjIgPj4+IDEyIDogKHQyW3MyKytdID0gMjQwIHwgcjIgPj4+IDE4LCB0MltzMisrXSA9IDEyOCB8IHIyID4+PiAxMiAmIDYzKSwgdDJbczIrK10gPSAxMjggfCByMiA+Pj4gNiAmIDYzKSwgdDJbczIrK10gPSAxMjggfCA2MyAmIHIyKTsKICAgICAgICAgICAgcmV0dXJuIHQyOwogICAgICAgICAgfShlMik7CiAgICAgICAgfSwgcy51dGY4ZGVjb2RlID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiBoLm5vZGVidWZmZXIgPyBvLnRyYW5zZm9ybVRvKCJub2RlYnVmZmVyIiwgZTIpLnRvU3RyaW5nKCJ1dGYtOCIpIDogZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgdmFyIHQyLCByMiwgbjIsIGkyLCBzMiA9IGUzLmxlbmd0aCwgYTIgPSBuZXcgQXJyYXkoMiAqIHMyKTsKICAgICAgICAgICAgZm9yICh0MiA9IHIyID0gMDsgdDIgPCBzMjsgKQogICAgICAgICAgICAgIGlmICgobjIgPSBlM1t0MisrXSkgPCAxMjgpCiAgICAgICAgICAgICAgICBhMltyMisrXSA9IG4yOwogICAgICAgICAgICAgIGVsc2UgaWYgKDQgPCAoaTIgPSB1W24yXSkpCiAgICAgICAgICAgICAgICBhMltyMisrXSA9IDY1NTMzLCB0MiArPSBpMiAtIDE7CiAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICBmb3IgKG4yICY9IDIgPT09IGkyID8gMzEgOiAzID09PSBpMiA/IDE1IDogNzsgMSA8IGkyICYmIHQyIDwgczI7ICkKICAgICAgICAgICAgICAgICAgbjIgPSBuMiA8PCA2IHwgNjMgJiBlM1t0MisrXSwgaTItLTsKICAgICAgICAgICAgICAgIDEgPCBpMiA/IGEyW3IyKytdID0gNjU1MzMgOiBuMiA8IDY1NTM2ID8gYTJbcjIrK10gPSBuMiA6IChuMiAtPSA2NTUzNiwgYTJbcjIrK10gPSA1NTI5NiB8IG4yID4+IDEwICYgMTAyMywgYTJbcjIrK10gPSA1NjMyMCB8IDEwMjMgJiBuMik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gYTIubGVuZ3RoICE9PSByMiAmJiAoYTIuc3ViYXJyYXkgPyBhMiA9IGEyLnN1YmFycmF5KDAsIHIyKSA6IGEyLmxlbmd0aCA9IHIyKSwgby5hcHBseUZyb21DaGFyQ29kZShhMik7CiAgICAgICAgICB9KGUyID0gby50cmFuc2Zvcm1UbyhoLnVpbnQ4YXJyYXkgPyAidWludDhhcnJheSIgOiAiYXJyYXkiLCBlMikpOwogICAgICAgIH0sIG8uaW5oZXJpdHMoYSwgbiksIGEucHJvdG90eXBlLnByb2Nlc3NDaHVuayA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB2YXIgdDIgPSBvLnRyYW5zZm9ybVRvKGgudWludDhhcnJheSA/ICJ1aW50OGFycmF5IiA6ICJhcnJheSIsIGUyLmRhdGEpOwogICAgICAgICAgaWYgKHRoaXMubGVmdE92ZXIgJiYgdGhpcy5sZWZ0T3Zlci5sZW5ndGgpIHsKICAgICAgICAgICAgaWYgKGgudWludDhhcnJheSkgewogICAgICAgICAgICAgIHZhciByMiA9IHQyOwogICAgICAgICAgICAgICh0MiA9IG5ldyBVaW50OEFycmF5KHIyLmxlbmd0aCArIHRoaXMubGVmdE92ZXIubGVuZ3RoKSkuc2V0KHRoaXMubGVmdE92ZXIsIDApLCB0Mi5zZXQocjIsIHRoaXMubGVmdE92ZXIubGVuZ3RoKTsKICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgdDIgPSB0aGlzLmxlZnRPdmVyLmNvbmNhdCh0Mik7CiAgICAgICAgICAgIHRoaXMubGVmdE92ZXIgPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgdmFyIG4yID0gZnVuY3Rpb24oZTMsIHQzKSB7CiAgICAgICAgICAgIHZhciByMzsKICAgICAgICAgICAgZm9yICgodDMgPSB0MyB8fCBlMy5sZW5ndGgpID4gZTMubGVuZ3RoICYmICh0MyA9IGUzLmxlbmd0aCksIHIzID0gdDMgLSAxOyAwIDw9IHIzICYmIDEyOCA9PSAoMTkyICYgZTNbcjNdKTsgKQogICAgICAgICAgICAgIHIzLS07CiAgICAgICAgICAgIHJldHVybiByMyA8IDAgPyB0MyA6IDAgPT09IHIzID8gdDMgOiByMyArIHVbZTNbcjNdXSA+IHQzID8gcjMgOiB0MzsKICAgICAgICAgIH0odDIpLCBpMiA9IHQyOwogICAgICAgICAgbjIgIT09IHQyLmxlbmd0aCAmJiAoaC51aW50OGFycmF5ID8gKGkyID0gdDIuc3ViYXJyYXkoMCwgbjIpLCB0aGlzLmxlZnRPdmVyID0gdDIuc3ViYXJyYXkobjIsIHQyLmxlbmd0aCkpIDogKGkyID0gdDIuc2xpY2UoMCwgbjIpLCB0aGlzLmxlZnRPdmVyID0gdDIuc2xpY2UobjIsIHQyLmxlbmd0aCkpKSwgdGhpcy5wdXNoKHsgZGF0YTogcy51dGY4ZGVjb2RlKGkyKSwgbWV0YTogZTIubWV0YSB9KTsKICAgICAgICB9LCBhLnByb3RvdHlwZS5mbHVzaCA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy5sZWZ0T3ZlciAmJiB0aGlzLmxlZnRPdmVyLmxlbmd0aCAmJiAodGhpcy5wdXNoKHsgZGF0YTogcy51dGY4ZGVjb2RlKHRoaXMubGVmdE92ZXIpLCBtZXRhOiB7fSB9KSwgdGhpcy5sZWZ0T3ZlciA9IG51bGwpOwogICAgICAgIH0sIHMuVXRmOERlY29kZVdvcmtlciA9IGEsIG8uaW5oZXJpdHMobCwgbiksIGwucHJvdG90eXBlLnByb2Nlc3NDaHVuayA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB0aGlzLnB1c2goeyBkYXRhOiBzLnV0ZjhlbmNvZGUoZTIuZGF0YSksIG1ldGE6IGUyLm1ldGEgfSk7CiAgICAgICAgfSwgcy5VdGY4RW5jb2RlV29ya2VyID0gbDsKICAgICAgfSwgeyAiLi9ub2RlanNVdGlscyI6IDE0LCAiLi9zdHJlYW0vR2VuZXJpY1dvcmtlciI6IDI4LCAiLi9zdXBwb3J0IjogMzAsICIuL3V0aWxzIjogMzIgfV0sIDMyOiBbZnVuY3Rpb24oZSwgdCwgYSkgewogICAgICAgIHZhciBvID0gZSgiLi9zdXBwb3J0IiksIGggPSBlKCIuL2Jhc2U2NCIpLCByID0gZSgiLi9ub2RlanNVdGlscyIpLCB1ID0gZSgiLi9leHRlcm5hbCIpOwogICAgICAgIGZ1bmN0aW9uIG4oZTIpIHsKICAgICAgICAgIHJldHVybiBlMjsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gbChlMiwgdDIpIHsKICAgICAgICAgIGZvciAodmFyIHIyID0gMDsgcjIgPCBlMi5sZW5ndGg7ICsrcjIpCiAgICAgICAgICAgIHQyW3IyXSA9IDI1NSAmIGUyLmNoYXJDb2RlQXQocjIpOwogICAgICAgICAgcmV0dXJuIHQyOwogICAgICAgIH0KICAgICAgICBlKCJzZXRpbW1lZGlhdGUiKSwgYS5uZXdCbG9iID0gZnVuY3Rpb24odDIsIHIyKSB7CiAgICAgICAgICBhLmNoZWNrU3VwcG9ydCgiYmxvYiIpOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcmV0dXJuIG5ldyBCbG9iKFt0Ml0sIHsgdHlwZTogcjIgfSk7CiAgICAgICAgICB9IGNhdGNoIChlMikgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIHZhciBuMiA9IG5ldyAoc2VsZi5CbG9iQnVpbGRlciB8fCBzZWxmLldlYktpdEJsb2JCdWlsZGVyIHx8IHNlbGYuTW96QmxvYkJ1aWxkZXIgfHwgc2VsZi5NU0Jsb2JCdWlsZGVyKSgpOwogICAgICAgICAgICAgIHJldHVybiBuMi5hcHBlbmQodDIpLCBuMi5nZXRCbG9iKHIyKTsKICAgICAgICAgICAgfSBjYXRjaCAoZTMpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkJ1ZyA6IGNhbid0IGNvbnN0cnVjdCB0aGUgQmxvYi4iKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH07CiAgICAgICAgdmFyIGkgPSB7IHN0cmluZ2lmeUJ5Q2h1bms6IGZ1bmN0aW9uKGUyLCB0MiwgcjIpIHsKICAgICAgICAgIHZhciBuMiA9IFtdLCBpMiA9IDAsIHMyID0gZTIubGVuZ3RoOwogICAgICAgICAgaWYgKHMyIDw9IHIyKQogICAgICAgICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBlMik7CiAgICAgICAgICBmb3IgKDsgaTIgPCBzMjsgKQogICAgICAgICAgICAiYXJyYXkiID09PSB0MiB8fCAibm9kZWJ1ZmZlciIgPT09IHQyID8gbjIucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGUyLnNsaWNlKGkyLCBNYXRoLm1pbihpMiArIHIyLCBzMikpKSkgOiBuMi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgZTIuc3ViYXJyYXkoaTIsIE1hdGgubWluKGkyICsgcjIsIHMyKSkpKSwgaTIgKz0gcjI7CiAgICAgICAgICByZXR1cm4gbjIuam9pbigiIik7CiAgICAgICAgfSwgc3RyaW5naWZ5QnlDaGFyOiBmdW5jdGlvbihlMikgewogICAgICAgICAgZm9yICh2YXIgdDIgPSAiIiwgcjIgPSAwOyByMiA8IGUyLmxlbmd0aDsgcjIrKykKICAgICAgICAgICAgdDIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShlMltyMl0pOwogICAgICAgICAgcmV0dXJuIHQyOwogICAgICAgIH0sIGFwcGx5Q2FuQmVVc2VkOiB7IHVpbnQ4YXJyYXk6IGZ1bmN0aW9uKCkgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcmV0dXJuIG8udWludDhhcnJheSAmJiAxID09PSBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIG5ldyBVaW50OEFycmF5KDEpKS5sZW5ndGg7CiAgICAgICAgICB9IGNhdGNoIChlMikgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfSgpLCBub2RlYnVmZmVyOiBmdW5jdGlvbigpIHsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHJldHVybiBvLm5vZGVidWZmZXIgJiYgMSA9PT0gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCByLmFsbG9jQnVmZmVyKDEpKS5sZW5ndGg7CiAgICAgICAgICB9IGNhdGNoIChlMikgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfSgpIH0gfTsKICAgICAgICBmdW5jdGlvbiBzKGUyKSB7CiAgICAgICAgICB2YXIgdDIgPSA2NTUzNiwgcjIgPSBhLmdldFR5cGVPZihlMiksIG4yID0gdHJ1ZTsKICAgICAgICAgIGlmICgidWludDhhcnJheSIgPT09IHIyID8gbjIgPSBpLmFwcGx5Q2FuQmVVc2VkLnVpbnQ4YXJyYXkgOiAibm9kZWJ1ZmZlciIgPT09IHIyICYmIChuMiA9IGkuYXBwbHlDYW5CZVVzZWQubm9kZWJ1ZmZlciksIG4yKQogICAgICAgICAgICBmb3IgKDsgMSA8IHQyOyApCiAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHJldHVybiBpLnN0cmluZ2lmeUJ5Q2h1bmsoZTIsIHIyLCB0Mik7CiAgICAgICAgICAgICAgfSBjYXRjaCAoZTMpIHsKICAgICAgICAgICAgICAgIHQyID0gTWF0aC5mbG9vcih0MiAvIDIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBpLnN0cmluZ2lmeUJ5Q2hhcihlMik7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGYoZTIsIHQyKSB7CiAgICAgICAgICBmb3IgKHZhciByMiA9IDA7IHIyIDwgZTIubGVuZ3RoOyByMisrKQogICAgICAgICAgICB0MltyMl0gPSBlMltyMl07CiAgICAgICAgICByZXR1cm4gdDI7CiAgICAgICAgfQogICAgICAgIGEuYXBwbHlGcm9tQ2hhckNvZGUgPSBzOwogICAgICAgIHZhciBjID0ge307CiAgICAgICAgYy5zdHJpbmcgPSB7IHN0cmluZzogbiwgYXJyYXk6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICByZXR1cm4gbChlMiwgbmV3IEFycmF5KGUyLmxlbmd0aCkpOwogICAgICAgIH0sIGFycmF5YnVmZmVyOiBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIGMuc3RyaW5nLnVpbnQ4YXJyYXkoZTIpLmJ1ZmZlcjsKICAgICAgICB9LCB1aW50OGFycmF5OiBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIGwoZTIsIG5ldyBVaW50OEFycmF5KGUyLmxlbmd0aCkpOwogICAgICAgIH0sIG5vZGVidWZmZXI6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICByZXR1cm4gbChlMiwgci5hbGxvY0J1ZmZlcihlMi5sZW5ndGgpKTsKICAgICAgICB9IH0sIGMuYXJyYXkgPSB7IHN0cmluZzogcywgYXJyYXk6IG4sIGFycmF5YnVmZmVyOiBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGUyKS5idWZmZXI7CiAgICAgICAgfSwgdWludDhhcnJheTogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShlMik7CiAgICAgICAgfSwgbm9kZWJ1ZmZlcjogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiByLm5ld0J1ZmZlckZyb20oZTIpOwogICAgICAgIH0gfSwgYy5hcnJheWJ1ZmZlciA9IHsgc3RyaW5nOiBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIHMobmV3IFVpbnQ4QXJyYXkoZTIpKTsKICAgICAgICB9LCBhcnJheTogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiBmKG5ldyBVaW50OEFycmF5KGUyKSwgbmV3IEFycmF5KGUyLmJ5dGVMZW5ndGgpKTsKICAgICAgICB9LCBhcnJheWJ1ZmZlcjogbiwgdWludDhhcnJheTogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheShlMik7CiAgICAgICAgfSwgbm9kZWJ1ZmZlcjogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiByLm5ld0J1ZmZlckZyb20obmV3IFVpbnQ4QXJyYXkoZTIpKTsKICAgICAgICB9IH0sIGMudWludDhhcnJheSA9IHsgc3RyaW5nOiBzLCBhcnJheTogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiBmKGUyLCBuZXcgQXJyYXkoZTIubGVuZ3RoKSk7CiAgICAgICAgfSwgYXJyYXlidWZmZXI6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICByZXR1cm4gZTIuYnVmZmVyOwogICAgICAgIH0sIHVpbnQ4YXJyYXk6IG4sIG5vZGVidWZmZXI6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICByZXR1cm4gci5uZXdCdWZmZXJGcm9tKGUyKTsKICAgICAgICB9IH0sIGMubm9kZWJ1ZmZlciA9IHsgc3RyaW5nOiBzLCBhcnJheTogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHJldHVybiBmKGUyLCBuZXcgQXJyYXkoZTIubGVuZ3RoKSk7CiAgICAgICAgfSwgYXJyYXlidWZmZXI6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICByZXR1cm4gYy5ub2RlYnVmZmVyLnVpbnQ4YXJyYXkoZTIpLmJ1ZmZlcjsKICAgICAgICB9LCB1aW50OGFycmF5OiBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIGYoZTIsIG5ldyBVaW50OEFycmF5KGUyLmxlbmd0aCkpOwogICAgICAgIH0sIG5vZGVidWZmZXI6IG4gfSwgYS50cmFuc2Zvcm1UbyA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgaWYgKHQyID0gdDIgfHwgIiIsICFlMikKICAgICAgICAgICAgcmV0dXJuIHQyOwogICAgICAgICAgYS5jaGVja1N1cHBvcnQoZTIpOwogICAgICAgICAgdmFyIHIyID0gYS5nZXRUeXBlT2YodDIpOwogICAgICAgICAgcmV0dXJuIGNbcjJdW2UyXSh0Mik7CiAgICAgICAgfSwgYS5yZXNvbHZlID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGZvciAodmFyIHQyID0gZTIuc3BsaXQoIi8iKSwgcjIgPSBbXSwgbjIgPSAwOyBuMiA8IHQyLmxlbmd0aDsgbjIrKykgewogICAgICAgICAgICB2YXIgaTIgPSB0MltuMl07CiAgICAgICAgICAgICIuIiA9PT0gaTIgfHwgIiIgPT09IGkyICYmIDAgIT09IG4yICYmIG4yICE9PSB0Mi5sZW5ndGggLSAxIHx8ICgiLi4iID09PSBpMiA/IHIyLnBvcCgpIDogcjIucHVzaChpMikpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHIyLmpvaW4oIi8iKTsKICAgICAgICB9LCBhLmdldFR5cGVPZiA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICByZXR1cm4gInN0cmluZyIgPT0gdHlwZW9mIGUyID8gInN0cmluZyIgOiAiW29iamVjdCBBcnJheV0iID09PSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZTIpID8gImFycmF5IiA6IG8ubm9kZWJ1ZmZlciAmJiByLmlzQnVmZmVyKGUyKSA/ICJub2RlYnVmZmVyIiA6IG8udWludDhhcnJheSAmJiBlMiBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgPyAidWludDhhcnJheSIgOiBvLmFycmF5YnVmZmVyICYmIGUyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgPyAiYXJyYXlidWZmZXIiIDogdm9pZCAwOwogICAgICAgIH0sIGEuY2hlY2tTdXBwb3J0ID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGlmICghb1tlMi50b0xvd2VyQ2FzZSgpXSkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGUyICsgIiBpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoaXMgcGxhdGZvcm0iKTsKICAgICAgICB9LCBhLk1BWF9WQUxVRV8xNkJJVFMgPSA2NTUzNSwgYS5NQVhfVkFMVUVfMzJCSVRTID0gLTEsIGEucHJldHR5ID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHZhciB0MiwgcjIsIG4yID0gIiI7CiAgICAgICAgICBmb3IgKHIyID0gMDsgcjIgPCAoZTIgfHwgIiIpLmxlbmd0aDsgcjIrKykKICAgICAgICAgICAgbjIgKz0gIlxceCIgKyAoKHQyID0gZTIuY2hhckNvZGVBdChyMikpIDwgMTYgPyAiMCIgOiAiIikgKyB0Mi50b1N0cmluZygxNikudG9VcHBlckNhc2UoKTsKICAgICAgICAgIHJldHVybiBuMjsKICAgICAgICB9LCBhLmRlbGF5ID0gZnVuY3Rpb24oZTIsIHQyLCByMikgewogICAgICAgICAgc2V0SW1tZWRpYXRlKGZ1bmN0aW9uKCkgewogICAgICAgICAgICBlMi5hcHBseShyMiB8fCBudWxsLCB0MiB8fCBbXSk7CiAgICAgICAgICB9KTsKICAgICAgICB9LCBhLmluaGVyaXRzID0gZnVuY3Rpb24oZTIsIHQyKSB7CiAgICAgICAgICBmdW5jdGlvbiByMigpIHsKICAgICAgICAgIH0KICAgICAgICAgIHIyLnByb3RvdHlwZSA9IHQyLnByb3RvdHlwZSwgZTIucHJvdG90eXBlID0gbmV3IHIyKCk7CiAgICAgICAgfSwgYS5leHRlbmQgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIHZhciBlMiwgdDIsIHIyID0ge307CiAgICAgICAgICBmb3IgKGUyID0gMDsgZTIgPCBhcmd1bWVudHMubGVuZ3RoOyBlMisrKQogICAgICAgICAgICBmb3IgKHQyIGluIGFyZ3VtZW50c1tlMl0pCiAgICAgICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGFyZ3VtZW50c1tlMl0sIHQyKSAmJiB2b2lkIDAgPT09IHIyW3QyXSAmJiAocjJbdDJdID0gYXJndW1lbnRzW2UyXVt0Ml0pOwogICAgICAgICAgcmV0dXJuIHIyOwogICAgICAgIH0sIGEucHJlcGFyZUNvbnRlbnQgPSBmdW5jdGlvbihyMiwgZTIsIG4yLCBpMiwgczIpIHsKICAgICAgICAgIHJldHVybiB1LlByb21pc2UucmVzb2x2ZShlMikudGhlbihmdW5jdGlvbihuMykgewogICAgICAgICAgICByZXR1cm4gby5ibG9iICYmIChuMyBpbnN0YW5jZW9mIEJsb2IgfHwgLTEgIT09IFsiW29iamVjdCBGaWxlXSIsICJbb2JqZWN0IEJsb2JdIl0uaW5kZXhPZihPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobjMpKSkgJiYgInVuZGVmaW5lZCIgIT0gdHlwZW9mIEZpbGVSZWFkZXIgPyBuZXcgdS5Qcm9taXNlKGZ1bmN0aW9uKHQyLCByMykgewogICAgICAgICAgICAgIHZhciBlMyA9IG5ldyBGaWxlUmVhZGVyKCk7CiAgICAgICAgICAgICAgZTMub25sb2FkID0gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgICAgIHQyKGU0LnRhcmdldC5yZXN1bHQpOwogICAgICAgICAgICAgIH0sIGUzLm9uZXJyb3IgPSBmdW5jdGlvbihlNCkgewogICAgICAgICAgICAgICAgcjMoZTQudGFyZ2V0LmVycm9yKTsKICAgICAgICAgICAgICB9LCBlMy5yZWFkQXNBcnJheUJ1ZmZlcihuMyk7CiAgICAgICAgICAgIH0pIDogbjM7CiAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIHZhciB0MiA9IGEuZ2V0VHlwZU9mKGUzKTsKICAgICAgICAgICAgcmV0dXJuIHQyID8gKCJhcnJheWJ1ZmZlciIgPT09IHQyID8gZTMgPSBhLnRyYW5zZm9ybVRvKCJ1aW50OGFycmF5IiwgZTMpIDogInN0cmluZyIgPT09IHQyICYmIChzMiA/IGUzID0gaC5kZWNvZGUoZTMpIDogbjIgJiYgdHJ1ZSAhPT0gaTIgJiYgKGUzID0gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgICByZXR1cm4gbChlNCwgby51aW50OGFycmF5ID8gbmV3IFVpbnQ4QXJyYXkoZTQubGVuZ3RoKSA6IG5ldyBBcnJheShlNC5sZW5ndGgpKTsKICAgICAgICAgICAgfShlMykpKSwgZTMpIDogdS5Qcm9taXNlLnJlamVjdChuZXcgRXJyb3IoIkNhbid0IHJlYWQgdGhlIGRhdGEgb2YgJyIgKyByMiArICInLiBJcyBpdCBpbiBhIHN1cHBvcnRlZCBKYXZhU2NyaXB0IHR5cGUgKFN0cmluZywgQmxvYiwgQXJyYXlCdWZmZXIsIGV0YykgPyIpKTsKICAgICAgICAgIH0pOwogICAgICAgIH07CiAgICAgIH0sIHsgIi4vYmFzZTY0IjogMSwgIi4vZXh0ZXJuYWwiOiA2LCAiLi9ub2RlanNVdGlscyI6IDE0LCAiLi9zdXBwb3J0IjogMzAsIHNldGltbWVkaWF0ZTogNTQgfV0sIDMzOiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBuID0gZSgiLi9yZWFkZXIvcmVhZGVyRm9yIiksIGkgPSBlKCIuL3V0aWxzIiksIHMgPSBlKCIuL3NpZ25hdHVyZSIpLCBhID0gZSgiLi96aXBFbnRyeSIpLCBvID0gZSgiLi9zdXBwb3J0Iik7CiAgICAgICAgZnVuY3Rpb24gaChlMikgewogICAgICAgICAgdGhpcy5maWxlcyA9IFtdLCB0aGlzLmxvYWRPcHRpb25zID0gZTI7CiAgICAgICAgfQogICAgICAgIGgucHJvdG90eXBlID0geyBjaGVja1NpZ25hdHVyZTogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGlmICghdGhpcy5yZWFkZXIucmVhZEFuZENoZWNrU2lnbmF0dXJlKGUyKSkgewogICAgICAgICAgICB0aGlzLnJlYWRlci5pbmRleCAtPSA0OwogICAgICAgICAgICB2YXIgdDIgPSB0aGlzLnJlYWRlci5yZWFkU3RyaW5nKDQpOwogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkNvcnJ1cHRlZCB6aXAgb3IgYnVnOiB1bmV4cGVjdGVkIHNpZ25hdHVyZSAoIiArIGkucHJldHR5KHQyKSArICIsIGV4cGVjdGVkICIgKyBpLnByZXR0eShlMikgKyAiKSIpOwogICAgICAgICAgfQogICAgICAgIH0sIGlzU2lnbmF0dXJlOiBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiA9IHRoaXMucmVhZGVyLmluZGV4OwogICAgICAgICAgdGhpcy5yZWFkZXIuc2V0SW5kZXgoZTIpOwogICAgICAgICAgdmFyIG4yID0gdGhpcy5yZWFkZXIucmVhZFN0cmluZyg0KSA9PT0gdDI7CiAgICAgICAgICByZXR1cm4gdGhpcy5yZWFkZXIuc2V0SW5kZXgocjIpLCBuMjsKICAgICAgICB9LCByZWFkQmxvY2tFbmRPZkNlbnRyYWw6IGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy5kaXNrTnVtYmVyID0gdGhpcy5yZWFkZXIucmVhZEludCgyKSwgdGhpcy5kaXNrV2l0aENlbnRyYWxEaXJTdGFydCA9IHRoaXMucmVhZGVyLnJlYWRJbnQoMiksIHRoaXMuY2VudHJhbERpclJlY29yZHNPblRoaXNEaXNrID0gdGhpcy5yZWFkZXIucmVhZEludCgyKSwgdGhpcy5jZW50cmFsRGlyUmVjb3JkcyA9IHRoaXMucmVhZGVyLnJlYWRJbnQoMiksIHRoaXMuY2VudHJhbERpclNpemUgPSB0aGlzLnJlYWRlci5yZWFkSW50KDQpLCB0aGlzLmNlbnRyYWxEaXJPZmZzZXQgPSB0aGlzLnJlYWRlci5yZWFkSW50KDQpLCB0aGlzLnppcENvbW1lbnRMZW5ndGggPSB0aGlzLnJlYWRlci5yZWFkSW50KDIpOwogICAgICAgICAgdmFyIGUyID0gdGhpcy5yZWFkZXIucmVhZERhdGEodGhpcy56aXBDb21tZW50TGVuZ3RoKSwgdDIgPSBvLnVpbnQ4YXJyYXkgPyAidWludDhhcnJheSIgOiAiYXJyYXkiLCByMiA9IGkudHJhbnNmb3JtVG8odDIsIGUyKTsKICAgICAgICAgIHRoaXMuemlwQ29tbWVudCA9IHRoaXMubG9hZE9wdGlvbnMuZGVjb2RlRmlsZU5hbWUocjIpOwogICAgICAgIH0sIHJlYWRCbG9ja1ppcDY0RW5kT2ZDZW50cmFsOiBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMuemlwNjRFbmRPZkNlbnRyYWxTaXplID0gdGhpcy5yZWFkZXIucmVhZEludCg4KSwgdGhpcy5yZWFkZXIuc2tpcCg0KSwgdGhpcy5kaXNrTnVtYmVyID0gdGhpcy5yZWFkZXIucmVhZEludCg0KSwgdGhpcy5kaXNrV2l0aENlbnRyYWxEaXJTdGFydCA9IHRoaXMucmVhZGVyLnJlYWRJbnQoNCksIHRoaXMuY2VudHJhbERpclJlY29yZHNPblRoaXNEaXNrID0gdGhpcy5yZWFkZXIucmVhZEludCg4KSwgdGhpcy5jZW50cmFsRGlyUmVjb3JkcyA9IHRoaXMucmVhZGVyLnJlYWRJbnQoOCksIHRoaXMuY2VudHJhbERpclNpemUgPSB0aGlzLnJlYWRlci5yZWFkSW50KDgpLCB0aGlzLmNlbnRyYWxEaXJPZmZzZXQgPSB0aGlzLnJlYWRlci5yZWFkSW50KDgpLCB0aGlzLnppcDY0RXh0ZW5zaWJsZURhdGEgPSB7fTsKICAgICAgICAgIGZvciAodmFyIGUyLCB0MiwgcjIsIG4yID0gdGhpcy56aXA2NEVuZE9mQ2VudHJhbFNpemUgLSA0NDsgMCA8IG4yOyApCiAgICAgICAgICAgIGUyID0gdGhpcy5yZWFkZXIucmVhZEludCgyKSwgdDIgPSB0aGlzLnJlYWRlci5yZWFkSW50KDQpLCByMiA9IHRoaXMucmVhZGVyLnJlYWREYXRhKHQyKSwgdGhpcy56aXA2NEV4dGVuc2libGVEYXRhW2UyXSA9IHsgaWQ6IGUyLCBsZW5ndGg6IHQyLCB2YWx1ZTogcjIgfTsKICAgICAgICB9LCByZWFkQmxvY2taaXA2NEVuZE9mQ2VudHJhbExvY2F0b3I6IGZ1bmN0aW9uKCkgewogICAgICAgICAgaWYgKHRoaXMuZGlza1dpdGhaaXA2NENlbnRyYWxEaXJTdGFydCA9IHRoaXMucmVhZGVyLnJlYWRJbnQoNCksIHRoaXMucmVsYXRpdmVPZmZzZXRFbmRPZlppcDY0Q2VudHJhbERpciA9IHRoaXMucmVhZGVyLnJlYWRJbnQoOCksIHRoaXMuZGlza3NDb3VudCA9IHRoaXMucmVhZGVyLnJlYWRJbnQoNCksIDEgPCB0aGlzLmRpc2tzQ291bnQpCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiTXVsdGktdm9sdW1lcyB6aXAgYXJlIG5vdCBzdXBwb3J0ZWQiKTsKICAgICAgICB9LCByZWFkTG9jYWxGaWxlczogZnVuY3Rpb24oKSB7CiAgICAgICAgICB2YXIgZTIsIHQyOwogICAgICAgICAgZm9yIChlMiA9IDA7IGUyIDwgdGhpcy5maWxlcy5sZW5ndGg7IGUyKyspCiAgICAgICAgICAgIHQyID0gdGhpcy5maWxlc1tlMl0sIHRoaXMucmVhZGVyLnNldEluZGV4KHQyLmxvY2FsSGVhZGVyT2Zmc2V0KSwgdGhpcy5jaGVja1NpZ25hdHVyZShzLkxPQ0FMX0ZJTEVfSEVBREVSKSwgdDIucmVhZExvY2FsUGFydCh0aGlzLnJlYWRlciksIHQyLmhhbmRsZVVURjgoKSwgdDIucHJvY2Vzc0F0dHJpYnV0ZXMoKTsKICAgICAgICB9LCByZWFkQ2VudHJhbERpcjogZnVuY3Rpb24oKSB7CiAgICAgICAgICB2YXIgZTI7CiAgICAgICAgICBmb3IgKHRoaXMucmVhZGVyLnNldEluZGV4KHRoaXMuY2VudHJhbERpck9mZnNldCk7IHRoaXMucmVhZGVyLnJlYWRBbmRDaGVja1NpZ25hdHVyZShzLkNFTlRSQUxfRklMRV9IRUFERVIpOyApCiAgICAgICAgICAgIChlMiA9IG5ldyBhKHsgemlwNjQ6IHRoaXMuemlwNjQgfSwgdGhpcy5sb2FkT3B0aW9ucykpLnJlYWRDZW50cmFsUGFydCh0aGlzLnJlYWRlciksIHRoaXMuZmlsZXMucHVzaChlMik7CiAgICAgICAgICBpZiAodGhpcy5jZW50cmFsRGlyUmVjb3JkcyAhPT0gdGhpcy5maWxlcy5sZW5ndGggJiYgMCAhPT0gdGhpcy5jZW50cmFsRGlyUmVjb3JkcyAmJiAwID09PSB0aGlzLmZpbGVzLmxlbmd0aCkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDb3JydXB0ZWQgemlwIG9yIGJ1ZzogZXhwZWN0ZWQgIiArIHRoaXMuY2VudHJhbERpclJlY29yZHMgKyAiIHJlY29yZHMgaW4gY2VudHJhbCBkaXIsIGdvdCAiICsgdGhpcy5maWxlcy5sZW5ndGgpOwogICAgICAgIH0sIHJlYWRFbmRPZkNlbnRyYWw6IGZ1bmN0aW9uKCkgewogICAgICAgICAgdmFyIGUyID0gdGhpcy5yZWFkZXIubGFzdEluZGV4T2ZTaWduYXR1cmUocy5DRU5UUkFMX0RJUkVDVE9SWV9FTkQpOwogICAgICAgICAgaWYgKGUyIDwgMCkKICAgICAgICAgICAgdGhyb3cgIXRoaXMuaXNTaWduYXR1cmUoMCwgcy5MT0NBTF9GSUxFX0hFQURFUikgPyBuZXcgRXJyb3IoIkNhbid0IGZpbmQgZW5kIG9mIGNlbnRyYWwgZGlyZWN0b3J5IDogaXMgdGhpcyBhIHppcCBmaWxlID8gSWYgaXQgaXMsIHNlZSBodHRwczovL3N0dWsuZ2l0aHViLmlvL2pzemlwL2RvY3VtZW50YXRpb24vaG93dG8vcmVhZF96aXAuaHRtbCIpIDogbmV3IEVycm9yKCJDb3JydXB0ZWQgemlwOiBjYW4ndCBmaW5kIGVuZCBvZiBjZW50cmFsIGRpcmVjdG9yeSIpOwogICAgICAgICAgdGhpcy5yZWFkZXIuc2V0SW5kZXgoZTIpOwogICAgICAgICAgdmFyIHQyID0gZTI7CiAgICAgICAgICBpZiAodGhpcy5jaGVja1NpZ25hdHVyZShzLkNFTlRSQUxfRElSRUNUT1JZX0VORCksIHRoaXMucmVhZEJsb2NrRW5kT2ZDZW50cmFsKCksIHRoaXMuZGlza051bWJlciA9PT0gaS5NQVhfVkFMVUVfMTZCSVRTIHx8IHRoaXMuZGlza1dpdGhDZW50cmFsRGlyU3RhcnQgPT09IGkuTUFYX1ZBTFVFXzE2QklUUyB8fCB0aGlzLmNlbnRyYWxEaXJSZWNvcmRzT25UaGlzRGlzayA9PT0gaS5NQVhfVkFMVUVfMTZCSVRTIHx8IHRoaXMuY2VudHJhbERpclJlY29yZHMgPT09IGkuTUFYX1ZBTFVFXzE2QklUUyB8fCB0aGlzLmNlbnRyYWxEaXJTaXplID09PSBpLk1BWF9WQUxVRV8zMkJJVFMgfHwgdGhpcy5jZW50cmFsRGlyT2Zmc2V0ID09PSBpLk1BWF9WQUxVRV8zMkJJVFMpIHsKICAgICAgICAgICAgaWYgKHRoaXMuemlwNjQgPSB0cnVlLCAoZTIgPSB0aGlzLnJlYWRlci5sYXN0SW5kZXhPZlNpZ25hdHVyZShzLlpJUDY0X0NFTlRSQUxfRElSRUNUT1JZX0xPQ0FUT1IpKSA8IDApCiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDb3JydXB0ZWQgemlwOiBjYW4ndCBmaW5kIHRoZSBaSVA2NCBlbmQgb2YgY2VudHJhbCBkaXJlY3RvcnkgbG9jYXRvciIpOwogICAgICAgICAgICBpZiAodGhpcy5yZWFkZXIuc2V0SW5kZXgoZTIpLCB0aGlzLmNoZWNrU2lnbmF0dXJlKHMuWklQNjRfQ0VOVFJBTF9ESVJFQ1RPUllfTE9DQVRPUiksIHRoaXMucmVhZEJsb2NrWmlwNjRFbmRPZkNlbnRyYWxMb2NhdG9yKCksICF0aGlzLmlzU2lnbmF0dXJlKHRoaXMucmVsYXRpdmVPZmZzZXRFbmRPZlppcDY0Q2VudHJhbERpciwgcy5aSVA2NF9DRU5UUkFMX0RJUkVDVE9SWV9FTkQpICYmICh0aGlzLnJlbGF0aXZlT2Zmc2V0RW5kT2ZaaXA2NENlbnRyYWxEaXIgPSB0aGlzLnJlYWRlci5sYXN0SW5kZXhPZlNpZ25hdHVyZShzLlpJUDY0X0NFTlRSQUxfRElSRUNUT1JZX0VORCksIHRoaXMucmVsYXRpdmVPZmZzZXRFbmRPZlppcDY0Q2VudHJhbERpciA8IDApKQogICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiQ29ycnVwdGVkIHppcDogY2FuJ3QgZmluZCB0aGUgWklQNjQgZW5kIG9mIGNlbnRyYWwgZGlyZWN0b3J5Iik7CiAgICAgICAgICAgIHRoaXMucmVhZGVyLnNldEluZGV4KHRoaXMucmVsYXRpdmVPZmZzZXRFbmRPZlppcDY0Q2VudHJhbERpciksIHRoaXMuY2hlY2tTaWduYXR1cmUocy5aSVA2NF9DRU5UUkFMX0RJUkVDVE9SWV9FTkQpLCB0aGlzLnJlYWRCbG9ja1ppcDY0RW5kT2ZDZW50cmFsKCk7CiAgICAgICAgICB9CiAgICAgICAgICB2YXIgcjIgPSB0aGlzLmNlbnRyYWxEaXJPZmZzZXQgKyB0aGlzLmNlbnRyYWxEaXJTaXplOwogICAgICAgICAgdGhpcy56aXA2NCAmJiAocjIgKz0gMjAsIHIyICs9IDEyICsgdGhpcy56aXA2NEVuZE9mQ2VudHJhbFNpemUpOwogICAgICAgICAgdmFyIG4yID0gdDIgLSByMjsKICAgICAgICAgIGlmICgwIDwgbjIpCiAgICAgICAgICAgIHRoaXMuaXNTaWduYXR1cmUodDIsIHMuQ0VOVFJBTF9GSUxFX0hFQURFUikgfHwgKHRoaXMucmVhZGVyLnplcm8gPSBuMik7CiAgICAgICAgICBlbHNlIGlmIChuMiA8IDApCiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiQ29ycnVwdGVkIHppcDogbWlzc2luZyAiICsgTWF0aC5hYnMobjIpICsgIiBieXRlcy4iKTsKICAgICAgICB9LCBwcmVwYXJlUmVhZGVyOiBmdW5jdGlvbihlMikgewogICAgICAgICAgdGhpcy5yZWFkZXIgPSBuKGUyKTsKICAgICAgICB9LCBsb2FkOiBmdW5jdGlvbihlMikgewogICAgICAgICAgdGhpcy5wcmVwYXJlUmVhZGVyKGUyKSwgdGhpcy5yZWFkRW5kT2ZDZW50cmFsKCksIHRoaXMucmVhZENlbnRyYWxEaXIoKSwgdGhpcy5yZWFkTG9jYWxGaWxlcygpOwogICAgICAgIH0gfSwgdC5leHBvcnRzID0gaDsKICAgICAgfSwgeyAiLi9yZWFkZXIvcmVhZGVyRm9yIjogMjIsICIuL3NpZ25hdHVyZSI6IDIzLCAiLi9zdXBwb3J0IjogMzAsICIuL3V0aWxzIjogMzIsICIuL3ppcEVudHJ5IjogMzQgfV0sIDM0OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBuID0gZSgiLi9yZWFkZXIvcmVhZGVyRm9yIiksIHMgPSBlKCIuL3V0aWxzIiksIGkgPSBlKCIuL2NvbXByZXNzZWRPYmplY3QiKSwgYSA9IGUoIi4vY3JjMzIiKSwgbyA9IGUoIi4vdXRmOCIpLCBoID0gZSgiLi9jb21wcmVzc2lvbnMiKSwgdSA9IGUoIi4vc3VwcG9ydCIpOwogICAgICAgIGZ1bmN0aW9uIGwoZTIsIHQyKSB7CiAgICAgICAgICB0aGlzLm9wdGlvbnMgPSBlMiwgdGhpcy5sb2FkT3B0aW9ucyA9IHQyOwogICAgICAgIH0KICAgICAgICBsLnByb3RvdHlwZSA9IHsgaXNFbmNyeXB0ZWQ6IGZ1bmN0aW9uKCkgewogICAgICAgICAgcmV0dXJuIDEgPT0gKDEgJiB0aGlzLmJpdEZsYWcpOwogICAgICAgIH0sIHVzZVVURjg6IGZ1bmN0aW9uKCkgewogICAgICAgICAgcmV0dXJuIDIwNDggPT0gKDIwNDggJiB0aGlzLmJpdEZsYWcpOwogICAgICAgIH0sIHJlYWRMb2NhbFBhcnQ6IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB2YXIgdDIsIHIyOwogICAgICAgICAgaWYgKGUyLnNraXAoMjIpLCB0aGlzLmZpbGVOYW1lTGVuZ3RoID0gZTIucmVhZEludCgyKSwgcjIgPSBlMi5yZWFkSW50KDIpLCB0aGlzLmZpbGVOYW1lID0gZTIucmVhZERhdGEodGhpcy5maWxlTmFtZUxlbmd0aCksIGUyLnNraXAocjIpLCAtMSA9PT0gdGhpcy5jb21wcmVzc2VkU2l6ZSB8fCAtMSA9PT0gdGhpcy51bmNvbXByZXNzZWRTaXplKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkJ1ZyBvciBjb3JydXB0ZWQgemlwIDogZGlkbid0IGdldCBlbm91Z2ggaW5mb3JtYXRpb24gZnJvbSB0aGUgY2VudHJhbCBkaXJlY3RvcnkgKGNvbXByZXNzZWRTaXplID09PSAtMSB8fCB1bmNvbXByZXNzZWRTaXplID09PSAtMSkiKTsKICAgICAgICAgIGlmIChudWxsID09PSAodDIgPSBmdW5jdGlvbihlMykgewogICAgICAgICAgICBmb3IgKHZhciB0MyBpbiBoKQogICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoaCwgdDMpICYmIGhbdDNdLm1hZ2ljID09PSBlMykKICAgICAgICAgICAgICAgIHJldHVybiBoW3QzXTsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9KHRoaXMuY29tcHJlc3Npb25NZXRob2QpKSkKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDb3JydXB0ZWQgemlwIDogY29tcHJlc3Npb24gIiArIHMucHJldHR5KHRoaXMuY29tcHJlc3Npb25NZXRob2QpICsgIiB1bmtub3duIChpbm5lciBmaWxlIDogIiArIHMudHJhbnNmb3JtVG8oInN0cmluZyIsIHRoaXMuZmlsZU5hbWUpICsgIikiKTsKICAgICAgICAgIHRoaXMuZGVjb21wcmVzc2VkID0gbmV3IGkodGhpcy5jb21wcmVzc2VkU2l6ZSwgdGhpcy51bmNvbXByZXNzZWRTaXplLCB0aGlzLmNyYzMyLCB0MiwgZTIucmVhZERhdGEodGhpcy5jb21wcmVzc2VkU2l6ZSkpOwogICAgICAgIH0sIHJlYWRDZW50cmFsUGFydDogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHRoaXMudmVyc2lvbk1hZGVCeSA9IGUyLnJlYWRJbnQoMiksIGUyLnNraXAoMiksIHRoaXMuYml0RmxhZyA9IGUyLnJlYWRJbnQoMiksIHRoaXMuY29tcHJlc3Npb25NZXRob2QgPSBlMi5yZWFkU3RyaW5nKDIpLCB0aGlzLmRhdGUgPSBlMi5yZWFkRGF0ZSgpLCB0aGlzLmNyYzMyID0gZTIucmVhZEludCg0KSwgdGhpcy5jb21wcmVzc2VkU2l6ZSA9IGUyLnJlYWRJbnQoNCksIHRoaXMudW5jb21wcmVzc2VkU2l6ZSA9IGUyLnJlYWRJbnQoNCk7CiAgICAgICAgICB2YXIgdDIgPSBlMi5yZWFkSW50KDIpOwogICAgICAgICAgaWYgKHRoaXMuZXh0cmFGaWVsZHNMZW5ndGggPSBlMi5yZWFkSW50KDIpLCB0aGlzLmZpbGVDb21tZW50TGVuZ3RoID0gZTIucmVhZEludCgyKSwgdGhpcy5kaXNrTnVtYmVyU3RhcnQgPSBlMi5yZWFkSW50KDIpLCB0aGlzLmludGVybmFsRmlsZUF0dHJpYnV0ZXMgPSBlMi5yZWFkSW50KDIpLCB0aGlzLmV4dGVybmFsRmlsZUF0dHJpYnV0ZXMgPSBlMi5yZWFkSW50KDQpLCB0aGlzLmxvY2FsSGVhZGVyT2Zmc2V0ID0gZTIucmVhZEludCg0KSwgdGhpcy5pc0VuY3J5cHRlZCgpKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkVuY3J5cHRlZCB6aXAgYXJlIG5vdCBzdXBwb3J0ZWQiKTsKICAgICAgICAgIGUyLnNraXAodDIpLCB0aGlzLnJlYWRFeHRyYUZpZWxkcyhlMiksIHRoaXMucGFyc2VaSVA2NEV4dHJhRmllbGQoZTIpLCB0aGlzLmZpbGVDb21tZW50ID0gZTIucmVhZERhdGEodGhpcy5maWxlQ29tbWVudExlbmd0aCk7CiAgICAgICAgfSwgcHJvY2Vzc0F0dHJpYnV0ZXM6IGZ1bmN0aW9uKCkgewogICAgICAgICAgdGhpcy51bml4UGVybWlzc2lvbnMgPSBudWxsLCB0aGlzLmRvc1Blcm1pc3Npb25zID0gbnVsbDsKICAgICAgICAgIHZhciBlMiA9IHRoaXMudmVyc2lvbk1hZGVCeSA+PiA4OwogICAgICAgICAgdGhpcy5kaXIgPSAhISgxNiAmIHRoaXMuZXh0ZXJuYWxGaWxlQXR0cmlidXRlcyksIDAgPT0gZTIgJiYgKHRoaXMuZG9zUGVybWlzc2lvbnMgPSA2MyAmIHRoaXMuZXh0ZXJuYWxGaWxlQXR0cmlidXRlcyksIDMgPT0gZTIgJiYgKHRoaXMudW5peFBlcm1pc3Npb25zID0gdGhpcy5leHRlcm5hbEZpbGVBdHRyaWJ1dGVzID4+IDE2ICYgNjU1MzUpLCB0aGlzLmRpciB8fCAiLyIgIT09IHRoaXMuZmlsZU5hbWVTdHIuc2xpY2UoLTEpIHx8ICh0aGlzLmRpciA9IHRydWUpOwogICAgICAgIH0sIHBhcnNlWklQNjRFeHRyYUZpZWxkOiBmdW5jdGlvbigpIHsKICAgICAgICAgIGlmICh0aGlzLmV4dHJhRmllbGRzWzFdKSB7CiAgICAgICAgICAgIHZhciBlMiA9IG4odGhpcy5leHRyYUZpZWxkc1sxXS52YWx1ZSk7CiAgICAgICAgICAgIHRoaXMudW5jb21wcmVzc2VkU2l6ZSA9PT0gcy5NQVhfVkFMVUVfMzJCSVRTICYmICh0aGlzLnVuY29tcHJlc3NlZFNpemUgPSBlMi5yZWFkSW50KDgpKSwgdGhpcy5jb21wcmVzc2VkU2l6ZSA9PT0gcy5NQVhfVkFMVUVfMzJCSVRTICYmICh0aGlzLmNvbXByZXNzZWRTaXplID0gZTIucmVhZEludCg4KSksIHRoaXMubG9jYWxIZWFkZXJPZmZzZXQgPT09IHMuTUFYX1ZBTFVFXzMyQklUUyAmJiAodGhpcy5sb2NhbEhlYWRlck9mZnNldCA9IGUyLnJlYWRJbnQoOCkpLCB0aGlzLmRpc2tOdW1iZXJTdGFydCA9PT0gcy5NQVhfVkFMVUVfMzJCSVRTICYmICh0aGlzLmRpc2tOdW1iZXJTdGFydCA9IGUyLnJlYWRJbnQoNCkpOwogICAgICAgICAgfQogICAgICAgIH0sIHJlYWRFeHRyYUZpZWxkczogZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHZhciB0MiwgcjIsIG4yLCBpMiA9IGUyLmluZGV4ICsgdGhpcy5leHRyYUZpZWxkc0xlbmd0aDsKICAgICAgICAgIGZvciAodGhpcy5leHRyYUZpZWxkcyB8fCAodGhpcy5leHRyYUZpZWxkcyA9IHt9KTsgZTIuaW5kZXggKyA0IDwgaTI7ICkKICAgICAgICAgICAgdDIgPSBlMi5yZWFkSW50KDIpLCByMiA9IGUyLnJlYWRJbnQoMiksIG4yID0gZTIucmVhZERhdGEocjIpLCB0aGlzLmV4dHJhRmllbGRzW3QyXSA9IHsgaWQ6IHQyLCBsZW5ndGg6IHIyLCB2YWx1ZTogbjIgfTsKICAgICAgICAgIGUyLnNldEluZGV4KGkyKTsKICAgICAgICB9LCBoYW5kbGVVVEY4OiBmdW5jdGlvbigpIHsKICAgICAgICAgIHZhciBlMiA9IHUudWludDhhcnJheSA/ICJ1aW50OGFycmF5IiA6ICJhcnJheSI7CiAgICAgICAgICBpZiAodGhpcy51c2VVVEY4KCkpCiAgICAgICAgICAgIHRoaXMuZmlsZU5hbWVTdHIgPSBvLnV0ZjhkZWNvZGUodGhpcy5maWxlTmFtZSksIHRoaXMuZmlsZUNvbW1lbnRTdHIgPSBvLnV0ZjhkZWNvZGUodGhpcy5maWxlQ29tbWVudCk7CiAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgdmFyIHQyID0gdGhpcy5maW5kRXh0cmFGaWVsZFVuaWNvZGVQYXRoKCk7CiAgICAgICAgICAgIGlmIChudWxsICE9PSB0MikKICAgICAgICAgICAgICB0aGlzLmZpbGVOYW1lU3RyID0gdDI7CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgIHZhciByMiA9IHMudHJhbnNmb3JtVG8oZTIsIHRoaXMuZmlsZU5hbWUpOwogICAgICAgICAgICAgIHRoaXMuZmlsZU5hbWVTdHIgPSB0aGlzLmxvYWRPcHRpb25zLmRlY29kZUZpbGVOYW1lKHIyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgbjIgPSB0aGlzLmZpbmRFeHRyYUZpZWxkVW5pY29kZUNvbW1lbnQoKTsKICAgICAgICAgICAgaWYgKG51bGwgIT09IG4yKQogICAgICAgICAgICAgIHRoaXMuZmlsZUNvbW1lbnRTdHIgPSBuMjsKICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgdmFyIGkyID0gcy50cmFuc2Zvcm1UbyhlMiwgdGhpcy5maWxlQ29tbWVudCk7CiAgICAgICAgICAgICAgdGhpcy5maWxlQ29tbWVudFN0ciA9IHRoaXMubG9hZE9wdGlvbnMuZGVjb2RlRmlsZU5hbWUoaTIpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSwgZmluZEV4dHJhRmllbGRVbmljb2RlUGF0aDogZnVuY3Rpb24oKSB7CiAgICAgICAgICB2YXIgZTIgPSB0aGlzLmV4dHJhRmllbGRzWzI4Nzg5XTsKICAgICAgICAgIGlmIChlMikgewogICAgICAgICAgICB2YXIgdDIgPSBuKGUyLnZhbHVlKTsKICAgICAgICAgICAgcmV0dXJuIDEgIT09IHQyLnJlYWRJbnQoMSkgPyBudWxsIDogYSh0aGlzLmZpbGVOYW1lKSAhPT0gdDIucmVhZEludCg0KSA/IG51bGwgOiBvLnV0ZjhkZWNvZGUodDIucmVhZERhdGEoZTIubGVuZ3RoIC0gNSkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfSwgZmluZEV4dHJhRmllbGRVbmljb2RlQ29tbWVudDogZnVuY3Rpb24oKSB7CiAgICAgICAgICB2YXIgZTIgPSB0aGlzLmV4dHJhRmllbGRzWzI1NDYxXTsKICAgICAgICAgIGlmIChlMikgewogICAgICAgICAgICB2YXIgdDIgPSBuKGUyLnZhbHVlKTsKICAgICAgICAgICAgcmV0dXJuIDEgIT09IHQyLnJlYWRJbnQoMSkgPyBudWxsIDogYSh0aGlzLmZpbGVDb21tZW50KSAhPT0gdDIucmVhZEludCg0KSA/IG51bGwgOiBvLnV0ZjhkZWNvZGUodDIucmVhZERhdGEoZTIubGVuZ3RoIC0gNSkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfSB9LCB0LmV4cG9ydHMgPSBsOwogICAgICB9LCB7ICIuL2NvbXByZXNzZWRPYmplY3QiOiAyLCAiLi9jb21wcmVzc2lvbnMiOiAzLCAiLi9jcmMzMiI6IDQsICIuL3JlYWRlci9yZWFkZXJGb3IiOiAyMiwgIi4vc3VwcG9ydCI6IDMwLCAiLi91dGY4IjogMzEsICIuL3V0aWxzIjogMzIgfV0sIDM1OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIGZ1bmN0aW9uIG4oZTIsIHQyLCByMikgewogICAgICAgICAgdGhpcy5uYW1lID0gZTIsIHRoaXMuZGlyID0gcjIuZGlyLCB0aGlzLmRhdGUgPSByMi5kYXRlLCB0aGlzLmNvbW1lbnQgPSByMi5jb21tZW50LCB0aGlzLnVuaXhQZXJtaXNzaW9ucyA9IHIyLnVuaXhQZXJtaXNzaW9ucywgdGhpcy5kb3NQZXJtaXNzaW9ucyA9IHIyLmRvc1Blcm1pc3Npb25zLCB0aGlzLl9kYXRhID0gdDIsIHRoaXMuX2RhdGFCaW5hcnkgPSByMi5iaW5hcnksIHRoaXMub3B0aW9ucyA9IHsgY29tcHJlc3Npb246IHIyLmNvbXByZXNzaW9uLCBjb21wcmVzc2lvbk9wdGlvbnM6IHIyLmNvbXByZXNzaW9uT3B0aW9ucyB9OwogICAgICAgIH0KICAgICAgICB2YXIgcyA9IGUoIi4vc3RyZWFtL1N0cmVhbUhlbHBlciIpLCBpID0gZSgiLi9zdHJlYW0vRGF0YVdvcmtlciIpLCBhID0gZSgiLi91dGY4IiksIG8gPSBlKCIuL2NvbXByZXNzZWRPYmplY3QiKSwgaCA9IGUoIi4vc3RyZWFtL0dlbmVyaWNXb3JrZXIiKTsKICAgICAgICBuLnByb3RvdHlwZSA9IHsgaW50ZXJuYWxTdHJlYW06IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB2YXIgdDIgPSBudWxsLCByMiA9ICJzdHJpbmciOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgaWYgKCFlMikKICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIk5vIG91dHB1dCB0eXBlIHNwZWNpZmllZC4iKTsKICAgICAgICAgICAgdmFyIG4yID0gInN0cmluZyIgPT09IChyMiA9IGUyLnRvTG93ZXJDYXNlKCkpIHx8ICJ0ZXh0IiA9PT0gcjI7CiAgICAgICAgICAgICJiaW5hcnlzdHJpbmciICE9PSByMiAmJiAidGV4dCIgIT09IHIyIHx8IChyMiA9ICJzdHJpbmciKSwgdDIgPSB0aGlzLl9kZWNvbXByZXNzV29ya2VyKCk7CiAgICAgICAgICAgIHZhciBpMiA9ICF0aGlzLl9kYXRhQmluYXJ5OwogICAgICAgICAgICBpMiAmJiAhbjIgJiYgKHQyID0gdDIucGlwZShuZXcgYS5VdGY4RW5jb2RlV29ya2VyKCkpKSwgIWkyICYmIG4yICYmICh0MiA9IHQyLnBpcGUobmV3IGEuVXRmOERlY29kZVdvcmtlcigpKSk7CiAgICAgICAgICB9IGNhdGNoIChlMykgewogICAgICAgICAgICAodDIgPSBuZXcgaCgiZXJyb3IiKSkuZXJyb3IoZTMpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG5ldyBzKHQyLCByMiwgIiIpOwogICAgICAgIH0sIGFzeW5jOiBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmludGVybmFsU3RyZWFtKGUyKS5hY2N1bXVsYXRlKHQyKTsKICAgICAgICB9LCBub2RlU3RyZWFtOiBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHJldHVybiB0aGlzLmludGVybmFsU3RyZWFtKGUyIHx8ICJub2RlYnVmZmVyIikudG9Ob2RlanNTdHJlYW0odDIpOwogICAgICAgIH0sIF9jb21wcmVzc1dvcmtlcjogZnVuY3Rpb24oZTIsIHQyKSB7CiAgICAgICAgICBpZiAodGhpcy5fZGF0YSBpbnN0YW5jZW9mIG8gJiYgdGhpcy5fZGF0YS5jb21wcmVzc2lvbi5tYWdpYyA9PT0gZTIubWFnaWMpCiAgICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRhLmdldENvbXByZXNzZWRXb3JrZXIoKTsKICAgICAgICAgIHZhciByMiA9IHRoaXMuX2RlY29tcHJlc3NXb3JrZXIoKTsKICAgICAgICAgIHJldHVybiB0aGlzLl9kYXRhQmluYXJ5IHx8IChyMiA9IHIyLnBpcGUobmV3IGEuVXRmOEVuY29kZVdvcmtlcigpKSksIG8uY3JlYXRlV29ya2VyRnJvbShyMiwgZTIsIHQyKTsKICAgICAgICB9LCBfZGVjb21wcmVzc1dvcmtlcjogZnVuY3Rpb24oKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0YSBpbnN0YW5jZW9mIG8gPyB0aGlzLl9kYXRhLmdldENvbnRlbnRXb3JrZXIoKSA6IHRoaXMuX2RhdGEgaW5zdGFuY2VvZiBoID8gdGhpcy5fZGF0YSA6IG5ldyBpKHRoaXMuX2RhdGEpOwogICAgICAgIH0gfTsKICAgICAgICBmb3IgKHZhciB1ID0gWyJhc1RleHQiLCAiYXNCaW5hcnkiLCAiYXNOb2RlQnVmZmVyIiwgImFzVWludDhBcnJheSIsICJhc0FycmF5QnVmZmVyIl0sIGwgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiVGhpcyBtZXRob2QgaGFzIGJlZW4gcmVtb3ZlZCBpbiBKU1ppcCAzLjAsIHBsZWFzZSBjaGVjayB0aGUgdXBncmFkZSBndWlkZS4iKTsKICAgICAgICB9LCBmID0gMDsgZiA8IHUubGVuZ3RoOyBmKyspCiAgICAgICAgICBuLnByb3RvdHlwZVt1W2ZdXSA9IGw7CiAgICAgICAgdC5leHBvcnRzID0gbjsKICAgICAgfSwgeyAiLi9jb21wcmVzc2VkT2JqZWN0IjogMiwgIi4vc3RyZWFtL0RhdGFXb3JrZXIiOiAyNywgIi4vc3RyZWFtL0dlbmVyaWNXb3JrZXIiOiAyOCwgIi4vc3RyZWFtL1N0cmVhbUhlbHBlciI6IDI5LCAiLi91dGY4IjogMzEgfV0sIDM2OiBbZnVuY3Rpb24oZSwgbCwgdCkgewogICAgICAgIChmdW5jdGlvbih0MikgewogICAgICAgICAgdmFyIHIsIG4sIGUyID0gdDIuTXV0YXRpb25PYnNlcnZlciB8fCB0Mi5XZWJLaXRNdXRhdGlvbk9ic2VydmVyOwogICAgICAgICAgaWYgKGUyKSB7CiAgICAgICAgICAgIHZhciBpID0gMCwgcyA9IG5ldyBlMih1KSwgYSA9IHQyLmRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCIiKTsKICAgICAgICAgICAgcy5vYnNlcnZlKGEsIHsgY2hhcmFjdGVyRGF0YTogdHJ1ZSB9KSwgciA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIGEuZGF0YSA9IGkgPSArK2kgJSAyOwogICAgICAgICAgICB9OwogICAgICAgICAgfSBlbHNlIGlmICh0Mi5zZXRJbW1lZGlhdGUgfHwgdm9pZCAwID09PSB0Mi5NZXNzYWdlQ2hhbm5lbCkKICAgICAgICAgICAgciA9ICJkb2N1bWVudCIgaW4gdDIgJiYgIm9ucmVhZHlzdGF0ZWNoYW5nZSIgaW4gdDIuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0IikgPyBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICB2YXIgZTMgPSB0Mi5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJzY3JpcHQiKTsKICAgICAgICAgICAgICBlMy5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICAgIHUoKSwgZTMub25yZWFkeXN0YXRlY2hhbmdlID0gbnVsbCwgZTMucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChlMyksIGUzID0gbnVsbDsKICAgICAgICAgICAgICB9LCB0Mi5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoZTMpOwogICAgICAgICAgICB9IDogZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgc2V0VGltZW91dCh1LCAwKTsKICAgICAgICAgICAgfTsKICAgICAgICAgIGVsc2UgewogICAgICAgICAgICB2YXIgbyA9IG5ldyB0Mi5NZXNzYWdlQ2hhbm5lbCgpOwogICAgICAgICAgICBvLnBvcnQxLm9ubWVzc2FnZSA9IHUsIHIgPSBmdW5jdGlvbigpIHsKICAgICAgICAgICAgICBvLnBvcnQyLnBvc3RNZXNzYWdlKDApOwogICAgICAgICAgICB9OwogICAgICAgICAgfQogICAgICAgICAgdmFyIGggPSBbXTsKICAgICAgICAgIGZ1bmN0aW9uIHUoKSB7CiAgICAgICAgICAgIHZhciBlMywgdDM7CiAgICAgICAgICAgIG4gPSB0cnVlOwogICAgICAgICAgICBmb3IgKHZhciByMiA9IGgubGVuZ3RoOyByMjsgKSB7CiAgICAgICAgICAgICAgZm9yICh0MyA9IGgsIGggPSBbXSwgZTMgPSAtMTsgKytlMyA8IHIyOyApCiAgICAgICAgICAgICAgICB0M1tlM10oKTsKICAgICAgICAgICAgICByMiA9IGgubGVuZ3RoOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG4gPSBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIGwuZXhwb3J0cyA9IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIDEgIT09IGgucHVzaChlMykgfHwgbiB8fCByKCk7CiAgICAgICAgICB9OwogICAgICAgIH0pLmNhbGwodGhpcywgInVuZGVmaW5lZCIgIT0gdHlwZW9mIGNvbW1vbmpzR2xvYmFsID8gY29tbW9uanNHbG9iYWwgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygc2VsZiA/IHNlbGYgOiAidW5kZWZpbmVkIiAhPSB0eXBlb2Ygd2luZG93ID8gd2luZG93IDoge30pOwogICAgICB9LCB7fV0sIDM3OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBpID0gZSgiaW1tZWRpYXRlIik7CiAgICAgICAgZnVuY3Rpb24gdSgpIHsKICAgICAgICB9CiAgICAgICAgdmFyIGwgPSB7fSwgcyA9IFsiUkVKRUNURUQiXSwgYSA9IFsiRlVMRklMTEVEIl0sIG4gPSBbIlBFTkRJTkciXTsKICAgICAgICBmdW5jdGlvbiBvKGUyKSB7CiAgICAgICAgICBpZiAoImZ1bmN0aW9uIiAhPSB0eXBlb2YgZTIpCiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoInJlc29sdmVyIG11c3QgYmUgYSBmdW5jdGlvbiIpOwogICAgICAgICAgdGhpcy5zdGF0ZSA9IG4sIHRoaXMucXVldWUgPSBbXSwgdGhpcy5vdXRjb21lID0gdm9pZCAwLCBlMiAhPT0gdSAmJiBkKHRoaXMsIGUyKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gaChlMiwgdDIsIHIyKSB7CiAgICAgICAgICB0aGlzLnByb21pc2UgPSBlMiwgImZ1bmN0aW9uIiA9PSB0eXBlb2YgdDIgJiYgKHRoaXMub25GdWxmaWxsZWQgPSB0MiwgdGhpcy5jYWxsRnVsZmlsbGVkID0gdGhpcy5vdGhlckNhbGxGdWxmaWxsZWQpLCAiZnVuY3Rpb24iID09IHR5cGVvZiByMiAmJiAodGhpcy5vblJlamVjdGVkID0gcjIsIHRoaXMuY2FsbFJlamVjdGVkID0gdGhpcy5vdGhlckNhbGxSZWplY3RlZCk7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGYodDIsIHIyLCBuMikgewogICAgICAgICAgaShmdW5jdGlvbigpIHsKICAgICAgICAgICAgdmFyIGUyOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIGUyID0gcjIobjIpOwogICAgICAgICAgICB9IGNhdGNoIChlMykgewogICAgICAgICAgICAgIHJldHVybiBsLnJlamVjdCh0MiwgZTMpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGUyID09PSB0MiA/IGwucmVqZWN0KHQyLCBuZXcgVHlwZUVycm9yKCJDYW5ub3QgcmVzb2x2ZSBwcm9taXNlIHdpdGggaXRzZWxmIikpIDogbC5yZXNvbHZlKHQyLCBlMik7CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gYyhlMikgewogICAgICAgICAgdmFyIHQyID0gZTIgJiYgZTIudGhlbjsKICAgICAgICAgIGlmIChlMiAmJiAoIm9iamVjdCIgPT0gdHlwZW9mIGUyIHx8ICJmdW5jdGlvbiIgPT0gdHlwZW9mIGUyKSAmJiAiZnVuY3Rpb24iID09IHR5cGVvZiB0MikKICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgIHQyLmFwcGx5KGUyLCBhcmd1bWVudHMpOwogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBkKHQyLCBlMikgewogICAgICAgICAgdmFyIHIyID0gZmFsc2U7CiAgICAgICAgICBmdW5jdGlvbiBuMihlMykgewogICAgICAgICAgICByMiB8fCAocjIgPSB0cnVlLCBsLnJlamVjdCh0MiwgZTMpKTsKICAgICAgICAgIH0KICAgICAgICAgIGZ1bmN0aW9uIGkyKGUzKSB7CiAgICAgICAgICAgIHIyIHx8IChyMiA9IHRydWUsIGwucmVzb2x2ZSh0MiwgZTMpKTsKICAgICAgICAgIH0KICAgICAgICAgIHZhciBzMiA9IHAoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIGUyKGkyLCBuMik7CiAgICAgICAgICB9KTsKICAgICAgICAgICJlcnJvciIgPT09IHMyLnN0YXR1cyAmJiBuMihzMi52YWx1ZSk7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIHAoZTIsIHQyKSB7CiAgICAgICAgICB2YXIgcjIgPSB7fTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHIyLnZhbHVlID0gZTIodDIpLCByMi5zdGF0dXMgPSAic3VjY2VzcyI7CiAgICAgICAgICB9IGNhdGNoIChlMykgewogICAgICAgICAgICByMi5zdGF0dXMgPSAiZXJyb3IiLCByMi52YWx1ZSA9IGUzOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHIyOwogICAgICAgIH0KICAgICAgICAodC5leHBvcnRzID0gbykucHJvdG90eXBlLmZpbmFsbHkgPSBmdW5jdGlvbih0MikgewogICAgICAgICAgaWYgKCJmdW5jdGlvbiIgIT0gdHlwZW9mIHQyKQogICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgIHZhciByMiA9IHRoaXMuY29uc3RydWN0b3I7CiAgICAgICAgICByZXR1cm4gdGhpcy50aGVuKGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICAgIHJldHVybiByMi5yZXNvbHZlKHQyKCkpLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGUyOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0sIGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICAgIHJldHVybiByMi5yZXNvbHZlKHQyKCkpLnRoZW4oZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgdGhyb3cgZTI7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSk7CiAgICAgICAgfSwgby5wcm90b3R5cGUuY2F0Y2ggPSBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIHRoaXMudGhlbihudWxsLCBlMik7CiAgICAgICAgfSwgby5wcm90b3R5cGUudGhlbiA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgaWYgKCJmdW5jdGlvbiIgIT0gdHlwZW9mIGUyICYmIHRoaXMuc3RhdGUgPT09IGEgfHwgImZ1bmN0aW9uIiAhPSB0eXBlb2YgdDIgJiYgdGhpcy5zdGF0ZSA9PT0gcykKICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICB2YXIgcjIgPSBuZXcgdGhpcy5jb25zdHJ1Y3Rvcih1KTsKICAgICAgICAgIHRoaXMuc3RhdGUgIT09IG4gPyBmKHIyLCB0aGlzLnN0YXRlID09PSBhID8gZTIgOiB0MiwgdGhpcy5vdXRjb21lKSA6IHRoaXMucXVldWUucHVzaChuZXcgaChyMiwgZTIsIHQyKSk7CiAgICAgICAgICByZXR1cm4gcjI7CiAgICAgICAgfSwgaC5wcm90b3R5cGUuY2FsbEZ1bGZpbGxlZCA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICBsLnJlc29sdmUodGhpcy5wcm9taXNlLCBlMik7CiAgICAgICAgfSwgaC5wcm90b3R5cGUub3RoZXJDYWxsRnVsZmlsbGVkID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGYodGhpcy5wcm9taXNlLCB0aGlzLm9uRnVsZmlsbGVkLCBlMik7CiAgICAgICAgfSwgaC5wcm90b3R5cGUuY2FsbFJlamVjdGVkID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGwucmVqZWN0KHRoaXMucHJvbWlzZSwgZTIpOwogICAgICAgIH0sIGgucHJvdG90eXBlLm90aGVyQ2FsbFJlamVjdGVkID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGYodGhpcy5wcm9taXNlLCB0aGlzLm9uUmVqZWN0ZWQsIGUyKTsKICAgICAgICB9LCBsLnJlc29sdmUgPSBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiA9IHAoYywgdDIpOwogICAgICAgICAgaWYgKCJlcnJvciIgPT09IHIyLnN0YXR1cykKICAgICAgICAgICAgcmV0dXJuIGwucmVqZWN0KGUyLCByMi52YWx1ZSk7CiAgICAgICAgICB2YXIgbjIgPSByMi52YWx1ZTsKICAgICAgICAgIGlmIChuMikKICAgICAgICAgICAgZChlMiwgbjIpOwogICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIGUyLnN0YXRlID0gYSwgZTIub3V0Y29tZSA9IHQyOwogICAgICAgICAgICBmb3IgKHZhciBpMiA9IC0xLCBzMiA9IGUyLnF1ZXVlLmxlbmd0aDsgKytpMiA8IHMyOyApCiAgICAgICAgICAgICAgZTIucXVldWVbaTJdLmNhbGxGdWxmaWxsZWQodDIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGUyOwogICAgICAgIH0sIGwucmVqZWN0ID0gZnVuY3Rpb24oZTIsIHQyKSB7CiAgICAgICAgICBlMi5zdGF0ZSA9IHMsIGUyLm91dGNvbWUgPSB0MjsKICAgICAgICAgIGZvciAodmFyIHIyID0gLTEsIG4yID0gZTIucXVldWUubGVuZ3RoOyArK3IyIDwgbjI7ICkKICAgICAgICAgICAgZTIucXVldWVbcjJdLmNhbGxSZWplY3RlZCh0Mik7CiAgICAgICAgICByZXR1cm4gZTI7CiAgICAgICAgfSwgby5yZXNvbHZlID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGlmIChlMiBpbnN0YW5jZW9mIHRoaXMpCiAgICAgICAgICAgIHJldHVybiBlMjsKICAgICAgICAgIHJldHVybiBsLnJlc29sdmUobmV3IHRoaXModSksIGUyKTsKICAgICAgICB9LCBvLnJlamVjdCA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB2YXIgdDIgPSBuZXcgdGhpcyh1KTsKICAgICAgICAgIHJldHVybiBsLnJlamVjdCh0MiwgZTIpOwogICAgICAgIH0sIG8uYWxsID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHZhciByMiA9IHRoaXM7CiAgICAgICAgICBpZiAoIltvYmplY3QgQXJyYXldIiAhPT0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGUyKSkKICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVqZWN0KG5ldyBUeXBlRXJyb3IoIm11c3QgYmUgYW4gYXJyYXkiKSk7CiAgICAgICAgICB2YXIgbjIgPSBlMi5sZW5ndGgsIGkyID0gZmFsc2U7CiAgICAgICAgICBpZiAoIW4yKQogICAgICAgICAgICByZXR1cm4gdGhpcy5yZXNvbHZlKFtdKTsKICAgICAgICAgIHZhciBzMiA9IG5ldyBBcnJheShuMiksIGEyID0gMCwgdDIgPSAtMSwgbzIgPSBuZXcgdGhpcyh1KTsKICAgICAgICAgIGZvciAoOyArK3QyIDwgbjI7ICkKICAgICAgICAgICAgaDIoZTJbdDJdLCB0Mik7CiAgICAgICAgICByZXR1cm4gbzI7CiAgICAgICAgICBmdW5jdGlvbiBoMihlMywgdDMpIHsKICAgICAgICAgICAgcjIucmVzb2x2ZShlMykudGhlbihmdW5jdGlvbihlNCkgewogICAgICAgICAgICAgIHMyW3QzXSA9IGU0LCArK2EyICE9PSBuMiB8fCBpMiB8fCAoaTIgPSB0cnVlLCBsLnJlc29sdmUobzIsIHMyKSk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgICAgaTIgfHwgKGkyID0gdHJ1ZSwgbC5yZWplY3QobzIsIGU0KSk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0sIG8ucmFjZSA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB2YXIgdDIgPSB0aGlzOwogICAgICAgICAgaWYgKCJbb2JqZWN0IEFycmF5XSIgIT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChlMikpCiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlamVjdChuZXcgVHlwZUVycm9yKCJtdXN0IGJlIGFuIGFycmF5IikpOwogICAgICAgICAgdmFyIHIyID0gZTIubGVuZ3RoLCBuMiA9IGZhbHNlOwogICAgICAgICAgaWYgKCFyMikKICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZShbXSk7CiAgICAgICAgICB2YXIgaTIgPSAtMSwgczIgPSBuZXcgdGhpcyh1KTsKICAgICAgICAgIGZvciAoOyArK2kyIDwgcjI7ICkKICAgICAgICAgICAgYTIgPSBlMltpMl0sIHQyLnJlc29sdmUoYTIpLnRoZW4oZnVuY3Rpb24oZTMpIHsKICAgICAgICAgICAgICBuMiB8fCAobjIgPSB0cnVlLCBsLnJlc29sdmUoczIsIGUzKSk7CiAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgICAgbjIgfHwgKG4yID0gdHJ1ZSwgbC5yZWplY3QoczIsIGUzKSk7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgdmFyIGEyOwogICAgICAgICAgcmV0dXJuIHMyOwogICAgICAgIH07CiAgICAgIH0sIHsgaW1tZWRpYXRlOiAzNiB9XSwgMzg6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIG4gPSB7fTsKICAgICAgICAoMCwgZSgiLi9saWIvdXRpbHMvY29tbW9uIikuYXNzaWduKShuLCBlKCIuL2xpYi9kZWZsYXRlIiksIGUoIi4vbGliL2luZmxhdGUiKSwgZSgiLi9saWIvemxpYi9jb25zdGFudHMiKSksIHQuZXhwb3J0cyA9IG47CiAgICAgIH0sIHsgIi4vbGliL2RlZmxhdGUiOiAzOSwgIi4vbGliL2luZmxhdGUiOiA0MCwgIi4vbGliL3V0aWxzL2NvbW1vbiI6IDQxLCAiLi9saWIvemxpYi9jb25zdGFudHMiOiA0NCB9XSwgMzk6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIGEgPSBlKCIuL3psaWIvZGVmbGF0ZSIpLCBvID0gZSgiLi91dGlscy9jb21tb24iKSwgaCA9IGUoIi4vdXRpbHMvc3RyaW5ncyIpLCBpID0gZSgiLi96bGliL21lc3NhZ2VzIiksIHMgPSBlKCIuL3psaWIvenN0cmVhbSIpLCB1ID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZywgbCA9IDAsIGYgPSAtMSwgYyA9IDAsIGQgPSA4OwogICAgICAgIGZ1bmN0aW9uIHAoZTIpIHsKICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBwKSkKICAgICAgICAgICAgcmV0dXJuIG5ldyBwKGUyKTsKICAgICAgICAgIHRoaXMub3B0aW9ucyA9IG8uYXNzaWduKHsgbGV2ZWw6IGYsIG1ldGhvZDogZCwgY2h1bmtTaXplOiAxNjM4NCwgd2luZG93Qml0czogMTUsIG1lbUxldmVsOiA4LCBzdHJhdGVneTogYywgdG86ICIiIH0sIGUyIHx8IHt9KTsKICAgICAgICAgIHZhciB0MiA9IHRoaXMub3B0aW9uczsKICAgICAgICAgIHQyLnJhdyAmJiAwIDwgdDIud2luZG93Qml0cyA/IHQyLndpbmRvd0JpdHMgPSAtdDIud2luZG93Qml0cyA6IHQyLmd6aXAgJiYgMCA8IHQyLndpbmRvd0JpdHMgJiYgdDIud2luZG93Qml0cyA8IDE2ICYmICh0Mi53aW5kb3dCaXRzICs9IDE2KSwgdGhpcy5lcnIgPSAwLCB0aGlzLm1zZyA9ICIiLCB0aGlzLmVuZGVkID0gZmFsc2UsIHRoaXMuY2h1bmtzID0gW10sIHRoaXMuc3RybSA9IG5ldyBzKCksIHRoaXMuc3RybS5hdmFpbF9vdXQgPSAwOwogICAgICAgICAgdmFyIHIyID0gYS5kZWZsYXRlSW5pdDIodGhpcy5zdHJtLCB0Mi5sZXZlbCwgdDIubWV0aG9kLCB0Mi53aW5kb3dCaXRzLCB0Mi5tZW1MZXZlbCwgdDIuc3RyYXRlZ3kpOwogICAgICAgICAgaWYgKHIyICE9PSBsKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoaVtyMl0pOwogICAgICAgICAgaWYgKHQyLmhlYWRlciAmJiBhLmRlZmxhdGVTZXRIZWFkZXIodGhpcy5zdHJtLCB0Mi5oZWFkZXIpLCB0Mi5kaWN0aW9uYXJ5KSB7CiAgICAgICAgICAgIHZhciBuMjsKICAgICAgICAgICAgaWYgKG4yID0gInN0cmluZyIgPT0gdHlwZW9mIHQyLmRpY3Rpb25hcnkgPyBoLnN0cmluZzJidWYodDIuZGljdGlvbmFyeSkgOiAiW29iamVjdCBBcnJheUJ1ZmZlcl0iID09PSB1LmNhbGwodDIuZGljdGlvbmFyeSkgPyBuZXcgVWludDhBcnJheSh0Mi5kaWN0aW9uYXJ5KSA6IHQyLmRpY3Rpb25hcnksIChyMiA9IGEuZGVmbGF0ZVNldERpY3Rpb25hcnkodGhpcy5zdHJtLCBuMikpICE9PSBsKQogICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihpW3IyXSk7CiAgICAgICAgICAgIHRoaXMuX2RpY3Rfc2V0ID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gbihlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiA9IG5ldyBwKHQyKTsKICAgICAgICAgIGlmIChyMi5wdXNoKGUyLCB0cnVlKSwgcjIuZXJyKQogICAgICAgICAgICB0aHJvdyByMi5tc2cgfHwgaVtyMi5lcnJdOwogICAgICAgICAgcmV0dXJuIHIyLnJlc3VsdDsKICAgICAgICB9CiAgICAgICAgcC5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgdmFyIHIyLCBuMiwgaTIgPSB0aGlzLnN0cm0sIHMyID0gdGhpcy5vcHRpb25zLmNodW5rU2l6ZTsKICAgICAgICAgIGlmICh0aGlzLmVuZGVkKQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICBuMiA9IHQyID09PSB+fnQyID8gdDIgOiB0cnVlID09PSB0MiA/IDQgOiAwLCAic3RyaW5nIiA9PSB0eXBlb2YgZTIgPyBpMi5pbnB1dCA9IGguc3RyaW5nMmJ1ZihlMikgOiAiW29iamVjdCBBcnJheUJ1ZmZlcl0iID09PSB1LmNhbGwoZTIpID8gaTIuaW5wdXQgPSBuZXcgVWludDhBcnJheShlMikgOiBpMi5pbnB1dCA9IGUyLCBpMi5uZXh0X2luID0gMCwgaTIuYXZhaWxfaW4gPSBpMi5pbnB1dC5sZW5ndGg7CiAgICAgICAgICBkbyB7CiAgICAgICAgICAgIGlmICgwID09PSBpMi5hdmFpbF9vdXQgJiYgKGkyLm91dHB1dCA9IG5ldyBvLkJ1ZjgoczIpLCBpMi5uZXh0X291dCA9IDAsIGkyLmF2YWlsX291dCA9IHMyKSwgMSAhPT0gKHIyID0gYS5kZWZsYXRlKGkyLCBuMikpICYmIHIyICE9PSBsKQogICAgICAgICAgICAgIHJldHVybiB0aGlzLm9uRW5kKHIyKSwgISh0aGlzLmVuZGVkID0gdHJ1ZSk7CiAgICAgICAgICAgIDAgIT09IGkyLmF2YWlsX291dCAmJiAoMCAhPT0gaTIuYXZhaWxfaW4gfHwgNCAhPT0gbjIgJiYgMiAhPT0gbjIpIHx8ICgic3RyaW5nIiA9PT0gdGhpcy5vcHRpb25zLnRvID8gdGhpcy5vbkRhdGEoaC5idWYyYmluc3RyaW5nKG8uc2hyaW5rQnVmKGkyLm91dHB1dCwgaTIubmV4dF9vdXQpKSkgOiB0aGlzLm9uRGF0YShvLnNocmlua0J1ZihpMi5vdXRwdXQsIGkyLm5leHRfb3V0KSkpOwogICAgICAgICAgfSB3aGlsZSAoKDAgPCBpMi5hdmFpbF9pbiB8fCAwID09PSBpMi5hdmFpbF9vdXQpICYmIDEgIT09IHIyKTsKICAgICAgICAgIHJldHVybiA0ID09PSBuMiA/IChyMiA9IGEuZGVmbGF0ZUVuZCh0aGlzLnN0cm0pLCB0aGlzLm9uRW5kKHIyKSwgdGhpcy5lbmRlZCA9IHRydWUsIHIyID09PSBsKSA6IDIgIT09IG4yIHx8ICh0aGlzLm9uRW5kKGwpLCAhKGkyLmF2YWlsX291dCA9IDApKTsKICAgICAgICB9LCBwLnByb3RvdHlwZS5vbkRhdGEgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgdGhpcy5jaHVua3MucHVzaChlMik7CiAgICAgICAgfSwgcC5wcm90b3R5cGUub25FbmQgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgZTIgPT09IGwgJiYgKCJzdHJpbmciID09PSB0aGlzLm9wdGlvbnMudG8gPyB0aGlzLnJlc3VsdCA9IHRoaXMuY2h1bmtzLmpvaW4oIiIpIDogdGhpcy5yZXN1bHQgPSBvLmZsYXR0ZW5DaHVua3ModGhpcy5jaHVua3MpKSwgdGhpcy5jaHVua3MgPSBbXSwgdGhpcy5lcnIgPSBlMiwgdGhpcy5tc2cgPSB0aGlzLnN0cm0ubXNnOwogICAgICAgIH0sIHIuRGVmbGF0ZSA9IHAsIHIuZGVmbGF0ZSA9IG4sIHIuZGVmbGF0ZVJhdyA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgcmV0dXJuICh0MiA9IHQyIHx8IHt9KS5yYXcgPSB0cnVlLCBuKGUyLCB0Mik7CiAgICAgICAgfSwgci5nemlwID0gZnVuY3Rpb24oZTIsIHQyKSB7CiAgICAgICAgICByZXR1cm4gKHQyID0gdDIgfHwge30pLmd6aXAgPSB0cnVlLCBuKGUyLCB0Mik7CiAgICAgICAgfTsKICAgICAgfSwgeyAiLi91dGlscy9jb21tb24iOiA0MSwgIi4vdXRpbHMvc3RyaW5ncyI6IDQyLCAiLi96bGliL2RlZmxhdGUiOiA0NiwgIi4vemxpYi9tZXNzYWdlcyI6IDUxLCAiLi96bGliL3pzdHJlYW0iOiA1MyB9XSwgNDA6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIGMgPSBlKCIuL3psaWIvaW5mbGF0ZSIpLCBkID0gZSgiLi91dGlscy9jb21tb24iKSwgcCA9IGUoIi4vdXRpbHMvc3RyaW5ncyIpLCBtID0gZSgiLi96bGliL2NvbnN0YW50cyIpLCBuID0gZSgiLi96bGliL21lc3NhZ2VzIiksIGkgPSBlKCIuL3psaWIvenN0cmVhbSIpLCBzID0gZSgiLi96bGliL2d6aGVhZGVyIiksIF8gPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nOwogICAgICAgIGZ1bmN0aW9uIGEoZTIpIHsKICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBhKSkKICAgICAgICAgICAgcmV0dXJuIG5ldyBhKGUyKTsKICAgICAgICAgIHRoaXMub3B0aW9ucyA9IGQuYXNzaWduKHsgY2h1bmtTaXplOiAxNjM4NCwgd2luZG93Qml0czogMCwgdG86ICIiIH0sIGUyIHx8IHt9KTsKICAgICAgICAgIHZhciB0MiA9IHRoaXMub3B0aW9uczsKICAgICAgICAgIHQyLnJhdyAmJiAwIDw9IHQyLndpbmRvd0JpdHMgJiYgdDIud2luZG93Qml0cyA8IDE2ICYmICh0Mi53aW5kb3dCaXRzID0gLXQyLndpbmRvd0JpdHMsIDAgPT09IHQyLndpbmRvd0JpdHMgJiYgKHQyLndpbmRvd0JpdHMgPSAtMTUpKSwgISgwIDw9IHQyLndpbmRvd0JpdHMgJiYgdDIud2luZG93Qml0cyA8IDE2KSB8fCBlMiAmJiBlMi53aW5kb3dCaXRzIHx8ICh0Mi53aW5kb3dCaXRzICs9IDMyKSwgMTUgPCB0Mi53aW5kb3dCaXRzICYmIHQyLndpbmRvd0JpdHMgPCA0OCAmJiAwID09ICgxNSAmIHQyLndpbmRvd0JpdHMpICYmICh0Mi53aW5kb3dCaXRzIHw9IDE1KSwgdGhpcy5lcnIgPSAwLCB0aGlzLm1zZyA9ICIiLCB0aGlzLmVuZGVkID0gZmFsc2UsIHRoaXMuY2h1bmtzID0gW10sIHRoaXMuc3RybSA9IG5ldyBpKCksIHRoaXMuc3RybS5hdmFpbF9vdXQgPSAwOwogICAgICAgICAgdmFyIHIyID0gYy5pbmZsYXRlSW5pdDIodGhpcy5zdHJtLCB0Mi53aW5kb3dCaXRzKTsKICAgICAgICAgIGlmIChyMiAhPT0gbS5aX09LKQogICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobltyMl0pOwogICAgICAgICAgdGhpcy5oZWFkZXIgPSBuZXcgcygpLCBjLmluZmxhdGVHZXRIZWFkZXIodGhpcy5zdHJtLCB0aGlzLmhlYWRlcik7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIG8oZTIsIHQyKSB7CiAgICAgICAgICB2YXIgcjIgPSBuZXcgYSh0Mik7CiAgICAgICAgICBpZiAocjIucHVzaChlMiwgdHJ1ZSksIHIyLmVycikKICAgICAgICAgICAgdGhyb3cgcjIubXNnIHx8IG5bcjIuZXJyXTsKICAgICAgICAgIHJldHVybiByMi5yZXN1bHQ7CiAgICAgICAgfQogICAgICAgIGEucHJvdG90eXBlLnB1c2ggPSBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiwgbjIsIGkyLCBzMiwgYTIsIG8yLCBoID0gdGhpcy5zdHJtLCB1ID0gdGhpcy5vcHRpb25zLmNodW5rU2l6ZSwgbCA9IHRoaXMub3B0aW9ucy5kaWN0aW9uYXJ5LCBmID0gZmFsc2U7CiAgICAgICAgICBpZiAodGhpcy5lbmRlZCkKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgbjIgPSB0MiA9PT0gfn50MiA/IHQyIDogdHJ1ZSA9PT0gdDIgPyBtLlpfRklOSVNIIDogbS5aX05PX0ZMVVNILCAic3RyaW5nIiA9PSB0eXBlb2YgZTIgPyBoLmlucHV0ID0gcC5iaW5zdHJpbmcyYnVmKGUyKSA6ICJbb2JqZWN0IEFycmF5QnVmZmVyXSIgPT09IF8uY2FsbChlMikgPyBoLmlucHV0ID0gbmV3IFVpbnQ4QXJyYXkoZTIpIDogaC5pbnB1dCA9IGUyLCBoLm5leHRfaW4gPSAwLCBoLmF2YWlsX2luID0gaC5pbnB1dC5sZW5ndGg7CiAgICAgICAgICBkbyB7CiAgICAgICAgICAgIGlmICgwID09PSBoLmF2YWlsX291dCAmJiAoaC5vdXRwdXQgPSBuZXcgZC5CdWY4KHUpLCBoLm5leHRfb3V0ID0gMCwgaC5hdmFpbF9vdXQgPSB1KSwgKHIyID0gYy5pbmZsYXRlKGgsIG0uWl9OT19GTFVTSCkpID09PSBtLlpfTkVFRF9ESUNUICYmIGwgJiYgKG8yID0gInN0cmluZyIgPT0gdHlwZW9mIGwgPyBwLnN0cmluZzJidWYobCkgOiAiW29iamVjdCBBcnJheUJ1ZmZlcl0iID09PSBfLmNhbGwobCkgPyBuZXcgVWludDhBcnJheShsKSA6IGwsIHIyID0gYy5pbmZsYXRlU2V0RGljdGlvbmFyeSh0aGlzLnN0cm0sIG8yKSksIHIyID09PSBtLlpfQlVGX0VSUk9SICYmIHRydWUgPT09IGYgJiYgKHIyID0gbS5aX09LLCBmID0gZmFsc2UpLCByMiAhPT0gbS5aX1NUUkVBTV9FTkQgJiYgcjIgIT09IG0uWl9PSykKICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vbkVuZChyMiksICEodGhpcy5lbmRlZCA9IHRydWUpOwogICAgICAgICAgICBoLm5leHRfb3V0ICYmICgwICE9PSBoLmF2YWlsX291dCAmJiByMiAhPT0gbS5aX1NUUkVBTV9FTkQgJiYgKDAgIT09IGguYXZhaWxfaW4gfHwgbjIgIT09IG0uWl9GSU5JU0ggJiYgbjIgIT09IG0uWl9TWU5DX0ZMVVNIKSB8fCAoInN0cmluZyIgPT09IHRoaXMub3B0aW9ucy50byA/IChpMiA9IHAudXRmOGJvcmRlcihoLm91dHB1dCwgaC5uZXh0X291dCksIHMyID0gaC5uZXh0X291dCAtIGkyLCBhMiA9IHAuYnVmMnN0cmluZyhoLm91dHB1dCwgaTIpLCBoLm5leHRfb3V0ID0gczIsIGguYXZhaWxfb3V0ID0gdSAtIHMyLCBzMiAmJiBkLmFycmF5U2V0KGgub3V0cHV0LCBoLm91dHB1dCwgaTIsIHMyLCAwKSwgdGhpcy5vbkRhdGEoYTIpKSA6IHRoaXMub25EYXRhKGQuc2hyaW5rQnVmKGgub3V0cHV0LCBoLm5leHRfb3V0KSkpKSwgMCA9PT0gaC5hdmFpbF9pbiAmJiAwID09PSBoLmF2YWlsX291dCAmJiAoZiA9IHRydWUpOwogICAgICAgICAgfSB3aGlsZSAoKDAgPCBoLmF2YWlsX2luIHx8IDAgPT09IGguYXZhaWxfb3V0KSAmJiByMiAhPT0gbS5aX1NUUkVBTV9FTkQpOwogICAgICAgICAgcmV0dXJuIHIyID09PSBtLlpfU1RSRUFNX0VORCAmJiAobjIgPSBtLlpfRklOSVNIKSwgbjIgPT09IG0uWl9GSU5JU0ggPyAocjIgPSBjLmluZmxhdGVFbmQodGhpcy5zdHJtKSwgdGhpcy5vbkVuZChyMiksIHRoaXMuZW5kZWQgPSB0cnVlLCByMiA9PT0gbS5aX09LKSA6IG4yICE9PSBtLlpfU1lOQ19GTFVTSCB8fCAodGhpcy5vbkVuZChtLlpfT0spLCAhKGguYXZhaWxfb3V0ID0gMCkpOwogICAgICAgIH0sIGEucHJvdG90eXBlLm9uRGF0YSA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB0aGlzLmNodW5rcy5wdXNoKGUyKTsKICAgICAgICB9LCBhLnByb3RvdHlwZS5vbkVuZCA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICBlMiA9PT0gbS5aX09LICYmICgic3RyaW5nIiA9PT0gdGhpcy5vcHRpb25zLnRvID8gdGhpcy5yZXN1bHQgPSB0aGlzLmNodW5rcy5qb2luKCIiKSA6IHRoaXMucmVzdWx0ID0gZC5mbGF0dGVuQ2h1bmtzKHRoaXMuY2h1bmtzKSksIHRoaXMuY2h1bmtzID0gW10sIHRoaXMuZXJyID0gZTIsIHRoaXMubXNnID0gdGhpcy5zdHJtLm1zZzsKICAgICAgICB9LCByLkluZmxhdGUgPSBhLCByLmluZmxhdGUgPSBvLCByLmluZmxhdGVSYXcgPSBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHJldHVybiAodDIgPSB0MiB8fCB7fSkucmF3ID0gdHJ1ZSwgbyhlMiwgdDIpOwogICAgICAgIH0sIHIudW5nemlwID0gbzsKICAgICAgfSwgeyAiLi91dGlscy9jb21tb24iOiA0MSwgIi4vdXRpbHMvc3RyaW5ncyI6IDQyLCAiLi96bGliL2NvbnN0YW50cyI6IDQ0LCAiLi96bGliL2d6aGVhZGVyIjogNDcsICIuL3psaWIvaW5mbGF0ZSI6IDQ5LCAiLi96bGliL21lc3NhZ2VzIjogNTEsICIuL3psaWIvenN0cmVhbSI6IDUzIH1dLCA0MTogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgbiA9ICJ1bmRlZmluZWQiICE9IHR5cGVvZiBVaW50OEFycmF5ICYmICJ1bmRlZmluZWQiICE9IHR5cGVvZiBVaW50MTZBcnJheSAmJiAidW5kZWZpbmVkIiAhPSB0eXBlb2YgSW50MzJBcnJheTsKICAgICAgICByLmFzc2lnbiA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICBmb3IgKHZhciB0MiA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7IHQyLmxlbmd0aDsgKSB7CiAgICAgICAgICAgIHZhciByMiA9IHQyLnNoaWZ0KCk7CiAgICAgICAgICAgIGlmIChyMikgewogICAgICAgICAgICAgIGlmICgib2JqZWN0IiAhPSB0eXBlb2YgcjIpCiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHIyICsgIm11c3QgYmUgbm9uLW9iamVjdCIpOwogICAgICAgICAgICAgIGZvciAodmFyIG4yIGluIHIyKQogICAgICAgICAgICAgICAgcjIuaGFzT3duUHJvcGVydHkobjIpICYmIChlMltuMl0gPSByMltuMl0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZTI7CiAgICAgICAgfSwgci5zaHJpbmtCdWYgPSBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHJldHVybiBlMi5sZW5ndGggPT09IHQyID8gZTIgOiBlMi5zdWJhcnJheSA/IGUyLnN1YmFycmF5KDAsIHQyKSA6IChlMi5sZW5ndGggPSB0MiwgZTIpOwogICAgICAgIH07CiAgICAgICAgdmFyIGkgPSB7IGFycmF5U2V0OiBmdW5jdGlvbihlMiwgdDIsIHIyLCBuMiwgaTIpIHsKICAgICAgICAgIGlmICh0Mi5zdWJhcnJheSAmJiBlMi5zdWJhcnJheSkKICAgICAgICAgICAgZTIuc2V0KHQyLnN1YmFycmF5KHIyLCByMiArIG4yKSwgaTIpOwogICAgICAgICAgZWxzZQogICAgICAgICAgICBmb3IgKHZhciBzMiA9IDA7IHMyIDwgbjI7IHMyKyspCiAgICAgICAgICAgICAgZTJbaTIgKyBzMl0gPSB0MltyMiArIHMyXTsKICAgICAgICB9LCBmbGF0dGVuQ2h1bmtzOiBmdW5jdGlvbihlMikgewogICAgICAgICAgdmFyIHQyLCByMiwgbjIsIGkyLCBzMiwgYTsKICAgICAgICAgIGZvciAodDIgPSBuMiA9IDAsIHIyID0gZTIubGVuZ3RoOyB0MiA8IHIyOyB0MisrKQogICAgICAgICAgICBuMiArPSBlMlt0Ml0ubGVuZ3RoOwogICAgICAgICAgZm9yIChhID0gbmV3IFVpbnQ4QXJyYXkobjIpLCB0MiA9IGkyID0gMCwgcjIgPSBlMi5sZW5ndGg7IHQyIDwgcjI7IHQyKyspCiAgICAgICAgICAgIHMyID0gZTJbdDJdLCBhLnNldChzMiwgaTIpLCBpMiArPSBzMi5sZW5ndGg7CiAgICAgICAgICByZXR1cm4gYTsKICAgICAgICB9IH0sIHMgPSB7IGFycmF5U2V0OiBmdW5jdGlvbihlMiwgdDIsIHIyLCBuMiwgaTIpIHsKICAgICAgICAgIGZvciAodmFyIHMyID0gMDsgczIgPCBuMjsgczIrKykKICAgICAgICAgICAgZTJbaTIgKyBzMl0gPSB0MltyMiArIHMyXTsKICAgICAgICB9LCBmbGF0dGVuQ2h1bmtzOiBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIFtdLmNvbmNhdC5hcHBseShbXSwgZTIpOwogICAgICAgIH0gfTsKICAgICAgICByLnNldFR5cGVkID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGUyID8gKHIuQnVmOCA9IFVpbnQ4QXJyYXksIHIuQnVmMTYgPSBVaW50MTZBcnJheSwgci5CdWYzMiA9IEludDMyQXJyYXksIHIuYXNzaWduKHIsIGkpKSA6IChyLkJ1ZjggPSBBcnJheSwgci5CdWYxNiA9IEFycmF5LCByLkJ1ZjMyID0gQXJyYXksIHIuYXNzaWduKHIsIHMpKTsKICAgICAgICB9LCByLnNldFR5cGVkKG4pOwogICAgICB9LCB7fV0sIDQyOiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBoID0gZSgiLi9jb21tb24iKSwgaSA9IHRydWUsIHMgPSB0cnVlOwogICAgICAgIHRyeSB7CiAgICAgICAgICBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIFswXSk7CiAgICAgICAgfSBjYXRjaCAoZTIpIHsKICAgICAgICAgIGkgPSBmYWxzZTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQ4QXJyYXkoMSkpOwogICAgICAgIH0gY2F0Y2ggKGUyKSB7CiAgICAgICAgICBzID0gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGZvciAodmFyIHUgPSBuZXcgaC5CdWY4KDI1NiksIG4gPSAwOyBuIDwgMjU2OyBuKyspCiAgICAgICAgICB1W25dID0gMjUyIDw9IG4gPyA2IDogMjQ4IDw9IG4gPyA1IDogMjQwIDw9IG4gPyA0IDogMjI0IDw9IG4gPyAzIDogMTkyIDw9IG4gPyAyIDogMTsKICAgICAgICBmdW5jdGlvbiBsKGUyLCB0MikgewogICAgICAgICAgaWYgKHQyIDwgNjU1MzcgJiYgKGUyLnN1YmFycmF5ICYmIHMgfHwgIWUyLnN1YmFycmF5ICYmIGkpKQogICAgICAgICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBoLnNocmlua0J1ZihlMiwgdDIpKTsKICAgICAgICAgIGZvciAodmFyIHIyID0gIiIsIG4yID0gMDsgbjIgPCB0MjsgbjIrKykKICAgICAgICAgICAgcjIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShlMltuMl0pOwogICAgICAgICAgcmV0dXJuIHIyOwogICAgICAgIH0KICAgICAgICB1WzI1NF0gPSB1WzI1NF0gPSAxLCByLnN0cmluZzJidWYgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgdmFyIHQyLCByMiwgbjIsIGkyLCBzMiwgYSA9IGUyLmxlbmd0aCwgbyA9IDA7CiAgICAgICAgICBmb3IgKGkyID0gMDsgaTIgPCBhOyBpMisrKQogICAgICAgICAgICA1NTI5NiA9PSAoNjQ1MTIgJiAocjIgPSBlMi5jaGFyQ29kZUF0KGkyKSkpICYmIGkyICsgMSA8IGEgJiYgNTYzMjAgPT0gKDY0NTEyICYgKG4yID0gZTIuY2hhckNvZGVBdChpMiArIDEpKSkgJiYgKHIyID0gNjU1MzYgKyAocjIgLSA1NTI5NiA8PCAxMCkgKyAobjIgLSA1NjMyMCksIGkyKyspLCBvICs9IHIyIDwgMTI4ID8gMSA6IHIyIDwgMjA0OCA/IDIgOiByMiA8IDY1NTM2ID8gMyA6IDQ7CiAgICAgICAgICBmb3IgKHQyID0gbmV3IGguQnVmOChvKSwgaTIgPSBzMiA9IDA7IHMyIDwgbzsgaTIrKykKICAgICAgICAgICAgNTUyOTYgPT0gKDY0NTEyICYgKHIyID0gZTIuY2hhckNvZGVBdChpMikpKSAmJiBpMiArIDEgPCBhICYmIDU2MzIwID09ICg2NDUxMiAmIChuMiA9IGUyLmNoYXJDb2RlQXQoaTIgKyAxKSkpICYmIChyMiA9IDY1NTM2ICsgKHIyIC0gNTUyOTYgPDwgMTApICsgKG4yIC0gNTYzMjApLCBpMisrKSwgcjIgPCAxMjggPyB0MltzMisrXSA9IHIyIDogKHIyIDwgMjA0OCA/IHQyW3MyKytdID0gMTkyIHwgcjIgPj4+IDYgOiAocjIgPCA2NTUzNiA/IHQyW3MyKytdID0gMjI0IHwgcjIgPj4+IDEyIDogKHQyW3MyKytdID0gMjQwIHwgcjIgPj4+IDE4LCB0MltzMisrXSA9IDEyOCB8IHIyID4+PiAxMiAmIDYzKSwgdDJbczIrK10gPSAxMjggfCByMiA+Pj4gNiAmIDYzKSwgdDJbczIrK10gPSAxMjggfCA2MyAmIHIyKTsKICAgICAgICAgIHJldHVybiB0MjsKICAgICAgICB9LCByLmJ1ZjJiaW5zdHJpbmcgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIGwoZTIsIGUyLmxlbmd0aCk7CiAgICAgICAgfSwgci5iaW5zdHJpbmcyYnVmID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGZvciAodmFyIHQyID0gbmV3IGguQnVmOChlMi5sZW5ndGgpLCByMiA9IDAsIG4yID0gdDIubGVuZ3RoOyByMiA8IG4yOyByMisrKQogICAgICAgICAgICB0MltyMl0gPSBlMi5jaGFyQ29kZUF0KHIyKTsKICAgICAgICAgIHJldHVybiB0MjsKICAgICAgICB9LCByLmJ1ZjJzdHJpbmcgPSBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiwgbjIsIGkyLCBzMiwgYSA9IHQyIHx8IGUyLmxlbmd0aCwgbyA9IG5ldyBBcnJheSgyICogYSk7CiAgICAgICAgICBmb3IgKHIyID0gbjIgPSAwOyByMiA8IGE7ICkKICAgICAgICAgICAgaWYgKChpMiA9IGUyW3IyKytdKSA8IDEyOCkKICAgICAgICAgICAgICBvW24yKytdID0gaTI7CiAgICAgICAgICAgIGVsc2UgaWYgKDQgPCAoczIgPSB1W2kyXSkpCiAgICAgICAgICAgICAgb1tuMisrXSA9IDY1NTMzLCByMiArPSBzMiAtIDE7CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgIGZvciAoaTIgJj0gMiA9PT0gczIgPyAzMSA6IDMgPT09IHMyID8gMTUgOiA3OyAxIDwgczIgJiYgcjIgPCBhOyApCiAgICAgICAgICAgICAgICBpMiA9IGkyIDw8IDYgfCA2MyAmIGUyW3IyKytdLCBzMi0tOwogICAgICAgICAgICAgIDEgPCBzMiA/IG9bbjIrK10gPSA2NTUzMyA6IGkyIDwgNjU1MzYgPyBvW24yKytdID0gaTIgOiAoaTIgLT0gNjU1MzYsIG9bbjIrK10gPSA1NTI5NiB8IGkyID4+IDEwICYgMTAyMywgb1tuMisrXSA9IDU2MzIwIHwgMTAyMyAmIGkyKTsKICAgICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGwobywgbjIpOwogICAgICAgIH0sIHIudXRmOGJvcmRlciA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgdmFyIHIyOwogICAgICAgICAgZm9yICgodDIgPSB0MiB8fCBlMi5sZW5ndGgpID4gZTIubGVuZ3RoICYmICh0MiA9IGUyLmxlbmd0aCksIHIyID0gdDIgLSAxOyAwIDw9IHIyICYmIDEyOCA9PSAoMTkyICYgZTJbcjJdKTsgKQogICAgICAgICAgICByMi0tOwogICAgICAgICAgcmV0dXJuIHIyIDwgMCA/IHQyIDogMCA9PT0gcjIgPyB0MiA6IHIyICsgdVtlMltyMl1dID4gdDIgPyByMiA6IHQyOwogICAgICAgIH07CiAgICAgIH0sIHsgIi4vY29tbW9uIjogNDEgfV0sIDQzOiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHQuZXhwb3J0cyA9IGZ1bmN0aW9uKGUyLCB0MiwgcjIsIG4pIHsKICAgICAgICAgIGZvciAodmFyIGkgPSA2NTUzNSAmIGUyIHwgMCwgcyA9IGUyID4+PiAxNiAmIDY1NTM1IHwgMCwgYSA9IDA7IDAgIT09IHIyOyApIHsKICAgICAgICAgICAgZm9yIChyMiAtPSBhID0gMmUzIDwgcjIgPyAyZTMgOiByMjsgcyA9IHMgKyAoaSA9IGkgKyB0MltuKytdIHwgMCkgfCAwLCAtLWE7ICkKICAgICAgICAgICAgICA7CiAgICAgICAgICAgIGkgJT0gNjU1MjEsIHMgJT0gNjU1MjE7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gaSB8IHMgPDwgMTYgfCAwOwogICAgICAgIH07CiAgICAgIH0sIHt9XSwgNDQ6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdC5leHBvcnRzID0geyBaX05PX0ZMVVNIOiAwLCBaX1BBUlRJQUxfRkxVU0g6IDEsIFpfU1lOQ19GTFVTSDogMiwgWl9GVUxMX0ZMVVNIOiAzLCBaX0ZJTklTSDogNCwgWl9CTE9DSzogNSwgWl9UUkVFUzogNiwgWl9PSzogMCwgWl9TVFJFQU1fRU5EOiAxLCBaX05FRURfRElDVDogMiwgWl9FUlJOTzogLTEsIFpfU1RSRUFNX0VSUk9SOiAtMiwgWl9EQVRBX0VSUk9SOiAtMywgWl9CVUZfRVJST1I6IC01LCBaX05PX0NPTVBSRVNTSU9OOiAwLCBaX0JFU1RfU1BFRUQ6IDEsIFpfQkVTVF9DT01QUkVTU0lPTjogOSwgWl9ERUZBVUxUX0NPTVBSRVNTSU9OOiAtMSwgWl9GSUxURVJFRDogMSwgWl9IVUZGTUFOX09OTFk6IDIsIFpfUkxFOiAzLCBaX0ZJWEVEOiA0LCBaX0RFRkFVTFRfU1RSQVRFR1k6IDAsIFpfQklOQVJZOiAwLCBaX1RFWFQ6IDEsIFpfVU5LTk9XTjogMiwgWl9ERUZMQVRFRDogOCB9OwogICAgICB9LCB7fV0sIDQ1OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBvID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICBmb3IgKHZhciBlMiwgdDIgPSBbXSwgcjIgPSAwOyByMiA8IDI1NjsgcjIrKykgewogICAgICAgICAgICBlMiA9IHIyOwogICAgICAgICAgICBmb3IgKHZhciBuID0gMDsgbiA8IDg7IG4rKykKICAgICAgICAgICAgICBlMiA9IDEgJiBlMiA/IDM5ODgyOTIzODQgXiBlMiA+Pj4gMSA6IGUyID4+PiAxOwogICAgICAgICAgICB0MltyMl0gPSBlMjsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0MjsKICAgICAgICB9KCk7CiAgICAgICAgdC5leHBvcnRzID0gZnVuY3Rpb24oZTIsIHQyLCByMiwgbikgewogICAgICAgICAgdmFyIGkgPSBvLCBzID0gbiArIHIyOwogICAgICAgICAgZTIgXj0gLTE7CiAgICAgICAgICBmb3IgKHZhciBhID0gbjsgYSA8IHM7IGErKykKICAgICAgICAgICAgZTIgPSBlMiA+Pj4gOCBeIGlbMjU1ICYgKGUyIF4gdDJbYV0pXTsKICAgICAgICAgIHJldHVybiAtMSBeIGUyOwogICAgICAgIH07CiAgICAgIH0sIHt9XSwgNDY6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdmFyIGgsIGMgPSBlKCIuLi91dGlscy9jb21tb24iKSwgdSA9IGUoIi4vdHJlZXMiKSwgZCA9IGUoIi4vYWRsZXIzMiIpLCBwID0gZSgiLi9jcmMzMiIpLCBuID0gZSgiLi9tZXNzYWdlcyIpLCBsID0gMCwgZiA9IDQsIG0gPSAwLCBfID0gLTIsIGcgPSAtMSwgYiA9IDQsIGkgPSAyLCB2ID0gOCwgeSA9IDksIHMgPSAyODYsIGEgPSAzMCwgbyA9IDE5LCB3ID0gMiAqIHMgKyAxLCBrID0gMTUsIHggPSAzLCBTID0gMjU4LCB6ID0gUyArIHggKyAxLCBDID0gNDIsIEUgPSAxMTMsIEEgPSAxLCBJID0gMiwgTyA9IDMsIEIgPSA0OwogICAgICAgIGZ1bmN0aW9uIFIoZTIsIHQyKSB7CiAgICAgICAgICByZXR1cm4gZTIubXNnID0gblt0Ml0sIHQyOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBUKGUyKSB7CiAgICAgICAgICByZXR1cm4gKGUyIDw8IDEpIC0gKDQgPCBlMiA/IDkgOiAwKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gRChlMikgewogICAgICAgICAgZm9yICh2YXIgdDIgPSBlMi5sZW5ndGg7IDAgPD0gLS10MjsgKQogICAgICAgICAgICBlMlt0Ml0gPSAwOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBGKGUyKSB7CiAgICAgICAgICB2YXIgdDIgPSBlMi5zdGF0ZSwgcjIgPSB0Mi5wZW5kaW5nOwogICAgICAgICAgcjIgPiBlMi5hdmFpbF9vdXQgJiYgKHIyID0gZTIuYXZhaWxfb3V0KSwgMCAhPT0gcjIgJiYgKGMuYXJyYXlTZXQoZTIub3V0cHV0LCB0Mi5wZW5kaW5nX2J1ZiwgdDIucGVuZGluZ19vdXQsIHIyLCBlMi5uZXh0X291dCksIGUyLm5leHRfb3V0ICs9IHIyLCB0Mi5wZW5kaW5nX291dCArPSByMiwgZTIudG90YWxfb3V0ICs9IHIyLCBlMi5hdmFpbF9vdXQgLT0gcjIsIHQyLnBlbmRpbmcgLT0gcjIsIDAgPT09IHQyLnBlbmRpbmcgJiYgKHQyLnBlbmRpbmdfb3V0ID0gMCkpOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBOKGUyLCB0MikgewogICAgICAgICAgdS5fdHJfZmx1c2hfYmxvY2soZTIsIDAgPD0gZTIuYmxvY2tfc3RhcnQgPyBlMi5ibG9ja19zdGFydCA6IC0xLCBlMi5zdHJzdGFydCAtIGUyLmJsb2NrX3N0YXJ0LCB0MiksIGUyLmJsb2NrX3N0YXJ0ID0gZTIuc3Ryc3RhcnQsIEYoZTIuc3RybSk7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIFUoZTIsIHQyKSB7CiAgICAgICAgICBlMi5wZW5kaW5nX2J1ZltlMi5wZW5kaW5nKytdID0gdDI7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIFAoZTIsIHQyKSB7CiAgICAgICAgICBlMi5wZW5kaW5nX2J1ZltlMi5wZW5kaW5nKytdID0gdDIgPj4+IDggJiAyNTUsIGUyLnBlbmRpbmdfYnVmW2UyLnBlbmRpbmcrK10gPSAyNTUgJiB0MjsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gTChlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiwgbjIsIGkyID0gZTIubWF4X2NoYWluX2xlbmd0aCwgczIgPSBlMi5zdHJzdGFydCwgYTIgPSBlMi5wcmV2X2xlbmd0aCwgbzIgPSBlMi5uaWNlX21hdGNoLCBoMiA9IGUyLnN0cnN0YXJ0ID4gZTIud19zaXplIC0geiA/IGUyLnN0cnN0YXJ0IC0gKGUyLndfc2l6ZSAtIHopIDogMCwgdTIgPSBlMi53aW5kb3csIGwyID0gZTIud19tYXNrLCBmMiA9IGUyLnByZXYsIGMyID0gZTIuc3Ryc3RhcnQgKyBTLCBkMiA9IHUyW3MyICsgYTIgLSAxXSwgcDIgPSB1MltzMiArIGEyXTsKICAgICAgICAgIGUyLnByZXZfbGVuZ3RoID49IGUyLmdvb2RfbWF0Y2ggJiYgKGkyID4+PSAyKSwgbzIgPiBlMi5sb29rYWhlYWQgJiYgKG8yID0gZTIubG9va2FoZWFkKTsKICAgICAgICAgIGRvIHsKICAgICAgICAgICAgaWYgKHUyWyhyMiA9IHQyKSArIGEyXSA9PT0gcDIgJiYgdTJbcjIgKyBhMiAtIDFdID09PSBkMiAmJiB1MltyMl0gPT09IHUyW3MyXSAmJiB1MlsrK3IyXSA9PT0gdTJbczIgKyAxXSkgewogICAgICAgICAgICAgIHMyICs9IDIsIHIyKys7CiAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgIH0gd2hpbGUgKHUyWysrczJdID09PSB1MlsrK3IyXSAmJiB1MlsrK3MyXSA9PT0gdTJbKytyMl0gJiYgdTJbKytzMl0gPT09IHUyWysrcjJdICYmIHUyWysrczJdID09PSB1MlsrK3IyXSAmJiB1MlsrK3MyXSA9PT0gdTJbKytyMl0gJiYgdTJbKytzMl0gPT09IHUyWysrcjJdICYmIHUyWysrczJdID09PSB1MlsrK3IyXSAmJiB1MlsrK3MyXSA9PT0gdTJbKytyMl0gJiYgczIgPCBjMik7CiAgICAgICAgICAgICAgaWYgKG4yID0gUyAtIChjMiAtIHMyKSwgczIgPSBjMiAtIFMsIGEyIDwgbjIpIHsKICAgICAgICAgICAgICAgIGlmIChlMi5tYXRjaF9zdGFydCA9IHQyLCBvMiA8PSAoYTIgPSBuMikpCiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgZDIgPSB1MltzMiArIGEyIC0gMV0sIHAyID0gdTJbczIgKyBhMl07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9IHdoaWxlICgodDIgPSBmMlt0MiAmIGwyXSkgPiBoMiAmJiAwICE9IC0taTIpOwogICAgICAgICAgcmV0dXJuIGEyIDw9IGUyLmxvb2thaGVhZCA/IGEyIDogZTIubG9va2FoZWFkOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBqKGUyKSB7CiAgICAgICAgICB2YXIgdDIsIHIyLCBuMiwgaTIsIHMyLCBhMiwgbzIsIGgyLCB1MiwgbDIsIGYyID0gZTIud19zaXplOwogICAgICAgICAgZG8gewogICAgICAgICAgICBpZiAoaTIgPSBlMi53aW5kb3dfc2l6ZSAtIGUyLmxvb2thaGVhZCAtIGUyLnN0cnN0YXJ0LCBlMi5zdHJzdGFydCA+PSBmMiArIChmMiAtIHopKSB7CiAgICAgICAgICAgICAgZm9yIChjLmFycmF5U2V0KGUyLndpbmRvdywgZTIud2luZG93LCBmMiwgZjIsIDApLCBlMi5tYXRjaF9zdGFydCAtPSBmMiwgZTIuc3Ryc3RhcnQgLT0gZjIsIGUyLmJsb2NrX3N0YXJ0IC09IGYyLCB0MiA9IHIyID0gZTIuaGFzaF9zaXplOyBuMiA9IGUyLmhlYWRbLS10Ml0sIGUyLmhlYWRbdDJdID0gZjIgPD0gbjIgPyBuMiAtIGYyIDogMCwgLS1yMjsgKQogICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgIGZvciAodDIgPSByMiA9IGYyOyBuMiA9IGUyLnByZXZbLS10Ml0sIGUyLnByZXZbdDJdID0gZjIgPD0gbjIgPyBuMiAtIGYyIDogMCwgLS1yMjsgKQogICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgIGkyICs9IGYyOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICgwID09PSBlMi5zdHJtLmF2YWlsX2luKQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBpZiAoYTIgPSBlMi5zdHJtLCBvMiA9IGUyLndpbmRvdywgaDIgPSBlMi5zdHJzdGFydCArIGUyLmxvb2thaGVhZCwgdTIgPSBpMiwgbDIgPSB2b2lkIDAsIGwyID0gYTIuYXZhaWxfaW4sIHUyIDwgbDIgJiYgKGwyID0gdTIpLCByMiA9IDAgPT09IGwyID8gMCA6IChhMi5hdmFpbF9pbiAtPSBsMiwgYy5hcnJheVNldChvMiwgYTIuaW5wdXQsIGEyLm5leHRfaW4sIGwyLCBoMiksIDEgPT09IGEyLnN0YXRlLndyYXAgPyBhMi5hZGxlciA9IGQoYTIuYWRsZXIsIG8yLCBsMiwgaDIpIDogMiA9PT0gYTIuc3RhdGUud3JhcCAmJiAoYTIuYWRsZXIgPSBwKGEyLmFkbGVyLCBvMiwgbDIsIGgyKSksIGEyLm5leHRfaW4gKz0gbDIsIGEyLnRvdGFsX2luICs9IGwyLCBsMiksIGUyLmxvb2thaGVhZCArPSByMiwgZTIubG9va2FoZWFkICsgZTIuaW5zZXJ0ID49IHgpCiAgICAgICAgICAgICAgZm9yIChzMiA9IGUyLnN0cnN0YXJ0IC0gZTIuaW5zZXJ0LCBlMi5pbnNfaCA9IGUyLndpbmRvd1tzMl0sIGUyLmluc19oID0gKGUyLmluc19oIDw8IGUyLmhhc2hfc2hpZnQgXiBlMi53aW5kb3dbczIgKyAxXSkgJiBlMi5oYXNoX21hc2s7IGUyLmluc2VydCAmJiAoZTIuaW5zX2ggPSAoZTIuaW5zX2ggPDwgZTIuaGFzaF9zaGlmdCBeIGUyLndpbmRvd1tzMiArIHggLSAxXSkgJiBlMi5oYXNoX21hc2ssIGUyLnByZXZbczIgJiBlMi53X21hc2tdID0gZTIuaGVhZFtlMi5pbnNfaF0sIGUyLmhlYWRbZTIuaW5zX2hdID0gczIsIHMyKyssIGUyLmluc2VydC0tLCAhKGUyLmxvb2thaGVhZCArIGUyLmluc2VydCA8IHgpKTsgKQogICAgICAgICAgICAgICAgOwogICAgICAgICAgfSB3aGlsZSAoZTIubG9va2FoZWFkIDwgeiAmJiAwICE9PSBlMi5zdHJtLmF2YWlsX2luKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gWihlMiwgdDIpIHsKICAgICAgICAgIGZvciAodmFyIHIyLCBuMjsgOyApIHsKICAgICAgICAgICAgaWYgKGUyLmxvb2thaGVhZCA8IHopIHsKICAgICAgICAgICAgICBpZiAoaihlMiksIGUyLmxvb2thaGVhZCA8IHogJiYgdDIgPT09IGwpCiAgICAgICAgICAgICAgICByZXR1cm4gQTsKICAgICAgICAgICAgICBpZiAoMCA9PT0gZTIubG9va2FoZWFkKQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHIyID0gMCwgZTIubG9va2FoZWFkID49IHggJiYgKGUyLmluc19oID0gKGUyLmluc19oIDw8IGUyLmhhc2hfc2hpZnQgXiBlMi53aW5kb3dbZTIuc3Ryc3RhcnQgKyB4IC0gMV0pICYgZTIuaGFzaF9tYXNrLCByMiA9IGUyLnByZXZbZTIuc3Ryc3RhcnQgJiBlMi53X21hc2tdID0gZTIuaGVhZFtlMi5pbnNfaF0sIGUyLmhlYWRbZTIuaW5zX2hdID0gZTIuc3Ryc3RhcnQpLCAwICE9PSByMiAmJiBlMi5zdHJzdGFydCAtIHIyIDw9IGUyLndfc2l6ZSAtIHogJiYgKGUyLm1hdGNoX2xlbmd0aCA9IEwoZTIsIHIyKSksIGUyLm1hdGNoX2xlbmd0aCA+PSB4KQogICAgICAgICAgICAgIGlmIChuMiA9IHUuX3RyX3RhbGx5KGUyLCBlMi5zdHJzdGFydCAtIGUyLm1hdGNoX3N0YXJ0LCBlMi5tYXRjaF9sZW5ndGggLSB4KSwgZTIubG9va2FoZWFkIC09IGUyLm1hdGNoX2xlbmd0aCwgZTIubWF0Y2hfbGVuZ3RoIDw9IGUyLm1heF9sYXp5X21hdGNoICYmIGUyLmxvb2thaGVhZCA+PSB4KSB7CiAgICAgICAgICAgICAgICBmb3IgKGUyLm1hdGNoX2xlbmd0aC0tOyBlMi5zdHJzdGFydCsrLCBlMi5pbnNfaCA9IChlMi5pbnNfaCA8PCBlMi5oYXNoX3NoaWZ0IF4gZTIud2luZG93W2UyLnN0cnN0YXJ0ICsgeCAtIDFdKSAmIGUyLmhhc2hfbWFzaywgcjIgPSBlMi5wcmV2W2UyLnN0cnN0YXJ0ICYgZTIud19tYXNrXSA9IGUyLmhlYWRbZTIuaW5zX2hdLCBlMi5oZWFkW2UyLmluc19oXSA9IGUyLnN0cnN0YXJ0LCAwICE9IC0tZTIubWF0Y2hfbGVuZ3RoOyApCiAgICAgICAgICAgICAgICAgIDsKICAgICAgICAgICAgICAgIGUyLnN0cnN0YXJ0Kys7CiAgICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgICBlMi5zdHJzdGFydCArPSBlMi5tYXRjaF9sZW5ndGgsIGUyLm1hdGNoX2xlbmd0aCA9IDAsIGUyLmluc19oID0gZTIud2luZG93W2UyLnN0cnN0YXJ0XSwgZTIuaW5zX2ggPSAoZTIuaW5zX2ggPDwgZTIuaGFzaF9zaGlmdCBeIGUyLndpbmRvd1tlMi5zdHJzdGFydCArIDFdKSAmIGUyLmhhc2hfbWFzazsKICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgIG4yID0gdS5fdHJfdGFsbHkoZTIsIDAsIGUyLndpbmRvd1tlMi5zdHJzdGFydF0pLCBlMi5sb29rYWhlYWQtLSwgZTIuc3Ryc3RhcnQrKzsKICAgICAgICAgICAgaWYgKG4yICYmIChOKGUyLCBmYWxzZSksIDAgPT09IGUyLnN0cm0uYXZhaWxfb3V0KSkKICAgICAgICAgICAgICByZXR1cm4gQTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBlMi5pbnNlcnQgPSBlMi5zdHJzdGFydCA8IHggLSAxID8gZTIuc3Ryc3RhcnQgOiB4IC0gMSwgdDIgPT09IGYgPyAoTihlMiwgdHJ1ZSksIDAgPT09IGUyLnN0cm0uYXZhaWxfb3V0ID8gTyA6IEIpIDogZTIubGFzdF9saXQgJiYgKE4oZTIsIGZhbHNlKSwgMCA9PT0gZTIuc3RybS5hdmFpbF9vdXQpID8gQSA6IEk7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIFcoZTIsIHQyKSB7CiAgICAgICAgICBmb3IgKHZhciByMiwgbjIsIGkyOyA7ICkgewogICAgICAgICAgICBpZiAoZTIubG9va2FoZWFkIDwgeikgewogICAgICAgICAgICAgIGlmIChqKGUyKSwgZTIubG9va2FoZWFkIDwgeiAmJiB0MiA9PT0gbCkKICAgICAgICAgICAgICAgIHJldHVybiBBOwogICAgICAgICAgICAgIGlmICgwID09PSBlMi5sb29rYWhlYWQpCiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocjIgPSAwLCBlMi5sb29rYWhlYWQgPj0geCAmJiAoZTIuaW5zX2ggPSAoZTIuaW5zX2ggPDwgZTIuaGFzaF9zaGlmdCBeIGUyLndpbmRvd1tlMi5zdHJzdGFydCArIHggLSAxXSkgJiBlMi5oYXNoX21hc2ssIHIyID0gZTIucHJldltlMi5zdHJzdGFydCAmIGUyLndfbWFza10gPSBlMi5oZWFkW2UyLmluc19oXSwgZTIuaGVhZFtlMi5pbnNfaF0gPSBlMi5zdHJzdGFydCksIGUyLnByZXZfbGVuZ3RoID0gZTIubWF0Y2hfbGVuZ3RoLCBlMi5wcmV2X21hdGNoID0gZTIubWF0Y2hfc3RhcnQsIGUyLm1hdGNoX2xlbmd0aCA9IHggLSAxLCAwICE9PSByMiAmJiBlMi5wcmV2X2xlbmd0aCA8IGUyLm1heF9sYXp5X21hdGNoICYmIGUyLnN0cnN0YXJ0IC0gcjIgPD0gZTIud19zaXplIC0geiAmJiAoZTIubWF0Y2hfbGVuZ3RoID0gTChlMiwgcjIpLCBlMi5tYXRjaF9sZW5ndGggPD0gNSAmJiAoMSA9PT0gZTIuc3RyYXRlZ3kgfHwgZTIubWF0Y2hfbGVuZ3RoID09PSB4ICYmIDQwOTYgPCBlMi5zdHJzdGFydCAtIGUyLm1hdGNoX3N0YXJ0KSAmJiAoZTIubWF0Y2hfbGVuZ3RoID0geCAtIDEpKSwgZTIucHJldl9sZW5ndGggPj0geCAmJiBlMi5tYXRjaF9sZW5ndGggPD0gZTIucHJldl9sZW5ndGgpIHsKICAgICAgICAgICAgICBmb3IgKGkyID0gZTIuc3Ryc3RhcnQgKyBlMi5sb29rYWhlYWQgLSB4LCBuMiA9IHUuX3RyX3RhbGx5KGUyLCBlMi5zdHJzdGFydCAtIDEgLSBlMi5wcmV2X21hdGNoLCBlMi5wcmV2X2xlbmd0aCAtIHgpLCBlMi5sb29rYWhlYWQgLT0gZTIucHJldl9sZW5ndGggLSAxLCBlMi5wcmV2X2xlbmd0aCAtPSAyOyArK2UyLnN0cnN0YXJ0IDw9IGkyICYmIChlMi5pbnNfaCA9IChlMi5pbnNfaCA8PCBlMi5oYXNoX3NoaWZ0IF4gZTIud2luZG93W2UyLnN0cnN0YXJ0ICsgeCAtIDFdKSAmIGUyLmhhc2hfbWFzaywgcjIgPSBlMi5wcmV2W2UyLnN0cnN0YXJ0ICYgZTIud19tYXNrXSA9IGUyLmhlYWRbZTIuaW5zX2hdLCBlMi5oZWFkW2UyLmluc19oXSA9IGUyLnN0cnN0YXJ0KSwgMCAhPSAtLWUyLnByZXZfbGVuZ3RoOyApCiAgICAgICAgICAgICAgICA7CiAgICAgICAgICAgICAgaWYgKGUyLm1hdGNoX2F2YWlsYWJsZSA9IDAsIGUyLm1hdGNoX2xlbmd0aCA9IHggLSAxLCBlMi5zdHJzdGFydCsrLCBuMiAmJiAoTihlMiwgZmFsc2UpLCAwID09PSBlMi5zdHJtLmF2YWlsX291dCkpCiAgICAgICAgICAgICAgICByZXR1cm4gQTsKICAgICAgICAgICAgfSBlbHNlIGlmIChlMi5tYXRjaF9hdmFpbGFibGUpIHsKICAgICAgICAgICAgICBpZiAoKG4yID0gdS5fdHJfdGFsbHkoZTIsIDAsIGUyLndpbmRvd1tlMi5zdHJzdGFydCAtIDFdKSkgJiYgTihlMiwgZmFsc2UpLCBlMi5zdHJzdGFydCsrLCBlMi5sb29rYWhlYWQtLSwgMCA9PT0gZTIuc3RybS5hdmFpbF9vdXQpCiAgICAgICAgICAgICAgICByZXR1cm4gQTsKICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgZTIubWF0Y2hfYXZhaWxhYmxlID0gMSwgZTIuc3Ryc3RhcnQrKywgZTIubG9va2FoZWFkLS07CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZTIubWF0Y2hfYXZhaWxhYmxlICYmIChuMiA9IHUuX3RyX3RhbGx5KGUyLCAwLCBlMi53aW5kb3dbZTIuc3Ryc3RhcnQgLSAxXSksIGUyLm1hdGNoX2F2YWlsYWJsZSA9IDApLCBlMi5pbnNlcnQgPSBlMi5zdHJzdGFydCA8IHggLSAxID8gZTIuc3Ryc3RhcnQgOiB4IC0gMSwgdDIgPT09IGYgPyAoTihlMiwgdHJ1ZSksIDAgPT09IGUyLnN0cm0uYXZhaWxfb3V0ID8gTyA6IEIpIDogZTIubGFzdF9saXQgJiYgKE4oZTIsIGZhbHNlKSwgMCA9PT0gZTIuc3RybS5hdmFpbF9vdXQpID8gQSA6IEk7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIE0oZTIsIHQyLCByMiwgbjIsIGkyKSB7CiAgICAgICAgICB0aGlzLmdvb2RfbGVuZ3RoID0gZTIsIHRoaXMubWF4X2xhenkgPSB0MiwgdGhpcy5uaWNlX2xlbmd0aCA9IHIyLCB0aGlzLm1heF9jaGFpbiA9IG4yLCB0aGlzLmZ1bmMgPSBpMjsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gSCgpIHsKICAgICAgICAgIHRoaXMuc3RybSA9IG51bGwsIHRoaXMuc3RhdHVzID0gMCwgdGhpcy5wZW5kaW5nX2J1ZiA9IG51bGwsIHRoaXMucGVuZGluZ19idWZfc2l6ZSA9IDAsIHRoaXMucGVuZGluZ19vdXQgPSAwLCB0aGlzLnBlbmRpbmcgPSAwLCB0aGlzLndyYXAgPSAwLCB0aGlzLmd6aGVhZCA9IG51bGwsIHRoaXMuZ3ppbmRleCA9IDAsIHRoaXMubWV0aG9kID0gdiwgdGhpcy5sYXN0X2ZsdXNoID0gLTEsIHRoaXMud19zaXplID0gMCwgdGhpcy53X2JpdHMgPSAwLCB0aGlzLndfbWFzayA9IDAsIHRoaXMud2luZG93ID0gbnVsbCwgdGhpcy53aW5kb3dfc2l6ZSA9IDAsIHRoaXMucHJldiA9IG51bGwsIHRoaXMuaGVhZCA9IG51bGwsIHRoaXMuaW5zX2ggPSAwLCB0aGlzLmhhc2hfc2l6ZSA9IDAsIHRoaXMuaGFzaF9iaXRzID0gMCwgdGhpcy5oYXNoX21hc2sgPSAwLCB0aGlzLmhhc2hfc2hpZnQgPSAwLCB0aGlzLmJsb2NrX3N0YXJ0ID0gMCwgdGhpcy5tYXRjaF9sZW5ndGggPSAwLCB0aGlzLnByZXZfbWF0Y2ggPSAwLCB0aGlzLm1hdGNoX2F2YWlsYWJsZSA9IDAsIHRoaXMuc3Ryc3RhcnQgPSAwLCB0aGlzLm1hdGNoX3N0YXJ0ID0gMCwgdGhpcy5sb29rYWhlYWQgPSAwLCB0aGlzLnByZXZfbGVuZ3RoID0gMCwgdGhpcy5tYXhfY2hhaW5fbGVuZ3RoID0gMCwgdGhpcy5tYXhfbGF6eV9tYXRjaCA9IDAsIHRoaXMubGV2ZWwgPSAwLCB0aGlzLnN0cmF0ZWd5ID0gMCwgdGhpcy5nb29kX21hdGNoID0gMCwgdGhpcy5uaWNlX21hdGNoID0gMCwgdGhpcy5keW5fbHRyZWUgPSBuZXcgYy5CdWYxNigyICogdyksIHRoaXMuZHluX2R0cmVlID0gbmV3IGMuQnVmMTYoMiAqICgyICogYSArIDEpKSwgdGhpcy5ibF90cmVlID0gbmV3IGMuQnVmMTYoMiAqICgyICogbyArIDEpKSwgRCh0aGlzLmR5bl9sdHJlZSksIEQodGhpcy5keW5fZHRyZWUpLCBEKHRoaXMuYmxfdHJlZSksIHRoaXMubF9kZXNjID0gbnVsbCwgdGhpcy5kX2Rlc2MgPSBudWxsLCB0aGlzLmJsX2Rlc2MgPSBudWxsLCB0aGlzLmJsX2NvdW50ID0gbmV3IGMuQnVmMTYoayArIDEpLCB0aGlzLmhlYXAgPSBuZXcgYy5CdWYxNigyICogcyArIDEpLCBEKHRoaXMuaGVhcCksIHRoaXMuaGVhcF9sZW4gPSAwLCB0aGlzLmhlYXBfbWF4ID0gMCwgdGhpcy5kZXB0aCA9IG5ldyBjLkJ1ZjE2KDIgKiBzICsgMSksIEQodGhpcy5kZXB0aCksIHRoaXMubF9idWYgPSAwLCB0aGlzLmxpdF9idWZzaXplID0gMCwgdGhpcy5sYXN0X2xpdCA9IDAsIHRoaXMuZF9idWYgPSAwLCB0aGlzLm9wdF9sZW4gPSAwLCB0aGlzLnN0YXRpY19sZW4gPSAwLCB0aGlzLm1hdGNoZXMgPSAwLCB0aGlzLmluc2VydCA9IDAsIHRoaXMuYmlfYnVmID0gMCwgdGhpcy5iaV92YWxpZCA9IDA7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIEcoZTIpIHsKICAgICAgICAgIHZhciB0MjsKICAgICAgICAgIHJldHVybiBlMiAmJiBlMi5zdGF0ZSA/IChlMi50b3RhbF9pbiA9IGUyLnRvdGFsX291dCA9IDAsIGUyLmRhdGFfdHlwZSA9IGksICh0MiA9IGUyLnN0YXRlKS5wZW5kaW5nID0gMCwgdDIucGVuZGluZ19vdXQgPSAwLCB0Mi53cmFwIDwgMCAmJiAodDIud3JhcCA9IC10Mi53cmFwKSwgdDIuc3RhdHVzID0gdDIud3JhcCA/IEMgOiBFLCBlMi5hZGxlciA9IDIgPT09IHQyLndyYXAgPyAwIDogMSwgdDIubGFzdF9mbHVzaCA9IGwsIHUuX3RyX2luaXQodDIpLCBtKSA6IFIoZTIsIF8pOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBLKGUyKSB7CiAgICAgICAgICB2YXIgdDIgPSBHKGUyKTsKICAgICAgICAgIHJldHVybiB0MiA9PT0gbSAmJiBmdW5jdGlvbihlMykgewogICAgICAgICAgICBlMy53aW5kb3dfc2l6ZSA9IDIgKiBlMy53X3NpemUsIEQoZTMuaGVhZCksIGUzLm1heF9sYXp5X21hdGNoID0gaFtlMy5sZXZlbF0ubWF4X2xhenksIGUzLmdvb2RfbWF0Y2ggPSBoW2UzLmxldmVsXS5nb29kX2xlbmd0aCwgZTMubmljZV9tYXRjaCA9IGhbZTMubGV2ZWxdLm5pY2VfbGVuZ3RoLCBlMy5tYXhfY2hhaW5fbGVuZ3RoID0gaFtlMy5sZXZlbF0ubWF4X2NoYWluLCBlMy5zdHJzdGFydCA9IDAsIGUzLmJsb2NrX3N0YXJ0ID0gMCwgZTMubG9va2FoZWFkID0gMCwgZTMuaW5zZXJ0ID0gMCwgZTMubWF0Y2hfbGVuZ3RoID0gZTMucHJldl9sZW5ndGggPSB4IC0gMSwgZTMubWF0Y2hfYXZhaWxhYmxlID0gMCwgZTMuaW5zX2ggPSAwOwogICAgICAgICAgfShlMi5zdGF0ZSksIHQyOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBZKGUyLCB0MiwgcjIsIG4yLCBpMiwgczIpIHsKICAgICAgICAgIGlmICghZTIpCiAgICAgICAgICAgIHJldHVybiBfOwogICAgICAgICAgdmFyIGEyID0gMTsKICAgICAgICAgIGlmICh0MiA9PT0gZyAmJiAodDIgPSA2KSwgbjIgPCAwID8gKGEyID0gMCwgbjIgPSAtbjIpIDogMTUgPCBuMiAmJiAoYTIgPSAyLCBuMiAtPSAxNiksIGkyIDwgMSB8fCB5IDwgaTIgfHwgcjIgIT09IHYgfHwgbjIgPCA4IHx8IDE1IDwgbjIgfHwgdDIgPCAwIHx8IDkgPCB0MiB8fCBzMiA8IDAgfHwgYiA8IHMyKQogICAgICAgICAgICByZXR1cm4gUihlMiwgXyk7CiAgICAgICAgICA4ID09PSBuMiAmJiAobjIgPSA5KTsKICAgICAgICAgIHZhciBvMiA9IG5ldyBIKCk7CiAgICAgICAgICByZXR1cm4gKGUyLnN0YXRlID0gbzIpLnN0cm0gPSBlMiwgbzIud3JhcCA9IGEyLCBvMi5nemhlYWQgPSBudWxsLCBvMi53X2JpdHMgPSBuMiwgbzIud19zaXplID0gMSA8PCBvMi53X2JpdHMsIG8yLndfbWFzayA9IG8yLndfc2l6ZSAtIDEsIG8yLmhhc2hfYml0cyA9IGkyICsgNywgbzIuaGFzaF9zaXplID0gMSA8PCBvMi5oYXNoX2JpdHMsIG8yLmhhc2hfbWFzayA9IG8yLmhhc2hfc2l6ZSAtIDEsIG8yLmhhc2hfc2hpZnQgPSB+figobzIuaGFzaF9iaXRzICsgeCAtIDEpIC8geCksIG8yLndpbmRvdyA9IG5ldyBjLkJ1ZjgoMiAqIG8yLndfc2l6ZSksIG8yLmhlYWQgPSBuZXcgYy5CdWYxNihvMi5oYXNoX3NpemUpLCBvMi5wcmV2ID0gbmV3IGMuQnVmMTYobzIud19zaXplKSwgbzIubGl0X2J1ZnNpemUgPSAxIDw8IGkyICsgNiwgbzIucGVuZGluZ19idWZfc2l6ZSA9IDQgKiBvMi5saXRfYnVmc2l6ZSwgbzIucGVuZGluZ19idWYgPSBuZXcgYy5CdWY4KG8yLnBlbmRpbmdfYnVmX3NpemUpLCBvMi5kX2J1ZiA9IDEgKiBvMi5saXRfYnVmc2l6ZSwgbzIubF9idWYgPSAzICogbzIubGl0X2J1ZnNpemUsIG8yLmxldmVsID0gdDIsIG8yLnN0cmF0ZWd5ID0gczIsIG8yLm1ldGhvZCA9IHIyLCBLKGUyKTsKICAgICAgICB9CiAgICAgICAgaCA9IFtuZXcgTSgwLCAwLCAwLCAwLCBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiA9IDY1NTM1OwogICAgICAgICAgZm9yIChyMiA+IGUyLnBlbmRpbmdfYnVmX3NpemUgLSA1ICYmIChyMiA9IGUyLnBlbmRpbmdfYnVmX3NpemUgLSA1KTsgOyApIHsKICAgICAgICAgICAgaWYgKGUyLmxvb2thaGVhZCA8PSAxKSB7CiAgICAgICAgICAgICAgaWYgKGooZTIpLCAwID09PSBlMi5sb29rYWhlYWQgJiYgdDIgPT09IGwpCiAgICAgICAgICAgICAgICByZXR1cm4gQTsKICAgICAgICAgICAgICBpZiAoMCA9PT0gZTIubG9va2FoZWFkKQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZTIuc3Ryc3RhcnQgKz0gZTIubG9va2FoZWFkLCBlMi5sb29rYWhlYWQgPSAwOwogICAgICAgICAgICB2YXIgbjIgPSBlMi5ibG9ja19zdGFydCArIHIyOwogICAgICAgICAgICBpZiAoKDAgPT09IGUyLnN0cnN0YXJ0IHx8IGUyLnN0cnN0YXJ0ID49IG4yKSAmJiAoZTIubG9va2FoZWFkID0gZTIuc3Ryc3RhcnQgLSBuMiwgZTIuc3Ryc3RhcnQgPSBuMiwgTihlMiwgZmFsc2UpLCAwID09PSBlMi5zdHJtLmF2YWlsX291dCkpCiAgICAgICAgICAgICAgcmV0dXJuIEE7CiAgICAgICAgICAgIGlmIChlMi5zdHJzdGFydCAtIGUyLmJsb2NrX3N0YXJ0ID49IGUyLndfc2l6ZSAtIHogJiYgKE4oZTIsIGZhbHNlKSwgMCA9PT0gZTIuc3RybS5hdmFpbF9vdXQpKQogICAgICAgICAgICAgIHJldHVybiBBOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIGUyLmluc2VydCA9IDAsIHQyID09PSBmID8gKE4oZTIsIHRydWUpLCAwID09PSBlMi5zdHJtLmF2YWlsX291dCA/IE8gOiBCKSA6IChlMi5zdHJzdGFydCA+IGUyLmJsb2NrX3N0YXJ0ICYmIChOKGUyLCBmYWxzZSksIGUyLnN0cm0uYXZhaWxfb3V0KSwgQSk7CiAgICAgICAgfSksIG5ldyBNKDQsIDQsIDgsIDQsIFopLCBuZXcgTSg0LCA1LCAxNiwgOCwgWiksIG5ldyBNKDQsIDYsIDMyLCAzMiwgWiksIG5ldyBNKDQsIDQsIDE2LCAxNiwgVyksIG5ldyBNKDgsIDE2LCAzMiwgMzIsIFcpLCBuZXcgTSg4LCAxNiwgMTI4LCAxMjgsIFcpLCBuZXcgTSg4LCAzMiwgMTI4LCAyNTYsIFcpLCBuZXcgTSgzMiwgMTI4LCAyNTgsIDEwMjQsIFcpLCBuZXcgTSgzMiwgMjU4LCAyNTgsIDQwOTYsIFcpXSwgci5kZWZsYXRlSW5pdCA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgcmV0dXJuIFkoZTIsIHQyLCB2LCAxNSwgOCwgMCk7CiAgICAgICAgfSwgci5kZWZsYXRlSW5pdDIgPSBZLCByLmRlZmxhdGVSZXNldCA9IEssIHIuZGVmbGF0ZVJlc2V0S2VlcCA9IEcsIHIuZGVmbGF0ZVNldEhlYWRlciA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgcmV0dXJuIGUyICYmIGUyLnN0YXRlID8gMiAhPT0gZTIuc3RhdGUud3JhcCA/IF8gOiAoZTIuc3RhdGUuZ3poZWFkID0gdDIsIG0pIDogXzsKICAgICAgICB9LCByLmRlZmxhdGUgPSBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiwgbjIsIGkyLCBzMjsKICAgICAgICAgIGlmICghZTIgfHwgIWUyLnN0YXRlIHx8IDUgPCB0MiB8fCB0MiA8IDApCiAgICAgICAgICAgIHJldHVybiBlMiA/IFIoZTIsIF8pIDogXzsKICAgICAgICAgIGlmIChuMiA9IGUyLnN0YXRlLCAhZTIub3V0cHV0IHx8ICFlMi5pbnB1dCAmJiAwICE9PSBlMi5hdmFpbF9pbiB8fCA2NjYgPT09IG4yLnN0YXR1cyAmJiB0MiAhPT0gZikKICAgICAgICAgICAgcmV0dXJuIFIoZTIsIDAgPT09IGUyLmF2YWlsX291dCA/IC01IDogXyk7CiAgICAgICAgICBpZiAobjIuc3RybSA9IGUyLCByMiA9IG4yLmxhc3RfZmx1c2gsIG4yLmxhc3RfZmx1c2ggPSB0MiwgbjIuc3RhdHVzID09PSBDKQogICAgICAgICAgICBpZiAoMiA9PT0gbjIud3JhcCkKICAgICAgICAgICAgICBlMi5hZGxlciA9IDAsIFUobjIsIDMxKSwgVShuMiwgMTM5KSwgVShuMiwgOCksIG4yLmd6aGVhZCA/IChVKG4yLCAobjIuZ3poZWFkLnRleHQgPyAxIDogMCkgKyAobjIuZ3poZWFkLmhjcmMgPyAyIDogMCkgKyAobjIuZ3poZWFkLmV4dHJhID8gNCA6IDApICsgKG4yLmd6aGVhZC5uYW1lID8gOCA6IDApICsgKG4yLmd6aGVhZC5jb21tZW50ID8gMTYgOiAwKSksIFUobjIsIDI1NSAmIG4yLmd6aGVhZC50aW1lKSwgVShuMiwgbjIuZ3poZWFkLnRpbWUgPj4gOCAmIDI1NSksIFUobjIsIG4yLmd6aGVhZC50aW1lID4+IDE2ICYgMjU1KSwgVShuMiwgbjIuZ3poZWFkLnRpbWUgPj4gMjQgJiAyNTUpLCBVKG4yLCA5ID09PSBuMi5sZXZlbCA/IDIgOiAyIDw9IG4yLnN0cmF0ZWd5IHx8IG4yLmxldmVsIDwgMiA/IDQgOiAwKSwgVShuMiwgMjU1ICYgbjIuZ3poZWFkLm9zKSwgbjIuZ3poZWFkLmV4dHJhICYmIG4yLmd6aGVhZC5leHRyYS5sZW5ndGggJiYgKFUobjIsIDI1NSAmIG4yLmd6aGVhZC5leHRyYS5sZW5ndGgpLCBVKG4yLCBuMi5nemhlYWQuZXh0cmEubGVuZ3RoID4+IDggJiAyNTUpKSwgbjIuZ3poZWFkLmhjcmMgJiYgKGUyLmFkbGVyID0gcChlMi5hZGxlciwgbjIucGVuZGluZ19idWYsIG4yLnBlbmRpbmcsIDApKSwgbjIuZ3ppbmRleCA9IDAsIG4yLnN0YXR1cyA9IDY5KSA6IChVKG4yLCAwKSwgVShuMiwgMCksIFUobjIsIDApLCBVKG4yLCAwKSwgVShuMiwgMCksIFUobjIsIDkgPT09IG4yLmxldmVsID8gMiA6IDIgPD0gbjIuc3RyYXRlZ3kgfHwgbjIubGV2ZWwgPCAyID8gNCA6IDApLCBVKG4yLCAzKSwgbjIuc3RhdHVzID0gRSk7CiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgIHZhciBhMiA9IHYgKyAobjIud19iaXRzIC0gOCA8PCA0KSA8PCA4OwogICAgICAgICAgICAgIGEyIHw9ICgyIDw9IG4yLnN0cmF0ZWd5IHx8IG4yLmxldmVsIDwgMiA/IDAgOiBuMi5sZXZlbCA8IDYgPyAxIDogNiA9PT0gbjIubGV2ZWwgPyAyIDogMykgPDwgNiwgMCAhPT0gbjIuc3Ryc3RhcnQgJiYgKGEyIHw9IDMyKSwgYTIgKz0gMzEgLSBhMiAlIDMxLCBuMi5zdGF0dXMgPSBFLCBQKG4yLCBhMiksIDAgIT09IG4yLnN0cnN0YXJ0ICYmIChQKG4yLCBlMi5hZGxlciA+Pj4gMTYpLCBQKG4yLCA2NTUzNSAmIGUyLmFkbGVyKSksIGUyLmFkbGVyID0gMTsKICAgICAgICAgICAgfQogICAgICAgICAgaWYgKDY5ID09PSBuMi5zdGF0dXMpCiAgICAgICAgICAgIGlmIChuMi5nemhlYWQuZXh0cmEpIHsKICAgICAgICAgICAgICBmb3IgKGkyID0gbjIucGVuZGluZzsgbjIuZ3ppbmRleCA8ICg2NTUzNSAmIG4yLmd6aGVhZC5leHRyYS5sZW5ndGgpICYmIChuMi5wZW5kaW5nICE9PSBuMi5wZW5kaW5nX2J1Zl9zaXplIHx8IChuMi5nemhlYWQuaGNyYyAmJiBuMi5wZW5kaW5nID4gaTIgJiYgKGUyLmFkbGVyID0gcChlMi5hZGxlciwgbjIucGVuZGluZ19idWYsIG4yLnBlbmRpbmcgLSBpMiwgaTIpKSwgRihlMiksIGkyID0gbjIucGVuZGluZywgbjIucGVuZGluZyAhPT0gbjIucGVuZGluZ19idWZfc2l6ZSkpOyApCiAgICAgICAgICAgICAgICBVKG4yLCAyNTUgJiBuMi5nemhlYWQuZXh0cmFbbjIuZ3ppbmRleF0pLCBuMi5nemluZGV4Kys7CiAgICAgICAgICAgICAgbjIuZ3poZWFkLmhjcmMgJiYgbjIucGVuZGluZyA+IGkyICYmIChlMi5hZGxlciA9IHAoZTIuYWRsZXIsIG4yLnBlbmRpbmdfYnVmLCBuMi5wZW5kaW5nIC0gaTIsIGkyKSksIG4yLmd6aW5kZXggPT09IG4yLmd6aGVhZC5leHRyYS5sZW5ndGggJiYgKG4yLmd6aW5kZXggPSAwLCBuMi5zdGF0dXMgPSA3Myk7CiAgICAgICAgICAgIH0gZWxzZQogICAgICAgICAgICAgIG4yLnN0YXR1cyA9IDczOwogICAgICAgICAgaWYgKDczID09PSBuMi5zdGF0dXMpCiAgICAgICAgICAgIGlmIChuMi5nemhlYWQubmFtZSkgewogICAgICAgICAgICAgIGkyID0gbjIucGVuZGluZzsKICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICBpZiAobjIucGVuZGluZyA9PT0gbjIucGVuZGluZ19idWZfc2l6ZSAmJiAobjIuZ3poZWFkLmhjcmMgJiYgbjIucGVuZGluZyA+IGkyICYmIChlMi5hZGxlciA9IHAoZTIuYWRsZXIsIG4yLnBlbmRpbmdfYnVmLCBuMi5wZW5kaW5nIC0gaTIsIGkyKSksIEYoZTIpLCBpMiA9IG4yLnBlbmRpbmcsIG4yLnBlbmRpbmcgPT09IG4yLnBlbmRpbmdfYnVmX3NpemUpKSB7CiAgICAgICAgICAgICAgICAgIHMyID0gMTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzMiA9IG4yLmd6aW5kZXggPCBuMi5nemhlYWQubmFtZS5sZW5ndGggPyAyNTUgJiBuMi5nemhlYWQubmFtZS5jaGFyQ29kZUF0KG4yLmd6aW5kZXgrKykgOiAwLCBVKG4yLCBzMik7CiAgICAgICAgICAgICAgfSB3aGlsZSAoMCAhPT0gczIpOwogICAgICAgICAgICAgIG4yLmd6aGVhZC5oY3JjICYmIG4yLnBlbmRpbmcgPiBpMiAmJiAoZTIuYWRsZXIgPSBwKGUyLmFkbGVyLCBuMi5wZW5kaW5nX2J1ZiwgbjIucGVuZGluZyAtIGkyLCBpMikpLCAwID09PSBzMiAmJiAobjIuZ3ppbmRleCA9IDAsIG4yLnN0YXR1cyA9IDkxKTsKICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgbjIuc3RhdHVzID0gOTE7CiAgICAgICAgICBpZiAoOTEgPT09IG4yLnN0YXR1cykKICAgICAgICAgICAgaWYgKG4yLmd6aGVhZC5jb21tZW50KSB7CiAgICAgICAgICAgICAgaTIgPSBuMi5wZW5kaW5nOwogICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgIGlmIChuMi5wZW5kaW5nID09PSBuMi5wZW5kaW5nX2J1Zl9zaXplICYmIChuMi5nemhlYWQuaGNyYyAmJiBuMi5wZW5kaW5nID4gaTIgJiYgKGUyLmFkbGVyID0gcChlMi5hZGxlciwgbjIucGVuZGluZ19idWYsIG4yLnBlbmRpbmcgLSBpMiwgaTIpKSwgRihlMiksIGkyID0gbjIucGVuZGluZywgbjIucGVuZGluZyA9PT0gbjIucGVuZGluZ19idWZfc2l6ZSkpIHsKICAgICAgICAgICAgICAgICAgczIgPSAxOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHMyID0gbjIuZ3ppbmRleCA8IG4yLmd6aGVhZC5jb21tZW50Lmxlbmd0aCA/IDI1NSAmIG4yLmd6aGVhZC5jb21tZW50LmNoYXJDb2RlQXQobjIuZ3ppbmRleCsrKSA6IDAsIFUobjIsIHMyKTsKICAgICAgICAgICAgICB9IHdoaWxlICgwICE9PSBzMik7CiAgICAgICAgICAgICAgbjIuZ3poZWFkLmhjcmMgJiYgbjIucGVuZGluZyA+IGkyICYmIChlMi5hZGxlciA9IHAoZTIuYWRsZXIsIG4yLnBlbmRpbmdfYnVmLCBuMi5wZW5kaW5nIC0gaTIsIGkyKSksIDAgPT09IHMyICYmIChuMi5zdGF0dXMgPSAxMDMpOwogICAgICAgICAgICB9IGVsc2UKICAgICAgICAgICAgICBuMi5zdGF0dXMgPSAxMDM7CiAgICAgICAgICBpZiAoMTAzID09PSBuMi5zdGF0dXMgJiYgKG4yLmd6aGVhZC5oY3JjID8gKG4yLnBlbmRpbmcgKyAyID4gbjIucGVuZGluZ19idWZfc2l6ZSAmJiBGKGUyKSwgbjIucGVuZGluZyArIDIgPD0gbjIucGVuZGluZ19idWZfc2l6ZSAmJiAoVShuMiwgMjU1ICYgZTIuYWRsZXIpLCBVKG4yLCBlMi5hZGxlciA+PiA4ICYgMjU1KSwgZTIuYWRsZXIgPSAwLCBuMi5zdGF0dXMgPSBFKSkgOiBuMi5zdGF0dXMgPSBFKSwgMCAhPT0gbjIucGVuZGluZykgewogICAgICAgICAgICBpZiAoRihlMiksIDAgPT09IGUyLmF2YWlsX291dCkKICAgICAgICAgICAgICByZXR1cm4gbjIubGFzdF9mbHVzaCA9IC0xLCBtOwogICAgICAgICAgfSBlbHNlIGlmICgwID09PSBlMi5hdmFpbF9pbiAmJiBUKHQyKSA8PSBUKHIyKSAmJiB0MiAhPT0gZikKICAgICAgICAgICAgcmV0dXJuIFIoZTIsIC01KTsKICAgICAgICAgIGlmICg2NjYgPT09IG4yLnN0YXR1cyAmJiAwICE9PSBlMi5hdmFpbF9pbikKICAgICAgICAgICAgcmV0dXJuIFIoZTIsIC01KTsKICAgICAgICAgIGlmICgwICE9PSBlMi5hdmFpbF9pbiB8fCAwICE9PSBuMi5sb29rYWhlYWQgfHwgdDIgIT09IGwgJiYgNjY2ICE9PSBuMi5zdGF0dXMpIHsKICAgICAgICAgICAgdmFyIG8yID0gMiA9PT0gbjIuc3RyYXRlZ3kgPyBmdW5jdGlvbihlMywgdDMpIHsKICAgICAgICAgICAgICBmb3IgKHZhciByMzsgOyApIHsKICAgICAgICAgICAgICAgIGlmICgwID09PSBlMy5sb29rYWhlYWQgJiYgKGooZTMpLCAwID09PSBlMy5sb29rYWhlYWQpKSB7CiAgICAgICAgICAgICAgICAgIGlmICh0MyA9PT0gbCkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gQTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoZTMubWF0Y2hfbGVuZ3RoID0gMCwgcjMgPSB1Ll90cl90YWxseShlMywgMCwgZTMud2luZG93W2UzLnN0cnN0YXJ0XSksIGUzLmxvb2thaGVhZC0tLCBlMy5zdHJzdGFydCsrLCByMyAmJiAoTihlMywgZmFsc2UpLCAwID09PSBlMy5zdHJtLmF2YWlsX291dCkpCiAgICAgICAgICAgICAgICAgIHJldHVybiBBOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gZTMuaW5zZXJ0ID0gMCwgdDMgPT09IGYgPyAoTihlMywgdHJ1ZSksIDAgPT09IGUzLnN0cm0uYXZhaWxfb3V0ID8gTyA6IEIpIDogZTMubGFzdF9saXQgJiYgKE4oZTMsIGZhbHNlKSwgMCA9PT0gZTMuc3RybS5hdmFpbF9vdXQpID8gQSA6IEk7CiAgICAgICAgICAgIH0objIsIHQyKSA6IDMgPT09IG4yLnN0cmF0ZWd5ID8gZnVuY3Rpb24oZTMsIHQzKSB7CiAgICAgICAgICAgICAgZm9yICh2YXIgcjMsIG4zLCBpMywgczMsIGEzID0gZTMud2luZG93OyA7ICkgewogICAgICAgICAgICAgICAgaWYgKGUzLmxvb2thaGVhZCA8PSBTKSB7CiAgICAgICAgICAgICAgICAgIGlmIChqKGUzKSwgZTMubG9va2FoZWFkIDw9IFMgJiYgdDMgPT09IGwpCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEE7CiAgICAgICAgICAgICAgICAgIGlmICgwID09PSBlMy5sb29rYWhlYWQpCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoZTMubWF0Y2hfbGVuZ3RoID0gMCwgZTMubG9va2FoZWFkID49IHggJiYgMCA8IGUzLnN0cnN0YXJ0ICYmIChuMyA9IGEzW2kzID0gZTMuc3Ryc3RhcnQgLSAxXSkgPT09IGEzWysraTNdICYmIG4zID09PSBhM1srK2kzXSAmJiBuMyA9PT0gYTNbKytpM10pIHsKICAgICAgICAgICAgICAgICAgczMgPSBlMy5zdHJzdGFydCArIFM7CiAgICAgICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgICAgfSB3aGlsZSAobjMgPT09IGEzWysraTNdICYmIG4zID09PSBhM1srK2kzXSAmJiBuMyA9PT0gYTNbKytpM10gJiYgbjMgPT09IGEzWysraTNdICYmIG4zID09PSBhM1srK2kzXSAmJiBuMyA9PT0gYTNbKytpM10gJiYgbjMgPT09IGEzWysraTNdICYmIG4zID09PSBhM1srK2kzXSAmJiBpMyA8IHMzKTsKICAgICAgICAgICAgICAgICAgZTMubWF0Y2hfbGVuZ3RoID0gUyAtIChzMyAtIGkzKSwgZTMubWF0Y2hfbGVuZ3RoID4gZTMubG9va2FoZWFkICYmIChlMy5tYXRjaF9sZW5ndGggPSBlMy5sb29rYWhlYWQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKGUzLm1hdGNoX2xlbmd0aCA+PSB4ID8gKHIzID0gdS5fdHJfdGFsbHkoZTMsIDEsIGUzLm1hdGNoX2xlbmd0aCAtIHgpLCBlMy5sb29rYWhlYWQgLT0gZTMubWF0Y2hfbGVuZ3RoLCBlMy5zdHJzdGFydCArPSBlMy5tYXRjaF9sZW5ndGgsIGUzLm1hdGNoX2xlbmd0aCA9IDApIDogKHIzID0gdS5fdHJfdGFsbHkoZTMsIDAsIGUzLndpbmRvd1tlMy5zdHJzdGFydF0pLCBlMy5sb29rYWhlYWQtLSwgZTMuc3Ryc3RhcnQrKyksIHIzICYmIChOKGUzLCBmYWxzZSksIDAgPT09IGUzLnN0cm0uYXZhaWxfb3V0KSkKICAgICAgICAgICAgICAgICAgcmV0dXJuIEE7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJldHVybiBlMy5pbnNlcnQgPSAwLCB0MyA9PT0gZiA/IChOKGUzLCB0cnVlKSwgMCA9PT0gZTMuc3RybS5hdmFpbF9vdXQgPyBPIDogQikgOiBlMy5sYXN0X2xpdCAmJiAoTihlMywgZmFsc2UpLCAwID09PSBlMy5zdHJtLmF2YWlsX291dCkgPyBBIDogSTsKICAgICAgICAgICAgfShuMiwgdDIpIDogaFtuMi5sZXZlbF0uZnVuYyhuMiwgdDIpOwogICAgICAgICAgICBpZiAobzIgIT09IE8gJiYgbzIgIT09IEIgfHwgKG4yLnN0YXR1cyA9IDY2NiksIG8yID09PSBBIHx8IG8yID09PSBPKQogICAgICAgICAgICAgIHJldHVybiAwID09PSBlMi5hdmFpbF9vdXQgJiYgKG4yLmxhc3RfZmx1c2ggPSAtMSksIG07CiAgICAgICAgICAgIGlmIChvMiA9PT0gSSAmJiAoMSA9PT0gdDIgPyB1Ll90cl9hbGlnbihuMikgOiA1ICE9PSB0MiAmJiAodS5fdHJfc3RvcmVkX2Jsb2NrKG4yLCAwLCAwLCBmYWxzZSksIDMgPT09IHQyICYmIChEKG4yLmhlYWQpLCAwID09PSBuMi5sb29rYWhlYWQgJiYgKG4yLnN0cnN0YXJ0ID0gMCwgbjIuYmxvY2tfc3RhcnQgPSAwLCBuMi5pbnNlcnQgPSAwKSkpLCBGKGUyKSwgMCA9PT0gZTIuYXZhaWxfb3V0KSkKICAgICAgICAgICAgICByZXR1cm4gbjIubGFzdF9mbHVzaCA9IC0xLCBtOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIHQyICE9PSBmID8gbSA6IG4yLndyYXAgPD0gMCA/IDEgOiAoMiA9PT0gbjIud3JhcCA/IChVKG4yLCAyNTUgJiBlMi5hZGxlciksIFUobjIsIGUyLmFkbGVyID4+IDggJiAyNTUpLCBVKG4yLCBlMi5hZGxlciA+PiAxNiAmIDI1NSksIFUobjIsIGUyLmFkbGVyID4+IDI0ICYgMjU1KSwgVShuMiwgMjU1ICYgZTIudG90YWxfaW4pLCBVKG4yLCBlMi50b3RhbF9pbiA+PiA4ICYgMjU1KSwgVShuMiwgZTIudG90YWxfaW4gPj4gMTYgJiAyNTUpLCBVKG4yLCBlMi50b3RhbF9pbiA+PiAyNCAmIDI1NSkpIDogKFAobjIsIGUyLmFkbGVyID4+PiAxNiksIFAobjIsIDY1NTM1ICYgZTIuYWRsZXIpKSwgRihlMiksIDAgPCBuMi53cmFwICYmIChuMi53cmFwID0gLW4yLndyYXApLCAwICE9PSBuMi5wZW5kaW5nID8gbSA6IDEpOwogICAgICAgIH0sIHIuZGVmbGF0ZUVuZCA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICB2YXIgdDI7CiAgICAgICAgICByZXR1cm4gZTIgJiYgZTIuc3RhdGUgPyAodDIgPSBlMi5zdGF0ZS5zdGF0dXMpICE9PSBDICYmIDY5ICE9PSB0MiAmJiA3MyAhPT0gdDIgJiYgOTEgIT09IHQyICYmIDEwMyAhPT0gdDIgJiYgdDIgIT09IEUgJiYgNjY2ICE9PSB0MiA/IFIoZTIsIF8pIDogKGUyLnN0YXRlID0gbnVsbCwgdDIgPT09IEUgPyBSKGUyLCAtMykgOiBtKSA6IF87CiAgICAgICAgfSwgci5kZWZsYXRlU2V0RGljdGlvbmFyeSA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgdmFyIHIyLCBuMiwgaTIsIHMyLCBhMiwgbzIsIGgyLCB1MiwgbDIgPSB0Mi5sZW5ndGg7CiAgICAgICAgICBpZiAoIWUyIHx8ICFlMi5zdGF0ZSkKICAgICAgICAgICAgcmV0dXJuIF87CiAgICAgICAgICBpZiAoMiA9PT0gKHMyID0gKHIyID0gZTIuc3RhdGUpLndyYXApIHx8IDEgPT09IHMyICYmIHIyLnN0YXR1cyAhPT0gQyB8fCByMi5sb29rYWhlYWQpCiAgICAgICAgICAgIHJldHVybiBfOwogICAgICAgICAgZm9yICgxID09PSBzMiAmJiAoZTIuYWRsZXIgPSBkKGUyLmFkbGVyLCB0MiwgbDIsIDApKSwgcjIud3JhcCA9IDAsIGwyID49IHIyLndfc2l6ZSAmJiAoMCA9PT0gczIgJiYgKEQocjIuaGVhZCksIHIyLnN0cnN0YXJ0ID0gMCwgcjIuYmxvY2tfc3RhcnQgPSAwLCByMi5pbnNlcnQgPSAwKSwgdTIgPSBuZXcgYy5CdWY4KHIyLndfc2l6ZSksIGMuYXJyYXlTZXQodTIsIHQyLCBsMiAtIHIyLndfc2l6ZSwgcjIud19zaXplLCAwKSwgdDIgPSB1MiwgbDIgPSByMi53X3NpemUpLCBhMiA9IGUyLmF2YWlsX2luLCBvMiA9IGUyLm5leHRfaW4sIGgyID0gZTIuaW5wdXQsIGUyLmF2YWlsX2luID0gbDIsIGUyLm5leHRfaW4gPSAwLCBlMi5pbnB1dCA9IHQyLCBqKHIyKTsgcjIubG9va2FoZWFkID49IHg7ICkgewogICAgICAgICAgICBmb3IgKG4yID0gcjIuc3Ryc3RhcnQsIGkyID0gcjIubG9va2FoZWFkIC0gKHggLSAxKTsgcjIuaW5zX2ggPSAocjIuaW5zX2ggPDwgcjIuaGFzaF9zaGlmdCBeIHIyLndpbmRvd1tuMiArIHggLSAxXSkgJiByMi5oYXNoX21hc2ssIHIyLnByZXZbbjIgJiByMi53X21hc2tdID0gcjIuaGVhZFtyMi5pbnNfaF0sIHIyLmhlYWRbcjIuaW5zX2hdID0gbjIsIG4yKyssIC0taTI7ICkKICAgICAgICAgICAgICA7CiAgICAgICAgICAgIHIyLnN0cnN0YXJ0ID0gbjIsIHIyLmxvb2thaGVhZCA9IHggLSAxLCBqKHIyKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiByMi5zdHJzdGFydCArPSByMi5sb29rYWhlYWQsIHIyLmJsb2NrX3N0YXJ0ID0gcjIuc3Ryc3RhcnQsIHIyLmluc2VydCA9IHIyLmxvb2thaGVhZCwgcjIubG9va2FoZWFkID0gMCwgcjIubWF0Y2hfbGVuZ3RoID0gcjIucHJldl9sZW5ndGggPSB4IC0gMSwgcjIubWF0Y2hfYXZhaWxhYmxlID0gMCwgZTIubmV4dF9pbiA9IG8yLCBlMi5pbnB1dCA9IGgyLCBlMi5hdmFpbF9pbiA9IGEyLCByMi53cmFwID0gczIsIG07CiAgICAgICAgfSwgci5kZWZsYXRlSW5mbyA9ICJwYWtvIGRlZmxhdGUgKGZyb20gTm9kZWNhIHByb2plY3QpIjsKICAgICAgfSwgeyAiLi4vdXRpbHMvY29tbW9uIjogNDEsICIuL2FkbGVyMzIiOiA0MywgIi4vY3JjMzIiOiA0NSwgIi4vbWVzc2FnZXMiOiA1MSwgIi4vdHJlZXMiOiA1MiB9XSwgNDc6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdC5leHBvcnRzID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICB0aGlzLnRleHQgPSAwLCB0aGlzLnRpbWUgPSAwLCB0aGlzLnhmbGFncyA9IDAsIHRoaXMub3MgPSAwLCB0aGlzLmV4dHJhID0gbnVsbCwgdGhpcy5leHRyYV9sZW4gPSAwLCB0aGlzLm5hbWUgPSAiIiwgdGhpcy5jb21tZW50ID0gIiIsIHRoaXMuaGNyYyA9IDAsIHRoaXMuZG9uZSA9IGZhbHNlOwogICAgICAgIH07CiAgICAgIH0sIHt9XSwgNDg6IFtmdW5jdGlvbihlLCB0LCByKSB7CiAgICAgICAgdC5leHBvcnRzID0gZnVuY3Rpb24oZTIsIHQyKSB7CiAgICAgICAgICB2YXIgcjIsIG4sIGksIHMsIGEsIG8sIGgsIHUsIGwsIGYsIGMsIGQsIHAsIG0sIF8sIGcsIGIsIHYsIHksIHcsIGssIHgsIFMsIHosIEM7CiAgICAgICAgICByMiA9IGUyLnN0YXRlLCBuID0gZTIubmV4dF9pbiwgeiA9IGUyLmlucHV0LCBpID0gbiArIChlMi5hdmFpbF9pbiAtIDUpLCBzID0gZTIubmV4dF9vdXQsIEMgPSBlMi5vdXRwdXQsIGEgPSBzIC0gKHQyIC0gZTIuYXZhaWxfb3V0KSwgbyA9IHMgKyAoZTIuYXZhaWxfb3V0IC0gMjU3KSwgaCA9IHIyLmRtYXgsIHUgPSByMi53c2l6ZSwgbCA9IHIyLndoYXZlLCBmID0gcjIud25leHQsIGMgPSByMi53aW5kb3csIGQgPSByMi5ob2xkLCBwID0gcjIuYml0cywgbSA9IHIyLmxlbmNvZGUsIF8gPSByMi5kaXN0Y29kZSwgZyA9ICgxIDw8IHIyLmxlbmJpdHMpIC0gMSwgYiA9ICgxIDw8IHIyLmRpc3RiaXRzKSAtIDE7CiAgICAgICAgICBlOgogICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgcCA8IDE1ICYmIChkICs9IHpbbisrXSA8PCBwLCBwICs9IDgsIGQgKz0geltuKytdIDw8IHAsIHAgKz0gOCksIHYgPSBtW2QgJiBnXTsKICAgICAgICAgICAgICB0OgogICAgICAgICAgICAgICAgZm9yICg7IDsgKSB7CiAgICAgICAgICAgICAgICAgIGlmIChkID4+Pj0geSA9IHYgPj4+IDI0LCBwIC09IHksIDAgPT09ICh5ID0gdiA+Pj4gMTYgJiAyNTUpKQogICAgICAgICAgICAgICAgICAgIENbcysrXSA9IDY1NTM1ICYgdjsKICAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCEoMTYgJiB5KSkgewogICAgICAgICAgICAgICAgICAgICAgaWYgKDAgPT0gKDY0ICYgeSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdiA9IG1bKDY1NTM1ICYgdikgKyAoZCAmICgxIDw8IHkpIC0gMSldOwogICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZSB0OwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgaWYgKDMyICYgeSkgewogICAgICAgICAgICAgICAgICAgICAgICByMi5tb2RlID0gMTI7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICBlMi5tc2cgPSAiaW52YWxpZCBsaXRlcmFsL2xlbmd0aCBjb2RlIiwgcjIubW9kZSA9IDMwOwogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdyA9IDY1NTM1ICYgdiwgKHkgJj0gMTUpICYmIChwIDwgeSAmJiAoZCArPSB6W24rK10gPDwgcCwgcCArPSA4KSwgdyArPSBkICYgKDEgPDwgeSkgLSAxLCBkID4+Pj0geSwgcCAtPSB5KSwgcCA8IDE1ICYmIChkICs9IHpbbisrXSA8PCBwLCBwICs9IDgsIGQgKz0geltuKytdIDw8IHAsIHAgKz0gOCksIHYgPSBfW2QgJiBiXTsKICAgICAgICAgICAgICAgICAgICByOgogICAgICAgICAgICAgICAgICAgICAgZm9yICg7IDsgKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkID4+Pj0geSA9IHYgPj4+IDI0LCBwIC09IHksICEoMTYgJiAoeSA9IHYgPj4+IDE2ICYgMjU1KSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoMCA9PSAoNjQgJiB5KSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdiA9IF9bKDY1NTM1ICYgdikgKyAoZCAmICgxIDw8IHkpIC0gMSldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWUgcjsKICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgZTIubXNnID0gImludmFsaWQgZGlzdGFuY2UgY29kZSIsIHIyLm1vZGUgPSAzMDsKICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrID0gNjU1MzUgJiB2LCBwIDwgKHkgJj0gMTUpICYmIChkICs9IHpbbisrXSA8PCBwLCAocCArPSA4KSA8IHkgJiYgKGQgKz0geltuKytdIDw8IHAsIHAgKz0gOCkpLCBoIDwgKGsgKz0gZCAmICgxIDw8IHkpIC0gMSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBlMi5tc2cgPSAiaW52YWxpZCBkaXN0YW5jZSB0b28gZmFyIGJhY2siLCByMi5tb2RlID0gMzA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZCA+Pj49IHksIHAgLT0geSwgKHkgPSBzIC0gYSkgPCBrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGwgPCAoeSA9IGsgLSB5KSAmJiByMi5zYW5lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlMi5tc2cgPSAiaW52YWxpZCBkaXN0YW5jZSB0b28gZmFyIGJhY2siLCByMi5tb2RlID0gMzA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoUyA9IGMsICh4ID0gMCkgPT09IGYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh4ICs9IHUgLSB5LCB5IDwgdykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHcgLT0geTsgQ1tzKytdID0gY1t4KytdLCAtLXk7ICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBzIC0gaywgUyA9IEM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChmIDwgeSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHggKz0gdSArIGYgLSB5LCAoeSAtPSBmKSA8IHcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh3IC09IHk7IENbcysrXSA9IGNbeCsrXSwgLS15OyApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoeCA9IDAsIGYgPCB3KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh3IC09IHkgPSBmOyBDW3MrK10gPSBjW3grK10sIC0teTsgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBzIC0gaywgUyA9IEM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHggKz0gZiAtIHksIHkgPCB3KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHcgLT0geTsgQ1tzKytdID0gY1t4KytdLCAtLXk7ICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IHMgLSBrLCBTID0gQzsKICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICg7IDIgPCB3OyApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDW3MrK10gPSBTW3grK10sIENbcysrXSA9IFNbeCsrXSwgQ1tzKytdID0gU1t4KytdLCB3IC09IDM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgdyAmJiAoQ1tzKytdID0gU1t4KytdLCAxIDwgdyAmJiAoQ1tzKytdID0gU1t4KytdKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh4ID0gcyAtIGs7IENbcysrXSA9IENbeCsrXSwgQ1tzKytdID0gQ1t4KytdLCBDW3MrK10gPSBDW3grK10sIDIgPCAodyAtPSAzKTsgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgICAgICAgICAgICAgIHcgJiYgKENbcysrXSA9IENbeCsrXSwgMSA8IHcgJiYgKENbcysrXSA9IENbeCsrXSkpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IHdoaWxlIChuIDwgaSAmJiBzIDwgbyk7CiAgICAgICAgICBuIC09IHcgPSBwID4+IDMsIGQgJj0gKDEgPDwgKHAgLT0gdyA8PCAzKSkgLSAxLCBlMi5uZXh0X2luID0gbiwgZTIubmV4dF9vdXQgPSBzLCBlMi5hdmFpbF9pbiA9IG4gPCBpID8gaSAtIG4gKyA1IDogNSAtIChuIC0gaSksIGUyLmF2YWlsX291dCA9IHMgPCBvID8gbyAtIHMgKyAyNTcgOiAyNTcgLSAocyAtIG8pLCByMi5ob2xkID0gZCwgcjIuYml0cyA9IHA7CiAgICAgICAgfTsKICAgICAgfSwge31dLCA0OTogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgSSA9IGUoIi4uL3V0aWxzL2NvbW1vbiIpLCBPID0gZSgiLi9hZGxlcjMyIiksIEIgPSBlKCIuL2NyYzMyIiksIFIgPSBlKCIuL2luZmZhc3QiKSwgVCA9IGUoIi4vaW5mdHJlZXMiKSwgRCA9IDEsIEYgPSAyLCBOID0gMCwgVSA9IC0yLCBQID0gMSwgbiA9IDg1MiwgaSA9IDU5MjsKICAgICAgICBmdW5jdGlvbiBMKGUyKSB7CiAgICAgICAgICByZXR1cm4gKGUyID4+PiAyNCAmIDI1NSkgKyAoZTIgPj4+IDggJiA2NTI4MCkgKyAoKDY1MjgwICYgZTIpIDw8IDgpICsgKCgyNTUgJiBlMikgPDwgMjQpOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBzKCkgewogICAgICAgICAgdGhpcy5tb2RlID0gMCwgdGhpcy5sYXN0ID0gZmFsc2UsIHRoaXMud3JhcCA9IDAsIHRoaXMuaGF2ZWRpY3QgPSBmYWxzZSwgdGhpcy5mbGFncyA9IDAsIHRoaXMuZG1heCA9IDAsIHRoaXMuY2hlY2sgPSAwLCB0aGlzLnRvdGFsID0gMCwgdGhpcy5oZWFkID0gbnVsbCwgdGhpcy53Yml0cyA9IDAsIHRoaXMud3NpemUgPSAwLCB0aGlzLndoYXZlID0gMCwgdGhpcy53bmV4dCA9IDAsIHRoaXMud2luZG93ID0gbnVsbCwgdGhpcy5ob2xkID0gMCwgdGhpcy5iaXRzID0gMCwgdGhpcy5sZW5ndGggPSAwLCB0aGlzLm9mZnNldCA9IDAsIHRoaXMuZXh0cmEgPSAwLCB0aGlzLmxlbmNvZGUgPSBudWxsLCB0aGlzLmRpc3Rjb2RlID0gbnVsbCwgdGhpcy5sZW5iaXRzID0gMCwgdGhpcy5kaXN0Yml0cyA9IDAsIHRoaXMubmNvZGUgPSAwLCB0aGlzLm5sZW4gPSAwLCB0aGlzLm5kaXN0ID0gMCwgdGhpcy5oYXZlID0gMCwgdGhpcy5uZXh0ID0gbnVsbCwgdGhpcy5sZW5zID0gbmV3IEkuQnVmMTYoMzIwKSwgdGhpcy53b3JrID0gbmV3IEkuQnVmMTYoMjg4KSwgdGhpcy5sZW5keW4gPSBudWxsLCB0aGlzLmRpc3RkeW4gPSBudWxsLCB0aGlzLnNhbmUgPSAwLCB0aGlzLmJhY2sgPSAwLCB0aGlzLndhcyA9IDA7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIGEoZTIpIHsKICAgICAgICAgIHZhciB0MjsKICAgICAgICAgIHJldHVybiBlMiAmJiBlMi5zdGF0ZSA/ICh0MiA9IGUyLnN0YXRlLCBlMi50b3RhbF9pbiA9IGUyLnRvdGFsX291dCA9IHQyLnRvdGFsID0gMCwgZTIubXNnID0gIiIsIHQyLndyYXAgJiYgKGUyLmFkbGVyID0gMSAmIHQyLndyYXApLCB0Mi5tb2RlID0gUCwgdDIubGFzdCA9IDAsIHQyLmhhdmVkaWN0ID0gMCwgdDIuZG1heCA9IDMyNzY4LCB0Mi5oZWFkID0gbnVsbCwgdDIuaG9sZCA9IDAsIHQyLmJpdHMgPSAwLCB0Mi5sZW5jb2RlID0gdDIubGVuZHluID0gbmV3IEkuQnVmMzIobiksIHQyLmRpc3Rjb2RlID0gdDIuZGlzdGR5biA9IG5ldyBJLkJ1ZjMyKGkpLCB0Mi5zYW5lID0gMSwgdDIuYmFjayA9IC0xLCBOKSA6IFU7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIG8oZTIpIHsKICAgICAgICAgIHZhciB0MjsKICAgICAgICAgIHJldHVybiBlMiAmJiBlMi5zdGF0ZSA/ICgodDIgPSBlMi5zdGF0ZSkud3NpemUgPSAwLCB0Mi53aGF2ZSA9IDAsIHQyLnduZXh0ID0gMCwgYShlMikpIDogVTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gaChlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiwgbjI7CiAgICAgICAgICByZXR1cm4gZTIgJiYgZTIuc3RhdGUgPyAobjIgPSBlMi5zdGF0ZSwgdDIgPCAwID8gKHIyID0gMCwgdDIgPSAtdDIpIDogKHIyID0gMSArICh0MiA+PiA0KSwgdDIgPCA0OCAmJiAodDIgJj0gMTUpKSwgdDIgJiYgKHQyIDwgOCB8fCAxNSA8IHQyKSA/IFUgOiAobnVsbCAhPT0gbjIud2luZG93ICYmIG4yLndiaXRzICE9PSB0MiAmJiAobjIud2luZG93ID0gbnVsbCksIG4yLndyYXAgPSByMiwgbjIud2JpdHMgPSB0MiwgbyhlMikpKSA6IFU7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIHUoZTIsIHQyKSB7CiAgICAgICAgICB2YXIgcjIsIG4yOwogICAgICAgICAgcmV0dXJuIGUyID8gKG4yID0gbmV3IHMoKSwgKGUyLnN0YXRlID0gbjIpLndpbmRvdyA9IG51bGwsIChyMiA9IGgoZTIsIHQyKSkgIT09IE4gJiYgKGUyLnN0YXRlID0gbnVsbCksIHIyKSA6IFU7CiAgICAgICAgfQogICAgICAgIHZhciBsLCBmLCBjID0gdHJ1ZTsKICAgICAgICBmdW5jdGlvbiBqKGUyKSB7CiAgICAgICAgICBpZiAoYykgewogICAgICAgICAgICB2YXIgdDI7CiAgICAgICAgICAgIGZvciAobCA9IG5ldyBJLkJ1ZjMyKDUxMiksIGYgPSBuZXcgSS5CdWYzMigzMiksIHQyID0gMDsgdDIgPCAxNDQ7ICkKICAgICAgICAgICAgICBlMi5sZW5zW3QyKytdID0gODsKICAgICAgICAgICAgZm9yICg7IHQyIDwgMjU2OyApCiAgICAgICAgICAgICAgZTIubGVuc1t0MisrXSA9IDk7CiAgICAgICAgICAgIGZvciAoOyB0MiA8IDI4MDsgKQogICAgICAgICAgICAgIGUyLmxlbnNbdDIrK10gPSA3OwogICAgICAgICAgICBmb3IgKDsgdDIgPCAyODg7ICkKICAgICAgICAgICAgICBlMi5sZW5zW3QyKytdID0gODsKICAgICAgICAgICAgZm9yIChUKEQsIGUyLmxlbnMsIDAsIDI4OCwgbCwgMCwgZTIud29yaywgeyBiaXRzOiA5IH0pLCB0MiA9IDA7IHQyIDwgMzI7ICkKICAgICAgICAgICAgICBlMi5sZW5zW3QyKytdID0gNTsKICAgICAgICAgICAgVChGLCBlMi5sZW5zLCAwLCAzMiwgZiwgMCwgZTIud29yaywgeyBiaXRzOiA1IH0pLCBjID0gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgICBlMi5sZW5jb2RlID0gbCwgZTIubGVuYml0cyA9IDksIGUyLmRpc3Rjb2RlID0gZiwgZTIuZGlzdGJpdHMgPSA1OwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBaKGUyLCB0MiwgcjIsIG4yKSB7CiAgICAgICAgICB2YXIgaTIsIHMyID0gZTIuc3RhdGU7CiAgICAgICAgICByZXR1cm4gbnVsbCA9PT0gczIud2luZG93ICYmIChzMi53c2l6ZSA9IDEgPDwgczIud2JpdHMsIHMyLnduZXh0ID0gMCwgczIud2hhdmUgPSAwLCBzMi53aW5kb3cgPSBuZXcgSS5CdWY4KHMyLndzaXplKSksIG4yID49IHMyLndzaXplID8gKEkuYXJyYXlTZXQoczIud2luZG93LCB0MiwgcjIgLSBzMi53c2l6ZSwgczIud3NpemUsIDApLCBzMi53bmV4dCA9IDAsIHMyLndoYXZlID0gczIud3NpemUpIDogKG4yIDwgKGkyID0gczIud3NpemUgLSBzMi53bmV4dCkgJiYgKGkyID0gbjIpLCBJLmFycmF5U2V0KHMyLndpbmRvdywgdDIsIHIyIC0gbjIsIGkyLCBzMi53bmV4dCksIChuMiAtPSBpMikgPyAoSS5hcnJheVNldChzMi53aW5kb3csIHQyLCByMiAtIG4yLCBuMiwgMCksIHMyLnduZXh0ID0gbjIsIHMyLndoYXZlID0gczIud3NpemUpIDogKHMyLnduZXh0ICs9IGkyLCBzMi53bmV4dCA9PT0gczIud3NpemUgJiYgKHMyLnduZXh0ID0gMCksIHMyLndoYXZlIDwgczIud3NpemUgJiYgKHMyLndoYXZlICs9IGkyKSkpLCAwOwogICAgICAgIH0KICAgICAgICByLmluZmxhdGVSZXNldCA9IG8sIHIuaW5mbGF0ZVJlc2V0MiA9IGgsIHIuaW5mbGF0ZVJlc2V0S2VlcCA9IGEsIHIuaW5mbGF0ZUluaXQgPSBmdW5jdGlvbihlMikgewogICAgICAgICAgcmV0dXJuIHUoZTIsIDE1KTsKICAgICAgICB9LCByLmluZmxhdGVJbml0MiA9IHUsIHIuaW5mbGF0ZSA9IGZ1bmN0aW9uKGUyLCB0MikgewogICAgICAgICAgdmFyIHIyLCBuMiwgaTIsIHMyLCBhMiwgbzIsIGgyLCB1MiwgbDIsIGYyLCBjMiwgZCwgcCwgbSwgXywgZywgYiwgdiwgeSwgdywgaywgeCwgUywgeiwgQyA9IDAsIEUgPSBuZXcgSS5CdWY4KDQpLCBBID0gWzE2LCAxNywgMTgsIDAsIDgsIDcsIDksIDYsIDEwLCA1LCAxMSwgNCwgMTIsIDMsIDEzLCAyLCAxNCwgMSwgMTVdOwogICAgICAgICAgaWYgKCFlMiB8fCAhZTIuc3RhdGUgfHwgIWUyLm91dHB1dCB8fCAhZTIuaW5wdXQgJiYgMCAhPT0gZTIuYXZhaWxfaW4pCiAgICAgICAgICAgIHJldHVybiBVOwogICAgICAgICAgMTIgPT09IChyMiA9IGUyLnN0YXRlKS5tb2RlICYmIChyMi5tb2RlID0gMTMpLCBhMiA9IGUyLm5leHRfb3V0LCBpMiA9IGUyLm91dHB1dCwgaDIgPSBlMi5hdmFpbF9vdXQsIHMyID0gZTIubmV4dF9pbiwgbjIgPSBlMi5pbnB1dCwgbzIgPSBlMi5hdmFpbF9pbiwgdTIgPSByMi5ob2xkLCBsMiA9IHIyLmJpdHMsIGYyID0gbzIsIGMyID0gaDIsIHggPSBOOwogICAgICAgICAgZToKICAgICAgICAgICAgZm9yICg7IDsgKQogICAgICAgICAgICAgIHN3aXRjaCAocjIubW9kZSkgewogICAgICAgICAgICAgICAgY2FzZSBQOgogICAgICAgICAgICAgICAgICBpZiAoMCA9PT0gcjIud3JhcCkgewogICAgICAgICAgICAgICAgICAgIHIyLm1vZGUgPSAxMzsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBmb3IgKDsgbDIgPCAxNjsgKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKDAgPT09IG8yKQogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICBvMi0tLCB1MiArPSBuMltzMisrXSA8PCBsMiwgbDIgKz0gODsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAoMiAmIHIyLndyYXAgJiYgMzU2MTUgPT09IHUyKSB7CiAgICAgICAgICAgICAgICAgICAgRVtyMi5jaGVjayA9IDBdID0gMjU1ICYgdTIsIEVbMV0gPSB1MiA+Pj4gOCAmIDI1NSwgcjIuY2hlY2sgPSBCKHIyLmNoZWNrLCBFLCAyLCAwKSwgbDIgPSB1MiA9IDAsIHIyLm1vZGUgPSAyOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChyMi5mbGFncyA9IDAsIHIyLmhlYWQgJiYgKHIyLmhlYWQuZG9uZSA9IGZhbHNlKSwgISgxICYgcjIud3JhcCkgfHwgKCgoMjU1ICYgdTIpIDw8IDgpICsgKHUyID4+IDgpKSAlIDMxKSB7CiAgICAgICAgICAgICAgICAgICAgZTIubXNnID0gImluY29ycmVjdCBoZWFkZXIgY2hlY2siLCByMi5tb2RlID0gMzA7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKDggIT0gKDE1ICYgdTIpKSB7CiAgICAgICAgICAgICAgICAgICAgZTIubXNnID0gInVua25vd24gY29tcHJlc3Npb24gbWV0aG9kIiwgcjIubW9kZSA9IDMwOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChsMiAtPSA0LCBrID0gOCArICgxNSAmICh1MiA+Pj49IDQpKSwgMCA9PT0gcjIud2JpdHMpCiAgICAgICAgICAgICAgICAgICAgcjIud2JpdHMgPSBrOwogICAgICAgICAgICAgICAgICBlbHNlIGlmIChrID4gcjIud2JpdHMpIHsKICAgICAgICAgICAgICAgICAgICBlMi5tc2cgPSAiaW52YWxpZCB3aW5kb3cgc2l6ZSIsIHIyLm1vZGUgPSAzMDsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICByMi5kbWF4ID0gMSA8PCBrLCBlMi5hZGxlciA9IHIyLmNoZWNrID0gMSwgcjIubW9kZSA9IDUxMiAmIHUyID8gMTAgOiAxMiwgbDIgPSB1MiA9IDA7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgICBmb3IgKDsgbDIgPCAxNjsgKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKDAgPT09IG8yKQogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICBvMi0tLCB1MiArPSBuMltzMisrXSA8PCBsMiwgbDIgKz0gODsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAocjIuZmxhZ3MgPSB1MiwgOCAhPSAoMjU1ICYgcjIuZmxhZ3MpKSB7CiAgICAgICAgICAgICAgICAgICAgZTIubXNnID0gInVua25vd24gY29tcHJlc3Npb24gbWV0aG9kIiwgcjIubW9kZSA9IDMwOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmICg1NzM0NCAmIHIyLmZsYWdzKSB7CiAgICAgICAgICAgICAgICAgICAgZTIubXNnID0gInVua25vd24gaGVhZGVyIGZsYWdzIHNldCIsIHIyLm1vZGUgPSAzMDsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICByMi5oZWFkICYmIChyMi5oZWFkLnRleHQgPSB1MiA+PiA4ICYgMSksIDUxMiAmIHIyLmZsYWdzICYmIChFWzBdID0gMjU1ICYgdTIsIEVbMV0gPSB1MiA+Pj4gOCAmIDI1NSwgcjIuY2hlY2sgPSBCKHIyLmNoZWNrLCBFLCAyLCAwKSksIGwyID0gdTIgPSAwLCByMi5tb2RlID0gMzsKICAgICAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICAgICAgZm9yICg7IGwyIDwgMzI7ICkgewogICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgICAgbzItLSwgdTIgKz0gbjJbczIrK10gPDwgbDIsIGwyICs9IDg7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgcjIuaGVhZCAmJiAocjIuaGVhZC50aW1lID0gdTIpLCA1MTIgJiByMi5mbGFncyAmJiAoRVswXSA9IDI1NSAmIHUyLCBFWzFdID0gdTIgPj4+IDggJiAyNTUsIEVbMl0gPSB1MiA+Pj4gMTYgJiAyNTUsIEVbM10gPSB1MiA+Pj4gMjQgJiAyNTUsIHIyLmNoZWNrID0gQihyMi5jaGVjaywgRSwgNCwgMCkpLCBsMiA9IHUyID0gMCwgcjIubW9kZSA9IDQ7CiAgICAgICAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgICAgICAgIGZvciAoOyBsMiA8IDE2OyApIHsKICAgICAgICAgICAgICAgICAgICBpZiAoMCA9PT0gbzIpCiAgICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHIyLmhlYWQgJiYgKHIyLmhlYWQueGZsYWdzID0gMjU1ICYgdTIsIHIyLmhlYWQub3MgPSB1MiA+PiA4KSwgNTEyICYgcjIuZmxhZ3MgJiYgKEVbMF0gPSAyNTUgJiB1MiwgRVsxXSA9IHUyID4+PiA4ICYgMjU1LCByMi5jaGVjayA9IEIocjIuY2hlY2ssIEUsIDIsIDApKSwgbDIgPSB1MiA9IDAsIHIyLm1vZGUgPSA1OwogICAgICAgICAgICAgICAgY2FzZSA1OgogICAgICAgICAgICAgICAgICBpZiAoMTAyNCAmIHIyLmZsYWdzKSB7CiAgICAgICAgICAgICAgICAgICAgZm9yICg7IGwyIDwgMTY7ICkgewogICAgICAgICAgICAgICAgICAgICAgaWYgKDAgPT09IG8yKQogICAgICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICAgICAgbzItLSwgdTIgKz0gbjJbczIrK10gPDwgbDIsIGwyICs9IDg7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHIyLmxlbmd0aCA9IHUyLCByMi5oZWFkICYmIChyMi5oZWFkLmV4dHJhX2xlbiA9IHUyKSwgNTEyICYgcjIuZmxhZ3MgJiYgKEVbMF0gPSAyNTUgJiB1MiwgRVsxXSA9IHUyID4+PiA4ICYgMjU1LCByMi5jaGVjayA9IEIocjIuY2hlY2ssIEUsIDIsIDApKSwgbDIgPSB1MiA9IDA7CiAgICAgICAgICAgICAgICAgIH0gZWxzZQogICAgICAgICAgICAgICAgICAgIHIyLmhlYWQgJiYgKHIyLmhlYWQuZXh0cmEgPSBudWxsKTsKICAgICAgICAgICAgICAgICAgcjIubW9kZSA9IDY7CiAgICAgICAgICAgICAgICBjYXNlIDY6CiAgICAgICAgICAgICAgICAgIGlmICgxMDI0ICYgcjIuZmxhZ3MgJiYgKG8yIDwgKGQgPSByMi5sZW5ndGgpICYmIChkID0gbzIpLCBkICYmIChyMi5oZWFkICYmIChrID0gcjIuaGVhZC5leHRyYV9sZW4gLSByMi5sZW5ndGgsIHIyLmhlYWQuZXh0cmEgfHwgKHIyLmhlYWQuZXh0cmEgPSBuZXcgQXJyYXkocjIuaGVhZC5leHRyYV9sZW4pKSwgSS5hcnJheVNldChyMi5oZWFkLmV4dHJhLCBuMiwgczIsIGQsIGspKSwgNTEyICYgcjIuZmxhZ3MgJiYgKHIyLmNoZWNrID0gQihyMi5jaGVjaywgbjIsIGQsIHMyKSksIG8yIC09IGQsIHMyICs9IGQsIHIyLmxlbmd0aCAtPSBkKSwgcjIubGVuZ3RoKSkKICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICByMi5sZW5ndGggPSAwLCByMi5tb2RlID0gNzsKICAgICAgICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgICAgICAgaWYgKDIwNDggJiByMi5mbGFncykgewogICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgICAgZm9yIChkID0gMDsgayA9IG4yW3MyICsgZCsrXSwgcjIuaGVhZCAmJiBrICYmIHIyLmxlbmd0aCA8IDY1NTM2ICYmIChyMi5oZWFkLm5hbWUgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShrKSksIGsgJiYgZCA8IG8yOyApCiAgICAgICAgICAgICAgICAgICAgICA7CiAgICAgICAgICAgICAgICAgICAgaWYgKDUxMiAmIHIyLmZsYWdzICYmIChyMi5jaGVjayA9IEIocjIuY2hlY2ssIG4yLCBkLCBzMikpLCBvMiAtPSBkLCBzMiArPSBkLCBrKQogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgICAgICAgcjIuaGVhZCAmJiAocjIuaGVhZC5uYW1lID0gbnVsbCk7CiAgICAgICAgICAgICAgICAgIHIyLmxlbmd0aCA9IDAsIHIyLm1vZGUgPSA4OwogICAgICAgICAgICAgICAgY2FzZSA4OgogICAgICAgICAgICAgICAgICBpZiAoNDA5NiAmIHIyLmZsYWdzKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKDAgPT09IG8yKQogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGQgPSAwOyBrID0gbjJbczIgKyBkKytdLCByMi5oZWFkICYmIGsgJiYgcjIubGVuZ3RoIDwgNjU1MzYgJiYgKHIyLmhlYWQuY29tbWVudCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGspKSwgayAmJiBkIDwgbzI7ICkKICAgICAgICAgICAgICAgICAgICAgIDsKICAgICAgICAgICAgICAgICAgICBpZiAoNTEyICYgcjIuZmxhZ3MgJiYgKHIyLmNoZWNrID0gQihyMi5jaGVjaywgbjIsIGQsIHMyKSksIG8yIC09IGQsIHMyICs9IGQsIGspCiAgICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICB9IGVsc2UKICAgICAgICAgICAgICAgICAgICByMi5oZWFkICYmIChyMi5oZWFkLmNvbW1lbnQgPSBudWxsKTsKICAgICAgICAgICAgICAgICAgcjIubW9kZSA9IDk7CiAgICAgICAgICAgICAgICBjYXNlIDk6CiAgICAgICAgICAgICAgICAgIGlmICg1MTIgJiByMi5mbGFncykgewogICAgICAgICAgICAgICAgICAgIGZvciAoOyBsMiA8IDE2OyApIHsKICAgICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAodTIgIT09ICg2NTUzNSAmIHIyLmNoZWNrKSkgewogICAgICAgICAgICAgICAgICAgICAgZTIubXNnID0gImhlYWRlciBjcmMgbWlzbWF0Y2giLCByMi5tb2RlID0gMzA7CiAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgbDIgPSB1MiA9IDA7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgcjIuaGVhZCAmJiAocjIuaGVhZC5oY3JjID0gcjIuZmxhZ3MgPj4gOSAmIDEsIHIyLmhlYWQuZG9uZSA9IHRydWUpLCBlMi5hZGxlciA9IHIyLmNoZWNrID0gMCwgcjIubW9kZSA9IDEyOwogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIGNhc2UgMTA6CiAgICAgICAgICAgICAgICAgIGZvciAoOyBsMiA8IDMyOyApIHsKICAgICAgICAgICAgICAgICAgICBpZiAoMCA9PT0gbzIpCiAgICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGUyLmFkbGVyID0gcjIuY2hlY2sgPSBMKHUyKSwgbDIgPSB1MiA9IDAsIHIyLm1vZGUgPSAxMTsKICAgICAgICAgICAgICAgIGNhc2UgMTE6CiAgICAgICAgICAgICAgICAgIGlmICgwID09PSByMi5oYXZlZGljdCkKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZTIubmV4dF9vdXQgPSBhMiwgZTIuYXZhaWxfb3V0ID0gaDIsIGUyLm5leHRfaW4gPSBzMiwgZTIuYXZhaWxfaW4gPSBvMiwgcjIuaG9sZCA9IHUyLCByMi5iaXRzID0gbDIsIDI7CiAgICAgICAgICAgICAgICAgIGUyLmFkbGVyID0gcjIuY2hlY2sgPSAxLCByMi5tb2RlID0gMTI7CiAgICAgICAgICAgICAgICBjYXNlIDEyOgogICAgICAgICAgICAgICAgICBpZiAoNSA9PT0gdDIgfHwgNiA9PT0gdDIpCiAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgIGNhc2UgMTM6CiAgICAgICAgICAgICAgICAgIGlmIChyMi5sYXN0KSB7CiAgICAgICAgICAgICAgICAgICAgdTIgPj4+PSA3ICYgbDIsIGwyIC09IDcgJiBsMiwgcjIubW9kZSA9IDI3OwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGZvciAoOyBsMiA8IDM7ICkgewogICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgICAgbzItLSwgdTIgKz0gbjJbczIrK10gPDwgbDIsIGwyICs9IDg7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgc3dpdGNoIChyMi5sYXN0ID0gMSAmIHUyLCBsMiAtPSAxLCAzICYgKHUyID4+Pj0gMSkpIHsKICAgICAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgICAgICByMi5tb2RlID0gMTQ7CiAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICAgICAgICBpZiAoaihyMiksIHIyLm1vZGUgPSAyMCwgNiAhPT0gdDIpCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgdTIgPj4+PSAyLCBsMiAtPSAyOwogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgICAgICAgICByMi5tb2RlID0gMTc7CiAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgICAgICAgICAgICBlMi5tc2cgPSAiaW52YWxpZCBibG9jayB0eXBlIiwgcjIubW9kZSA9IDMwOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHUyID4+Pj0gMiwgbDIgLT0gMjsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDE0OgogICAgICAgICAgICAgICAgICBmb3IgKHUyID4+Pj0gNyAmIGwyLCBsMiAtPSA3ICYgbDI7IGwyIDwgMzI7ICkgewogICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgICAgbzItLSwgdTIgKz0gbjJbczIrK10gPDwgbDIsIGwyICs9IDg7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKCg2NTUzNSAmIHUyKSAhPSAodTIgPj4+IDE2IF4gNjU1MzUpKSB7CiAgICAgICAgICAgICAgICAgICAgZTIubXNnID0gImludmFsaWQgc3RvcmVkIGJsb2NrIGxlbmd0aHMiLCByMi5tb2RlID0gMzA7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKHIyLmxlbmd0aCA9IDY1NTM1ICYgdTIsIGwyID0gdTIgPSAwLCByMi5tb2RlID0gMTUsIDYgPT09IHQyKQogICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICBjYXNlIDE1OgogICAgICAgICAgICAgICAgICByMi5tb2RlID0gMTY7CiAgICAgICAgICAgICAgICBjYXNlIDE2OgogICAgICAgICAgICAgICAgICBpZiAoZCA9IHIyLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgIGlmIChvMiA8IGQgJiYgKGQgPSBvMiksIGgyIDwgZCAmJiAoZCA9IGgyKSwgMCA9PT0gZCkKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgICAgSS5hcnJheVNldChpMiwgbjIsIHMyLCBkLCBhMiksIG8yIC09IGQsIHMyICs9IGQsIGgyIC09IGQsIGEyICs9IGQsIHIyLmxlbmd0aCAtPSBkOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHIyLm1vZGUgPSAxMjsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBjYXNlIDE3OgogICAgICAgICAgICAgICAgICBmb3IgKDsgbDIgPCAxNDsgKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKDAgPT09IG8yKQogICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICBvMi0tLCB1MiArPSBuMltzMisrXSA8PCBsMiwgbDIgKz0gODsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAocjIubmxlbiA9IDI1NyArICgzMSAmIHUyKSwgdTIgPj4+PSA1LCBsMiAtPSA1LCByMi5uZGlzdCA9IDEgKyAoMzEgJiB1MiksIHUyID4+Pj0gNSwgbDIgLT0gNSwgcjIubmNvZGUgPSA0ICsgKDE1ICYgdTIpLCB1MiA+Pj49IDQsIGwyIC09IDQsIDI4NiA8IHIyLm5sZW4gfHwgMzAgPCByMi5uZGlzdCkgewogICAgICAgICAgICAgICAgICAgIGUyLm1zZyA9ICJ0b28gbWFueSBsZW5ndGggb3IgZGlzdGFuY2Ugc3ltYm9scyIsIHIyLm1vZGUgPSAzMDsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICByMi5oYXZlID0gMCwgcjIubW9kZSA9IDE4OwogICAgICAgICAgICAgICAgY2FzZSAxODoKICAgICAgICAgICAgICAgICAgZm9yICg7IHIyLmhhdmUgPCByMi5uY29kZTsgKSB7CiAgICAgICAgICAgICAgICAgICAgZm9yICg7IGwyIDwgMzsgKSB7CiAgICAgICAgICAgICAgICAgICAgICBpZiAoMCA9PT0gbzIpCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgICAgICBvMi0tLCB1MiArPSBuMltzMisrXSA8PCBsMiwgbDIgKz0gODsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcjIubGVuc1tBW3IyLmhhdmUrK11dID0gNyAmIHUyLCB1MiA+Pj49IDMsIGwyIC09IDM7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgZm9yICg7IHIyLmhhdmUgPCAxOTsgKQogICAgICAgICAgICAgICAgICAgIHIyLmxlbnNbQVtyMi5oYXZlKytdXSA9IDA7CiAgICAgICAgICAgICAgICAgIGlmIChyMi5sZW5jb2RlID0gcjIubGVuZHluLCByMi5sZW5iaXRzID0gNywgUyA9IHsgYml0czogcjIubGVuYml0cyB9LCB4ID0gVCgwLCByMi5sZW5zLCAwLCAxOSwgcjIubGVuY29kZSwgMCwgcjIud29yaywgUyksIHIyLmxlbmJpdHMgPSBTLmJpdHMsIHgpIHsKICAgICAgICAgICAgICAgICAgICBlMi5tc2cgPSAiaW52YWxpZCBjb2RlIGxlbmd0aHMgc2V0IiwgcjIubW9kZSA9IDMwOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHIyLmhhdmUgPSAwLCByMi5tb2RlID0gMTk7CiAgICAgICAgICAgICAgICBjYXNlIDE5OgogICAgICAgICAgICAgICAgICBmb3IgKDsgcjIuaGF2ZSA8IHIyLm5sZW4gKyByMi5uZGlzdDsgKSB7CiAgICAgICAgICAgICAgICAgICAgZm9yICg7IGcgPSAoQyA9IHIyLmxlbmNvZGVbdTIgJiAoMSA8PCByMi5sZW5iaXRzKSAtIDFdKSA+Pj4gMTYgJiAyNTUsIGIgPSA2NTUzNSAmIEMsICEoKF8gPSBDID4+PiAyNCkgPD0gbDIpOyApIHsKICAgICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoYiA8IDE2KQogICAgICAgICAgICAgICAgICAgICAgdTIgPj4+PSBfLCBsMiAtPSBfLCByMi5sZW5zW3IyLmhhdmUrK10gPSBiOwogICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgaWYgKDE2ID09PSBiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoeiA9IF8gKyAyOyBsMiA8IHo7ICkgewogICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgbzItLSwgdTIgKz0gbjJbczIrK10gPDwgbDIsIGwyICs9IDg7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHUyID4+Pj0gXywgbDIgLT0gXywgMCA9PT0gcjIuaGF2ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgIGUyLm1zZyA9ICJpbnZhbGlkIGJpdCBsZW5ndGggcmVwZWF0IiwgcjIubW9kZSA9IDMwOwogICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGsgPSByMi5sZW5zW3IyLmhhdmUgLSAxXSwgZCA9IDMgKyAoMyAmIHUyKSwgdTIgPj4+PSAyLCBsMiAtPSAyOwogICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgxNyA9PT0gYikgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHogPSBfICsgMzsgbDIgPCB6OyApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoMCA9PT0gbzIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGwyIC09IF8sIGsgPSAwLCBkID0gMyArICg3ICYgKHUyID4+Pj0gXykpLCB1MiA+Pj49IDMsIGwyIC09IDM7CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHogPSBfICsgNzsgbDIgPCB6OyApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoMCA9PT0gbzIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGwyIC09IF8sIGsgPSAwLCBkID0gMTEgKyAoMTI3ICYgKHUyID4+Pj0gXykpLCB1MiA+Pj49IDcsIGwyIC09IDc7CiAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICBpZiAocjIuaGF2ZSArIGQgPiByMi5ubGVuICsgcjIubmRpc3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZTIubXNnID0gImludmFsaWQgYml0IGxlbmd0aCByZXBlYXQiLCByMi5tb2RlID0gMzA7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgZm9yICg7IGQtLTsgKQogICAgICAgICAgICAgICAgICAgICAgICByMi5sZW5zW3IyLmhhdmUrK10gPSBrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAoMzAgPT09IHIyLm1vZGUpCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIGlmICgwID09PSByMi5sZW5zWzI1Nl0pIHsKICAgICAgICAgICAgICAgICAgICBlMi5tc2cgPSAiaW52YWxpZCBjb2RlIC0tIG1pc3NpbmcgZW5kLW9mLWJsb2NrIiwgcjIubW9kZSA9IDMwOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChyMi5sZW5iaXRzID0gOSwgUyA9IHsgYml0czogcjIubGVuYml0cyB9LCB4ID0gVChELCByMi5sZW5zLCAwLCByMi5ubGVuLCByMi5sZW5jb2RlLCAwLCByMi53b3JrLCBTKSwgcjIubGVuYml0cyA9IFMuYml0cywgeCkgewogICAgICAgICAgICAgICAgICAgIGUyLm1zZyA9ICJpbnZhbGlkIGxpdGVyYWwvbGVuZ3RocyBzZXQiLCByMi5tb2RlID0gMzA7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKHIyLmRpc3RiaXRzID0gNiwgcjIuZGlzdGNvZGUgPSByMi5kaXN0ZHluLCBTID0geyBiaXRzOiByMi5kaXN0Yml0cyB9LCB4ID0gVChGLCByMi5sZW5zLCByMi5ubGVuLCByMi5uZGlzdCwgcjIuZGlzdGNvZGUsIDAsIHIyLndvcmssIFMpLCByMi5kaXN0Yml0cyA9IFMuYml0cywgeCkgewogICAgICAgICAgICAgICAgICAgIGUyLm1zZyA9ICJpbnZhbGlkIGRpc3RhbmNlcyBzZXQiLCByMi5tb2RlID0gMzA7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKHIyLm1vZGUgPSAyMCwgNiA9PT0gdDIpCiAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgIGNhc2UgMjA6CiAgICAgICAgICAgICAgICAgIHIyLm1vZGUgPSAyMTsKICAgICAgICAgICAgICAgIGNhc2UgMjE6CiAgICAgICAgICAgICAgICAgIGlmICg2IDw9IG8yICYmIDI1OCA8PSBoMikgewogICAgICAgICAgICAgICAgICAgIGUyLm5leHRfb3V0ID0gYTIsIGUyLmF2YWlsX291dCA9IGgyLCBlMi5uZXh0X2luID0gczIsIGUyLmF2YWlsX2luID0gbzIsIHIyLmhvbGQgPSB1MiwgcjIuYml0cyA9IGwyLCBSKGUyLCBjMiksIGEyID0gZTIubmV4dF9vdXQsIGkyID0gZTIub3V0cHV0LCBoMiA9IGUyLmF2YWlsX291dCwgczIgPSBlMi5uZXh0X2luLCBuMiA9IGUyLmlucHV0LCBvMiA9IGUyLmF2YWlsX2luLCB1MiA9IHIyLmhvbGQsIGwyID0gcjIuYml0cywgMTIgPT09IHIyLm1vZGUgJiYgKHIyLmJhY2sgPSAtMSk7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgZm9yIChyMi5iYWNrID0gMDsgZyA9IChDID0gcjIubGVuY29kZVt1MiAmICgxIDw8IHIyLmxlbmJpdHMpIC0gMV0pID4+PiAxNiAmIDI1NSwgYiA9IDY1NTM1ICYgQywgISgoXyA9IEMgPj4+IDI0KSA8PSBsMik7ICkgewogICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgICAgbzItLSwgdTIgKz0gbjJbczIrK10gPDwgbDIsIGwyICs9IDg7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKGcgJiYgMCA9PSAoMjQwICYgZykpIHsKICAgICAgICAgICAgICAgICAgICBmb3IgKHYgPSBfLCB5ID0gZywgdyA9IGI7IGcgPSAoQyA9IHIyLmxlbmNvZGVbdyArICgodTIgJiAoMSA8PCB2ICsgeSkgLSAxKSA+PiB2KV0pID4+PiAxNiAmIDI1NSwgYiA9IDY1NTM1ICYgQywgISh2ICsgKF8gPSBDID4+PiAyNCkgPD0gbDIpOyApIHsKICAgICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB1MiA+Pj49IHYsIGwyIC09IHYsIHIyLmJhY2sgKz0gdjsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAodTIgPj4+PSBfLCBsMiAtPSBfLCByMi5iYWNrICs9IF8sIHIyLmxlbmd0aCA9IGIsIDAgPT09IGcpIHsKICAgICAgICAgICAgICAgICAgICByMi5tb2RlID0gMjY7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgaWYgKDMyICYgZykgewogICAgICAgICAgICAgICAgICAgIHIyLmJhY2sgPSAtMSwgcjIubW9kZSA9IDEyOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmICg2NCAmIGcpIHsKICAgICAgICAgICAgICAgICAgICBlMi5tc2cgPSAiaW52YWxpZCBsaXRlcmFsL2xlbmd0aCBjb2RlIiwgcjIubW9kZSA9IDMwOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHIyLmV4dHJhID0gMTUgJiBnLCByMi5tb2RlID0gMjI7CiAgICAgICAgICAgICAgICBjYXNlIDIyOgogICAgICAgICAgICAgICAgICBpZiAocjIuZXh0cmEpIHsKICAgICAgICAgICAgICAgICAgICBmb3IgKHogPSByMi5leHRyYTsgbDIgPCB6OyApIHsKICAgICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByMi5sZW5ndGggKz0gdTIgJiAoMSA8PCByMi5leHRyYSkgLSAxLCB1MiA+Pj49IHIyLmV4dHJhLCBsMiAtPSByMi5leHRyYSwgcjIuYmFjayArPSByMi5leHRyYTsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICByMi53YXMgPSByMi5sZW5ndGgsIHIyLm1vZGUgPSAyMzsKICAgICAgICAgICAgICAgIGNhc2UgMjM6CiAgICAgICAgICAgICAgICAgIGZvciAoOyBnID0gKEMgPSByMi5kaXN0Y29kZVt1MiAmICgxIDw8IHIyLmRpc3RiaXRzKSAtIDFdKSA+Pj4gMTYgJiAyNTUsIGIgPSA2NTUzNSAmIEMsICEoKF8gPSBDID4+PiAyNCkgPD0gbDIpOyApIHsKICAgICAgICAgICAgICAgICAgICBpZiAoMCA9PT0gbzIpCiAgICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmICgwID09ICgyNDAgJiBnKSkgewogICAgICAgICAgICAgICAgICAgIGZvciAodiA9IF8sIHkgPSBnLCB3ID0gYjsgZyA9IChDID0gcjIuZGlzdGNvZGVbdyArICgodTIgJiAoMSA8PCB2ICsgeSkgLSAxKSA+PiB2KV0pID4+PiAxNiAmIDI1NSwgYiA9IDY1NTM1ICYgQywgISh2ICsgKF8gPSBDID4+PiAyNCkgPD0gbDIpOyApIHsKICAgICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB1MiA+Pj49IHYsIGwyIC09IHYsIHIyLmJhY2sgKz0gdjsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICBpZiAodTIgPj4+PSBfLCBsMiAtPSBfLCByMi5iYWNrICs9IF8sIDY0ICYgZykgewogICAgICAgICAgICAgICAgICAgIGUyLm1zZyA9ICJpbnZhbGlkIGRpc3RhbmNlIGNvZGUiLCByMi5tb2RlID0gMzA7CiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgcjIub2Zmc2V0ID0gYiwgcjIuZXh0cmEgPSAxNSAmIGcsIHIyLm1vZGUgPSAyNDsKICAgICAgICAgICAgICAgIGNhc2UgMjQ6CiAgICAgICAgICAgICAgICAgIGlmIChyMi5leHRyYSkgewogICAgICAgICAgICAgICAgICAgIGZvciAoeiA9IHIyLmV4dHJhOyBsMiA8IHo7ICkgewogICAgICAgICAgICAgICAgICAgICAgaWYgKDAgPT09IG8yKQogICAgICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICAgICAgbzItLSwgdTIgKz0gbjJbczIrK10gPDwgbDIsIGwyICs9IDg7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHIyLm9mZnNldCArPSB1MiAmICgxIDw8IHIyLmV4dHJhKSAtIDEsIHUyID4+Pj0gcjIuZXh0cmEsIGwyIC09IHIyLmV4dHJhLCByMi5iYWNrICs9IHIyLmV4dHJhOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIGlmIChyMi5vZmZzZXQgPiByMi5kbWF4KSB7CiAgICAgICAgICAgICAgICAgICAgZTIubXNnID0gImludmFsaWQgZGlzdGFuY2UgdG9vIGZhciBiYWNrIiwgcjIubW9kZSA9IDMwOwogICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgIHIyLm1vZGUgPSAyNTsKICAgICAgICAgICAgICAgIGNhc2UgMjU6CiAgICAgICAgICAgICAgICAgIGlmICgwID09PSBoMikKICAgICAgICAgICAgICAgICAgICBicmVhayBlOwogICAgICAgICAgICAgICAgICBpZiAoZCA9IGMyIC0gaDIsIHIyLm9mZnNldCA+IGQpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoKGQgPSByMi5vZmZzZXQgLSBkKSA+IHIyLndoYXZlICYmIHIyLnNhbmUpIHsKICAgICAgICAgICAgICAgICAgICAgIGUyLm1zZyA9ICJpbnZhbGlkIGRpc3RhbmNlIHRvbyBmYXIgYmFjayIsIHIyLm1vZGUgPSAzMDsKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBwID0gZCA+IHIyLnduZXh0ID8gKGQgLT0gcjIud25leHQsIHIyLndzaXplIC0gZCkgOiByMi53bmV4dCAtIGQsIGQgPiByMi5sZW5ndGggJiYgKGQgPSByMi5sZW5ndGgpLCBtID0gcjIud2luZG93OwogICAgICAgICAgICAgICAgICB9IGVsc2UKICAgICAgICAgICAgICAgICAgICBtID0gaTIsIHAgPSBhMiAtIHIyLm9mZnNldCwgZCA9IHIyLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgZm9yIChoMiA8IGQgJiYgKGQgPSBoMiksIGgyIC09IGQsIHIyLmxlbmd0aCAtPSBkOyBpMlthMisrXSA9IG1bcCsrXSwgLS1kOyApCiAgICAgICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgICAgICAwID09PSByMi5sZW5ndGggJiYgKHIyLm1vZGUgPSAyMSk7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyNjoKICAgICAgICAgICAgICAgICAgaWYgKDAgPT09IGgyKQogICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgIGkyW2EyKytdID0gcjIubGVuZ3RoLCBoMi0tLCByMi5tb2RlID0gMjE7CiAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgY2FzZSAyNzoKICAgICAgICAgICAgICAgICAgaWYgKHIyLndyYXApIHsKICAgICAgICAgICAgICAgICAgICBmb3IgKDsgbDIgPCAzMjsgKSB7CiAgICAgICAgICAgICAgICAgICAgICBpZiAoMCA9PT0gbzIpCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIGU7CiAgICAgICAgICAgICAgICAgICAgICBvMi0tLCB1MiB8PSBuMltzMisrXSA8PCBsMiwgbDIgKz0gODsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGMyIC09IGgyLCBlMi50b3RhbF9vdXQgKz0gYzIsIHIyLnRvdGFsICs9IGMyLCBjMiAmJiAoZTIuYWRsZXIgPSByMi5jaGVjayA9IHIyLmZsYWdzID8gQihyMi5jaGVjaywgaTIsIGMyLCBhMiAtIGMyKSA6IE8ocjIuY2hlY2ssIGkyLCBjMiwgYTIgLSBjMikpLCBjMiA9IGgyLCAocjIuZmxhZ3MgPyB1MiA6IEwodTIpKSAhPT0gcjIuY2hlY2spIHsKICAgICAgICAgICAgICAgICAgICAgIGUyLm1zZyA9ICJpbmNvcnJlY3QgZGF0YSBjaGVjayIsIHIyLm1vZGUgPSAzMDsKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBsMiA9IHUyID0gMDsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICByMi5tb2RlID0gMjg7CiAgICAgICAgICAgICAgICBjYXNlIDI4OgogICAgICAgICAgICAgICAgICBpZiAocjIud3JhcCAmJiByMi5mbGFncykgewogICAgICAgICAgICAgICAgICAgIGZvciAoOyBsMiA8IDMyOyApIHsKICAgICAgICAgICAgICAgICAgICAgIGlmICgwID09PSBvMikKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgICAgICAgIG8yLS0sIHUyICs9IG4yW3MyKytdIDw8IGwyLCBsMiArPSA4OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAodTIgIT09ICg0Mjk0OTY3Mjk1ICYgcjIudG90YWwpKSB7CiAgICAgICAgICAgICAgICAgICAgICBlMi5tc2cgPSAiaW5jb3JyZWN0IGxlbmd0aCBjaGVjayIsIHIyLm1vZGUgPSAzMDsKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBsMiA9IHUyID0gMDsKICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICByMi5tb2RlID0gMjk7CiAgICAgICAgICAgICAgICBjYXNlIDI5OgogICAgICAgICAgICAgICAgICB4ID0gMTsKICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgIGNhc2UgMzA6CiAgICAgICAgICAgICAgICAgIHggPSAtMzsKICAgICAgICAgICAgICAgICAgYnJlYWsgZTsKICAgICAgICAgICAgICAgIGNhc2UgMzE6CiAgICAgICAgICAgICAgICAgIHJldHVybiAtNDsKICAgICAgICAgICAgICAgIGNhc2UgMzI6CiAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICByZXR1cm4gVTsKICAgICAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gZTIubmV4dF9vdXQgPSBhMiwgZTIuYXZhaWxfb3V0ID0gaDIsIGUyLm5leHRfaW4gPSBzMiwgZTIuYXZhaWxfaW4gPSBvMiwgcjIuaG9sZCA9IHUyLCByMi5iaXRzID0gbDIsIChyMi53c2l6ZSB8fCBjMiAhPT0gZTIuYXZhaWxfb3V0ICYmIHIyLm1vZGUgPCAzMCAmJiAocjIubW9kZSA8IDI3IHx8IDQgIT09IHQyKSkgJiYgWihlMiwgZTIub3V0cHV0LCBlMi5uZXh0X291dCwgYzIgLSBlMi5hdmFpbF9vdXQpID8gKHIyLm1vZGUgPSAzMSwgLTQpIDogKGYyIC09IGUyLmF2YWlsX2luLCBjMiAtPSBlMi5hdmFpbF9vdXQsIGUyLnRvdGFsX2luICs9IGYyLCBlMi50b3RhbF9vdXQgKz0gYzIsIHIyLnRvdGFsICs9IGMyLCByMi53cmFwICYmIGMyICYmIChlMi5hZGxlciA9IHIyLmNoZWNrID0gcjIuZmxhZ3MgPyBCKHIyLmNoZWNrLCBpMiwgYzIsIGUyLm5leHRfb3V0IC0gYzIpIDogTyhyMi5jaGVjaywgaTIsIGMyLCBlMi5uZXh0X291dCAtIGMyKSksIGUyLmRhdGFfdHlwZSA9IHIyLmJpdHMgKyAocjIubGFzdCA/IDY0IDogMCkgKyAoMTIgPT09IHIyLm1vZGUgPyAxMjggOiAwKSArICgyMCA9PT0gcjIubW9kZSB8fCAxNSA9PT0gcjIubW9kZSA/IDI1NiA6IDApLCAoMCA9PSBmMiAmJiAwID09PSBjMiB8fCA0ID09PSB0MikgJiYgeCA9PT0gTiAmJiAoeCA9IC01KSwgeCk7CiAgICAgICAgfSwgci5pbmZsYXRlRW5kID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIGlmICghZTIgfHwgIWUyLnN0YXRlKQogICAgICAgICAgICByZXR1cm4gVTsKICAgICAgICAgIHZhciB0MiA9IGUyLnN0YXRlOwogICAgICAgICAgcmV0dXJuIHQyLndpbmRvdyAmJiAodDIud2luZG93ID0gbnVsbCksIGUyLnN0YXRlID0gbnVsbCwgTjsKICAgICAgICB9LCByLmluZmxhdGVHZXRIZWFkZXIgPSBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHZhciByMjsKICAgICAgICAgIHJldHVybiBlMiAmJiBlMi5zdGF0ZSA/IDAgPT0gKDIgJiAocjIgPSBlMi5zdGF0ZSkud3JhcCkgPyBVIDogKChyMi5oZWFkID0gdDIpLmRvbmUgPSBmYWxzZSwgTikgOiBVOwogICAgICAgIH0sIHIuaW5mbGF0ZVNldERpY3Rpb25hcnkgPSBmdW5jdGlvbihlMiwgdDIpIHsKICAgICAgICAgIHZhciByMiwgbjIgPSB0Mi5sZW5ndGg7CiAgICAgICAgICByZXR1cm4gZTIgJiYgZTIuc3RhdGUgPyAwICE9PSAocjIgPSBlMi5zdGF0ZSkud3JhcCAmJiAxMSAhPT0gcjIubW9kZSA/IFUgOiAxMSA9PT0gcjIubW9kZSAmJiBPKDEsIHQyLCBuMiwgMCkgIT09IHIyLmNoZWNrID8gLTMgOiBaKGUyLCB0MiwgbjIsIG4yKSA/IChyMi5tb2RlID0gMzEsIC00KSA6IChyMi5oYXZlZGljdCA9IDEsIE4pIDogVTsKICAgICAgICB9LCByLmluZmxhdGVJbmZvID0gInBha28gaW5mbGF0ZSAoZnJvbSBOb2RlY2EgcHJvamVjdCkiOwogICAgICB9LCB7ICIuLi91dGlscy9jb21tb24iOiA0MSwgIi4vYWRsZXIzMiI6IDQzLCAiLi9jcmMzMiI6IDQ1LCAiLi9pbmZmYXN0IjogNDgsICIuL2luZnRyZWVzIjogNTAgfV0sIDUwOiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIHZhciBEID0gZSgiLi4vdXRpbHMvY29tbW9uIiksIEYgPSBbMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExLCAxMywgMTUsIDE3LCAxOSwgMjMsIDI3LCAzMSwgMzUsIDQzLCA1MSwgNTksIDY3LCA4MywgOTksIDExNSwgMTMxLCAxNjMsIDE5NSwgMjI3LCAyNTgsIDAsIDBdLCBOID0gWzE2LCAxNiwgMTYsIDE2LCAxNiwgMTYsIDE2LCAxNiwgMTcsIDE3LCAxNywgMTcsIDE4LCAxOCwgMTgsIDE4LCAxOSwgMTksIDE5LCAxOSwgMjAsIDIwLCAyMCwgMjAsIDIxLCAyMSwgMjEsIDIxLCAxNiwgNzIsIDc4XSwgVSA9IFsxLCAyLCAzLCA0LCA1LCA3LCA5LCAxMywgMTcsIDI1LCAzMywgNDksIDY1LCA5NywgMTI5LCAxOTMsIDI1NywgMzg1LCA1MTMsIDc2OSwgMTAyNSwgMTUzNywgMjA0OSwgMzA3MywgNDA5NywgNjE0NSwgODE5MywgMTIyODksIDE2Mzg1LCAyNDU3NywgMCwgMF0sIFAgPSBbMTYsIDE2LCAxNiwgMTYsIDE3LCAxNywgMTgsIDE4LCAxOSwgMTksIDIwLCAyMCwgMjEsIDIxLCAyMiwgMjIsIDIzLCAyMywgMjQsIDI0LCAyNSwgMjUsIDI2LCAyNiwgMjcsIDI3LCAyOCwgMjgsIDI5LCAyOSwgNjQsIDY0XTsKICAgICAgICB0LmV4cG9ydHMgPSBmdW5jdGlvbihlMiwgdDIsIHIyLCBuLCBpLCBzLCBhLCBvKSB7CiAgICAgICAgICB2YXIgaCwgdSwgbCwgZiwgYywgZCwgcCwgbSwgXywgZyA9IG8uYml0cywgYiA9IDAsIHYgPSAwLCB5ID0gMCwgdyA9IDAsIGsgPSAwLCB4ID0gMCwgUyA9IDAsIHogPSAwLCBDID0gMCwgRSA9IDAsIEEgPSBudWxsLCBJID0gMCwgTyA9IG5ldyBELkJ1ZjE2KDE2KSwgQiA9IG5ldyBELkJ1ZjE2KDE2KSwgUiA9IG51bGwsIFQgPSAwOwogICAgICAgICAgZm9yIChiID0gMDsgYiA8PSAxNTsgYisrKQogICAgICAgICAgICBPW2JdID0gMDsKICAgICAgICAgIGZvciAodiA9IDA7IHYgPCBuOyB2KyspCiAgICAgICAgICAgIE9bdDJbcjIgKyB2XV0rKzsKICAgICAgICAgIGZvciAoayA9IGcsIHcgPSAxNTsgMSA8PSB3ICYmIDAgPT09IE9bd107IHctLSkKICAgICAgICAgICAgOwogICAgICAgICAgaWYgKHcgPCBrICYmIChrID0gdyksIDAgPT09IHcpCiAgICAgICAgICAgIHJldHVybiBpW3MrK10gPSAyMDk3MTUyMCwgaVtzKytdID0gMjA5NzE1MjAsIG8uYml0cyA9IDEsIDA7CiAgICAgICAgICBmb3IgKHkgPSAxOyB5IDwgdyAmJiAwID09PSBPW3ldOyB5KyspCiAgICAgICAgICAgIDsKICAgICAgICAgIGZvciAoayA8IHkgJiYgKGsgPSB5KSwgYiA9IHogPSAxOyBiIDw9IDE1OyBiKyspCiAgICAgICAgICAgIGlmICh6IDw8PSAxLCAoeiAtPSBPW2JdKSA8IDApCiAgICAgICAgICAgICAgcmV0dXJuIC0xOwogICAgICAgICAgaWYgKDAgPCB6ICYmICgwID09PSBlMiB8fCAxICE9PSB3KSkKICAgICAgICAgICAgcmV0dXJuIC0xOwogICAgICAgICAgZm9yIChCWzFdID0gMCwgYiA9IDE7IGIgPCAxNTsgYisrKQogICAgICAgICAgICBCW2IgKyAxXSA9IEJbYl0gKyBPW2JdOwogICAgICAgICAgZm9yICh2ID0gMDsgdiA8IG47IHYrKykKICAgICAgICAgICAgMCAhPT0gdDJbcjIgKyB2XSAmJiAoYVtCW3QyW3IyICsgdl1dKytdID0gdik7CiAgICAgICAgICBpZiAoZCA9IDAgPT09IGUyID8gKEEgPSBSID0gYSwgMTkpIDogMSA9PT0gZTIgPyAoQSA9IEYsIEkgLT0gMjU3LCBSID0gTiwgVCAtPSAyNTcsIDI1NikgOiAoQSA9IFUsIFIgPSBQLCAtMSksIGIgPSB5LCBjID0gcywgUyA9IHYgPSBFID0gMCwgbCA9IC0xLCBmID0gKEMgPSAxIDw8ICh4ID0gaykpIC0gMSwgMSA9PT0gZTIgJiYgODUyIDwgQyB8fCAyID09PSBlMiAmJiA1OTIgPCBDKQogICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICAgIGZvciAoOyA7ICkgewogICAgICAgICAgICBmb3IgKHAgPSBiIC0gUywgXyA9IGFbdl0gPCBkID8gKG0gPSAwLCBhW3ZdKSA6IGFbdl0gPiBkID8gKG0gPSBSW1QgKyBhW3ZdXSwgQVtJICsgYVt2XV0pIDogKG0gPSA5NiwgMCksIGggPSAxIDw8IGIgLSBTLCB5ID0gdSA9IDEgPDwgeDsgaVtjICsgKEUgPj4gUykgKyAodSAtPSBoKV0gPSBwIDw8IDI0IHwgbSA8PCAxNiB8IF8gfCAwLCAwICE9PSB1OyApCiAgICAgICAgICAgICAgOwogICAgICAgICAgICBmb3IgKGggPSAxIDw8IGIgLSAxOyBFICYgaDsgKQogICAgICAgICAgICAgIGggPj49IDE7CiAgICAgICAgICAgIGlmICgwICE9PSBoID8gKEUgJj0gaCAtIDEsIEUgKz0gaCkgOiBFID0gMCwgdisrLCAwID09IC0tT1tiXSkgewogICAgICAgICAgICAgIGlmIChiID09PSB3KQogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgYiA9IHQyW3IyICsgYVt2XV07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGsgPCBiICYmIChFICYgZikgIT09IGwpIHsKICAgICAgICAgICAgICBmb3IgKDAgPT09IFMgJiYgKFMgPSBrKSwgYyArPSB5LCB6ID0gMSA8PCAoeCA9IGIgLSBTKTsgeCArIFMgPCB3ICYmICEoKHogLT0gT1t4ICsgU10pIDw9IDApOyApCiAgICAgICAgICAgICAgICB4KyssIHogPDw9IDE7CiAgICAgICAgICAgICAgaWYgKEMgKz0gMSA8PCB4LCAxID09PSBlMiAmJiA4NTIgPCBDIHx8IDIgPT09IGUyICYmIDU5MiA8IEMpCiAgICAgICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICAgICAgICBpW2wgPSBFICYgZl0gPSBrIDw8IDI0IHwgeCA8PCAxNiB8IGMgLSBzIHwgMDsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIDAgIT09IEUgJiYgKGlbYyArIEVdID0gYiAtIFMgPDwgMjQgfCA2NCA8PCAxNiB8IDApLCBvLmJpdHMgPSBrLCAwOwogICAgICAgIH07CiAgICAgIH0sIHsgIi4uL3V0aWxzL2NvbW1vbiI6IDQxIH1dLCA1MTogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB0LmV4cG9ydHMgPSB7IDI6ICJuZWVkIGRpY3Rpb25hcnkiLCAxOiAic3RyZWFtIGVuZCIsIDA6ICIiLCAiLTEiOiAiZmlsZSBlcnJvciIsICItMiI6ICJzdHJlYW0gZXJyb3IiLCAiLTMiOiAiZGF0YSBlcnJvciIsICItNCI6ICJpbnN1ZmZpY2llbnQgbWVtb3J5IiwgIi01IjogImJ1ZmZlciBlcnJvciIsICItNiI6ICJpbmNvbXBhdGlibGUgdmVyc2lvbiIgfTsKICAgICAgfSwge31dLCA1MjogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB2YXIgaSA9IGUoIi4uL3V0aWxzL2NvbW1vbiIpLCBvID0gMCwgaCA9IDE7CiAgICAgICAgZnVuY3Rpb24gbihlMikgewogICAgICAgICAgZm9yICh2YXIgdDIgPSBlMi5sZW5ndGg7IDAgPD0gLS10MjsgKQogICAgICAgICAgICBlMlt0Ml0gPSAwOwogICAgICAgIH0KICAgICAgICB2YXIgcyA9IDAsIGEgPSAyOSwgdSA9IDI1NiwgbCA9IHUgKyAxICsgYSwgZiA9IDMwLCBjID0gMTksIF8gPSAyICogbCArIDEsIGcgPSAxNSwgZCA9IDE2LCBwID0gNywgbSA9IDI1NiwgYiA9IDE2LCB2ID0gMTcsIHkgPSAxOCwgdyA9IFswLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAxLCAxLCAxLCAxLCAyLCAyLCAyLCAyLCAzLCAzLCAzLCAzLCA0LCA0LCA0LCA0LCA1LCA1LCA1LCA1LCAwXSwgayA9IFswLCAwLCAwLCAwLCAxLCAxLCAyLCAyLCAzLCAzLCA0LCA0LCA1LCA1LCA2LCA2LCA3LCA3LCA4LCA4LCA5LCA5LCAxMCwgMTAsIDExLCAxMSwgMTIsIDEyLCAxMywgMTNdLCB4ID0gWzAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDIsIDMsIDddLCBTID0gWzE2LCAxNywgMTgsIDAsIDgsIDcsIDksIDYsIDEwLCA1LCAxMSwgNCwgMTIsIDMsIDEzLCAyLCAxNCwgMSwgMTVdLCB6ID0gbmV3IEFycmF5KDIgKiAobCArIDIpKTsKICAgICAgICBuKHopOwogICAgICAgIHZhciBDID0gbmV3IEFycmF5KDIgKiBmKTsKICAgICAgICBuKEMpOwogICAgICAgIHZhciBFID0gbmV3IEFycmF5KDUxMik7CiAgICAgICAgbihFKTsKICAgICAgICB2YXIgQSA9IG5ldyBBcnJheSgyNTYpOwogICAgICAgIG4oQSk7CiAgICAgICAgdmFyIEkgPSBuZXcgQXJyYXkoYSk7CiAgICAgICAgbihJKTsKICAgICAgICB2YXIgTywgQiwgUiwgVCA9IG5ldyBBcnJheShmKTsKICAgICAgICBmdW5jdGlvbiBEKGUyLCB0MiwgcjIsIG4yLCBpMikgewogICAgICAgICAgdGhpcy5zdGF0aWNfdHJlZSA9IGUyLCB0aGlzLmV4dHJhX2JpdHMgPSB0MiwgdGhpcy5leHRyYV9iYXNlID0gcjIsIHRoaXMuZWxlbXMgPSBuMiwgdGhpcy5tYXhfbGVuZ3RoID0gaTIsIHRoaXMuaGFzX3N0cmVlID0gZTIgJiYgZTIubGVuZ3RoOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBGKGUyLCB0MikgewogICAgICAgICAgdGhpcy5keW5fdHJlZSA9IGUyLCB0aGlzLm1heF9jb2RlID0gMCwgdGhpcy5zdGF0X2Rlc2MgPSB0MjsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gTihlMikgewogICAgICAgICAgcmV0dXJuIGUyIDwgMjU2ID8gRVtlMl0gOiBFWzI1NiArIChlMiA+Pj4gNyldOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBVKGUyLCB0MikgewogICAgICAgICAgZTIucGVuZGluZ19idWZbZTIucGVuZGluZysrXSA9IDI1NSAmIHQyLCBlMi5wZW5kaW5nX2J1ZltlMi5wZW5kaW5nKytdID0gdDIgPj4+IDggJiAyNTU7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIFAoZTIsIHQyLCByMikgewogICAgICAgICAgZTIuYmlfdmFsaWQgPiBkIC0gcjIgPyAoZTIuYmlfYnVmIHw9IHQyIDw8IGUyLmJpX3ZhbGlkICYgNjU1MzUsIFUoZTIsIGUyLmJpX2J1ZiksIGUyLmJpX2J1ZiA9IHQyID4+IGQgLSBlMi5iaV92YWxpZCwgZTIuYmlfdmFsaWQgKz0gcjIgLSBkKSA6IChlMi5iaV9idWYgfD0gdDIgPDwgZTIuYmlfdmFsaWQgJiA2NTUzNSwgZTIuYmlfdmFsaWQgKz0gcjIpOwogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBMKGUyLCB0MiwgcjIpIHsKICAgICAgICAgIFAoZTIsIHIyWzIgKiB0Ml0sIHIyWzIgKiB0MiArIDFdKTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gaihlMiwgdDIpIHsKICAgICAgICAgIGZvciAodmFyIHIyID0gMDsgcjIgfD0gMSAmIGUyLCBlMiA+Pj49IDEsIHIyIDw8PSAxLCAwIDwgLS10MjsgKQogICAgICAgICAgICA7CiAgICAgICAgICByZXR1cm4gcjIgPj4+IDE7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIFooZTIsIHQyLCByMikgewogICAgICAgICAgdmFyIG4yLCBpMiwgczIgPSBuZXcgQXJyYXkoZyArIDEpLCBhMiA9IDA7CiAgICAgICAgICBmb3IgKG4yID0gMTsgbjIgPD0gZzsgbjIrKykKICAgICAgICAgICAgczJbbjJdID0gYTIgPSBhMiArIHIyW24yIC0gMV0gPDwgMTsKICAgICAgICAgIGZvciAoaTIgPSAwOyBpMiA8PSB0MjsgaTIrKykgewogICAgICAgICAgICB2YXIgbzIgPSBlMlsyICogaTIgKyAxXTsKICAgICAgICAgICAgMCAhPT0gbzIgJiYgKGUyWzIgKiBpMl0gPSBqKHMyW28yXSsrLCBvMikpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBmdW5jdGlvbiBXKGUyKSB7CiAgICAgICAgICB2YXIgdDI7CiAgICAgICAgICBmb3IgKHQyID0gMDsgdDIgPCBsOyB0MisrKQogICAgICAgICAgICBlMi5keW5fbHRyZWVbMiAqIHQyXSA9IDA7CiAgICAgICAgICBmb3IgKHQyID0gMDsgdDIgPCBmOyB0MisrKQogICAgICAgICAgICBlMi5keW5fZHRyZWVbMiAqIHQyXSA9IDA7CiAgICAgICAgICBmb3IgKHQyID0gMDsgdDIgPCBjOyB0MisrKQogICAgICAgICAgICBlMi5ibF90cmVlWzIgKiB0Ml0gPSAwOwogICAgICAgICAgZTIuZHluX2x0cmVlWzIgKiBtXSA9IDEsIGUyLm9wdF9sZW4gPSBlMi5zdGF0aWNfbGVuID0gMCwgZTIubGFzdF9saXQgPSBlMi5tYXRjaGVzID0gMDsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gTShlMikgewogICAgICAgICAgOCA8IGUyLmJpX3ZhbGlkID8gVShlMiwgZTIuYmlfYnVmKSA6IDAgPCBlMi5iaV92YWxpZCAmJiAoZTIucGVuZGluZ19idWZbZTIucGVuZGluZysrXSA9IGUyLmJpX2J1ZiksIGUyLmJpX2J1ZiA9IDAsIGUyLmJpX3ZhbGlkID0gMDsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gSChlMiwgdDIsIHIyLCBuMikgewogICAgICAgICAgdmFyIGkyID0gMiAqIHQyLCBzMiA9IDIgKiByMjsKICAgICAgICAgIHJldHVybiBlMltpMl0gPCBlMltzMl0gfHwgZTJbaTJdID09PSBlMltzMl0gJiYgbjJbdDJdIDw9IG4yW3IyXTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gRyhlMiwgdDIsIHIyKSB7CiAgICAgICAgICBmb3IgKHZhciBuMiA9IGUyLmhlYXBbcjJdLCBpMiA9IHIyIDw8IDE7IGkyIDw9IGUyLmhlYXBfbGVuICYmIChpMiA8IGUyLmhlYXBfbGVuICYmIEgodDIsIGUyLmhlYXBbaTIgKyAxXSwgZTIuaGVhcFtpMl0sIGUyLmRlcHRoKSAmJiBpMisrLCAhSCh0MiwgbjIsIGUyLmhlYXBbaTJdLCBlMi5kZXB0aCkpOyApCiAgICAgICAgICAgIGUyLmhlYXBbcjJdID0gZTIuaGVhcFtpMl0sIHIyID0gaTIsIGkyIDw8PSAxOwogICAgICAgICAgZTIuaGVhcFtyMl0gPSBuMjsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gSyhlMiwgdDIsIHIyKSB7CiAgICAgICAgICB2YXIgbjIsIGkyLCBzMiwgYTIsIG8yID0gMDsKICAgICAgICAgIGlmICgwICE9PSBlMi5sYXN0X2xpdCkKICAgICAgICAgICAgZm9yICg7IG4yID0gZTIucGVuZGluZ19idWZbZTIuZF9idWYgKyAyICogbzJdIDw8IDggfCBlMi5wZW5kaW5nX2J1ZltlMi5kX2J1ZiArIDIgKiBvMiArIDFdLCBpMiA9IGUyLnBlbmRpbmdfYnVmW2UyLmxfYnVmICsgbzJdLCBvMisrLCAwID09PSBuMiA/IEwoZTIsIGkyLCB0MikgOiAoTChlMiwgKHMyID0gQVtpMl0pICsgdSArIDEsIHQyKSwgMCAhPT0gKGEyID0gd1tzMl0pICYmIFAoZTIsIGkyIC09IElbczJdLCBhMiksIEwoZTIsIHMyID0gTigtLW4yKSwgcjIpLCAwICE9PSAoYTIgPSBrW3MyXSkgJiYgUChlMiwgbjIgLT0gVFtzMl0sIGEyKSksIG8yIDwgZTIubGFzdF9saXQ7ICkKICAgICAgICAgICAgICA7CiAgICAgICAgICBMKGUyLCBtLCB0Mik7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIFkoZTIsIHQyKSB7CiAgICAgICAgICB2YXIgcjIsIG4yLCBpMiwgczIgPSB0Mi5keW5fdHJlZSwgYTIgPSB0Mi5zdGF0X2Rlc2Muc3RhdGljX3RyZWUsIG8yID0gdDIuc3RhdF9kZXNjLmhhc19zdHJlZSwgaDIgPSB0Mi5zdGF0X2Rlc2MuZWxlbXMsIHUyID0gLTE7CiAgICAgICAgICBmb3IgKGUyLmhlYXBfbGVuID0gMCwgZTIuaGVhcF9tYXggPSBfLCByMiA9IDA7IHIyIDwgaDI7IHIyKyspCiAgICAgICAgICAgIDAgIT09IHMyWzIgKiByMl0gPyAoZTIuaGVhcFsrK2UyLmhlYXBfbGVuXSA9IHUyID0gcjIsIGUyLmRlcHRoW3IyXSA9IDApIDogczJbMiAqIHIyICsgMV0gPSAwOwogICAgICAgICAgZm9yICg7IGUyLmhlYXBfbGVuIDwgMjsgKQogICAgICAgICAgICBzMlsyICogKGkyID0gZTIuaGVhcFsrK2UyLmhlYXBfbGVuXSA9IHUyIDwgMiA/ICsrdTIgOiAwKV0gPSAxLCBlMi5kZXB0aFtpMl0gPSAwLCBlMi5vcHRfbGVuLS0sIG8yICYmIChlMi5zdGF0aWNfbGVuIC09IGEyWzIgKiBpMiArIDFdKTsKICAgICAgICAgIGZvciAodDIubWF4X2NvZGUgPSB1MiwgcjIgPSBlMi5oZWFwX2xlbiA+PiAxOyAxIDw9IHIyOyByMi0tKQogICAgICAgICAgICBHKGUyLCBzMiwgcjIpOwogICAgICAgICAgZm9yIChpMiA9IGgyOyByMiA9IGUyLmhlYXBbMV0sIGUyLmhlYXBbMV0gPSBlMi5oZWFwW2UyLmhlYXBfbGVuLS1dLCBHKGUyLCBzMiwgMSksIG4yID0gZTIuaGVhcFsxXSwgZTIuaGVhcFstLWUyLmhlYXBfbWF4XSA9IHIyLCBlMi5oZWFwWy0tZTIuaGVhcF9tYXhdID0gbjIsIHMyWzIgKiBpMl0gPSBzMlsyICogcjJdICsgczJbMiAqIG4yXSwgZTIuZGVwdGhbaTJdID0gKGUyLmRlcHRoW3IyXSA+PSBlMi5kZXB0aFtuMl0gPyBlMi5kZXB0aFtyMl0gOiBlMi5kZXB0aFtuMl0pICsgMSwgczJbMiAqIHIyICsgMV0gPSBzMlsyICogbjIgKyAxXSA9IGkyLCBlMi5oZWFwWzFdID0gaTIrKywgRyhlMiwgczIsIDEpLCAyIDw9IGUyLmhlYXBfbGVuOyApCiAgICAgICAgICAgIDsKICAgICAgICAgIGUyLmhlYXBbLS1lMi5oZWFwX21heF0gPSBlMi5oZWFwWzFdLCBmdW5jdGlvbihlMywgdDMpIHsKICAgICAgICAgICAgdmFyIHIzLCBuMywgaTMsIHMzLCBhMywgbzMsIGgzID0gdDMuZHluX3RyZWUsIHUzID0gdDMubWF4X2NvZGUsIGwyID0gdDMuc3RhdF9kZXNjLnN0YXRpY190cmVlLCBmMiA9IHQzLnN0YXRfZGVzYy5oYXNfc3RyZWUsIGMyID0gdDMuc3RhdF9kZXNjLmV4dHJhX2JpdHMsIGQyID0gdDMuc3RhdF9kZXNjLmV4dHJhX2Jhc2UsIHAyID0gdDMuc3RhdF9kZXNjLm1heF9sZW5ndGgsIG0yID0gMDsKICAgICAgICAgICAgZm9yIChzMyA9IDA7IHMzIDw9IGc7IHMzKyspCiAgICAgICAgICAgICAgZTMuYmxfY291bnRbczNdID0gMDsKICAgICAgICAgICAgZm9yIChoM1syICogZTMuaGVhcFtlMy5oZWFwX21heF0gKyAxXSA9IDAsIHIzID0gZTMuaGVhcF9tYXggKyAxOyByMyA8IF87IHIzKyspCiAgICAgICAgICAgICAgcDIgPCAoczMgPSBoM1syICogaDNbMiAqIChuMyA9IGUzLmhlYXBbcjNdKSArIDFdICsgMV0gKyAxKSAmJiAoczMgPSBwMiwgbTIrKyksIGgzWzIgKiBuMyArIDFdID0gczMsIHUzIDwgbjMgfHwgKGUzLmJsX2NvdW50W3MzXSsrLCBhMyA9IDAsIGQyIDw9IG4zICYmIChhMyA9IGMyW24zIC0gZDJdKSwgbzMgPSBoM1syICogbjNdLCBlMy5vcHRfbGVuICs9IG8zICogKHMzICsgYTMpLCBmMiAmJiAoZTMuc3RhdGljX2xlbiArPSBvMyAqIChsMlsyICogbjMgKyAxXSArIGEzKSkpOwogICAgICAgICAgICBpZiAoMCAhPT0gbTIpIHsKICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICBmb3IgKHMzID0gcDIgLSAxOyAwID09PSBlMy5ibF9jb3VudFtzM107ICkKICAgICAgICAgICAgICAgICAgczMtLTsKICAgICAgICAgICAgICAgIGUzLmJsX2NvdW50W3MzXS0tLCBlMy5ibF9jb3VudFtzMyArIDFdICs9IDIsIGUzLmJsX2NvdW50W3AyXS0tLCBtMiAtPSAyOwogICAgICAgICAgICAgIH0gd2hpbGUgKDAgPCBtMik7CiAgICAgICAgICAgICAgZm9yIChzMyA9IHAyOyAwICE9PSBzMzsgczMtLSkKICAgICAgICAgICAgICAgIGZvciAobjMgPSBlMy5ibF9jb3VudFtzM107IDAgIT09IG4zOyApCiAgICAgICAgICAgICAgICAgIHUzIDwgKGkzID0gZTMuaGVhcFstLXIzXSkgfHwgKGgzWzIgKiBpMyArIDFdICE9PSBzMyAmJiAoZTMub3B0X2xlbiArPSAoczMgLSBoM1syICogaTMgKyAxXSkgKiBoM1syICogaTNdLCBoM1syICogaTMgKyAxXSA9IHMzKSwgbjMtLSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0oZTIsIHQyKSwgWihzMiwgdTIsIGUyLmJsX2NvdW50KTsKICAgICAgICB9CiAgICAgICAgZnVuY3Rpb24gWChlMiwgdDIsIHIyKSB7CiAgICAgICAgICB2YXIgbjIsIGkyLCBzMiA9IC0xLCBhMiA9IHQyWzFdLCBvMiA9IDAsIGgyID0gNywgdTIgPSA0OwogICAgICAgICAgZm9yICgwID09PSBhMiAmJiAoaDIgPSAxMzgsIHUyID0gMyksIHQyWzIgKiAocjIgKyAxKSArIDFdID0gNjU1MzUsIG4yID0gMDsgbjIgPD0gcjI7IG4yKyspCiAgICAgICAgICAgIGkyID0gYTIsIGEyID0gdDJbMiAqIChuMiArIDEpICsgMV0sICsrbzIgPCBoMiAmJiBpMiA9PT0gYTIgfHwgKG8yIDwgdTIgPyBlMi5ibF90cmVlWzIgKiBpMl0gKz0gbzIgOiAwICE9PSBpMiA/IChpMiAhPT0gczIgJiYgZTIuYmxfdHJlZVsyICogaTJdKyssIGUyLmJsX3RyZWVbMiAqIGJdKyspIDogbzIgPD0gMTAgPyBlMi5ibF90cmVlWzIgKiB2XSsrIDogZTIuYmxfdHJlZVsyICogeV0rKywgczIgPSBpMiwgdTIgPSAobzIgPSAwKSA9PT0gYTIgPyAoaDIgPSAxMzgsIDMpIDogaTIgPT09IGEyID8gKGgyID0gNiwgMykgOiAoaDIgPSA3LCA0KSk7CiAgICAgICAgfQogICAgICAgIGZ1bmN0aW9uIFYoZTIsIHQyLCByMikgewogICAgICAgICAgdmFyIG4yLCBpMiwgczIgPSAtMSwgYTIgPSB0MlsxXSwgbzIgPSAwLCBoMiA9IDcsIHUyID0gNDsKICAgICAgICAgIGZvciAoMCA9PT0gYTIgJiYgKGgyID0gMTM4LCB1MiA9IDMpLCBuMiA9IDA7IG4yIDw9IHIyOyBuMisrKQogICAgICAgICAgICBpZiAoaTIgPSBhMiwgYTIgPSB0MlsyICogKG4yICsgMSkgKyAxXSwgISgrK28yIDwgaDIgJiYgaTIgPT09IGEyKSkgewogICAgICAgICAgICAgIGlmIChvMiA8IHUyKQogICAgICAgICAgICAgICAgZm9yICg7IEwoZTIsIGkyLCBlMi5ibF90cmVlKSwgMCAhPSAtLW8yOyApCiAgICAgICAgICAgICAgICAgIDsKICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAwICE9PSBpMiA/IChpMiAhPT0gczIgJiYgKEwoZTIsIGkyLCBlMi5ibF90cmVlKSwgbzItLSksIEwoZTIsIGIsIGUyLmJsX3RyZWUpLCBQKGUyLCBvMiAtIDMsIDIpKSA6IG8yIDw9IDEwID8gKEwoZTIsIHYsIGUyLmJsX3RyZWUpLCBQKGUyLCBvMiAtIDMsIDMpKSA6IChMKGUyLCB5LCBlMi5ibF90cmVlKSwgUChlMiwgbzIgLSAxMSwgNykpOwogICAgICAgICAgICAgIHMyID0gaTIsIHUyID0gKG8yID0gMCkgPT09IGEyID8gKGgyID0gMTM4LCAzKSA6IGkyID09PSBhMiA/IChoMiA9IDYsIDMpIDogKGgyID0gNywgNCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbihUKTsKICAgICAgICB2YXIgcSA9IGZhbHNlOwogICAgICAgIGZ1bmN0aW9uIEooZTIsIHQyLCByMiwgbjIpIHsKICAgICAgICAgIFAoZTIsIChzIDw8IDEpICsgKG4yID8gMSA6IDApLCAzKSwgZnVuY3Rpb24oZTMsIHQzLCByMywgbjMpIHsKICAgICAgICAgICAgTShlMyksIG4zICYmIChVKGUzLCByMyksIFUoZTMsIH5yMykpLCBpLmFycmF5U2V0KGUzLnBlbmRpbmdfYnVmLCBlMy53aW5kb3csIHQzLCByMywgZTMucGVuZGluZyksIGUzLnBlbmRpbmcgKz0gcjM7CiAgICAgICAgICB9KGUyLCB0MiwgcjIsIHRydWUpOwogICAgICAgIH0KICAgICAgICByLl90cl9pbml0ID0gZnVuY3Rpb24oZTIpIHsKICAgICAgICAgIHEgfHwgKGZ1bmN0aW9uKCkgewogICAgICAgICAgICB2YXIgZTMsIHQyLCByMiwgbjIsIGkyLCBzMiA9IG5ldyBBcnJheShnICsgMSk7CiAgICAgICAgICAgIGZvciAobjIgPSByMiA9IDA7IG4yIDwgYSAtIDE7IG4yKyspCiAgICAgICAgICAgICAgZm9yIChJW24yXSA9IHIyLCBlMyA9IDA7IGUzIDwgMSA8PCB3W24yXTsgZTMrKykKICAgICAgICAgICAgICAgIEFbcjIrK10gPSBuMjsKICAgICAgICAgICAgZm9yIChBW3IyIC0gMV0gPSBuMiwgbjIgPSBpMiA9IDA7IG4yIDwgMTY7IG4yKyspCiAgICAgICAgICAgICAgZm9yIChUW24yXSA9IGkyLCBlMyA9IDA7IGUzIDwgMSA8PCBrW24yXTsgZTMrKykKICAgICAgICAgICAgICAgIEVbaTIrK10gPSBuMjsKICAgICAgICAgICAgZm9yIChpMiA+Pj0gNzsgbjIgPCBmOyBuMisrKQogICAgICAgICAgICAgIGZvciAoVFtuMl0gPSBpMiA8PCA3LCBlMyA9IDA7IGUzIDwgMSA8PCBrW24yXSAtIDc7IGUzKyspCiAgICAgICAgICAgICAgICBFWzI1NiArIGkyKytdID0gbjI7CiAgICAgICAgICAgIGZvciAodDIgPSAwOyB0MiA8PSBnOyB0MisrKQogICAgICAgICAgICAgIHMyW3QyXSA9IDA7CiAgICAgICAgICAgIGZvciAoZTMgPSAwOyBlMyA8PSAxNDM7ICkKICAgICAgICAgICAgICB6WzIgKiBlMyArIDFdID0gOCwgZTMrKywgczJbOF0rKzsKICAgICAgICAgICAgZm9yICg7IGUzIDw9IDI1NTsgKQogICAgICAgICAgICAgIHpbMiAqIGUzICsgMV0gPSA5LCBlMysrLCBzMls5XSsrOwogICAgICAgICAgICBmb3IgKDsgZTMgPD0gMjc5OyApCiAgICAgICAgICAgICAgelsyICogZTMgKyAxXSA9IDcsIGUzKyssIHMyWzddKys7CiAgICAgICAgICAgIGZvciAoOyBlMyA8PSAyODc7ICkKICAgICAgICAgICAgICB6WzIgKiBlMyArIDFdID0gOCwgZTMrKywgczJbOF0rKzsKICAgICAgICAgICAgZm9yIChaKHosIGwgKyAxLCBzMiksIGUzID0gMDsgZTMgPCBmOyBlMysrKQogICAgICAgICAgICAgIENbMiAqIGUzICsgMV0gPSA1LCBDWzIgKiBlM10gPSBqKGUzLCA1KTsKICAgICAgICAgICAgTyA9IG5ldyBEKHosIHcsIHUgKyAxLCBsLCBnKSwgQiA9IG5ldyBEKEMsIGssIDAsIGYsIGcpLCBSID0gbmV3IEQobmV3IEFycmF5KDApLCB4LCAwLCBjLCBwKTsKICAgICAgICAgIH0oKSwgcSA9IHRydWUpLCBlMi5sX2Rlc2MgPSBuZXcgRihlMi5keW5fbHRyZWUsIE8pLCBlMi5kX2Rlc2MgPSBuZXcgRihlMi5keW5fZHRyZWUsIEIpLCBlMi5ibF9kZXNjID0gbmV3IEYoZTIuYmxfdHJlZSwgUiksIGUyLmJpX2J1ZiA9IDAsIGUyLmJpX3ZhbGlkID0gMCwgVyhlMik7CiAgICAgICAgfSwgci5fdHJfc3RvcmVkX2Jsb2NrID0gSiwgci5fdHJfZmx1c2hfYmxvY2sgPSBmdW5jdGlvbihlMiwgdDIsIHIyLCBuMikgewogICAgICAgICAgdmFyIGkyLCBzMiwgYTIgPSAwOwogICAgICAgICAgMCA8IGUyLmxldmVsID8gKDIgPT09IGUyLnN0cm0uZGF0YV90eXBlICYmIChlMi5zdHJtLmRhdGFfdHlwZSA9IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIHZhciB0MywgcjMgPSA0MDkzNjI0NDQ3OwogICAgICAgICAgICBmb3IgKHQzID0gMDsgdDMgPD0gMzE7IHQzKyssIHIzID4+Pj0gMSkKICAgICAgICAgICAgICBpZiAoMSAmIHIzICYmIDAgIT09IGUzLmR5bl9sdHJlZVsyICogdDNdKQogICAgICAgICAgICAgICAgcmV0dXJuIG87CiAgICAgICAgICAgIGlmICgwICE9PSBlMy5keW5fbHRyZWVbMThdIHx8IDAgIT09IGUzLmR5bl9sdHJlZVsyMF0gfHwgMCAhPT0gZTMuZHluX2x0cmVlWzI2XSkKICAgICAgICAgICAgICByZXR1cm4gaDsKICAgICAgICAgICAgZm9yICh0MyA9IDMyOyB0MyA8IHU7IHQzKyspCiAgICAgICAgICAgICAgaWYgKDAgIT09IGUzLmR5bl9sdHJlZVsyICogdDNdKQogICAgICAgICAgICAgICAgcmV0dXJuIGg7CiAgICAgICAgICAgIHJldHVybiBvOwogICAgICAgICAgfShlMikpLCBZKGUyLCBlMi5sX2Rlc2MpLCBZKGUyLCBlMi5kX2Rlc2MpLCBhMiA9IGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIHZhciB0MzsKICAgICAgICAgICAgZm9yIChYKGUzLCBlMy5keW5fbHRyZWUsIGUzLmxfZGVzYy5tYXhfY29kZSksIFgoZTMsIGUzLmR5bl9kdHJlZSwgZTMuZF9kZXNjLm1heF9jb2RlKSwgWShlMywgZTMuYmxfZGVzYyksIHQzID0gYyAtIDE7IDMgPD0gdDMgJiYgMCA9PT0gZTMuYmxfdHJlZVsyICogU1t0M10gKyAxXTsgdDMtLSkKICAgICAgICAgICAgICA7CiAgICAgICAgICAgIHJldHVybiBlMy5vcHRfbGVuICs9IDMgKiAodDMgKyAxKSArIDUgKyA1ICsgNCwgdDM7CiAgICAgICAgICB9KGUyKSwgaTIgPSBlMi5vcHRfbGVuICsgMyArIDcgPj4+IDMsIChzMiA9IGUyLnN0YXRpY19sZW4gKyAzICsgNyA+Pj4gMykgPD0gaTIgJiYgKGkyID0gczIpKSA6IGkyID0gczIgPSByMiArIDUsIHIyICsgNCA8PSBpMiAmJiAtMSAhPT0gdDIgPyBKKGUyLCB0MiwgcjIsIG4yKSA6IDQgPT09IGUyLnN0cmF0ZWd5IHx8IHMyID09PSBpMiA/IChQKGUyLCAyICsgKG4yID8gMSA6IDApLCAzKSwgSyhlMiwgeiwgQykpIDogKFAoZTIsIDQgKyAobjIgPyAxIDogMCksIDMpLCBmdW5jdGlvbihlMywgdDMsIHIzLCBuMykgewogICAgICAgICAgICB2YXIgaTM7CiAgICAgICAgICAgIGZvciAoUChlMywgdDMgLSAyNTcsIDUpLCBQKGUzLCByMyAtIDEsIDUpLCBQKGUzLCBuMyAtIDQsIDQpLCBpMyA9IDA7IGkzIDwgbjM7IGkzKyspCiAgICAgICAgICAgICAgUChlMywgZTMuYmxfdHJlZVsyICogU1tpM10gKyAxXSwgMyk7CiAgICAgICAgICAgIFYoZTMsIGUzLmR5bl9sdHJlZSwgdDMgLSAxKSwgVihlMywgZTMuZHluX2R0cmVlLCByMyAtIDEpOwogICAgICAgICAgfShlMiwgZTIubF9kZXNjLm1heF9jb2RlICsgMSwgZTIuZF9kZXNjLm1heF9jb2RlICsgMSwgYTIgKyAxKSwgSyhlMiwgZTIuZHluX2x0cmVlLCBlMi5keW5fZHRyZWUpKSwgVyhlMiksIG4yICYmIE0oZTIpOwogICAgICAgIH0sIHIuX3RyX3RhbGx5ID0gZnVuY3Rpb24oZTIsIHQyLCByMikgewogICAgICAgICAgcmV0dXJuIGUyLnBlbmRpbmdfYnVmW2UyLmRfYnVmICsgMiAqIGUyLmxhc3RfbGl0XSA9IHQyID4+PiA4ICYgMjU1LCBlMi5wZW5kaW5nX2J1ZltlMi5kX2J1ZiArIDIgKiBlMi5sYXN0X2xpdCArIDFdID0gMjU1ICYgdDIsIGUyLnBlbmRpbmdfYnVmW2UyLmxfYnVmICsgZTIubGFzdF9saXRdID0gMjU1ICYgcjIsIGUyLmxhc3RfbGl0KyssIDAgPT09IHQyID8gZTIuZHluX2x0cmVlWzIgKiByMl0rKyA6IChlMi5tYXRjaGVzKyssIHQyLS0sIGUyLmR5bl9sdHJlZVsyICogKEFbcjJdICsgdSArIDEpXSsrLCBlMi5keW5fZHRyZWVbMiAqIE4odDIpXSsrKSwgZTIubGFzdF9saXQgPT09IGUyLmxpdF9idWZzaXplIC0gMTsKICAgICAgICB9LCByLl90cl9hbGlnbiA9IGZ1bmN0aW9uKGUyKSB7CiAgICAgICAgICBQKGUyLCAyLCAzKSwgTChlMiwgbSwgeiksIGZ1bmN0aW9uKGUzKSB7CiAgICAgICAgICAgIDE2ID09PSBlMy5iaV92YWxpZCA/IChVKGUzLCBlMy5iaV9idWYpLCBlMy5iaV9idWYgPSAwLCBlMy5iaV92YWxpZCA9IDApIDogOCA8PSBlMy5iaV92YWxpZCAmJiAoZTMucGVuZGluZ19idWZbZTMucGVuZGluZysrXSA9IDI1NSAmIGUzLmJpX2J1ZiwgZTMuYmlfYnVmID4+PSA4LCBlMy5iaV92YWxpZCAtPSA4KTsKICAgICAgICAgIH0oZTIpOwogICAgICAgIH07CiAgICAgIH0sIHsgIi4uL3V0aWxzL2NvbW1vbiI6IDQxIH1dLCA1MzogW2Z1bmN0aW9uKGUsIHQsIHIpIHsKICAgICAgICB0LmV4cG9ydHMgPSBmdW5jdGlvbigpIHsKICAgICAgICAgIHRoaXMuaW5wdXQgPSBudWxsLCB0aGlzLm5leHRfaW4gPSAwLCB0aGlzLmF2YWlsX2luID0gMCwgdGhpcy50b3RhbF9pbiA9IDAsIHRoaXMub3V0cHV0ID0gbnVsbCwgdGhpcy5uZXh0X291dCA9IDAsIHRoaXMuYXZhaWxfb3V0ID0gMCwgdGhpcy50b3RhbF9vdXQgPSAwLCB0aGlzLm1zZyA9ICIiLCB0aGlzLnN0YXRlID0gbnVsbCwgdGhpcy5kYXRhX3R5cGUgPSAyLCB0aGlzLmFkbGVyID0gMDsKICAgICAgICB9OwogICAgICB9LCB7fV0sIDU0OiBbZnVuY3Rpb24oZSwgdCwgcikgewogICAgICAgIChmdW5jdGlvbihlMikgewogICAgICAgICAgIWZ1bmN0aW9uKHIyLCBuKSB7CiAgICAgICAgICAgIGlmICghcjIuc2V0SW1tZWRpYXRlKSB7CiAgICAgICAgICAgICAgdmFyIGksIHMsIHQyLCBhLCBvID0gMSwgaCA9IHt9LCB1ID0gZmFsc2UsIGwgPSByMi5kb2N1bWVudCwgZTMgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mKHIyKTsKICAgICAgICAgICAgICBlMyA9IGUzICYmIGUzLnNldFRpbWVvdXQgPyBlMyA6IHIyLCBpID0gIltvYmplY3QgcHJvY2Vzc10iID09PSB7fS50b1N0cmluZy5jYWxsKHIyLnByb2Nlc3MpID8gZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgICAgIHByb2Nlc3MubmV4dFRpY2soZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICAgIGMoZTQpOwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgfSA6IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgaWYgKHIyLnBvc3RNZXNzYWdlICYmICFyMi5pbXBvcnRTY3JpcHRzKSB7CiAgICAgICAgICAgICAgICAgIHZhciBlNCA9IHRydWUsIHQzID0gcjIub25tZXNzYWdlOwogICAgICAgICAgICAgICAgICByZXR1cm4gcjIub25tZXNzYWdlID0gZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgICAgICAgZTQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgfSwgcjIucG9zdE1lc3NhZ2UoIiIsICIqIiksIHIyLm9ubWVzc2FnZSA9IHQzLCBlNDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9KCkgPyAoYSA9ICJzZXRJbW1lZGlhdGUkIiArIE1hdGgucmFuZG9tKCkgKyAiJCIsIHIyLmFkZEV2ZW50TGlzdGVuZXIgPyByMi5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwgZCwgZmFsc2UpIDogcjIuYXR0YWNoRXZlbnQoIm9ubWVzc2FnZSIsIGQpLCBmdW5jdGlvbihlNCkgewogICAgICAgICAgICAgICAgcjIucG9zdE1lc3NhZ2UoYSArIGU0LCAiKiIpOwogICAgICAgICAgICAgIH0pIDogcjIuTWVzc2FnZUNoYW5uZWwgPyAoKHQyID0gbmV3IE1lc3NhZ2VDaGFubmVsKCkpLnBvcnQxLm9ubWVzc2FnZSA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgICAgICBjKGU0LmRhdGEpOwogICAgICAgICAgICAgIH0sIGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgICAgICB0Mi5wb3J0Mi5wb3N0TWVzc2FnZShlNCk7CiAgICAgICAgICAgICAgfSkgOiBsICYmICJvbnJlYWR5c3RhdGVjaGFuZ2UiIGluIGwuY3JlYXRlRWxlbWVudCgic2NyaXB0IikgPyAocyA9IGwuZG9jdW1lbnRFbGVtZW50LCBmdW5jdGlvbihlNCkgewogICAgICAgICAgICAgICAgdmFyIHQzID0gbC5jcmVhdGVFbGVtZW50KCJzY3JpcHQiKTsKICAgICAgICAgICAgICAgIHQzLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkgewogICAgICAgICAgICAgICAgICBjKGU0KSwgdDMub25yZWFkeXN0YXRlY2hhbmdlID0gbnVsbCwgcy5yZW1vdmVDaGlsZCh0MyksIHQzID0gbnVsbDsKICAgICAgICAgICAgICAgIH0sIHMuYXBwZW5kQ2hpbGQodDMpOwogICAgICAgICAgICAgIH0pIDogZnVuY3Rpb24oZTQpIHsKICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoYywgMCwgZTQpOwogICAgICAgICAgICAgIH0sIGUzLnNldEltbWVkaWF0ZSA9IGZ1bmN0aW9uKGU0KSB7CiAgICAgICAgICAgICAgICAiZnVuY3Rpb24iICE9IHR5cGVvZiBlNCAmJiAoZTQgPSBuZXcgRnVuY3Rpb24oIiIgKyBlNCkpOwogICAgICAgICAgICAgICAgZm9yICh2YXIgdDMgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpLCByMyA9IDA7IHIzIDwgdDMubGVuZ3RoOyByMysrKQogICAgICAgICAgICAgICAgICB0M1tyM10gPSBhcmd1bWVudHNbcjMgKyAxXTsKICAgICAgICAgICAgICAgIHZhciBuMiA9IHsgY2FsbGJhY2s6IGU0LCBhcmdzOiB0MyB9OwogICAgICAgICAgICAgICAgcmV0dXJuIGhbb10gPSBuMiwgaShvKSwgbysrOwogICAgICAgICAgICAgIH0sIGUzLmNsZWFySW1tZWRpYXRlID0gZjsKICAgICAgICAgICAgfQogICAgICAgICAgICBmdW5jdGlvbiBmKGU0KSB7CiAgICAgICAgICAgICAgZGVsZXRlIGhbZTRdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZ1bmN0aW9uIGMoZTQpIHsKICAgICAgICAgICAgICBpZiAodSkKICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoYywgMCwgZTQpOwogICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgdmFyIHQzID0gaFtlNF07CiAgICAgICAgICAgICAgICBpZiAodDMpIHsKICAgICAgICAgICAgICAgICAgdSA9IHRydWU7CiAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgIWZ1bmN0aW9uKGU1KSB7CiAgICAgICAgICAgICAgICAgICAgICB2YXIgdDQgPSBlNS5jYWxsYmFjaywgcjMgPSBlNS5hcmdzOwogICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChyMy5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICAgICAgICAgIHQ0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICAgICAgICAgICAgICB0NChyM1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICAgICAgICAgICAgICB0NChyM1swXSwgcjNbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgICAgICAgICAgICAgICAgdDQocjNbMF0sIHIzWzFdLCByM1syXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgdDQuYXBwbHkobiwgcjMpOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0odDMpOwogICAgICAgICAgICAgICAgICB9IGZpbmFsbHkgewogICAgICAgICAgICAgICAgICAgIGYoZTQpLCB1ID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZnVuY3Rpb24gZChlNCkgewogICAgICAgICAgICAgIGU0LnNvdXJjZSA9PT0gcjIgJiYgInN0cmluZyIgPT0gdHlwZW9mIGU0LmRhdGEgJiYgMCA9PT0gZTQuZGF0YS5pbmRleE9mKGEpICYmIGMoK2U0LmRhdGEuc2xpY2UoYS5sZW5ndGgpKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSgidW5kZWZpbmVkIiA9PSB0eXBlb2Ygc2VsZiA/IHZvaWQgMCA9PT0gZTIgPyB0aGlzIDogZTIgOiBzZWxmKTsKICAgICAgICB9KS5jYWxsKHRoaXMsICJ1bmRlZmluZWQiICE9IHR5cGVvZiBjb21tb25qc0dsb2JhbCA/IGNvbW1vbmpzR2xvYmFsIDogInVuZGVmaW5lZCIgIT0gdHlwZW9mIHNlbGYgPyBzZWxmIDogInVuZGVmaW5lZCIgIT0gdHlwZW9mIHdpbmRvdyA/IHdpbmRvdyA6IHt9KTsKICAgICAgfSwge31dIH0sIHt9LCBbMTBdKSgxMCk7CiAgICB9KTsKICB9KShqc3ppcF9taW4pOwogIHZhciBqc3ppcF9taW5FeHBvcnRzID0ganN6aXBfbWluLmV4cG9ydHM7CiAgdmFyIEpTWmlwID0gLyogQF9fUFVSRV9fICovIGdldERlZmF1bHRFeHBvcnRGcm9tQ2pzKGpzemlwX21pbkV4cG9ydHMpOwogIC8qKgogICAqIEBsaWNlbnNlCiAgICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQwogICAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wCiAgICovCiAgY29uc3QgcHJveHlNYXJrZXIgPSBTeW1ib2woIkNvbWxpbmsucHJveHkiKTsKICBjb25zdCBjcmVhdGVFbmRwb2ludCA9IFN5bWJvbCgiQ29tbGluay5lbmRwb2ludCIpOwogIGNvbnN0IHJlbGVhc2VQcm94eSA9IFN5bWJvbCgiQ29tbGluay5yZWxlYXNlUHJveHkiKTsKICBjb25zdCBmaW5hbGl6ZXIgPSBTeW1ib2woIkNvbWxpbmsuZmluYWxpemVyIik7CiAgY29uc3QgdGhyb3dNYXJrZXIgPSBTeW1ib2woIkNvbWxpbmsudGhyb3duIik7CiAgY29uc3QgaXNPYmplY3QgPSAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAib2JqZWN0IiAmJiB2YWwgIT09IG51bGwgfHwgdHlwZW9mIHZhbCA9PT0gImZ1bmN0aW9uIjsKICBjb25zdCBwcm94eVRyYW5zZmVySGFuZGxlciA9IHsKICAgIGNhbkhhbmRsZTogKHZhbCkgPT4gaXNPYmplY3QodmFsKSAmJiB2YWxbcHJveHlNYXJrZXJdLAogICAgc2VyaWFsaXplKG9iaikgewogICAgICBjb25zdCB7IHBvcnQxLCBwb3J0MiB9ID0gbmV3IE1lc3NhZ2VDaGFubmVsKCk7CiAgICAgIGV4cG9zZShvYmosIHBvcnQxKTsKICAgICAgcmV0dXJuIFtwb3J0MiwgW3BvcnQyXV07CiAgICB9LAogICAgZGVzZXJpYWxpemUocG9ydCkgewogICAgICBwb3J0LnN0YXJ0KCk7CiAgICAgIHJldHVybiB3cmFwKHBvcnQpOwogICAgfQogIH07CiAgY29uc3QgdGhyb3dUcmFuc2ZlckhhbmRsZXIgPSB7CiAgICBjYW5IYW5kbGU6ICh2YWx1ZSkgPT4gaXNPYmplY3QodmFsdWUpICYmIHRocm93TWFya2VyIGluIHZhbHVlLAogICAgc2VyaWFsaXplKHsgdmFsdWUgfSkgewogICAgICBsZXQgc2VyaWFsaXplZDsKICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRXJyb3IpIHsKICAgICAgICBzZXJpYWxpemVkID0gewogICAgICAgICAgaXNFcnJvcjogdHJ1ZSwKICAgICAgICAgIHZhbHVlOiB7CiAgICAgICAgICAgIG1lc3NhZ2U6IHZhbHVlLm1lc3NhZ2UsCiAgICAgICAgICAgIG5hbWU6IHZhbHVlLm5hbWUsCiAgICAgICAgICAgIHN0YWNrOiB2YWx1ZS5zdGFjawogICAgICAgICAgfQogICAgICAgIH07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgc2VyaWFsaXplZCA9IHsgaXNFcnJvcjogZmFsc2UsIHZhbHVlIH07CiAgICAgIH0KICAgICAgcmV0dXJuIFtzZXJpYWxpemVkLCBbXV07CiAgICB9LAogICAgZGVzZXJpYWxpemUoc2VyaWFsaXplZCkgewogICAgICBpZiAoc2VyaWFsaXplZC5pc0Vycm9yKSB7CiAgICAgICAgdGhyb3cgT2JqZWN0LmFzc2lnbihuZXcgRXJyb3Ioc2VyaWFsaXplZC52YWx1ZS5tZXNzYWdlKSwgc2VyaWFsaXplZC52YWx1ZSk7CiAgICAgIH0KICAgICAgdGhyb3cgc2VyaWFsaXplZC52YWx1ZTsKICAgIH0KICB9OwogIGNvbnN0IHRyYW5zZmVySGFuZGxlcnMgPSAvKiBAX19QVVJFX18gKi8gbmV3IE1hcChbCiAgICBbInByb3h5IiwgcHJveHlUcmFuc2ZlckhhbmRsZXJdLAogICAgWyJ0aHJvdyIsIHRocm93VHJhbnNmZXJIYW5kbGVyXQogIF0pOwogIGZ1bmN0aW9uIGlzQWxsb3dlZE9yaWdpbihhbGxvd2VkT3JpZ2lucywgb3JpZ2luKSB7CiAgICBmb3IgKGNvbnN0IGFsbG93ZWRPcmlnaW4gb2YgYWxsb3dlZE9yaWdpbnMpIHsKICAgICAgaWYgKG9yaWdpbiA9PT0gYWxsb3dlZE9yaWdpbiB8fCBhbGxvd2VkT3JpZ2luID09PSAiKiIpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoYWxsb3dlZE9yaWdpbiBpbnN0YW5jZW9mIFJlZ0V4cCAmJiBhbGxvd2VkT3JpZ2luLnRlc3Qob3JpZ2luKSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGZ1bmN0aW9uIGV4cG9zZShvYmosIGVwID0gZ2xvYmFsVGhpcywgYWxsb3dlZE9yaWdpbnMgPSBbIioiXSkgewogICAgZXAuYWRkRXZlbnRMaXN0ZW5lcigibWVzc2FnZSIsIGZ1bmN0aW9uIGNhbGxiYWNrKGV2KSB7CiAgICAgIGlmICghZXYgfHwgIWV2LmRhdGEpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKCFpc0FsbG93ZWRPcmlnaW4oYWxsb3dlZE9yaWdpbnMsIGV2Lm9yaWdpbikpIHsKICAgICAgICBjb25zb2xlLndhcm4oYEludmFsaWQgb3JpZ2luICcke2V2Lm9yaWdpbn0nIGZvciBjb21saW5rIHByb3h5YCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IHsgaWQsIHR5cGUsIHBhdGggfSA9IE9iamVjdC5hc3NpZ24oeyBwYXRoOiBbXSB9LCBldi5kYXRhKTsKICAgICAgY29uc3QgYXJndW1lbnRMaXN0ID0gKGV2LmRhdGEuYXJndW1lbnRMaXN0IHx8IFtdKS5tYXAoZnJvbVdpcmVWYWx1ZSk7CiAgICAgIGxldCByZXR1cm5WYWx1ZTsKICAgICAgdHJ5IHsKICAgICAgICBjb25zdCBwYXJlbnQgPSBwYXRoLnNsaWNlKDAsIC0xKS5yZWR1Y2UoKG9iajIsIHByb3ApID0+IG9iajJbcHJvcF0sIG9iaik7CiAgICAgICAgY29uc3QgcmF3VmFsdWUgPSBwYXRoLnJlZHVjZSgob2JqMiwgcHJvcCkgPT4gb2JqMltwcm9wXSwgb2JqKTsKICAgICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICAgIGNhc2UgIkdFVCI6CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHJhd1ZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAiU0VUIjoKICAgICAgICAgICAgewogICAgICAgICAgICAgIHBhcmVudFtwYXRoLnNsaWNlKC0xKVswXV0gPSBmcm9tV2lyZVZhbHVlKGV2LmRhdGEudmFsdWUpOwogICAgICAgICAgICAgIHJldHVyblZhbHVlID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgIkFQUExZIjoKICAgICAgICAgICAgewogICAgICAgICAgICAgIHJldHVyblZhbHVlID0gcmF3VmFsdWUuYXBwbHkocGFyZW50LCBhcmd1bWVudExpc3QpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAiQ09OU1RSVUNUIjoKICAgICAgICAgICAgewogICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gbmV3IHJhd1ZhbHVlKC4uLmFyZ3VtZW50TGlzdCk7CiAgICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSBwcm94eSh2YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICJFTkRQT0lOVCI6CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBjb25zdCB7IHBvcnQxLCBwb3J0MiB9ID0gbmV3IE1lc3NhZ2VDaGFubmVsKCk7CiAgICAgICAgICAgICAgZXhwb3NlKG9iaiwgcG9ydDIpOwogICAgICAgICAgICAgIHJldHVyblZhbHVlID0gdHJhbnNmZXIocG9ydDEsIFtwb3J0MV0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAiUkVMRUFTRSI6CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICByZXR1cm5WYWx1ZSA9IHZvaWQgMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKHZhbHVlKSB7CiAgICAgICAgcmV0dXJuVmFsdWUgPSB7IHZhbHVlLCBbdGhyb3dNYXJrZXJdOiAwIH07CiAgICAgIH0KICAgICAgUHJvbWlzZS5yZXNvbHZlKHJldHVyblZhbHVlKS5jYXRjaCgodmFsdWUpID0+IHsKICAgICAgICByZXR1cm4geyB2YWx1ZSwgW3Rocm93TWFya2VyXTogMCB9OwogICAgICB9KS50aGVuKChyZXR1cm5WYWx1ZTIpID0+IHsKICAgICAgICBjb25zdCBbd2lyZVZhbHVlLCB0cmFuc2ZlcmFibGVzXSA9IHRvV2lyZVZhbHVlKHJldHVyblZhbHVlMik7CiAgICAgICAgZXAucG9zdE1lc3NhZ2UoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LCB3aXJlVmFsdWUpLCB7IGlkIH0pLCB0cmFuc2ZlcmFibGVzKTsKICAgICAgICBpZiAodHlwZSA9PT0gIlJFTEVBU0UiKSB7CiAgICAgICAgICBlcC5yZW1vdmVFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwgY2FsbGJhY2spOwogICAgICAgICAgY2xvc2VFbmRQb2ludChlcCk7CiAgICAgICAgICBpZiAoZmluYWxpemVyIGluIG9iaiAmJiB0eXBlb2Ygb2JqW2ZpbmFsaXplcl0gPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgICAgb2JqW2ZpbmFsaXplcl0oKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0pLmNhdGNoKChlcnJvcikgPT4gewogICAgICAgIGNvbnN0IFt3aXJlVmFsdWUsIHRyYW5zZmVyYWJsZXNdID0gdG9XaXJlVmFsdWUoewogICAgICAgICAgdmFsdWU6IG5ldyBUeXBlRXJyb3IoIlVuc2VyaWFsaXphYmxlIHJldHVybiB2YWx1ZSIpLAogICAgICAgICAgW3Rocm93TWFya2VyXTogMAogICAgICAgIH0pOwogICAgICAgIGVwLnBvc3RNZXNzYWdlKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSwgd2lyZVZhbHVlKSwgeyBpZCB9KSwgdHJhbnNmZXJhYmxlcyk7CiAgICAgIH0pOwogICAgfSk7CiAgICBpZiAoZXAuc3RhcnQpIHsKICAgICAgZXAuc3RhcnQoKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gaXNNZXNzYWdlUG9ydChlbmRwb2ludCkgewogICAgcmV0dXJuIGVuZHBvaW50LmNvbnN0cnVjdG9yLm5hbWUgPT09ICJNZXNzYWdlUG9ydCI7CiAgfQogIGZ1bmN0aW9uIGNsb3NlRW5kUG9pbnQoZW5kcG9pbnQpIHsKICAgIGlmIChpc01lc3NhZ2VQb3J0KGVuZHBvaW50KSkKICAgICAgZW5kcG9pbnQuY2xvc2UoKTsKICB9CiAgZnVuY3Rpb24gd3JhcChlcCwgdGFyZ2V0KSB7CiAgICByZXR1cm4gY3JlYXRlUHJveHkoZXAsIFtdLCB0YXJnZXQpOwogIH0KICBmdW5jdGlvbiB0aHJvd0lmUHJveHlSZWxlYXNlZChpc1JlbGVhc2VkKSB7CiAgICBpZiAoaXNSZWxlYXNlZCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIlByb3h5IGhhcyBiZWVuIHJlbGVhc2VkIGFuZCBpcyBub3QgdXNlYWJsZSIpOwogICAgfQogIH0KICBmdW5jdGlvbiByZWxlYXNlRW5kcG9pbnQoZXApIHsKICAgIHJldHVybiByZXF1ZXN0UmVzcG9uc2VNZXNzYWdlKGVwLCB7CiAgICAgIHR5cGU6ICJSRUxFQVNFIgogICAgfSkudGhlbigoKSA9PiB7CiAgICAgIGNsb3NlRW5kUG9pbnQoZXApOwogICAgfSk7CiAgfQogIGNvbnN0IHByb3h5Q291bnRlciA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgV2Vha01hcCgpOwogIGNvbnN0IHByb3h5RmluYWxpemVycyA9ICJGaW5hbGl6YXRpb25SZWdpc3RyeSIgaW4gZ2xvYmFsVGhpcyAmJiBuZXcgRmluYWxpemF0aW9uUmVnaXN0cnkoKGVwKSA9PiB7CiAgICBjb25zdCBuZXdDb3VudCA9IChwcm94eUNvdW50ZXIuZ2V0KGVwKSB8fCAwKSAtIDE7CiAgICBwcm94eUNvdW50ZXIuc2V0KGVwLCBuZXdDb3VudCk7CiAgICBpZiAobmV3Q291bnQgPT09IDApIHsKICAgICAgcmVsZWFzZUVuZHBvaW50KGVwKTsKICAgIH0KICB9KTsKICBmdW5jdGlvbiByZWdpc3RlclByb3h5KHByb3h5MiwgZXApIHsKICAgIGNvbnN0IG5ld0NvdW50ID0gKHByb3h5Q291bnRlci5nZXQoZXApIHx8IDApICsgMTsKICAgIHByb3h5Q291bnRlci5zZXQoZXAsIG5ld0NvdW50KTsKICAgIGlmIChwcm94eUZpbmFsaXplcnMpIHsKICAgICAgcHJveHlGaW5hbGl6ZXJzLnJlZ2lzdGVyKHByb3h5MiwgZXAsIHByb3h5Mik7CiAgICB9CiAgfQogIGZ1bmN0aW9uIHVucmVnaXN0ZXJQcm94eShwcm94eTIpIHsKICAgIGlmIChwcm94eUZpbmFsaXplcnMpIHsKICAgICAgcHJveHlGaW5hbGl6ZXJzLnVucmVnaXN0ZXIocHJveHkyKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gY3JlYXRlUHJveHkoZXAsIHBhdGggPSBbXSwgdGFyZ2V0ID0gZnVuY3Rpb24oKSB7CiAgfSkgewogICAgbGV0IGlzUHJveHlSZWxlYXNlZCA9IGZhbHNlOwogICAgY29uc3QgcHJveHkyID0gbmV3IFByb3h5KHRhcmdldCwgewogICAgICBnZXQoX3RhcmdldCwgcHJvcCkgewogICAgICAgIHRocm93SWZQcm94eVJlbGVhc2VkKGlzUHJveHlSZWxlYXNlZCk7CiAgICAgICAgaWYgKHByb3AgPT09IHJlbGVhc2VQcm94eSkgewogICAgICAgICAgcmV0dXJuICgpID0+IHsKICAgICAgICAgICAgdW5yZWdpc3RlclByb3h5KHByb3h5Mik7CiAgICAgICAgICAgIHJlbGVhc2VFbmRwb2ludChlcCk7CiAgICAgICAgICAgIGlzUHJveHlSZWxlYXNlZCA9IHRydWU7CiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICBpZiAocHJvcCA9PT0gInRoZW4iKSB7CiAgICAgICAgICBpZiAocGF0aC5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgcmV0dXJuIHsgdGhlbjogKCkgPT4gcHJveHkyIH07CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCByID0gcmVxdWVzdFJlc3BvbnNlTWVzc2FnZShlcCwgewogICAgICAgICAgICB0eXBlOiAiR0VUIiwKICAgICAgICAgICAgcGF0aDogcGF0aC5tYXAoKHApID0+IHAudG9TdHJpbmcoKSkKICAgICAgICAgIH0pLnRoZW4oZnJvbVdpcmVWYWx1ZSk7CiAgICAgICAgICByZXR1cm4gci50aGVuLmJpbmQocik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBjcmVhdGVQcm94eShlcCwgWy4uLnBhdGgsIHByb3BdKTsKICAgICAgfSwKICAgICAgc2V0KF90YXJnZXQsIHByb3AsIHJhd1ZhbHVlKSB7CiAgICAgICAgdGhyb3dJZlByb3h5UmVsZWFzZWQoaXNQcm94eVJlbGVhc2VkKTsKICAgICAgICBjb25zdCBbdmFsdWUsIHRyYW5zZmVyYWJsZXNdID0gdG9XaXJlVmFsdWUocmF3VmFsdWUpOwogICAgICAgIHJldHVybiByZXF1ZXN0UmVzcG9uc2VNZXNzYWdlKGVwLCB7CiAgICAgICAgICB0eXBlOiAiU0VUIiwKICAgICAgICAgIHBhdGg6IFsuLi5wYXRoLCBwcm9wXS5tYXAoKHApID0+IHAudG9TdHJpbmcoKSksCiAgICAgICAgICB2YWx1ZQogICAgICAgIH0sIHRyYW5zZmVyYWJsZXMpLnRoZW4oZnJvbVdpcmVWYWx1ZSk7CiAgICAgIH0sCiAgICAgIGFwcGx5KF90YXJnZXQsIF90aGlzQXJnLCByYXdBcmd1bWVudExpc3QpIHsKICAgICAgICB0aHJvd0lmUHJveHlSZWxlYXNlZChpc1Byb3h5UmVsZWFzZWQpOwogICAgICAgIGNvbnN0IGxhc3QgPSBwYXRoW3BhdGgubGVuZ3RoIC0gMV07CiAgICAgICAgaWYgKGxhc3QgPT09IGNyZWF0ZUVuZHBvaW50KSB7CiAgICAgICAgICByZXR1cm4gcmVxdWVzdFJlc3BvbnNlTWVzc2FnZShlcCwgewogICAgICAgICAgICB0eXBlOiAiRU5EUE9JTlQiCiAgICAgICAgICB9KS50aGVuKGZyb21XaXJlVmFsdWUpOwogICAgICAgIH0KICAgICAgICBpZiAobGFzdCA9PT0gImJpbmQiKSB7CiAgICAgICAgICByZXR1cm4gY3JlYXRlUHJveHkoZXAsIHBhdGguc2xpY2UoMCwgLTEpKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgW2FyZ3VtZW50TGlzdCwgdHJhbnNmZXJhYmxlc10gPSBwcm9jZXNzQXJndW1lbnRzKHJhd0FyZ3VtZW50TGlzdCk7CiAgICAgICAgcmV0dXJuIHJlcXVlc3RSZXNwb25zZU1lc3NhZ2UoZXAsIHsKICAgICAgICAgIHR5cGU6ICJBUFBMWSIsCiAgICAgICAgICBwYXRoOiBwYXRoLm1hcCgocCkgPT4gcC50b1N0cmluZygpKSwKICAgICAgICAgIGFyZ3VtZW50TGlzdAogICAgICAgIH0sIHRyYW5zZmVyYWJsZXMpLnRoZW4oZnJvbVdpcmVWYWx1ZSk7CiAgICAgIH0sCiAgICAgIGNvbnN0cnVjdChfdGFyZ2V0LCByYXdBcmd1bWVudExpc3QpIHsKICAgICAgICB0aHJvd0lmUHJveHlSZWxlYXNlZChpc1Byb3h5UmVsZWFzZWQpOwogICAgICAgIGNvbnN0IFthcmd1bWVudExpc3QsIHRyYW5zZmVyYWJsZXNdID0gcHJvY2Vzc0FyZ3VtZW50cyhyYXdBcmd1bWVudExpc3QpOwogICAgICAgIHJldHVybiByZXF1ZXN0UmVzcG9uc2VNZXNzYWdlKGVwLCB7CiAgICAgICAgICB0eXBlOiAiQ09OU1RSVUNUIiwKICAgICAgICAgIHBhdGg6IHBhdGgubWFwKChwKSA9PiBwLnRvU3RyaW5nKCkpLAogICAgICAgICAgYXJndW1lbnRMaXN0CiAgICAgICAgfSwgdHJhbnNmZXJhYmxlcykudGhlbihmcm9tV2lyZVZhbHVlKTsKICAgICAgfQogICAgfSk7CiAgICByZWdpc3RlclByb3h5KHByb3h5MiwgZXApOwogICAgcmV0dXJuIHByb3h5MjsKICB9CiAgZnVuY3Rpb24gbXlGbGF0KGFycikgewogICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5jb25jYXQuYXBwbHkoW10sIGFycik7CiAgfQogIGZ1bmN0aW9uIHByb2Nlc3NBcmd1bWVudHMoYXJndW1lbnRMaXN0KSB7CiAgICBjb25zdCBwcm9jZXNzZWQgPSBhcmd1bWVudExpc3QubWFwKHRvV2lyZVZhbHVlKTsKICAgIHJldHVybiBbcHJvY2Vzc2VkLm1hcCgodikgPT4gdlswXSksIG15RmxhdChwcm9jZXNzZWQubWFwKCh2KSA9PiB2WzFdKSldOwogIH0KICBjb25zdCB0cmFuc2ZlckNhY2hlID0gLyogQF9fUFVSRV9fICovIG5ldyBXZWFrTWFwKCk7CiAgZnVuY3Rpb24gdHJhbnNmZXIob2JqLCB0cmFuc2ZlcnMpIHsKICAgIHRyYW5zZmVyQ2FjaGUuc2V0KG9iaiwgdHJhbnNmZXJzKTsKICAgIHJldHVybiBvYmo7CiAgfQogIGZ1bmN0aW9uIHByb3h5KG9iaikgewogICAgcmV0dXJuIE9iamVjdC5hc3NpZ24ob2JqLCB7IFtwcm94eU1hcmtlcl06IHRydWUgfSk7CiAgfQogIGZ1bmN0aW9uIHRvV2lyZVZhbHVlKHZhbHVlKSB7CiAgICBmb3IgKGNvbnN0IFtuYW1lLCBoYW5kbGVyXSBvZiB0cmFuc2ZlckhhbmRsZXJzKSB7CiAgICAgIGlmIChoYW5kbGVyLmNhbkhhbmRsZSh2YWx1ZSkpIHsKICAgICAgICBjb25zdCBbc2VyaWFsaXplZFZhbHVlLCB0cmFuc2ZlcmFibGVzXSA9IGhhbmRsZXIuc2VyaWFsaXplKHZhbHVlKTsKICAgICAgICByZXR1cm4gWwogICAgICAgICAgewogICAgICAgICAgICB0eXBlOiAiSEFORExFUiIsCiAgICAgICAgICAgIG5hbWUsCiAgICAgICAgICAgIHZhbHVlOiBzZXJpYWxpemVkVmFsdWUKICAgICAgICAgIH0sCiAgICAgICAgICB0cmFuc2ZlcmFibGVzCiAgICAgICAgXTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIFsKICAgICAgewogICAgICAgIHR5cGU6ICJSQVciLAogICAgICAgIHZhbHVlCiAgICAgIH0sCiAgICAgIHRyYW5zZmVyQ2FjaGUuZ2V0KHZhbHVlKSB8fCBbXQogICAgXTsKICB9CiAgZnVuY3Rpb24gZnJvbVdpcmVWYWx1ZSh2YWx1ZSkgewogICAgc3dpdGNoICh2YWx1ZS50eXBlKSB7CiAgICAgIGNhc2UgIkhBTkRMRVIiOgogICAgICAgIHJldHVybiB0cmFuc2ZlckhhbmRsZXJzLmdldCh2YWx1ZS5uYW1lKS5kZXNlcmlhbGl6ZSh2YWx1ZS52YWx1ZSk7CiAgICAgIGNhc2UgIlJBVyI6CiAgICAgICAgcmV0dXJuIHZhbHVlLnZhbHVlOwogICAgfQogIH0KICBmdW5jdGlvbiByZXF1ZXN0UmVzcG9uc2VNZXNzYWdlKGVwLCBtc2csIHRyYW5zZmVycykgewogICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7CiAgICAgIGNvbnN0IGlkID0gZ2VuZXJhdGVVVUlEKCk7CiAgICAgIGVwLmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCBmdW5jdGlvbiBsKGV2KSB7CiAgICAgICAgaWYgKCFldi5kYXRhIHx8ICFldi5kYXRhLmlkIHx8IGV2LmRhdGEuaWQgIT09IGlkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGVwLnJlbW92ZUV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCBsKTsKICAgICAgICByZXNvbHZlKGV2LmRhdGEpOwogICAgICB9KTsKICAgICAgaWYgKGVwLnN0YXJ0KSB7CiAgICAgICAgZXAuc3RhcnQoKTsKICAgICAgfQogICAgICBlcC5wb3N0TWVzc2FnZShPYmplY3QuYXNzaWduKHsgaWQgfSwgbXNnKSwgdHJhbnNmZXJzKTsKICAgIH0pOwogIH0KICBmdW5jdGlvbiBnZW5lcmF0ZVVVSUQoKSB7CiAgICByZXR1cm4gbmV3IEFycmF5KDQpLmZpbGwoMCkubWFwKCgpID0+IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIE51bWJlci5NQVhfU0FGRV9JTlRFR0VSKS50b1N0cmluZygxNikpLmpvaW4oIi0iKTsKICB9CiAgY2xhc3MgRGlzcG9zYWJsZUpTWmlwIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBfX3B1YmxpY0ZpZWxkKHRoaXMsICJ6aXAiLCBuZXcgSlNaaXAoKSk7CiAgICB9CiAgICBmaWxlKHsgbmFtZSwgZGF0YSB9KSB7CiAgICAgIHRoaXMuemlwLmZpbGUobmFtZSwgZGF0YSk7CiAgICB9CiAgICBmaWxlcyhmaWxlcykgewogICAgICBmaWxlcy5mb3JFYWNoKCh7IG5hbWUsIGRhdGEgfSkgPT4gewogICAgICAgIHRoaXMuemlwLmZpbGUobmFtZSwgZGF0YSk7CiAgICAgIH0pOwogICAgfQogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9leHBsaWNpdC1mdW5jdGlvbi1yZXR1cm4tdHlwZQogICAgYXN5bmMgdW56aXBGaWxlKHsgZGF0YSwgcGF0aCwgdHlwZSB9KSB7CiAgICAgIHZhciBfYTsKICAgICAgY29uc3QgemlwID0gYXdhaXQgSlNaaXAubG9hZEFzeW5jKGRhdGEpOwogICAgICByZXR1cm4gKF9hID0gemlwLmZpbGUocGF0aCkpID09IG51bGwgPyB2b2lkIDAgOiBfYS5hc3luYyh0eXBlKTsKICAgIH0KICAgIGFzeW5jIGdlbmVyYXRlQXN5bmMob3B0aW9ucywgb25VcGRhdGUpIHsKICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuemlwLmdlbmVyYXRlQXN5bmMoeyAuLi5vcHRpb25zLCB0eXBlOiAidWludDhhcnJheSIgfSwgb25VcGRhdGUpOwogICAgICByZXR1cm4gdHJhbnNmZXIoZGF0YSwgW2RhdGEuYnVmZmVyXSk7CiAgICB9CiAgICBnZW5lcmF0ZVN0cmVhbShvcHRpb25zLCBvblVwZGF0ZSwgb25FbmQpIHsKICAgICAgY29uc3Qgc3RyZWFtID0gdGhpcy56aXAuZ2VuZXJhdGVJbnRlcm5hbFN0cmVhbSh7IC4uLm9wdGlvbnMsIHR5cGU6ICJ1aW50OGFycmF5IiB9KTsKICAgICAgY29uc3QgemlwU3RyZWFtID0gbmV3IFJlYWRhYmxlU3RyZWFtKHsKICAgICAgICBzdGFydDogKGNvbnRyb2xsZXIpID0+IHsKICAgICAgICAgIHN0cmVhbS5vbigiZXJyb3IiLCAoZSkgPT4gewogICAgICAgICAgICBjb250cm9sbGVyLmVycm9yKGUpOwogICAgICAgICAgICBvbkVuZCA9PSBudWxsID8gdm9pZCAwIDogb25FbmQoKTsKICAgICAgICAgIH0pOwogICAgICAgICAgc3RyZWFtLm9uKCJlbmQiLCAoKSA9PiB7CiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgICAgICAgIGNvbnRyb2xsZXIuY2xvc2UoKTsKICAgICAgICAgICAgICBvbkVuZCA9PSBudWxsID8gdm9pZCAwIDogb25FbmQoKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICAgIHN0cmVhbS5vbigiZGF0YSIsIChkYXRhLCBtZXRhRGF0YSkgPT4gewogICAgICAgICAgICBjb250cm9sbGVyLmVucXVldWUoZGF0YSk7CiAgICAgICAgICAgIG9uVXBkYXRlID09IG51bGwgPyB2b2lkIDAgOiBvblVwZGF0ZShtZXRhRGF0YSk7CiAgICAgICAgICB9KTsKICAgICAgICAgIHN0cmVhbS5yZXN1bWUoKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgICByZXR1cm4gdHJhbnNmZXIoeyB6aXBTdHJlYW0gfSwgW3ppcFN0cmVhbV0pOwogICAgfQogIH0KICBleHBvc2UoRGlzcG9zYWJsZUpTWmlwKTsKfSkoKTsK";
      const decodeBase64 = (base64) => Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
      const blob = typeof window !== "undefined" && window.Blob && new Blob([decodeBase64(encodedJs)], { type: "text/javascript;charset=utf-8" });
      function WorkerWrapper(options) {
        let objURL;
        try {
          objURL = blob && (window.URL || window.webkitURL).createObjectURL(blob);
          if (!objURL)
            throw "";
          const worker = new Worker(objURL, {
            name: options == null ? void 0 : options.name
          });
          worker.addEventListener("error", () => {
            (window.URL || window.webkitURL).revokeObjectURL(objURL);
          });
          return worker;
        } catch (e) {
          return new Worker(
            "data:text/javascript;base64," + encodedJs,
            {
              name: options == null ? void 0 : options.name
            }
          );
        } finally {
          objURL && (window.URL || window.webkitURL).revokeObjectURL(objURL);
        }
      }
      const getTransferableData = (files) => files.map(({ data }) => data).filter((data) => typeof data !== "string");
      class JSZipWorkerPool {
        constructor() {
          __publicField(this, "pool", []);
          __publicField(this, "waitingQueue", []);
          __publicField(this, "unzipFile", async (params) => {
            const worker = await this.acquireWorker();
            const zip = await new worker.JSZip();
            const clean = () => {
              zip[releaseProxy]();
              this.releaseWorker(worker);
            };
            try {
              return await zip.unzipFile(transfer(params, [params.data]));
            } catch (error) {
              clean();
              throw error;
            }
          });
          for (let id = 0; id < WORKER_THREAD_NUM; id++) {
            this.pool.push({
              id,
              idle: true
            });
          }
        }
        async createWorker() {
          const worker = new WorkerWrapper();
          return wrap(worker);
        }
        waitIdleWorker() {
          return new Promise((resolve) => {
            this.waitingQueue.push(resolve);
          });
        }
        async acquireWorker() {
          let worker = this.pool.find(({ idle }) => idle);
          if (!worker)
            worker = await this.waitIdleWorker();
          if (!worker.JSZip)
            worker.JSZip = await this.createWorker();
          worker.idle = false;
          return worker;
        }
        releaseWorker(worker) {
          worker.idle = true;
          if (!this.waitingQueue.length)
            return;
          const emit = removeAt(this.waitingQueue, 0);
          emit(worker);
        }
        async generateAsync(files, options, onUpdate) {
          const worker = await this.acquireWorker();
          const zip = await new worker.JSZip();
          try {
            await zip.files(transfer(files, getTransferableData(files)));
            return await zip.generateAsync(
              options,
              proxy((metaData) => {
                if (metaData.currentFile)
                  onUpdate == null ? void 0 : onUpdate({ workerId: worker.id, ...metaData });
              })
            );
          } finally {
            zip[releaseProxy]();
            this.releaseWorker(worker);
          }
        }
        async generateStream(files, options, onUpdate) {
          const worker = await this.acquireWorker();
          const zip = await new worker.JSZip();
          try {
            await zip.files(transfer(files, getTransferableData(files)));
            const { zipStream } = await zip.generateStream(
              options,
              proxy((metaData) => {
                if (metaData.currentFile)
                  onUpdate == null ? void 0 : onUpdate({ workerId: worker.id, ...metaData });
              })
            );
            return zipStream;
          } finally {
            zip[releaseProxy]();
            this.releaseWorker(worker);
          }
        }
      }
      const jszipPool = new JSZipWorkerPool();
      class JSZip {
        constructor() {
          __publicField(this, "files", []);
        }
        file(name, data) {
          this.files.push({ name, data });
        }
        generateAsync(options, onUpdate) {
          const { files } = this;
          this.files = [];
          return jszipPool.generateAsync(files, options, onUpdate);
        }
        generateStream(options, onUpdate) {
          const { files } = this;
          this.files = [];
          return jszipPool.generateStream(files, options, onUpdate);
        }
      }
      __publicField(JSZip, "unzipFile", (params) => jszipPool.unzipFile(params));
      extendPrototype(localforage);
      class DownloadHistory {
        constructor(name) {
          __publicField(this, "store");
          __publicField(this, "ready");
          this.name = name;
          this.store = localforage.createInstance({
            name: "nhentai_helper",
            storeName: name
          });
          this.ready = this.store.ready().then(() => true).catch((e) => {
            logger.error(e);
            return false;
          });
        }
        async add(key) {
          if (!await this.ready)
            return;
          try {
            await this.store.setItem(key, true);
            logger.log(`mark "${key}" as downloaded`);
          } catch (e) {
            logger.error(e);
          }
        }
        async del(key) {
          if (!await this.ready)
            return;
          try {
            await this.store.removeItem(key);
            logger.log(`unmark "${key}" as downloaded`);
          } catch (e) {
            logger.error(e);
          }
        }
        async has(key) {
          if (!await this.ready)
            return false;
          try {
            return await this.store.getItem(key) === true;
          } catch (e) {
            logger.error(e);
          }
          return false;
        }
        async size() {
          if (!await this.ready)
            return NaN;
          return this.store.length();
        }
        async import(keys2) {
          if (!await this.ready)
            throw new Error(`store ${this.name} cannot ready`);
          try {
            await this.store.setItems(keys2.map((gid2) => ({ key: gid2, value: true })));
          } catch (e) {
            logger.error(e);
          }
        }
        async export() {
          if (!await this.ready)
            throw new Error(`store ${this.name} cannot ready`);
          return this.store.keys();
        }
        async clear() {
          if (!await this.ready)
            return;
          await this.store.clear();
        }
      }
      const gidHistory = new DownloadHistory("dl_history_gid");
      const enTitleHistory = new DownloadHistory("dl_history_en");
      const jpTitleHistory = new DownloadHistory("dl_history");
      const prettyTitleHistory = new DownloadHistory("dl_history_pretty");
      const normalizeTitle = (title) => title.replace(/\s/g, "");
      const getTitleMd5 = (title) => md5(normalizeTitle(title));
      const markAsDownloaded = (gid2, { english: english2, japanese: japanese2, pretty } = {}) => {
        void gidHistory.add(String(gid2));
        if (english2)
          void enTitleHistory.add(getTitleMd5(english2));
        if (japanese2)
          void jpTitleHistory.add(getTitleMd5(japanese2));
        if (pretty)
          void prettyTitleHistory.add(getTitleMd5(pretty));
      };
      const unmarkAsDownloaded = (gid2, { english: english2, japanese: japanese2, pretty } = {}) => {
        void gidHistory.del(String(gid2));
        if (english2)
          void enTitleHistory.del(getTitleMd5(english2));
        if (japanese2)
          void jpTitleHistory.del(getTitleMd5(japanese2));
        if (pretty)
          void prettyTitleHistory.del(getTitleMd5(pretty));
      };
      const isDownloadedByGid = (gid2) => gidHistory.has(String(gid2));
      const isDownloadedByTitle = async ({
        english: english2,
        japanese: japanese2,
        pretty
      } = {}) => {
        if (settings.judgeDownloadedByJapanese && japanese2) {
          const md5v2 = getTitleMd5(japanese2);
          if (await jpTitleHistory.has(md5v2))
            return true;
          const md5v1 = md5(japanese2);
          if (await jpTitleHistory.has(md5v1)) {
            void jpTitleHistory.add(md5v2);
            void jpTitleHistory.del(md5v1);
            return true;
          }
        }
        if (settings.judgeDownloadedByEnglish && english2 && await enTitleHistory.has(getTitleMd5(english2))) {
          return true;
        }
        if (settings.judgeDownloadedByPretty && pretty && await enTitleHistory.has(getTitleMd5(pretty))) {
          return true;
        }
        return false;
      };
      const getDownloadNumber = () => gidHistory.size();
      const EXPORT_HEADER_GID = "gid:";
      const EXPORT_HEADER_TITLE_JP = "title:";
      const EXPORT_HEADER_TITLE_EN = "title_en:";
      const EXPORT_HEADER_TITLE_PRETTY = "title_pretty:";
      const EXPORT_SEPARATOR = ",";
      const EXPORT_TEXT_FILENAME = "history.txt";
      const exportDownloadHistory = async () => {
        try {
          const gids = await gidHistory.export();
          const jpTitles = await jpTitleHistory.export();
          const enTitles = await enTitleHistory.export();
          const prettyTitles = await prettyTitleHistory.export();
          const text = `${EXPORT_HEADER_GID}${gids.join(EXPORT_SEPARATOR)}
${EXPORT_HEADER_TITLE_JP}${jpTitles.join(EXPORT_SEPARATOR)}
${EXPORT_HEADER_TITLE_EN}${enTitles.join(EXPORT_SEPARATOR)}
${EXPORT_HEADER_TITLE_PRETTY}${prettyTitles.join(EXPORT_SEPARATOR)}`;
          const zip = new JSZip();
          zip.file(EXPORT_TEXT_FILENAME, text);
          const data = await zip.generateAsync({
            compression: "DEFLATE",
            compressionOptions: { level: 9 }
          });
          const timeStr = dateTimeFormatter.format(Date.now()).replace(/[^\d]/g, "");
          const filename = `nhentai-helper-download-history-${timeStr}.zip`;
          FileSaver_minExports.saveAs(new File([data], filename, { type: "application/zip" }));
          logger.log("export download history", filename);
          return true;
        } catch (error) {
          logger.error(error);
        }
        return false;
      };
      const importDownloadHistory = async (data) => {
        try {
          const str = await JSZip.unzipFile({ data, path: EXPORT_TEXT_FILENAME, type: "string" });
          if (!str) {
            logger.error("zip doesn't contain file", EXPORT_TEXT_FILENAME);
            return false;
          }
          const lines = str.split("\n");
          for (const line of lines) {
            if (line.startsWith(EXPORT_HEADER_GID)) {
              const gids = line.replace(EXPORT_HEADER_GID, "").split(EXPORT_SEPARATOR);
              await gidHistory.import(gids);
            } else if (line.startsWith(EXPORT_HEADER_TITLE_JP)) {
              const titles = line.replace(EXPORT_HEADER_TITLE_JP, "").split(EXPORT_SEPARATOR);
              await jpTitleHistory.import(titles);
            } else if (line.startsWith(EXPORT_HEADER_TITLE_EN)) {
              const titles = line.replace(EXPORT_HEADER_TITLE_EN, "").split(EXPORT_SEPARATOR);
              await enTitleHistory.import(titles);
            } else if (line.startsWith(EXPORT_HEADER_TITLE_PRETTY)) {
              const titles = line.replace(EXPORT_HEADER_TITLE_PRETTY, "").split(EXPORT_SEPARATOR);
              await prettyTitleHistory.import(titles);
            }
          }
          return true;
        } catch (error) {
          logger.error(error);
        }
        return false;
      };
      const clearDownloadHistory = async () => {
        try {
          await gidHistory.clear();
          await enTitleHistory.clear();
          await jpTitleHistory.clear();
          await prettyTitleHistory.clear();
          return true;
        } catch (error) {
          logger.error(error);
        }
        return false;
      };
      const isSameTitleString = (title1, title2) => !!title1 && !!title2 && normalizeTitle(title1) === normalizeTitle(title2);
      const isSameTitle = (title1, title2) => {
        if (settings.judgeDownloadedByJapanese && isSameTitleString(title1.japanese, title2.japanese)) {
          return true;
        }
        if (settings.judgeDownloadedByEnglish && isSameTitleString(title1.english, title2.english)) {
          return true;
        }
        if (settings.judgeDownloadedByPretty && isSameTitleString(title1.pretty, title2.pretty)) {
          return true;
        }
        return false;
      };
      const createElement = (tag, props, ...children) => {
        if (typeof tag === "function")
          return tag(props, ...children);
        const element = document.createElement(tag);
        Object.entries(props ?? {}).forEach(([name, value]) => {
          if (name === "html")
            element.innerHTML = value;
          else if (name === "class")
            element.classList.add(...String(value).split(" "));
          else if (name === "style" && typeof value === "object") {
            const styleString = Object.entries(value).map(([k, v]) => `${camelCase(k)}:${String(v)}`).join(";");
            element.setAttribute("style", styleString);
          } else if (name.startsWith("on")) {
            element.addEventListener(kebabCase(name.replace("on", "")), value);
          } else
            element.setAttribute(name, String(value));
        });
        children.flat().forEach((child) => {
          appendChild(element, child);
        });
        return element;
      };
      const appendChild = (parent, child) => {
        if (!child)
          return;
        parent.appendChild(typeof child === "string" ? document.createTextNode(child) : child);
      };
      const Fragment = (props, ...children) => {
        return children;
      };
      const jsx = { createElement, Fragment };
      const readFile = (file) => new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => {
          resolve(reader.result);
        };
        reader.onabort = reject;
        reader.onerror = reject;
        reader.readAsArrayBuffer(file);
      });
      const pickFile = (accept) => new Promise((resolve) => {
        const input = /* @__PURE__ */ jsx.createElement(
          "input",
          {
            type: "file",
            accept,
            onChange: () => {
              var _a;
              resolve((_a = input.files) == null ? void 0 : _a[0]);
            }
          }
        );
        input.click();
      });
      const pickAndReadFile = async (accept) => {
        const file = await pickFile(accept);
        if (file)
          return readFile(file);
      };
      const showMessage = (params) => elementPlus.ElMessage({ ...params, appendTo: _monkeyWindow.document.body });
      const _hoisted_1$1 = { class: "nhentai-helper-setting-help-buttons no-sl" };
      const _hoisted_2 = ["id"];
      const _hoisted_3 = { id: "nhentai-helper-setting-dialog" };
      const _hoisted_4 = {
        class: "asterisk-example no-sl",
        style: { "margin-bottom": "18px" }
      };
      const _hoisted_5 = { class: "inline-item" };
      const _hoisted_6 = { class: "inline-item__name" };
      const _hoisted_7 = { class: "inline-item" };
      const _hoisted_8 = { class: "inline-item__name" };
      const _hoisted_9 = { style: { "color": "var(--el-text-color-regular)" } };
      const _hoisted_10 = {
        key: 0,
        class: "no-sl"
      };
      const _hoisted_11 = {
        key: 0,
        class: "no-sl"
      };
      const _hoisted_12 = { class: "no-sl" };
      const _hoisted_13 = { class: "no-sl" };
      const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
        __name: "SettingsDialog",
        setup(__props, { expose: __expose }) {
          startWatchSettings();
          const threadNumMarks = {
            1: "1",
            4: "4",
            8: "8",
            16: "16",
            32: {
              label: "32",
              style: { whiteSpace: "nowrap" }
            }
          };
          const compressionLevelMarks = {
            0: "0",
            1: "1",
            9: "9"
          };
          const { t: t2, n, locale } = useI18n();
          const show = vue.ref(false);
          const downloadedNum = vue.ref(NaN);
          const filenameLengthNumber = vue.computed({
            get: () => typeof writeableSettings.filenameLength === "number" ? writeableSettings.filenameLength : 0,
            set: (val) => {
              writeableSettings.filenameLength = val;
            }
          });
          const filenameLengthAuto = vue.computed({
            get: () => writeableSettings.filenameLength === "auto",
            set: (val) => {
              writeableSettings.filenameLength = val ? "auto" : 0;
            }
          });
          const refreshDownloadNum = async () => {
            downloadedNum.value = await getDownloadNumber();
          };
          const open2 = () => {
            show.value = true;
            refreshDownloadNum();
          };
          const openHelp = () => {
            _GM_openInTab(
              locale.value === "zh" ? "https://github.com/Tsuk1ko/nhentai-helper/blob/master/README-ZH.md#%E8%AE%BE%E7%BD%AE" : "https://github.com/Tsuk1ko/nhentai-helper/blob/master/README.md#settings",
              { active: true, setParent: true }
            );
          };
          const exporting = vue.ref(false);
          const importing = vue.ref(false);
          const clearing = vue.ref(false);
          const showMessageBySucceed = (succeed) => {
            showMessage({
              type: succeed ? "success" : "error",
              message: succeed ? "Succeed" : "Failed, please check console for error message"
            });
          };
          const exportHistory = async () => {
            exporting.value = true;
            const succeed = await exportDownloadHistory();
            exporting.value = false;
            showMessageBySucceed(succeed);
          };
          const importHistory = async () => {
            const data = await pickAndReadFile("application/zip");
            if (!data)
              return;
            importing.value = true;
            const succeed = await importDownloadHistory(data);
            importing.value = false;
            refreshDownloadNum();
            showMessageBySucceed(succeed);
          };
          const clearHistory = async () => {
            clearing.value = true;
            const succeed = await clearDownloadHistory();
            clearing.value = false;
            refreshDownloadNum();
            showMessageBySucceed(succeed);
          };
          const addTitleReplacement = () => {
            writeableSettings.titleReplacement.push({ from: "", to: "", regexp: false });
          };
          const delTitleReplacement = (index) => {
            writeableSettings.titleReplacement.splice(index, 1);
          };
          vue.watch(
            () => writeableSettings.language,
            (val) => {
              locale.value = val;
            }
          );
          __expose({ open: open2 });
          return (_ctx, _cache) => {
            return vue.openBlock(), vue.createBlock(vue.unref(elementPlus.ElDialog), {
              modelValue: show.value,
              "onUpdate:modelValue": _cache[25] || (_cache[25] = ($event) => show.value = $event),
              center: true,
              top: "50px"
            }, {
              header: vue.withCtx(({ titleId, titleClass }) => [
                vue.createElementVNode("div", _hoisted_1$1, [
                  vue.createVNode(vue.unref(elementPlus.ElButton), {
                    size: "small",
                    onClick: openHelp
                  }, {
                    default: vue.withCtx(() => [
                      vue.createTextVNode(vue.toDisplayString(vue.unref(t2)("setting.helpButton")), 1)
                    ]),
                    _: 1
                  })
                ]),
                vue.createElementVNode("span", {
                  id: titleId,
                  class: vue.normalizeClass([titleClass, "no-sl"])
                }, vue.toDisplayString(vue.unref(t2)("setting.title")), 11, _hoisted_2)
              ]),
              default: vue.withCtx(() => [
                vue.createElementVNode("div", _hoisted_3, [
                  vue.createElementVNode("div", _hoisted_4, vue.toDisplayString(vue.unref(t2)("setting.asteriskTip")), 1),
                  vue.createVNode(vue.unref(elementPlus.ElForm), {
                    "label-width": "auto",
                    "label-position": "left"
                  }, {
                    default: vue.withCtx(() => [
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), { label: "Language" }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSelect), {
                            modelValue: vue.unref(writeableSettings).language,
                            "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.unref(writeableSettings).language = $event)
                          }, {
                            default: vue.withCtx(() => [
                              vue.createVNode(vue.unref(elementPlus.ElOption), {
                                label: "English",
                                value: "en"
                              }),
                              vue.createVNode(vue.unref(elementPlus.ElOption), {
                                label: "中文",
                                value: "zh"
                              })
                            ]),
                            _: 1
                          }, 8, ["modelValue"])
                        ]),
                        _: 1
                      }),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        class: "m-b-32",
                        label: vue.unref(t2)("setting.downloadThread")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSlider), {
                            modelValue: vue.unref(writeableSettings).threadNum,
                            "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => vue.unref(writeableSettings).threadNum = $event),
                            min: 1,
                            max: 32,
                            marks: threadNumMarks
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        class: "refresh-required",
                        label: vue.unref(t2)("setting.openOnNewTab")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSwitch), {
                            modelValue: vue.unref(writeableSettings).openOnNewTab,
                            "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => vue.unref(writeableSettings).openOnNewTab = $event)
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.compressionFilename")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElInput), {
                            modelValue: vue.unref(writeableSettings).compressionFilename,
                            "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => vue.unref(writeableSettings).compressionFilename = $event),
                            placeholder: vue.unref(settingDefinitions).compressionFilename.default,
                            onBlur: _cache[4] || (_cache[4] = ($event) => {
                              if (!vue.unref(writeableSettings).compressionFilename) {
                                vue.unref(writeableSettings).compressionFilename = vue.unref(settingDefinitions).compressionFilename.default;
                              }
                            })
                          }, null, 8, ["modelValue", "placeholder"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), { label: "└ {{artist}}" }, {
                        default: vue.withCtx(() => [
                          vue.createElementVNode("div", _hoisted_5, [
                            vue.createElementVNode("span", _hoisted_6, vue.toDisplayString(vue.unref(t2)("setting.maxNumber")), 1),
                            vue.createVNode(vue.unref(elementPlus.ElInputNumber), {
                              modelValue: vue.unref(writeableSettings).filenameMaxArtistsNumber,
                              "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => vue.unref(writeableSettings).filenameMaxArtistsNumber = $event),
                              size: "small",
                              min: 0,
                              "value-on-clear": vue.unref(settingDefinitions).filenameMaxArtistsNumber.default,
                              "step-strictly": true,
                              style: { width: "90px" }
                            }, null, 8, ["modelValue", "value-on-clear"])
                          ]),
                          vue.createElementVNode("div", _hoisted_7, [
                            vue.createElementVNode("span", _hoisted_8, vue.toDisplayString(vue.unref(t2)("setting.separator")), 1),
                            vue.createVNode(vue.unref(elementPlus.ElInput), {
                              modelValue: vue.unref(writeableSettings).filenameArtistsSeparator,
                              "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => vue.unref(writeableSettings).filenameArtistsSeparator = $event),
                              size: "small",
                              placeholder: vue.unref(settingDefinitions).filenameArtistsSeparator.default,
                              style: { width: "50px" }
                            }, null, 8, ["modelValue", "placeholder"])
                          ])
                        ]),
                        _: 1
                      }),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        class: "m-b-32",
                        label: vue.unref(t2)("setting.compressionLevel")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSlider), {
                            modelValue: vue.unref(writeableSettings).compressionLevel,
                            "onUpdate:modelValue": _cache[7] || (_cache[7] = ($event) => vue.unref(writeableSettings).compressionLevel = $event),
                            min: 0,
                            max: 9,
                            marks: compressionLevelMarks
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.filenameLength")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElInputNumber), {
                            modelValue: filenameLengthNumber.value,
                            "onUpdate:modelValue": _cache[8] || (_cache[8] = ($event) => filenameLengthNumber.value = $event),
                            min: 0,
                            "value-on-clear": vue.unref(settingDefinitions).filenameLength.default,
                            "step-strictly": true,
                            disabled: vue.unref(writeableSettings).filenameLength === "auto"
                          }, null, 8, ["modelValue", "value-on-clear", "disabled"]),
                          vue.createVNode(vue.unref(elementPlus.ElCheckbox), {
                            modelValue: filenameLengthAuto.value,
                            "onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => filenameLengthAuto.value = $event),
                            class: "m-l-16",
                            label: vue.unref(t2)("common.auto")
                          }, null, 8, ["modelValue", "label"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.autoCancelDownloadedManga")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSwitch), {
                            modelValue: vue.unref(writeableSettings).autoCancelDownloadedManga,
                            "onUpdate:modelValue": _cache[10] || (_cache[10] = ($event) => vue.unref(writeableSettings).autoCancelDownloadedManga = $event)
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.autoRetryWhenErrorOccurs")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSwitch), {
                            modelValue: vue.unref(writeableSettings).autoRetryWhenErrorOccurs,
                            "onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => vue.unref(writeableSettings).autoRetryWhenErrorOccurs = $event)
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.autoShowAll")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSwitch), {
                            modelValue: vue.unref(writeableSettings).autoShowAll,
                            "onUpdate:modelValue": _cache[12] || (_cache[12] = ($event) => vue.unref(writeableSettings).autoShowAll = $event)
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        class: "refresh-required",
                        label: vue.unref(t2)("setting.showIgnoreButton")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSwitch), {
                            modelValue: vue.unref(writeableSettings).showIgnoreButton,
                            "onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => vue.unref(writeableSettings).showIgnoreButton = $event)
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.judgeDownloadedMangaByTitle")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElCheckbox), {
                            modelValue: vue.unref(writeableSettings).judgeDownloadedByEnglish,
                            "onUpdate:modelValue": _cache[14] || (_cache[14] = ($event) => vue.unref(writeableSettings).judgeDownloadedByEnglish = $event),
                            label: vue.unref(t2)("common.english")
                          }, null, 8, ["modelValue", "label"]),
                          vue.createVNode(vue.unref(elementPlus.ElCheckbox), {
                            modelValue: vue.unref(writeableSettings).judgeDownloadedByJapanese,
                            "onUpdate:modelValue": _cache[15] || (_cache[15] = ($event) => vue.unref(writeableSettings).judgeDownloadedByJapanese = $event),
                            label: vue.unref(t2)("common.japanese")
                          }, null, 8, ["modelValue", "label"]),
                          vue.createVNode(vue.unref(elementPlus.ElCheckbox), {
                            modelValue: vue.unref(writeableSettings).judgeDownloadedByPretty,
                            "onUpdate:modelValue": _cache[16] || (_cache[16] = ($event) => vue.unref(writeableSettings).judgeDownloadedByPretty = $event),
                            label: vue.unref(t2)("common.pretty")
                          }, null, 8, ["modelValue", "label"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.addMetaFile")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElCheckboxGroup), {
                            modelValue: vue.unref(writeableSettings).addMetaFile,
                            "onUpdate:modelValue": _cache[17] || (_cache[17] = ($event) => vue.unref(writeableSettings).addMetaFile = $event)
                          }, {
                            default: vue.withCtx(() => [
                              vue.createVNode(vue.unref(elementPlus.ElCheckbox), {
                                label: "ComicInfo.xml",
                                value: "ComicInfoXml"
                              }),
                              vue.createVNode(vue.unref(elementPlus.ElCheckbox), {
                                label: "info.json (eze)",
                                value: "EzeInfoJson"
                              })
                            ]),
                            _: 1
                          }, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.unref(writeableSettings).addMetaFile.includes("ComicInfoXml") ? (vue.openBlock(), vue.createBlock(vue.unref(elementPlus.ElFormItem), {
                        key: 0,
                        label: `└ ${vue.unref(t2)("setting.metaFileTitleLanguage")}`
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSelect), {
                            modelValue: vue.unref(writeableSettings).metaFileTitleLanguage,
                            "onUpdate:modelValue": _cache[18] || (_cache[18] = ($event) => vue.unref(writeableSettings).metaFileTitleLanguage = $event)
                          }, {
                            default: vue.withCtx(() => [
                              vue.createVNode(vue.unref(elementPlus.ElOption), {
                                label: vue.unref(t2)("common.english"),
                                value: "english"
                              }, null, 8, ["label"]),
                              vue.createVNode(vue.unref(elementPlus.ElOption), {
                                label: vue.unref(t2)("common.japanese"),
                                value: "japanese"
                              }, null, 8, ["label"])
                            ]),
                            _: 1
                          }, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"])) : vue.createCommentVNode("", true),
                      vue.createVNode(vue.unref(elementPlus.ElDivider), null, {
                        default: vue.withCtx(() => [
                          vue.createTextVNode(vue.toDisplayString(vue.unref(t2)("setting.advanceTitle")), 1)
                        ]),
                        _: 1
                      }),
                      vue.unref(IS_NHENTAI) ? (vue.openBlock(), vue.createBlock(vue.unref(elementPlus.ElFormItem), {
                        key: 1,
                        label: vue.unref(t2)("setting.nHentaiDownloadHost")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSelect), {
                            modelValue: vue.unref(writeableSettings).nHentaiDownloadHost,
                            "onUpdate:modelValue": _cache[19] || (_cache[19] = ($event) => vue.unref(writeableSettings).nHentaiDownloadHost = $event),
                            disabled: !!vue.unref(writeableSettings).customDownloadUrl
                          }, {
                            default: vue.withCtx(() => [
                              (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(nHentaiDownloadHosts), (host2) => {
                                return vue.openBlock(), vue.createBlock(vue.unref(elementPlus.ElOption), {
                                  key: host2,
                                  label: host2,
                                  value: host2
                                }, null, 8, ["label", "value"]);
                              }), 128)),
                              vue.createVNode(vue.unref(elementPlus.ElOption), {
                                label: vue.unref(t2)("common.random"),
                                value: "random"
                              }, null, 8, ["label"]),
                              vue.createVNode(vue.unref(elementPlus.ElOption), {
                                label: vue.unref(t2)("common.balance"),
                                value: "balance"
                              }, null, 8, ["label"])
                            ]),
                            _: 1
                          }, 8, ["modelValue", "disabled"])
                        ]),
                        _: 1
                      }, 8, ["label"])) : vue.createCommentVNode("", true),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.customDownloadUrl")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElInput), {
                            modelValue: vue.unref(writeableSettings).customDownloadUrl,
                            "onUpdate:modelValue": _cache[20] || (_cache[20] = ($event) => vue.unref(writeableSettings).customDownloadUrl = $event)
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.compressionStreamFiles")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSwitch), {
                            modelValue: vue.unref(writeableSettings).compressionStreamFiles,
                            "onUpdate:modelValue": _cache[21] || (_cache[21] = ($event) => vue.unref(writeableSettings).compressionStreamFiles = $event)
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.seriesMode")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSwitch), {
                            modelValue: vue.unref(writeableSettings).seriesMode,
                            "onUpdate:modelValue": _cache[22] || (_cache[22] = ($event) => vue.unref(writeableSettings).seriesMode = $event)
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.createVNode(vue.unref(elementPlus.ElFormItem), {
                        label: vue.unref(t2)("setting.streamDownload")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSwitch), {
                            modelValue: vue.unref(writeableSettings).streamDownload,
                            "onUpdate:modelValue": _cache[23] || (_cache[23] = ($event) => vue.unref(writeableSettings).streamDownload = $event),
                            disabled: vue.unref(DISABLE_STREAM_DOWNLOAD)
                          }, null, 8, ["modelValue", "disabled"])
                        ]),
                        _: 1
                      }, 8, ["label"]),
                      vue.unref(IS_NHENTAI) ? (vue.openBlock(), vue.createBlock(vue.unref(elementPlus.ElFormItem), {
                        key: 2,
                        class: "refresh-required",
                        label: vue.unref(t2)("setting.preventConsoleClearing")
                      }, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElSwitch), {
                            modelValue: vue.unref(writeableSettings).preventConsoleClearing,
                            "onUpdate:modelValue": _cache[24] || (_cache[24] = ($event) => vue.unref(writeableSettings).preventConsoleClearing = $event)
                          }, null, 8, ["modelValue"])
                        ]),
                        _: 1
                      }, 8, ["label"])) : vue.createCommentVNode("", true),
                      vue.createVNode(vue.unref(elementPlus.ElCollapse), null, {
                        default: vue.withCtx(() => [
                          vue.createVNode(vue.unref(elementPlus.ElCollapseItem), null, {
                            title: vue.withCtx(() => [
                              vue.createElementVNode("span", _hoisted_9, vue.toDisplayString(vue.unref(t2)("setting.titleReplacement")), 1)
                            ]),
                            default: vue.withCtx(() => [
                              vue.createVNode(vue.unref(elementPlus.ElTable), {
                                id: "title-replacement-table",
                                data: vue.unref(writeableSettings).titleReplacement
                              }, {
                                append: vue.withCtx(() => [
                                  vue.createVNode(vue.unref(elementPlus.ElButton), {
                                    text: "",
                                    style: { "width": "100%" },
                                    onClick: addTitleReplacement
                                  }, {
                                    default: vue.withCtx(() => [
                                      vue.createTextVNode("+")
                                    ]),
                                    _: 1
                                  })
                                ]),
                                default: vue.withCtx(() => [
                                  vue.createVNode(vue.unref(elementPlus.ElTableColumn), { label: "From" }, {
                                    default: vue.withCtx((scope) => [
                                      vue.createVNode(vue.unref(elementPlus.ElInput), {
                                        modelValue: scope.row.from,
                                        "onUpdate:modelValue": ($event) => scope.row.from = $event
                                      }, {
                                        prefix: vue.withCtx(() => [
                                          scope.row.regexp ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_10, "/")) : vue.createCommentVNode("", true)
                                        ]),
                                        suffix: vue.withCtx(() => [
                                          scope.row.regexp ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_11, "/")) : vue.createCommentVNode("", true)
                                        ]),
                                        _: 2
                                      }, 1032, ["modelValue", "onUpdate:modelValue"])
                                    ]),
                                    _: 1
                                  }),
                                  vue.createVNode(vue.unref(elementPlus.ElTableColumn), { label: "To" }, {
                                    default: vue.withCtx((scope) => [
                                      vue.createVNode(vue.unref(elementPlus.ElInput), {
                                        modelValue: scope.row.to,
                                        "onUpdate:modelValue": ($event) => scope.row.to = $event
                                      }, null, 8, ["modelValue", "onUpdate:modelValue"])
                                    ]),
                                    _: 1
                                  }),
                                  vue.createVNode(vue.unref(elementPlus.ElTableColumn), {
                                    label: "RegExp",
                                    width: "80"
                                  }, {
                                    default: vue.withCtx((scope) => [
                                      vue.createVNode(vue.unref(elementPlus.ElSwitch), {
                                        modelValue: scope.row.regexp,
                                        "onUpdate:modelValue": ($event) => scope.row.regexp = $event
                                      }, null, 8, ["modelValue", "onUpdate:modelValue"])
                                    ]),
                                    _: 1
                                  }),
                                  vue.createVNode(vue.unref(elementPlus.ElTableColumn), { width: "70" }, {
                                    default: vue.withCtx((scope) => [
                                      vue.createVNode(_sfc_main$2, {
                                        onConfirm: () => delTitleReplacement(scope.$index)
                                      }, {
                                        default: vue.withCtx(() => [
                                          vue.createVNode(vue.unref(elementPlus.ElButton), {
                                            type: "danger",
                                            icon: vue.unref(delete_default)
                                          }, null, 8, ["icon"])
                                        ]),
                                        _: 2
                                      }, 1032, ["onConfirm"])
                                    ]),
                                    _: 1
                                  })
                                ]),
                                _: 1
                              }, 8, ["data"])
                            ]),
                            _: 1
                          })
                        ]),
                        _: 1
                      })
                    ]),
                    _: 1
                  }),
                  vue.createVNode(vue.unref(elementPlus.ElDivider), null, {
                    default: vue.withCtx(() => [
                      vue.createTextVNode(vue.toDisplayString(vue.unref(t2)("setting.history.title")), 1)
                    ]),
                    _: 1
                  }),
                  vue.createElementVNode("p", _hoisted_12, vue.toDisplayString(vue.unref(t2)("setting.history.downloadedNumberTip", {
                    num: Number.isNaN(downloadedNum.value) ? downloadedNum.value : vue.unref(n)(downloadedNum.value)
                  })), 1),
                  vue.createVNode(vue.unref(elementPlus.ElButton), {
                    type: "primary",
                    icon: vue.unref(download_default),
                    disabled: !downloadedNum.value,
                    loading: exporting.value,
                    onClick: exportHistory
                  }, {
                    default: vue.withCtx(() => [
                      vue.createTextVNode(vue.toDisplayString(vue.unref(t2)("setting.history.export")), 1)
                    ]),
                    _: 1
                  }, 8, ["icon", "disabled", "loading"]),
                  vue.createVNode(vue.unref(elementPlus.ElButton), {
                    type: "primary",
                    icon: vue.unref(upload_default),
                    loading: importing.value,
                    onClick: importHistory
                  }, {
                    default: vue.withCtx(() => [
                      vue.createTextVNode(vue.toDisplayString(vue.unref(t2)("setting.history.import")), 1)
                    ]),
                    _: 1
                  }, 8, ["icon", "loading"]),
                  vue.createVNode(_sfc_main$2, { onConfirm: clearHistory }, {
                    default: vue.withCtx(() => [
                      vue.createVNode(vue.unref(elementPlus.ElButton), {
                        type: "danger",
                        icon: vue.unref(delete_default),
                        loading: clearing.value
                      }, {
                        default: vue.withCtx(() => [
                          vue.createTextVNode(vue.toDisplayString(vue.unref(t2)("setting.history.clear")), 1)
                        ]),
                        _: 1
                      }, 8, ["icon", "loading"])
                    ]),
                    _: 1
                  }),
                  vue.createElementVNode("p", _hoisted_13, vue.toDisplayString(vue.unref(t2)("setting.history.importTip")), 1)
                ])
              ]),
              _: 1
            }, 8, ["modelValue"]);
          };
        }
      });
      const SettingsDialog = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-35ed07a0"]]);
      const compileTemplate = (tpl) => template(tpl, { interpolate: /{{([\s\S]+?)}}/g });
      const getDownloadExt = () => {
        const ext = last(settings.compressionFilename.split("."));
        if (ext)
          return ext.toLowerCase();
        return "zip";
      };
      const getCompressionOptions = () => {
        return {
          streamFiles: settings.compressionStreamFiles,
          compression: settings.compressionLevel > 0 ? "DEFLATE" : "STORE",
          compressionOptions: { level: settings.compressionLevel }
        };
      };
      const getShowAllBtn = () => new Promise((resolve, reject) => {
        const $btn = $("#show-all-images-button");
        if ($btn.length > 0) {
          resolve($btn);
          return;
        }
        const container = document.getElementById("thumbnail-container");
        if (!container) {
          reject(new Error("Show all button not found"));
          return;
        }
        new MutationObserver((mutations, self2) => {
          mutations.forEach(({ addedNodes }) => {
            const btnContainer = addedNodes[0];
            if ((btnContainer == null ? void 0 : btnContainer.id) === "show-all-images-container") {
              self2.disconnect();
              resolve($("#show-all-images-button"));
            }
          });
        }).observe(container, { childList: true });
      });
      const createMangaDownloadInfo = (gallery2, needReactive = false) => {
        const info = {
          gallery: gallery2,
          done: 0,
          compressing: false,
          compressingPercent: "0",
          error: false
        };
        if (needReactive) {
          vue.markRaw(info.gallery);
          return vue.reactive(info);
        }
        return info;
      };
      var noty = { exports: {} };
      /* 
        @package NOTY - Dependency-free notification library 
        @version version: 3.1.4 
        @contributors https://github.com/needim/noty/graphs/contributors 
        @documentation Examples and Documentation - http://needim.github.com/noty 
        @license Licensed under the MIT licenses: http://www.opensource.org/licenses/mit-license.php 
      */
      (function(module2, exports2) {
        (function webpackUniversalModuleDefinition(root2, factory) {
          module2.exports = factory();
        })(commonjsGlobal, function() {
          return (
            /******/
            function(modules) {
              var installedModules = {};
              function __webpack_require__(moduleId) {
                if (installedModules[moduleId]) {
                  return installedModules[moduleId].exports;
                }
                var module22 = installedModules[moduleId] = {
                  /******/
                  i: moduleId,
                  /******/
                  l: false,
                  /******/
                  exports: {}
                  /******/
                };
                modules[moduleId].call(module22.exports, module22, module22.exports, __webpack_require__);
                module22.l = true;
                return module22.exports;
              }
              __webpack_require__.m = modules;
              __webpack_require__.c = installedModules;
              __webpack_require__.i = function(value) {
                return value;
              };
              __webpack_require__.d = function(exports22, name, getter) {
                if (!__webpack_require__.o(exports22, name)) {
                  Object.defineProperty(exports22, name, {
                    /******/
                    configurable: false,
                    /******/
                    enumerable: true,
                    /******/
                    get: getter
                    /******/
                  });
                }
              };
              __webpack_require__.n = function(module22) {
                var getter = module22 && module22.__esModule ? (
                  /******/
                  function getDefault() {
                    return module22["default"];
                  }
                ) : (
                  /******/
                  function getModuleExports() {
                    return module22;
                  }
                );
                __webpack_require__.d(getter, "a", getter);
                return getter;
              };
              __webpack_require__.o = function(object, property2) {
                return Object.prototype.hasOwnProperty.call(object, property2);
              };
              __webpack_require__.p = "";
              return __webpack_require__(__webpack_require__.s = 6);
            }([
              /* 0 */
              /***/
              function(module22, exports22, __webpack_require__) {
                Object.defineProperty(exports22, "__esModule", {
                  value: true
                });
                exports22.css = exports22.deepExtend = exports22.animationEndEvents = void 0;
                var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
                  return typeof obj;
                } : function(obj) {
                  return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
                };
                exports22.inArray = inArray;
                exports22.stopPropagation = stopPropagation;
                exports22.generateID = generateID;
                exports22.outerHeight = outerHeight;
                exports22.addListener = addListener;
                exports22.hasClass = hasClass;
                exports22.addClass = addClass;
                exports22.removeClass = removeClass;
                exports22.remove = remove;
                exports22.classList = classList;
                exports22.visibilityChangeFlow = visibilityChangeFlow;
                exports22.createAudioElements = createAudioElements;
                var _api = __webpack_require__(1);
                var API = _interopRequireWildcard(_api);
                function _interopRequireWildcard(obj) {
                  if (obj && obj.__esModule) {
                    return obj;
                  } else {
                    var newObj = {};
                    if (obj != null) {
                      for (var key in obj) {
                        if (Object.prototype.hasOwnProperty.call(obj, key))
                          newObj[key] = obj[key];
                      }
                    }
                    newObj.default = obj;
                    return newObj;
                  }
                }
                exports22.animationEndEvents = "webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend";
                function inArray(needle, haystack, argStrict) {
                  var key = void 0;
                  var strict = !!argStrict;
                  if (strict) {
                    for (key in haystack) {
                      if (haystack.hasOwnProperty(key) && haystack[key] === needle) {
                        return true;
                      }
                    }
                  } else {
                    for (key in haystack) {
                      if (haystack.hasOwnProperty(key) && haystack[key] === needle) {
                        return true;
                      }
                    }
                  }
                  return false;
                }
                function stopPropagation(evt) {
                  evt = evt || window.event;
                  if (typeof evt.stopPropagation !== "undefined") {
                    evt.stopPropagation();
                  } else {
                    evt.cancelBubble = true;
                  }
                }
                exports22.deepExtend = function deepExtend2(out) {
                  out = out || {};
                  for (var i = 1; i < arguments.length; i++) {
                    var obj = arguments[i];
                    if (!obj)
                      continue;
                    for (var key in obj) {
                      if (obj.hasOwnProperty(key)) {
                        if (Array.isArray(obj[key])) {
                          out[key] = obj[key];
                        } else if (_typeof(obj[key]) === "object" && obj[key] !== null) {
                          out[key] = deepExtend2(out[key], obj[key]);
                        } else {
                          out[key] = obj[key];
                        }
                      }
                    }
                  }
                  return out;
                };
                function generateID() {
                  var prefix = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "";
                  var id = "noty_" + prefix + "_";
                  id += "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
                    var r = Math.random() * 16 | 0;
                    var v = c === "x" ? r : r & 3 | 8;
                    return v.toString(16);
                  });
                  return id;
                }
                function outerHeight(el) {
                  var height = el.offsetHeight;
                  var style = window.getComputedStyle(el);
                  height += parseInt(style.marginTop) + parseInt(style.marginBottom);
                  return height;
                }
                exports22.css = /* @__PURE__ */ function() {
                  var cssPrefixes = ["Webkit", "O", "Moz", "ms"];
                  var cssProps = {};
                  function camelCase2(string) {
                    return string.replace(/^-ms-/, "ms-").replace(/-([\da-z])/gi, function(match2, letter) {
                      return letter.toUpperCase();
                    });
                  }
                  function getVendorProp(name) {
                    var style = document.body.style;
                    if (name in style)
                      return name;
                    var i = cssPrefixes.length;
                    var capName = name.charAt(0).toUpperCase() + name.slice(1);
                    var vendorName = void 0;
                    while (i--) {
                      vendorName = cssPrefixes[i] + capName;
                      if (vendorName in style)
                        return vendorName;
                    }
                    return name;
                  }
                  function getStyleProp(name) {
                    name = camelCase2(name);
                    return cssProps[name] || (cssProps[name] = getVendorProp(name));
                  }
                  function applyCss(element, prop, value) {
                    prop = getStyleProp(prop);
                    element.style[prop] = value;
                  }
                  return function(element, properties) {
                    var args = arguments;
                    var prop = void 0;
                    var value = void 0;
                    if (args.length === 2) {
                      for (prop in properties) {
                        if (properties.hasOwnProperty(prop)) {
                          value = properties[prop];
                          if (value !== void 0 && properties.hasOwnProperty(prop)) {
                            applyCss(element, prop, value);
                          }
                        }
                      }
                    } else {
                      applyCss(element, args[1], args[2]);
                    }
                  };
                }();
                function addListener(el, events, cb) {
                  var useCapture = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : false;
                  events = events.split(" ");
                  for (var i = 0; i < events.length; i++) {
                    if (document.addEventListener) {
                      el.addEventListener(events[i], cb, useCapture);
                    } else if (document.attachEvent) {
                      el.attachEvent("on" + events[i], cb);
                    }
                  }
                }
                function hasClass(element, name) {
                  var list = typeof element === "string" ? element : classList(element);
                  return list.indexOf(" " + name + " ") >= 0;
                }
                function addClass(element, name) {
                  var oldList = classList(element);
                  var newList = oldList + name;
                  if (hasClass(oldList, name))
                    return;
                  element.className = newList.substring(1);
                }
                function removeClass(element, name) {
                  var oldList = classList(element);
                  var newList = void 0;
                  if (!hasClass(element, name))
                    return;
                  newList = oldList.replace(" " + name + " ", " ");
                  element.className = newList.substring(1, newList.length - 1);
                }
                function remove(element) {
                  if (element.parentNode) {
                    element.parentNode.removeChild(element);
                  }
                }
                function classList(element) {
                  return (" " + (element && element.className || "") + " ").replace(/\s+/gi, " ");
                }
                function visibilityChangeFlow() {
                  var hidden = void 0;
                  var visibilityChange = void 0;
                  if (typeof document.hidden !== "undefined") {
                    hidden = "hidden";
                    visibilityChange = "visibilitychange";
                  } else if (typeof document.msHidden !== "undefined") {
                    hidden = "msHidden";
                    visibilityChange = "msvisibilitychange";
                  } else if (typeof document.webkitHidden !== "undefined") {
                    hidden = "webkitHidden";
                    visibilityChange = "webkitvisibilitychange";
                  }
                  function onVisibilityChange() {
                    API.PageHidden = document[hidden];
                    handleVisibilityChange();
                  }
                  function onBlur() {
                    API.PageHidden = true;
                    handleVisibilityChange();
                  }
                  function onFocus() {
                    API.PageHidden = false;
                    handleVisibilityChange();
                  }
                  function handleVisibilityChange() {
                    if (API.PageHidden)
                      stopAll();
                    else
                      resumeAll();
                  }
                  function stopAll() {
                    setTimeout(function() {
                      Object.keys(API.Store).forEach(function(id) {
                        if (API.Store.hasOwnProperty(id)) {
                          if (API.Store[id].options.visibilityControl) {
                            API.Store[id].stop();
                          }
                        }
                      });
                    }, 100);
                  }
                  function resumeAll() {
                    setTimeout(function() {
                      Object.keys(API.Store).forEach(function(id) {
                        if (API.Store.hasOwnProperty(id)) {
                          if (API.Store[id].options.visibilityControl) {
                            API.Store[id].resume();
                          }
                        }
                      });
                      API.queueRenderAll();
                    }, 100);
                  }
                  if (visibilityChange) {
                    addListener(document, visibilityChange, onVisibilityChange);
                  }
                  addListener(window, "blur", onBlur);
                  addListener(window, "focus", onFocus);
                }
                function createAudioElements(ref2) {
                  if (ref2.hasSound) {
                    var audioElement = document.createElement("audio");
                    ref2.options.sounds.sources.forEach(function(s) {
                      var source = document.createElement("source");
                      source.src = s;
                      source.type = "audio/" + getExtension(s);
                      audioElement.appendChild(source);
                    });
                    if (ref2.barDom) {
                      ref2.barDom.appendChild(audioElement);
                    } else {
                      document.querySelector("body").appendChild(audioElement);
                    }
                    audioElement.volume = ref2.options.sounds.volume;
                    if (!ref2.soundPlayed) {
                      audioElement.play();
                      ref2.soundPlayed = true;
                    }
                    audioElement.onended = function() {
                      remove(audioElement);
                    };
                  }
                }
                function getExtension(fileName) {
                  return fileName.match(/\.([^.]+)$/)[1];
                }
              },
              /* 1 */
              /***/
              function(module22, exports22, __webpack_require__) {
                Object.defineProperty(exports22, "__esModule", {
                  value: true
                });
                exports22.Defaults = exports22.Store = exports22.Queues = exports22.DefaultMaxVisible = exports22.docTitle = exports22.DocModalCount = exports22.PageHidden = void 0;
                exports22.getQueueCounts = getQueueCounts;
                exports22.addToQueue = addToQueue;
                exports22.removeFromQueue = removeFromQueue;
                exports22.queueRender = queueRender;
                exports22.queueRenderAll = queueRenderAll;
                exports22.ghostFix = ghostFix;
                exports22.build = build;
                exports22.hasButtons = hasButtons;
                exports22.handleModal = handleModal;
                exports22.handleModalClose = handleModalClose;
                exports22.queueClose = queueClose;
                exports22.dequeueClose = dequeueClose;
                exports22.fire = fire;
                exports22.openFlow = openFlow;
                exports22.closeFlow = closeFlow;
                var _utils = __webpack_require__(0);
                var Utils = _interopRequireWildcard(_utils);
                function _interopRequireWildcard(obj) {
                  if (obj && obj.__esModule) {
                    return obj;
                  } else {
                    var newObj = {};
                    if (obj != null) {
                      for (var key in obj) {
                        if (Object.prototype.hasOwnProperty.call(obj, key))
                          newObj[key] = obj[key];
                      }
                    }
                    newObj.default = obj;
                    return newObj;
                  }
                }
                exports22.PageHidden = false;
                var DocModalCount = exports22.DocModalCount = 0;
                var DocTitleProps = {
                  originalTitle: null,
                  count: 0,
                  changed: false,
                  timer: -1
                };
                var docTitle = exports22.docTitle = {
                  increment: function increment() {
                    DocTitleProps.count++;
                    docTitle._update();
                  },
                  decrement: function decrement() {
                    DocTitleProps.count--;
                    if (DocTitleProps.count <= 0) {
                      docTitle._clear();
                      return;
                    }
                    docTitle._update();
                  },
                  _update: function _update() {
                    var title = document.title;
                    if (!DocTitleProps.changed) {
                      DocTitleProps.originalTitle = title;
                      document.title = "(" + DocTitleProps.count + ") " + title;
                      DocTitleProps.changed = true;
                    } else {
                      document.title = "(" + DocTitleProps.count + ") " + DocTitleProps.originalTitle;
                    }
                  },
                  _clear: function _clear() {
                    if (DocTitleProps.changed) {
                      DocTitleProps.count = 0;
                      document.title = DocTitleProps.originalTitle;
                      DocTitleProps.changed = false;
                    }
                  }
                };
                var DefaultMaxVisible = exports22.DefaultMaxVisible = 5;
                var Queues = exports22.Queues = {
                  global: {
                    maxVisible: DefaultMaxVisible,
                    queue: []
                  }
                };
                var Store = exports22.Store = {};
                exports22.Defaults = {
                  type: "alert",
                  layout: "topRight",
                  theme: "mint",
                  text: "",
                  timeout: false,
                  progressBar: true,
                  closeWith: ["click"],
                  animation: {
                    open: "noty_effects_open",
                    close: "noty_effects_close"
                  },
                  id: false,
                  force: false,
                  killer: false,
                  queue: "global",
                  container: false,
                  buttons: [],
                  callbacks: {
                    beforeShow: null,
                    onShow: null,
                    afterShow: null,
                    onClose: null,
                    afterClose: null,
                    onClick: null,
                    onHover: null,
                    onTemplate: null
                  },
                  sounds: {
                    sources: [],
                    volume: 1,
                    conditions: []
                  },
                  titleCount: {
                    conditions: []
                  },
                  modal: false,
                  visibilityControl: false
                  /**
                   * @param {string} queueName
                   * @return {object}
                   */
                };
                function getQueueCounts() {
                  var queueName = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "global";
                  var count = 0;
                  var max = DefaultMaxVisible;
                  if (Queues.hasOwnProperty(queueName)) {
                    max = Queues[queueName].maxVisible;
                    Object.keys(Store).forEach(function(i) {
                      if (Store[i].options.queue === queueName && !Store[i].closed)
                        count++;
                    });
                  }
                  return {
                    current: count,
                    maxVisible: max
                  };
                }
                function addToQueue(ref2) {
                  if (!Queues.hasOwnProperty(ref2.options.queue)) {
                    Queues[ref2.options.queue] = { maxVisible: DefaultMaxVisible, queue: [] };
                  }
                  Queues[ref2.options.queue].queue.push(ref2);
                }
                function removeFromQueue(ref2) {
                  if (Queues.hasOwnProperty(ref2.options.queue)) {
                    var queue = [];
                    Object.keys(Queues[ref2.options.queue].queue).forEach(function(i) {
                      if (Queues[ref2.options.queue].queue[i].id !== ref2.id) {
                        queue.push(Queues[ref2.options.queue].queue[i]);
                      }
                    });
                    Queues[ref2.options.queue].queue = queue;
                  }
                }
                function queueRender() {
                  var queueName = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "global";
                  if (Queues.hasOwnProperty(queueName)) {
                    var noty2 = Queues[queueName].queue.shift();
                    if (noty2)
                      noty2.show();
                  }
                }
                function queueRenderAll() {
                  Object.keys(Queues).forEach(function(queueName) {
                    queueRender(queueName);
                  });
                }
                function ghostFix(ref2) {
                  var ghostID = Utils.generateID("ghost");
                  var ghost = document.createElement("div");
                  ghost.setAttribute("id", ghostID);
                  Utils.css(ghost, {
                    height: Utils.outerHeight(ref2.barDom) + "px"
                  });
                  ref2.barDom.insertAdjacentHTML("afterend", ghost.outerHTML);
                  Utils.remove(ref2.barDom);
                  ghost = document.getElementById(ghostID);
                  Utils.addClass(ghost, "noty_fix_effects_height");
                  Utils.addListener(ghost, Utils.animationEndEvents, function() {
                    Utils.remove(ghost);
                  });
                }
                function build(ref2) {
                  findOrCreateContainer(ref2);
                  var markup = '<div class="noty_body">' + ref2.options.text + "</div>" + buildButtons(ref2) + '<div class="noty_progressbar"></div>';
                  ref2.barDom = document.createElement("div");
                  ref2.barDom.setAttribute("id", ref2.id);
                  Utils.addClass(ref2.barDom, "noty_bar noty_type__" + ref2.options.type + " noty_theme__" + ref2.options.theme);
                  ref2.barDom.innerHTML = markup;
                  fire(ref2, "onTemplate");
                }
                function hasButtons(ref2) {
                  return !!(ref2.options.buttons && Object.keys(ref2.options.buttons).length);
                }
                function buildButtons(ref2) {
                  if (hasButtons(ref2)) {
                    var buttons = document.createElement("div");
                    Utils.addClass(buttons, "noty_buttons");
                    Object.keys(ref2.options.buttons).forEach(function(key) {
                      buttons.appendChild(ref2.options.buttons[key].dom);
                    });
                    ref2.options.buttons.forEach(function(btn) {
                      buttons.appendChild(btn.dom);
                    });
                    return buttons.outerHTML;
                  }
                  return "";
                }
                function handleModal(ref2) {
                  if (ref2.options.modal) {
                    if (DocModalCount === 0) {
                      createModal();
                    }
                    exports22.DocModalCount = DocModalCount += 1;
                  }
                }
                function handleModalClose(ref2) {
                  if (ref2.options.modal && DocModalCount > 0) {
                    exports22.DocModalCount = DocModalCount -= 1;
                    if (DocModalCount <= 0) {
                      var modal = document.querySelector(".noty_modal");
                      if (modal) {
                        Utils.removeClass(modal, "noty_modal_open");
                        Utils.addClass(modal, "noty_modal_close");
                        Utils.addListener(modal, Utils.animationEndEvents, function() {
                          Utils.remove(modal);
                        });
                      }
                    }
                  }
                }
                function createModal() {
                  var body = document.querySelector("body");
                  var modal = document.createElement("div");
                  Utils.addClass(modal, "noty_modal");
                  body.insertBefore(modal, body.firstChild);
                  Utils.addClass(modal, "noty_modal_open");
                  Utils.addListener(modal, Utils.animationEndEvents, function() {
                    Utils.removeClass(modal, "noty_modal_open");
                  });
                }
                function findOrCreateContainer(ref2) {
                  if (ref2.options.container) {
                    ref2.layoutDom = document.querySelector(ref2.options.container);
                    return;
                  }
                  var layoutID = "noty_layout__" + ref2.options.layout;
                  ref2.layoutDom = document.querySelector("div#" + layoutID);
                  if (!ref2.layoutDom) {
                    ref2.layoutDom = document.createElement("div");
                    ref2.layoutDom.setAttribute("id", layoutID);
                    ref2.layoutDom.setAttribute("role", "alert");
                    ref2.layoutDom.setAttribute("aria-live", "polite");
                    Utils.addClass(ref2.layoutDom, "noty_layout");
                    document.querySelector("body").appendChild(ref2.layoutDom);
                  }
                }
                function queueClose(ref2) {
                  if (ref2.options.timeout) {
                    if (ref2.options.progressBar && ref2.progressDom) {
                      Utils.css(ref2.progressDom, {
                        transition: "width " + ref2.options.timeout + "ms linear",
                        width: "0%"
                      });
                    }
                    clearTimeout(ref2.closeTimer);
                    ref2.closeTimer = setTimeout(function() {
                      ref2.close();
                    }, ref2.options.timeout);
                  }
                }
                function dequeueClose(ref2) {
                  if (ref2.options.timeout && ref2.closeTimer) {
                    clearTimeout(ref2.closeTimer);
                    ref2.closeTimer = -1;
                    if (ref2.options.progressBar && ref2.progressDom) {
                      Utils.css(ref2.progressDom, {
                        transition: "width 0ms linear",
                        width: "100%"
                      });
                    }
                  }
                }
                function fire(ref2, eventName) {
                  if (ref2.listeners.hasOwnProperty(eventName)) {
                    ref2.listeners[eventName].forEach(function(cb) {
                      if (typeof cb === "function") {
                        cb.apply(ref2);
                      }
                    });
                  }
                }
                function openFlow(ref2) {
                  fire(ref2, "afterShow");
                  queueClose(ref2);
                  Utils.addListener(ref2.barDom, "mouseenter", function() {
                    dequeueClose(ref2);
                  });
                  Utils.addListener(ref2.barDom, "mouseleave", function() {
                    queueClose(ref2);
                  });
                }
                function closeFlow(ref2) {
                  delete Store[ref2.id];
                  ref2.closing = false;
                  fire(ref2, "afterClose");
                  Utils.remove(ref2.barDom);
                  if (ref2.layoutDom.querySelectorAll(".noty_bar").length === 0 && !ref2.options.container) {
                    Utils.remove(ref2.layoutDom);
                  }
                  if (Utils.inArray("docVisible", ref2.options.titleCount.conditions) || Utils.inArray("docHidden", ref2.options.titleCount.conditions)) {
                    docTitle.decrement();
                  }
                  queueRender(ref2.options.queue);
                }
              },
              /* 2 */
              /***/
              function(module22, exports22, __webpack_require__) {
                Object.defineProperty(exports22, "__esModule", {
                  value: true
                });
                exports22.NotyButton = void 0;
                var _utils = __webpack_require__(0);
                var Utils = _interopRequireWildcard(_utils);
                function _interopRequireWildcard(obj) {
                  if (obj && obj.__esModule) {
                    return obj;
                  } else {
                    var newObj = {};
                    if (obj != null) {
                      for (var key in obj) {
                        if (Object.prototype.hasOwnProperty.call(obj, key))
                          newObj[key] = obj[key];
                      }
                    }
                    newObj.default = obj;
                    return newObj;
                  }
                }
                function _classCallCheck(instance, Constructor) {
                  if (!(instance instanceof Constructor)) {
                    throw new TypeError("Cannot call a class as a function");
                  }
                }
                exports22.NotyButton = function NotyButton2(html2, classes, cb) {
                  var _this = this;
                  var attributes = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : {};
                  _classCallCheck(this, NotyButton2);
                  this.dom = document.createElement("button");
                  this.dom.innerHTML = html2;
                  this.id = attributes.id = attributes.id || Utils.generateID("button");
                  this.cb = cb;
                  Object.keys(attributes).forEach(function(propertyName) {
                    _this.dom.setAttribute(propertyName, attributes[propertyName]);
                  });
                  Utils.addClass(this.dom, classes || "noty_btn");
                  return this;
                };
              },
              /* 3 */
              /***/
              function(module22, exports22, __webpack_require__) {
                Object.defineProperty(exports22, "__esModule", {
                  value: true
                });
                var _createClass = /* @__PURE__ */ function() {
                  function defineProperties(target, props) {
                    for (var i = 0; i < props.length; i++) {
                      var descriptor = props[i];
                      descriptor.enumerable = descriptor.enumerable || false;
                      descriptor.configurable = true;
                      if ("value" in descriptor)
                        descriptor.writable = true;
                      Object.defineProperty(target, descriptor.key, descriptor);
                    }
                  }
                  return function(Constructor, protoProps, staticProps) {
                    if (protoProps)
                      defineProperties(Constructor.prototype, protoProps);
                    if (staticProps)
                      defineProperties(Constructor, staticProps);
                    return Constructor;
                  };
                }();
                function _classCallCheck(instance, Constructor) {
                  if (!(instance instanceof Constructor)) {
                    throw new TypeError("Cannot call a class as a function");
                  }
                }
                exports22.Push = function() {
                  function Push2() {
                    var workerPath = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "/service-worker.js";
                    _classCallCheck(this, Push2);
                    this.subData = {};
                    this.workerPath = workerPath;
                    this.listeners = {
                      onPermissionGranted: [],
                      onPermissionDenied: [],
                      onSubscriptionSuccess: [],
                      onSubscriptionCancel: [],
                      onWorkerError: [],
                      onWorkerSuccess: [],
                      onWorkerNotSupported: []
                    };
                    return this;
                  }
                  _createClass(Push2, [{
                    key: "on",
                    value: function on(eventName) {
                      var cb = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : function() {
                      };
                      if (typeof cb === "function" && this.listeners.hasOwnProperty(eventName)) {
                        this.listeners[eventName].push(cb);
                      }
                      return this;
                    }
                  }, {
                    key: "fire",
                    value: function fire(eventName) {
                      var _this = this;
                      var params = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : [];
                      if (this.listeners.hasOwnProperty(eventName)) {
                        this.listeners[eventName].forEach(function(cb) {
                          if (typeof cb === "function") {
                            cb.apply(_this, params);
                          }
                        });
                      }
                    }
                  }, {
                    key: "create",
                    value: function create() {
                      console.log("NOT IMPLEMENTED YET");
                    }
                    /**
                     * @return {boolean}
                     */
                  }, {
                    key: "isSupported",
                    value: function isSupported() {
                      var result = false;
                      try {
                        result = window.Notification || window.webkitNotifications || navigator.mozNotification || window.external && window.external.msIsSiteMode() !== void 0;
                      } catch (e) {
                      }
                      return result;
                    }
                    /**
                     * @return {string}
                     */
                  }, {
                    key: "getPermissionStatus",
                    value: function getPermissionStatus() {
                      var perm = "default";
                      if (window.Notification && window.Notification.permissionLevel) {
                        perm = window.Notification.permissionLevel;
                      } else if (window.webkitNotifications && window.webkitNotifications.checkPermission) {
                        switch (window.webkitNotifications.checkPermission()) {
                          case 1:
                            perm = "default";
                            break;
                          case 0:
                            perm = "granted";
                            break;
                          default:
                            perm = "denied";
                        }
                      } else if (window.Notification && window.Notification.permission) {
                        perm = window.Notification.permission;
                      } else if (navigator.mozNotification) {
                        perm = "granted";
                      } else if (window.external && window.external.msIsSiteMode() !== void 0) {
                        perm = window.external.msIsSiteMode() ? "granted" : "default";
                      }
                      return perm.toString().toLowerCase();
                    }
                    /**
                     * @return {string}
                     */
                  }, {
                    key: "getEndpoint",
                    value: function getEndpoint(subscription) {
                      var endpoint = subscription.endpoint;
                      var subscriptionId = subscription.subscriptionId;
                      if (subscriptionId && endpoint.indexOf(subscriptionId) === -1) {
                        endpoint += "/" + subscriptionId;
                      }
                      return endpoint;
                    }
                    /**
                     * @return {boolean}
                     */
                  }, {
                    key: "isSWRegistered",
                    value: function isSWRegistered() {
                      try {
                        return navigator.serviceWorker.controller.state === "activated";
                      } catch (e) {
                        return false;
                      }
                    }
                    /**
                     * @return {void}
                     */
                  }, {
                    key: "unregisterWorker",
                    value: function unregisterWorker() {
                      var self2 = this;
                      if ("serviceWorker" in navigator) {
                        navigator.serviceWorker.getRegistrations().then(function(registrations) {
                          var _iteratorNormalCompletion = true;
                          var _didIteratorError = false;
                          var _iteratorError = void 0;
                          try {
                            for (var _iterator = registrations[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                              var registration = _step.value;
                              registration.unregister();
                              self2.fire("onSubscriptionCancel");
                            }
                          } catch (err) {
                            _didIteratorError = true;
                            _iteratorError = err;
                          } finally {
                            try {
                              if (!_iteratorNormalCompletion && _iterator.return) {
                                _iterator.return();
                              }
                            } finally {
                              if (_didIteratorError) {
                                throw _iteratorError;
                              }
                            }
                          }
                        });
                      }
                    }
                    /**
                     * @return {void}
                     */
                  }, {
                    key: "requestSubscription",
                    value: function requestSubscription() {
                      var _this2 = this;
                      var userVisibleOnly = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true;
                      var self2 = this;
                      var current = this.getPermissionStatus();
                      var cb = function cb2(result) {
                        if (result === "granted") {
                          _this2.fire("onPermissionGranted");
                          if ("serviceWorker" in navigator) {
                            navigator.serviceWorker.register(_this2.workerPath).then(function() {
                              navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
                                self2.fire("onWorkerSuccess");
                                serviceWorkerRegistration.pushManager.subscribe({
                                  userVisibleOnly
                                }).then(function(subscription) {
                                  var key = subscription.getKey("p256dh");
                                  var token = subscription.getKey("auth");
                                  self2.subData = {
                                    endpoint: self2.getEndpoint(subscription),
                                    p256dh: key ? window.btoa(String.fromCharCode.apply(null, new Uint8Array(key))) : null,
                                    auth: token ? window.btoa(String.fromCharCode.apply(null, new Uint8Array(token))) : null
                                  };
                                  self2.fire("onSubscriptionSuccess", [self2.subData]);
                                }).catch(function(err) {
                                  self2.fire("onWorkerError", [err]);
                                });
                              });
                            });
                          } else {
                            self2.fire("onWorkerNotSupported");
                          }
                        } else if (result === "denied") {
                          _this2.fire("onPermissionDenied");
                          _this2.unregisterWorker();
                        }
                      };
                      if (current === "default") {
                        if (window.Notification && window.Notification.requestPermission) {
                          window.Notification.requestPermission(cb);
                        } else if (window.webkitNotifications && window.webkitNotifications.checkPermission) {
                          window.webkitNotifications.requestPermission(cb);
                        }
                      } else {
                        cb(current);
                      }
                    }
                  }]);
                  return Push2;
                }();
              },
              /* 4 */
              /***/
              function(module22, exports22, __webpack_require__) {
                (function(process2, global2) {
                  var require2;
                  /*!
                  * @overview es6-promise - a tiny implementation of Promises/A+.
                  * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
                  * @license   Licensed under MIT license
                  *            See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
                  * @version   4.1.1
                  */
                  (function(global22, factory) {
                    module22.exports = factory();
                  })(this, function() {
                    function objectOrFunction(x) {
                      var type = typeof x;
                      return x !== null && (type === "object" || type === "function");
                    }
                    function isFunction2(x) {
                      return typeof x === "function";
                    }
                    var _isArray = void 0;
                    if (Array.isArray) {
                      _isArray = Array.isArray;
                    } else {
                      _isArray = function(x) {
                        return Object.prototype.toString.call(x) === "[object Array]";
                      };
                    }
                    var isArray2 = _isArray;
                    var len = 0;
                    var vertxNext = void 0;
                    var customSchedulerFn = void 0;
                    var asap = function asap2(callback, arg) {
                      queue[len] = callback;
                      queue[len + 1] = arg;
                      len += 2;
                      if (len === 2) {
                        if (customSchedulerFn) {
                          customSchedulerFn(flush);
                        } else {
                          scheduleFlush();
                        }
                      }
                    };
                    function setScheduler(scheduleFn) {
                      customSchedulerFn = scheduleFn;
                    }
                    function setAsap(asapFn) {
                      asap = asapFn;
                    }
                    var browserWindow = typeof window !== "undefined" ? window : void 0;
                    var browserGlobal = browserWindow || {};
                    var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
                    var isNode = typeof self === "undefined" && typeof process2 !== "undefined" && {}.toString.call(process2) === "[object process]";
                    var isWorker = typeof Uint8ClampedArray !== "undefined" && typeof importScripts !== "undefined" && typeof MessageChannel !== "undefined";
                    function useNextTick() {
                      return function() {
                        return process2.nextTick(flush);
                      };
                    }
                    function useVertxTimer() {
                      if (typeof vertxNext !== "undefined") {
                        return function() {
                          vertxNext(flush);
                        };
                      }
                      return useSetTimeout();
                    }
                    function useMutationObserver() {
                      var iterations = 0;
                      var observer = new BrowserMutationObserver(flush);
                      var node = document.createTextNode("");
                      observer.observe(node, { characterData: true });
                      return function() {
                        node.data = iterations = ++iterations % 2;
                      };
                    }
                    function useMessageChannel() {
                      var channel = new MessageChannel();
                      channel.port1.onmessage = flush;
                      return function() {
                        return channel.port2.postMessage(0);
                      };
                    }
                    function useSetTimeout() {
                      var globalSetTimeout = setTimeout;
                      return function() {
                        return globalSetTimeout(flush, 1);
                      };
                    }
                    var queue = new Array(1e3);
                    function flush() {
                      for (var i = 0; i < len; i += 2) {
                        var callback = queue[i];
                        var arg = queue[i + 1];
                        callback(arg);
                        queue[i] = void 0;
                        queue[i + 1] = void 0;
                      }
                      len = 0;
                    }
                    function attemptVertx() {
                      try {
                        var r = require2;
                        var vertx = __webpack_require__(9);
                        vertxNext = vertx.runOnLoop || vertx.runOnContext;
                        return useVertxTimer();
                      } catch (e) {
                        return useSetTimeout();
                      }
                    }
                    var scheduleFlush = void 0;
                    if (isNode) {
                      scheduleFlush = useNextTick();
                    } else if (BrowserMutationObserver) {
                      scheduleFlush = useMutationObserver();
                    } else if (isWorker) {
                      scheduleFlush = useMessageChannel();
                    } else if (browserWindow === void 0 && true) {
                      scheduleFlush = attemptVertx();
                    } else {
                      scheduleFlush = useSetTimeout();
                    }
                    function then(onFulfillment, onRejection) {
                      var _arguments = arguments;
                      var parent = this;
                      var child = new this.constructor(noop2);
                      if (child[PROMISE_ID] === void 0) {
                        makePromise(child);
                      }
                      var _state = parent._state;
                      if (_state) {
                        (function() {
                          var callback = _arguments[_state - 1];
                          asap(function() {
                            return invokeCallback(_state, child, callback, parent._result);
                          });
                        })();
                      } else {
                        subscribe(parent, child, onFulfillment, onRejection);
                      }
                      return child;
                    }
                    function resolve$1(object) {
                      var Constructor = this;
                      if (object && typeof object === "object" && object.constructor === Constructor) {
                        return object;
                      }
                      var promise = new Constructor(noop2);
                      resolve(promise, object);
                      return promise;
                    }
                    var PROMISE_ID = Math.random().toString(36).substring(16);
                    function noop2() {
                    }
                    var PENDING = void 0;
                    var FULFILLED = 1;
                    var REJECTED = 2;
                    var GET_THEN_ERROR = new ErrorObject();
                    function selfFulfillment() {
                      return new TypeError("You cannot resolve a promise with itself");
                    }
                    function cannotReturnOwn() {
                      return new TypeError("A promises callback cannot return that same promise.");
                    }
                    function getThen(promise) {
                      try {
                        return promise.then;
                      } catch (error) {
                        GET_THEN_ERROR.error = error;
                        return GET_THEN_ERROR;
                      }
                    }
                    function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {
                      try {
                        then$$1.call(value, fulfillmentHandler, rejectionHandler);
                      } catch (e) {
                        return e;
                      }
                    }
                    function handleForeignThenable(promise, thenable, then$$1) {
                      asap(function(promise2) {
                        var sealed = false;
                        var error = tryThen(then$$1, thenable, function(value) {
                          if (sealed) {
                            return;
                          }
                          sealed = true;
                          if (thenable !== value) {
                            resolve(promise2, value);
                          } else {
                            fulfill(promise2, value);
                          }
                        }, function(reason) {
                          if (sealed) {
                            return;
                          }
                          sealed = true;
                          reject(promise2, reason);
                        }, "Settle: " + (promise2._label || " unknown promise"));
                        if (!sealed && error) {
                          sealed = true;
                          reject(promise2, error);
                        }
                      }, promise);
                    }
                    function handleOwnThenable(promise, thenable) {
                      if (thenable._state === FULFILLED) {
                        fulfill(promise, thenable._result);
                      } else if (thenable._state === REJECTED) {
                        reject(promise, thenable._result);
                      } else {
                        subscribe(thenable, void 0, function(value) {
                          return resolve(promise, value);
                        }, function(reason) {
                          return reject(promise, reason);
                        });
                      }
                    }
                    function handleMaybeThenable(promise, maybeThenable, then$$1) {
                      if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) {
                        handleOwnThenable(promise, maybeThenable);
                      } else {
                        if (then$$1 === GET_THEN_ERROR) {
                          reject(promise, GET_THEN_ERROR.error);
                          GET_THEN_ERROR.error = null;
                        } else if (then$$1 === void 0) {
                          fulfill(promise, maybeThenable);
                        } else if (isFunction2(then$$1)) {
                          handleForeignThenable(promise, maybeThenable, then$$1);
                        } else {
                          fulfill(promise, maybeThenable);
                        }
                      }
                    }
                    function resolve(promise, value) {
                      if (promise === value) {
                        reject(promise, selfFulfillment());
                      } else if (objectOrFunction(value)) {
                        handleMaybeThenable(promise, value, getThen(value));
                      } else {
                        fulfill(promise, value);
                      }
                    }
                    function publishRejection(promise) {
                      if (promise._onerror) {
                        promise._onerror(promise._result);
                      }
                      publish(promise);
                    }
                    function fulfill(promise, value) {
                      if (promise._state !== PENDING) {
                        return;
                      }
                      promise._result = value;
                      promise._state = FULFILLED;
                      if (promise._subscribers.length !== 0) {
                        asap(publish, promise);
                      }
                    }
                    function reject(promise, reason) {
                      if (promise._state !== PENDING) {
                        return;
                      }
                      promise._state = REJECTED;
                      promise._result = reason;
                      asap(publishRejection, promise);
                    }
                    function subscribe(parent, child, onFulfillment, onRejection) {
                      var _subscribers = parent._subscribers;
                      var length = _subscribers.length;
                      parent._onerror = null;
                      _subscribers[length] = child;
                      _subscribers[length + FULFILLED] = onFulfillment;
                      _subscribers[length + REJECTED] = onRejection;
                      if (length === 0 && parent._state) {
                        asap(publish, parent);
                      }
                    }
                    function publish(promise) {
                      var subscribers = promise._subscribers;
                      var settled = promise._state;
                      if (subscribers.length === 0) {
                        return;
                      }
                      var child = void 0, callback = void 0, detail = promise._result;
                      for (var i = 0; i < subscribers.length; i += 3) {
                        child = subscribers[i];
                        callback = subscribers[i + settled];
                        if (child) {
                          invokeCallback(settled, child, callback, detail);
                        } else {
                          callback(detail);
                        }
                      }
                      promise._subscribers.length = 0;
                    }
                    function ErrorObject() {
                      this.error = null;
                    }
                    var TRY_CATCH_ERROR = new ErrorObject();
                    function tryCatch(callback, detail) {
                      try {
                        return callback(detail);
                      } catch (e) {
                        TRY_CATCH_ERROR.error = e;
                        return TRY_CATCH_ERROR;
                      }
                    }
                    function invokeCallback(settled, promise, callback, detail) {
                      var hasCallback = isFunction2(callback), value = void 0, error = void 0, succeeded = void 0, failed = void 0;
                      if (hasCallback) {
                        value = tryCatch(callback, detail);
                        if (value === TRY_CATCH_ERROR) {
                          failed = true;
                          error = value.error;
                          value.error = null;
                        } else {
                          succeeded = true;
                        }
                        if (promise === value) {
                          reject(promise, cannotReturnOwn());
                          return;
                        }
                      } else {
                        value = detail;
                        succeeded = true;
                      }
                      if (promise._state !== PENDING)
                        ;
                      else if (hasCallback && succeeded) {
                        resolve(promise, value);
                      } else if (failed) {
                        reject(promise, error);
                      } else if (settled === FULFILLED) {
                        fulfill(promise, value);
                      } else if (settled === REJECTED) {
                        reject(promise, value);
                      }
                    }
                    function initializePromise(promise, resolver) {
                      try {
                        resolver(function resolvePromise(value) {
                          resolve(promise, value);
                        }, function rejectPromise(reason) {
                          reject(promise, reason);
                        });
                      } catch (e) {
                        reject(promise, e);
                      }
                    }
                    var id = 0;
                    function nextId() {
                      return id++;
                    }
                    function makePromise(promise) {
                      promise[PROMISE_ID] = id++;
                      promise._state = void 0;
                      promise._result = void 0;
                      promise._subscribers = [];
                    }
                    function Enumerator$1(Constructor, input) {
                      this._instanceConstructor = Constructor;
                      this.promise = new Constructor(noop2);
                      if (!this.promise[PROMISE_ID]) {
                        makePromise(this.promise);
                      }
                      if (isArray2(input)) {
                        this.length = input.length;
                        this._remaining = input.length;
                        this._result = new Array(this.length);
                        if (this.length === 0) {
                          fulfill(this.promise, this._result);
                        } else {
                          this.length = this.length || 0;
                          this._enumerate(input);
                          if (this._remaining === 0) {
                            fulfill(this.promise, this._result);
                          }
                        }
                      } else {
                        reject(this.promise, validationError());
                      }
                    }
                    function validationError() {
                      return new Error("Array Methods must be provided an Array");
                    }
                    Enumerator$1.prototype._enumerate = function(input) {
                      for (var i = 0; this._state === PENDING && i < input.length; i++) {
                        this._eachEntry(input[i], i);
                      }
                    };
                    Enumerator$1.prototype._eachEntry = function(entry, i) {
                      var c = this._instanceConstructor;
                      var resolve$$1 = c.resolve;
                      if (resolve$$1 === resolve$1) {
                        var _then = getThen(entry);
                        if (_then === then && entry._state !== PENDING) {
                          this._settledAt(entry._state, i, entry._result);
                        } else if (typeof _then !== "function") {
                          this._remaining--;
                          this._result[i] = entry;
                        } else if (c === Promise$2) {
                          var promise = new c(noop2);
                          handleMaybeThenable(promise, entry, _then);
                          this._willSettleAt(promise, i);
                        } else {
                          this._willSettleAt(new c(function(resolve$$12) {
                            return resolve$$12(entry);
                          }), i);
                        }
                      } else {
                        this._willSettleAt(resolve$$1(entry), i);
                      }
                    };
                    Enumerator$1.prototype._settledAt = function(state, i, value) {
                      var promise = this.promise;
                      if (promise._state === PENDING) {
                        this._remaining--;
                        if (state === REJECTED) {
                          reject(promise, value);
                        } else {
                          this._result[i] = value;
                        }
                      }
                      if (this._remaining === 0) {
                        fulfill(promise, this._result);
                      }
                    };
                    Enumerator$1.prototype._willSettleAt = function(promise, i) {
                      var enumerator = this;
                      subscribe(promise, void 0, function(value) {
                        return enumerator._settledAt(FULFILLED, i, value);
                      }, function(reason) {
                        return enumerator._settledAt(REJECTED, i, reason);
                      });
                    };
                    function all$1(entries) {
                      return new Enumerator$1(this, entries).promise;
                    }
                    function race$1(entries) {
                      var Constructor = this;
                      if (!isArray2(entries)) {
                        return new Constructor(function(_, reject2) {
                          return reject2(new TypeError("You must pass an array to race."));
                        });
                      } else {
                        return new Constructor(function(resolve2, reject2) {
                          var length = entries.length;
                          for (var i = 0; i < length; i++) {
                            Constructor.resolve(entries[i]).then(resolve2, reject2);
                          }
                        });
                      }
                    }
                    function reject$1(reason) {
                      var Constructor = this;
                      var promise = new Constructor(noop2);
                      reject(promise, reason);
                      return promise;
                    }
                    function needsResolver() {
                      throw new TypeError("You must pass a resolver function as the first argument to the promise constructor");
                    }
                    function needsNew() {
                      throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
                    }
                    function Promise$2(resolver) {
                      this[PROMISE_ID] = nextId();
                      this._result = this._state = void 0;
                      this._subscribers = [];
                      if (noop2 !== resolver) {
                        typeof resolver !== "function" && needsResolver();
                        this instanceof Promise$2 ? initializePromise(this, resolver) : needsNew();
                      }
                    }
                    Promise$2.all = all$1;
                    Promise$2.race = race$1;
                    Promise$2.resolve = resolve$1;
                    Promise$2.reject = reject$1;
                    Promise$2._setScheduler = setScheduler;
                    Promise$2._setAsap = setAsap;
                    Promise$2._asap = asap;
                    Promise$2.prototype = {
                      constructor: Promise$2,
                      /**
                        The primary way of interacting with a promise is through its `then` method,
                        which registers callbacks to receive either a promise's eventual value or the
                        reason why the promise cannot be fulfilled.
                      
                        ```js
                        findUser().then(function(user){
                          // user is available
                        }, function(reason){
                          // user is unavailable, and you are given the reason why
                        });
                        ```
                      
                        Chaining
                        --------
                      
                        The return value of `then` is itself a promise.  This second, 'downstream'
                        promise is resolved with the return value of the first promise's fulfillment
                        or rejection handler, or rejected if the handler throws an exception.
                      
                        ```js
                        findUser().then(function (user) {
                          return user.name;
                        }, function (reason) {
                          return 'default name';
                        }).then(function (userName) {
                          // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
                          // will be `'default name'`
                        });
                      
                        findUser().then(function (user) {
                          throw new Error('Found user, but still unhappy');
                        }, function (reason) {
                          throw new Error('`findUser` rejected and we're unhappy');
                        }).then(function (value) {
                          // never reached
                        }, function (reason) {
                          // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
                          // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
                        });
                        ```
                        If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
                      
                        ```js
                        findUser().then(function (user) {
                          throw new PedagogicalException('Upstream error');
                        }).then(function (value) {
                          // never reached
                        }).then(function (value) {
                          // never reached
                        }, function (reason) {
                          // The `PedgagocialException` is propagated all the way down to here
                        });
                        ```
                      
                        Assimilation
                        ------------
                      
                        Sometimes the value you want to propagate to a downstream promise can only be
                        retrieved asynchronously. This can be achieved by returning a promise in the
                        fulfillment or rejection handler. The downstream promise will then be pending
                        until the returned promise is settled. This is called *assimilation*.
                      
                        ```js
                        findUser().then(function (user) {
                          return findCommentsByAuthor(user);
                        }).then(function (comments) {
                          // The user's comments are now available
                        });
                        ```
                      
                        If the assimliated promise rejects, then the downstream promise will also reject.
                      
                        ```js
                        findUser().then(function (user) {
                          return findCommentsByAuthor(user);
                        }).then(function (comments) {
                          // If `findCommentsByAuthor` fulfills, we'll have the value here
                        }, function (reason) {
                          // If `findCommentsByAuthor` rejects, we'll have the reason here
                        });
                        ```
                      
                        Simple Example
                        --------------
                      
                        Synchronous Example
                      
                        ```javascript
                        let result;
                      
                        try {
                          result = findResult();
                          // success
                        } catch(reason) {
                          // failure
                        }
                        ```
                      
                        Errback Example
                      
                        ```js
                        findResult(function(result, err){
                          if (err) {
                            // failure
                          } else {
                            // success
                          }
                        });
                        ```
                      
                        Promise Example;
                      
                        ```javascript
                        findResult().then(function(result){
                          // success
                        }, function(reason){
                          // failure
                        });
                        ```
                      
                        Advanced Example
                        --------------
                      
                        Synchronous Example
                      
                        ```javascript
                        let author, books;
                      
                        try {
                          author = findAuthor();
                          books  = findBooksByAuthor(author);
                          // success
                        } catch(reason) {
                          // failure
                        }
                        ```
                      
                        Errback Example
                      
                        ```js
                      
                        function foundBooks(books) {
                      
                        }
                      
                        function failure(reason) {
                      
                        }
                      
                        findAuthor(function(author, err){
                          if (err) {
                            failure(err);
                            // failure
                          } else {
                            try {
                              findBoooksByAuthor(author, function(books, err) {
                                if (err) {
                                  failure(err);
                                } else {
                                  try {
                                    foundBooks(books);
                                  } catch(reason) {
                                    failure(reason);
                                  }
                                }
                              });
                            } catch(error) {
                              failure(err);
                            }
                            // success
                          }
                        });
                        ```
                      
                        Promise Example;
                      
                        ```javascript
                        findAuthor().
                          then(findBooksByAuthor).
                          then(function(books){
                            // found books
                        }).catch(function(reason){
                          // something went wrong
                        });
                        ```
                      
                        @method then
                        @param {Function} onFulfilled
                        @param {Function} onRejected
                        Useful for tooling.
                        @return {Promise}
                      */
                      then,
                      /**
                        `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
                        as the catch block of a try/catch statement.
                      
                        ```js
                        function findAuthor(){
                          throw new Error('couldn't find that author');
                        }
                      
                        // synchronous
                        try {
                          findAuthor();
                        } catch(reason) {
                          // something went wrong
                        }
                      
                        // async with promises
                        findAuthor().catch(function(reason){
                          // something went wrong
                        });
                        ```
                      
                        @method catch
                        @param {Function} onRejection
                        Useful for tooling.
                        @return {Promise}
                      */
                      "catch": function _catch(onRejection) {
                        return this.then(null, onRejection);
                      }
                    };
                    function polyfill$1() {
                      var local = void 0;
                      if (typeof global2 !== "undefined") {
                        local = global2;
                      } else if (typeof self !== "undefined") {
                        local = self;
                      } else {
                        try {
                          local = Function("return this")();
                        } catch (e) {
                          throw new Error("polyfill failed because global object is unavailable in this environment");
                        }
                      }
                      var P = local.Promise;
                      if (P) {
                        var promiseToString = null;
                        try {
                          promiseToString = Object.prototype.toString.call(P.resolve());
                        } catch (e) {
                        }
                        if (promiseToString === "[object Promise]" && !P.cast) {
                          return;
                        }
                      }
                      local.Promise = Promise$2;
                    }
                    Promise$2.polyfill = polyfill$1;
                    Promise$2.Promise = Promise$2;
                    return Promise$2;
                  });
                }).call(exports22, __webpack_require__(7), __webpack_require__(8));
              },
              /* 5 */
              /***/
              function(module22, exports22) {
              },
              /* 6 */
              /***/
              function(module22, exports22, __webpack_require__) {
                Object.defineProperty(exports22, "__esModule", {
                  value: true
                });
                var _createClass = /* @__PURE__ */ function() {
                  function defineProperties(target, props) {
                    for (var i = 0; i < props.length; i++) {
                      var descriptor = props[i];
                      descriptor.enumerable = descriptor.enumerable || false;
                      descriptor.configurable = true;
                      if ("value" in descriptor)
                        descriptor.writable = true;
                      Object.defineProperty(target, descriptor.key, descriptor);
                    }
                  }
                  return function(Constructor, protoProps, staticProps) {
                    if (protoProps)
                      defineProperties(Constructor.prototype, protoProps);
                    if (staticProps)
                      defineProperties(Constructor, staticProps);
                    return Constructor;
                  };
                }();
                __webpack_require__(5);
                var _es6Promise = __webpack_require__(4);
                var _es6Promise2 = _interopRequireDefault(_es6Promise);
                var _utils = __webpack_require__(0);
                var Utils = _interopRequireWildcard(_utils);
                var _api = __webpack_require__(1);
                var API = _interopRequireWildcard(_api);
                var _button = __webpack_require__(2);
                var _push = __webpack_require__(3);
                function _interopRequireWildcard(obj) {
                  if (obj && obj.__esModule) {
                    return obj;
                  } else {
                    var newObj = {};
                    if (obj != null) {
                      for (var key in obj) {
                        if (Object.prototype.hasOwnProperty.call(obj, key))
                          newObj[key] = obj[key];
                      }
                    }
                    newObj.default = obj;
                    return newObj;
                  }
                }
                function _interopRequireDefault(obj) {
                  return obj && obj.__esModule ? obj : { default: obj };
                }
                function _classCallCheck(instance, Constructor) {
                  if (!(instance instanceof Constructor)) {
                    throw new TypeError("Cannot call a class as a function");
                  }
                }
                var Noty2 = function() {
                  function Noty22() {
                    var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
                    _classCallCheck(this, Noty22);
                    this.options = Utils.deepExtend({}, API.Defaults, options);
                    this.id = this.options.id || Utils.generateID("bar");
                    this.closeTimer = -1;
                    this.barDom = null;
                    this.layoutDom = null;
                    this.progressDom = null;
                    this.showing = false;
                    this.shown = false;
                    this.closed = false;
                    this.closing = false;
                    this.killable = this.options.timeout || this.options.closeWith.length > 0;
                    this.hasSound = this.options.sounds.sources.length > 0;
                    this.soundPlayed = false;
                    this.listeners = {
                      beforeShow: [],
                      onShow: [],
                      afterShow: [],
                      onClose: [],
                      afterClose: [],
                      onClick: [],
                      onHover: [],
                      onTemplate: []
                    };
                    this.promises = {
                      show: null,
                      close: null
                    };
                    this.on("beforeShow", this.options.callbacks.beforeShow);
                    this.on("onShow", this.options.callbacks.onShow);
                    this.on("afterShow", this.options.callbacks.afterShow);
                    this.on("onClose", this.options.callbacks.onClose);
                    this.on("afterClose", this.options.callbacks.afterClose);
                    this.on("onClick", this.options.callbacks.onClick);
                    this.on("onHover", this.options.callbacks.onHover);
                    this.on("onTemplate", this.options.callbacks.onTemplate);
                    return this;
                  }
                  _createClass(Noty22, [{
                    key: "on",
                    value: function on(eventName) {
                      var cb = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : function() {
                      };
                      if (typeof cb === "function" && this.listeners.hasOwnProperty(eventName)) {
                        this.listeners[eventName].push(cb);
                      }
                      return this;
                    }
                    /**
                     * @return {Noty}
                     */
                  }, {
                    key: "show",
                    value: function show() {
                      var _this = this;
                      if (this.options.killer === true) {
                        Noty22.closeAll();
                      } else if (typeof this.options.killer === "string") {
                        Noty22.closeAll(this.options.killer);
                      }
                      var queueCounts = API.getQueueCounts(this.options.queue);
                      if (queueCounts.current >= queueCounts.maxVisible || API.PageHidden && this.options.visibilityControl) {
                        API.addToQueue(this);
                        if (API.PageHidden && this.hasSound && Utils.inArray("docHidden", this.options.sounds.conditions)) {
                          Utils.createAudioElements(this);
                        }
                        if (API.PageHidden && Utils.inArray("docHidden", this.options.titleCount.conditions)) {
                          API.docTitle.increment();
                        }
                        return this;
                      }
                      API.Store[this.id] = this;
                      API.fire(this, "beforeShow");
                      this.showing = true;
                      if (this.closing) {
                        this.showing = false;
                        return this;
                      }
                      API.build(this);
                      API.handleModal(this);
                      if (this.options.force) {
                        this.layoutDom.insertBefore(this.barDom, this.layoutDom.firstChild);
                      } else {
                        this.layoutDom.appendChild(this.barDom);
                      }
                      if (this.hasSound && !this.soundPlayed && Utils.inArray("docVisible", this.options.sounds.conditions)) {
                        Utils.createAudioElements(this);
                      }
                      if (Utils.inArray("docVisible", this.options.titleCount.conditions)) {
                        API.docTitle.increment();
                      }
                      this.shown = true;
                      this.closed = false;
                      if (API.hasButtons(this)) {
                        Object.keys(this.options.buttons).forEach(function(key) {
                          var btn = _this.barDom.querySelector("#" + _this.options.buttons[key].id);
                          Utils.addListener(btn, "click", function(e) {
                            Utils.stopPropagation(e);
                            _this.options.buttons[key].cb();
                          });
                        });
                      }
                      this.progressDom = this.barDom.querySelector(".noty_progressbar");
                      if (Utils.inArray("click", this.options.closeWith)) {
                        Utils.addClass(this.barDom, "noty_close_with_click");
                        Utils.addListener(this.barDom, "click", function(e) {
                          Utils.stopPropagation(e);
                          API.fire(_this, "onClick");
                          _this.close();
                        }, false);
                      }
                      Utils.addListener(this.barDom, "mouseenter", function() {
                        API.fire(_this, "onHover");
                      }, false);
                      if (this.options.timeout)
                        Utils.addClass(this.barDom, "noty_has_timeout");
                      if (this.options.progressBar) {
                        Utils.addClass(this.barDom, "noty_has_progressbar");
                      }
                      if (Utils.inArray("button", this.options.closeWith)) {
                        Utils.addClass(this.barDom, "noty_close_with_button");
                        var closeButton = document.createElement("div");
                        Utils.addClass(closeButton, "noty_close_button");
                        closeButton.innerHTML = "×";
                        this.barDom.appendChild(closeButton);
                        Utils.addListener(closeButton, "click", function(e) {
                          Utils.stopPropagation(e);
                          _this.close();
                        }, false);
                      }
                      API.fire(this, "onShow");
                      if (this.options.animation.open === null) {
                        this.promises.show = new _es6Promise2.default(function(resolve) {
                          resolve();
                        });
                      } else if (typeof this.options.animation.open === "function") {
                        this.promises.show = new _es6Promise2.default(this.options.animation.open.bind(this));
                      } else {
                        Utils.addClass(this.barDom, this.options.animation.open);
                        this.promises.show = new _es6Promise2.default(function(resolve) {
                          Utils.addListener(_this.barDom, Utils.animationEndEvents, function() {
                            Utils.removeClass(_this.barDom, _this.options.animation.open);
                            resolve();
                          });
                        });
                      }
                      this.promises.show.then(function() {
                        var _t = _this;
                        setTimeout(function() {
                          API.openFlow(_t);
                        }, 100);
                      });
                      return this;
                    }
                    /**
                     * @return {Noty}
                     */
                  }, {
                    key: "stop",
                    value: function stop() {
                      API.dequeueClose(this);
                      return this;
                    }
                    /**
                     * @return {Noty}
                     */
                  }, {
                    key: "resume",
                    value: function resume() {
                      API.queueClose(this);
                      return this;
                    }
                    /**
                     * @param {int|boolean} ms
                     * @return {Noty}
                     */
                  }, {
                    key: "setTimeout",
                    value: function(_setTimeout) {
                      function setTimeout2(_x) {
                        return _setTimeout.apply(this, arguments);
                      }
                      setTimeout2.toString = function() {
                        return _setTimeout.toString();
                      };
                      return setTimeout2;
                    }(function(ms) {
                      this.stop();
                      this.options.timeout = ms;
                      if (this.barDom) {
                        if (this.options.timeout) {
                          Utils.addClass(this.barDom, "noty_has_timeout");
                        } else {
                          Utils.removeClass(this.barDom, "noty_has_timeout");
                        }
                        var _t = this;
                        setTimeout(function() {
                          _t.resume();
                        }, 100);
                      }
                      return this;
                    })
                    /**
                     * @param {string} html
                     * @param {boolean} optionsOverride
                     * @return {Noty}
                     */
                  }, {
                    key: "setText",
                    value: function setText(html2) {
                      var optionsOverride = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
                      if (this.barDom) {
                        this.barDom.querySelector(".noty_body").innerHTML = html2;
                      }
                      if (optionsOverride)
                        this.options.text = html2;
                      return this;
                    }
                    /**
                     * @param {string} type
                     * @param {boolean} optionsOverride
                     * @return {Noty}
                     */
                  }, {
                    key: "setType",
                    value: function setType(type) {
                      var _this2 = this;
                      var optionsOverride = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
                      if (this.barDom) {
                        var classList = Utils.classList(this.barDom).split(" ");
                        classList.forEach(function(c) {
                          if (c.substring(0, 11) === "noty_type__") {
                            Utils.removeClass(_this2.barDom, c);
                          }
                        });
                        Utils.addClass(this.barDom, "noty_type__" + type);
                      }
                      if (optionsOverride)
                        this.options.type = type;
                      return this;
                    }
                    /**
                     * @param {string} theme
                     * @param {boolean} optionsOverride
                     * @return {Noty}
                     */
                  }, {
                    key: "setTheme",
                    value: function setTheme(theme) {
                      var _this3 = this;
                      var optionsOverride = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
                      if (this.barDom) {
                        var classList = Utils.classList(this.barDom).split(" ");
                        classList.forEach(function(c) {
                          if (c.substring(0, 12) === "noty_theme__") {
                            Utils.removeClass(_this3.barDom, c);
                          }
                        });
                        Utils.addClass(this.barDom, "noty_theme__" + theme);
                      }
                      if (optionsOverride)
                        this.options.theme = theme;
                      return this;
                    }
                    /**
                     * @return {Noty}
                     */
                  }, {
                    key: "close",
                    value: function close() {
                      var _this4 = this;
                      if (this.closed)
                        return this;
                      if (!this.shown) {
                        API.removeFromQueue(this);
                        return this;
                      }
                      API.fire(this, "onClose");
                      this.closing = true;
                      if (this.options.animation.close === null) {
                        this.promises.close = new _es6Promise2.default(function(resolve) {
                          resolve();
                        });
                      } else if (typeof this.options.animation.close === "function") {
                        this.promises.close = new _es6Promise2.default(this.options.animation.close.bind(this));
                      } else {
                        Utils.addClass(this.barDom, this.options.animation.close);
                        this.promises.close = new _es6Promise2.default(function(resolve) {
                          Utils.addListener(_this4.barDom, Utils.animationEndEvents, function() {
                            if (_this4.options.force) {
                              Utils.remove(_this4.barDom);
                            } else {
                              API.ghostFix(_this4);
                            }
                            resolve();
                          });
                        });
                      }
                      this.promises.close.then(function() {
                        API.closeFlow(_this4);
                        API.handleModalClose(_this4);
                      });
                      this.closed = true;
                      return this;
                    }
                    // API functions
                    /**
                     * @param {boolean|string} queueName
                     * @return {Noty}
                     */
                  }], [{
                    key: "closeAll",
                    value: function closeAll() {
                      var queueName = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false;
                      Object.keys(API.Store).forEach(function(id) {
                        if (queueName) {
                          if (API.Store[id].options.queue === queueName && API.Store[id].killable) {
                            API.Store[id].close();
                          }
                        } else if (API.Store[id].killable) {
                          API.Store[id].close();
                        }
                      });
                      return this;
                    }
                    /**
                     * @param {Object} obj
                     * @return {Noty}
                     */
                  }, {
                    key: "overrideDefaults",
                    value: function overrideDefaults(obj) {
                      API.Defaults = Utils.deepExtend({}, API.Defaults, obj);
                      return this;
                    }
                    /**
                     * @param {int} amount
                     * @param {string} queueName
                     * @return {Noty}
                     */
                  }, {
                    key: "setMaxVisible",
                    value: function setMaxVisible() {
                      var amount = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : API.DefaultMaxVisible;
                      var queueName = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "global";
                      if (!API.Queues.hasOwnProperty(queueName)) {
                        API.Queues[queueName] = { maxVisible: amount, queue: [] };
                      }
                      API.Queues[queueName].maxVisible = amount;
                      return this;
                    }
                    /**
                     * @param {string} innerHtml
                     * @param {String} classes
                     * @param {Function} cb
                     * @param {Object} attributes
                     * @return {NotyButton}
                     */
                  }, {
                    key: "button",
                    value: function button(innerHtml) {
                      var classes = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : null;
                      var cb = arguments[2];
                      var attributes = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : {};
                      return new _button.NotyButton(innerHtml, classes, cb, attributes);
                    }
                    /**
                     * @return {string}
                     */
                  }, {
                    key: "version",
                    value: function version() {
                      return "3.1.4";
                    }
                    /**
                     * @param {String} workerPath
                     * @return {Push}
                     */
                  }, {
                    key: "Push",
                    value: function Push(workerPath) {
                      return new _push.Push(workerPath);
                    }
                  }]);
                  return Noty22;
                }();
                exports22.default = Noty2;
                Utils.visibilityChangeFlow();
                module22.exports = exports22["default"];
              },
              /* 7 */
              /***/
              function(module22, exports22) {
                var process2 = module22.exports = {};
                var cachedSetTimeout;
                var cachedClearTimeout;
                function defaultSetTimout() {
                  throw new Error("setTimeout has not been defined");
                }
                function defaultClearTimeout() {
                  throw new Error("clearTimeout has not been defined");
                }
                (function() {
                  try {
                    if (typeof setTimeout === "function") {
                      cachedSetTimeout = setTimeout;
                    } else {
                      cachedSetTimeout = defaultSetTimout;
                    }
                  } catch (e) {
                    cachedSetTimeout = defaultSetTimout;
                  }
                  try {
                    if (typeof clearTimeout === "function") {
                      cachedClearTimeout = clearTimeout;
                    } else {
                      cachedClearTimeout = defaultClearTimeout;
                    }
                  } catch (e) {
                    cachedClearTimeout = defaultClearTimeout;
                  }
                })();
                function runTimeout(fun) {
                  if (cachedSetTimeout === setTimeout) {
                    return setTimeout(fun, 0);
                  }
                  if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
                    cachedSetTimeout = setTimeout;
                    return setTimeout(fun, 0);
                  }
                  try {
                    return cachedSetTimeout(fun, 0);
                  } catch (e) {
                    try {
                      return cachedSetTimeout.call(null, fun, 0);
                    } catch (e2) {
                      return cachedSetTimeout.call(this, fun, 0);
                    }
                  }
                }
                function runClearTimeout(marker) {
                  if (cachedClearTimeout === clearTimeout) {
                    return clearTimeout(marker);
                  }
                  if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
                    cachedClearTimeout = clearTimeout;
                    return clearTimeout(marker);
                  }
                  try {
                    return cachedClearTimeout(marker);
                  } catch (e) {
                    try {
                      return cachedClearTimeout.call(null, marker);
                    } catch (e2) {
                      return cachedClearTimeout.call(this, marker);
                    }
                  }
                }
                var queue = [];
                var draining = false;
                var currentQueue;
                var queueIndex = -1;
                function cleanUpNextTick() {
                  if (!draining || !currentQueue) {
                    return;
                  }
                  draining = false;
                  if (currentQueue.length) {
                    queue = currentQueue.concat(queue);
                  } else {
                    queueIndex = -1;
                  }
                  if (queue.length) {
                    drainQueue();
                  }
                }
                function drainQueue() {
                  if (draining) {
                    return;
                  }
                  var timeout = runTimeout(cleanUpNextTick);
                  draining = true;
                  var len = queue.length;
                  while (len) {
                    currentQueue = queue;
                    queue = [];
                    while (++queueIndex < len) {
                      if (currentQueue) {
                        currentQueue[queueIndex].run();
                      }
                    }
                    queueIndex = -1;
                    len = queue.length;
                  }
                  currentQueue = null;
                  draining = false;
                  runClearTimeout(timeout);
                }
                process2.nextTick = function(fun) {
                  var args = new Array(arguments.length - 1);
                  if (arguments.length > 1) {
                    for (var i = 1; i < arguments.length; i++) {
                      args[i - 1] = arguments[i];
                    }
                  }
                  queue.push(new Item(fun, args));
                  if (queue.length === 1 && !draining) {
                    runTimeout(drainQueue);
                  }
                };
                function Item(fun, array) {
                  this.fun = fun;
                  this.array = array;
                }
                Item.prototype.run = function() {
                  this.fun.apply(null, this.array);
                };
                process2.title = "browser";
                process2.browser = true;
                process2.env = {};
                process2.argv = [];
                process2.version = "";
                process2.versions = {};
                function noop2() {
                }
                process2.on = noop2;
                process2.addListener = noop2;
                process2.once = noop2;
                process2.off = noop2;
                process2.removeListener = noop2;
                process2.removeAllListeners = noop2;
                process2.emit = noop2;
                process2.prependListener = noop2;
                process2.prependOnceListener = noop2;
                process2.listeners = function(name) {
                  return [];
                };
                process2.binding = function(name) {
                  throw new Error("process.binding is not supported");
                };
                process2.cwd = function() {
                  return "/";
                };
                process2.chdir = function(dir) {
                  throw new Error("process.chdir is not supported");
                };
                process2.umask = function() {
                  return 0;
                };
              },
              /* 8 */
              /***/
              function(module22, exports22) {
                var g;
                g = /* @__PURE__ */ function() {
                  return this;
                }();
                try {
                  g = g || Function("return this")() || (1, eval)("this");
                } catch (e) {
                  if (typeof window === "object")
                    g = window;
                }
                module22.exports = g;
              },
              /* 9 */
              /***/
              function(module22, exports22) {
              }
              /******/
            ])
          );
        });
      })(noty);
      var notyExports = noty.exports;
      const Noty = /* @__PURE__ */ getDefaultExportFromCjs(notyExports);
      const resource$1 = {
        "common": {
          "settings": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Settings" } },
          "auto": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Auto" } },
          "english": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "English" } },
          "japanese": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Japanese" } },
          "chinese": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Chinese" } },
          "pretty": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Pretty" } },
          "filter": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Filter" } },
          "none": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "None" } },
          "random": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Random" } },
          "balance": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Balance" } },
          "abbr": {
            "english": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "EN" } },
            "japanese": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "JP" } },
            "chinese": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "CN" } }
          }
        },
        "setting": {
          "title": { "t": 0, "b": { "t": 2, "i": [{ "t": 6, "k": { "t": 7, "v": "common.settings" } }] } },
          "advanceTitle": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Advance Settings" } },
          "helpButton": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Help" } },
          "asteriskTip": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "means refresh is required to take effect" } },
          "downloadThread": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Download thread" } },
          "openOnNewTab": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Open on new tab" } },
          "compressionFilename": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Compression filename" } },
          "maxNumber": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Max number" } },
          "separator": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Separator" } },
          "compressionLevel": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Compression level" } },
          "filenameLength": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Filename length" } },
          "autoCancelDownloadedManga": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Auto cancel downloaded manga" } },
          "autoRetryWhenErrorOccurs": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Auto retry when error occurs" } },
          "autoShowAll": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Auto show all" } },
          "showIgnoreButton": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": 'Show "Ignore" button' } },
          "judgeDownloadedMangaByTitle": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Judge downloaded manga by title" } },
          "customDownloadUrl": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Custom download URL" } },
          "compressionStreamFiles": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": 'Compression "streamFiles"' } },
          "seriesMode": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Series mode" } },
          "streamDownload": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Stream download" } },
          "preventConsoleClearing": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Prevent console clearing" } },
          "nHentaiDownloadHost": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "nHentai download host" } },
          "addMetaFile": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Add metadata file" } },
          "metaFileTitleLanguage": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Title language" } },
          "titleReplacement": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Title replacement" } },
          "history": {
            "title": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Download History" } },
            "downloadedNumberTip": { "t": 0, "b": { "t": 2, "i": [{ "t": 3, "v": "You have downloaded " }, { "t": 4, "k": "num" }, { "t": 3, "v": " manga on this site using nHentai Helper." }] } },
            "import": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Import" } },
            "export": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Export" } },
            "clear": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Clear" } },
            "importTip": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Tip: Import will not clear the existing history, but merges with it." } }
          }
        },
        "dialog": {
          "yes": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "YES" } },
          "no": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "NO" } },
          "action": {
            "getInfo": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "getting information" } },
            "download": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "downloading" } }
          },
          "downloadAgainConfirm": ({ named }) => `<i>${named("title")}</i> is already downloaded${named("hasQueue") ? " or in queue" : ""}.<br>Do you want to download again?`,
          "errorRetryConfirm": (ctx) => `Error occurred while ${getActionText(ctx)}, retry?`,
          "errorRetryTip": (ctx) => `Error occurred while ${getActionText(ctx)}, retrying...`,
          "downloadedTip": { "t": 0, "b": { "t": 2, "i": [{ "t": 3, "v": "<i>" }, { "t": 4, "k": "title" }, { "t": 3, "v": "</i> is already downloaded or in queue." }] } },
          "getMediaUrlTemplateFailed": { "t": 0, "b": { "t": 2, "i": [{ "t": 3, "v": 'Fail to get image download url. Please set "' }, { "t": 6, "k": { "t": 9, "v": "setting.customDownloadUrl" } }, { "t": 3, "v": '" manually, or open a github issue to report with current url.' }] } }
        },
        "button": {
          "download": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Download" } },
          "downloading": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Downloading" } },
          "compressing": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Compressing" } }
        },
        "confirmPopup": {
          "title": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "Are you sure?" } },
          "yes": { "t": 0, "b": { "static": "", "t": 2, "i": [] } },
          "no": { "t": 0, "b": { "static": "", "t": 2, "i": [] } }
        }
      };
      const resource = {
        "common": {
          "settings": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "设置" } },
          "auto": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "自动" } },
          "english": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "英文" } },
          "japanese": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "日文" } },
          "chinese": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "中文" } },
          "pretty": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "简略" } },
          "filter": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "过滤" } },
          "none": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "无" } },
          "random": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "随机" } },
          "balance": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "均衡" } },
          "abbr": {
            "english": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "英" } },
            "japanese": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "日" } },
            "chinese": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "中" } }
          }
        },
        "setting": {
          "title": { "t": 0, "b": { "t": 2, "i": [{ "t": 6, "k": { "t": 7, "v": "common.settings" } }] } },
          "advanceTitle": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "进阶设置" } },
          "helpButton": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "帮助" } },
          "asteriskTip": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "表示刷新页面才能生效" } },
          "downloadThread": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "下载线程数" } },
          "openOnNewTab": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "在新选项卡打开" } },
          "compressionFilename": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "压缩文件名" } },
          "maxNumber": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "最大数量" } },
          "separator": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "分隔符" } },
          "compressionLevel": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "压缩等级" } },
          "filenameLength": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "文件名长度" } },
          "autoCancelDownloadedManga": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "自动取消下载过的本子" } },
          "autoRetryWhenErrorOccurs": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "发生错误时自动重试" } },
          "autoShowAll": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "自动显示全部" } },
          "showIgnoreButton": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "显示“忽略”按钮" } },
          "judgeDownloadedMangaByTitle": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "用标题判断本子是否下载过" } },
          "customDownloadUrl": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "自定义下载地址" } },
          "compressionStreamFiles": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": '压缩 "streamFiles" 选项' } },
          "seriesMode": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "串行模式" } },
          "streamDownload": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "流式下载" } },
          "preventConsoleClearing": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "阻止控制台清空" } },
          "nHentaiDownloadHost": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "nHentai 下载节点" } },
          "addMetaFile": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "添加元数据文件" } },
          "metaFileTitleLanguage": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "标题语言" } },
          "titleReplacement": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "标题替换" } },
          "history": {
            "title": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "下载历史" } },
            "downloadedNumberTip": { "t": 0, "b": { "t": 2, "i": [{ "t": 3, "v": "你在这个站点上已经用 nHentai 助手下载了 " }, { "t": 4, "k": "num" }, { "t": 3, "v": " 个本子" }] } },
            "import": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "导入" } },
            "export": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "导出" } },
            "clear": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "清空" } },
            "importTip": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "提示:导入会将导入的历史记录与现有历史记录合并,不会清空现有历史记录" } }
          }
        },
        "dialog": {
          "yes": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "是的" } },
          "no": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "算了" } },
          "action": {
            "getInfo": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "获取信息" } },
            "download": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "下载" } }
          },
          "downloadAgainConfirm": ({ named }) => `《${named("title")}》已下载过${named("hasQueue") ? "或在队列中" : ""},你希望再次下载吗?`,
          "errorRetryConfirm": (ctx) => `${getActionText(ctx)}发生错误,是否重试?`,
          "errorRetryTip": (ctx) => `${getActionText(ctx)}发生错误,重试中……`,
          "downloadedTip": { "t": 0, "b": { "t": 2, "i": [{ "t": 3, "v": "《" }, { "t": 4, "k": "title" }, { "t": 3, "v": "》已经下载过或在队列中" }] } },
          "getMediaUrlTemplateFailed": { "t": 0, "b": { "t": 2, "i": [{ "t": 3, "v": "获取图片下载地址失败,请手动设置“" }, { "t": 6, "k": { "t": 9, "v": "setting.customDownloadUrl" } }, { "t": 3, "v": "”,或前往 github issue 或脚本页面反馈并附带当前网址" }] } }
        },
        "button": {
          "download": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "下载" } },
          "downloading": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "下载中" } },
          "compressing": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "压缩中" } }
        },
        "confirmPopup": {
          "title": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "真的吗?" } },
          "yes": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "真的" } },
          "no": { "t": 0, "b": { "t": 2, "i": [{ "t": 3 }], "s": "算了" } }
        }
      };
      const i18n = createI18n({
        legacy: false,
        locale: settings.language,
        fallbackLocale: "en",
        messages: { en: resource$1, zh: resource }
      });
      const { t: t$1 } = i18n.global;
      const notyConfirmOption = {
        type: "error",
        layout: "bottomRight",
        theme: "nest",
        timeout: false,
        closeWith: []
      };
      const downloadAgainConfirm = async (title, hasQueue = false) => {
        if (hasQueue && settings.autoCancelDownloadedManga) {
          downloadedTip(title);
          return false;
        }
        return new Promise((resolve) => {
          const n = new Noty({
            ...notyConfirmOption,
            text: t$1("dialog.downloadAgainConfirm", { title, hasQueue }),
            buttons: [
              Noty.button(t$1("dialog.yes"), "btn btn-noty-blue btn-noty", () => {
                n.close();
                resolve(true);
              }),
              Noty.button(t$1("dialog.no"), "btn btn-noty-green btn-noty", () => {
                n.close();
                resolve(false);
              })
            ]
          });
          n.show();
        });
      };
      const errorRetryConfirm = (action, noCb, yesCb) => {
        if (settings.autoRetryWhenErrorOccurs) {
          errorRetryTip(action);
          yesCb == null ? void 0 : yesCb();
          return;
        }
        const n = new Noty({
          ...notyConfirmOption,
          text: t$1("dialog.errorRetryConfirm", { action }),
          buttons: [
            Noty.button(t$1("dialog.no"), "btn btn-noty-blue btn-noty", () => {
              n.close();
              noCb == null ? void 0 : noCb();
            }),
            Noty.button(t$1("dialog.yes"), "btn btn-noty-green btn-noty", () => {
              n.close();
              yesCb == null ? void 0 : yesCb();
            })
          ]
        });
        n.show();
      };
      const downloadedTip = (title) => {
        new Noty({
          type: "info",
          layout: "bottomRight",
          theme: "nest",
          closeWith: [],
          timeout: 4e3,
          text: t$1("dialog.downloadedTip", { title })
        }).show();
      };
      const errorRetryTip = (action) => {
        new Noty({
          type: "warning",
          layout: "bottomRight",
          theme: "nest",
          closeWith: [],
          timeout: 3e3,
          text: t$1("dialog.errorRetryTip", { action })
        }).show();
      };
      const openAlert = (i18nKey) => {
        const n = new Noty({
          layout: "center",
          theme: "nest",
          modal: true,
          closeWith: [],
          text: t$1(i18nKey),
          buttons: [
            Noty.button("OK", "btn btn-noty-blue btn-noty", () => {
              n.close();
            })
          ]
        });
        n.show();
      };
      var StreamSaver = { exports: {} };
      /*! streamsaver. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
      (function(module2) {
        ((name, definition) => {
          module2.exports = definition();
        })("streamSaver", () => {
          const global2 = typeof window === "object" ? window : this;
          if (!global2.HTMLElement)
            console.warn("streamsaver is meant to run on browsers main thread");
          let mitmTransporter = null;
          let supportsTransferable = false;
          const test = (fn) => {
            try {
              fn();
            } catch (e) {
            }
          };
          const ponyfill = global2.WebStreamsPolyfill || {};
          const isSecureContext = global2.isSecureContext;
          let useBlobFallback = /constructor/i.test(global2.HTMLElement) || !!global2.safari || !!global2.WebKitPoint;
          const downloadStrategy = isSecureContext || "MozAppearance" in document.documentElement.style ? "iframe" : "navigate";
          const streamSaver = {
            createWriteStream,
            WritableStream: global2.WritableStream || ponyfill.WritableStream,
            supported: true,
            version: { full: "2.0.5", major: 2, minor: 0, dot: 5 },
            mitm: "https://jimmywarting.github.io/StreamSaver.js/mitm.html?version=2.0.0"
          };
          function makeIframe(src) {
            if (!src)
              throw new Error("meh");
            const iframe = document.createElement("iframe");
            iframe.hidden = true;
            iframe.src = src;
            iframe.loaded = false;
            iframe.name = "iframe";
            iframe.isIframe = true;
            iframe.postMessage = (...args) => iframe.contentWindow.postMessage(...args);
            iframe.addEventListener("load", () => {
              iframe.loaded = true;
            }, { once: true });
            document.body.appendChild(iframe);
            return iframe;
          }
          function makePopup(src) {
            const options = "width=200,height=100";
            const delegate = document.createDocumentFragment();
            const popup = {
              frame: global2.open(src, "popup", options),
              loaded: false,
              isIframe: false,
              isPopup: true,
              remove() {
                popup.frame.close();
              },
              addEventListener(...args) {
                delegate.addEventListener(...args);
              },
              dispatchEvent(...args) {
                delegate.dispatchEvent(...args);
              },
              removeEventListener(...args) {
                delegate.removeEventListener(...args);
              },
              postMessage(...args) {
                popup.frame.postMessage(...args);
              }
            };
            const onReady = (evt) => {
              if (evt.source === popup.frame) {
                popup.loaded = true;
                global2.removeEventListener("message", onReady);
                popup.dispatchEvent(new Event("load"));
              }
            };
            global2.addEventListener("message", onReady);
            return popup;
          }
          try {
            new Response(new ReadableStream());
            if (isSecureContext && !("serviceWorker" in navigator)) {
              useBlobFallback = true;
            }
          } catch (err) {
            useBlobFallback = true;
          }
          test(() => {
            const { readable } = new TransformStream();
            const mc = new MessageChannel();
            mc.port1.postMessage(readable, [readable]);
            mc.port1.close();
            mc.port2.close();
            supportsTransferable = true;
            Object.defineProperty(streamSaver, "TransformStream", {
              configurable: false,
              writable: false,
              value: TransformStream
            });
          });
          function loadTransporter() {
            if (!mitmTransporter) {
              mitmTransporter = isSecureContext ? makeIframe(streamSaver.mitm) : makePopup(streamSaver.mitm);
            }
          }
          function createWriteStream(filename, options, size) {
            let opts = {
              size: null,
              pathname: null,
              writableStrategy: void 0,
              readableStrategy: void 0
            };
            let bytesWritten = 0;
            let downloadUrl = null;
            let channel = null;
            let ts = null;
            if (Number.isFinite(options)) {
              [size, options] = [options, size];
              console.warn("[StreamSaver] Deprecated pass an object as 2nd argument when creating a write stream");
              opts.size = size;
              opts.writableStrategy = options;
            } else if (options && options.highWaterMark) {
              console.warn("[StreamSaver] Deprecated pass an object as 2nd argument when creating a write stream");
              opts.size = size;
              opts.writableStrategy = options;
            } else {
              opts = options || {};
            }
            if (!useBlobFallback) {
              loadTransporter();
              channel = new MessageChannel();
              filename = encodeURIComponent(filename.replace(/\//g, ":")).replace(/['()]/g, escape).replace(/\*/g, "%2A");
              const response = {
                transferringReadable: supportsTransferable,
                pathname: opts.pathname || Math.random().toString().slice(-6) + "/" + filename,
                headers: {
                  "Content-Type": "application/octet-stream; charset=utf-8",
                  "Content-Disposition": "attachment; filename*=UTF-8''" + filename
                }
              };
              if (opts.size) {
                response.headers["Content-Length"] = opts.size;
              }
              const args = [response, "*", [channel.port2]];
              if (supportsTransferable) {
                const transformer = downloadStrategy === "iframe" ? void 0 : {
                  // This transformer & flush method is only used by insecure context.
                  transform(chunk, controller) {
                    if (!(chunk instanceof Uint8Array)) {
                      throw new TypeError("Can only write Uint8Arrays");
                    }
                    bytesWritten += chunk.length;
                    controller.enqueue(chunk);
                    if (downloadUrl) {
                      location.href = downloadUrl;
                      downloadUrl = null;
                    }
                  },
                  flush() {
                    if (downloadUrl) {
                      location.href = downloadUrl;
                    }
                  }
                };
                ts = new streamSaver.TransformStream(
                  transformer,
                  opts.writableStrategy,
                  opts.readableStrategy
                );
                const readableStream = ts.readable;
                channel.port1.postMessage({ readableStream }, [readableStream]);
              }
              channel.port1.onmessage = (evt) => {
                if (evt.data.download) {
                  if (downloadStrategy === "navigate") {
                    mitmTransporter.remove();
                    mitmTransporter = null;
                    if (bytesWritten) {
                      location.href = evt.data.download;
                    } else {
                      downloadUrl = evt.data.download;
                    }
                  } else {
                    if (mitmTransporter.isPopup) {
                      mitmTransporter.remove();
                      mitmTransporter = null;
                      if (downloadStrategy === "iframe") {
                        makeIframe(streamSaver.mitm);
                      }
                    }
                    makeIframe(evt.data.download);
                  }
                } else if (evt.data.abort) {
                  chunks = [];
                  channel.port1.postMessage("abort");
                  channel.port1.onmessage = null;
                  channel.port1.close();
                  channel.port2.close();
                  channel = null;
                }
              };
              if (mitmTransporter.loaded) {
                mitmTransporter.postMessage(...args);
              } else {
                mitmTransporter.addEventListener("load", () => {
                  mitmTransporter.postMessage(...args);
                }, { once: true });
              }
            }
            let chunks = [];
            return !useBlobFallback && ts && ts.writable || new streamSaver.WritableStream({
              write(chunk) {
                if (!(chunk instanceof Uint8Array)) {
                  throw new TypeError("Can only write Uint8Arrays");
                }
                if (useBlobFallback) {
                  chunks.push(chunk);
                  return;
                }
                channel.port1.postMessage(chunk);
                bytesWritten += chunk.length;
                if (downloadUrl) {
                  location.href = downloadUrl;
                  downloadUrl = null;
                }
              },
              close() {
                if (useBlobFallback) {
                  const blob2 = new Blob(chunks, { type: "application/octet-stream; charset=utf-8" });
                  const link = document.createElement("a");
                  link.href = URL.createObjectURL(blob2);
                  link.download = filename;
                  link.click();
                } else {
                  channel.port1.postMessage("end");
                }
              },
              abort() {
                chunks = [];
                channel.port1.postMessage("abort");
                channel.port1.onmessage = null;
                channel.port1.close();
                channel.port2.close();
                channel = null;
              }
            }, opts.writableStrategy);
          }
          return streamSaver;
        });
      })(StreamSaver);
      var StreamSaverExports = StreamSaver.exports;
      class MultiThread {
        constructor(tasks, taskFunc, params) {
          __publicField(this, "threads", []);
          __publicField(this, "taskIndex", 0);
          __publicField(this, "started", false);
          __publicField(this, "aborted", false);
          this.tasks = tasks;
          this.taskFunc = taskFunc;
          this.params = params;
        }
        startThread(threadId) {
          let abortFunc;
          const threadPromise = (async () => {
            while (true) {
              if (this.aborted)
                break;
              const i = this.taskIndex++;
              if (i >= this.tasks.length)
                break;
              const { abort, promise } = await this.taskFunc(this.tasks[i], threadId, this.params);
              abortFunc = abort;
              await promise;
            }
          })();
          return {
            abort: () => abortFunc == null ? void 0 : abortFunc(),
            promise: threadPromise
          };
        }
        start() {
          if (this.started)
            throw new Error("Multi-thread started.");
          this.started = true;
          for (let threadId = 0; threadId < settings.threadNum; threadId++) {
            this.threads.push(this.startThread(threadId));
          }
          return {
            abort: () => {
              this.aborted = true;
              this.threads.forEach(({ abort }) => abort());
            },
            promise: Promise.all(this.threads.map(({ promise }) => promise)).then()
          };
        }
      }
      class RequestAbortError extends Error {
        constructor(url) {
          super(`Request abort ${url}`);
        }
      }
      const isAbortError = (e) => e instanceof RequestAbortError;
      const request = (urlGetter, responseType, retry = 3) => {
        let abortFunc;
        const dataPromise = new Promise((resolve, reject) => {
          try {
            const url = typeof urlGetter === "function" ? urlGetter() : urlGetter;
            const req = _GM_xmlhttpRequest({
              method: "GET",
              url,
              responseType,
              onerror: (e) => {
                if (retry === 0) {
                  logger.error("Network error", url, e);
                  reject(e);
                } else {
                  logger.warn("Network error, retry", url, e);
                  setTimeout(() => {
                    const { abort, dataPromise: dataPromise2 } = request(urlGetter, responseType, retry - 1);
                    abortFunc = abort;
                    resolve(dataPromise2);
                  }, 1e3);
                }
              },
              onload: (r) => {
                const { status, response } = r;
                if (status === 200)
                  resolve(response);
                else if (retry === 0)
                  reject(r);
                else {
                  logger.warn("Request error, retry", status, url, r);
                  setTimeout(() => {
                    const { abort, dataPromise: dataPromise2 } = request(urlGetter, responseType, retry - 1);
                    abortFunc = abort;
                    resolve(dataPromise2);
                  }, 1e3);
                }
              }
            });
            abortFunc = () => {
              req.abort();
              logger.log("Request abort", url);
              reject(new RequestAbortError(url));
            };
          } catch (error) {
            reject(error);
          }
        });
        return {
          abort: () => abortFunc == null ? void 0 : abortFunc(),
          dataPromise
        };
      };
      const getText = (url) => request(url).dataPromise;
      const fetchJSON = (url) => fetch(url).then((r) => r.json());
      const checkHost = async (url) => {
        const { origin } = new URL(url);
        try {
          await fetch(origin, { method: "HEAD", mode: "no-cors" });
          return true;
        } catch {
          return false;
        }
      };
      class Counter {
        constructor(keys2) {
          __publicField(this, "countMap", {});
          __publicField(this, "countKeys");
          if (!keys2.length)
            throw new Error("Counter no key");
          this.countKeys = [...keys2];
          this.countKeys.forEach((key) => {
            this.countMap[key] = 0;
          });
        }
        add(key) {
          this.countMap[key]++;
        }
        del(key) {
          this.countMap[key]--;
        }
        getMin() {
          return minBy(this.countKeys, (key) => this.countMap[key]);
        }
      }
      const loadHTML = (html2) => {
        const parser2 = new DOMParser();
        return $(parser2.parseFromString(html2, "text/html").body);
      };
      var NHentaiImgExt = /* @__PURE__ */ ((NHentaiImgExt2) => {
        NHentaiImgExt2["j"] = "jpg";
        NHentaiImgExt2["p"] = "png";
        NHentaiImgExt2["g"] = "gif";
        return NHentaiImgExt2;
      })(NHentaiImgExt || {});
      const nHentaiImgExtReversed = invert(NHentaiImgExt);
      const getTypeFromExt = (ext) => nHentaiImgExtReversed[ext.toLowerCase()];
      const nHentaiDownloadHostCounter = new Counter(nHentaiDownloadHosts);
      const getNHentaiDownloadHost = () => {
        switch (settings.nHentaiDownloadHost) {
          case NHentaiDownloadHostSpecial.RANDOM:
            return sample(nHentaiDownloadHosts);
          case NHentaiDownloadHostSpecial.BALANCE:
            return nHentaiDownloadHostCounter.getMin();
          default:
            return settings.nHentaiDownloadHost;
        }
      };
      const getMediaDownloadUrl = (mid, filename) => `https://${getNHentaiDownloadHost()}/galleries/${mid}/${filename}`;
      const getMediaDownloadUrlOnMirrorSite = async (mid, filename) => (await getCompliedMediaUrlTemplate())({ mid, filename });
      const getGalleryFromApi = (gid2) => {
        const url = `https://nhentai.net/api/gallery/${gid2}`;
        return fetchJSON(url);
      };
      const getGalleryFromWebpage = async (gid) => {
        var _a;
        let doc = document;
        if (!IS_PAGE_MANGA_DETAIL) {
          const html = await getText(`/g/${gid}`);
          const match = (_a = /gallery(\(\{[\s\S]+\}\));/.exec(html)) == null ? void 0 : _a[1];
          if (match) {
            try {
              const gallery = eval(match);
              gallery.id = Number(gid);
            } catch {
              logger.warn("get gallery by eval failed");
            }
          }
          const parser = new DOMParser();
          doc = parser.parseFromString(html, "text/html");
        }
        const $doc = $(doc.body);
        const english = $doc.find("#info h1").text();
        const japanese = $doc.find("#info h2").text();
        const pages = [];
        let mediaId = "";
        $doc.find("#thumbnail-container img").each((i, img) => {
          const src = img.dataset.src ?? img.src;
          const match2 = /\/(\d+)\/(\d+)t?\.(\w+)/.exec(src);
          if (!match2)
            return;
          const [, mid, index, ext] = match2;
          if (!mediaId)
            mediaId = mid;
          const t2 = getTypeFromExt(ext);
          if (!t2)
            return;
          pages[Number(index) - 1] = { t: t2 };
        });
        if (!english && !japanese || !mediaId || !pages.length) {
          throw new Error("Get gallery info error.");
        }
        const getTags = (type, elContains) => {
          const $names = $(`#tags .tag-container:contains(${elContains}) .tag > .name`);
          const names = filter(Array.from($names).map((el) => el.innerText.trim()));
          return names.map((name) => ({ type, name }));
        };
        const tags = [
          ...getTags("parody", "Parodies"),
          ...getTags("character", "Characters"),
          ...getTags("tag", "Tags"),
          ...getTags("artist", "Artists"),
          ...getTags("group", "Groups"),
          ...getTags("language", "Languages"),
          ...getTags("category", "Categories")
        ];
        const uploadDateStr = $("#tags .tag-container:contains(Uploaded) time").attr("datetime");
        const uploadDate = uploadDateStr ? new Date(uploadDateStr) : void 0;
        return {
          id: Number(gid),
          media_id: mediaId,
          title: {
            english: english || japanese,
            japanese: japanese || english,
            pretty: ""
          },
          images: {
            pages
          },
          tags,
          upload_date: uploadDate && String(uploadDate) !== "Invalid Date" ? Math.floor(uploadDate.getTime() / 1e3) : void 0
        };
      };
      const getCFNameArtists = (tags2) => {
        const artists = map(
          tags2.filter(({ name, type }) => type === "artist" && name),
          "name"
        );
        if (!artists.length)
          return "none";
        const maxNum = settings.filenameMaxArtistsNumber;
        if (maxNum && artists.length > maxNum)
          return "various";
        return artists.join(settings.filenameArtistsSeparator);
      };
      const getGallery = async (gid2) => {
        const gallery2 = IS_NHENTAI ? await getGalleryFromApi(gid2) : await getGalleryFromWebpage(gid2);
        logger.log("gallery", gallery2);
        return gallery2;
      };
      const getGalleryInfo = async (gid2) => {
        const {
          id,
          media_id,
          title,
          images: { pages: pages2 },
          num_pages,
          tags: tags2,
          upload_date
        } = await (async () => {
          var _a;
          if (gid2)
            return getGallery(gid2);
          const gidFromUrl = (_a = /^\/g\/(\d+)/.exec(location.pathname)) == null ? void 0 : _a[1];
          const localGallery = _unsafeWindow._gallery ?? _unsafeWindow.gallery;
          if (localGallery) {
            if (gidFromUrl)
              localGallery.id = Number(gidFromUrl);
            return localGallery;
          }
          if (gidFromUrl)
            return getGallery(gidFromUrl);
          throw new Error("Cannot get gallery info.");
        })();
        const { english: english2, japanese: japanese2, pretty } = title;
        const infoPages = (Array.isArray(pages2) ? pages2 : Object.values(pages2)).map(
          ({ t: t2, w, h: h2 }, i) => ({ i: i + 1, t: NHentaiImgExt[t2], w, h: h2 })
        );
        const info = {
          gid: id,
          mid: media_id,
          title,
          pages: infoPages,
          cfName: compileTemplate(settings.compressionFilename)({
            english: applyTitleReplacement(english2 || japanese2),
            japanese: applyTitleReplacement(japanese2 || english2),
            pretty: applyTitleReplacement(pretty || english2 || japanese2),
            id,
            pages: num_pages,
            artist: getCFNameArtists(tags2)
          }).replace(/[/\\:*?"<>|]/g, ""),
          tags: tags2,
          uploadDate: upload_date
        };
        logger.log("info", info);
        return info;
      };
      const fetchMediaUrlTemplate = async () => {
        var _a, _b, _c;
        const onlineViewUrl = ((_b = (_a = document.querySelector(".gallery a")) == null ? void 0 : _a.getAttribute("href")) == null ? void 0 : _b.concat("/1")) ?? ((_c = document.querySelector("a.gallerythumb")) == null ? void 0 : _c.getAttribute("href"));
        if (!onlineViewUrl) {
          throw new Error("get media url failed: cannot find a gallery");
        }
        logger.log(`fetching media url template by ${onlineViewUrl}`);
        const onlineViewHtml = await getText(onlineViewUrl);
        const $doc2 = loadHTML(onlineViewHtml);
        const imgSrc = $doc2.find("#image-container img").attr("src");
        if (!imgSrc) {
          throw new Error("get media url failed: cannot find an image src");
        }
        const template2 = imgSrc.replace(/\/\d+\//, "/{{mid}}/").replace(/\/\d+\.[^/]+$/, "/{{filename}}");
        _GM_setValue(MEDIA_URL_TEMPLATE_KEY, template2);
        return template2;
      };
      const getMediaUrlTemplate = async () => {
        const cachedTemplate = _GM_getValue(MEDIA_URL_TEMPLATE_KEY);
        if (cachedTemplate && await checkHost(cachedTemplate)) {
          logger.log(`use cached media url template: ${cachedTemplate}`);
          return cachedTemplate;
        }
        try {
          const template2 = await fetchMediaUrlTemplate();
          logger.log(`use media url template: ${template2}`);
          return template2;
        } catch (error) {
          openAlert("dialog.getMediaUrlTemplateFailed");
          logger.error(error);
          throw error;
        }
      };
      const getCompliedMediaUrlTemplate = once(async () => compileTemplate(await getMediaUrlTemplate()));
      const applyTitleReplacement = (title) => {
        if (!validTitleReplacement.value.length)
          return title;
        return validTitleReplacement.value.reduce((pre, { from, to, regexp }) => {
          try {
            return pre.replaceAll(regexp ? new RegExp(from, "g") : from, to);
          } catch {
            return pre;
          }
        }, title);
      };
      let textareaEl;
      const encodeHtml = (text) => {
        if (!textareaEl)
          textareaEl = document.createElement("textarea");
        textareaEl.innerText = text;
        const encodedText = textareaEl.innerHTML;
        textareaEl.innerHTML = "";
        return encodedText;
      };
      const langMap = {
        chinese: "zh",
        english: "en",
        japanese: "ja"
      };
      class ComicInfoXmlBuilder {
        constructor(info) {
          __publicField(this, "serializer", new XMLSerializer());
          __publicField(this, "doc", document.implementation.createDocument(null, "ComicInfo"));
          this.setRootNS();
          this.appendElement(
            "Title",
            settings.metaFileTitleLanguage in info.title ? info.title[settings.metaFileTitleLanguage] : info.title.english
          );
          this.appendElement(
            "Notes",
            `Created by nHentai Helper (Tsuk1ko/nhentai-helper) on ${(/* @__PURE__ */ new Date()).toISOString()}`
          );
          if (info.uploadDate) {
            const date = new Date(info.uploadDate * 1e3);
            this.appendElement("Year", date.getUTCFullYear());
            this.appendElement("Month", date.getUTCMonth() + 1);
            this.appendElement("Day", date.getUTCDate());
          }
          const getTags2 = (type) => info.tags.filter((t2) => t2.type === type);
          const artistTags = getTags2("artist");
          if (artistTags.length) {
            this.appendElement("Writer", map(artistTags, "name").join(", "));
          }
          const tags2 = getTags2("tag");
          if (tags2.length) {
            this.appendElement("Tags", map(tags2, "name").join(", "));
          }
          this.appendElement("Web", `${location.origin}/g/${info.gid}`);
          this.appendElement("PageCount", info.pages.length);
          const languageTag = info.tags.find(({ type, name }) => type === "language" && name in langMap);
          if (languageTag) {
            this.appendElement("LanguageISO", langMap[languageTag.name]);
          }
          this.appendElement("Format", /\[digital\]/i.test(info.title.english) ? "Digital" : "TBP");
          this.appendElement("Manga", "Yes");
          const characterTags = getTags2("character");
          if (characterTags.length) {
            this.appendElement("Characters", map(characterTags, "name").join(", "));
          }
          const pagesEl = this.createElement("Pages");
          const pageEls = info.pages.map(
            ({ i, w, h: h2 }) => this.createElement("Page", void 0, { Image: i, ImageWidth: w, ImageHeight: h2 })
          );
          pagesEl.append(...pageEls);
          this.root.append(pagesEl);
        }
        build() {
          const xml = this.serializer.serializeToString(this.doc);
          return `<?xml version="1.0" encoding="utf-8"?>
${xml}`;
        }
        get root() {
          return this.doc.documentElement;
        }
        setRootNS() {
          this.root.setAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
          this.root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
        }
        createElement(name, value, attrs) {
          const el = this.doc.createElement(name);
          if (!isNil(value))
            el.innerHTML = encodeHtml(String(value));
          if (attrs) {
            forEach(attrs, (v, k) => {
              if (!isNil(v))
                el.setAttribute(k, String(v));
            });
          }
          return el;
        }
        appendElement(name, value, attrs) {
          this.root.append(this.createElement(name, value, attrs));
        }
      }
      class EzeInfoJsonBuilder {
        constructor(info) {
          __publicField(this, "data");
          var _a;
          const date = info.uploadDate ? new Date(info.uploadDate * 1e3) : void 0;
          this.data = {
            gallery_info: {
              title: info.title.english,
              title_title_original: info.title.japanese,
              link: `${location.origin}/g/${info.gid}`,
              category: (_a = info.tags.find(({ type }) => type === "category")) == null ? void 0 : _a.name,
              tags: mapValues(groupBy(info.tags, "type"), (tags2) => map(tags2, "name")),
              ...this.getLanguageInfo(info),
              upload_date: date ? [
                date.getUTCFullYear(),
                date.getUTCMonth() + 1,
                date.getUTCDate(),
                date.getUTCHours(),
                date.getUTCMinutes(),
                date.getUTCSeconds()
              ] : void 0,
              source: {
                site: location.origin,
                gid: info.gid
              }
            }
          };
        }
        build() {
          return JSON.stringify(this.data);
        }
        getLanguageInfo(info) {
          let language;
          let translated = false;
          info.tags.filter(({ type }) => type === "language").forEach(({ name }) => {
            if (name === "translated") {
              translated = true;
              return;
            }
            language = name;
          });
          return { language, translated };
        }
      }
      const metaBuilderMap = {
        ComicInfoXml: { name: "ComicInfo.xml", Builder: ComicInfoXmlBuilder },
        EzeInfoJson: { name: "info.json", Builder: EzeInfoJsonBuilder }
      };
      const generateMetaFiles = (info) => {
        if (!settings.addMetaFile.length)
          return [];
        const files = [];
        for (const key of settings.addMetaFile) {
          if (key in metaBuilderMap) {
            const { name, Builder } = metaBuilderMap[key];
            files.push({
              name,
              data: new Builder(info).build()
            });
          }
        }
        return files;
      };
      var ErrorAction = /* @__PURE__ */ ((ErrorAction2) => {
        ErrorAction2["GET_INFO"] = "getInfo";
        ErrorAction2["DOWNLOAD"] = "download";
        return ErrorAction2;
      })(ErrorAction || {});
      const downloadGalleryByInfo = async (info, { progressDisplayController, rangeCheckers } = {}) => {
        info.done = 0;
        let { mid, pages: pages2, cfName } = info.gallery;
        if (rangeCheckers == null ? void 0 : rangeCheckers.length) {
          pages2 = pages2.filter(({ i }) => rangeCheckers.some((check) => check(i)));
        }
        let aborted = false;
        info.cancel = () => {
          aborted = true;
          progressDisplayController == null ? void 0 : progressDisplayController.reset();
        };
        progressDisplayController == null ? void 0 : progressDisplayController.bindInfo(info);
        progressDisplayController == null ? void 0 : progressDisplayController.updateProgress();
        const zip = new JSZip();
        const metaFiles = generateMetaFiles(info.gallery);
        if (metaFiles.length) {
          metaFiles.forEach(({ name, data }) => {
            zip.file(name, data);
          });
        }
        const downloadTask = async (page, threadID, { filenameLength, customDownloadUrl }) => {
          if (info.error)
            return { abort: () => {
            }, promise: Promise.resolve() };
          const usedCounterKeys = [];
          const urlGetter = customDownloadUrl ? compileTemplate(customDownloadUrl)({ mid, index: page.i, ext: page.t }) : IS_NHENTAI ? settings.nHentaiDownloadHost === NHentaiDownloadHostSpecial.BALANCE || settings.nHentaiDownloadHost === NHentaiDownloadHostSpecial.RANDOM ? () => {
            const url = getMediaDownloadUrl(mid, `${page.i}.${page.t}`);
            logger.log(`[${threadID}] ${url}`);
            if (settings.nHentaiDownloadHost === NHentaiDownloadHostSpecial.BALANCE) {
              const counterKey = new URL(url).host;
              usedCounterKeys.push(counterKey);
              nHentaiDownloadHostCounter.add(counterKey);
            }
            return url;
          } : getMediaDownloadUrl(mid, `${page.i}.${page.t}`) : await getMediaDownloadUrlOnMirrorSite(mid, `${page.i}.${page.t}`).catch(() => {
          });
          if (!urlGetter) {
            info.error = true;
            return { abort: () => {
            }, promise: Promise.resolve() };
          }
          if (typeof urlGetter !== "function") {
            logger.log(`[${threadID}] ${urlGetter}`);
          }
          const { abort: abort2, dataPromise } = request(urlGetter, "arraybuffer");
          return {
            abort: () => {
              logger.log(`[${threadID}] abort`);
              abort2();
            },
            promise: dataPromise.then(async (data) => {
              if (data) {
                zip.file(`${String(page.i).padStart(filenameLength || 0, "0")}.${page.t}`, data);
              }
              info.done++;
              progressDisplayController == null ? void 0 : progressDisplayController.updateProgress();
            }).catch((e) => {
              if (isAbortError(e))
                return;
              info.error = true;
              throw e;
            }).finally(() => {
              if (usedCounterKeys.length) {
                usedCounterKeys.forEach((key) => {
                  nHentaiDownloadHostCounter.del(key);
                });
              }
            })
          };
        };
        const multiThread = new MultiThread(pages2, downloadTask, {
          filenameLength: settings.filenameLength === "auto" ? Math.ceil(Math.log10(Math.max(...pages2.map(({ i }) => Number(i))))) : settings.filenameLength,
          customDownloadUrl: settings.customDownloadUrl
        });
        const { abort, promise } = multiThread.start();
        info.cancel = () => {
          aborted = true;
          abort();
          progressDisplayController == null ? void 0 : progressDisplayController.reset();
        };
        if (!aborted)
          await promise;
        if (aborted)
          return;
        return async () => {
          info.compressing = true;
          progressDisplayController == null ? void 0 : progressDisplayController.updateProgress();
          logger.log("start compressing", cfName);
          let lastZipFile = "";
          const onCompressionUpdate = ({ workerId, percent, currentFile }) => {
            if (lastZipFile !== currentFile && currentFile) {
              lastZipFile = currentFile;
              logger.log(`[${workerId}] compressing ${percent.toFixed(2)}%`, currentFile);
            }
            info.compressingPercent = percent.toFixed(2);
            progressDisplayController == null ? void 0 : progressDisplayController.updateProgress();
          };
          if (settings.streamDownload) {
            logger.log("stream mode on");
            const fileStream = StreamSaverExports.createWriteStream(cfName);
            const zipStream = await zip.generateStream(getCompressionOptions(), onCompressionUpdate);
            await zipStream.pipeTo(fileStream);
          } else {
            const data = await zip.generateAsync(getCompressionOptions(), onCompressionUpdate);
            FileSaver_minExports.saveAs(new File([data], cfName, { type: "application/zip" }));
          }
          logger.log("completed", cfName);
          progressDisplayController == null ? void 0 : progressDisplayController.complete();
          progressDisplayController == null ? void 0 : progressDisplayController.unbindInfo();
        };
      };
      const addDownloadGalleryTask = (gallery2, { progressDisplayController, markGalleryDownloaded } = {}) => {
        const info = createMangaDownloadInfo(gallery2, true);
        info.cancel = () => {
          progressDisplayController == null ? void 0 : progressDisplayController.reset();
        };
        dlQueue.push(async () => {
          const zipFunc = await downloadGalleryByInfo(info, { progressDisplayController }).catch((e) => {
            progressDisplayController == null ? void 0 : progressDisplayController.error();
            errorRetryConfirm(
              ErrorAction.DOWNLOAD,
              () => {
                dlQueue.skipFromError().catch(logger.error);
              },
              () => {
                info.error = false;
                dlQueue.restartFromError().catch(logger.error);
              }
            );
            throw e;
          });
          if (zipFunc) {
            zipQueue.push(async () => {
              try {
                await zipFunc();
                markAsDownloaded(gallery2.gid, gallery2.title);
                markGalleryDownloaded == null ? void 0 : markGalleryDownloaded();
              } catch (error) {
                if (!error)
                  logger.warn("user abort stream download");
                logger.error(error);
                progressDisplayController == null ? void 0 : progressDisplayController.error();
              }
            }, info);
            zipQueue.start().catch(logger.error);
          }
        }, info);
        dlQueue.start().catch(logger.error);
      };
      const { t } = i18n.global;
      class ProgressDisplayController {
        constructor(enableHeadTxt = false, docTitle) {
          __publicField(this, "downloadBtn");
          __publicField(this, "btnTxt");
          __publicField(this, "info");
          this.enableHeadTxt = enableHeadTxt;
          this.docTitle = docTitle;
          this.btnTxt = /* @__PURE__ */ jsx.createElement("span", { class: "download-zip-txt" }, this.defaultBtnText());
          this.downloadBtn = /* @__PURE__ */ jsx.createElement("button", { class: "btn btn-secondary nhentai-helper-btn download-zip-btn" }, /* @__PURE__ */ jsx.createElement("i", { class: "fa fa-download" }), " ", this.btnTxt);
        }
        get compressingHeadText() {
          return this.enableHeadTxt ? `${t("button.compressing")} ${getDownloadExt()} ` : "";
        }
        get downloadingHeadText() {
          return this.enableHeadTxt ? `${t("button.downloading")} ${getDownloadExt()} ` : "";
        }
        defaultBtnText(suffix) {
          if (!this.enableHeadTxt)
            return suffix ?? "";
          return `${t("button.download")} ${getDownloadExt()}${suffix ? ` ${suffix}` : ""}`;
        }
        bindInfo(info) {
          this.info = info;
        }
        unbindInfo() {
          this.info = void 0;
        }
        lockBtn(text) {
          this.downloadBtn.setAttribute("disabled", "disabled");
          if (text)
            this.btnTxt.innerText = text;
        }
        releaseBtn() {
          this.downloadBtn.removeAttribute("disabled");
        }
        complete() {
          this.setDocTitle("✓");
          this.btnTxt.innerText = this.defaultBtnText("✓");
          this.releaseBtn();
        }
        reset() {
          this.setDocTitle();
          this.btnTxt.innerText = this.defaultBtnText();
          this.releaseBtn();
        }
        error() {
          this.releaseBtn();
          this.btnTxt.innerText = "Error";
          this.setDocTitle("×");
        }
        updateProgress() {
          if (!this.info)
            return;
          const { done, compressing, compressingPercent } = this.info;
          if (compressing) {
            this.setDocTitle(`${compressingPercent}%`);
            this.btnTxt.innerText = `${this.compressingHeadText}${compressingPercent}%`;
          } else {
            const total = this.info.gallery.pages.length;
            this.setDocTitle(`${done}/${total}`);
            this.btnTxt.innerText = `${this.downloadingHeadText}${done}/${total}`;
          }
        }
        setDocTitle(prefix) {
          if (!this.docTitle)
            return;
          document.title = prefix ? `[${prefix}] ${this.docTitle}` : this.docTitle;
        }
      }
      class IgnoreController {
        constructor(text = true, status = false) {
          __publicField(this, "ignoreBtn");
          __publicField(this, "icon");
          __publicField(this, "text");
          this.status = status;
          this.icon = /* @__PURE__ */ jsx.createElement("i", { class: this.iconClass });
          if (text)
            this.text = /* @__PURE__ */ jsx.createElement("span", null, this.btnText);
          this.ignoreBtn = /* @__PURE__ */ jsx.createElement("button", { class: "btn btn-secondary nhentai-helper-btn ignore-btn" }, this.icon, " ", this.text);
        }
        setStatus(status) {
          this.status = status;
          this.updateBtn();
        }
        getStatus() {
          return this.status;
        }
        get iconClass() {
          return this.status ? "fa fa-eye-slash" : "fa fa-eye";
        }
        get btnText() {
          return this.status ? "Unignore this" : "Ignore this";
        }
        updateBtn() {
          this.icon.className = this.iconClass;
          if (this.text)
            this.text.innerText = this.btnText;
        }
      }
      const initDetailPage = async () => {
        const progressDisplayController = new ProgressDisplayController(true, document.title);
        const { downloadBtn } = progressDisplayController;
        const pagesInput = /* @__PURE__ */ jsx.createElement("input", { class: "pages-input", placeholder: "Download pages (e.g. 1-10,12,14,18-)" });
        $("#info > .buttons").append(downloadBtn).after(pagesInput);
        let ignoreController;
        if (settings.showIgnoreButton) {
          const gallery2 = await getGalleryInfo();
          const isDownloaded = await isDownloadedByGid(gallery2.gid);
          ignoreController = new IgnoreController(true, isDownloaded);
          const { ignoreBtn } = ignoreController;
          ignoreBtn.addEventListener("click", () => {
            const ignore = ignoreController.getStatus();
            if (ignore)
              unmarkAsDownloaded(gallery2.gid, gallery2.title);
            else
              markAsDownloaded(gallery2.gid, gallery2.title);
            ignoreController.setStatus(!ignore);
          });
          $("#info > .buttons").append(ignoreBtn);
        }
        downloadBtn.addEventListener("click", async () => {
          var _a;
          const gallery2 = await getGalleryInfo();
          const rangeCheckers = pagesInput.value.split(",").filter((range) => !Number.isNaN(parseInt(range))).map((range) => {
            const [start, end] = range.split("-").map((num) => parseInt(num));
            if (typeof end === "undefined")
              return (page) => page === start;
            else if (Number.isNaN(end))
              return (page) => page >= start;
            else
              return (page) => start <= page && page <= end;
          });
          progressDisplayController.lockBtn();
          try {
            const downloaded = await isDownloadedByGid(gallery2.gid) || await isDownloadedByTitle(gallery2.title);
            if (downloaded && !await downloadAgainConfirm(gallery2.title.japanese || gallery2.title.english)) {
              progressDisplayController.reset();
              markAsDownloaded(gallery2.gid, gallery2.title);
              ignoreController == null ? void 0 : ignoreController.setStatus(true);
              return;
            }
            await ((_a = await downloadGalleryByInfo(createMangaDownloadInfo(gallery2), {
              progressDisplayController,
              rangeCheckers
            })) == null ? void 0 : _a());
            markAsDownloaded(gallery2.gid, gallery2.title);
            ignoreController == null ? void 0 : ignoreController.setStatus(true);
          } catch (error) {
            progressDisplayController.error();
            logger.error(error);
          }
        });
        applyAutoShowAll();
      };
      const applyAutoShowAll = () => {
        if (settings.autoShowAll) {
          getShowAllBtn().then(($btn) => $btn.trigger("click")).catch(logger.error);
        }
      };
      function tryOnScopeDispose(fn) {
        if (vue.getCurrentScope()) {
          vue.onScopeDispose(fn);
          return true;
        }
        return false;
      }
      function toValue(r) {
        return typeof r === "function" ? r() : vue.unref(r);
      }
      const isClient = typeof window !== "undefined" && typeof document !== "undefined";
      typeof WorkerGlobalScope !== "undefined" && globalThis instanceof WorkerGlobalScope;
      const toString = Object.prototype.toString;
      const isObject = (val) => toString.call(val) === "[object Object]";
      const noop = () => {
      };
      function createFilterWrapper(filter2, fn) {
        function wrapper(...args) {
          return new Promise((resolve, reject) => {
            Promise.resolve(filter2(() => fn.apply(this, args), { fn, thisArg: this, args })).then(resolve).catch(reject);
          });
        }
        return wrapper;
      }
      const bypassFilter = (invoke2) => {
        return invoke2();
      };
      function pausableFilter(extendFilter = bypassFilter) {
        const isActive = vue.ref(true);
        function pause() {
          isActive.value = false;
        }
        function resume() {
          isActive.value = true;
        }
        const eventFilter = (...args) => {
          if (isActive.value)
            extendFilter(...args);
        };
        return { isActive: vue.readonly(isActive), pause, resume, eventFilter };
      }
      function getLifeCycleTarget(target) {
        return target || vue.getCurrentInstance();
      }
      function watchWithFilter(source, cb, options = {}) {
        const {
          eventFilter = bypassFilter,
          ...watchOptions
        } = options;
        return vue.watch(
          source,
          createFilterWrapper(
            eventFilter,
            cb
          ),
          watchOptions
        );
      }
      function watchPausable(source, cb, options = {}) {
        const {
          eventFilter: filter2,
          ...watchOptions
        } = options;
        const { eventFilter, pause, resume, isActive } = pausableFilter(filter2);
        const stop = watchWithFilter(
          source,
          cb,
          {
            ...watchOptions,
            eventFilter
          }
        );
        return { stop, pause, resume, isActive };
      }
      function tryOnMounted(fn, sync = true, target) {
        const instance = getLifeCycleTarget();
        if (instance)
          vue.onMounted(fn, target);
        else if (sync)
          fn();
        else
          vue.nextTick(fn);
      }
      function unrefElement(elRef) {
        var _a;
        const plain = toValue(elRef);
        return (_a = plain == null ? void 0 : plain.$el) != null ? _a : plain;
      }
      const defaultWindow = isClient ? window : void 0;
      function useEventListener(...args) {
        let target;
        let events2;
        let listeners;
        let options;
        if (typeof args[0] === "string" || Array.isArray(args[0])) {
          [events2, listeners, options] = args;
          target = defaultWindow;
        } else {
          [target, events2, listeners, options] = args;
        }
        if (!target)
          return noop;
        if (!Array.isArray(events2))
          events2 = [events2];
        if (!Array.isArray(listeners))
          listeners = [listeners];
        const cleanups = [];
        const cleanup = () => {
          cleanups.forEach((fn) => fn());
          cleanups.length = 0;
        };
        const register = (el, event, listener, options2) => {
          el.addEventListener(event, listener, options2);
          return () => el.removeEventListener(event, listener, options2);
        };
        const stopWatch = vue.watch(
          () => [unrefElement(target), toValue(options)],
          ([el, options2]) => {
            cleanup();
            if (!el)
              return;
            const optionsClone = isObject(options2) ? { ...options2 } : options2;
            cleanups.push(
              ...events2.flatMap((event) => {
                return listeners.map((listener) => register(el, event, listener, optionsClone));
              })
            );
          },
          { immediate: true, flush: "post" }
        );
        const stop = () => {
          stopWatch();
          cleanup();
        };
        tryOnScopeDispose(stop);
        return stop;
      }
      const _global = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
      const globalKey = "__vueuse_ssr_handlers__";
      const handlers = /* @__PURE__ */ getHandlers();
      function getHandlers() {
        if (!(globalKey in _global))
          _global[globalKey] = _global[globalKey] || {};
        return _global[globalKey];
      }
      function getSSRHandler(key, fallback) {
        return handlers[key] || fallback;
      }
      function guessSerializerType(rawInit) {
        return rawInit == null ? "any" : rawInit instanceof Set ? "set" : rawInit instanceof Map ? "map" : rawInit instanceof Date ? "date" : typeof rawInit === "boolean" ? "boolean" : typeof rawInit === "string" ? "string" : typeof rawInit === "object" ? "object" : !Number.isNaN(rawInit) ? "number" : "any";
      }
      const StorageSerializers = {
        boolean: {
          read: (v) => v === "true",
          write: (v) => String(v)
        },
        object: {
          read: (v) => JSON.parse(v),
          write: (v) => JSON.stringify(v)
        },
        number: {
          read: (v) => Number.parseFloat(v),
          write: (v) => String(v)
        },
        any: {
          read: (v) => v,
          write: (v) => String(v)
        },
        string: {
          read: (v) => v,
          write: (v) => String(v)
        },
        map: {
          read: (v) => new Map(JSON.parse(v)),
          write: (v) => JSON.stringify(Array.from(v.entries()))
        },
        set: {
          read: (v) => new Set(JSON.parse(v)),
          write: (v) => JSON.stringify(Array.from(v))
        },
        date: {
          read: (v) => new Date(v),
          write: (v) => v.toISOString()
        }
      };
      const customStorageEventName = "vueuse-storage";
      function useStorage(key, defaults2, storage, options = {}) {
        var _a;
        const {
          flush = "pre",
          deep = true,
          listenToStorageChanges = true,
          writeDefaults = true,
          mergeDefaults = false,
          shallow,
          window: window2 = defaultWindow,
          eventFilter,
          onError = (e) => {
            console.error(e);
          },
          initOnMounted
        } = options;
        const data = (shallow ? vue.shallowRef : vue.ref)(typeof defaults2 === "function" ? defaults2() : defaults2);
        if (!storage) {
          try {
            storage = getSSRHandler("getDefaultStorage", () => {
              var _a2;
              return (_a2 = defaultWindow) == null ? void 0 : _a2.localStorage;
            })();
          } catch (e) {
            onError(e);
          }
        }
        if (!storage)
          return data;
        const rawInit = toValue(defaults2);
        const type = guessSerializerType(rawInit);
        const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];
        const { pause: pauseWatch, resume: resumeWatch } = watchPausable(
          data,
          () => write(data.value),
          { flush, deep, eventFilter }
        );
        if (window2 && listenToStorageChanges) {
          tryOnMounted(() => {
            useEventListener(window2, "storage", update);
            useEventListener(window2, customStorageEventName, updateFromCustomEvent);
            if (initOnMounted)
              update();
          });
        }
        if (!initOnMounted)
          update();
        function dispatchWriteEvent(oldValue, newValue) {
          if (window2) {
            window2.dispatchEvent(new CustomEvent(customStorageEventName, {
              detail: {
                key,
                oldValue,
                newValue,
                storageArea: storage
              }
            }));
          }
        }
        function write(v) {
          try {
            const oldValue = storage.getItem(key);
            if (v == null) {
              dispatchWriteEvent(oldValue, null);
              storage.removeItem(key);
            } else {
              const serialized = serializer.write(v);
              if (oldValue !== serialized) {
                storage.setItem(key, serialized);
                dispatchWriteEvent(oldValue, serialized);
              }
            }
          } catch (e) {
            onError(e);
          }
        }
        function read(event) {
          const rawValue = event ? event.newValue : storage.getItem(key);
          if (rawValue == null) {
            if (writeDefaults && rawInit != null)
              storage.setItem(key, serializer.write(rawInit));
            return rawInit;
          } else if (!event && mergeDefaults) {
            const value = serializer.read(rawValue);
            if (typeof mergeDefaults === "function")
              return mergeDefaults(value, rawInit);
            else if (type === "object" && !Array.isArray(value))
              return { ...rawInit, ...value };
            return value;
          } else if (typeof rawValue !== "string") {
            return rawValue;
          } else {
            return serializer.read(rawValue);
          }
        }
        function update(event) {
          if (event && event.storageArea !== storage)
            return;
          if (event && event.key == null) {
            data.value = rawInit;
            return;
          }
          if (event && event.key !== key)
            return;
          pauseWatch();
          try {
            if ((event == null ? void 0 : event.newValue) !== serializer.write(data.value))
              data.value = read(event);
          } catch (e) {
            onError(e);
          } finally {
            if (event)
              vue.nextTick(resumeWatch);
            else
              resumeWatch();
          }
        }
        function updateFromCustomEvent(event) {
          update(event.detail);
        }
        return data;
      }
      function useSessionStorage(key, initialValue, options = {}) {
        const { window: window2 = defaultWindow } = options;
        return useStorage(key, initialValue, window2 == null ? void 0 : window2.sessionStorage, options);
      }
      const _hoisted_1 = { class: "language-filter" };
      const _sfc_main = /* @__PURE__ */ vue.defineComponent({
        __name: "LanguageFilter",
        setup(__props, { expose: __expose }) {
          const { t: t2 } = i18n.global;
          const languageFilter = useSessionStorage("languageFilter", [], {
            listenToStorageChanges: false
          });
          const options = IS_NHENTAI_TO ? [
            ["japanese", "2"],
            ["english", "19"],
            ["chinese", "10197"]
          ] : [
            ["japanese", "6346"],
            ["english", "12227"],
            ["chinese", "29963"]
          ];
          vue.watch(
            languageFilter,
            (val) => {
              filterLanguage(languageFilter.value);
            },
            { deep: true, immediate: true }
          );
          __expose({
            filterLanguage: ($node) => {
              filterLanguage(languageFilter.value, $node);
            }
          });
          return (_ctx, _cache) => {
            return vue.openBlock(), vue.createElementBlock("li", _hoisted_1, [
              vue.createVNode(vue.unref(elementPlus.ElSelect), {
                modelValue: vue.unref(languageFilter),
                "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(languageFilter) ? languageFilter.value = $event : null),
                class: "filter-select",
                multiple: "",
                "collapse-tags": "",
                "collapse-tags-tooltip": "",
                placeholder: vue.unref(t2)("common.filter")
              }, {
                default: vue.withCtx(() => [
                  (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(options), ([key, val]) => {
                    return vue.openBlock(), vue.createBlock(vue.unref(elementPlus.ElOption), {
                      key,
                      label: vue.unref(t2)(`common.abbr.${key}`),
                      value: val
                    }, {
                      default: vue.withCtx(() => [
                        vue.createTextVNode(vue.toDisplayString(vue.unref(t2)(`common.${key}`)), 1)
                      ]),
                      _: 2
                    }, 1032, ["label", "value"]);
                  }), 128))
                ]),
                _: 1
              }, 8, ["modelValue", "placeholder"])
            ]);
          };
        }
      });
      const LanguageFilter = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-73f7b9fb"]]);
      const filterLanguage = (tags2, $node) => {
        const getNode = $node ? (selector) => $node.find(selector) : (selector) => $(selector);
        getNode(".gallery").removeClass("hidden");
        if (tags2.length) {
          const notSelector = tags2.map((tag) => `:not([data-tags~=${tag}])`).join("");
          getNode(`.gallery${notSelector}`).addClass("hidden");
        }
      };
      const mountLanguageFilter = () => {
        var _a;
        const menuLeft = document.querySelector("ul.menu.left");
        if (!menuLeft)
          return {};
        const vnode = vue.h(LanguageFilter);
        vue.render(vnode, menuLeft);
        return ((_a = vnode.component) == null ? void 0 : _a.exposed) ?? {};
      };
      const initListPage = () => {
        $(".gallery").each(initGallery);
        const { filterLanguage: filterLanguage2 } = mountLanguageFilter();
        initShortcut();
        restoreDownloadQueue();
        const contentEl = $("#content")[0];
        if (contentEl) {
          new MutationObserver((mutations) => {
            mutations.forEach(({ addedNodes }) => {
              addedNodes.forEach((node) => {
                const $el = $(node);
                $el.find(".gallery").each(initGallery);
                filterLanguage2 == null ? void 0 : filterLanguage2($el);
              });
            });
          }).observe(contentEl, { childList: true });
        }
      };
      const initShortcut = () => {
        $(document).on("keydown", (event) => {
          switch (event.key) {
            case "ArrowLeft":
              $(".pagination .previous").trigger("click");
              break;
            case "ArrowRight":
              $(".pagination .next").trigger("click");
              break;
          }
        });
      };
      const restoreDownloadQueue = () => {
        const galleriesJson = sessionStorage.getItem("downloadQueue");
        if (!galleriesJson)
          return;
        try {
          const galleries = JSON.parse(galleriesJson);
          for (const gallery2 of galleries) {
            addDownloadGalleryTask(gallery2);
          }
        } catch (error) {
          logger.error(error);
        }
      };
      const initGallery = function() {
        var _a;
        const $gallery = $(this);
        if ($gallery.attr("init"))
          return;
        $gallery.attr("init", "true");
        const $a = $gallery.find("a.cover");
        if (settings.openOnNewTab)
          $a.attr("target", "_blank");
        const gid2 = (_a = /\/g\/([0-9]+)/.exec($a.attr("href"))) == null ? void 0 : _a[1];
        if (!gid2)
          return;
        const enTitle = $gallery.find(".caption").text().trim();
        const progressDisplayController = new ProgressDisplayController();
        const { downloadBtn } = progressDisplayController;
        $gallery.append(downloadBtn);
        let ignoreController;
        let galleryTitle;
        const markGalleryDownloaded = () => {
          $gallery.addClass("downloaded");
          ignoreController == null ? void 0 : ignoreController.setStatus(true);
        };
        const unmarkGalleryDownloaded = () => {
          $gallery.removeClass("downloaded");
          ignoreController == null ? void 0 : ignoreController.setStatus(false);
        };
        void Promise.all([isDownloadedByGid(gid2), isDownloadedByTitle({ english: enTitle })]).then(
          ([gidDownloaded, titleDownloaded]) => {
            const downloaded = gidDownloaded || titleDownloaded;
            if (downloaded)
              markGalleryDownloaded();
            if (settings.showIgnoreButton) {
              ignoreController = new IgnoreController(false, downloaded);
              const { ignoreBtn } = ignoreController;
              ignoreBtn.addEventListener("click", () => {
                const ignore = ignoreController.getStatus();
                if (ignore) {
                  unmarkGalleryDownloaded();
                  unmarkAsDownloaded(gid2, galleryTitle);
                } else {
                  markGalleryDownloaded();
                  markAsDownloaded(gid2, galleryTitle);
                }
              });
              $gallery.append(ignoreBtn);
            }
          }
        );
        let gallery2;
        let skipDownloadedCheck = false;
        const startDownload = async () => {
          if (!settings.autoCancelDownloadedManga) {
            progressDisplayController.lockBtn("Wait");
          }
          if (!skipDownloadedCheck && await isDownloadedByGid(gid2)) {
            const title = $gallery.find(".caption").text();
            if (!await downloadAgainConfirm(title, true)) {
              progressDisplayController.reset();
              markGalleryDownloaded();
              return;
            }
            skipDownloadedCheck = true;
          }
          if (settings.autoCancelDownloadedManga) {
            progressDisplayController.lockBtn("Wait");
          }
          if (!gallery2) {
            try {
              gallery2 = await getGalleryInfo(gid2);
              galleryTitle = gallery2.title;
            } catch (error) {
              logger.error(error);
              progressDisplayController.error();
              errorRetryConfirm(ErrorAction.GET_INFO, void 0, startDownload);
              return;
            }
          }
          if (!skipDownloadedCheck) {
            if (await isDownloadedByTitle(gallery2.title) && !await downloadAgainConfirm(gallery2.title.japanese || gallery2.title.english, true)) {
              progressDisplayController.reset();
              markAsDownloaded(gid2, gallery2.title);
              markGalleryDownloaded();
              return;
            }
            if (dlQueue.queue.some(
              ({
                info: {
                  gallery: { title }
                }
              }) => isSameTitle(title, gallery2.title)
            ) && !await downloadAgainConfirm(gallery2.title.japanese || gallery2.title.english, true)) {
              progressDisplayController.reset();
              return;
            }
          }
          addDownloadGalleryTask(gallery2, { progressDisplayController, markGalleryDownloaded });
        };
        downloadBtn.addEventListener("click", startDownload);
      };
      class StyleInjector {
        constructor(style) {
          __publicField(this, "styleNode");
          this.styleNode = /* @__PURE__ */ jsx.createElement("style", null, style);
        }
        inject() {
          document.head.append(this.styleNode);
        }
        remove() {
          this.styleNode.remove();
        }
      }
      const initOnlineViewPage = () => {
        if (!IS_NHENTAI)
          initViewMode();
      };
      const initViewMode = () => {
        const style = new StyleInjector(
          "#image-container img{width:auto;max-width:calc(100vw - 20px);max-height:100vh}"
        );
        const viewModeText = ["[off]", "[on]"];
        let viewMode = _GM_getValue("online_view_mode", 0);
        applyOnlineViewStyle(!!viewMode, style);
        const btnText = /* @__PURE__ */ jsx.createElement("span", null, viewModeText[viewMode]);
        const btn = /* @__PURE__ */ jsx.createElement("button", { id: "online-view-mode-btn", class: "btn btn-secondary" }, "100% view height ", btnText);
        btn.addEventListener("click", () => {
          viewMode = 1 - viewMode;
          _GM_setValue("online_view_mode", viewMode);
          btnText.innerText = viewModeText[viewMode];
          applyOnlineViewStyle(!!viewMode, style);
        });
        $("#page-container").prepend(btn);
      };
      const applyOnlineViewStyle = (enable, style) => {
        if (enable)
          style.inject();
        else
          style.remove();
      };
      const initPage = () => {
        if (IS_PAGE_MANGA_LIST) {
          initListPage();
          applyPjax();
        } else if (IS_PAGE_MANGA_DETAIL)
          initDetailPage().catch(logger.error);
        else if (IS_PAGE_ONLINE_VIEW)
          initOnlineViewPage();
      };
      const applyPjax = () => {
        $(document).pjax(".pagination a, .sort a", {
          container: "#content",
          fragment: "#content",
          timeout: 1e4
        });
        $(document).on("pjax:end", () => {
          $(".pagination a").each(function() {
            const $this = $(this);
            const href = $this.attr("href");
            const isPathname = href.startsWith("/");
            const url = isPathname ? new URL(href, location.origin) : new URL(href);
            url.searchParams.delete("_pjax");
            $this.attr("href", isPathname ? `${url.pathname}${url.search}` : url.href);
          });
          applyLazyLoad();
        });
      };
      const applyLazyLoad = () => {
        const { _n_app } = _unsafeWindow;
        if (_n_app) {
          _n_app.install_lazy_loader();
          _n_app.install_blacklisting();
        }
      };
      const createAppAndMount = (component, appInitFunc) => {
        const el = document.createElement("div");
        document.body.append(el);
        const app = vue.createApp(component);
        appInitFunc == null ? void 0 : appInitFunc(app);
        return app.mount(el);
      };
      const initSettingsDialogApp = once(
        () => createAppAndMount(SettingsDialog, (app) => {
          app.use(i18n);
        })
      );
      const openSettingsDialog = () => {
        const dialog = initSettingsDialogApp();
        dialog.open();
      };
      createAppAndMount(_sfc_main$3);
      initPage();
      _GM_registerMenuCommand(i18n.global.t("common.settings"), openSettingsDialog);
    }
  });
  require_main_001();

})(jQuery, Vue, ElementPlus);